From 7205cb5cb9ae7d6741a0bbaddb8f1c75aebb437c Mon Sep 17 00:00:00 2001 From: lnk Date: Mon, 15 Jun 2026 15:48:16 +0800 Subject: [PATCH] =?UTF-8?q?=E8=87=AA=E4=B8=BB=E5=8D=8F=E8=AE=AE=E5=BA=93?= =?UTF-8?q?=E7=BC=96=E8=AF=91=E9=80=9A=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/inc/ExceptionReport.h | 135 + include/inc/Goose.h | 223 ++ include/inc/STR_UTIL.H | 158 + include/inc/Smem.h | 467 +++ include/inc/acse2.h | 310 ++ include/inc/acse2log.h | 144 + include/inc/acse2usr.h | 406 +++ include/inc/acseauth.h | 120 + include/inc/adlc.h | 1021 +++++++ include/inc/adlc_dsm.h | 73 + include/inc/adlc_log.h | 879 ++++++ include/inc/adlc_sm.h | 317 ++ include/inc/adlc_sts.h | 82 + include/inc/adlc_usr.h | 441 +++ include/inc/arg.h | 44 + include/inc/asn1defs.h | 40 + include/inc/asn1log.h | 106 + include/inc/asn1r.h | 718 +++++ include/inc/cfg_util.h | 112 + include/inc/cfglog.h | 101 + include/inc/checksum.h | 46 + include/inc/clnp.h | 259 ++ include/inc/clnp_llc.h | 66 + include/inc/clnp_log.h | 231 ++ include/inc/clnp_sne.h | 227 ++ include/inc/clnp_sta.h | 125 + include/inc/clnp_tnt.h | 45 + include/inc/clnp_usr.h | 462 +++ include/inc/clnpport.h | 52 + include/inc/conpack.h | 101 + include/inc/copp.h | 68 + include/inc/copp_log.h | 167 ++ include/inc/copp_usr.h | 193 ++ include/inc/cosp.h | 199 ++ include/inc/cosp_log.h | 214 ++ include/inc/cosp_usr.h | 531 ++++ include/inc/dibmatch.h | 64 + include/inc/ethertyp.h | 72 + include/inc/ethsub.h | 132 + include/inc/fkeydefs.h | 209 ++ include/inc/gen_list.h | 117 + include/inc/gensock2.h | 591 ++++ include/inc/glberror.h | 117 + include/inc/glbopt.h | 43 + include/inc/glbsem.h | 565 ++++ include/inc/glbtypes.h | 691 +++++ include/inc/gse_mgmt.h | 252 ++ include/inc/gvaldefs.h | 48 + include/inc/lean_a.h | 145 + include/inc/llcio.h | 337 +++ include/inc/llcioctl.h | 121 + include/inc/mem_chk.h | 339 +++ include/inc/memlog.h | 201 ++ include/inc/mloguser.h | 297 ++ include/inc/mms_def2.h | 308 ++ include/inc/mms_dfun.h | 212 ++ include/inc/mms_err.h | 213 ++ include/inc/mms_log.h | 109 + include/inc/mms_mp.h | 234 ++ include/inc/mms_pcon.h | 294 ++ include/inc/mms_pdom.h | 419 +++ include/inc/mms_perr.h | 248 ++ include/inc/mms_pevn.h | 956 ++++++ include/inc/mms_pfil.h | 297 ++ include/inc/mms_pjou.h | 299 ++ include/inc/mms_pocs.h | 120 + include/inc/mms_pprg.h | 287 ++ include/inc/mms_psem.h | 338 +++ include/inc/mms_pvar.h | 683 +++++ include/inc/mms_pvmd.h | 291 ++ include/inc/mms_vvar.h | 1090 +++++++ include/inc/mmsdefs.h | 235 ++ include/inc/mmsefun.h | 188 ++ include/inc/mmsintr2.h | 317 ++ include/inc/mmsldefs.h | 94 + include/inc/mmslog.h | 735 +++++ include/inc/mmslusec.h | 58 + include/inc/mmsop_en/mmsop_en.h | 185 ++ include/inc/mvl_acse.h | 234 ++ include/inc/mvl_defs.h | 2552 ++++++++++++++++ include/inc/mvl_log.h | 198 ++ include/inc/mvl_uca.h | 898 ++++++ include/inc/ntddosi.h | 114 + include/inc/osillc.h | 97 + include/inc/qmem.h | 35 + include/inc/rs_a.h | 119 + include/inc/rs_defs.h | 241 ++ include/inc/scl.h | 715 +++++ include/inc/scrndefs.h | 97 + include/inc/slog.h | 1599 ++++++++++ include/inc/smp.h | 110 + include/inc/smp_log.h | 286 ++ include/inc/smp_usr.h | 344 +++ include/inc/smpval.h | 138 + include/inc/sock_log.h | 210 ++ include/inc/ssec.h | 1182 ++++++++ include/inc/ssec_int.h | 56 + include/inc/ssleLog.h | 154 + include/inc/stdtime.h | 1446 +++++++++ include/inc/stdtime_config.h | 153 + include/inc/stdtime_endian.h | 90 + include/inc/stdtime_enum_err.h | 65 + include/inc/stdtime_enum_func.h | 425 +++ include/inc/stdtime_mms_btime.h | 81 + include/inc/stdtime_mms_utctime.h | 61 + include/inc/stdtime_quadlib.h | 1081 +++++++ include/inc/stdtime_stdint.h | 237 ++ include/inc/stdtime_timezone_csv.h | 381 +++ include/inc/stdtime_tzrules.h | 58 + include/inc/stdtime_w32.h | 353 +++ include/inc/stime.h | 38 + include/inc/sx_arb.h | 119 + include/inc/sx_defs.h | 611 ++++ include/inc/sx_log.h | 337 +++ include/inc/sysincs.h | 468 +++ include/inc/time_str.h | 137 + include/inc/tp0_sock.h | 268 ++ include/inc/tp4.h | 363 +++ include/inc/tp4_encd.h | 407 +++ include/inc/tp4_log.h | 228 ++ include/inc/tp4api.h | 333 +++ include/inc/tp4api.h.bak | 333 +++ lib/libcurl.so.4 | Bin 0 -> 1164856 bytes lib/libcurl.so.4.3.0 | Bin 0 -> 352958 bytes lib/libcurl.so.4.7.0 | Bin 0 -> 1164856 bytes lib/liblog4cplus.so.9 | Bin 0 -> 2304296 bytes lib/libmxml.so.1 | Bin 0 -> 132088 bytes lib/libmxml.so.1.5 | Bin 0 -> 132088 bytes mms/mms_process.c | 12 +- mms/mmscli_rpt.c | 4 +- mms/mmsop_en.c | 12 +- mms/rdb_ext_utils.c | 6 +- mmslib/.vscode/c_cpp_properties.json | 18 + mmslib/.vscode/launch.json | 24 + mmslib/.vscode/settings.json | 59 + mmslib/Makefile | 151 + mmslib/Makefile.Debug | 1899 ++++++++++++ mmslib/Makefile.Release | 1899 ++++++++++++ mmslib/asn1/ard_bool.c | 65 + mmslib/asn1/ard_bstr.c | 242 ++ mmslib/asn1/ard_btod.c | 72 + mmslib/asn1/ard_delm.c | 274 ++ mmslib/asn1/ard_flt.c | 572 ++++ mmslib/asn1/ard_idnt.c | 91 + mmslib/asn1/ard_int.c | 490 +++ mmslib/asn1/ard_objd.c | 113 + mmslib/asn1/ard_ostr.c | 188 ++ mmslib/asn1/ard_strn.c | 54 + mmslib/asn1/ard_time.c | 284 ++ mmslib/asn1/ard_utc.c | 80 + mmslib/asn1/ard_vstr.c | 214 ++ mmslib/asn1/are_bool.c | 48 + mmslib/asn1/are_bstr.c | 74 + mmslib/asn1/are_btod.c | 58 + mmslib/asn1/are_delm.c | 43 + mmslib/asn1/are_flt.c | 122 + mmslib/asn1/are_int.c | 241 ++ mmslib/asn1/are_objd.c | 80 + mmslib/asn1/are_ostr.c | 61 + mmslib/asn1/are_time.c | 88 + mmslib/asn1/are_utc.c | 82 + mmslib/asn1/are_vstr.c | 162 + mmslib/asn1/asn1r.c | 1693 +++++++++++ mmslib/build-ubuntu.sh | 39 + mmslib/fe_common.pri | 47 + mmslib/inc/ExceptionReport.h | 135 + mmslib/inc/Goose.h | 223 ++ mmslib/inc/STR_UTIL.H | 158 + mmslib/inc/Smem.h | 467 +++ mmslib/inc/acse2.h | 310 ++ mmslib/inc/acse2log.h | 144 + mmslib/inc/acse2usr.h | 406 +++ mmslib/inc/acseauth.h | 120 + mmslib/inc/adlc.h | 1021 +++++++ mmslib/inc/adlc_dsm.h | 73 + mmslib/inc/adlc_log.h | 879 ++++++ mmslib/inc/adlc_sm.h | 317 ++ mmslib/inc/adlc_sts.h | 82 + mmslib/inc/adlc_usr.h | 441 +++ mmslib/inc/arg.h | 44 + mmslib/inc/asn1defs.h | 40 + mmslib/inc/asn1log.h | 106 + mmslib/inc/asn1r.h | 718 +++++ mmslib/inc/cfg_util.h | 112 + mmslib/inc/cfglog.h | 101 + mmslib/inc/checksum.h | 46 + mmslib/inc/clnp.h | 259 ++ mmslib/inc/clnp_llc.h | 66 + mmslib/inc/clnp_log.h | 231 ++ mmslib/inc/clnp_sne.h | 227 ++ mmslib/inc/clnp_sta.h | 125 + mmslib/inc/clnp_tnt.h | 45 + mmslib/inc/clnp_usr.h | 462 +++ mmslib/inc/clnpport.h | 52 + mmslib/inc/conpack.h | 101 + mmslib/inc/copp.h | 68 + mmslib/inc/copp_log.h | 167 ++ mmslib/inc/copp_usr.h | 193 ++ mmslib/inc/cosp.h | 199 ++ mmslib/inc/cosp_log.h | 214 ++ mmslib/inc/cosp_usr.h | 531 ++++ mmslib/inc/dibmatch.h | 64 + mmslib/inc/ethertyp.h | 72 + mmslib/inc/ethsub.h | 132 + mmslib/inc/fkeydefs.h | 209 ++ mmslib/inc/gen_list.h | 117 + mmslib/inc/gensock2.h | 591 ++++ mmslib/inc/glberror.h | 117 + mmslib/inc/glbopt.h | 43 + mmslib/inc/glbsem.h | 565 ++++ mmslib/inc/glbtypes.h | 688 +++++ mmslib/inc/gse_mgmt.h | 252 ++ mmslib/inc/gvaldefs.h | 48 + mmslib/inc/lean_a.h | 145 + mmslib/inc/llcio.h | 337 +++ mmslib/inc/llcioctl.h | 121 + mmslib/inc/mem_chk.h | 339 +++ mmslib/inc/memlog.h | 201 ++ mmslib/inc/mloguser.h | 297 ++ mmslib/inc/mms_def2.h | 308 ++ mmslib/inc/mms_dfun.h | 212 ++ mmslib/inc/mms_err.h | 213 ++ mmslib/inc/mms_log.h | 109 + mmslib/inc/mms_mp.h | 234 ++ mmslib/inc/mms_pcon.h | 294 ++ mmslib/inc/mms_pdom.h | 419 +++ mmslib/inc/mms_perr.h | 248 ++ mmslib/inc/mms_pevn.h | 956 ++++++ mmslib/inc/mms_pfil.h | 297 ++ mmslib/inc/mms_pjou.h | 299 ++ mmslib/inc/mms_pocs.h | 120 + mmslib/inc/mms_pprg.h | 287 ++ mmslib/inc/mms_psem.h | 338 +++ mmslib/inc/mms_pvar.h | 683 +++++ mmslib/inc/mms_pvmd.h | 291 ++ mmslib/inc/mms_vvar.h | 1090 +++++++ mmslib/inc/mmsdefs.h | 235 ++ mmslib/inc/mmsefun.h | 188 ++ mmslib/inc/mmsintr2.h | 317 ++ mmslib/inc/mmsldefs.h | 94 + mmslib/inc/mmslog.h | 735 +++++ mmslib/inc/mmslusec.h | 58 + mmslib/inc/mmsop_en/mmsop_en.h | 185 ++ mmslib/inc/mvl_acse.h | 234 ++ mmslib/inc/mvl_defs.h | 2552 ++++++++++++++++ mmslib/inc/mvl_log.h | 198 ++ mmslib/inc/mvl_uca.h | 898 ++++++ mmslib/inc/ntddosi.h | 114 + mmslib/inc/osillc.h | 97 + mmslib/inc/qmem.h | 35 + mmslib/inc/rs_a.h | 119 + mmslib/inc/rs_defs.h | 241 ++ mmslib/inc/scl.h | 715 +++++ mmslib/inc/scrndefs.h | 97 + mmslib/inc/slog.h | 1599 ++++++++++ mmslib/inc/smp.h | 110 + mmslib/inc/smp_log.h | 286 ++ mmslib/inc/smp_usr.h | 344 +++ mmslib/inc/smpval.h | 138 + mmslib/inc/sock_log.h | 210 ++ mmslib/inc/ssec.h | 1182 ++++++++ mmslib/inc/ssec_int.h | 56 + mmslib/inc/ssleLog.h | 154 + mmslib/inc/stdtime.h | 1446 +++++++++ mmslib/inc/stdtime_config.h | 153 + mmslib/inc/stdtime_endian.h | 90 + mmslib/inc/stdtime_enum_err.h | 65 + mmslib/inc/stdtime_enum_func.h | 425 +++ mmslib/inc/stdtime_mms_btime.h | 81 + mmslib/inc/stdtime_mms_utctime.h | 61 + mmslib/inc/stdtime_quadlib.h | 1081 +++++++ mmslib/inc/stdtime_stdint.h | 237 ++ mmslib/inc/stdtime_timezone_csv.h | 381 +++ mmslib/inc/stdtime_tzrules.h | 58 + mmslib/inc/stdtime_w32.h | 353 +++ mmslib/inc/stime.h | 38 + mmslib/inc/sx_arb.h | 119 + mmslib/inc/sx_defs.h | 611 ++++ mmslib/inc/sx_log.h | 337 +++ mmslib/inc/sysincs.h | 459 +++ mmslib/inc/time_str.h | 137 + mmslib/inc/tp0_sock.h | 268 ++ mmslib/inc/tp4.h | 363 +++ mmslib/inc/tp4_encd.h | 407 +++ mmslib/inc/tp4_log.h | 228 ++ mmslib/inc/tp4api.h | 333 +++ mmslib/inc/tp4api.h.bak | 333 +++ mmslib/mem/mem_chks.c | 1837 ++++++++++++ mmslib/mmsl/mms_adl.c | 1346 +++++++++ mmslib/mmsl/mms_alta.c | 934 ++++++ mmslib/mmsl/mms_aref.c | 390 +++ mmslib/mmsl/mms_ced.c | 265 ++ mmslib/mmsl/mms_ced3.c | 223 ++ mmslib/mmsl/mms_ced4.c | 936 ++++++ mmslib/mmsl/mms_ced5.c | 77 + mmslib/mmsl/mms_ced6.c | 151 + mmslib/mmsl/mms_ced7.c | 543 ++++ mmslib/mmsl/mms_err.c | 775 +++++ mmslib/mmsl/mms_err2.c | 110 + mmslib/mmsl/mms_err3.c | 75 + mmslib/mmsl/mms_err4.c | 96 + mmslib/mmsl/mms_rej.c | 281 ++ mmslib/mmsl/mms_rtaa.c | 1222 ++++++++ mmslib/mmsl/mms_tdef.c | 3265 ++++++++++++++++++++ mmslib/mmsl/mmscancl.c | 73 + mmslib/mmsl/mmsconcl.c | 76 + mmslib/mmsl/mmsdata.c | 1758 +++++++++++ mmslib/mmsl/mmsdatat.c | 1231 ++++++++ mmslib/mmsl/mmsdec.c | 768 +++++ mmslib/mmsl/mmsdtext.c | 729 +++++ mmslib/mmsl/mmsinit.c | 587 ++++ mmslib/mmsl/mmsl_fin.c | 355 +++ mmslib/mmsl/mmslvar.c | 232 ++ mmslib/mmsl/mmsstat.c | 205 ++ mmslib/mmsl/ms_ext.c | 442 +++ mmslib/mmsl/ms_size.c | 600 ++++ mmslib/mmsl/ms_tdef.c | 1153 +++++++ mmslib/mmsl/ms_tdef2.c | 226 ++ mmslib/mmsl/ms_tdef4.c | 51 + mmslib/mmsl/msdataas.c | 101 + mmslib/mmsl/rq_ackev.c | 113 + mmslib/mmsl/rq_cancl.c | 153 + mmslib/mmsl/rq_concl.c | 151 + mmslib/mmsl/rq_defee.c | 127 + mmslib/mmsl/rq_evnot.c | 181 ++ mmslib/mmsl/rq_getcl.c | 225 ++ mmslib/mmsl/rq_getdo.c | 354 +++ mmslib/mmsl/rq_getea.c | 290 ++ mmslib/mmsl/rq_getec.c | 321 ++ mmslib/mmsl/rq_getee.c | 807 +++++ mmslib/mmsl/rq_getpi.c | 327 ++ mmslib/mmsl/rq_getty.c | 141 + mmslib/mmsl/rq_getva.c | 225 ++ mmslib/mmsl/rq_getvl.c | 187 ++ mmslib/mmsl/rq_ident.c | 247 ++ mmslib/mmsl/rq_info.c | 127 + mmslib/mmsl/rq_init.c | 251 ++ mmslib/mmsl/rq_namel.c | 253 ++ mmslib/mmsl/rq_read.c | 276 ++ mmslib/mmsl/rq_repea.c | 117 + mmslib/mmsl/rq_repec.c | 249 ++ mmslib/mmsl/rq_repee.c | 262 ++ mmslib/mmsl/rq_stat.c | 107 + mmslib/mmsl/rq_trige.c | 104 + mmslib/mmsl/rq_ustat.c | 118 + mmslib/mmsl/rq_write.c | 212 ++ mmslib/mmsl/rs_ackev.c | 231 ++ mmslib/mmsl/rs_cancl.c | 147 + mmslib/mmsl/rs_concl.c | 136 + mmslib/mmsl/rs_defee.c | 387 +++ mmslib/mmsl/rs_evnot.c | 479 +++ mmslib/mmsl/rs_getcl.c | 158 + mmslib/mmsl/rs_getdo.c | 151 + mmslib/mmsl/rs_getea.c | 154 + mmslib/mmsl/rs_getec.c | 170 ++ mmslib/mmsl/rs_getee.c | 527 ++++ mmslib/mmsl/rs_getpi.c | 148 + mmslib/mmsl/rs_getty.c | 126 + mmslib/mmsl/rs_getva.c | 170 ++ mmslib/mmsl/rs_getvl.c | 139 + mmslib/mmsl/rs_ident.c | 122 + mmslib/mmsl/rs_info.c | 184 ++ mmslib/mmsl/rs_init.c | 266 ++ mmslib/mmsl/rs_namel.c | 341 +++ mmslib/mmsl/rs_read.c | 209 ++ mmslib/mmsl/rs_repea.c | 126 + mmslib/mmsl/rs_repec.c | 148 + mmslib/mmsl/rs_repee.c | 142 + mmslib/mmsl/rs_stat.c | 120 + mmslib/mmsl/rs_trige.c | 151 + mmslib/mmsl/rs_ustat.c | 47 + mmslib/mmsl/rs_write.c | 248 ++ mmslib/mmsle/mms_ced1.c | 448 +++ mmslib/mmsle/mms_ced2.c | 115 + mmslib/mmsle/rq_altec.c | 124 + mmslib/mmsle/rq_altee.c | 233 ++ mmslib/mmsle/rq_crepi.c | 122 + mmslib/mmsle/rq_defea.c | 125 + mmslib/mmsle/rq_defec.c | 131 + mmslib/mmsle/rq_defsc.c | 100 + mmslib/mmsle/rq_defse.c | 104 + mmslib/mmsle/rq_defty.c | 96 + mmslib/mmsle/rq_defva.c | 100 + mmslib/mmsle/rq_defvl.c | 106 + mmslib/mmsle/rq_deldo.c | 93 + mmslib/mmsle/rq_delea.c | 141 + mmslib/mmsle/rq_delec.c | 142 + mmslib/mmsle/rq_delee.c | 141 + mmslib/mmsle/rq_delpi.c | 96 + mmslib/mmsle/rq_delse.c | 97 + mmslib/mmsle/rq_delty.c | 169 ++ mmslib/mmsle/rq_delva.c | 168 ++ mmslib/mmsle/rq_delvl.c | 171 ++ mmslib/mmsle/rq_downl.c | 214 ++ mmslib/mmsle/rq_fclos.c | 96 + mmslib/mmsle/rq_fdele.c | 97 + mmslib/mmsle/rq_fdir.c | 351 +++ mmslib/mmsle/rq_fopen.c | 197 ++ mmslib/mmsle/rq_fread.c | 190 ++ mmslib/mmsle/rq_frena.c | 108 + mmslib/mmsle/rq_getae.c | 682 +++++ mmslib/mmsle/rq_getas.c | 498 ++++ mmslib/mmsle/rq_getsc.c | 168 ++ mmslib/mmsle/rq_initd.c | 146 + mmslib/mmsle/rq_initu.c | 215 ++ mmslib/mmsle/rq_input.c | 146 + mmslib/mmsle/rq_jcrea.c | 97 + mmslib/mmsle/rq_jdele.c | 97 + mmslib/mmsle/rq_jinit.c | 130 + mmslib/mmsle/rq_jread.c | 431 +++ mmslib/mmsle/rq_jstat.c | 144 + mmslib/mmsle/rq_jwrit.c | 144 + mmslib/mmsle/rq_kill.c | 96 + mmslib/mmsle/rq_loadd.c | 126 + mmslib/mmsle/rq_obtfi.c | 115 + mmslib/mmsle/rq_outpu.c | 110 + mmslib/mmsle/rq_rddwn.c | 121 + mmslib/mmsle/rq_rdupl.c | 100 + mmslib/mmsle/rq_relct.c | 108 + mmslib/mmsle/rq_renam.c | 120 + mmslib/mmsle/rq_reset.c | 96 + mmslib/mmsle/rq_resum.c | 107 + mmslib/mmsle/rq_rsent.c | 457 +++ mmslib/mmsle/rq_rspoo.c | 221 ++ mmslib/mmsle/rq_rssta.c | 198 ++ mmslib/mmsle/rq_start.c | 108 + mmslib/mmsle/rq_stop.c | 96 + mmslib/mmsle/rq_store.c | 108 + mmslib/mmsle/rq_takec.c | 192 ++ mmslib/mmsle/rq_termd.c | 143 + mmslib/mmsle/rq_termu.c | 94 + mmslib/mmsle/rq_uploa.c | 216 ++ mmslib/mmsle/rs_altec.c | 226 ++ mmslib/mmsle/rs_altee.c | 256 ++ mmslib/mmsle/rs_crepi.c | 242 ++ mmslib/mmsle/rs_defea.c | 315 ++ mmslib/mmsle/rs_defec.c | 290 ++ mmslib/mmsle/rs_defsc.c | 169 ++ mmslib/mmsle/rs_defse.c | 147 + mmslib/mmsle/rs_defty.c | 116 + mmslib/mmsle/rs_defva.c | 198 ++ mmslib/mmsle/rs_defvl.c | 177 ++ mmslib/mmsle/rs_deldo.c | 96 + mmslib/mmsle/rs_delea.c | 250 ++ mmslib/mmsle/rs_delec.c | 250 ++ mmslib/mmsle/rs_delee.c | 286 ++ mmslib/mmsle/rs_delpi.c | 95 + mmslib/mmsle/rs_delse.c | 102 + mmslib/mmsle/rs_delty.c | 251 ++ mmslib/mmsle/rs_delva.c | 101 + mmslib/mmsle/rs_delvl.c | 103 + mmslib/mmsle/rs_downl.c | 130 + mmslib/mmsle/rs_fclos.c | 101 + mmslib/mmsle/rs_fdele.c | 134 + mmslib/mmsle/rs_fdir.c | 298 ++ mmslib/mmsle/rs_fopen.c | 190 ++ mmslib/mmsle/rs_fread.c | 122 + mmslib/mmsle/rs_frena.c | 172 ++ mmslib/mmsle/rs_getae.c | 378 +++ mmslib/mmsle/rs_getas.c | 348 +++ mmslib/mmsle/rs_getsc.c | 135 + mmslib/mmsle/rs_initd.c | 240 ++ mmslib/mmsle/rs_initu.c | 132 + mmslib/mmsle/rs_input.c | 251 ++ mmslib/mmsle/rs_jcrea.c | 133 + mmslib/mmsle/rs_jdele.c | 132 + mmslib/mmsle/rs_jinit.c | 260 ++ mmslib/mmsle/rs_jread.c | 620 ++++ mmslib/mmsle/rs_jstat.c | 130 + mmslib/mmsle/rs_jwrit.c | 241 ++ mmslib/mmsle/rs_kill.c | 109 + mmslib/mmsle/rs_loadd.c | 288 ++ mmslib/mmsle/rs_obtfi.c | 217 ++ mmslib/mmsle/rs_outpu.c | 184 ++ mmslib/mmsle/rs_rddwn.c | 251 ++ mmslib/mmsle/rs_rdupl.c | 157 + mmslib/mmsle/rs_relct.c | 148 + mmslib/mmsle/rs_renam.c | 232 ++ mmslib/mmsle/rs_reset.c | 109 + mmslib/mmsle/rs_resum.c | 157 + mmslib/mmsle/rs_rsent.c | 305 ++ mmslib/mmsle/rs_rspoo.c | 191 ++ mmslib/mmsle/rs_rssta.c | 138 + mmslib/mmsle/rs_start.c | 153 + mmslib/mmsle/rs_stop.c | 108 + mmslib/mmsle/rs_store.c | 200 ++ mmslib/mmsle/rs_takec.c | 342 +++ mmslib/mmsle/rs_termd.c | 156 + mmslib/mmsle/rs_termu.c | 95 + mmslib/mmsle/rs_uploa.c | 128 + mmslib/mmslib.cpp | 13 + mmslib/mmslib.h | 13 + mmslib/mmslib.pro | 500 ++++ mmslib/mmslib.pro.user | 194 ++ mmslib/mmslib.pro.user.18 | 258 ++ mmslib/mmslib.pro.user.2.7pre1 | 243 ++ mmslib/mmslib.pro.user.3.2-pre1 | 247 ++ mmslib/mmslib.pro.user.5822199 | 243 ++ mmslib/mmslib.pro.user.5822199.2.7pre1 | 243 ++ mmslib/mmslib.pro.user.d8c8bb2 | 243 ++ mmslib/mvlu/c_concl.c | 160 + mmslib/mvlu/c_defvl.c | 134 + mmslib/mvlu/c_delvl.c | 134 + mmslib/mvlu/c_fclose.c | 133 + mmslib/mvlu/c_fdel.c | 150 + mmslib/mvlu/c_fdir.c | 231 ++ mmslib/mvlu/c_fget.c | 460 +++ mmslib/mvlu/c_fopen.c | 158 + mmslib/mvlu/c_fread.c | 139 + mmslib/mvlu/c_fren.c | 140 + mmslib/mvlu/c_getdom.c | 133 + mmslib/mvlu/c_getnam.c | 133 + mmslib/mvlu/c_getvar.c | 133 + mmslib/mvlu/c_getvla.c | 135 + mmslib/mvlu/c_ident.c | 115 + mmslib/mvlu/c_info.c | 292 ++ mmslib/mvlu/c_jinit.c | 134 + mmslib/mvlu/c_jread.c | 202 ++ mmslib/mvlu/c_jstat.c | 134 + mmslib/mvlu/c_obtfi.c | 135 + mmslib/mvlu/c_read.c | 243 ++ mmslib/mvlu/c_status.c | 133 + mmslib/mvlu/c_write.c | 322 ++ mmslib/mvlu/mvl61850.c | 1177 ++++++++ mmslib/mvlu/mvl61850_ctl.c | 811 +++++ mmslib/mvlu/mvl61850_rpt.c | 1367 +++++++++ mmslib/mvlu/mvl_buf.c | 24 + mmslib/mvlu/mvl_dtyp.c | 532 ++++ mmslib/mvlu/mvl_ijou.c | 601 ++++ mmslib/mvlu/mvl_obj.c | 1131 +++++++ mmslib/mvlu/mvl_objb.c | 755 +++++ mmslib/mvlu/mvl_send.c | 176 ++ mmslib/mvlu/mvl_serv.c | 1069 +++++++ mmslib/mvlu/mvl_typ2.c | 322 ++ mmslib/mvlu/mvl_type.c | 266 ++ mmslib/mvlu/mvl_uca.c | 2688 +++++++++++++++++ mmslib/mvlu/mvl_var.c | 400 +++ mmslib/mvlu/mvlu_rpt.c | 2570 ++++++++++++++++ mmslib/mvlu/mvlu_rt.c | 422 +++ mmslib/mvlu/mvlu_sbo.c | 352 +++ mmslib/mvlu/mvluleaf.c | 477 +++ mmslib/mvlu/s_cancel.c | 53 + mmslib/mvlu/s_concl.c | 99 + mmslib/mvlu/s_defvl.c | 137 + mmslib/mvlu/s_delvl.c | 190 ++ mmslib/mvlu/s_fclose.c | 68 + mmslib/mvlu/s_fdel.c | 77 + mmslib/mvlu/s_fdir.c | 769 +++++ mmslib/mvlu/s_fopen.c | 81 + mmslib/mvlu/s_fread.c | 75 + mmslib/mvlu/s_fren.c | 82 + mmslib/mvlu/s_getcl.c | 65 + mmslib/mvlu/s_getdom.c | 108 + mmslib/mvlu/s_getnam.c | 439 +++ mmslib/mvlu/s_getvaa.c | 265 ++ mmslib/mvlu/s_getvla.c | 167 ++ mmslib/mvlu/s_ident.c | 65 + mmslib/mvlu/s_info.c | 219 ++ mmslib/mvlu/s_jinit.c | 69 + mmslib/mvlu/s_jread.c | 337 +++ mmslib/mvlu/s_jstat.c | 67 + mmslib/mvlu/s_obtfi.c | 466 +++ mmslib/mvlu/s_read.c | 449 +++ mmslib/mvlu/s_status.c | 67 + mmslib/mvlu/s_write.c | 438 +++ mmslib/mvlu/sclproc.c | 3286 ++++++++++++++++++++ mmslib/object_script.libmmslib.Debug | 349 +++ mmslib/object_script.libmmslib.Release | 349 +++ mmslib/ositcps/acse2dec.c | 2268 ++++++++++++++ mmslib/ositcps/acse2dib.c | 522 ++++ mmslib/ositcps/acse2enc.c | 1334 +++++++++ mmslib/ositcps/acse2var.c | 39 + mmslib/ositcps/checksum.c | 246 ++ mmslib/ositcps/copp_dec.c | 488 +++ mmslib/ositcps/copp_enc.c | 660 ++++ mmslib/ositcps/coppdaru.c | 280 ++ mmslib/ositcps/coppdcp.c | 767 +++++ mmslib/ositcps/coppdcpr.c | 401 +++ mmslib/ositcps/cosp_dec.c | 1090 +++++++ mmslib/ositcps/cosp_enc.c | 812 +++++ mmslib/ositcps/cospmain.c | 2043 +++++++++++++ mmslib/ositcps/lean_cfg.c | 1271 ++++++++ mmslib/ositcps/lean_var.c | 163 + mmslib/ositcps/osicfgx.c | 1822 +++++++++++ mmslib/ositcps/tp0_dec.c | 181 ++ mmslib/ositcps/tp0_socks.c | 1937 ++++++++++++ mmslib/ositcps/tp0calld.c | 210 ++ mmslib/ositcps/tp0callg.c | 243 ++ mmslib/ositcps/tp0main.c | 1173 ++++++++ mmslib/ositcps/tp4_enc.c | 539 ++++ mmslib/ositcps/tp4port.c | 100 + mmslib/ositcps/tpx_dec.c | 1053 +++++++ mmslib/slog/qmem.c | 166 ++ mmslib/slog/slog.c | 1004 +++++++ mmslib/slog/slogfil.c | 741 +++++ mmslib/slog/sloghex.c | 362 +++ mmslib/slog/slogipcs.c | 124 + mmslib/slog/slogmem.c | 434 +++ mmslib/ssec0/ssecusr0.c | 794 +++++ mmslib/util/cfg_util.c | 889 ++++++ mmslib/util/genlists.c | 464 +++ mmslib/util/gensock2.c | 2814 +++++++++++++++++ mmslib/util/glbsem.c | 462 +++ mmslib/util/glbsem_unix.c | 1064 +++++++ mmslib/util/glbsem_w32.c | 1139 +++++++ mmslib/util/scl_log.c | 353 +++ mmslib/util/sclparse.c | 2507 ++++++++++++++++ mmslib/util/sclstore.c | 737 +++++ mmslib/util/stdtime.c | 3815 ++++++++++++++++++++++++ mmslib/util/stdtime_mms_btime.c | 194 ++ mmslib/util/stdtime_mms_utctime.c | 169 ++ mmslib/util/stdtime_quadlib.c | 1599 ++++++++++ mmslib/util/stdtime_w32.c | 1348 +++++++++ mmslib/util/stime.c | 479 +++ mmslib/util/str_util.c | 947 ++++++ mmslib/util/sx_axs4d.c | 1964 ++++++++++++ mmslib/util/sx_data.c | 2601 ++++++++++++++++ mmslib/util/sx_dec.c | 2520 ++++++++++++++++ mmslib/util/sx_enc.c | 1344 +++++++++ mmslib/util/time_str.c | 2748 +++++++++++++++++ pt61850netd_pqfe.pro | 50 +- 621 files changed, 224958 insertions(+), 48 deletions(-) create mode 100644 include/inc/ExceptionReport.h create mode 100644 include/inc/Goose.h create mode 100644 include/inc/STR_UTIL.H create mode 100644 include/inc/Smem.h create mode 100644 include/inc/acse2.h create mode 100644 include/inc/acse2log.h create mode 100644 include/inc/acse2usr.h create mode 100644 include/inc/acseauth.h create mode 100644 include/inc/adlc.h create mode 100644 include/inc/adlc_dsm.h create mode 100644 include/inc/adlc_log.h create mode 100644 include/inc/adlc_sm.h create mode 100644 include/inc/adlc_sts.h create mode 100644 include/inc/adlc_usr.h create mode 100644 include/inc/arg.h create mode 100644 include/inc/asn1defs.h create mode 100644 include/inc/asn1log.h create mode 100644 include/inc/asn1r.h create mode 100644 include/inc/cfg_util.h create mode 100644 include/inc/cfglog.h create mode 100644 include/inc/checksum.h create mode 100644 include/inc/clnp.h create mode 100644 include/inc/clnp_llc.h create mode 100644 include/inc/clnp_log.h create mode 100644 include/inc/clnp_sne.h create mode 100644 include/inc/clnp_sta.h create mode 100644 include/inc/clnp_tnt.h create mode 100644 include/inc/clnp_usr.h create mode 100644 include/inc/clnpport.h create mode 100644 include/inc/conpack.h create mode 100644 include/inc/copp.h create mode 100644 include/inc/copp_log.h create mode 100644 include/inc/copp_usr.h create mode 100644 include/inc/cosp.h create mode 100644 include/inc/cosp_log.h create mode 100644 include/inc/cosp_usr.h create mode 100644 include/inc/dibmatch.h create mode 100644 include/inc/ethertyp.h create mode 100644 include/inc/ethsub.h create mode 100644 include/inc/fkeydefs.h create mode 100644 include/inc/gen_list.h create mode 100644 include/inc/gensock2.h create mode 100644 include/inc/glberror.h create mode 100644 include/inc/glbopt.h create mode 100644 include/inc/glbsem.h create mode 100644 include/inc/glbtypes.h create mode 100644 include/inc/gse_mgmt.h create mode 100644 include/inc/gvaldefs.h create mode 100644 include/inc/lean_a.h create mode 100644 include/inc/llcio.h create mode 100644 include/inc/llcioctl.h create mode 100644 include/inc/mem_chk.h create mode 100644 include/inc/memlog.h create mode 100644 include/inc/mloguser.h create mode 100644 include/inc/mms_def2.h create mode 100644 include/inc/mms_dfun.h create mode 100644 include/inc/mms_err.h create mode 100644 include/inc/mms_log.h create mode 100644 include/inc/mms_mp.h create mode 100644 include/inc/mms_pcon.h create mode 100644 include/inc/mms_pdom.h create mode 100644 include/inc/mms_perr.h create mode 100644 include/inc/mms_pevn.h create mode 100644 include/inc/mms_pfil.h create mode 100644 include/inc/mms_pjou.h create mode 100644 include/inc/mms_pocs.h create mode 100644 include/inc/mms_pprg.h create mode 100644 include/inc/mms_psem.h create mode 100644 include/inc/mms_pvar.h create mode 100644 include/inc/mms_pvmd.h create mode 100644 include/inc/mms_vvar.h create mode 100644 include/inc/mmsdefs.h create mode 100644 include/inc/mmsefun.h create mode 100644 include/inc/mmsintr2.h create mode 100644 include/inc/mmsldefs.h create mode 100644 include/inc/mmslog.h create mode 100644 include/inc/mmslusec.h create mode 100644 include/inc/mmsop_en/mmsop_en.h create mode 100644 include/inc/mvl_acse.h create mode 100644 include/inc/mvl_defs.h create mode 100644 include/inc/mvl_log.h create mode 100644 include/inc/mvl_uca.h create mode 100644 include/inc/ntddosi.h create mode 100644 include/inc/osillc.h create mode 100644 include/inc/qmem.h create mode 100644 include/inc/rs_a.h create mode 100644 include/inc/rs_defs.h create mode 100644 include/inc/scl.h create mode 100644 include/inc/scrndefs.h create mode 100644 include/inc/slog.h create mode 100644 include/inc/smp.h create mode 100644 include/inc/smp_log.h create mode 100644 include/inc/smp_usr.h create mode 100644 include/inc/smpval.h create mode 100644 include/inc/sock_log.h create mode 100644 include/inc/ssec.h create mode 100644 include/inc/ssec_int.h create mode 100644 include/inc/ssleLog.h create mode 100644 include/inc/stdtime.h create mode 100644 include/inc/stdtime_config.h create mode 100644 include/inc/stdtime_endian.h create mode 100644 include/inc/stdtime_enum_err.h create mode 100644 include/inc/stdtime_enum_func.h create mode 100644 include/inc/stdtime_mms_btime.h create mode 100644 include/inc/stdtime_mms_utctime.h create mode 100644 include/inc/stdtime_quadlib.h create mode 100644 include/inc/stdtime_stdint.h create mode 100644 include/inc/stdtime_timezone_csv.h create mode 100644 include/inc/stdtime_tzrules.h create mode 100644 include/inc/stdtime_w32.h create mode 100644 include/inc/stime.h create mode 100644 include/inc/sx_arb.h create mode 100644 include/inc/sx_defs.h create mode 100644 include/inc/sx_log.h create mode 100644 include/inc/sysincs.h create mode 100644 include/inc/time_str.h create mode 100644 include/inc/tp0_sock.h create mode 100644 include/inc/tp4.h create mode 100644 include/inc/tp4_encd.h create mode 100644 include/inc/tp4_log.h create mode 100644 include/inc/tp4api.h create mode 100644 include/inc/tp4api.h.bak create mode 100644 lib/libcurl.so.4 create mode 100644 lib/libcurl.so.4.3.0 create mode 100644 lib/libcurl.so.4.7.0 create mode 100644 lib/liblog4cplus.so.9 create mode 100644 lib/libmxml.so.1 create mode 100644 lib/libmxml.so.1.5 create mode 100644 mmslib/.vscode/c_cpp_properties.json create mode 100644 mmslib/.vscode/launch.json create mode 100644 mmslib/.vscode/settings.json create mode 100644 mmslib/Makefile create mode 100644 mmslib/Makefile.Debug create mode 100644 mmslib/Makefile.Release create mode 100644 mmslib/asn1/ard_bool.c create mode 100644 mmslib/asn1/ard_bstr.c create mode 100644 mmslib/asn1/ard_btod.c create mode 100644 mmslib/asn1/ard_delm.c create mode 100644 mmslib/asn1/ard_flt.c create mode 100644 mmslib/asn1/ard_idnt.c create mode 100644 mmslib/asn1/ard_int.c create mode 100644 mmslib/asn1/ard_objd.c create mode 100644 mmslib/asn1/ard_ostr.c create mode 100644 mmslib/asn1/ard_strn.c create mode 100644 mmslib/asn1/ard_time.c create mode 100644 mmslib/asn1/ard_utc.c create mode 100644 mmslib/asn1/ard_vstr.c create mode 100644 mmslib/asn1/are_bool.c create mode 100644 mmslib/asn1/are_bstr.c create mode 100644 mmslib/asn1/are_btod.c create mode 100644 mmslib/asn1/are_delm.c create mode 100644 mmslib/asn1/are_flt.c create mode 100644 mmslib/asn1/are_int.c create mode 100644 mmslib/asn1/are_objd.c create mode 100644 mmslib/asn1/are_ostr.c create mode 100644 mmslib/asn1/are_time.c create mode 100644 mmslib/asn1/are_utc.c create mode 100644 mmslib/asn1/are_vstr.c create mode 100644 mmslib/asn1/asn1r.c create mode 100644 mmslib/build-ubuntu.sh create mode 100644 mmslib/fe_common.pri create mode 100644 mmslib/inc/ExceptionReport.h create mode 100644 mmslib/inc/Goose.h create mode 100644 mmslib/inc/STR_UTIL.H create mode 100644 mmslib/inc/Smem.h create mode 100644 mmslib/inc/acse2.h create mode 100644 mmslib/inc/acse2log.h create mode 100644 mmslib/inc/acse2usr.h create mode 100644 mmslib/inc/acseauth.h create mode 100644 mmslib/inc/adlc.h create mode 100644 mmslib/inc/adlc_dsm.h create mode 100644 mmslib/inc/adlc_log.h create mode 100644 mmslib/inc/adlc_sm.h create mode 100644 mmslib/inc/adlc_sts.h create mode 100644 mmslib/inc/adlc_usr.h create mode 100644 mmslib/inc/arg.h create mode 100644 mmslib/inc/asn1defs.h create mode 100644 mmslib/inc/asn1log.h create mode 100644 mmslib/inc/asn1r.h create mode 100644 mmslib/inc/cfg_util.h create mode 100644 mmslib/inc/cfglog.h create mode 100644 mmslib/inc/checksum.h create mode 100644 mmslib/inc/clnp.h create mode 100644 mmslib/inc/clnp_llc.h create mode 100644 mmslib/inc/clnp_log.h create mode 100644 mmslib/inc/clnp_sne.h create mode 100644 mmslib/inc/clnp_sta.h create mode 100644 mmslib/inc/clnp_tnt.h create mode 100644 mmslib/inc/clnp_usr.h create mode 100644 mmslib/inc/clnpport.h create mode 100644 mmslib/inc/conpack.h create mode 100644 mmslib/inc/copp.h create mode 100644 mmslib/inc/copp_log.h create mode 100644 mmslib/inc/copp_usr.h create mode 100644 mmslib/inc/cosp.h create mode 100644 mmslib/inc/cosp_log.h create mode 100644 mmslib/inc/cosp_usr.h create mode 100644 mmslib/inc/dibmatch.h create mode 100644 mmslib/inc/ethertyp.h create mode 100644 mmslib/inc/ethsub.h create mode 100644 mmslib/inc/fkeydefs.h create mode 100644 mmslib/inc/gen_list.h create mode 100644 mmslib/inc/gensock2.h create mode 100644 mmslib/inc/glberror.h create mode 100644 mmslib/inc/glbopt.h create mode 100644 mmslib/inc/glbsem.h create mode 100644 mmslib/inc/glbtypes.h create mode 100644 mmslib/inc/gse_mgmt.h create mode 100644 mmslib/inc/gvaldefs.h create mode 100644 mmslib/inc/lean_a.h create mode 100644 mmslib/inc/llcio.h create mode 100644 mmslib/inc/llcioctl.h create mode 100644 mmslib/inc/mem_chk.h create mode 100644 mmslib/inc/memlog.h create mode 100644 mmslib/inc/mloguser.h create mode 100644 mmslib/inc/mms_def2.h create mode 100644 mmslib/inc/mms_dfun.h create mode 100644 mmslib/inc/mms_err.h create mode 100644 mmslib/inc/mms_log.h create mode 100644 mmslib/inc/mms_mp.h create mode 100644 mmslib/inc/mms_pcon.h create mode 100644 mmslib/inc/mms_pdom.h create mode 100644 mmslib/inc/mms_perr.h create mode 100644 mmslib/inc/mms_pevn.h create mode 100644 mmslib/inc/mms_pfil.h create mode 100644 mmslib/inc/mms_pjou.h create mode 100644 mmslib/inc/mms_pocs.h create mode 100644 mmslib/inc/mms_pprg.h create mode 100644 mmslib/inc/mms_psem.h create mode 100644 mmslib/inc/mms_pvar.h create mode 100644 mmslib/inc/mms_pvmd.h create mode 100644 mmslib/inc/mms_vvar.h create mode 100644 mmslib/inc/mmsdefs.h create mode 100644 mmslib/inc/mmsefun.h create mode 100644 mmslib/inc/mmsintr2.h create mode 100644 mmslib/inc/mmsldefs.h create mode 100644 mmslib/inc/mmslog.h create mode 100644 mmslib/inc/mmslusec.h create mode 100644 mmslib/inc/mmsop_en/mmsop_en.h create mode 100644 mmslib/inc/mvl_acse.h create mode 100644 mmslib/inc/mvl_defs.h create mode 100644 mmslib/inc/mvl_log.h create mode 100644 mmslib/inc/mvl_uca.h create mode 100644 mmslib/inc/ntddosi.h create mode 100644 mmslib/inc/osillc.h create mode 100644 mmslib/inc/qmem.h create mode 100644 mmslib/inc/rs_a.h create mode 100644 mmslib/inc/rs_defs.h create mode 100644 mmslib/inc/scl.h create mode 100644 mmslib/inc/scrndefs.h create mode 100644 mmslib/inc/slog.h create mode 100644 mmslib/inc/smp.h create mode 100644 mmslib/inc/smp_log.h create mode 100644 mmslib/inc/smp_usr.h create mode 100644 mmslib/inc/smpval.h create mode 100644 mmslib/inc/sock_log.h create mode 100644 mmslib/inc/ssec.h create mode 100644 mmslib/inc/ssec_int.h create mode 100644 mmslib/inc/ssleLog.h create mode 100644 mmslib/inc/stdtime.h create mode 100644 mmslib/inc/stdtime_config.h create mode 100644 mmslib/inc/stdtime_endian.h create mode 100644 mmslib/inc/stdtime_enum_err.h create mode 100644 mmslib/inc/stdtime_enum_func.h create mode 100644 mmslib/inc/stdtime_mms_btime.h create mode 100644 mmslib/inc/stdtime_mms_utctime.h create mode 100644 mmslib/inc/stdtime_quadlib.h create mode 100644 mmslib/inc/stdtime_stdint.h create mode 100644 mmslib/inc/stdtime_timezone_csv.h create mode 100644 mmslib/inc/stdtime_tzrules.h create mode 100644 mmslib/inc/stdtime_w32.h create mode 100644 mmslib/inc/stime.h create mode 100644 mmslib/inc/sx_arb.h create mode 100644 mmslib/inc/sx_defs.h create mode 100644 mmslib/inc/sx_log.h create mode 100644 mmslib/inc/sysincs.h create mode 100644 mmslib/inc/time_str.h create mode 100644 mmslib/inc/tp0_sock.h create mode 100644 mmslib/inc/tp4.h create mode 100644 mmslib/inc/tp4_encd.h create mode 100644 mmslib/inc/tp4_log.h create mode 100644 mmslib/inc/tp4api.h create mode 100644 mmslib/inc/tp4api.h.bak create mode 100644 mmslib/mem/mem_chks.c create mode 100644 mmslib/mmsl/mms_adl.c create mode 100644 mmslib/mmsl/mms_alta.c create mode 100644 mmslib/mmsl/mms_aref.c create mode 100644 mmslib/mmsl/mms_ced.c create mode 100644 mmslib/mmsl/mms_ced3.c create mode 100644 mmslib/mmsl/mms_ced4.c create mode 100644 mmslib/mmsl/mms_ced5.c create mode 100644 mmslib/mmsl/mms_ced6.c create mode 100644 mmslib/mmsl/mms_ced7.c create mode 100644 mmslib/mmsl/mms_err.c create mode 100644 mmslib/mmsl/mms_err2.c create mode 100644 mmslib/mmsl/mms_err3.c create mode 100644 mmslib/mmsl/mms_err4.c create mode 100644 mmslib/mmsl/mms_rej.c create mode 100644 mmslib/mmsl/mms_rtaa.c create mode 100644 mmslib/mmsl/mms_tdef.c create mode 100644 mmslib/mmsl/mmscancl.c create mode 100644 mmslib/mmsl/mmsconcl.c create mode 100644 mmslib/mmsl/mmsdata.c create mode 100644 mmslib/mmsl/mmsdatat.c create mode 100644 mmslib/mmsl/mmsdec.c create mode 100644 mmslib/mmsl/mmsdtext.c create mode 100644 mmslib/mmsl/mmsinit.c create mode 100644 mmslib/mmsl/mmsl_fin.c create mode 100644 mmslib/mmsl/mmslvar.c create mode 100644 mmslib/mmsl/mmsstat.c create mode 100644 mmslib/mmsl/ms_ext.c create mode 100644 mmslib/mmsl/ms_size.c create mode 100644 mmslib/mmsl/ms_tdef.c create mode 100644 mmslib/mmsl/ms_tdef2.c create mode 100644 mmslib/mmsl/ms_tdef4.c create mode 100644 mmslib/mmsl/msdataas.c create mode 100644 mmslib/mmsl/rq_ackev.c create mode 100644 mmslib/mmsl/rq_cancl.c create mode 100644 mmslib/mmsl/rq_concl.c create mode 100644 mmslib/mmsl/rq_defee.c create mode 100644 mmslib/mmsl/rq_evnot.c create mode 100644 mmslib/mmsl/rq_getcl.c create mode 100644 mmslib/mmsl/rq_getdo.c create mode 100644 mmslib/mmsl/rq_getea.c create mode 100644 mmslib/mmsl/rq_getec.c create mode 100644 mmslib/mmsl/rq_getee.c create mode 100644 mmslib/mmsl/rq_getpi.c create mode 100644 mmslib/mmsl/rq_getty.c create mode 100644 mmslib/mmsl/rq_getva.c create mode 100644 mmslib/mmsl/rq_getvl.c create mode 100644 mmslib/mmsl/rq_ident.c create mode 100644 mmslib/mmsl/rq_info.c create mode 100644 mmslib/mmsl/rq_init.c create mode 100644 mmslib/mmsl/rq_namel.c create mode 100644 mmslib/mmsl/rq_read.c create mode 100644 mmslib/mmsl/rq_repea.c create mode 100644 mmslib/mmsl/rq_repec.c create mode 100644 mmslib/mmsl/rq_repee.c create mode 100644 mmslib/mmsl/rq_stat.c create mode 100644 mmslib/mmsl/rq_trige.c create mode 100644 mmslib/mmsl/rq_ustat.c create mode 100644 mmslib/mmsl/rq_write.c create mode 100644 mmslib/mmsl/rs_ackev.c create mode 100644 mmslib/mmsl/rs_cancl.c create mode 100644 mmslib/mmsl/rs_concl.c create mode 100644 mmslib/mmsl/rs_defee.c create mode 100644 mmslib/mmsl/rs_evnot.c create mode 100644 mmslib/mmsl/rs_getcl.c create mode 100644 mmslib/mmsl/rs_getdo.c create mode 100644 mmslib/mmsl/rs_getea.c create mode 100644 mmslib/mmsl/rs_getec.c create mode 100644 mmslib/mmsl/rs_getee.c create mode 100644 mmslib/mmsl/rs_getpi.c create mode 100644 mmslib/mmsl/rs_getty.c create mode 100644 mmslib/mmsl/rs_getva.c create mode 100644 mmslib/mmsl/rs_getvl.c create mode 100644 mmslib/mmsl/rs_ident.c create mode 100644 mmslib/mmsl/rs_info.c create mode 100644 mmslib/mmsl/rs_init.c create mode 100644 mmslib/mmsl/rs_namel.c create mode 100644 mmslib/mmsl/rs_read.c create mode 100644 mmslib/mmsl/rs_repea.c create mode 100644 mmslib/mmsl/rs_repec.c create mode 100644 mmslib/mmsl/rs_repee.c create mode 100644 mmslib/mmsl/rs_stat.c create mode 100644 mmslib/mmsl/rs_trige.c create mode 100644 mmslib/mmsl/rs_ustat.c create mode 100644 mmslib/mmsl/rs_write.c create mode 100644 mmslib/mmsle/mms_ced1.c create mode 100644 mmslib/mmsle/mms_ced2.c create mode 100644 mmslib/mmsle/rq_altec.c create mode 100644 mmslib/mmsle/rq_altee.c create mode 100644 mmslib/mmsle/rq_crepi.c create mode 100644 mmslib/mmsle/rq_defea.c create mode 100644 mmslib/mmsle/rq_defec.c create mode 100644 mmslib/mmsle/rq_defsc.c create mode 100644 mmslib/mmsle/rq_defse.c create mode 100644 mmslib/mmsle/rq_defty.c create mode 100644 mmslib/mmsle/rq_defva.c create mode 100644 mmslib/mmsle/rq_defvl.c create mode 100644 mmslib/mmsle/rq_deldo.c create mode 100644 mmslib/mmsle/rq_delea.c create mode 100644 mmslib/mmsle/rq_delec.c create mode 100644 mmslib/mmsle/rq_delee.c create mode 100644 mmslib/mmsle/rq_delpi.c create mode 100644 mmslib/mmsle/rq_delse.c create mode 100644 mmslib/mmsle/rq_delty.c create mode 100644 mmslib/mmsle/rq_delva.c create mode 100644 mmslib/mmsle/rq_delvl.c create mode 100644 mmslib/mmsle/rq_downl.c create mode 100644 mmslib/mmsle/rq_fclos.c create mode 100644 mmslib/mmsle/rq_fdele.c create mode 100644 mmslib/mmsle/rq_fdir.c create mode 100644 mmslib/mmsle/rq_fopen.c create mode 100644 mmslib/mmsle/rq_fread.c create mode 100644 mmslib/mmsle/rq_frena.c create mode 100644 mmslib/mmsle/rq_getae.c create mode 100644 mmslib/mmsle/rq_getas.c create mode 100644 mmslib/mmsle/rq_getsc.c create mode 100644 mmslib/mmsle/rq_initd.c create mode 100644 mmslib/mmsle/rq_initu.c create mode 100644 mmslib/mmsle/rq_input.c create mode 100644 mmslib/mmsle/rq_jcrea.c create mode 100644 mmslib/mmsle/rq_jdele.c create mode 100644 mmslib/mmsle/rq_jinit.c create mode 100644 mmslib/mmsle/rq_jread.c create mode 100644 mmslib/mmsle/rq_jstat.c create mode 100644 mmslib/mmsle/rq_jwrit.c create mode 100644 mmslib/mmsle/rq_kill.c create mode 100644 mmslib/mmsle/rq_loadd.c create mode 100644 mmslib/mmsle/rq_obtfi.c create mode 100644 mmslib/mmsle/rq_outpu.c create mode 100644 mmslib/mmsle/rq_rddwn.c create mode 100644 mmslib/mmsle/rq_rdupl.c create mode 100644 mmslib/mmsle/rq_relct.c create mode 100644 mmslib/mmsle/rq_renam.c create mode 100644 mmslib/mmsle/rq_reset.c create mode 100644 mmslib/mmsle/rq_resum.c create mode 100644 mmslib/mmsle/rq_rsent.c create mode 100644 mmslib/mmsle/rq_rspoo.c create mode 100644 mmslib/mmsle/rq_rssta.c create mode 100644 mmslib/mmsle/rq_start.c create mode 100644 mmslib/mmsle/rq_stop.c create mode 100644 mmslib/mmsle/rq_store.c create mode 100644 mmslib/mmsle/rq_takec.c create mode 100644 mmslib/mmsle/rq_termd.c create mode 100644 mmslib/mmsle/rq_termu.c create mode 100644 mmslib/mmsle/rq_uploa.c create mode 100644 mmslib/mmsle/rs_altec.c create mode 100644 mmslib/mmsle/rs_altee.c create mode 100644 mmslib/mmsle/rs_crepi.c create mode 100644 mmslib/mmsle/rs_defea.c create mode 100644 mmslib/mmsle/rs_defec.c create mode 100644 mmslib/mmsle/rs_defsc.c create mode 100644 mmslib/mmsle/rs_defse.c create mode 100644 mmslib/mmsle/rs_defty.c create mode 100644 mmslib/mmsle/rs_defva.c create mode 100644 mmslib/mmsle/rs_defvl.c create mode 100644 mmslib/mmsle/rs_deldo.c create mode 100644 mmslib/mmsle/rs_delea.c create mode 100644 mmslib/mmsle/rs_delec.c create mode 100644 mmslib/mmsle/rs_delee.c create mode 100644 mmslib/mmsle/rs_delpi.c create mode 100644 mmslib/mmsle/rs_delse.c create mode 100644 mmslib/mmsle/rs_delty.c create mode 100644 mmslib/mmsle/rs_delva.c create mode 100644 mmslib/mmsle/rs_delvl.c create mode 100644 mmslib/mmsle/rs_downl.c create mode 100644 mmslib/mmsle/rs_fclos.c create mode 100644 mmslib/mmsle/rs_fdele.c create mode 100644 mmslib/mmsle/rs_fdir.c create mode 100644 mmslib/mmsle/rs_fopen.c create mode 100644 mmslib/mmsle/rs_fread.c create mode 100644 mmslib/mmsle/rs_frena.c create mode 100644 mmslib/mmsle/rs_getae.c create mode 100644 mmslib/mmsle/rs_getas.c create mode 100644 mmslib/mmsle/rs_getsc.c create mode 100644 mmslib/mmsle/rs_initd.c create mode 100644 mmslib/mmsle/rs_initu.c create mode 100644 mmslib/mmsle/rs_input.c create mode 100644 mmslib/mmsle/rs_jcrea.c create mode 100644 mmslib/mmsle/rs_jdele.c create mode 100644 mmslib/mmsle/rs_jinit.c create mode 100644 mmslib/mmsle/rs_jread.c create mode 100644 mmslib/mmsle/rs_jstat.c create mode 100644 mmslib/mmsle/rs_jwrit.c create mode 100644 mmslib/mmsle/rs_kill.c create mode 100644 mmslib/mmsle/rs_loadd.c create mode 100644 mmslib/mmsle/rs_obtfi.c create mode 100644 mmslib/mmsle/rs_outpu.c create mode 100644 mmslib/mmsle/rs_rddwn.c create mode 100644 mmslib/mmsle/rs_rdupl.c create mode 100644 mmslib/mmsle/rs_relct.c create mode 100644 mmslib/mmsle/rs_renam.c create mode 100644 mmslib/mmsle/rs_reset.c create mode 100644 mmslib/mmsle/rs_resum.c create mode 100644 mmslib/mmsle/rs_rsent.c create mode 100644 mmslib/mmsle/rs_rspoo.c create mode 100644 mmslib/mmsle/rs_rssta.c create mode 100644 mmslib/mmsle/rs_start.c create mode 100644 mmslib/mmsle/rs_stop.c create mode 100644 mmslib/mmsle/rs_store.c create mode 100644 mmslib/mmsle/rs_takec.c create mode 100644 mmslib/mmsle/rs_termd.c create mode 100644 mmslib/mmsle/rs_termu.c create mode 100644 mmslib/mmsle/rs_uploa.c create mode 100644 mmslib/mmslib.cpp create mode 100644 mmslib/mmslib.h create mode 100644 mmslib/mmslib.pro create mode 100644 mmslib/mmslib.pro.user create mode 100644 mmslib/mmslib.pro.user.18 create mode 100644 mmslib/mmslib.pro.user.2.7pre1 create mode 100644 mmslib/mmslib.pro.user.3.2-pre1 create mode 100644 mmslib/mmslib.pro.user.5822199 create mode 100644 mmslib/mmslib.pro.user.5822199.2.7pre1 create mode 100644 mmslib/mmslib.pro.user.d8c8bb2 create mode 100644 mmslib/mvlu/c_concl.c create mode 100644 mmslib/mvlu/c_defvl.c create mode 100644 mmslib/mvlu/c_delvl.c create mode 100644 mmslib/mvlu/c_fclose.c create mode 100644 mmslib/mvlu/c_fdel.c create mode 100644 mmslib/mvlu/c_fdir.c create mode 100644 mmslib/mvlu/c_fget.c create mode 100644 mmslib/mvlu/c_fopen.c create mode 100644 mmslib/mvlu/c_fread.c create mode 100644 mmslib/mvlu/c_fren.c create mode 100644 mmslib/mvlu/c_getdom.c create mode 100644 mmslib/mvlu/c_getnam.c create mode 100644 mmslib/mvlu/c_getvar.c create mode 100644 mmslib/mvlu/c_getvla.c create mode 100644 mmslib/mvlu/c_ident.c create mode 100644 mmslib/mvlu/c_info.c create mode 100644 mmslib/mvlu/c_jinit.c create mode 100644 mmslib/mvlu/c_jread.c create mode 100644 mmslib/mvlu/c_jstat.c create mode 100644 mmslib/mvlu/c_obtfi.c create mode 100644 mmslib/mvlu/c_read.c create mode 100644 mmslib/mvlu/c_status.c create mode 100644 mmslib/mvlu/c_write.c create mode 100644 mmslib/mvlu/mvl61850.c create mode 100644 mmslib/mvlu/mvl61850_ctl.c create mode 100644 mmslib/mvlu/mvl61850_rpt.c create mode 100644 mmslib/mvlu/mvl_buf.c create mode 100644 mmslib/mvlu/mvl_dtyp.c create mode 100644 mmslib/mvlu/mvl_ijou.c create mode 100644 mmslib/mvlu/mvl_obj.c create mode 100644 mmslib/mvlu/mvl_objb.c create mode 100644 mmslib/mvlu/mvl_send.c create mode 100644 mmslib/mvlu/mvl_serv.c create mode 100644 mmslib/mvlu/mvl_typ2.c create mode 100644 mmslib/mvlu/mvl_type.c create mode 100644 mmslib/mvlu/mvl_uca.c create mode 100644 mmslib/mvlu/mvl_var.c create mode 100644 mmslib/mvlu/mvlu_rpt.c create mode 100644 mmslib/mvlu/mvlu_rt.c create mode 100644 mmslib/mvlu/mvlu_sbo.c create mode 100644 mmslib/mvlu/mvluleaf.c create mode 100644 mmslib/mvlu/s_cancel.c create mode 100644 mmslib/mvlu/s_concl.c create mode 100644 mmslib/mvlu/s_defvl.c create mode 100644 mmslib/mvlu/s_delvl.c create mode 100644 mmslib/mvlu/s_fclose.c create mode 100644 mmslib/mvlu/s_fdel.c create mode 100644 mmslib/mvlu/s_fdir.c create mode 100644 mmslib/mvlu/s_fopen.c create mode 100644 mmslib/mvlu/s_fread.c create mode 100644 mmslib/mvlu/s_fren.c create mode 100644 mmslib/mvlu/s_getcl.c create mode 100644 mmslib/mvlu/s_getdom.c create mode 100644 mmslib/mvlu/s_getnam.c create mode 100644 mmslib/mvlu/s_getvaa.c create mode 100644 mmslib/mvlu/s_getvla.c create mode 100644 mmslib/mvlu/s_ident.c create mode 100644 mmslib/mvlu/s_info.c create mode 100644 mmslib/mvlu/s_jinit.c create mode 100644 mmslib/mvlu/s_jread.c create mode 100644 mmslib/mvlu/s_jstat.c create mode 100644 mmslib/mvlu/s_obtfi.c create mode 100644 mmslib/mvlu/s_read.c create mode 100644 mmslib/mvlu/s_status.c create mode 100644 mmslib/mvlu/s_write.c create mode 100644 mmslib/mvlu/sclproc.c create mode 100644 mmslib/object_script.libmmslib.Debug create mode 100644 mmslib/object_script.libmmslib.Release create mode 100644 mmslib/ositcps/acse2dec.c create mode 100644 mmslib/ositcps/acse2dib.c create mode 100644 mmslib/ositcps/acse2enc.c create mode 100644 mmslib/ositcps/acse2var.c create mode 100644 mmslib/ositcps/checksum.c create mode 100644 mmslib/ositcps/copp_dec.c create mode 100644 mmslib/ositcps/copp_enc.c create mode 100644 mmslib/ositcps/coppdaru.c create mode 100644 mmslib/ositcps/coppdcp.c create mode 100644 mmslib/ositcps/coppdcpr.c create mode 100644 mmslib/ositcps/cosp_dec.c create mode 100644 mmslib/ositcps/cosp_enc.c create mode 100644 mmslib/ositcps/cospmain.c create mode 100644 mmslib/ositcps/lean_cfg.c create mode 100644 mmslib/ositcps/lean_var.c create mode 100644 mmslib/ositcps/osicfgx.c create mode 100644 mmslib/ositcps/tp0_dec.c create mode 100644 mmslib/ositcps/tp0_socks.c create mode 100644 mmslib/ositcps/tp0calld.c create mode 100644 mmslib/ositcps/tp0callg.c create mode 100644 mmslib/ositcps/tp0main.c create mode 100644 mmslib/ositcps/tp4_enc.c create mode 100644 mmslib/ositcps/tp4port.c create mode 100644 mmslib/ositcps/tpx_dec.c create mode 100644 mmslib/slog/qmem.c create mode 100644 mmslib/slog/slog.c create mode 100644 mmslib/slog/slogfil.c create mode 100644 mmslib/slog/sloghex.c create mode 100644 mmslib/slog/slogipcs.c create mode 100644 mmslib/slog/slogmem.c create mode 100644 mmslib/ssec0/ssecusr0.c create mode 100644 mmslib/util/cfg_util.c create mode 100644 mmslib/util/genlists.c create mode 100644 mmslib/util/gensock2.c create mode 100644 mmslib/util/glbsem.c create mode 100644 mmslib/util/glbsem_unix.c create mode 100644 mmslib/util/glbsem_w32.c create mode 100644 mmslib/util/scl_log.c create mode 100644 mmslib/util/sclparse.c create mode 100644 mmslib/util/sclstore.c create mode 100644 mmslib/util/stdtime.c create mode 100644 mmslib/util/stdtime_mms_btime.c create mode 100644 mmslib/util/stdtime_mms_utctime.c create mode 100644 mmslib/util/stdtime_quadlib.c create mode 100644 mmslib/util/stdtime_w32.c create mode 100644 mmslib/util/stime.c create mode 100644 mmslib/util/str_util.c create mode 100644 mmslib/util/sx_axs4d.c create mode 100644 mmslib/util/sx_data.c create mode 100644 mmslib/util/sx_dec.c create mode 100644 mmslib/util/sx_enc.c create mode 100644 mmslib/util/time_str.c diff --git a/include/inc/ExceptionReport.h b/include/inc/ExceptionReport.h new file mode 100644 index 0000000..996f8d4 --- /dev/null +++ b/include/inc/ExceptionReport.h @@ -0,0 +1,135 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003-2204, All Rights Reserved */ +/* */ +/* MODULE NAME : ExceptionReport.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : Unhandled Exception Handler */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/13/06 DSF 03 Migrate to VS.NET 2005 */ +/* 06/30/05 DSF 02 Generate a mini dump */ +/* 12/20/04 DSF 01 Minor usability changes */ +/* Stack State recorder */ +/************************************************************************/ + +#pragma once + +#include "glbtypes.h" +#include "sysincs.h" +#include "slog.h" +#include "mem_chk.h" +#include +#include +#include +#include +#include +#include +using namespace std; + +enum BasicType // Stolen from CVCONST.H in the DIA 2.0 SDK +{ + btNoType = 0, + btVoid = 1, + btChar = 2, + btWChar = 3, + btInt = 6, + btUInt = 7, + btFloat = 8, + btBCD = 9, + btBool = 10, + btLong = 13, + btULong = 14, + btCurrency = 25, + btDate = 26, + btVariant = 27, + btComplex = 28, + btBit = 29, + btBSTR = 30, + btHresult = 31 +}; + +class WheatyExceptionReport +{ + public: + + WheatyExceptionReport( ); + WheatyExceptionReport( bool terminate ); + ~WheatyExceptionReport( ); + + void SetLogFileName( PTSTR pszLogFileName ); + + + // entry point where control comes on an unhandled exception + static LONG WINAPI WheatyUnhandledExceptionFilter( + PEXCEPTION_POINTERS pExceptionInfo ); + + static BOOL GetLogicalAddress( PVOID addr, PTSTR szModule, DWORD len, + DWORD& section, DWORD& offset ); + + private: + + // where report info is extracted and generated + static void GenerateExceptionReport( PEXCEPTION_POINTERS pExceptionInfo ); + + // where mini dump is generated + static void GenerateDumpFile( PEXCEPTION_POINTERS pExceptionInfo ); + + // Helper functions + static LPTSTR GetExceptionString( DWORD dwCode ); + static void WriteStackDetails( PCONTEXT pContext, bool bWriteVariables ); + + static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO,ULONG, PVOID); + + static bool FormatSymbolValue( PSYMBOL_INFO, STACKFRAME *, char * pszBuffer, unsigned cbBuffer ); + + static char * DumpTypeIndex( char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool & ); + + static char * FormatOutputValue( char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress ); + + static BasicType GetBasicType( DWORD typeIndex, DWORD64 modBase ); + + static int __cdecl _tprintf(const TCHAR * format, ...); + + // Variables used by the class + static TCHAR m_szLogFileName[MAX_PATH]; + static TCHAR m_szDumpFileName[MAX_PATH]; + static LOG_CTRL m_logCtrl; + static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter; + static HANDLE m_hReportFile; + static HANDLE m_hProcess; + static bool m_bTerminate; +}; + + +extern WheatyExceptionReport g_WheatyExceptionReport; // global instance of class + +struct SourceInfo + { + string filename; + long linenum; + }; + +struct StackInfo + { + DWORD threadID; + SYSTEMTIME timestamp; + vector stack; + + void Log (); + }; + +void GetStackInfo (StackInfo& stackInfo); + +extern "C" void ExpInit (); +extern "C" void ExpRaiseDebugException (); +extern "C" void ExpSetLogCtrl (LOG_CTRL *pLogCtrl); + + diff --git a/include/inc/Goose.h b/include/inc/Goose.h new file mode 100644 index 0000000..88af00b --- /dev/null +++ b/include/inc/Goose.h @@ -0,0 +1,223 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999-2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : goose.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/23/08 JRB 10 Fix len of gcRef, dataSetRef, appID. */ +/* 09/11/07 JRB 09 Add gse_iec_enc_part1, gse_iec_enc_part2. */ +/* Chg gcRef, dataSetRef, appID data type from */ +/* char ptr to char array (reduces allocation). */ +/* Fix type of numDataEntries, confRev. */ +/* 01/08/03 JRB 08 Del obsolete dataRef, elementId from structs */ +/* & from gse_iec_data_init args. */ +/* 12/03/02 ASK 07 Chg Goose structs for new ASN.1 encoding. Chg*/ +/* gse_iec_encode and gse_iec_hdr_decode protos */ +/* for Ethertype. include "ethertyp.h" */ +/* 09/30/02 NAV 06 Add ifdef __cplusplus */ +/* 02/26/02 JRB 05 Chg IEC GOOSE asn1Data args to UCHAR. */ +/* Chg some IEC GOOSE decode params to INT32. */ +/* 01/02/02 JRB 04 Add IEC GOOSE definitions. */ +/* 07/25/00 RKR 03 changed VisibleString SendingIED to ST_CHAR */ +/* 09/10/99 JRB 02 Chg SqNum, StNum, HoldTim, & BackTim */ +/* to UINT32 to match GOMSFE 0.9. */ +/* 06/25/99 MDE 01 Created */ +/************************************************************************/ +#ifndef GOOSE_HDR_INCLUDED +#define GOOSE_HDR_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "asn1r.h" /* need MMS_UTC_TIME */ +#include "clnp_usr.h" +#include "clnp_sne.h" +#include "acse2usr.h" +#include "ethertyp.h" +#include "mvl_defs.h" /* need MVL61850_MAX_* defines. */ +/* NOTE: need runtime_type from "mms_vvar.h" but requires bunch of */ +/* other includes, so just use forward declaration. */ +struct runtime_type; /* forward declaration */ + +/************************************************************************/ + + +#define GOOSE_NAME_MISMATCH 0x112 +#define GOOSE_DONE_TOO_SOON 0x113 + +/************************************************************************/ +#define GOOSE_MAX_NUM_DNA_BITS 128 +#define GOOSE_MAX_NUM_USR_BITS 512 + +#define GOOSE_DEF_NUM_DNA_BITS 64 +#define GOOSE_DEF_NUM_USR_BITS 128 + +typedef struct + { +/* GOOSE Stack addressing information */ + AUDT_APDU audtApdu; + +/* GOOSE MMS values */ + ST_CHAR SendingIED[66]; + MMS_BTOD t; + ST_UINT32 SqNum; + ST_UINT32 StNum; + ST_UINT32 HoldTim; + ST_UINT32 BackTim; + ST_UINT16 PhsID; + + ST_INT num_dna_bits; + ST_UCHAR DNA[GOOSE_MAX_NUM_DNA_BITS/8]; + + ST_INT num_usr_bits; + ST_UCHAR UserSt[GOOSE_MAX_NUM_USR_BITS/8]; + } GOOSE_INFO; + +/************************************************************************/ +/* The user makes use of these functions to send and receive GOOSE */ +/* messages. */ + +ST_RET mmsl_send_goose (GOOSE_INFO *gi); +ST_VOID u_mmsl_goose_received (GOOSE_INFO *goose_info); + +/************************************************************************/ +/* Internal */ + +#define GOOSE_MAX_PDU_SIZE 200 + +/* Define macro so new function just calls old function. */ +#define gse_uca_write(gi) mmsl_send_goose (gi) + +ST_RET gse_uca_decode (SN_UNITDATA *sn_udt, /* input subnet packet */ + GOOSE_INFO *goose_info); /* output GOOSE data */ + +/************************************************************************/ +/* BEGIN IEC GOOSE DEFINITIONS */ +/************************************************************************/ +typedef struct + { + struct runtime_type *runtimeTypeHead; /* Array of Runtime Types */ + ST_INT numRuntimeTypes; /* # of Runtime Types in array */ + ST_CHAR *dataBuf; /* ptr to local data */ + ST_VOID *userInfo; /* To store anything user wants.*/ + /* GSE code does not use it. */ + } GSE_IEC_DATA_ENTRY; + +typedef struct + { + ST_UINT8 *asn1Ptr; + ST_INT asn1Len; + } GSE_IEC_DATA_ENTRY_RX; + +typedef struct + { + ST_CHAR gcRef [MVL61850_MAX_OBJREF_LEN+1]; /* GoCBRef in IEC 61850 */ + ST_UINT32 timeToLive; + ST_CHAR dataSetRef [MVL61850_MAX_OBJREF_LEN+1];/* DatSet in IEC 61850 */ + ST_BOOLEAN appID_pres; + ST_CHAR appID [MVL61850_MAX_RPTID_LEN+1]; /* GoID in IEC 61850 */ + /* (was AppID in Ed 1) */ + MMS_UTC_TIME utcTime; + ST_UINT32 stNum; + ST_UINT32 sqNum; + ST_BOOLEAN test; + ST_UINT32 confRev; + ST_BOOLEAN needsCommissioning; + ST_INT32 numDataEntries; + GSE_IEC_DATA_ENTRY *dataEntries; /* array of data entry structs */ + }GSE_IEC_CTRL; + +typedef struct + { + ST_CHAR *gcRef; + ST_UINT32 timeToLive; + ST_CHAR *dataSetRef; + ST_BOOLEAN appID_pres; + ST_CHAR *appID; + MMS_UTC_TIME utcTime; + ST_UINT32 stNum; + ST_UINT32 sqNum; + ST_BOOLEAN test; + ST_UINT32 confRev; + ST_BOOLEAN needsCommissioning; + ST_INT32 numDataEntries; + ST_INT tmpIndex; /* index to current entry in "dataEntries" array.*/ + /* Used during decode when filling in "dataEntries".*/ + GSE_IEC_DATA_ENTRY_RX *dataEntries; /* array of data entry structs */ + }GSE_IEC_HDR; + +/* Subnet functions (clnp_snet_*) must be used to set multicast filters.*/ +/* The following "gse_*" macros may be used to access these functions. */ +#define gse_set_multicast_filter clnp_snet_set_multicast_filter +#define gse_discovery_start clnp_snet_rx_all_multicast_start +#define gse_discovery_stop clnp_snet_rx_all_multicast_stop + +GSE_IEC_HDR *gse_iec_hdr_decode (ST_UCHAR *apdu, ST_INT apdu_len); +/* After calling "gse_iec_hdr_decode", user can examine "dataEntries" */ +/* array in GSE_IEC_HDR, and call "ms_asn1_to_local" to decode any or */ +/* all dataEntries. */ + +/* User must call this function when they are done with the decoded */ +/* GOOSE info to free up the resources. */ +ST_RET gse_iec_decode_done (GSE_IEC_HDR *hdr); + + +GSE_IEC_CTRL *gse_iec_control_create (ST_CHAR *gcRef, ST_CHAR *dataSetRefRef, ST_CHAR *appId, + ST_INT numDataEntry); +ST_RET gse_iec_control_destroy (GSE_IEC_CTRL *ctrl); + +ST_RET gse_iec_data_init (GSE_IEC_CTRL *ctrl, + ST_INT index, + struct runtime_type *runtimeTypeHead, + ST_INT numRuntimeTypes + ); + +ST_RET gse_iec_data_update (GSE_IEC_CTRL *ctrl, + ST_INT index, + ST_VOID *dataPtr); + +ST_UCHAR *gse_iec_encode (GSE_IEC_CTRL *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info);/* ptr to Ethertype info*/ + +ST_RET gse_iec_send (GSE_IEC_CTRL *ctrl, + ST_UCHAR *dstMac, /* Destination MAC addr */ + ST_UCHAR *asn1Data, /* ptr to ASN.1 encoded data*/ + ST_INT asn1DataLen); /* len of ASN.1 encoded data*/ + +/* Functions to use for 2-part encode. Reduces re-encoding of data. */ +ST_UCHAR *gse_iec_enc_part1 (GSE_IEC_CTRL *ctrl, + ST_UCHAR *buf_ptr, /* buffer in which to encode */ + ST_INT buf_len, /* buffer len */ + ST_INT *asn1_len_out); /* len of ASN.1 encoded data */ +ST_UCHAR *gse_iec_enc_part2 (GSE_IEC_CTRL *ctrl, + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UCHAR *buf_ptr, /* buffer in which to encode */ + ST_INT buf_len, /* buffer len */ + ST_INT enc_part1_len, /* len of data encoded by */ + /* gse_iec_enc_part1 */ + /* CRITICAL: must be < buf_len. */ + ST_INT *asn1_len_out); /* len of ASN.1 encoded data */ + +/************************************************************************/ +/* END IEC GOOSE DEFINITIONS */ +/************************************************************************/ +#ifdef __cplusplus +} +#endif +#endif /* included */ diff --git a/include/inc/STR_UTIL.H b/include/inc/STR_UTIL.H new file mode 100644 index 0000000..a9609b0 --- /dev/null +++ b/include/inc/STR_UTIL.H @@ -0,0 +1,158 @@ +#ifndef STR_UTIL_INCLUDED +#define STR_UTIL_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2000 - 2004 All Rights Reserved */ +/* */ +/* MODULE NAME : str_util.h */ +/* PRODUCT(S) : General Use */ +/* */ +/* MODULE DESCRIPTION : */ +/* General purpose string manipulation functions. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/29/07 JRB 23 Add strncat_maxstrlen. Del strncat_safe (len */ +/* was wrong), use strncat or strncat_maxstrlen.*/ +/* 10/11/07 JRB 22 Add asciiToSint32, asciiToUint32 */ +/* 07/28/05 DWL 21 Use const ST_CHAR* in asciiTo* functions. */ +/* 03/14/05 JRB 20 Add get_next_string. */ +/* 12/03/04 JRB 19 Use strcasecmp, strncasecmp if supported. */ +/* 07/09/04 JRB 18 Add strncat_safe, strncpy_safe. */ +/* 03/08/04 EJV 17 Added getKeywordFromFile function. */ +/* 12/12/03 JRB 16 Add LYNX support. */ +/* 12/10/03 MDE 15 Added itoa/ltoa/utoa/ultoa replacements */ +/* 04/10/03 DSF 14 Added strnstr */ +/* 02/20/03 JRB 13 Del PSOS code. */ +/* 12/20/02 CRM 12 Added "defined(linux)" for strcmpi, etc. */ +/* 02/28/02 EJV 11 Added asciiToFloat, asciiToDouble. */ +/* 02/25/02 EJV 10 Replaced ascii_to_ macros with asciiToxxx fun*/ +/* Added asciiToUlong, asciiToUint16, */ +/* asciiToUint8, asciiToSint, asciiToUint */ +/* hex_to_ascii_str: added param hex_no_spaces. */ +/* 12/09/01 GLB 05 Added asciiToSlong, asciiToSint16, */ +/* asciiToSint8, asciiToUchar */ +/* 09/10/01 GLB 08 Added ascii_to_uint & ascii_to_slongint */ +/* 08/06/01 GLB 07 Added ascii_to_sint */ +/* 06/06/01 GLB 06 Added ascii_to_double & ascii_to_float */ +/* 05/21/01 MDE 05 Added bitstring_to_ascii_str */ +/* 01/19/01 EJV 04 UNIX: added strcmpi, stricmp, strnicmp protos*/ +/* 01/05/01 EJV 03 Corrected ascii_to_ushortint, AIX returned 0.*/ +/* ascii_to_ulongint: changed "%ul" to "%lu". */ +/* 11/02/00 MDE 02 Added _hex_no_spaces */ +/* 02/03/00 JRB 01 Created */ +/************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +ST_VOID hex_to_ascii_str ( + ST_CHAR *astr, /* ascii string */ + ST_UCHAR *hstr, /* hex string */ + ST_UINT hlen, /* len of hex string */ + ST_BOOLEAN hex_no_spaces); + +ST_RET ascii_to_hex_str ( + ST_UCHAR *hstr, /* hex string */ + ST_UINT *hlen_out, /* ptr to hex len to be set */ + ST_UINT hlen_max, /* maximum hex len to allow. */ + ST_CHAR *astr); /* ascii string */ + +ST_VOID bitstring_to_ascii_str (ST_CHAR *astr, ST_UCHAR *bstr, + ST_UINT numBits); + + +ST_RET asciiToSlong (const ST_CHAR *astr, + ST_LONG *sLong); +ST_RET asciiToUlong (const ST_CHAR *astr, + ST_ULONG *uLong); + +ST_RET asciiToSint (const ST_CHAR *astr, + ST_INT *sInt); +ST_RET asciiToUint (const ST_CHAR *astr, + ST_UINT *uInt); + +ST_RET asciiToSint32 (const ST_CHAR *astr, /* ascii string */ + ST_INT32 *value); /* ptr to converted value*/ +ST_RET asciiToUint32 (const ST_CHAR *astr, /* ascii string */ + ST_UINT32 *value); /* ptr to converted value*/ + +ST_RET asciiToSint16 (const ST_CHAR *astr, + ST_INT16 *sInt16); +ST_RET asciiToUint16 (const ST_CHAR *astr, + ST_UINT16 *uInt16); + +ST_RET asciiToSint8 (const ST_CHAR *astr, + ST_INT8 *sInt8); +ST_RET asciiToUint8 (const ST_CHAR *astr, + ST_UINT8 *uInt8); + +ST_RET asciiToUchar (const ST_CHAR *astr, + ST_UCHAR *uChar); + +ST_RET asciiToFloat (const ST_CHAR *astr, + ST_FLOAT *floatNum); +ST_RET asciiToDouble (const ST_CHAR *astr, + ST_DOUBLE *doubleNum); + + +char *strnstr (char *str1, char *str2, int len); + +/* SISCO code calls strcmpi, stricmp, strnicmp (Windows functions). */ +/* On systems that support strcasecmp, strncasecmp, remap to use them. */ +#if defined(_AIX) || defined(sun) || defined(__alpha) || defined(__hpux) || \ + defined(linux) +#ifndef strcmpi +#define strcmpi strcasecmp +#endif +#ifndef stricmp +#define stricmp strcasecmp +#endif +#ifndef strnicmp +#define strnicmp strncasecmp +#endif +#endif /* UNIX-like systems that support strcasecmp, strncasecmp. */ + +/* On systems that DON'T support strcasecmp, strncasecmp, use SISCO functions. */ +#if defined(VXWORKS) || defined(__LYNX) +ST_INT strcmpi (ST_CHAR *,ST_CHAR *); +ST_INT stricmp (ST_CHAR *,ST_CHAR *); +ST_INT strnicmp (ST_CHAR *,ST_CHAR *,ST_INT n); +#endif + +/* "strncat_maxstrlen" is like "strncat" but the third arg is the */ +/* maximum length of the destination string. */ +ST_RET strncat_maxstrlen (char *dest, char *src, size_t maxstrlen); + +/* "strncpy_safe" makes sure that the "dest" string is NULL-terminated. */ +/* The standard "strncpy" does NOT always NULL-terminate "dest". */ +ST_VOID strncpy_safe (char *dest, char *src, int max_len); + +ST_CHAR *sInt8ToAscii (ST_INT8 v, ST_CHAR *p); +ST_CHAR *uInt8ToAscii (ST_UINT8 v, ST_CHAR *p); +ST_CHAR *sInt16ToAscii (ST_INT16 v, ST_CHAR *p); +ST_CHAR *uInt16ToAscii (ST_UINT16 v, ST_CHAR *p); +ST_CHAR *sInt32ToAscii (ST_INT32 v, ST_CHAR *p); +ST_CHAR *uInt32ToAscii (ST_UINT32 v, ST_CHAR *p); +ST_CHAR *sIntToAscii (ST_INT v, ST_CHAR *p); +ST_CHAR *uIntToAscii (ST_UINT v, ST_CHAR *p); +ST_CHAR *sLongToAscii (ST_LONG v, ST_CHAR *p); +ST_CHAR *uLongToAscii (ST_ULONG v, ST_CHAR *p); + +/* misc functions */ +ST_BOOLEAN getKeywordFromFile (ST_CHAR *fileStr, ST_CHAR *keywordStr, + ST_CHAR *valBuf, ST_UINT valBufLen); + +ST_CHAR *get_next_string (ST_CHAR **ptrptr, ST_CHAR *delimiters); + +#ifdef __cplusplus +} +#endif + +#endif /* !STR_UTIL_INCLUDED */ + diff --git a/include/inc/Smem.h b/include/inc/Smem.h new file mode 100644 index 0000000..85d1971 --- /dev/null +++ b/include/inc/Smem.h @@ -0,0 +1,467 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999, All Rights Reserved */ +/* */ +/* MODULE NAME : smem.h */ +/* PRODUCT(S) : Utilities */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/14/03 JRB 10 Eliminate compiler warnings. */ +/* 10/09/01 JRB 09 Add non-debug log macros. */ +/* 10/02/01 JRB 08 Del DBL_LNK from SMEM_CONTEXT (never used). */ +/* Add forward declarations to reduce warnings. */ +/* 09/21/01 JRB 07 Add args to smem_add_pool. */ +/* Chg args to u_smem_*. */ +/* Del unused prototypes. */ +/* Add u_smem_get_buf_detail. */ +/* Pass old & new size to smem_realloc. */ +/* Add m_add_pool proto. */ +/* Del #ifdef ACSE && LEANT. */ +/* Del smemInitialized,smemDefCtxt (not needed).*/ +/* Add more SLOG macros. */ +/* Chg poolName, contextName to (ST_CHAR *). */ +/* 05/21/01 MDE 06 Mode SMEM context management work */ +/* 03/19/01 JEB 05 Moved all SMEM context defs to this file. */ +/* 03/10/01 GLB 04 Added u_smem_get_pool_params */ +/* 03/10/01 GLB 03 Added smemcfgx for parsing memory cfg. file */ +/* 02/26/01 MDE 02 Added clone control to SMEM_POOL_CTRL */ +/* 12/09/99 MDE 01 New */ +/************************************************************************/ +/************************************************************************/ + +#ifndef SMEM_INCLUDED +#define SMEM_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "gen_list.h" + +/************************************************************************/ + +#define SMEM_MAX_RANGE_TRACK 10 + +typedef struct _smem_range_track + { + ST_UINT lowLimit; + ST_UINT highLimit; + ST_LONG currNum; + ST_LONG maxNum; + } SMEM_RANGE_TRACK; + +typedef struct _smem_rt_ctrl + { + ST_INT numRanges; + SMEM_RANGE_TRACK rt[SMEM_MAX_RANGE_TRACK]; + } SMEM_RT_CTRL; + +/************************************************************************/ +struct _smem_pool_ctrl; /* forward declaration */ +struct _smem_context; /* forward declaration */ + +typedef struct _smem_pool_ctrl + { + struct _smem_pool_ctrl *next; + ST_CHAR *poolName; + ST_UINT bufSize; + ST_UINT8 numBuf; + ST_UINT8 nextAvailBuf; + ST_UINT8 *availIndexStack; /* Index table, size [numBuf] */ + ST_CHAR *firstBuf; + ST_CHAR *lastBuf; + struct _smem_context *smemContext; + + ST_BOOLEAN autoClone; + ST_INT maxClones; + ST_INT cloneCount; + +#ifdef DEBUG_SISCO + ST_UINT8 maxNumUsed; + ST_UINT16 *usedSize; /* usedSize [numBuf] */ +#endif + + ST_VOID *usr; /* SMEM user can use this ... */ + } SMEM_POOL_CTRL; + + +typedef struct _smem_context + { + ST_CHAR *contextName; + ST_INT usrId; /* User */ + ST_VOID *usr; /* User */ + +/* Must be arranged from smallest to largest buffer size */ + SMEM_POOL_CTRL *smemPoolCtrlList; + +/* Optional range tracking */ + SMEM_RT_CTRL *smemRangeTrack; + } SMEM_CONTEXT; + +/************************************************************************/ +/************************************************************************/ + +ST_RET smemcfgx (ST_CHAR *xml_filename); + +ST_VOID u_smem_get_pool_params ( SMEM_CONTEXT *contextName, + ST_UINT8 *numBuf, ST_UINT *bufSize, + ST_BOOLEAN *autoClone, + ST_INT *maxClones, + ST_CHAR **poolName); + +SMEM_POOL_CTRL *u_smem_need_buffers (SMEM_CONTEXT *smemContext, + ST_UINT8 numBuf, ST_UINT bufSize); +ST_CHAR *u_smem_get_buf_detail (ST_VOID *bufptr, ST_INT bufSize); + +SMEM_POOL_CTRL *smem_add_pool (SMEM_CONTEXT *smemContext, + ST_UINT8 numBuf, ST_UINT bufSize, + ST_BOOLEAN autoClone, + ST_INT maxClones, + ST_CHAR *poolName); + +ST_VOID *smem_malloc (SMEM_CONTEXT *smemContext, ST_UINT size); +ST_VOID *smem_calloc (SMEM_CONTEXT *smemContext, ST_UINT num, ST_UINT size); +ST_VOID *smem_realloc (SMEM_CONTEXT *smemContext, ST_VOID *oldptr, + ST_UINT oldsize, ST_UINT newsize); +ST_VOID smem_free (SMEM_CONTEXT *smemContext, ST_VOID *ptr); +ST_VOID smem_log_state (SMEM_CONTEXT *smemContext); + +ST_VOID smem_range_check (SMEM_CONTEXT *smemContext, + ST_UINT size, ST_BOOLEAN add); + + +/************************************************************************/ +/* mem_smem.c function prototypes */ +/************************************************************************/ +SMEM_POOL_CTRL *m_add_pool (SMEM_CONTEXT *smemContext, + ST_UINT8 numBuf, ST_UINT bufSize, + ST_BOOLEAN autoClone, + ST_INT maxClones, + ST_CHAR *poolName); + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +#define SMEM_LOG_ERR 0x0001 +#define SMEM_LOG_NERR 0x0002 +#define SMEM_LOG_FLOW 0x0004 +#define SMEM_LOG_DEBUG 0x0008 + +extern ST_UINT smem_debug_sel; + +/************************************************************************/ +/************************************************************************/ + +extern SD_CONST ST_CHAR *SD_CONST _smem_log_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smem_log_flow_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smem_log_nerr_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smem_log_debug_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smem_log_dump_logstr; + +#ifdef DEBUG_SISCO + +#define SMEMLOG_ERR0(a) {\ + _slog (sLogCtrl,_smem_log_err_logstr,\ + thisFileName,__LINE__,a);\ + } +#define SMEMLOG_ERR1(a,b) {\ + _slog (sLogCtrl,_smem_log_err_logstr,\ + thisFileName,__LINE__,a,b);\ + } + +#define SMEMLOG_ERR2(a,b,c) {\ + _slog (sLogCtrl,_smem_log_err_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } + +#define SMEMLOG_CERR0(a) {\ + _slogc (sLogCtrl,a);\ + } +#define SMEMLOG_CERR1(a,b) {\ + _slogc (sLogCtrl,a,b);\ + } + +#define SMEMLOG_CERR2(a,b,c) {\ + _slogc (sLogCtrl,a,b,c);\ + } + +#define SMEMLOG_NERR0(a) {\ + if (smem_debug_sel & SMEM_LOG_NERR)\ + _slog (sLogCtrl,_smem_log_nerr_logstr,\ + thisFileName,__LINE__,a);\ + } +#define SMEMLOG_NERR1(a,b) {\ + if (smem_debug_sel & SMEM_LOG_NERR)\ + _slog (sLogCtrl,_smem_log_nerr_logstr,\ + thisFileName,__LINE__,a,b);\ + } + +#define SMEMLOG_FLOW1(a,b) {\ + if (smem_debug_sel & SMEM_LOG_FLOW)\ + _slog (sLogCtrl,_smem_log_flow_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define SMEMLOG_CFLOW1(a,b) {\ + if (smem_debug_sel & SMEM_LOG_FLOW)\ + _slogc (sLogCtrl,a,b);\ + } +#define SMEMLOG_CFLOW2(a,b,c) {\ + if (smem_debug_sel & SMEM_LOG_FLOW)\ + _slogc (sLogCtrl,a,b,c);\ + } + +#define SMEMLOG_DUMP0(a) {\ + _slog (sLogCtrl,_smem_log_dump_logstr,\ + thisFileName,__LINE__,a);\ + } +#define SMEMLOG_DUMP1(a,b) {\ + _slog (sLogCtrl,_smem_log_dump_logstr,\ + thisFileName,__LINE__,a,b);\ + } + +#define SMEMLOG_CDUMP0(a) {\ + _slogc (sLogCtrl,a);\ + } + +#define SMEMLOG_CDUMP1(a,b) {\ + _slogc (sLogCtrl,a,b);\ + } + +#define SMEMLOG_CDUMP2(a,b,c) {\ + _slogc (sLogCtrl,a,b,c);\ + } + +#define SMEMLOG_CDUMP3(a,b,c,d) {\ + _slogc (sLogCtrl,a,b,c,d);\ + } + +#define SMEMLOG_CDUMP4(a,b,c,d,e) {\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define SMEMLOG_CDUMP5(a,b,c,d,e,f) {\ + _slogc (sLogCtrl,a,b,c,d,e,f);\ + } + +#define SMEMLOG_DEBUG0(a) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slog (sLogCtrl,_smem_log_debug_logstr,\ + thisFileName,__LINE__,a);\ + } + +#define SMEMLOG_DEBUG1(a,b) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slog (sLogCtrl,_smem_log_debug_logstr,\ + thisFileName,__LINE__,a,b);\ + } + +#define SMEMLOG_DEBUG2(a,b,c) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slog (sLogCtrl,_smem_log_debug_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define SMEMLOG_DEBUG3(a,b,c,d) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slog (sLogCtrl,_smem_log_debug_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define SMEMLOG_DEBUG4(a,b,c,d,e) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slog (sLogCtrl,_smem_log_debug_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define SMEMLOG_CDEBUG0(a) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slogc (sLogCtrl,a);\ + } + +#define SMEMLOG_CDEBUG1(a,b) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slogc (sLogCtrl,a,b);\ + } + +#define SMEMLOG_CDEBUG2(a,b,c) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define SMEMLOG_CDEBUG3(a,b,c,d) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slogc (sLogCtrl,a,b,c,d);\ + } + +#else /* #ifdef DEBUG_SISCO */ + +#define SMEMLOG_ERR0(a) +#define SMEMLOG_ERR1(a,b) +#define SMEMLOG_ERR2(a,b,c) +#define SMEMLOG_CERR0(a) +#define SMEMLOG_CERR1(a,b) +#define SMEMLOG_CERR2(a,b,c) +#define SMEMLOG_NERR0(a) +#define SMEMLOG_NERR1(a,b) +#define SMEMLOG_FLOW1(a,b) +#define SMEMLOG_CFLOW1(a,b) +#define SMEMLOG_CFLOW2(a,b,c) +#define SMEMLOG_DUMP0(a) +#define SMEMLOG_DUMP1(a,b) +#define SMEMLOG_CDUMP0(a,b) +#define SMEMLOG_CDUMP1(a,b) +#define SMEMLOG_CDUMP2(a,b,c) +#define SMEMLOG_CDUMP3(a,b,c,d) +#define SMEMLOG_CDUMP4(a,b,c,d,e) +#define SMEMLOG_CDUMP5(a,b,c,d,e,f) +#define SMEMLOG_DEBUG0(a,b,c) +#define SMEMLOG_DEBUG2(a,b,c) +#define SMEMLOG_DEBUG3(a,b,c,d) +#define SMEMLOG_DEBUG4(a,b,c,d,e) +#define SMEMLOG_CDEBUG0(a) +#define SMEMLOG_CDEBUG1(a,b) +#define SMEMLOG_CDEBUG2(a,b,c) +#define SMEMLOG_CDEBUG3(a,b,c,d) + +#endif /* #ifdef DEBUG_SISCO */ + +/************************************************************************/ +/* Here we define a context control table and the associated indices */ + +#define M_SMEM_MAX_CONTEXT 30 /* number of specific context array elements */ + /* + extra context array elements for user applications */ + /* = MAX context array size */ +extern SMEM_CONTEXT m_smem_ctxt[M_SMEM_MAX_CONTEXT]; + +/* All users of SMEM that want a a context are to specify it here as an */ +/* index into the m_smem_ctxt table. */ + +/* Valid context indices */ +#define MSMEM_GEN_IDX 0 /* chk_* macros use this ctxt*/ + +/* MMS-EASE Lite indices */ +#define MSMEM_DEC_OS_INFO_IDX 1 +#define MSMEM_ENC_OS_INFO_IDX 2 +#define MSMEM_WR_DATA_DEC_BUF_IDX 3 +#define MSMEM_ASN1_DATA_ENC_IDX 4 +#define MSMEM_PDU_ENC_IDX 5 +#define MSMEM_COM_EVENT_IDX 6 +#define MSMEM_RXPDU_IDX 7 +#define MSMEM_NETINFO_IDX 8 +#define MSMEM_DYN_RT_IDX 9 +#define MSMEM_AA_ENCODE_IDX 10 +#define MSMEM_REQ_CTRL_IDX 11 +#define MSMEM_IND_CTRL_IDX 12 +#define MSMEM_MVLU_VA_IDX 13 +#define MSMEM_MVLU_VA_CTRL_IDX 14 +#define MSMEM_MVLU_VA_DATA_IDX 15 +#define MSMEM_MVLU_GNL_IDX 16 +#define MSMEM_MVLU_AA_IDX 17 + +/* For STACK (ACSE and LEANT) */ +#define MSMEM_ACSE_CONN_IDX 18 +#define MSMEM_ACSE_DATA_IDX 19 +#define MSMEM_COSP_CN_IDX 20 +#define MSMEM_N_UNITDATA_IDX 21 +#define MSMEM_SOCK_INFO_IDX 22 +#define MSMEM_SPDU_TX_IDX 23 +#define MSMEM_STARTUP_IDX 24 +#define MSMEM_TPKT_IDX 25 + +/* The following are valid Contexts */ +#define MSMEM_GEN &m_smem_ctxt[MSMEM_GEN_IDX] + +/* MMS-EASE Lite indices */ +#define MSMEM_DEC_OS_INFO &m_smem_ctxt[MSMEM_DEC_OS_INFO_IDX] +#define MSMEM_ENC_OS_INFO &m_smem_ctxt[MSMEM_ENC_OS_INFO_IDX] +#define MSMEM_WR_DATA_DEC_BUF &m_smem_ctxt[MSMEM_WR_DATA_DEC_BUF_IDX] +#define MSMEM_ASN1_DATA_ENC &m_smem_ctxt[MSMEM_ASN1_DATA_ENC_IDX] +#define MSMEM_PDU_ENC &m_smem_ctxt[MSMEM_PDU_ENC_IDX] +#define MSMEM_COM_EVENT &m_smem_ctxt[MSMEM_COM_EVENT_IDX] +#define MSMEM_RXPDU &m_smem_ctxt[MSMEM_RXPDU_IDX] +#define MSMEM_NETINFO &m_smem_ctxt[MSMEM_NETINFO_IDX] +#define MSMEM_REQ_CTRL &m_smem_ctxt[MSMEM_REQ_CTRL_IDX] +#define MSMEM_IND_CTRL &m_smem_ctxt[MSMEM_IND_CTRL_IDX] +#define MSMEM_MVLU_VA &m_smem_ctxt[MSMEM_MVLU_VA_IDX] +#define MSMEM_MVLU_VA_CTRL &m_smem_ctxt[MSMEM_MVLU_VA_CTRL_IDX] +#define MSMEM_MVLU_VA_DATA &m_smem_ctxt[MSMEM_MVLU_VA_DATA_IDX] +#define MSMEM_MVLU_AA &m_smem_ctxt[MSMEM_MVLU_AA_IDX] +#define MSMEM_MVLU_GNL &m_smem_ctxt[MSMEM_MVLU_GNL_IDX] +#define MSMEM_DYN_RT &m_smem_ctxt[MSMEM_DYN_RT_IDX] +#define MSMEM_AA_ENCODE &m_smem_ctxt[MSMEM_AA_ENCODE_IDX] + +/* For STACK (ACSE and LEANT) */ +#define MSMEM_ACSE_CONN &m_smem_ctxt[MSMEM_ACSE_CONN_IDX] +#define MSMEM_ACSE_DATA &m_smem_ctxt[MSMEM_ACSE_DATA_IDX] +#define MSMEM_COSP_CN &m_smem_ctxt[MSMEM_COSP_CN_IDX] +#define MSMEM_N_UNITDATA &m_smem_ctxt[MSMEM_N_UNITDATA_IDX] +#define MSMEM_SOCK_INFO &m_smem_ctxt[MSMEM_SOCK_INFO_IDX] +#define MSMEM_SPDU_TX &m_smem_ctxt[MSMEM_SPDU_TX_IDX] +#define MSMEM_STARTUP &m_smem_ctxt[MSMEM_STARTUP_IDX] +#define MSMEM_TPKT &m_smem_ctxt[MSMEM_TPKT_IDX] + +#ifdef SMEMCFGX +/************************************************************************/ +/* This list is used to log error messages when an invalid context name */ +/* is entered. The error message for an invalid context name will list */ +/* all valid context names, as listed below. */ +/* Note: these names should match those listed above and those in */ +/* 'smemcfg.xml' */ + +typedef struct + { + ST_INT idx; + ST_CHAR *name; + } SMEM_CTXT_NAME; + +static SMEM_CTXT_NAME smemCtxtNames[] = + { + {MSMEM_GEN_IDX, "MSMEM_GEN"}, + {MSMEM_DEC_OS_INFO_IDX, "MSMEM_DEC_OS_INFO"}, + {MSMEM_ENC_OS_INFO_IDX, "MSMEM_ENC_OS_INFO"}, + {MSMEM_WR_DATA_DEC_BUF_IDX, "MSMEM_WR_DATA_DEC_BUF"}, + {MSMEM_ASN1_DATA_ENC_IDX, "MSMEM_ASN1_DATA_ENC"}, + {MSMEM_PDU_ENC_IDX, "MSMEM_PDU_ENC"}, + {MSMEM_COM_EVENT_IDX, "MSMEM_COM_EVENT"}, + {MSMEM_RXPDU_IDX, "MSMEM_RXPDU"}, + {MSMEM_NETINFO_IDX, "MSMEM_NETINFO"}, + {MSMEM_REQ_CTRL_IDX, "MSMEM_REQ_CTRL"}, + {MSMEM_IND_CTRL_IDX, "MSMEM_IND_CTRL"}, + {MSMEM_MVLU_VA_IDX, "MSMEM_MVLU_VA"}, + {MSMEM_MVLU_VA_CTRL_IDX, "MSMEM_MVLU_VA_CTRL"}, + {MSMEM_MVLU_VA_DATA_IDX, "MSMEM_MVLU_VA_DATA"}, + {MSMEM_MVLU_AA_IDX, "MSMEM_MVLU_AA"}, + {MSMEM_MVLU_GNL_IDX, "MSMEM_MVLU_GNL"}, + {MSMEM_DYN_RT_IDX, "MSMEM_DYN_RT"}, + {MSMEM_AA_ENCODE_IDX, "MSMEM_AA_ENCODE"}, + {MSMEM_ACSE_CONN_IDX, "MSMEM_ACSE_CONN"}, + {MSMEM_ACSE_DATA_IDX, "MSMEM_ACSE_DATA"}, + {MSMEM_COSP_CN_IDX, "MSMEM_COSP_CN"}, + {MSMEM_N_UNITDATA_IDX, "MSMEM_N_UNITDATA"}, + {MSMEM_SOCK_INFO_IDX, "MSMEM_SOCK_INFO"}, + {MSMEM_SPDU_TX_IDX, "MSMEM_SPDU_TX"}, + {MSMEM_STARTUP_IDX, "MSMEM_STARTUP"}, + {MSMEM_TPKT_IDX, "MSMEM_TPKT"} + }; + +static ST_INT smem_num_ctxt_names = sizeof(smemCtxtNames)/sizeof(SMEM_CTXT_NAME); + +#endif + +/************************************************************************/ +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* smem.h already included */ + diff --git a/include/inc/acse2.h b/include/inc/acse2.h new file mode 100644 index 0000000..aa88728 --- /dev/null +++ b/include/inc/acse2.h @@ -0,0 +1,310 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995 - 2004, All Rights Reserved */ +/* */ +/* MODULE NAME : acse2.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* ACSE main header file. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/27/04 EJV 16 ACSE_CONN (MAP30_ACSE): added initiator. */ +/* 08/25/03 EJV 15 Del old password auth (OBSOLETE_ACSE_AUTH) */ +/* ACSE_CONN: added part_auth_info, encrypt_ctrl*/ +/* Added security functions protos. */ +/* 08/01/03 JRB 14 Add lean_a.h for DIB_ENTRY. */ +/* 06/17/03 EJV 13 Moved DIB_MATCH... from m_match.h. */ +/* 10/14/02 ASK 12 Added abort diagnostic tag */ +/* 09/27/02 ASK 11 Added ASN.1 security tags to AARE APDU, moved*/ +/* bitstring defines from acse2dec.c */ +/* 06/20/02 JRB 10 Add TSELs & remote NSAP/IP to ACSE_CONN. */ +/* 12/11/01 JRB 09 Convert to use ASN1R. */ +/* 09/10/01 JRB 08 Put back cosp_cn_ptr, cosp_cn_len. */ +/* 08/01/01 JRB 07 Del cosp_cn_ptr, cosp_cn_len from ACSE_CONN. */ +/* 04/03/01 JRB 06 Add PSELs & SSELs to ACSE_CONN. */ +/* 01/05/01 EJV 05 Changes for use over Marben */ +/* 07/14/99 JRB 04 Add ACSE Password Authentication stuff. */ +/* 08/13/98 JRB 03 Lint cleanup. */ +/* 07/23/98 JRB 02 Delete Marben support. */ +/* 11/10/97 JRB 01 Chg cosp_buf to (ST_UCHAR *). */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/19/97 JRB 08 MOSI cleanup. */ +/* 03/07/97 JRB 07 Added MOSI support. */ +/* 01/02/97 EJV 06 Added ACSE2_INCLUDED and __cplusplus. */ +/* 06/25/96 JRB 05 Added 'LEAN_T' support. */ +/* 05/02/96 JRB 04 Add STATE_TP4CONN_WAIT. */ +/* 04/18/96 JRB 03 Add STATE_AARE_ABANDON. */ +/* 03/26/96 MDE 02 Added 'REDUCED_STACK' support */ +/* 10/30/95 JRB 01 Created */ +/************************************************************************/ + +#ifndef ACSE2_INCLUDED +#define ACSE2_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gen_list.h" +#include "acse2log.h" /* slog macros for ACSE */ +#include "acse2usr.h" +#if !defined(MAP30_ACSE) +#include "lean_a.h" /* need DIB_ENTRY */ +#endif +#include "dibmatch.h" + +/* Defines for bits in bitstring encoded values. */ +#define BIT_VERSION1 0x80 /* AARQ, AARE protocol_version */ +#define BIT_AUTHENTICATION 0x80 /* AARQ, AARE acse_requirements */ + +/* ACPM states. */ +#define STATE_INVALID -1 /* So user cannot use freed struct*/ +#define STATE_IDLE 0 +#define STATE_AARE_WAIT 1 +#define STATE_AASCRSP_WAIT 2 +#define STATE_RLRE_WAIT 3 +#define STATE_ARLSRSP_WAIT 4 +#define STATE_ASSOCIATED 5 +#define STATE_INIT_COLL 6 +#define STATE_RESP_COLL 7 +#define STATE_AARE_ABANDON 8 +#define STATE_TP4CONN_WAIT 9 + +/* ASN.1 tags for ACSE APDUs */ +#define TAG_AARQ 0 +#define TAG_AARE 1 +#define TAG_RLRQ 2 +#define TAG_RLRE 3 +#define TAG_ABRT 4 +#define TAG_ADT 5 +/* ASN.1 tags for CONNECTIONLESS ACSE APDUs */ +#define TAG_AUDT 0 + +/* ASN.1 tags for elements of AARQ APDU */ +#define AARQ_protocol_version 0 +#define AARQ_ASO_context_name 1 +#define AARQ_CALLED_AP_title 2 +#define AARQ_CALLED_AE_qual 3 +#define AARQ_CALLED_AP_inv_id 4 +#define AARQ_CALLED_AE_inv_id 5 +#define AARQ_CALLING_AP_title 6 +#define AARQ_CALLING_AE_qual 7 +#define AARQ_CALLING_AP_inv_id 8 +#define AARQ_CALLING_AE_inv_id 9 +#define AARQ_acse_requirements 10 +#define AARQ_mechanism_name 11 +#define AARQ_CALLING_auth_value 12 +#define AARQ_user_info 30 + +/* ASN.1 tags for elements of AUDT APDU (same as AARQ) */ +#define AUDT_protocol_version AARQ_protocol_version +#define AUDT_ASO_context_name AARQ_ASO_context_name +#define AUDT_CALLED_AP_title AARQ_CALLED_AP_title +#define AUDT_CALLED_AE_qual AARQ_CALLED_AE_qual +#define AUDT_CALLED_AP_inv_id AARQ_CALLED_AP_inv_id +#define AUDT_CALLED_AE_inv_id AARQ_CALLED_AE_inv_id +#define AUDT_CALLING_AP_title AARQ_CALLING_AP_title +#define AUDT_CALLING_AE_qual AARQ_CALLING_AE_qual +#define AUDT_CALLING_AP_inv_id AARQ_CALLING_AP_inv_id +#define AUDT_CALLING_AE_inv_id AARQ_CALLING_AE_inv_id +#define AUDT_user_info AARQ_user_info + +/* ASN.1 tags for elements of AARE APDU */ +#define AARE_protocol_version 0 +#define AARE_ASO_context_name 1 +#define AARE_result 2 +#define AARE_result_source_diagnostic 3 +#define AARE_RESPONDING_AP_title 4 +#define AARE_RESPONDING_AE_qual 5 +#define AARE_RESPONDING_AP_inv_id 6 +#define AARE_RESPONDING_AE_inv_id 7 +#define AARE_RESPONDER_acse_requirements 8 /* See the ACSE Spec for the strange name */ +#define AARE_mechanism_name 9 +#define AARE_RESPONDING_auth_value 10 +#define AARE_user_info 30 + +/* ASN.1 tags for elements of RLRQ APDU */ +#define RLRQ_reason 0 +#define RLRQ_user_info 30 + +/* ASN.1 tags for elements of RLRE APDU */ +#define RLRE_reason 0 +#define RLRE_user_info 30 + +/* ASN.1 tags for elements of ABRT APDU */ +#define ABRT_source 0 +#define ABRT_diagnostic 1 +#define ABRT_user_info 30 + +/* ASN.1 tags for elements of ADT APDU */ +#define ADT_user_info 30 + +#define ACSE_SERVICE_USER 0 +#define ACSE_SERVICE_PROVIDER 1 + +/************************************************************************/ +/* ACSE_CONN structure */ +/************************************************************************/ +#if defined (MOSI) +#define MAX_COSP_COPP_HEADER (((MAX_PSEL_LEN+MAX_SSEL_LEN)*2)+200) +typedef struct tagACSE_CONN + { + /* common part */ + ST_UINT apdu_len; /* len of a APDU (also PS-user data len)*/ + ST_UCHAR *apdu_ptr; /* pointer to start of APDU encoding */ + ST_UINT ppdu_len; /* len of a PPDU (also SS-user data len)*/ + ST_UCHAR *ppdu_ptr; /* pointer to start of PPDU encoding */ + ST_CHAR pcimms; + ST_CHAR pciacse; + /* ACSE part */ + ST_LONG user_conn_id; /* ACSE-user's connection ID. */ + ST_INT state; /* See "STATE_*" defines */ + ST_BOOLEAN initiator; /* Flag: did we initiate this connection? */ + /* COPP part */ + ST_INT num_ctxt; + ST_INT copp_state; /* See "COPP_STATE_*" defines */ + /* cosp part */ + ST_INT cosp_state; /* See "COSP_CSTATE_*" defines */ + ST_UINT cosp_cn_len; + char *cosp_cn_ptr; /* CONNECT SPDU saved until TCONN.cnf */ + ST_LONG cosp_bind_id; /* COSP bind id saved until CN arrive */ + ST_BOOLEAN cosp_vtca; /* SD_TRUE if transport connection acceptor*/ + ST_BOOLEAN cosp_vcoll; /* SD_TRUE if collision of FINISH SPDUs */ + ST_BOOLEAN cosp_vdnr; /* SD_TRUE if DISCONNECT SPDU has been */ + /* received in STA 09 (following */ + /* collision of FINISH SPDUs). */ + /* TP4 part */ + ST_LONG tp4_conn_id; /* TP4 connect id */ + ST_BOOLEAN cr; /* "collision of release" flag */ + ST_BOOLEAN rl; /* "release started" flag */ + BUFFER save_buf; /* buffer to save AARQ or RLRE to send later */ + ST_UCHAR loc_psel [MAX_PSEL_LEN+1]; /* Local PSEL (1st byte = len) */ + ST_UCHAR rem_psel [MAX_PSEL_LEN+1]; /* Remote PSEL (1st byte = len) */ + ST_UCHAR loc_ssel [MAX_SSEL_LEN+1]; /* Local SSEL (1st byte = len) */ + ST_UCHAR rem_ssel [MAX_SSEL_LEN+1]; /* Remote SSEL (1st byte = len) */ + ST_UCHAR loc_tsel [MAX_TSEL_LEN+1]; /* Local TSEL (1st byte = len) */ + ST_UCHAR rem_tsel [MAX_TSEL_LEN+1]; /* Remote TSEL (1st byte = len) */ + union + { + ST_UCHAR nsap [CLNP_MAX_LEN_NSAP+1];/* Remote NSAP (1st byte = len) */ + ST_ULONG ip; /* OR IP Addr (network byte order)*/ + }remNetAddr; + /* authentication and security */ + ACSE_AUTH_INFO part_auth_info; /* partner authentication info */ + S_SEC_ENCRYPT_CTRL encrypt_ctrl; /* connection encryption info */ + } ACSE_CONN; +#elif defined (MAP30_ACSE) +typedef struct acse_bind_info_tag + { + ST_CHAR ar_name[MAX_NAME_LEN+1]; /* local AR Name to be bind */ + ST_LONG user_bind_id; /* Save User's bind ID */ + ST_INT suic_chan_base; /* start chan where we register AR Name */ + ST_INT num_calling; /* num of calling channels */ + ST_INT num_called; /* num of called channels */ + } ACSE_BIND_INFO; + +typedef struct tagACSE_CONN + { + /* fields below are changed during binding */ + ACSE_BIND_INFO *bind_info; /* pointer to ACSE bind info */ + ST_LONG user_bind_id; /* user's bind ID */ + ST_INT chan; /* SUIC channel */ + /* fields below are changed during connection/disconnection */ + ST_INT state; /* See "STATE_*" defines */ + ST_LONG user_conn_id; /* user's connect ID */ + ST_BOOLEAN initiator; /* Flag: did we initiate this connection? */ + ST_UINT ap_context; /* SUIC AP context from associate ind */ + ST_INT num_pc_defs; /* pres context deflist count from aind */ + PC_DEF *pc_deflist; /* pres context deflist ptr from aind */ + } ACSE_CONN; +#else /* !MOSI and !MAP30_ACSE */ +typedef struct tagACSE_CONN + { + ST_LONG user_bind_id; /* tp4_connect_ind saves for u_a_associate_ind */ + ST_LONG tp4_conn_id; + ST_LONG user_conn_id; + ST_INT state; /* See "STATE_*" defines */ + ST_BOOLEAN initiator; /* Flag: did we initiate this connection? */ + ST_UCHAR *rcv_data; /* buffer to reassembling TPDUs */ + ST_UINT rcv_data_len; /* Length of data in rcv_data. */ + BUFFER save_buf; /* buffer to save AARQ or RLRE to send later */ + } ACSE_CONN; +#endif /* !MOSI */ + +/************************************************************************/ +/* PBIND structure */ +/************************************************************************/ +typedef struct tagPBIND + { + DBL_LNK link; + ST_LONG user_bind_id; /* User-supplied Bind ID */ + ST_LONG clnp_bind_id; /* Register ID returned by OSIAM */ + ST_LONG real_clpp_bind_id; /* Used in real bind/unbind to Marben */ + ST_INT sap; /* SAP number this register is bound to */ + PRES_ADDR loc_addr; + } PBIND; + +/************************************************************************/ +/* General address matching defines, control, functions */ +/* */ + +#if !defined(MAP30_ACSE) +/* Lean-T specific functions */ +ST_RET dib_match_remote_ar (DIB_MATCH_CTRL *matchCtrl, AARQ_APDU *aarq, + DIB_ENTRY **dib_entry_out); +ST_RET dib_match_local_ar (DIB_MATCH_CTRL *matchCtrl, AARQ_APDU *aarq, + DIB_ENTRY **dib_entry_out); +ST_INT dib_cmp_local_addr (DIB_MATCH_CTRL *matchCtrl, AARQ_APDU *aarq, + DIB_ENTRY *dib_entry); +ST_INT dib_cmp_remote_addr (DIB_MATCH_CTRL *matchCtrl, AARQ_APDU *aarq, + DIB_ENTRY *dib_entry); +#endif /* !defined(MAP30_ACSE) */ + + +/************************************************************************/ +/* Security functions */ +ST_RET a_get_security_info (ST_LONG acse_conn_id, S_SEC_SPARAMS *secParams); +ST_RET a_free_security_info (ACSE_AUTH_INFO *authInfo); +ST_RET a_free_part_security_info (ST_LONG acse_conn_id); + + +/************************************************************************/ +/* Global variables. */ +/************************************************************************/ +extern ST_INT num_pbinds; /* Number of P-Address bindings.*/ +extern PBIND *pbind_list; /* Linked list of PBIND structs */ +extern ST_BOOLEAN nsap_bind_done; /* Don't allow 2nd bind until 1st done */ +extern MMS_OBJ_ID mms_obj_id; /* ISO MMS Object ID */ +extern MMS_OBJ_ID acse_obj_id; /* ACSE Object ID */ +extern MMS_OBJ_ID asn1_obj_id; /* ASN.1 Object ID */ +extern MMS_OBJ_ID a_auth_password_obj_id; /* Obj ID for ACSE Password*/ + /* Authentication mech. */ + +extern ST_UINT acse_msgsize; +#ifdef MOSI +extern ST_UINT cosp_msgsize; +extern ST_UCHAR *cosp_buf; +extern ACSE_CONN *decode_acse_conn; /* connection we're doing decode for. */ +#endif + +/************************************************************************/ +/* Prototypes */ +/************************************************************************/ +ST_VOID clnp_unbind_cnf (PBIND *pbind); +ST_VOID asn1_skip_elmnt (ASN1_DEC_CTXT *aCtx); +ST_VOID acse_free_con (ACSE_CONN *con); + + +#ifdef __cplusplus +} +#endif + +#endif /* ACSE2_INCLUDED */ + diff --git a/include/inc/acse2log.h b/include/inc/acse2log.h new file mode 100644 index 0000000..a2cd434 --- /dev/null +++ b/include/inc/acse2log.h @@ -0,0 +1,144 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-2003, All Rights Reserved */ +/* */ +/* MODULE NAME : acse2log.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* ACSE logging header file. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/02/05 JRB 07 Added acse2usr.h */ +/* 06/17/03 EJV 06 Converted to new log macros. */ +/* Deleted _audt_*_logstr. Added DIB logging. */ +/* 12/11/00 EJV 05 Added more log macros */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 12/16/96 JRB 04 Del "AUDTLOG_*" macros. Use "ACSELOG_*" for */ +/* CL ACSE as well as CO ACSE. */ +/* 10/08/98 MDE 08 Migrated to updated SLOG interface */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/20/97 JRB 07 Stop checking for sLogCtrl==NULL. */ +/* 02/20/97 JRB 06 Move *_debug_sel & logmasks from acse2log.h */ +/* to acse2usr.h. */ +/* 01/02/97 EJV 05 Added ACSE2LOG_INCLUDED */ +/* 12/16/96 JRB 04 Add "AUDTLOG_*" macros for CLACSE. */ +/* 07/19/96 JRB 03 Change DEBUG_MMS to DEBUG_SISCO. */ +/* 04/17/96 JRB 02 Del acse_sLogCtrl, use sLogCtrl (slog.c) now */ +/* 10/30/95 JRB 01 Created */ +/************************************************************************/ +#ifndef ACSE2LOG_INCLUDED +#define ACSE2LOG_INCLUDED + +#include "acse2usr.h" /* need acse_debug_sel & log mask defines */ + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef DEBUG_SISCO +/****************************************************************/ +/* Log Control macros */ +/****************************************************************/ + +extern SD_CONST ST_CHAR *SD_CONST _acse_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _acse_enc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _acse_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _acse_dib_logstr; +#endif /* DEBUG_SISCO */ + +/*--------------------------------------*/ +/* ACSELOG_DEC macros */ +/*--------------------------------------*/ +#define ACSELOG_DEC0(a) \ + SLOG_0 (acse_debug_sel & ACSE_LOG_DEC,_acse_dec_logstr,a) +#define ACSELOG_DEC1(a,b) \ + SLOG_1 (acse_debug_sel & ACSE_LOG_DEC,_acse_dec_logstr,a,b) +#define ACSELOG_DEC2(a,b,c) \ + SLOG_2 (acse_debug_sel & ACSE_LOG_DEC,_acse_dec_logstr,a,b,c) +#define ACSELOG_DEC3(a,b,c,d) \ + SLOG_3 (acse_debug_sel & ACSE_LOG_DEC,_acse_dec_logstr,a,b,c,d) + +#define ACSELOG_DEC0C(a) SLOGC_0 (acse_debug_sel & ACSE_LOG_DEC,a) +#define ACSELOG_DEC1C(a,b) SLOGC_1 (acse_debug_sel & ACSE_LOG_DEC,a,b) +#define ACSELOG_DEC2C(a,b,c) SLOGC_2 (acse_debug_sel & ACSE_LOG_DEC,a,b,c) +#define ACSELOG_DEC3C(a,b,c,d) SLOGC_3 (acse_debug_sel & ACSE_LOG_DEC,a,b,c,d) + +#define ACSELOG_DECH(a,b) SLOGH (acse_debug_sel & ACSE_LOG_DEC,a,b) + +/*--------------------------------------*/ +/* ACSELOG_ENC macros */ +/*--------------------------------------*/ +#define ACSELOG_ENC0(a) \ + SLOG_0 (acse_debug_sel & ACSE_LOG_ENC,_acse_enc_logstr,a) +#define ACSELOG_ENC1(a,b) \ + SLOG_1 (acse_debug_sel & ACSE_LOG_ENC,_acse_enc_logstr,a,b) +#define ACSELOG_ENC2(a,b,c) \ + SLOG_2 (acse_debug_sel & ACSE_LOG_ENC,_acse_enc_logstr,a,b,c) +#define ACSELOG_ENC3(a,b,c,d) \ + SLOG_3 (acse_debug_sel & ACSE_LOG_ENC,_acse_enc_logstr,a,b,c,d) + +#define ACSELOG_ENC0C(a) SLOGC_0 (acse_debug_sel & ACSE_LOG_ENC,a) +#define ACSELOG_ENC1C(a,b) SLOGC_1 (acse_debug_sel & ACSE_LOG_ENC,a,b) +#define ACSELOG_ENC2C(a,b,c) SLOGC_2 (acse_debug_sel & ACSE_LOG_ENC,a,b,c) +#define ACSELOG_ENC3C(a,b,c,d) SLOGC_3 (acse_debug_sel & ACSE_LOG_ENC,a,b,c,d) + +#define ACSELOG_ENCH(a,b) SLOGH (acse_debug_sel & ACSE_LOG_ENC,a,b) + +/*--------------------------------------*/ +/* ACSELOG_ERR macros */ +/*--------------------------------------*/ +#define ACSELOG_ERR0(a) \ + SLOG_0 (acse_debug_sel & ACSE_LOG_ERR,_acse_err_logstr,a) +#define ACSELOG_ERR1(a,b) \ + SLOG_1 (acse_debug_sel & ACSE_LOG_ERR,_acse_err_logstr,a,b) +#define ACSELOG_ERR2(a,b,c) \ + SLOG_2 (acse_debug_sel & ACSE_LOG_ERR,_acse_err_logstr,a,b,c) +#define ACSELOG_ERR3(a,b,c,d) \ + SLOG_3 (acse_debug_sel & ACSE_LOG_ERR,_acse_err_logstr,a,b,c,d) + +#define ACSELOG_ERR0C(a) SLOGC_0 (acse_debug_sel & ACSE_LOG_ERR,a) +#define ACSELOG_ERR1C(a,b) SLOGC_1 (acse_debug_sel & ACSE_LOG_ERR,a,b) +#define ACSELOG_ERR2C(a,b,c) SLOGC_2 (acse_debug_sel & ACSE_LOG_ERR,a,b,c) +#define ACSELOG_ERR3C(a,b,c,d) SLOGC_3 (acse_debug_sel & ACSE_LOG_ERR,a,b,c,d) + +#define ACSELOG_ERRH(a,b) SLOGH (acse_debug_sel & ACSE_LOG_ERR,a,b) + +/*--------------------------------------*/ +/* ACSELOG_DIB macros */ +/*--------------------------------------*/ +#define ACSELOG_DIB0(a) \ + SLOG_0 (acse_debug_sel & ACSE_LOG_DIB,_acse_dib_logstr,a) +#define ACSELOG_DIB1(a,b) \ + SLOG_1 (acse_debug_sel & ACSE_LOG_DIB,_acse_dib_logstr,a,b) +#define ACSELOG_DIB2(a,b,c) \ + SLOG_2 (acse_debug_sel & ACSE_LOG_DIB,_acse_dib_logstr,a,b,c) +#define ACSELOG_DIB3(a,b,c,d) \ + SLOG_3 (acse_debug_sel & ACSE_LOG_DIB,_acse_dib_logstr,a,b,c,d) + +#define ACSELOG_DIB0C(a) SLOGC_0 (acse_debug_sel & ACSE_LOG_DIB,a) +#define ACSELOG_DIB1C(a,b) SLOGC_1 (acse_debug_sel & ACSE_LOG_DIB,a,b) +#define ACSELOG_DIB2C(a,b,c) SLOGC_2 (acse_debug_sel & ACSE_LOG_DIB,a,b,c) +#define ACSELOG_DIB3C(a,b,c,d) SLOGC_3 (acse_debug_sel & ACSE_LOG_DIB,a,b,c,d) + +#define ACSELOG_DIBH(a,b) SLOGH (acse_debug_sel & ACSE_LOG_DIB,a,b) + + +/****************************************************************/ +/* Log Control prototypes. */ +/****************************************************************/ +ST_VOID acse_default_log (ST_VOID); /* Set default log configuration */ + +#ifdef __cplusplus +} +#endif + +#endif /* ACSE2LOG_INCLUDED */ + diff --git a/include/inc/acse2usr.h b/include/inc/acse2usr.h new file mode 100644 index 0000000..4030758 --- /dev/null +++ b/include/inc/acse2usr.h @@ -0,0 +1,406 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-2005, All Rights Reserved */ +/* */ +/* MODULE NAME : acse2usr.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* ACSE main header file. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/05/05 EJV 33 PRES_ADDR added port. */ +/* 03/28/05 EJV 32 MMSEASE_MOSE: add MAX_PSEL_LEN, MAX_SSEL_LEN */ +/* 10/21/03 JRB 31 Add a_get_event_handles_unix. */ +/* 08/25/03 EJV 30 Del old password auth (OBSOLETE_ACSE_AUTH) */ +/* Added a_get_chan. */ +/* Renamed encrypt_info to encrypt_ctrl */ +/* 07/23/03 MDE 29 Removed ACSE_AUTH_ENABLED, S_SEC_ENABLED */ +/* 06/17/03 EJV 28 Added ACSE_LOG_DIB mask. */ +/* 06/13/03 MDE 27 Added Security */ +/* 10/14/02 ASK 26 Added abort diagnostic to ABRT_APDU. */ +/* 09/30/02 ASK 25 Moved authentication defines / protos into */ +/* acseauth.h */ +/* 09/27/02 ASK 24 Add authentication stuff to AARE_APDU */ +/* 06/20/02 JRB 23 Add calling_paddr to AARQ_APDU. */ +/* Replace "nsap" in PRES_ADDR with union. */ +/* 05/02/02 MDE 22 Added _copp_bind */ +/* 02/14/02 ASK 21 Add a_associate_reqm */ +/* 01/22/02 JRB 20 Add args to copp_initialize (same as MAP30..)*/ +/* Del a_set_msgsize (no longer needed). */ +/* 01/10/02 JRB 19 Add cltp_decode_nsdu_2 proto. */ +/* 12/20/01 JRB 18 Del clpp_bind functions and bind id args to */ +/* a_unit_data_req & u_a_unit_data_ind. */ +/* 05/10/01 JRB 17 Chg SSEL_LEN from 16 to 4. */ +/* 12/18/00 EJV 16 Added remAr param to a_associate_req for */ +/* Lite over Marben stack (MAP30_ACSE). */ +/* 08/05/99 JRB 15 Add a_get_ev... prototype. */ +/* 07/14/99 JRB 14 Add ACSE Password Authentication stuff. */ +/* 01/28/99 JRB 13 Move cltp_decode_nsdu proto from TP4 to here.*/ +/* 12/04/98 JRB 12 Del "audt_debug_sel". */ +/* Add "loc_mac" to AUDT_APDU. */ +/* 08/13/98 JRB 11 Lint cleanup. */ +/* 08/14/97 JRB 10 Added "tp_type" to PRES_ADDR. */ +/* Del MAX_TSEL_LEN & MAX_NSAP_LEN defines (use */ +/* MAX_TSEL_LEN & MAX_IP_ADDR_LEN in tp4api.h). */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 04/10/97 JRB 09 Chg error defs to use base from "glberror.h".*/ +/* 03/07/97 JRB 08 Add COPP & COSP logmasks for MOSI. */ +/* 02/20/97 JRB 07 Move *_debug_sel & logmasks from acse2log.h */ +/* to acse2usr.h. */ +/* 01/09/97 MDE 06 Allow user to specify destination MAC */ +/* 01/01/97 RKR 05 Added ACSE2USR_INCLUDED and __cplusplus */ +/* 10/04/96 JRB 04 Add adlcAddr to PRES_ADDR for MCGW. */ +/* 08/15/96 JRB 03 Add a_buffers_avail prototype for LEAN_T. */ +/* 04/18/96 JRB 02 Chg a_associate_req return to ST_LONG. */ +/* 03/26/96 MDE 01 Added header, 'REDUCED_STACK' support */ +/************************************************************************/ + +#ifndef ACSE2USR_INCLUDED +#define ACSE2USR_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "asn1defs.h" +#include "acseauth.h" +#include "ssec.h" +#include "clnp_usr.h" +#include "tp4api.h" /* Need TP_TYPE_* defines for "tp_type" values. */ + /* Need MAX_TSEL_LEN & MAX_IP_ADDR_LEN defines. */ + + +/****************************************************************/ +/* Log Control */ +/****************************************************************/ +#define ACSE_LOG_ERR 0x00000001 +#define ACSE_LOG_ENC 0x00000002 +#define ACSE_LOG_DEC 0x00000004 +#define ACSE_LOG_DIB 0x00000008 + +#define COPP_LOG_ERR 0x00000100L +#define COPP_LOG_DEC 0x00001000L +#define COPP_LOG_DEC_HEX 0x00002000L +#define COPP_LOG_ENC 0x00004000L +#define COPP_LOG_ENC_HEX 0x00008000L + +#define COSP_LOG_ERR 0x00010000L +#define COSP_LOG_DEC 0x00100000L +#define COSP_LOG_DEC_HEX 0x00200000L +#define COSP_LOG_ENC 0x00400000L +#define COSP_LOG_ENC_HEX 0x00800000L + + +extern ST_UINT acse_debug_sel; + +/************************************************************************/ +/* Error codes (returned from a_* functions). */ +/* NOTE: Values begin from E_ACSE2 (found in glberror.h). */ +/* NOTE: The exception codes (EX_ACSE_*) do not have separate range. */ +/************************************************************************/ +#define E_ACSE_ENC_ERR 0x3001 +#define E_ACSE_SEND_ERR 0x3002 +#define E_ACSE_INVALID_CONN_ID 0x3003 +#define E_ACSE_INVALID_STATE 0x3004 +#define E_ACSE_INVALID_PARAM 0x3005 +#define E_ACSE_BUFFER_OVERFLOW 0x3006 +#define E_ACSE_MEMORY_ALLOC 0x3007 + +/************************************************************************/ +/* Exception codes (passed to u_a_except or u_cla_except). */ +/* Caused by decode or state problems. */ +/************************************************************************/ +#define EX_ACSE_DECODE 0x3081 +#define EX_ACSE_INVALID_STATE 0x3082 + +/************************************************************************/ +/* Structure definitions. */ +/************************************************************************/ +/* This structure represents the entire Presentation address */ +/* NOTE: Using Fastbyte Presentation and Session, there are no P-Sels */ +/* and S-Sels, so the P-Address is equivalent to the T-Address */ + +#if defined(MMSEASE_MOSI) +#define MAX_PSEL_LEN 16 +#define MAX_SSEL_LEN 16 +#else +#define MAX_PSEL_LEN 4 /* International Std Profile recommends 4*/ +#define MAX_SSEL_LEN 4 /* GOSIP Ver2 recommends len of 2 */ +#endif +/* MAX_TSEL_LEN defined in "tp4api.h" */ +/* MAX_IP_ADDR_LEN defined in "tp4api.h" */ +typedef struct tagPRES_ADDR + { +#if !defined(REDUCED_STACK) + ST_UINT psel_len; + ST_UCHAR psel [MAX_PSEL_LEN]; + ST_UINT ssel_len; + ST_UCHAR ssel [MAX_SSEL_LEN]; + ST_INT tp_type; /* Type of transport: TP_TYPE_TP4 or TP_TYPE_TCP.*/ + ST_UINT tsel_len; + ST_UCHAR tsel [MAX_TSEL_LEN]; + ST_UINT nsap_len; + union + { /* If TP_TYPE_TP4, use "nsap". If TP_TYPE_TCP, use "ip". */ + ST_UCHAR nsap [CLNP_MAX_LEN_NSAP]; /* NSAP OR */ + ST_ULONG ip; /* IP Addr (network byte order) */ + }netAddr; + ST_UINT16 port; +#if defined (MCGW) + ST_UINT16 adlcAddr; +#endif /* defined (MCGW) */ +#else + ST_UINT16 adlcAddr; +#endif + } PRES_ADDR; + +/* This structure is used for any data that must be encoded/decoded */ +/* by the user instead of the ACSE. */ +/* If len == 0, or ptr == NULL, it is assumed there is no data. */ +typedef struct tagBUFFER + { + ST_INT len; /* Length of encoded data. */ + ST_UCHAR *ptr; /* Pointer to encoded data. */ + } BUFFER; + +/* This structure contains AE_TITLE info. */ +typedef struct tagAE_TITLE + { + ST_BOOLEAN AP_title_pres; /* present flag */ + MMS_OBJ_ID AP_title; /* AP title */ + ST_BOOLEAN AE_qual_pres; /* present flag */ + ST_INT32 AE_qual; /* AE qualifier */ + ST_BOOLEAN AP_inv_id_pres; /* present flag */ + ST_INT32 AP_inv_id; /* AP invocation ID */ + ST_BOOLEAN AE_inv_id_pres; /* present flag */ + ST_INT32 AE_inv_id; /* AE invocation ID */ + } AE_TITLE; + +/* This structure is used for the AARQ_APDU. */ +typedef struct tagAARQ_APDU + { + /* The following entries passed to peer in AARQ-apdu.*/ + /* ACSE sets and checks "protocol-version". Must be "version1". */ + ST_BOOLEAN ASO_context_name_pres; + MMS_OBJ_ID ASO_context_name; + AE_TITLE called_ae_title; + AE_TITLE calling_ae_title; + + /* authentication and security */ + ACSE_AUTH_INFO auth_info; + S_SEC_ENCRYPT_CTRL encrypt_ctrl; + + BUFFER user_info; /* User must encode/decode */ + + /* The following entries passed to presentation. */ + /* NOTE: "calling_paddr" ignored by "a_associate_req" function. */ + /* Contains remote addr when "u_a_associate_ind" called. */ + PRES_ADDR calling_paddr; + PRES_ADDR called_paddr; + } AARQ_APDU; + +/* This structure is used for the AUDT_APDU */ +/* NOTE: same as AARQ_APDU except add calling_paddr. */ +typedef struct tagAUDT_APDU + { + /* The following entries passed to peer in AUDT-apdu.*/ + /* ACSE sets and checks "protocol-version". Must be "version1". */ + ST_BOOLEAN ASO_context_name_pres; + MMS_OBJ_ID ASO_context_name; + AE_TITLE called_ae_title; + AE_TITLE calling_ae_title; + BUFFER user_info; /* User must encode/decode */ + + /* The following entries passed to or received from presentation. */ + PRES_ADDR calling_paddr; + PRES_ADDR called_paddr; + + /* User doesn't need to set loc_mac before calling a_unit_data_req. */ + /* Decode process fills in loc_mac before calling u_a_unit_data_ind. */ + ST_UCHAR loc_mac [CLNP_MAX_LEN_MAC]; /* Local MAC addr */ + ST_BOOLEAN rem_mac_valid; /* SD_TRUE if MAC addr valid */ + ST_UCHAR rem_mac [CLNP_MAX_LEN_MAC]; /* Remote MAC addr */ + } AUDT_APDU; + + +/* This structure is used for the AARE_APDU. */ +typedef struct tagAARE_APDU + { + /* ACSE sets and checks "protocol-version". Must be "version1". */ + ST_BOOLEAN ASO_context_name_pres; + MMS_OBJ_ID ASO_context_name; + AE_TITLE responding_ae_title; + ST_INT16 result; + ST_BOOLEAN result_source_diag_pres; + ST_UINT16 result_source; /* Passed as asn1_tag to ASN1 functs */ + ST_INT16 result_diag; + + /* authentication and security */ + ACSE_AUTH_INFO auth_info; + S_SEC_ENCRYPT_CTRL encrypt_ctrl; + + BUFFER user_info; /* User must encode/decode */ + } AARE_APDU; + +/* This structure is used for the RLRQ_APDU. */ +typedef struct tagRLRQ_APDU + { + ST_BOOLEAN reason_pres; + ST_INT16 reason; + BUFFER user_info; /* User must encode/decode */ + } RLRQ_APDU; + +/* This structure is used for the RLRE_APDU. */ +typedef struct tagRLRE_APDU + { + ST_BOOLEAN reason_pres; + ST_INT16 reason; + BUFFER user_info; /* User must encode/decode */ + /* NOTE: With Fastbyte presentation and session, there is no way to */ + /* refuse a release, so the "Result" parameter is assumed to be */ + /* "affirmative", and is therefore not needed in this structure.*/ + } RLRE_APDU; + +/* This structure is used for the ABRT_APDU. */ +typedef struct tagABRT_APDU + { + ST_INT16 source; /* Abort source (0=user, 1=provider) */ + ST_BOOLEAN diagnostic_pres; + ST_ACSE_AUTH diagnostic; /* Abort diagnostic; codes in acseauth.h */ + BUFFER user_info; /* User must encode/decode */ + } ABRT_APDU; + +/* NOTE: the ASO-association-identifier in the ACSE specification is not*/ +/* supported in this implementation. It will not be sent in outgoing */ +/* APDUs and will be ignored in incoming APDUs. */ + +/************************************************************************/ +/* Prototypes */ +/************************************************************************/ +ST_RET copp_initialize (ST_INT max_conns, ST_UINT msg_size); +ST_RET copp_terminate (ST_VOID); +ST_BOOLEAN copp_event (ST_VOID); +#if defined(MAP30_ACSE) +ST_RET copp_bind (ST_LONG user_bind_id, ST_CHAR *loc_ar_name, + ST_INT num_calling, ST_INT num_called); +ST_RET _copp_bind (ST_LONG user_bind_id, ST_CHAR *loc_ar_name, + ST_INT num_calling, ST_INT num_called, + ST_BOOLEAN activate); +#else +ST_RET copp_bind (ST_LONG user_bind_id, PRES_ADDR *pres_addr, + ST_INT sharable, ST_INT max_conns); +#endif /* !defined(MAP30_ACSE) */ +ST_VOID u_copp_bind_cnf (ST_LONG user_bind_id, ST_LONG copp_bind_id, ST_RET result); +ST_RET copp_unbind (ST_LONG copp_bind_id); +ST_VOID u_copp_unbind_cnf (ST_LONG user_bind_id); +ST_RET audt_set_msgsize (ST_UINT len); +#if defined(MAP30_ACSE) +ST_LONG a_associate_req ( + ST_LONG copp_bind_id, /* ACSE's bind ID received in u_copp_bind_cnf*/ + ST_LONG user_conn_id, /* USER's ID for this connection */ + AARQ_APDU *info, /* AARQ_APDU info */ + ST_CHAR *remAr); /* remote AR Name. */ + +ST_LONG a_associate_reqm ( + ST_LONG copp_bind_id, /* ACSE's bind ID received in u_copp_bind_cnf*/ + ST_LONG user_conn_id, /* USER's ID for this connection */ + AARQ_APDU *aarq_apdu, /* AARQ_APDU info */ + ST_CHAR *locAr, /* local AR Name. */ + ST_CHAR *remAr); /* remote AR Name. */ +#else +ST_LONG a_associate_req ( + ST_LONG copp_bind_id, /* ACSE's bind ID received in u_copp_bind_cnf*/ + ST_LONG user_conn_id, /* USER's ID for this connection */ + AARQ_APDU *info); /* AARQ_APDU info. */ +#endif /* !defined(MAP30_ACSE) */ +ST_VOID u_a_associate_ind ( + ST_LONG user_bind_id, /* USER's Bind ID passed to copp_bind */ + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + AARQ_APDU *info); /* AARQ_APDU info. */ +ST_RET a_associate_rsp ( + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + ST_LONG user_conn_id, /* USER's ID for this connection */ + AARE_APDU *info); /* AARE_APDU info. */ +ST_VOID u_a_associate_cnf ( + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + ST_LONG user_conn_id, /* USER's ID for this connection */ + AARE_APDU *info); /* AARE_APDU info. */ +ST_RET a_release_req ( + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + RLRQ_APDU *info); /* RLRQ_APDU info. */ +ST_VOID u_a_release_ind ( + ST_LONG user_conn_id, /* USER's ID for this connection */ + RLRQ_APDU *info); /* RLRQ_APDU info. */ +ST_RET a_release_rsp ( + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + RLRE_APDU *info); /* RLRE_APDU info. */ +ST_VOID u_a_release_cnf ( + ST_LONG user_conn_id, /* user's ID for this connection */ + RLRE_APDU *info); /* RLRE_APDU info. */ +ST_RET a_abort_req ( + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + ABRT_APDU *info); /* ABORT request info. */ +ST_VOID u_a_abort_ind ( + ST_LONG user_conn_id, /* USER's ID for this connection */ + ABRT_APDU *info); /* ABORT request info. */ +ST_RET a_data_req ( + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + ST_UINT data_len, + ST_UCHAR *data); +ST_VOID u_a_data_ind ( + ST_LONG user_conn_id, /* USER's ID for this connection */ + ST_UINT data_len, + ST_UCHAR *data); +ST_INT a_buffers_avail ( + ST_LONG acse_conn_id); /* ACSE's ID for this connection */ +ST_VOID u_a_except ( + ST_LONG user_conn_id, /* USER's ID for this connection */ + ST_INT code, /* See EX_ACSE_* defines */ + ST_CHAR *filename, /* Source code file name */ + ST_INT line); /* source code line number */ +ST_VOID u_cla_except ( + ST_LONG user_bind_id, /* USER's ID for this bind */ + ST_INT code, /* See EX_ACSE_* defines */ + ST_CHAR *filename, /* Source code file name */ + ST_INT line); /* source code line number */ + +ST_RET clpp_initialize (ST_VOID); +ST_RET clpp_terminate (ST_VOID); +ST_RET a_unit_data_req ( + AUDT_APDU *info); /* AUDT_APDU info. */ +ST_VOID u_a_unit_data_ind ( + AUDT_APDU *info); /* AUDT_APDU info. */ +ST_BOOLEAN clpp_event (ST_VOID); + +ST_VOID cltp_decode_nsdu (N_UNITDATA *n_unitdata); +ST_RET cltp_decode_nsdu_2 (N_UNITDATA *pNudt, AUDT_APDU *pAudt); + +/************************************************************************/ +/* Address resolution utility functions. */ +/************************************************************************/ +ST_UCHAR *a_get_rem_nsap (ST_LONG acse_conn_id); +ST_ULONG a_get_rem_ip_addr (ST_LONG acse_conn_id); + +/************************************************************************/ +/* Miscellaneous functions */ +/************************************************************************/ +ST_EVENT_SEM a_get_event_handles (ST_INT *pNumEntries); +int *a_get_event_handles_unix (ST_INT *pNumEntries); /* for UNIX-like systems*/ +ST_RET a_get_chan (ST_LONG acse_conn_id, ST_INT *chan_out); + + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* ACSE2USR_INCLUDED */ +/************************************************************************/ + diff --git a/include/inc/acseauth.h b/include/inc/acseauth.h new file mode 100644 index 0000000..0d600da --- /dev/null +++ b/include/inc/acseauth.h @@ -0,0 +1,120 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-2004, All Rights Reserved */ +/* */ +/* MODULE NAME : acseauth.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* ACSE Authentication header file. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/05/04 EJV 07 Added MACE_MECH_ID and PASWORD_MECH_ID defs. */ +/* 02/04/04 EJV 06 Removed extern maceMechId. */ +/* 08/20/03 EJV 05 Added extern maceMechId. */ +/* 07/08/03 EJV 04 Del old password auth (OBSOLETE_ACSE_AUTH) */ +/* 03/19/03 MDE 03 Added ACSE_AUTH_MECH_MACE_CERT */ +/* 03/13/03 EJV 02 Added asn1r.h. */ +/* 09/30/02 ASK 01 Created */ +/************************************************************************/ + +#ifndef ACSEAUTH_INCLUDED +#define ACSEAUTH_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "asn1r.h" /* for MMS_OBJ_ID */ + +/************************************************************************/ +/* New Authentication stuff */ +/************************************************************************/ +/*#define ACSE_MAX_LEN_PASSWORD 16*/ +/*renxiaobao mod*/ +#define ACSE_MAX_LEN_PASSWORD 32 + +typedef ST_INT16 ST_ACSE_AUTH; + +/* Authentication mechanisms MMS_OBJ_ID */ +#define PASS_MECH_ID {4, {2 ,2 ,3 ,1 }} + +#define MACE_MECH_ID \ + { 8, /* num_comps */ \ + { /* comps */ \ + 1, /* ??? */ \ + 0, /* ??? */ \ + 840, /* iso member-body usa */ \ + 0, /* ansi-t1-259-1997 */ \ + 1, /* stase */ \ + 0, /* stase-authentication value */ \ + 1, /* abstractSyntax */ \ + 1 /* version */ \ + } \ + } + +/* The ACSE user shall return one of the falling codes once they have */ +/* taken a look at the partner's ACSE_AUTH_INFO structure. */ + +/* These return codes map to the ABRT-diagnostic of the Abort PDU. */ +/* Returning any of these will result in an abort PDU being sent with */ +/* the specified diagnostic code. */ +#define ACSE_AUTH_SUCCESS 0 +#define ACSE_DIAG_NO_REASON 1 +#define ACSE_DIAG_PROTOCOL_ERROR 2 +#define ACSE_DIAG_AUTH_MECH_NAME_NOT_RECOGNIZED 3 +#define ACSE_DIAG_AUTH_MECH_NAME_REQUIRED 4 +#define ACSE_DIAG_AUTH_FAILURE 5 +#define ACSE_DIAG_AUTH_REQUIRED 6 + +/* Mechanism types */ +#define ACSE_AUTH_MECH_PASSWORD 0 +#define ACSE_AUTH_MECH_MACE_CERT 1 +#define ACSE_AUTH_MECH_OTHER 2 + +/* This structure is used for any mechanism data that must be */ +/* encoded/decoded by the user instead of the ACSE. */ +typedef struct + { + ST_INT len; /* Length of encoded data. */ + ST_UCHAR *ptr; /* Pointer to encoded data. */ + ST_UCHAR *buf; /* User buffer (chk_free'd if != NULL) */ + } USR_AUTH_BUFFER; + + +/* User-Supplied Authentication Structure */ +typedef struct + { + ST_BOOLEAN auth_pres; /* If this structure is filled out */ + ST_INT mech_type; /* One of the mechanism types, defined above */ + + union + { + struct + { + ST_CHAR password[ACSE_MAX_LEN_PASSWORD + 1]; + } pw_auth; + struct + { + MMS_OBJ_ID mech_id; /* User must set to desired id */ + USR_AUTH_BUFFER auth_value; /* User must encode/decode ASN.1 */ + } other_auth; + } u; + + } ACSE_AUTH_INFO; + + + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* ACSEAUTH_INCLUDED */ +/************************************************************************/ diff --git a/include/inc/adlc.h b/include/inc/adlc.h new file mode 100644 index 0000000..98d2932 --- /dev/null +++ b/include/inc/adlc.h @@ -0,0 +1,1021 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-2002, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : adlc.h */ +/* PRODUCT(S) : ADLC */ +/* */ +/* MODULE DESCRIPTION : */ +/* Function prototypes and commands definations as defined in */ +/* ISO/IEC 4335 for frame format */ +/* Note : For ADLC context packet refers to information passing with */ +/* stack while frame refers to information passing with Serial Manager */ +/* */ +/* This module can be divided into five parts */ +/* 1. First part deals with all the numeric defines and command defn */ +/* as in ISO specs */ +/* 2. This part deals with the defination of the data structures used */ +/* 3. This part has function like macros used to get and set various */ +/* fields */ +/* 4. This has the declaration of all the global variables as extern. */ +/* All the global variables are declared in adlc_var.c */ +/* 5. This part has the prototypes of global functions shared between */ +/* modules. All the functions are put separately according to the */ +/* module it belongs to */ +/* Note : For ADLC context packet refers to information passing with */ +/* stack while frame refers to information passing with Serial Manager */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/24/02 KCR 35 Added rdThreadError handling semaphore */ +/* 09/22/02 KCR 34 Added paranthesis to macros */ +/* 06/15/01 JRB 33 ipcChk* macros call chk_*, not x_chk_*. */ +/* 03/03/00 KCR 32 Exit Thread using events not TerminateThread() */ +/* 10/01/99 NAV 31 Added more SD_CONST modifiers */ +/* 09/13/99 MDE 30 Added SD_CONST modifiers */ +/* 04/20/98 IKE 29 Moved u_smp_record_time in Serial Manager */ +/* 03/05/98 IKE 28 Added Critical Sections to protect Adlc Data */ +/* Removed adlcIpcxxx functions */ +/* 02/04/98 IKE 27 Added deleteUIFramesFromTxList to fix bug */ +/* 10/20/97 IKE 26 Added addToListTime for Link Manager */ +/* 09/23/97 IKE 25 Added adlcExtWritePacket for define UCA_SMP */ +/* 09/18/97 IKE 24 Added telephone support */ +/* 07/16/97 IKE 23 Added device statistics and device filt log */ +/* 06/12/97 IKE 22 Made ADLC protocol transaction oriented */ +/* 05/12/97 IKE 21 Changed to MMSEASE 7.0 Data Types */ +/* 02/24/96 IKE 20 Removed #ifdef PLAIN_DOS and used ADLC_LM */ +/* define for ipc specific code */ +/* CFG_PORT also for DOS so multiple ports can */ +/* be initialized in dos platform */ +/* 02/03/97 IKE 19 adlcCfg per port basis */ +/* 01/23/97 IKE 18 Added txRxModeCounter for proper behaviour */ +/* of turnaround timers */ +/* 01/17/97 IKE 17 Added defn of initSiscoUtilGlbVarsForAdlc */ +/* and addToCfgPort */ +/* 12/03/96 IKE 16 WIN32 Support, header files cleanup */ +/* Added adlc_sm.h, some func prototypes for */ +/* adlc_tst.c */ +/* 11/15/96 IKE 15 Added adlcInitGlbVars */ +/* 11/06/96 IKE 14 Changed C++ style comments to C style */ +/* comments to make it more platform independent*/ +/* 10/28/96 KCR 13 Put ipcChkxxx macros to replace chk_xxx */ +/* 09/30/96 IKE 12 Moved adlc_stats from adlc.h to adlc_usr.h */ +/* so other apps could reference it */ +/* Added communicationMedia, put ifdef MASTER */ +/* in ADLC_CFG struct for members that were used*/ +/* for master only, added reconfigure option */ +/* 09/17/96 IKE 11 Added some struct members to ADLC_CFG_INFO */ +/* and ADLC_PORT_INFO structure */ +/* 08/22/96 IKE 10 Support for contention avoidance */ +/* Changed > to >= in CHECK_TIMEOUT macro */ +/* 08/16/96 IKE 09 Added rxMFramesList, vR and infoBufLen in */ +/* port struct (to make UI into INFO), added */ +/* turnaroundtime in cfg and device struct, */ +/* changed UPDATE_TIMEOUT */ +/* 08/05/96 IKE 08 Added connectAll to device struct, mode to */ +/* port struct and radioDelayTime to cfg struct */ +/* 07/17/96 IKE 07 Removed some lint and C6.00 warnings by type */ +/* casting to ST_UCHAR in some macros */ +/* 06/20/96 KCR 06 Increased MAX_ADLC_FRAME_LEN from 256 to 2048*/ +/* 06/18/96 IKE 05 Changed the type of configured timeout into */ +/* ST_DOUBLE. Added stackTaskId for DOS platform. */ +/* Changed time related macros to functions and */ +/* moved to module adlc_tm.c */ +/* 06/11/96 IKE 04 Added cnp_usr.h, frame timeout and SM_PUT */ +/* 05/22/96 IKE 03 Added defn for three types of run mode */ +/* Modified xxx_ADDR_FIELD_OFFSET. Put suffix */ +/* "ADLC_S" for link states for the ADLC */ +/* connection state machine */ +/* Added eventList and taskList */ +/* Added prototypes of added functions */ +/* 04/04/96 rkr 02 Cleanup */ +/* 07/18/95 IKE 01 Initial release. */ +/************************************************************************/ + +#ifndef _ADLC_H_ +#define _ADLC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gen_list.h" +#include "adlc_usr.h" +#if defined(ADLC_LM) +#include "adlc_ipc.h" +#endif +#include "adlc_log.h" +#include "adlc_sm.h" + +#if defined(ADLC_TESTING) +#include +#define ADLC_ASSERT(f) assert(f); +#else + #define ADLC_ASSERT(f) +#endif + +#if !defined(ADLC_LM) +/* At one time these macros called "x_chk_*" for DEBUG or */ +/* nonDEBUG, to be sure that the semaphore was locked. */ +/* Now "chk_*" always lock the sempaphore, so use them. */ +#define ipcChkCalloc(x,y) chk_calloc (x,y) +#define ipcChkMalloc(x) chk_malloc (x) +#define ipcChkFree(x) chk_free (x) +#endif + +#ifdef CNP +#include "cnp_usr.h" +#endif + +/************************************************************************/ +/* Constants related to configuration */ +/************************************************************************/ +#define MAX_ADLC_REQS 10 +#define MAX_ADLC_FRAME_LEN 2048 /* 2048 = 2035 + 11 + 2 */ + +/* Following are the run mode for ADLC Master */ +#define POLLED_MODE 0 +#define ENHANCED_POLLED_MODE 1 +#define CONTENTION_MODE 2 + +/* Following are the communication media for ADLC */ +#define CABLE_MEDIA 0 +#define RADIO_MEDIA 1 + +#define FRAME_FORMAT_TYPE3 0x9 /* used for polling */ +#define FRAME_FORMAT_TYPE4 0xA /* used for contention */ +#define MIN_ADLC_FRAME_LEN 11 /* Supervisory and Unnumbered */ +#define MIN_INFO_FRAME_LEN 13 + +#define SOF_FIELD_LEN 1 +#define SOF_FIELD_OFFSET 0 + +#define FORMAT_FIELD_LEN 2 +#define FORMAT_FIELD_OFFSET 1 + +#define DST_ADDR_FIELD_LEN 2 +#define DST_ADDR_FIELD_OFFSET 3 + +#define SRC_ADDR_FIELD_LEN 2 +#define SRC_ADDR_FIELD_OFFSET 5 + +#define CTRL_FILED_LEN 1 +#define CTRL_FIELD_OFFSET 7 + +#define CRC_FIELD_LEN 2 +#define CRC_FIELD_OFFSET 8 + +#define INFO_FIELD_OFFSET 10 + +#define EOF_FIELD_LEN 1 + + +#define PF_BIT 0x10 /* Poll / Final Bit */ +#define INFORMATION_FORMAT 0x00 /* last bit set to zero */ +#define INFO 0x00 /* Information */ + +#define SUPERVISORY_FORMAT 0x01 /* last bit = 1, 2nd last = 0 */ +#define RR 0x01 /* Receive Ready */ +#define RNR 0x05 /* Receive Not Ready */ +#define REJ 0x09 /* Reject */ + +#define UNNUMBERED_FORMAT 0x03 /* last two bits are set */ +#define UI 0x03 /* Unnumbered Information */ +#define SNRM 0x83 /* Set Normal Response */ +#define UA 0x63 /* Unnumbered Acknowledgment */ +#define DISC 0x43 /* Disconnect */ +#define RD 0x43 /* Request Disconnect */ +#define DM 0x0F /* Disconnect Mode */ +#define FRMR 0x87 /* Frame Reject */ + +/************************************************************************/ +/* flag attributes used when using function resetConnection */ +/************************************************************************/ +#define ADLC_DELETE_CON 1 +#define ADLC_RESET_ONLY 2 + +#if !defined(ADLC_LM) +/************************************************************************/ +/* used for global variable stackTaskId. We need to know in dos which */ +/* stack is linked to with ADLC to do different actions for different */ +/* stack */ +/* LM has this capability that it can run over both stacks at the same */ +/* time. and it will know by mapping the local address with task id */ +/************************************************************************/ +#define RLI_TASK_ID_RSGW 4 +#define RLI_TASK_ID_TRIM7 7 +#endif /* !ADLC_LM */ + +/************************************************************************/ +/* ADLC_CFG_INFO */ +/* */ +/************************************************************************/ +typedef struct tagAdlcCfgInfo + { + ST_INT modulus; + ST_INT frameLen; + ST_INT maxAdlcReqs; + ST_INT runMode; + ST_INT communicationMedia; + ST_INT retries; + ST_UCHAR sof; + ST_UCHAR eof; + ST_DOUBLE responseTimeout; /* refers to responseTimeout in port struct */ + ST_DOUBLE frameTimeout; /* refers to frameTimeout in port struct */ + ST_DOUBLE signalTimeout; /* refers to signalTimeout in port struct */ + ST_DOUBLE radioDekeyDelay; /* refers to signalTimeout in port struct */ + ST_DOUBLE radioStartOfTxDelay; /* refers to signalTimeout in port struct */ + ST_INT preambleLen; +#if defined(ADLC_MASTER) + ST_DOUBLE maxConnectRetryTimeout; + ST_DOUBLE deviceTurnaroundTime; /* refers to turnaround time in dev struct */ + ST_DOUBLE portTurnaroundTime; /* refers to turnaround time in port struct */ + ST_INT portUsage; +#endif /* ADLC_MASTER */ + } ADLC_CFG_INFO; + +/************************************************************************/ +/* ADLC_FRAME */ +/* */ +/* The following structure is used to read and write from the lower */ +/* layer (Serial Manager) */ +/************************************************************************/ +/* MMSOP_STATUS defines */ +#define STAT_STANDBY 0 +#define STAT_PROGRESS 1 +#define STAT_NACKED 2 +#define STAT_ACKED 3 + +typedef struct tagAdlcFrame + { + DBL_LNK p; /* required for link list operations */ + struct tagAdlcConInfo *cptr; /* Connection which it belongs to */ + ST_INT status; /* one of the above */ + ST_UCHAR cmd; + union + { + ST_UCHAR *infoBuf; + ST_UCHAR *redrBuf; + ST_UCHAR suprBuf[MIN_ADLC_FRAME_LEN]; + ST_UCHAR unumBuf[MIN_ADLC_FRAME_LEN]; + }u; + ST_INT infoLen; /* For info frame it is used for len of INFO msg */ + ST_INT frameLen; /* Total length of the frame including headers and trailers */ +#if defined(ADLC_LM) + DOUBLE addToListTime; +#endif + } ADLC_FRAME; + +/************************************************************************/ +/* ADLC_REQ */ +/* The following structure is to store one complete LSDU INFO */ +/* frame received from user application (Stack) */ +/************************************************************************/ +typedef struct tagAdlcReq + { + DBL_LNK p; /* required for link list operations */ +#if defined(ADLC_LM) + RLI_IPC_HDR hdr; /* IPC info including semaphore */ +#endif + struct tagAdlcConInfo *cptr; /* Connection which it belongs to */ + ADLC_FRAME *txIFramesList; /* Head to the segments of LSDU (small frames) */ + ST_ULONG usr1; /* user data - from original ADLC_CMD */ +#if defined(UCA_SMP) + ADLC_FRAME *txUIFramesList; /* Head to the segments of LSDU (small frames) */ + ST_LONG userId; +#endif + } ADLC_REQ; + +/************************************************************************/ +/* ADLC_CON_INFO */ +/* */ +/* ADLC connection information based on (Dn,Nn) where Dn represents */ +/* a device and Nn represents an OSI node */ +/************************************************************************/ +/* State Machine Design per connection for "state" */ +#define ADLC_S_DISCONNECT_PHASE 0 /* setting up data link */ +#define ADLC_S_LINK_DISCONNECT 1 /* setting up data link */ +#define ADLC_S_LINK_SETUP 2 /* setting up data link */ +#define ADLC_S_NORMAL 3 /* information transfer */ +#define ADLC_S_REMOTE_BUSY 4 /* information transfer */ +#define ADLC_S_SEND_REJECT 5 /* information transfer */ +#define ADLC_S_FRAME_REJECT 6 /* for slave only */ +#define ADLC_S_RESET 7 /* for slave only */ + +typedef struct tagAdlcConInfo + { + DBL_LNK p; /* required for link list operations */ + ST_UINT16 masterAddr; /* ISO node address */ + ST_INT txRxMode; /* TX_MODE or RX_MODE */ + struct tagAdlcDevInfo *dptr; /* ADLC device structure pointer */ + struct tagAdlcPortInfo *pptr; /* port which it belongs to */ + ST_INT state; /* Connection state defined above */ + ST_UCHAR vR; /* Receive State Variable */ + ST_UCHAR vS; /* Send State Variable */ + ST_UCHAR sendCount; /* How many frames we have sent */ + ST_INT infoBufLen; /* Length of info message for rxIFramesList */ + ST_INT txAdlcReqCount; /* How many write request ?? */ + ST_INT retries; /* How many retries are allowed */ + ADLC_FRAME *rxIFramesList; /* Info frames which are not complete LSDU */ +#if defined(ADLC_MASTER) + ST_DOUBLE connectRetryTimeout; /* To store the time when we will try to reconnect */ +#endif +#if defined(UCA_SMP) + ST_INT txExtAdlcReqCount; /* How many write request ?? */ + ADLC_FRAME *rxUIFramesList; /* Info frames which are not complete LSDU */ + ST_INT extInfoBufLen; /* Length of ui message for rxUIFramesList */ +#endif + } ADLC_CON_INFO; +/************************************************************************/ +/* ADLC_DEV_INFO */ +/* */ +/* Tracking structure for device. This is the main entry point to */ +/* reference to almost any device related info. This will be allocated */ +/* at the startup when reading from configuration file */ +/************************************************************************/ +#define MAX_DEV_NAME_SIZE 80 + +/* Mode could be one of the following */ +/* ADLC slave will only have two modes TX_MODE and RX_MODE */ +/* Slave will initially be at RX_MODE. It will go to TX_MODE when he */ +/* sees the P/F bit and after transmission it will go back to RX_MODE */ +/* In case of timeout it will remain in RX_MODE */ +/* ADLC master will initially be in TX_MODE. It will go in RX_MODE only */ +/* when it expects the response back from the slave. In case of timeout */ +/* it will go back to TX_MODE. */ +#define TX_MODE 0 +#define RX_MODE 1 + +typedef struct tagAdlcDevInfo + { + DBL_LNK p; /* required for link list operations */ + ST_CHAR name[MAX_DEV_NAME_SIZE+1]; /* storage for device name */ + ST_UINT16 address; /* Device's 16-bit address */ + ST_INT txRxMode; /* TX_MODE or RX_MODE */ + struct tagAdlcPortInfo *pptr; /* port which it belongs to */ + ADLC_CON_INFO *conList; +#if defined(ADLC_MASTER) + ST_INT pollGroup; /* 1 to MAX_POLL_GROUPS */ + ST_BOOLEAN connectAll; /* flag only used in adlcConnectAll() */ + ST_DOUBLE turnaroundTime; +#if defined(ADLC_LM) + ST_INT txRxModeCounter; /* for proper behaviour of turnaround timer */ +#endif /* ADLC_LM */ +#endif /* ADLC_MASTER */ +#if defined(ADLC_LM) + ADLC_DEV_STATS devStats; +#endif /* ADLC_LM */ + } ADLC_DEV_INFO; + +/************************************************************************/ +/* ADLC_PORT_INFO */ +/* */ +/* Tracking structure for network */ +/* will be allocated at the startup when reading from configuration file*/ +/* */ +/* txRxMode : is either TX_MODE or RX_MODE. */ +/* For master It is used in code in the following three ways */ +/* pptr->txRxMode = RX_MODE when p/f bit given to a slave */ +/* pptr->txRxMode = TX_MODE when port turnaround time or timeout has */ +/* elapsed */ +/* For slave It is used in code in the following three ways */ +/* pptr->txRxMode = TX_MODE when p/f is received from master */ +/* pptr->txRxMode = RX_MODE when p/f bit given from slave */ +/* if pptr->txRxMode == TX_MODE to see if we got p/f from master */ +/* runMode : is POLLED_MODE, ENHANCED_POLLED_MODE or CONTENTION_MODE */ +/* The idea is when runMode is configured in CONTENTION_MODE, then */ +/* pptr->runMode can change dynamically else pptr->runMode will remain */ +/* same as configured runMode (i.e. ADLC_RUN_MODE(pptr)) */ +/* For slave it is used in the following ways */ +/* pptr->runMode = POLLED_MODE when p/f is received from master */ +/* pptr->runMode = CONTENTION_MODE when p/f bit given from slave */ +/* if pptr->runMode == CONTENTION_MODE to encode the frame format */ +/* For Master it is used in the following ways */ +/* pptr->runMode = ENHANCED_POLLED_MODE when dcd is high most of times */ +/* pptr->runMode = CONTENTION_MODE when RR frames are more than INFO */ +/* if pptr->runMode == CONTENTION txStateService is called else */ +/* txService is called */ +/************************************************************************/ +/* States for getting the frame from the port used in "rxState" */ +#define STATE_WAIT_SOF 0 +#define STATE_WAIT_LEN 1 +#define STATE_WAIT_CRC 2 +#define STATE_WAIT_DATA 3 +#define STATE_WAIT_EOF 4 + +/* States for slave tranmit algorithm used in "signalState" */ +#define SL_TX_STATE_IDLE 0 +#define SL_TX_STATE_PF_RCVD 1 +#define SL_TX_STATE_WAIT_FOR_CTS_HIGH 2 +#define SL_TX_STATE_START_OF_TX_DELAY 3 +#define SL_TX_STATE_OK_TO_TX 4 +#define SL_TX_STATE_WAIT_FOR_TX_BUF_EMPTY 5 +#define SL_TX_STATE_DEKEY_DELAY 6 +#define SL_TX_STATE_WAIT_FOR_CTS_LOW 7 +#define SL_TX_STATE_UNSOL_TX 8 +#define SL_TX_STATE_WAIT_FOR_LINK 9 +#define SL_TX_STATE_START_OF_UNSOL_TX_DELAY 10 +#define SL_TX_STATE_OK_TO_UNSOL_TX 11 + +/*States for master tranmit in contention used in "signalState" */ +#define MA_TX_STATE_IDLE 0 +#define MA_TX_STATE_WAIT_FOR_CTS_HIGH 1 +#define MA_TX_STATE_WAIT_FOR_DCD_LOW 2 +#define MA_TX_STATE_OK_TO_TX 3 +#define MA_TX_STATE_WAIT_FOR_TX_BUF_EMPTY 4 +#define MA_TX_STATE_DEKEY_DELAY 5 +#define MA_TX_STATE_WAIT_FOR_CTS_LOW 6 +#define MA_TX_STATE_WAIT_FOR_CTS_HIGH_DCD_LOW 7 +typedef struct tagAdlcPortInfo + { + DBL_LNK p; /* required for link list operations */ + ST_INT port; /* digiboard port ID */ + ST_INT rxState; /* receive state */ + ST_UCHAR *rxBuf; + ST_UINT rxLen; + ADLC_CON_INFO *outstandingCptr; /* At one time only one con. have P/F set */ + ADLC_DEV_INFO *devList; /* linked list of devices associated with this port */ + ADLC_REQ *txAdlcReqList; /* linked list of write packet list from stack */ + ADLC_FRAME *txUFramesList; /* linked list of unnumbered frames */ + ADLC_FRAME *txSFramesList; /* linked list of supervisory frames */ + ADLC_FRAME *txMFramesList; /* linked list of multicast frames to tx */ + ADLC_FRAME *rxMFramesList; /* linked list of multicast frames to rx not complete LSDU */ + ST_UCHAR vR; /* receive state variable for multicast frames */ + ST_INT infoBufLen; /* Length of info message for rxMFramesList */ + ST_DOUBLE responseTimeout; /* The time request with P/F set was sent */ + ST_INT signalState; /* used for transmit algorithm */ + ST_DOUBLE signalTimeout; /* used for transmit algorithm */ + ST_INT txRxMode; /* TX_MODE or RX_MODE */ + ST_INT runMode; /* POLLED_MODE, ENHANCED_POLLED_MODE or CONTENTION_MODE */ + ADLC_CFG_INFO adlcCfg; +#if defined(ADLC_MASTER) + ADLC_FRAME *txRFramesList; /* linked list of redirect frames */ + ST_DOUBLE turnaroundTime; + ST_ULONG rxInfo; /* Received INFO frames used for switching modes*/ + ST_ULONG rxRr; /* Received RR frames used for switching modes*/ + ST_ULONG txInfo; /* Transmitted INFO frames used for transmit algorithm */ + ST_ULONG txRr; /* Transmitted RR frames used for transmit algorithm */ + ST_BOOLEAN bTxRrFlag; /* should RR have higher priority than INFO ? */ + ST_DOUBLE lastSnrmTime; /* the recorded time when last snrm was sent */ + ST_INT prQueArray[12]; /* array of int which will store priority order */ +#endif +#if defined(ADLC_LM) + HEV txDoneSem; /* sem to wait on the sm to be waited */ + HEV frameArrivalSem; /* sem to wait for frame to rx */ + HEV frameInListSem; /* sem to wait for frame to tx */ + HEV rdThreadErrSem; /* sem to clean up from read thread error */ + ST_BOOLEAN bPortBusy; /* if true - tx is pending */ +#if defined(ADLC_MASTER) + HTIMER hTxStateTimer; /* used in txStateService to drive state mach */ + ST_INT txRxModeCounter; /* for proper behaviour of turnaround timer */ +#endif /* ADLC_MASTER */ +#endif /* ADLC_LM */ +#if !defined(ADLC_LM) + ST_DOUBLE frameTimeout; +#endif +#if defined(UCA_SMP) + ADLC_REQ *txExtAdlcReqList; /* linked list of ext write packet list from stack */ + ST_CHAR recTime[SMP_SIZE_OF_REC_TIME]; /* buffer to hold time stamp */ +#endif + } ADLC_PORT_INFO; + +#if defined(ADLC_MASTER) +/************************************************************************/ +/* POLLED_DEV */ +/* */ +/* Link Manager Polling Structure */ +/************************************************************************/ + +typedef struct tagPolledDevices + { + DBL_LNK l; /* gen list link */ + ADLC_DEV_INFO *dptr; /* pointer to device structure */ + ST_BOOLEAN bSuspendPolling; /* don't poll this one for a while */ + } POLLED_DEV; + +/************************************************************************/ +/* POLL_GROUP */ +/* */ +/************************************************************************/ +#define FIRST_POLL_GROUP 1 +#define MAX_POLL_GROUPS 3 + +/* assume that pollGrpID's start at 1 and go up to MAX_POLL_GROUPS */ +/* assume that poll group 1 is polled most frequently and poll group */ +/* MAX_POLL_GROUPS is polled least frequently. */ +/* when requested to change the poll rate for a device, change the poll */ +/* group for the device - increment poll group to decrease polling or */ +/* decrement poll group to increase poll frequency */ + +typedef struct tagPollGroup + { + DBL_LNK l; /* gen list link */ + ST_INT pollGrpID; /* a unique int 1 to MAX_POLL_GROUPS */ + ST_DOUBLE pollRate; /* in m seconds from config file */ + POLLED_DEV *pollDevList; /* a linked list of devices to poll */ +#if !defined(ADLC_LM) + ST_DOUBLE pollTime; /* To store the time of last poll */ +#endif +#if defined(ADLC_LM) + HTIMER hTimer; /* used in MuxWaitSem to trigger poll */ +#endif + } POLL_GROUP; + +#endif /* ADLC_MASTER */ + +#if defined(ADLC_LM) +/************************************************************************/ +/* ADLC_TASK_INFO */ +/* */ +/************************************************************************/ +typedef struct tagAdlcTaskInfo + { + DBL_LNK l; /* gen list link */ + ST_UINT16 localAddr; + HQUEUE qHandle; + ST_INT taskId; +/* PID pid; */ + } ADLC_TASK_INFO; + +/************************************************************************/ +/* ADLC_FILTER_DEV_LOG_INFO */ +/* */ +/************************************************************************/ +typedef struct tagAdlcFilterDevLogInfo + { + ST_UINT16 address; + ST_BOOLEAN bFilter; + ST_ULONG saveIoLogMask; + } ADLC_FILTER_DEV_LOG_INFO; + +#endif /* ADLC_LM */ + +#if !defined(ADLC_LM) +/************************************************************************/ +/* ADLC_EVENT_INFO */ +/* */ +/************************************************************************/ +typedef struct tagAdlcEventInfo + { + DBL_LNK l; /* gen list link */ + ST_INT adlcEventOp; + ST_INT adlcRetCode; + ST_VOID *adlcEventCb; + } ADLC_EVENT_INFO; +#endif +/************************************************************************/ +/* Function like macros to get and set various fields */ +/************************************************************************/ +/* This macro gets the frame format from the frame */ +#define FRAME_FORMAT_GET(frame) ((frame[1] << 8) | (frame[2])) + +/* This macro gets the length of the frame from the frame */ +#define FRAME_LEN_GET(frame) (((frame[1] << 8) | (frame[2])) & 0x07FF) + +/* This macro sets the length of the frame in the frame format field */ +#define FRAME_LEN_SET(x,r) (x = ((x) & 0xF800) | ((r) & 0x07FF)) + +/* This macro gets the type of the frame from the frame */ +#define FRAME_TYPE_GET(frame) (ST_UCHAR) (frame[1] >> 4) + +/* This macro sets the type of the frame in the frame format field */ +#define FRAME_TYPE_SET(x,y) (x = ((x) & 0x0FFF) | ((y) << 12)) + +/* This macro gets the eos bit from the frame */ +#define EOS_GET(frame) (frame[1] & 0x08) + +/* This macro sets the eos in the frame format field */ +#define EOS_SET(x) (x = ((x) & 0xF7FF)) + +/* This macro gets the destination address from the frame */ +#define DST_ADDR_GET(frame) (ST_UINT16) (frame[3] << 8 | frame[4]) + +/* This macro gets the source address from the frame */ +#define SRC_ADDR_GET(frame) (ST_UINT16) (frame[5] << 8 | frame[6]) + +/* This macro gets the device address from the receing frame */ +#if defined(ADLC_MASTER) +#define DEV_ADDR_GET(frame) SRC_ADDR_GET(frame) +#endif +#if defined(ADLC_SLAVE) +#define DEV_ADDR_GET(frame) DST_ADDR_GET(frame) +#endif + +/* This macro gets the control byte from the frame */ +#define CTRL_BYTE_GET(frame) (frame[7]) + +/* This macro gets the Poll Final Bit from the control byte */ +#define PF_GET(x) ((x) & 0x10) /* Poll Final Bit get */ + +/* This macros tells to have a poll/final bit depending on frame type */ +#define PF_DECIDE(frameType) (frameType == FRAME_FORMAT_TYPE3 ? PF_BIT : 0x0) + +/* This macro sets the Poll Final Bit in the control byte */ +#define PF_SET(x) (x = (x) | (ST_UCHAR) 0x10) /* Poll Final Bit set */ + +/* These get the code from the control byte including the format type */ +#define UNUM_CODE_GET(x) (ST_UCHAR) ((x) & 0xEF) +#define SUPR_CODE_GET(x) (ST_UCHAR) ((x) & 0x0F) +#define INFO_CODE_GET(x) (ST_UCHAR) ((x) & 0x01) + + +/* These macros get the N(R) and N(S) in an info command. */ +#define INFO_NR_GET(x) (ST_UCHAR) (((x) & 0xE0) >> 5) +#define INFO_NS_GET(x) (ST_UCHAR) (((x) & 0x0E) >> 1) + +/* These macros alter the N(R) and N(S) in an info command. */ +#define INFO_NS_SET(x,r) (x = (x) | (ST_UCHAR) ((r) << 1)) +#define INFO_NR_SET(x,r) (x = (x) | (ST_UCHAR) ((r) << 5)) + +/* This macro gets the N(R) in a supervisory command. */ +#define SUPR_NR_GET(x) (ST_UCHAR) (((x) & 0xE0) >> 5) + +/* This macro alters the N(R) in a supervisory command. */ +#define SUPR_NR_SET(x,r) (x = (x) | (ST_UCHAR) ((r) << 5)) + +/* This macro gets the crc from the frame */ +#define FRAME_CRC_GET(frame,offset) ((frame[offset] << 8) | (frame[offset + 1])) + + +/* This macro rotates the bytes in unsigned int */ +#define ROTATE(x) { ST_UINT16 tmp;\ + tmp = (x) & 0xFF;\ + x = (x) >> 8;\ + x |= tmp << 8;\ + } + +/* Modulo-N increment and decrement macros */ +#define DEC_MODULO_N(x,y,z) (ST_UCHAR) (((x) >= (y)) ? ((x) - (y)) : (((x) + (z)) - (y))) +#define INC_MODULO_N(x,y,z) (ST_UCHAR) (((x) + (y)) % (z)) +#define DIFF_MODULO_N(x,y,z) (ST_UCHAR) (((x) >= (y)) ? (x) - (y) : ((x) + (z)) - (y)) + +/* if the most significant bit is set it is either broadcast or multicast */ +#define IS_MULTICAST_ADDR(x) ((x) & 0x8000) + +/* if the bit 13 is not set it is a remote address */ +#define IS_REMOTE_ADDR(x) !((x) & 0x2000) + +/* Used to change port=0 into COM1, port=1 into COM2 etc. */ +#define GET_COM_NO(x) ((x) + 1) + +/* Time Management Macros */ +#define START_TIMEOUT(x,y) (x = sGetMsTime() + (y)) +#define UPDATE_TIMEOUT(x,y) if (x) x = sGetMsTime() + (y) +#define STOP_TIMEOUT(x) (x = 0.0) +#define CHECK_TIMEOUT(x) ((x) && (sGetMsTime() >= (x))) +#define IS_TIMEOUT_ENABLED(x) (x) +#define IS_TIMEOUT_DISABLED(x) !(x) + +/* Macros to work on ADLC_CFG_INFO structure */ +#define ADLC_MODULUS(x) x->adlcCfg.modulus +#define ADLC_FRAME_LEN(x) x->adlcCfg.frameLen +#define ADLC_INFO_LEN(x) (x->adlcCfg.frameLen - MIN_INFO_FRAME_LEN) +#define ADLC_MAX_ADLC_REQS(x) x->adlcCfg.maxAdlcReqs +#define ADLC_RUN_MODE(x) x->adlcCfg.runMode +#define ADLC_COMMUNICATION_MEDIA(x) x->adlcCfg.communicationMedia +#define ADLC_RETRIES(x) x->adlcCfg.retries +#define ADLC_SOF(x) x->adlcCfg.sof +#define ADLC_EOF(x) x->adlcCfg.eof +#define ADLC_RESPONSE_TIMEOUT(x) x->adlcCfg.responseTimeout +#define ADLC_FRAME_TIMEOUT(x) x->adlcCfg.frameTimeout +#define ADLC_SIGNAL_TIMEOUT(x) x->adlcCfg.signalTimeout +#define ADLC_RADIO_DEKEY_DELAY(x) x->adlcCfg.radioDekeyDelay +#define ADLC_RADIO_START_OF_TX_DELAY(x) x->adlcCfg.radioStartOfTxDelay +#define ADLC_PREAMBLE_LEN(x) x->adlcCfg.preambleLen + +#if defined(ADLC_MASTER) +#define ADLC_MAX_CONNECT_RETRY_TIMEOUT(x) x->adlcCfg.maxConnectRetryTimeout +#define ADLC_DEVICE_TURNAROUND_TIME(x) x->adlcCfg.deviceTurnaroundTime +#define ADLC_PORT_TURNAROUND_TIME(x) x->adlcCfg.portTurnaroundTime +#define ADLC_PORT_USAGE(x) x->adlcCfg.portUsage +#endif /* ADLC_MASTER */ + +#if defined(CNP) +/* This macro checks if there is data on port and it gives the char else -1 */ +#define RX_BYTE(port) ((cnp_cnt (port)) ? cnp_getc (port) : -1 ) + +/* This macro puts the data on the port */ +#define SM_PUT(a,b,c) cnp_put(a,b,c) +#else + +#define RX_BYTE(port) ((sm_rx_cnt (port)) ? sm_getc (port) : -1 ) +#define SM_PUT(a,b,c) sm_put(a,b,c) + +#endif /* CNP */ + +#ifdef ADLC_TESTING + +/* Macro to get a random integer within a specified range */ +#define GET_RANDOM_BETWEEN( min, max ) ((rand() % (int)(((max)+1) - (min))) + (min)) + +/* Macro to get one random value out of two */ +#define GET_RANDOM_OF(val1,val2) (rand() < RAND_MAX / 2 ? val1 : val2) + +#endif +/************************************************************************/ +/* Global Variables Declarations */ +/************************************************************************/ +extern ADLC_CFG_INFO adlcCfg; +extern ADLC_PORT_INFO *portList; +extern CFG_PORT *portConfigList; +extern const ST_UINT16 adlc_crc_table[256]; +extern ADLC_STATS adlcStats; +extern ST_BOOLEAN terminateFlag; + +#if defined(ADLC_MASTER) +extern POLL_GROUP *pollGroupList; +extern ST_ULONG gRrFrames; +extern ST_ULONG gInfoFrames; +#endif + +#if defined(ADLC_ERROR) +extern ADLC_ERROR_INFO adlcError; +#endif + +#if !defined(ADLC_LM) +extern ADLC_EVENT_INFO *eventList; +extern ST_INT stackTaskId; +#endif + +#if defined(ADLC_LM) +extern ADLC_TASK_INFO *taskList; +extern ST_INT connectedTask[RLI_TASK_ID_LAST + 1]; +extern ST_INT serMgrSleep; +extern PID myPID; +extern ADLC_FILTER_DEV_LOG_INFO stFiltDevLog; +extern CRITICAL_SECTION protectAdlcData; /* to guard adlc data between threads */ +#endif +/************************************************************************/ +/* Global Functions Declarations */ +/* make the following functions static if you can */ +/************************************************************************/ +/* adlc_utl.c */ +ST_UCHAR eventTypeOf(ST_UCHAR ctrlByte); +ST_VOID timeout_error (ADLC_CON_INFO *cptr); +ST_VOID resetConnection (ADLC_CON_INFO *cptr,ST_INT attrib); +ST_VOID resetStateVarsForConnection(ADLC_CON_INFO *cptr); +ST_RET verifyCrc(ST_UCHAR *frame, ST_UINT frameLen); +ST_UINT16 calcCrc (ST_UCHAR *data, ST_UINT length); + +ADLC_PORT_INFO *getPortPtrFromPort(ST_INT port); +ADLC_DEV_INFO *getDevPtrFromAddress(ST_UINT16 addr); +ADLC_DEV_INFO *getDevPtrFromName(ST_CHAR *name); +ADLC_CON_INFO *getConPtrFromAddrPair(ST_UINT16 slaveAddr,ST_UINT16 masterAddr); +ADLC_CON_INFO *getConPtrFromDptr(ADLC_DEV_INFO *dptr,ST_UINT16 masterAddr); + +ADLC_PORT_INFO *addToPortList(ST_INT port, const ADLC_CFG_INFO *pstAdlcCfg); +CFG_PORT *addToCfgPortList(ST_INT port); +ADLC_DEV_INFO *addToDevList(ADLC_PORT_INFO *pptr, ST_CHAR *name, + ST_UINT16 address,ST_INT pollGroup,ST_BOOLEAN connectAll); +ADLC_CON_INFO *addToConList(ADLC_DEV_INFO *dptr,ST_UINT16 masterAddr); +ST_VOID addToSFramesList(ADLC_CON_INFO *cptr, ST_UCHAR cmd); +ST_VOID addToUFramesList(ADLC_CON_INFO *cptr, ST_UCHAR cmd); +ST_VOID addToRFramesList(ADLC_PORT_INFO *pptr); +ST_VOID addToMFramesInTxList(ST_UINT16 srcAddr,ST_UINT16 dstAddr, ST_VOID *data, ST_INT dataLen); +ST_VOID addToMFramesInRxList(ADLC_PORT_INFO *pptr,ST_UCHAR *data,ST_INT dataLen); +ADLC_REQ *addToReqList(ADLC_CON_INFO *cptr); +ST_VOID addToIFramesInTxList(ADLC_REQ *rptr,ST_UCHAR *data,ST_INT len); +ST_VOID addToIFramesInRxList(ADLC_CON_INFO *cptr,ST_UCHAR *data,ST_INT len); + +ST_VOID deleteAllConnections(ADLC_DEV_INFO *dptr); +ST_VOID deleteConnection(ADLC_CON_INFO *cptr); +ST_VOID deleteDevice(ADLC_DEV_INFO *dptr); +ST_VOID deletePort(ADLC_PORT_INFO *pptr); +ST_VOID deleteCfgPort(CFG_PORT *pstCfgPort); +ST_VOID deleteAllFrames(ADLC_CON_INFO *cptr); +ST_VOID deleteSFramesList(ADLC_CON_INFO *cptr); +ST_VOID deleteSFramesListWithoutPf(ADLC_CON_INFO *cptr); +ST_VOID deleteUFramesList(ADLC_CON_INFO *cptr); +ST_VOID deleteIFramesFromRxList(ADLC_CON_INFO *cptr); +ST_VOID deleteIFramesFromTxList(ADLC_CON_INFO *cptr); +ST_VOID deleteMFramesFromTxList(ADLC_PORT_INFO *pptr); +ST_VOID deleteMFramesFromRxList(ADLC_PORT_INFO *pptr); +ST_VOID deleteAckedIFramesFromTxList(ADLC_CON_INFO *cptr,ST_UCHAR nR); +ST_VOID deleteFrame(ADLC_FRAME *fptr,ADLC_FRAME **framesList); +ST_VOID deleteReqFrame (ADLC_REQ *rptr); + +ST_BOOLEAN isDevPtrValid(ADLC_DEV_INFO *rDptr); +ST_VOID nackAllIFramesFromTxList(ADLC_CON_INFO *cptr); +ST_BOOLEAN isInfoQueuedUp(ADLC_CON_INFO *cptr); +ST_BOOLEAN isPollQueuedUp(ADLC_CON_INFO *cptr); +ST_BOOLEAN isUFrameQueuedUp(ADLC_CON_INFO *cptr); +ST_BOOLEAN isOkToPoll(ADLC_CON_INFO *cptr); +ST_BOOLEAN isOkToSendUnum(ADLC_CON_INFO *cptr,ST_BOOLEAN justCheck); +ST_BOOLEAN isOkToSendSupr(ADLC_CON_INFO *cptr,ST_BOOLEAN justCheck); +ST_BOOLEAN isOkToSendInfo(ADLC_CON_INFO *cptr,ST_BOOLEAN justCheck); +ST_BOOLEAN isOkToSendMult(ADLC_PORT_INFO *pptr,ST_BOOLEAN justCheck); +ST_BOOLEAN isConStateInInfoTransfer(ADLC_CON_INFO *cptr); +ST_VOID getPfAndEosBit(ADLC_FRAME *nextFptr,ST_UCHAR sendCount, + ST_BOOLEAN *pfBit,ST_BOOLEAN *eosBit, ADLC_PORT_INFO *pptr); +ST_VOID adlc_except (SD_CONST ST_CHAR *file, ST_INT line); +ST_UINT16 getLocalAddr(ADLC_CON_INFO *cptr); +ST_UINT16 getRemoteAddr(ADLC_CON_INFO *cptr); +CFG_PORT *findCfgPort(ST_INT port); +ST_VOID adlcEndLogging (ST_VOID); + +#if defined(ADLC_MASTER) +POLL_GROUP *findPollGroup(ST_INT pollGrpID); +POLL_GROUP *addToPollGroupList(ST_INT pollGrpID,ST_DOUBLE pollRate); +ST_RET addDevToPollGrp(ADLC_DEV_INFO *dptr,ST_INT pollGroup); +POLLED_DEV *findPolledDevByName(char *devName); +POLLED_DEV *findPolledDevByAddress(ST_UINT16 addr); +#endif + +/* adlc_dec.c */ +ST_RET getFrame(ADLC_PORT_INFO *pptr); +ST_RET processAdlcFrame(ADLC_PORT_INFO *pptr); +ST_VOID giveIndicationToStack (ADLC_CON_INFO *cptr,ST_INT opcode,ST_RET retCode, ST_LONG usr1); + +/* adlc_enc.c */ +ST_RET send_info_frame(ADLC_FRAME *fptr,ST_BOOLEAN pfBit,ST_BOOLEAN eosBit); +ST_RET send_supr_frame(ADLC_FRAME *fptr); +ST_RET send_unum_frame(ADLC_FRAME *fptr); +ST_RET send_ui_frame(ADLC_FRAME *fptr); +ST_RET send_redr_frame(ADLC_FRAME *fptr,ADLC_PORT_INFO *pptr); +ST_RET send_mult_frame(ADLC_FRAME *fptr,ADLC_PORT_INFO *pptr); +ST_VOID enc_adlc_frame(ST_UCHAR *frame,ST_UINT16 srcAddr,ST_UINT16 dstAddr,ST_UCHAR ctrlByte, + ST_UINT16 frameFormat,ST_INT dataLen, ADLC_PORT_INFO *pptr); +ST_UINT16 getFrameFormat(ST_INT frameLen,ST_BOOLEAN eosBit,ST_UCHAR frameType); + +/* adlc_ssv.c adlc_msv.c */ +ST_VOID adlcService(ST_VOID); +ST_BOOLEAN checkTxService(ADLC_PORT_INFO *pptr); +ST_VOID txService(ADLC_PORT_INFO *pptr); +ST_VOID rxService(ADLC_PORT_INFO *pptr); +ST_VOID txStateService(ADLC_PORT_INFO *pptr); +ST_VOID timeoutService(ADLC_PORT_INFO *pptr); +ST_VOID stopWaitingForResp(ADLC_CON_INFO *cptr, ST_BOOLEAN bResetRetries); + +#if defined(ADLC_SLAVE) +ST_VOID startSignalTimeout(ADLC_PORT_INFO *pptr); +ST_VOID stopSignalTimeout(ADLC_PORT_INFO *pptr); +ST_BOOLEAN checkSignalTimeout(ADLC_PORT_INFO *pptr); +ST_VOID goInTxMode(ADLC_CON_INFO *cptr); +ST_VOID goInRxMode(ADLC_CON_INFO *cptr); +ST_VOID waitForResponse(ADLC_CON_INFO *cptr); +#endif /* ADLC_SLAVE */ + +#if defined(ADLC_MASTER) +ST_VOID pollDevice(ADLC_DEV_INFO *dptr); +ST_VOID pollConnection(ADLC_CON_INFO *cptr); +ST_VOID waitForResponse(ADLC_CON_INFO *cptr); +ST_VOID startConRetryTimeout(ADLC_CON_INFO *cptr); +ST_BOOLEAN checkConRetryTimeout(ADLC_CON_INFO *cptr); +ST_VOID stopConRetryTimeout(ADLC_CON_INFO *cptr); +ST_VOID startDeviceTurnaroundTimeout(ADLC_DEV_INFO *dptr); +ST_BOOLEAN checkDeviceTurnaroundTimeout(ADLC_DEV_INFO *dptr); +ST_VOID stopDeviceTurnaroundTimeout(ADLC_DEV_INFO *dptr); +ST_VOID startPortTurnaroundTimeout(ADLC_PORT_INFO *pptr); +ST_BOOLEAN checkPortTurnaroundTimeout(ADLC_PORT_INFO *pptr); +ST_VOID stopPortTurnaroundTimeout(ADLC_PORT_INFO *pptr); +ST_RET startPollTimer(POLL_GROUP *pstPollGrp); +ST_RET updatePollTimer(POLL_GROUP *pstPollGrp); +ST_RET stopPollTimer(POLL_GROUP *pstPollGrp); +ST_BOOLEAN checkPollTimer(POLL_GROUP *pstPollGrp); +ST_RET pollInit(ST_VOID); + +ST_VOID triggerLogicAnalyzer(ST_INT port); +#endif /* ADLC_MASTER */ + +/* adlc_tm.c */ +ST_VOID startRespTimeout(ADLC_PORT_INFO *pptr); +ST_VOID updateRespTimeout(ADLC_PORT_INFO *pptr); +ST_VOID stopRespTimeout(ADLC_PORT_INFO *pptr); +ST_BOOLEAN checkRespTimeout(ADLC_PORT_INFO *pptr); +ST_BOOLEAN isRespTimeoutEnabled(ADLC_PORT_INFO *pptr); +ST_BOOLEAN isRespTimeoutDisabled(ADLC_PORT_INFO *pptr); +ST_VOID startSignalTimeout(ADLC_PORT_INFO *pptr); +ST_VOID updateSignalTimeout(ADLC_PORT_INFO *pptr); +ST_VOID stopSignalTimeout(ADLC_PORT_INFO *pptr); +ST_BOOLEAN checkSignalTimeout(ADLC_PORT_INFO *pptr); +ST_VOID startRadioDelayTimeout(ADLC_PORT_INFO *pptr); +ST_VOID startFrameTimeout(ADLC_PORT_INFO *pptr); +ST_BOOLEAN checkFrameTimeout(ADLC_PORT_INFO *pptr); +ST_VOID stopFrameTimeout(ADLC_PORT_INFO *pptr); +ST_VOID time_delay (ST_DOUBLE tme); + +/* adlc_log.c */ +ST_VOID logAdlcStats(ST_VOID); + +/* adlc_get.c */ +ST_CHAR *getCommandName(ST_UCHAR ctrlByte); +ST_CHAR *getConState(ST_INT state); +ST_CHAR *getTxRxMode(ST_INT mode); +ST_CHAR *getRunMode(ST_INT mode); +ST_CHAR *getCommunicationMedia(ST_INT media); +ST_CHAR *getOpCode(ST_INT opcode); +ST_CHAR *getRetCode(ST_RET retCode); +ST_CHAR *getSignalState(ST_INT signalState); + +/* adlc_var.c */ +ST_VOID adlcInitGlbVars(ST_VOID); +ST_VOID initSiscoUtilGlbVarsForAdlc(ST_VOID); + +/* adlc_lsm.c */ +ST_VOID rdThreadErrorHandling(ADLC_PORT_INFO *pptr); + +/* adlc_cfg.c adlc_odb.c adlc_hc.c */ +ST_RET adlcConfigure (ST_VOID); +#if defined(ADLC_LM) +ST_RET adlcReConfigure (ST_VOID); +ST_RET updateAdlcLoggingParameters(ST_VOID); +ST_RET updateAdlcPollParameters(ST_UINT hi,ST_UINT med, ST_UINT low); +ST_RET adlcCloseDatabase (ST_VOID); +#endif + +/* adlc_tst.c */ +#ifdef ADLC_TESTING +ST_VOID testSetMain (ST_VOID); +ST_VOID switchMenu(ST_VOID); +ST_VOID memCheckError (ST_VOID); +ST_VOID screenLogFun (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); +ST_VOID doEnableScreenLog (ST_VOID); +ST_VOID doDisableScreenLog (ST_VOID); +#if defined(__OS2__) +extern HEV o_kbd_event_sem; +#endif +#if defined(_WIN32) +extern HEV kbdEvent; +#endif +#if defined(ADLC_LM) +ST_RET handleKeyboardEvent(ST_ULONG userId, ST_ULONG postCount); +ST_RET testStartKeyboard (ST_VOID); +ST_RET testEndKeyboard (ST_VOID); +#endif /* ADLC_LM */ +#endif + +#if !defined(ADLC_LM) +ADLC_EVENT_INFO *addToEventList(ST_INT adlcEventOp,ST_VOID *adlcEventCb,ST_INT adlcRetCode); +#endif + +#if defined(ADLC_LM) +ST_RET exitCallBack (ST_ULONG userId, ST_ULONG postCount); + +ST_RET term_init (ST_VOID); +ST_RET term_rest (ST_VOID); +ST_RET adlcQueInit (ST_VOID); +ADLC_TASK_INFO *addToTaskList(ST_UINT16 localAddr,ST_INT taskId,HQUEUE qHandle); +ADLC_TASK_INFO *getTaskPtrFromLocalAddress(ST_UINT16 addr); +ADLC_TASK_INFO *getTaskPtrFromTaskId(ST_INT taskId); +ST_VOID deleteTask(ADLC_TASK_INFO *tptr); +ST_VOID deleteTaskFromLocalAddress(ST_UINT16 localAddr); +ST_RET addTaskForLocalAddress(ST_UINT16 addr,ST_INT taskId); +ST_VOID deleteTaskFromTaskId(ST_INT taskId); +ST_INT getTaskId(ADLC_CON_INFO *cptr,ST_INT *taskId); +ST_VOID logIpcError(ST_INT retCode, ST_CHAR *str, ST_CHAR *file, ST_INT line); +ST_VOID updateStatusBar(ST_CHAR *szBuff); +ST_VOID screenLogFun (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); + +/* adlc_lm.c */ +ST_RET handleCmdQueEvent (ST_ULONG userId, ST_ULONG qMsgLen, ST_VOID *qMsg); +ST_RET handleDataQueEvent (ST_ULONG userId, ST_ULONG qMsgLen, ST_VOID *qMsg); +ST_RET sendDataMsgToStack(ADLC_CMD *srcPstCmd,ST_INT stackTaskId); +ST_RET sendDataMsgToStackNoAlloc(ADLC_CMD *dstPstCmd,ST_INT stackTaskId); +#endif /* ADLC_LM */ + +#if defined(__OS2__) +ST_VOID exitLogging (ST_ULONG ulTermCode); +ST_VOID exitCleanFun (ST_ULONG ulTermCode); +#endif + +#if defined(_WIN32) +ST_VOID exitLogging (ST_VOID); +ST_VOID exitCleanFun (ST_VOID); +#endif + +#if defined(UCA_SMP) +ADLC_REQ *addToExtReqList(ADLC_CON_INFO *cptr,ADLC_REQ **adlcReqList,ST_LONG userId); +ST_VOID deleteExtReqFrame(ADLC_REQ *rptr); +ST_VOID addToUIFramesInTxList(ADLC_REQ *rptr,ST_UCHAR *data,ST_INT dataLen); +ST_VOID addToUIFramesInRxList(ADLC_CON_INFO *cptr,ST_UCHAR *data,ST_INT dataLen); +ST_VOID deleteUIFramesFromRxList(ADLC_CON_INFO *cptr); +ST_VOID deleteUIFramesFromTxList(ADLC_CON_INFO *cptr); +ST_RET sendExtWriteDoneToStack(ADLC_CON_INFO *cptr, ST_LONG userId, + ST_CHAR *timeSync, ST_INT bufLen, + ST_RET retCode); +#endif /* UCA_SMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* _ADLC_H */ + + + diff --git a/include/inc/adlc_dsm.h b/include/inc/adlc_dsm.h new file mode 100644 index 0000000..319cd58 --- /dev/null +++ b/include/inc/adlc_dsm.h @@ -0,0 +1,73 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-1996, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : adlc_dsm.h */ +/* PRODUCT(S) : ADLC */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains functions that provide for serial port communi- */ +/* cations for the Digiboard. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* ST_INT sm_init(port,baud,parity,data,stop) */ +/* ST_INT sm_exit(port) */ +/* ST_INT sm_put (port,len,buffer) */ +/* ST_INT sm_putc (port,ch) */ +/* ST_INT sm_rx_cnt (port) */ +/* ST_INT sm_get (port,len,buffer) */ +/* ST_INT sm_getc (port) */ +/* ST_INT sm_rx_flush(port) */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/12/97 IKE 09 Changed to MMSEASE 7.0 Data Types */ +/* 02/21/97 IKE 08 Changed COM_TEST to ESSENTIAL_COM to make */ +/* more sense */ +/* 12/03/96 IKE 07 Moved some stuff to adlc_sm.h */ +/* 09/19/96 IKE 06 Rearranged sm_get and sm_set functions */ +/* 08/22/96 IKE 05 Added sm_get_dcd for contention avoidance */ +/* 06/11/96 IKE 04 Added more functions to check RS232 signals */ +/* 05/22/96 IKE 03 Added functions to control RS232 signals */ +/* 04/04/96 rkr 02 Cleanup */ +/* 11/12/95 IKE 1 Created */ +/************************************************************************/ + +#ifndef _ADLC_DSM_H_ +#define _ADLC_DSM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(ESSENTIAL_COM) + +ST_INT xc_entr (ST_INT); +ST_INT xc_exit(ST_VOID); +ST_INT xc_init(ST_INT, ST_INT, ST_INT, ST_INT, ST_INT); +ST_INT xc_link (ST_INT, ST_INT); +ST_INT xc_unlk (ST_INT); +ST_INT xc_put (ST_INT, ST_CHAR*, ST_INT*); +ST_INT xc_putc (ST_INT, ST_CHAR); +ST_INT xc_get (ST_INT, ST_CHAR*, ST_INT*); +ST_INT xc_getc (ST_INT); +ST_INT xc_dtr (ST_INT, ST_INT); +ST_INT xc_rts (ST_INT, ST_INT); +ST_INT xc_cts(ST_INT); +ST_INT xc_dsr(ST_INT); +ST_INT xc_dcd(ST_INT); +ST_INT xc_test (ST_INT); +ST_INT xc_utest (ST_INT); +ST_INT xc_uwait(ST_INT); +#endif /* ESSENTIAL_COM */ + +#ifdef __cplusplus +} +#endif + +#endif /* adlc_dsm.h already included */ diff --git a/include/inc/adlc_log.h b/include/inc/adlc_log.h new file mode 100644 index 0000000..a6c50eb --- /dev/null +++ b/include/inc/adlc_log.h @@ -0,0 +1,879 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-1996, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : adlc_log.h */ +/* PRODUCT(S) : ADLC */ +/* */ +/* MODULE DESCRIPTION : */ +/* All the logging macros are defined in following order for easy */ +/* editing of this file. Please keep the same order if logging macros */ +/* need to be changed */ +/* */ +/* ADLC_MASK_LOG_ERR for critical errors */ +/* ADLC_MASK_LOG_NERR for normal errors */ +/* ADLC_MASK_LOG_FLOW for program flow logging */ +/* ADLC_MASK_LOG_IO for control frames */ +/* ADLC_MASK_LOG_DEBUG for debugging purposes */ +/* ADLC_MASK_LOG_ALWAYS for always logging */ +/* ADLC_MASK_LOG_SM for serial manager logging */ +/* ADLC_MASK_LOG_INFO_FRAME for data coming to or from stack */ +/* ADLC_MASK_LOG_USER from or to user (stack) logging */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/13/99 MDE 19 Added SD_CONST modifiers */ +/* 02/01/99 JRB 18 Fix ADLC_LOG_DEV_FILT macros for new API. */ +/* Put back ADLC_MAX_LOG_MASK. ADLC_LM needs it.*/ +/* 10/08/98 MDE 17 Migrated to updated SLOG interface */ +/* 09/01/98 IKE 16 Removed the if statement for ALWAYS macros */ +/* 09/18/97 IKE 15 Added telephone support */ +/* 08/27/97 IKE 14 Fixed number of parameters in */ +/* ADLC_LOG_DEV_FILT macros for non debug ver */ +/* 07/16/97 IKE 13 Added ADLC_LOG_DEV_FILT */ +/* 06/13/97 EJV 12 Added ADLC_LOG_ERR5 */ +/* 05/12/97 IKE 11 Changed to MMSEASE 7.0 Data Types */ +/* 04/30/97 IKE 10 Updated ADLC_MAX_LOG_MASK */ +/* 02/24/97 IKE 09 Changed logMask6 to use adlc_debug_sel */ +/* moved log masks to adlc_usr.h, changed */ +/* the logging macros to use slog functions */ +/* deleted macros specific to OS2 */ +/* 12/03/96 IKE 08 WIN32 Support, header files cleanup */ +/* 11/06/96 IKE 07 Changed C++ style comments to C style */ +/* comments to make it more platform independent*/ +/* 10/28/96 KCR 06 Changed LT of HEX logging macros to _CONT */ +/* 10/22/96 IKE 05 Added LOG_ALWAYS5 */ +/* 10/04/96 IKE 04 Changed DEBUG_MMS to DEBUG_SISCO */ +/* 06/21/96 IKE 03 Added ADLC_SM, ADLC_INFO_FRAME and ADLC_USER */ +/* Changed from slog_remote to SLOG6_REM_xxx */ +/* 04/04/96 rkr 02 Cleanup, removed slog_ipc.h */ +/* 01/20/96 IKE 01 Merged NAV's OS2 code */ +/* 11/25/95 IKE 1.00 Created */ +/************************************************************************/ + +#ifndef ADLC_LOG_INCLUDED +#define ADLC_LOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "slog.h" + +/************************************************************************/ +/* The Logging Control structure */ +/* Note that more than one may be used, and there is a 1-to-1 mapping */ +/* of the control structure to associated file && memory buffer. */ +/************************************************************************/ + +#define ADLC_MAX_LOG_MASK (ADLC_MASK_LOG_ERR | ADLC_MASK_LOG_NERR | \ + ADLC_MASK_LOG_FLOW | \ + ADLC_MASK_LOG_IO | ADLC_MASK_LOG_HEXIO | \ + ADLC_MASK_LOG_DEBUG | ADLC_MASK_LOG_HEXDEBUG | \ + ADLC_MASK_LOG_SM | ADLC_MASK_LOG_HEXSM | \ + ADLC_MASK_LOG_INFO_FRAME | ADLC_MASK_LOG_HEXINFO_FRAME | \ + ADLC_MASK_LOG_USER | ADLC_MASK_LOG_HEXUSER) + +#define ADLC_LOG_CLOSE_FILE (p) {slogCloseFile (p);} + +/* Control bit set/clear macros */ + +#define ADLC_SET_CTRL(a) {sLogCtrl->logCtrl |= (a);} +#define ADLC_CLR_CTRL(a) {sLogCtrl->logCtrl &= ~(a);} + +#define ADLC_SET_FILE_CTRL(a) {sLogCtrl->fc.ctrl |= (a);} +#define ADLC_CLR_FILE_CTRL(a) {sLogCtrl->fc.ctrl &= ~(a);} + +#define ADLC_SET_LOG_MASK(a) {adlc_debug_sel |= (a);} +#define ADLC_CLR_LOG_MASK(a) {adlc_debug_sel &= ~(a);} + + +#ifdef DEBUG_SISCO /* if DEBUG_SISCO is defined, expand macros */ + +/************************************************************************/ +/* ADLC LOGGING CONTROL */ +/************************************************************************/ + +/* Log Type Strings */ +extern SD_CONST ST_CHAR *_adlc_err_logstr; +extern SD_CONST ST_CHAR *_adlc_nerr_logstr; +extern SD_CONST ST_CHAR *_adlc_flow_logstr; +extern SD_CONST ST_CHAR *_adlc_io_logstr; +extern SD_CONST ST_CHAR *_adlc_debug_logstr; +extern SD_CONST ST_CHAR *_adlc_always_logstr; +extern SD_CONST ST_CHAR *_adlc_sm_logstr; +extern SD_CONST ST_CHAR *_adlc_info_frame_logstr; +extern SD_CONST ST_CHAR *_adlc_user_logstr; + +/* --------------------------------------------------------------- */ +/* ------------------ Error Logging Macros ------------------ */ +#define ADLC_LOG_ERR0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slog (sLogCtrl, _adlc_err_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_ERR1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slog (sLogCtrl, _adlc_err_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_ERR2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slog (sLogCtrl, _adlc_err_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_ERR3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slog (sLogCtrl, _adlc_err_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_ERR4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slog (sLogCtrl, _adlc_err_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define ADLC_LOG_ERR5(a,b,c,d,e,f) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slog (sLogCtrl, _adlc_err_logstr,\ + thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CERR0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CERR1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CERR2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CERR3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CERR4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_ERR_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slogHex (sLogCtrl,a,b);\ + } + + +/* --------------------------------------------------------------- */ +/* ------------------ Normal Error Logging Macros ------------------ */ + +#define ADLC_LOG_NERR0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slog (sLogCtrl, _adlc_nerr_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_NERR1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slog (sLogCtrl, _adlc_nerr_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_NERR2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slog (sLogCtrl, _adlc_nerr_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_NERR3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slog (sLogCtrl, _adlc_nerr_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_NERR4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slog (sLogCtrl, _adlc_nerr_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CNERR0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CNERR1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CNERR2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CNERR3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CNERR4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_NERR_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ Flow Logging Macros ------------------ */ + +#define ADLC_LOG_FLOW0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slog (sLogCtrl, _adlc_flow_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_FLOW1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slog (sLogCtrl, _adlc_flow_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_FLOW2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slog (sLogCtrl, _adlc_flow_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_FLOW3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slog (sLogCtrl, _adlc_flow_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_FLOW4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slog (sLogCtrl, _adlc_flow_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CFLOW0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CFLOW1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CFLOW2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CFLOW3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CFLOW4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_FLOW_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ I/O Logging Macros ------------------ */ + +#define ADLC_LOG_IO0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_IO1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_IO2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_IO3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_IO4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CIO0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CIO1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CIO2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CIO3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CIO4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_IO_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_HEXIO)\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ Debug Logging Macros ------------------ */ + +#define ADLC_LOG_DEBUG0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slog (sLogCtrl, _adlc_debug_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_DEBUG1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slog (sLogCtrl, _adlc_debug_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_DEBUG2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slog (sLogCtrl, _adlc_debug_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_DEBUG3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slog (sLogCtrl, _adlc_debug_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_DEBUG4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slog (sLogCtrl, _adlc_debug_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CDEBUG0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CDEBUG1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CDEBUG2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CDEBUG3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CDEBUG4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_DEBUG_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_HEXDEBUG)\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ Always Logging Macros ------------------ */ + +#define ADLC_LOG_ALWAYS0(a) {\ + _slog (sLogCtrl, _adlc_always_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_ALWAYS1(a,b) {\ + _slog (sLogCtrl, _adlc_always_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_ALWAYS2(a,b,c) {\ + _slog (sLogCtrl, _adlc_always_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_ALWAYS3(a,b,c,d) {\ + _slog (sLogCtrl, _adlc_always_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_ALWAYS4(a,b,c,d,e) {\ + _slog (sLogCtrl, _adlc_always_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define ADLC_LOG_ALWAYS5(a,b,c,d,e,f) {\ + _slog (sLogCtrl, _adlc_always_logstr,\ + thisFileName,__LINE__,a,b,c,d,e,f);\ + } +/* 'Continue' versions */ +#define ADLC_LOG_CALWAYS0(a) {\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CALWAYS1(a,b) {\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CALWAYS2(a,b,c) {\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CALWAYS3(a,b,c,d) {\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CALWAYS4(a,b,c,d,e) {\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } +#define ADLC_LOG_CALWAYS5(a,b,c,d,e,f) {\ + _slogc (sLogCtrl,a,b,c,d,e,f);\ + } + +#define ADLC_LOG_ALWAYS_HEX(a,b) {\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ SM Logging Macros ------------------ */ + +#define ADLC_LOG_SM0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slog (sLogCtrl, _adlc_sm_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_SM1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slog (sLogCtrl, _adlc_sm_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_SM2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slog (sLogCtrl, _adlc_sm_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_SM3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slog (sLogCtrl, _adlc_sm_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_SM4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slog (sLogCtrl, _adlc_sm_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CSM0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CSM1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CSM2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CSM3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CSM4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_SM_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_HEXSM)\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ INFO_FRAME Logging Macros ------------------ */ + +#define ADLC_LOG_INFO_FRAME0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slog (sLogCtrl, _adlc_info_frame_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_INFO_FRAME1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slog (sLogCtrl, _adlc_info_frame_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_INFO_FRAME2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slog (sLogCtrl, _adlc_info_frame_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_INFO_FRAME3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slog (sLogCtrl, _adlc_info_frame_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_INFO_FRAME4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slog (sLogCtrl, _adlc_info_frame_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CINFO_FRAME0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CINFO_FRAME1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CINFO_FRAME2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CINFO_FRAME3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CINFO_FRAME4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_INFO_FRAME_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_HEXINFO_FRAME)\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ USER Logging Macros ------------------ */ + +#define ADLC_LOG_USER0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slog (sLogCtrl, _adlc_user_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_USER1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slog (sLogCtrl, _adlc_user_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_USER2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slog (sLogCtrl, _adlc_user_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_USER3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slog (sLogCtrl, _adlc_user_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_USER4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slog (sLogCtrl, _adlc_user_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } +#define ADLC_LOG_USER5(a,b,c,d,e,f) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slog (sLogCtrl, _adlc_user_logstr,\ + thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CUSER0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CUSER1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CUSER2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CUSER3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CUSER4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } +#define ADLC_LOG_CUSER5(a,b,c,d,e,f) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slogc (sLogCtrl,a,b,c,d,e,f);\ + } +#define ADLC_LOG_USER_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_HEXUSER)\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ DEV_FILT Logging Macros ------------------ */ +#if defined(ADLC_LM) +#define ADLC_LOG_DEV_FILT0(x,a) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_DEV_FILT1(x,a,b) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_DEV_FILT2(x,a,b,c) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_DEV_FILT3(x,a,b,c,d) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_DEV_FILT4(x,a,b,c,d,e) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CDEV_FILT0(x,a) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CDEV_FILT1(x,a,b) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CDEV_FILT2(x,a,b,c) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CDEV_FILT3(x,a,b,c,d) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CDEV_FILT4(x,a,b,c,d,e) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_DEV_FILT_HEX(x,a,b) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slogHex (sLogCtrl,a,b);\ + } +#endif /* ADLC_LM */ +#else /* DEBUG_SISCO not defined */ + +/*----------------------------------------------------------------------- + * Error Logging Macros for Hard( serious ) Errors + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_ERR0(a) +#define ADLC_LOG_ERR1(a,b) +#define ADLC_LOG_ERR2(a,b,c) +#define ADLC_LOG_ERR3(a,b,c,d) +#define ADLC_LOG_ERR4(a,b,c,d,e) +#define ADLC_LOG_ERR5(a,b,c,d,e,f) + +#define ADLC_LOG_CERR0(a) +#define ADLC_LOG_CERR1(a,b) +#define ADLC_LOG_CERR2(a,b,c) +#define ADLC_LOG_CERR3(a,b,c,d) +#define ADLC_LOG_CERR4(a,b,c,d,e) + +#define ADLC_LOG_ERR_HEX(a,b) + +/*----------------------------------------------------------------------- + * Logging Macros for on Errors + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_NERR0(a) +#define ADLC_LOG_NERR1(a,b) +#define ADLC_LOG_NERR2(a,b,c) +#define ADLC_LOG_NERR3(a,b,c,d) +#define ADLC_LOG_NERR4(a,b,c,d,e) + +#define ADLC_LOG_CNERR0(a) +#define ADLC_LOG_CNERR1(a,b) +#define ADLC_LOG_CNERR2(a,b,c) +#define ADLC_LOG_CNERR3(a,b,c,d) +#define ADLC_LOG_CNERR4(a,b,c,d,e) + +#define ADLC_LOG_NERR_HEX(a,b) +/*----------------------------------------------------------------------- + * Flow Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_FLOW0(a) +#define ADLC_LOG_FLOW1(a,b) +#define ADLC_LOG_FLOW2(a,b,c) +#define ADLC_LOG_FLOW3(a,b,c,d) +#define ADLC_LOG_FLOW4(a,b,c,d,e) +#define ADLC_LOG_FLOW5(a,b,c,d,e,f) + +#define ADLC_LOG_CFLOW0(a) +#define ADLC_LOG_CFLOW1(a,b) +#define ADLC_LOG_CFLOW2(a,b,c) +#define ADLC_LOG_CFLOW3(a,b,c,d) +#define ADLC_LOG_CFLOW4(a,b,c,d,e) +#define ADLC_LOG_CFLOW5(a,b,c,d,e,f) + +#define ADLC_LOG_FLOW_HEX(a,b) +/*----------------------------------------------------------------------- + * I/O Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_IO0(a) +#define ADLC_LOG_IO1(a,b) +#define ADLC_LOG_IO2(a,b,c) +#define ADLC_LOG_IO3(a,b,c,d) +#define ADLC_LOG_IO4(a,b,c,d,e) + +#define ADLC_LOG_CIO0(a) +#define ADLC_LOG_CIO1(a,b) +#define ADLC_LOG_CIO2(a,b,c) +#define ADLC_LOG_CIO3(a,b,c,d) +#define ADLC_LOG_CIO4(a,b,c,d,e) + +#define ADLC_LOG_IO_HEX(a,b) + +/*----------------------------------------------------------------------- + * Debug Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_DEBUG0(a) +#define ADLC_LOG_DEBUG1(a,b) +#define ADLC_LOG_DEBUG2(a,b,c) +#define ADLC_LOG_DEBUG3(a,b,c,d) +#define ADLC_LOG_DEBUG4(a,b,c,d,e) + +#define ADLC_LOG_CDEBUG0(a) +#define ADLC_LOG_CDEBUG1(a,b) +#define ADLC_LOG_CDEBUG2(a,b,c) +#define ADLC_LOG_CDEBUG3(a,b,c,d) +#define ADLC_LOG_CDEBUG4(a,b,c,d,e) + +#define ADLC_LOG_DEBUG_HEX(a,b) + +/*----------------------------------------------------------------------- + * Always Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_ALWAYS0(a) +#define ADLC_LOG_ALWAYS1(a,b) +#define ADLC_LOG_ALWAYS2(a,b,c) +#define ADLC_LOG_ALWAYS3(a,b,c,d) +#define ADLC_LOG_ALWAYS4(a,b,c,d,e) +#define ADLC_LOG_ALWAYS5(a,b,c,d,e,f) + +#define ADLC_LOG_CALWAYS0(a) +#define ADLC_LOG_CALWAYS1(a,b) +#define ADLC_LOG_CALWAYS2(a,b,c) +#define ADLC_LOG_CALWAYS3(a,b,c,d) +#define ADLC_LOG_CALWAYS4(a,b,c,d,e) +#define ADLC_LOG_CALWAYS5(a,b,c,d,e,f) + +#define ADLC_LOG_ALWAYS_HEX(a,b) + +/*----------------------------------------------------------------------- + * Serial Manager Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_SM0(a) +#define ADLC_LOG_SM1(a,b) +#define ADLC_LOG_SM2(a,b,c) +#define ADLC_LOG_SM3(a,b,c,d) +#define ADLC_LOG_SM4(a,b,c,d,e) + +#define ADLC_LOG_CSM0(a) +#define ADLC_LOG_CSM1(a,b) +#define ADLC_LOG_CSM2(a,b,c) +#define ADLC_LOG_CSM3(a,b,c,d) +#define ADLC_LOG_CSM4(a,b,c,d,e) + +#define ADLC_LOG_SM_HEX(a,b) + +/*----------------------------------------------------------------------- + * INFO_FRAME Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_INFO_FRAME0(a) +#define ADLC_LOG_INFO_FRAME1(a,b) +#define ADLC_LOG_INFO_FRAME2(a,b,c) +#define ADLC_LOG_INFO_FRAME3(a,b,c,d) +#define ADLC_LOG_INFO_FRAME4(a,b,c,d,e) + +#define ADLC_LOG_CINFO_FRAME0(a) +#define ADLC_LOG_CINFO_FRAME1(a,b) +#define ADLC_LOG_CINFO_FRAME2(a,b,c) +#define ADLC_LOG_CINFO_FRAME3(a,b,c,d) +#define ADLC_LOG_CINFO_FRAME4(a,b,c,d,e) + +#define ADLC_LOG_INFO_FRAME_HEX(a,b) + +/*----------------------------------------------------------------------- + * USER Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_USER0(a) +#define ADLC_LOG_USER1(a,b) +#define ADLC_LOG_USER2(a,b,c) +#define ADLC_LOG_USER3(a,b,c,d) +#define ADLC_LOG_USER4(a,b,c,d,e) +#define ADLC_LOG_USER5(a,b,c,d,e,f) + +#define ADLC_LOG_CUSER0(a) +#define ADLC_LOG_CUSER1(a,b) +#define ADLC_LOG_CUSER2(a,b,c) +#define ADLC_LOG_CUSER3(a,b,c,d) +#define ADLC_LOG_CUSER4(a,b,c,d,e) +#define ADLC_LOG_CUSER5(a,b,c,d,e,f) + +#define ADLC_LOG_USER_HEX(a,b) + +/*----------------------------------------------------------------------- + * DEV_FILT Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_DEV_FILT0(x,a) +#define ADLC_LOG_DEV_FILT1(x,a,b) +#define ADLC_LOG_DEV_FILT2(x,a,b,c) +#define ADLC_LOG_DEV_FILT3(x,a,b,c,d) +#define ADLC_LOG_DEV_FILT4(x,a,b,c,d,e) + +#define ADLC_LOG_CDEV_FILT0(x,a) +#define ADLC_LOG_CDEV_FILT1(x,a,b) +#define ADLC_LOG_CDEV_FILT2(x,a,b,c) +#define ADLC_LOG_CDEV_FILT3(x,a,b,c,d) +#define ADLC_LOG_CDEV_FILT4(x,a,b,c,d,e) + +#define ADLC_LOG_DEV_FILT_HEX(x,a,b) + +#endif /* for DEBUG_SISCO */ + +#ifdef __cplusplus +} +#endif + +#endif /* ADLC_LOG_INCLUDED */ + diff --git a/include/inc/adlc_sm.h b/include/inc/adlc_sm.h new file mode 100644 index 0000000..1eecba1 --- /dev/null +++ b/include/inc/adlc_sm.h @@ -0,0 +1,317 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-2002, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : adlc_sm.h */ +/* PRODUCT(S) : ADLC */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains functions that provide for serial port communi- */ +/* cations for the Digiboard. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* ST_INT sm_init(port,baud,parity,data,stop) */ +/* ST_INT sm_exit(port) */ +/* ST_INT sm_put (port,len,buffer) */ +/* ST_INT sm_putc (port,ch) */ +/* ST_INT sm_rx_cnt (port) */ +/* ST_INT sm_get (port,packet,toRead,bytesRead) */ +/* ST_INT sm_getc (port) */ +/* ST_INT sm_rx_flush(port) */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/24/02 KCR 12 Added rdThreadError handling semaphore */ +/* 04/20/98 IKE 11 Moved u_smp_record_time in Serial Manager */ +/* 10/06/97 IKE 10 Added more baud rates */ +/* 09/18/97 IKE 09 Added telephone support */ +/* 05/12/97 IKE 08 Changed to MMSEASE 7.0 Data Types */ +/* 02/03/97 IKE 07 adlcCfg per port basis */ +/* CFG_PORT also for DOS so multiple ports can */ +/* be initialized in dos platform */ +/* 09/19/96 IKE 06 Rearranged sm_get and sm_set functions */ +/* 08/22/96 IKE 05 Added sm_get_dcd for contention avoidance */ +/* 06/11/96 IKE 04 Added more functions to check RS232 signals */ +/* 05/22/96 IKE 03 Added functions to control RS232 signals */ +/* 04/04/96 rkr 02 Cleanup */ +/* 11/12/95 IKE 1 Created */ +/************************************************************************/ + +#ifndef _ADLC_SM_H_ +#define _ADLC_SM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define COM1 0 /* Async Adapter COM1: */ +#define COM2 1 /* Async Adapter COM2: */ +#define COM3 2 /* Async Adapter COM3: */ +#define COM4 3 /* Async Adapter COM4: */ +#define COM5 4 /* Async Adapter COM5: */ +#define COM6 5 /* Async Adapter COM6: */ +#define COM7 6 /* Async Adapter COM7: */ +#define COM8 7 /* Async Adapter COM8: */ +#define COM9 8 /* Async Adapter COM9: */ +#define COM10 9 /* Async Adapter COM10: */ +#define COM11 10 /* ETC. */ +#define COM12 11 +#define COM13 12 +#define COM14 13 +#define COM15 14 +#define COM16 15 +#define COM17 16 +#define COM18 17 +#define COM19 18 +#define COM20 19 +#define COM21 20 +#define COM22 21 +#define COM23 22 +#define COM24 23 +#define COM25 24 +#define COM26 25 +#define COM27 26 +#define COM28 27 +#define COM29 28 +#define COM30 29 +#define COM31 30 +#define COM32 31 +#define COM33 32 +#define COM34 33 + +#define LOW 0 +#define HIGH 1 + +ST_RET sm_init (ST_INT,ST_INT,ST_INT,ST_INT,ST_INT); +ST_RET sm_exit (ST_INT); +ST_RET sm_put (ST_INT,ST_INT, ST_CHAR *); +ST_RET sm_putc (ST_INT, ST_CHAR); +ST_INT sm_rx_cnt (ST_INT port); +ST_INT sm_tx_cnt (ST_INT port); +ST_RET sm_get (ST_INT,ST_CHAR *,ST_INT,ST_INT *); +ST_INT sm_getc (ST_INT); +ST_VOID sm_rx_flush (ST_INT); +ST_RET sm_set_signals (ST_INT port); +ST_RET sm_clear_signals (ST_INT port); +ST_RET sm_set_rts (ST_INT port); +ST_RET sm_clear_rts (ST_INT port); +ST_RET sm_set_dtr (ST_INT port); +ST_RET sm_clear_dtr (ST_INT port); +ST_RET sm_set_rts_clear_dtr(ST_INT port); +ST_RET sm_clear_rts_set_dtr(ST_INT port); +ST_INT sm_get_rts (ST_INT port); +ST_INT sm_get_dtr (ST_INT port); +ST_INT sm_get_cts (ST_INT port); +ST_INT sm_get_dsr (ST_INT port); +ST_INT sm_get_dcd (ST_INT port); + +#if !defined(ADLC_LM) +/* The INIT (ah=00, Int 14h) communications parameters */ + +#define BAUD110 0 /* Baud rate 110 */ +#define BAUD150 1 /* Baud rate 150 */ +#define BAUD300 2 /* Baud rate 300 */ +#define BAUD600 3 /* Baud rate 600 */ +#define BAUD1200 4 /* Baud rate 1200 */ +#define BAUD2400 5 /* Baud rate 2400 */ +#define BAUD4800 6 /* Baud rate 4800 */ +#define BAUD9600 7 /* Baud rate 9600 */ +#define BAUD19200 8 /* Baud rate 19200 */ +#define BAUD38400 9 /* Baud rate 38400 */ +#define BAUD57K 10 /* Baud rate 57.4K */ +#define BAUD115K 11 /* Baud rate 115.2K */ +#define BAUD56K 12 /* Baud rate 56K */ +#define BAUD128K 13 /* Baud rate 128K */ +#define BAUD256K 14 /* Baud rate 256K */ + +#define DATA7 0 /* Data bits 7 */ +#define DATA8 1 /* Data bits 8 */ + +#define NOPAR 0 /* Parity none */ +#define ODDPAR 1 /* Parity odd */ +#define EVENPAR 2 /* Parity even */ + +#define STOP1 0 /* Stop bits 1 */ +#define STOP2 1 /* Stop bits 2 */ + +#endif /* !ADLC_LM */ + +#if defined(ADLC_LM) +/* Request OpCode Definitions */ +#define SM_INITIALIZE_PORT_REQ 0 /* open the port */ +#define SM_TERMINATE_PORT_REQ 1 /* close the port */ +#define SM_READ_REQ 2 /* read from the port */ +#define SM_WRITE_REQ 3 /* write to the port */ +#define SM_IN_BYTE_COUNT_REQ 4 /* check the input Q */ +#define SM_OUT_BYTE_COUNT_REQ 5 /* check the output Q */ +#define SM_GET_STATUS_REQ 6 /* get modem status */ +#define SM_SET_STATUS_REQ 7 /* set modem status */ +#define SM_RX_FLUSH_REQ 8 /* flush recieve buffer */ +#define SM_GET_FRAME_REQ 9 /* respond to frameArr */ + +/* Request Error Code Definitions */ +#define SM_NO_ERR 0 +#define SM_INIT_ERR 1 +#define SM_TX_ERR 2 +#define SM_RX_ERR 3 +#define SM_INVALID_REQ 4 +#define SM_PORT_ALREADY_OPEN 5 +#define SM_OPEN_ERROR 6 +#define SM_SET_BAUD_FAILURE 7 +#define SM_SET_LINE_FAILURE 8 +#define SM_SET_FLOW_FAILURE 9 +#define SM_PORT_NOT_OPEN 10 +#define SM_INVALID_PARAM 11 +#define SM_ERROR 12 +#define SM_NO_FRAMES_AVAILABLE 13 +#define SM_NO_WRITE_CONF_AVIAL 14 +#define SM_SEM_OPEN_FAILURE 15 +#define SM_TERMINATED 16 + +/* Request Status Code Definitions */ +#define SM_COMPLETED 0 +#define SM_PENDING 1 +#define SM_UNDERWAY 2 +#define SM_ABORTED 3 +#define SM_FAILED 4 +#define SM_TX_RX_IN_PROCESS 5 /* pend TX & RX on terminate*/ +#define SM_TX_IN_PROCESS 6 /* pending TX on terminate */ +#define SM_RX_IN_PROCESS 7 /* pending RX on terminate */ + +/* Request Specific Structures */ +typedef struct smRdwrReq + { + ST_INT len; /* num of bytes to read or write */ + ST_CHAR *data; /* user allocates and frees for read or */ + }SM_RDWR_REQ; /* write */ + +typedef struct smFrameReq + { + ST_INT port; /* port the frame was received from */ + ST_INT len; /* frame length */ + ST_CHAR *data; /* SM allocates - user frees!!! */ +#if defined(UCA_SMP) + ST_CHAR recTime[SMP_SIZE_OF_REC_TIME]; /* buffer to hold time stamp */ +#endif + }SM_FRAME_REQ; + +typedef struct smLineParam + { + ST_INT baudRate; /* 300, 1200, 4800, 9600, 19.2, 38.4, 57.6 */ + ST_INT dataBits; /* 5, 6, 7, 8 */ + ST_INT parity; /* 0=none, 1=odd, 2=even, 3=mark, 4=space */ + ST_INT stopBits; /* 0=>1, 1=>1.5 stop bits, 2=>2 */ + }SM_LINE_PARAM; + +typedef struct smHandShake + { + ST_BOOLEAN enableDTR; /* enable DTR input handshaking */ + ST_BOOLEAN enableCTS; /* enable CTS output handshaking */ + ST_BOOLEAN enableDSRout; /* enable DSR output handshaking */ + ST_BOOLEAN enableDCD; /* enable DCD output handshaking */ + ST_BOOLEAN enableDSRin; /* enable DSR input sensitivity */ + ST_BOOLEAN enableRTS; /* enable RTS input handshaking */ + }SM_HAND_SHAKE; + +typedef struct smFlowCtrl + { + ST_BOOLEAN enableTxFlow; /* enable auto transmit XON/XOFF */ + ST_BOOLEAN enableRxFlow; /* enable auto receive XON/XOFF */ + ST_UCHAR xonChar; /* usually 0x11 */ + ST_UCHAR xoffChar; /* usually 0x13 */ + }SM_FLOW_CTRL; + +typedef struct smInitReq + { + SM_LINE_PARAM initLineParam; + SM_HAND_SHAKE initHandShake; + SM_FLOW_CTRL initFlowCtrl; + HANDLE hCom; + ST_INT frameLen; + ST_UCHAR sof; + ST_UCHAR eof; + HEV txDoneSem; + HEV frameArrivalSem; + HEV rdThreadErrSem; + }SM_INIT_REQ; + +typedef struct smStatusReq + { + ST_BOOLEAN dtr; + ST_BOOLEAN rts; + ST_BOOLEAN dcd; + ST_BOOLEAN cts; + ST_BOOLEAN dsr; + }SM_STATUS_REQ; + +/************************************************************************/ +/* SM_REQ */ +/* Every request to serial Manager uses this data structure */ +/************************************************************************/ +typedef struct smReq + { + struct dbl_lnk l; + ST_INT opCode; /* operation requested */ + ST_INT status; + ST_INT errCode; + ST_INT port; + union + { + SM_RDWR_REQ readWriteReq; + SM_INIT_REQ initReq; + SM_STATUS_REQ setStatReq; + } i; /* input data */ + union + { + SM_RDWR_REQ readReq; + SM_STATUS_REQ getStatReq; + ST_INT byteCount; + SM_FRAME_REQ frameArrReq; + }o; /* output data */ + }SM_REQ; + +/* serial manager user access functions */ +ST_RET sm_get_status (ST_INT port,SM_REQ *pstReq); +ST_VOID sm_set_status(ST_INT port, SM_REQ *pstReq); +ST_RET _SmInitialize(ST_VOID); /* startup code */ +ST_RET _SmRequest(SM_REQ *); /* service user requests */ +ST_VOID _SmTerminate(ST_VOID); /* cleanup code */ + +#ifdef ADLC_TESTING +ST_VOID _SmShowStats(ST_INT port); +#endif + +#endif /* ADLC_LM */ + +/************************************************************************/ +/* CFG_PORT */ +/* This data structure is used only when reading the configuration File */ +/* and when opening a port, after that it is not used any more */ +/************************************************************************/ +typedef struct cfgPortStuff + { + struct dbl_lnk l; + ST_INT port; +#if !defined(ADLC_LM) + ST_INT baud; + ST_INT parity; + ST_INT data; + ST_INT stop; +#endif +#if defined(ADLC_LM) + SM_LINE_PARAM stLineParam; + SM_HAND_SHAKE stHandShake; + SM_FLOW_CTRL stFlowCtrl; +#endif + }CFG_PORT; + +#ifdef __cplusplus +} +#endif + +#endif /* adlc_sm.h already included */ diff --git a/include/inc/adlc_sts.h b/include/inc/adlc_sts.h new file mode 100644 index 0000000..795942e --- /dev/null +++ b/include/inc/adlc_sts.h @@ -0,0 +1,82 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-1996, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : adlc_sts.h */ +/* PRODUCT(S) : ADLC */ +/* */ +/* MODULE DESCRIPTION : This header file defines data structures */ +/* and types for rli adlc link manager. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/16/97 IKE 05 Added device statistics and device filt log */ +/* 05/12/97 IKE 04 Changed to MMSEASE 7.0 Data Types */ +/* 04/10/97 EJV 03 Deletes defines ADLC_MASTER, ADLC_SLAVE */ +/* 10/23/96 IKE 02 Added statsResetTime */ +/* 09/30/96 IKE 01 Created */ +/************************************************************************/ + +#ifndef ADLC_STS_H +#define ADLC_STS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ + +/************************************************************************/ +typedef struct tagAdlcStats + { + ST_LONG statsResetTime; /* time stats last reset */ + ST_ULONG txFrames; /* Total transmitted Frames */ + ST_ULONG rxFrames; /* Total received Frames */ + ST_ULONG goodFrames; /* Total good frames received */ + ST_ULONG badFrames; /* Total bad frames when sof was ok */ + ST_ULONG discardedBytes; /* Total discarded bytes */ + ST_ULONG mCastFrames; /* Total Multicast Frames */ + ST_ULONG txPackets; /* Total Transmitted MMS LSDU */ + ST_ULONG rxPackets; /* Total Received MMS LSDU */ + ST_ULONG rxInfo; /* Total Received INFO frames */ + ST_ULONG rxRr; /* Total Received RR frames */ + ST_ULONG rxRnr; /* Total Received RNR frames */ + ST_ULONG rxRej; /* Total Received REJ frames */ + ST_ULONG rxUi; /* Total Received UI frames */ + ST_ULONG txUFrames; /* Total Transmitted Unumbered frames */ + ST_ULONG txSFrames; /* Total Transmitted Supervisory frames */ + ST_ULONG txMFrames; /* Total Transmitted Multicast frames */ + ST_ULONG txIFrames; /* Total Transmitted INFO frames */ + ST_ULONG txUiFrames; /* Total Received UI frames */ + ST_ULONG timeout; /* Total Timeouts */ + ST_ULONG retransmits; /* Total retransmit INFO frames */ + ST_ULONG rxUa; /* Total Received UA frames */ + ST_ULONG rxRd; /* Total Received RD frames */ + ST_ULONG rxDm; /* Total Received DM frames */ + ST_ULONG rxFrmr; /* Total Received FRMR frames */ + ST_ULONG txRFrames; /* Total Received Redirect frames */ + ST_ULONG rxSnrm; /* Total Received SNRM frames */ + ST_ULONG rxDisc; /* Total Received DISC frames */ + } ADLC_STATS; + +#if defined(__OS2__) || defined(_WIN32) +typedef struct tagAdlcDevStats + { + ST_ULONG txFrames; /* Total transmitted Frames */ + ST_ULONG rxFrames; /* Total received Frames */ + ST_ULONG timeout; /* Total Timeouts */ + ST_ULONG retransmits; /* Total retransmitted INFO frames */ + } ADLC_DEV_STATS; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ADLC_STS.H already included */ + diff --git a/include/inc/adlc_usr.h b/include/inc/adlc_usr.h new file mode 100644 index 0000000..eec47f4 --- /dev/null +++ b/include/inc/adlc_usr.h @@ -0,0 +1,441 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-1997, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : adlc_usr.h */ +/* PRODUCT(S) : ADLC */ +/* */ +/* MODULE DESCRIPTION : This header file defines data structures */ +/* and types for ADLC */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/05/03 EJV 21 Chg mms_debug_sel to ST_UINT, and deleted */ +/* L suffix from MMS_LOG_... masks. */ +/* 10/17/01 JRB 20 Del #ifdef UCA_SMP */ +/* 02/04/99 JRB 19 Added adlcStartLinkMan.. */ +/* 10/08/98 MDE 18 Removed ADLC_MASK_LOG_ALWAYS */ +/* 10/21/97 IKE 17 Changed OSI_ADDR to LOCAL_ADDR in error codes*/ +/* 10/14/97 IKE 16 Split into two modules and put all the ipc */ +/* specific stuff into adlc_ipc.h */ +/* 10/1/97 IKE 15 Removed ADLC_LM define if _WIN32 or OS2 is */ +/* defined */ +/* 09/26/97 IKE 14 Added ADLC_M_LOCAL_BASE_ADDR */ +/* 09/22/97 IKE 13 Added SMP(Station Managment Protocol) support*/ +/* 09/18/97 IKE 12 Added telephone support */ +/* 07/16/97 IKE 11 Added support for new ADLC commands */ +/* adlcGetDevStats and adlcFilterDevLog. */ +/* 05/12/97 IKE 10 Changed to MMSEASE 7.0 Data Types */ +/* 04/10/97 EJV 09 Replaced error codes base 0x06xx with 0xA6xx */ +/* 03/13/97 EJV 08 Changes for BRIDGE-132-095 (COGW,RSGW,MCGW): */ +/* - added adlcLogState function; */ +/* 02/24/97 IKE 07 Moved the log masks defn from adlc_log.h */ +/* 01/22/97 IKE 06 Put prototypes for adlcOpenInterface and */ +/* adlcCloseInterface */ +/* 12/03/96 IKE 05 WIN32 Support */ +/* 09/30/96 IKE 04 Removed ifdef PLAIN_DOS for adlcRead func */ +/* so Lean-t stack can use same funct for OS2 */ +/* 05/22/96 IKE 03 Added some more error codes */ +/* 04/04/96 rkr 02 Cleanup */ +/* 01/02/96 IKE 01 Created */ +/************************************************************************/ + +#ifndef ADLC_USR_H +#define ADLC_USR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "adlc_sts.h" + +#include "smp_usr.h" + +#define ADLC_ALL_ES 0x8080 /* ES-Hello Multicast Address */ +#define ADLC_ALL_IS 0x8081 /* IS-Hello Multicast Address */ +#define ALL_STATIONS_ADDR 0xFFFF /* Broadcast Address */ +#define NO_STATION_ADDR 0x0000 /* No station address */ +#define ADLC_M_BASE_LOC_ADDR 0x2000 /* For Adlc Master local Addr */ +#define ADLC_USR_M_BASE_LOC_ADDR 0x3000 /* For user apps local adlc addr*/ + +#define CMD_BASE_ADLC_LM 600 + +/****************************************************************/ +/* Log Control */ +/****************************************************************/ +/* adlc logging mask */ +#define ADLC_MASK_LOG_ERR 0x00010000 +#define ADLC_MASK_LOG_NERR 0x00020000 +#define ADLC_MASK_LOG_FLOW 0x00040000 +#define ADLC_MASK_LOG_IO 0x00080000 +#define ADLC_MASK_LOG_HEXIO 0x00100000 +#define ADLC_MASK_LOG_DEBUG 0x00200000 +#define ADLC_MASK_LOG_HEXDEBUG 0x00400000 +#define ADLC_MASK_LOG_SM 0x01000000 +#define ADLC_MASK_LOG_HEXSM 0x02000000 +#define ADLC_MASK_LOG_INFO_FRAME 0x04000000 +#define ADLC_MASK_LOG_HEXINFO_FRAME 0x08000000 +#define ADLC_MASK_LOG_USER 0x10000000 +#define ADLC_MASK_LOG_HEXUSER 0x20000000 + +extern ST_UINT adlc_debug_sel; +/****************************************************************/ +/* ADLC Command OpCodes */ +/****************************************************************/ + +#define ADLC_CMD_CONNECT_NODE (CMD_BASE_ADLC_LM + 1) +#define ADLC_CMD_DISCONNECT_NODE (CMD_BASE_ADLC_LM + 2) +#define ADLC_CMD_CONNECT_NODE_DONE (CMD_BASE_ADLC_LM + 3) +#define ADLC_CMD_DISCONNECT_NODE_DONE (CMD_BASE_ADLC_LM + 4) +#define ADLC_CMD_CONNECT_ALL (CMD_BASE_ADLC_LM + 5) +#define ADLC_CMD_DISCONNECT_ALL (CMD_BASE_ADLC_LM + 6) +#define ADLC_CMD_WRITE_PACKET (CMD_BASE_ADLC_LM + 7) +#define ADLC_CMD_GET_CON_STATUS (CMD_BASE_ADLC_LM + 8) +#define ADLC_CMD_ADD_DEV (CMD_BASE_ADLC_LM + 9) +#define ADLC_CMD_REMOVE_DEV (CMD_BASE_ADLC_LM + 10) +#define ADLC_CMD_START_POLL_DEV (CMD_BASE_ADLC_LM + 11) +#define ADLC_CMD_STOP_POLL_DEV (CMD_BASE_ADLC_LM + 12) +#define ADLC_CMD_CHANGE_POLL_RATE (CMD_BASE_ADLC_LM + 13) +#define ADLC_CMD_QUERY_POLL_INFO (CMD_BASE_ADLC_LM + 14) + +/* #if ADLC_LM */ +#define ADLC_CMD_SET_SM_SLEEP (CMD_BASE_ADLC_LM + 15) +#define ADLC_CMD_GET_SM_SLEEP (CMD_BASE_ADLC_LM + 16) +#define ADLC_CMD_GET_DEV_STATS (CMD_BASE_ADLC_LM + 17) +#define ADLC_CMD_FILTER_DEV_LOG (CMD_BASE_ADLC_LM + 18) +#define ADLC_CMD_ADD_PORT (CMD_BASE_ADLC_LM + 19) +#define ADLC_CMD_REMOVE_PORT (CMD_BASE_ADLC_LM + 20) +#define ADLC_CMD_TEL_DIAL (CMD_BASE_ADLC_LM + 21) +#define ADLC_CMD_TEL_DIAL_DONE (CMD_BASE_ADLC_LM + 22) +#define ADLC_CMD_TEL_HANGUP (CMD_BASE_ADLC_LM + 23) +#define ADLC_CMD_TEL_HANGUP_DONE (CMD_BASE_ADLC_LM + 24) +/* #endif ADLC_LM */ + +#define ADLC_CMD_EXT_WRITE_PACKET (CMD_BASE_ADLC_LM + 25) +#define ADLC_CMD_EXT_WRITE_PACKET_DONE (CMD_BASE_ADLC_LM + 26) + +#define ADLC_CMD_WRITE_PACKET_DONE (CMD_BASE_ADLC_LM + 27) + + +#define ADLC_DEV_NAME_SIZE 80 + +/************************************************************************/ +/* ADLC_CONNECT_NODE */ +/* This is a bidirectional event */ +/* This could be an event from stack to ADLC and vice versa */ +/************************************************************************/ +typedef struct tagAdlcConnectNode + { + struct + { + ST_UINT16 localAddr; /* OSI node address */ + ST_UINT16 remoteAddr; /* ADLC device address */ + ST_ULONG usr1; /* user data */ + } i; + } ADLC_CONNECT_NODE; + +/************************************************************************/ +/* ADLC_DISCONNECT_NODE */ +/* This is a bidirectional event */ +/* This could be an event from stack to ADLC and vice versa */ +/************************************************************************/ + +typedef ADLC_CONNECT_NODE ADLC_DISCONNECT_NODE; + + +/************************************************************************/ +/* ADLC_CONNECT_NODE_DONE */ +/* This is event from ADLC to stack */ +/************************************************************************/ + +typedef ADLC_CONNECT_NODE ADLC_CONNECT_NODE_DONE; + +/************************************************************************/ +/* ADLC_DISCONNECT_NODE_DONE */ +/* This is event from ADLC to stack */ +/************************************************************************/ +typedef ADLC_CONNECT_NODE ADLC_DISCONNECT_NODE_DONE; + +/************************************************************************/ +/* ADLC_CONNECT_ALL */ +/* This is an event from stack to ADLC */ +/************************************************************************/ +typedef struct tagAdlcConnectAll + { + struct + { + ST_UINT16 localAddr; /* OSI node address */ + ST_ULONG usr1; /* user data */ + } i; + } ADLC_CONNECT_ALL; + +/************************************************************************/ +/* ADLC_DISCONNECT_ALL */ +/* This is an event from stack to ADLC */ +/************************************************************************/ +typedef ADLC_CONNECT_ALL ADLC_DISCONNECT_ALL; + +/************************************************************************/ +/* ADLC_WRITE_PACKET */ +/* This is a bidirectional event */ +/* This could be an event from stack to ADLC and vice versa */ +/************************************************************************/ +typedef struct tagAdlcWritePacket + { + struct /* input parameters */ + { + ST_UINT16 remoteAddr; /* device where data is going */ + ST_UINT16 localAddr; /* device where data comes from */ + ST_INT dataSize; + ST_VOID *data; /* allocated memory */ + ST_ULONG usr1; /* user data */ + } i; + } ADLC_WRITE_PACKET; + +/************************************************************************/ +/* ADLC_WRITE_PACKET_DONE */ +/* This is an event from ADLC to stack */ +/************************************************************************/ +typedef ADLC_WRITE_PACKET ADLC_WRITE_PACKET_DONE; + +/************************************************************************/ +/* ADLC_GET_CON_STATUS */ +/* This is an event from any task to ADLC */ +/************************************************************************/ + +#define ADLC_CON_STATUS_ONLINE 1 +#define ADLC_CON_STATUS_OFFLINE 2 +#define ADLC_CON_STATUS_UNKNOWN 3 + +typedef struct tagAdlcGetConStat + { + struct /* input parameters */ + { + ST_UINT16 remoteAddr; /* ADLC device /remote addr */ + ST_UINT16 localAddr; /* OSI node / local addr */ + } i; + struct /* output parameters */ + { + ST_INT conStatusOut; + } o; + } ADLC_GET_CON_STATUS; + +#define ADLC_NO_POLLING 0 +#define ADLC_POLL_FREQ_HI 1 +#define ADLC_POLL_FREQ_MED 2 +#define ADLC_POLL_FREQ_LOW 3 + +/************************************************************************/ +/* ADLC_ADD_DEV */ +/* This is an event from any task to ADLC */ +/************************************************************************/ +typedef struct tagAdlcAddDev + { + struct /* input parameters */ + { + ST_CHAR devName[ADLC_DEV_NAME_SIZE+1]; + ST_UINT16 address; + ST_INT pollGroup; /* defined above */ + ST_INT port; /* what port it belongs to */ + ST_BOOLEAN connectAll; /* should we try to connect it if connectAll issued */ + ST_ULONG usr1; /* user data */ + } i; + } ADLC_ADD_DEV; + +/************************************************************************/ +/* ADLC_REMOVE_DEV */ +/* This is an event from any task to ADLC */ +/************************************************************************/ +typedef struct tagAdlcRemoveDev + { + struct /* input parameters */ + { + ST_CHAR devName[ADLC_DEV_NAME_SIZE+1]; + ST_ULONG usr1; /* user data */ + } i; + } ADLC_REMOVE_DEV; + +/************************************************************************/ +/* ADLC_START_POLL_DEV */ +/* This is an event from any task to ADLC */ +/************************************************************************/ +typedef struct tagAdlcStartPollDev + { + struct /* input parameters */ + { + ST_CHAR devName[ADLC_DEV_NAME_SIZE+1]; + ST_ULONG usr1; /* user data */ + } i; + } ADLC_START_POLL_DEV; + +/************************************************************************/ +/* ADLC_STOP_POLL_DEV */ +/* This is an event from any task to ADLC */ +/************************************************************************/ +typedef struct tagAdlcStopPollDev + { + struct /* input parameters */ + { + ST_CHAR devName[ADLC_DEV_NAME_SIZE+1]; + ST_ULONG usr1; /* user data */ + } i; + } ADLC_STOP_POLL_DEV; + +/************************************************************************/ +/* ADLC_CHANGE_POLL_RATE */ +/* This is an event from any task to ADLC */ +/************************************************************************/ +/* Notes on changing the poll rate for a device: + To poll the device more frequently set + pollFreqDelta = ADLC_INC_POLL_FREQ; + The device will be moved to the poll group that polls more + frequently. + + Example: current pollGroup=3 with pollRate=n seconds + new pollGroup=2 with pollRate=n-m seconds + + Reverse the above discussion to decrease the polling frequency. */ + +#define ADLC_INC_POLL_FREQ 1 +#define ADLC_DEC_POLL_FREQ 2 + +typedef struct tagAdlcChangePollRate + { + struct /* input parameters */ + { + ST_CHAR devName[ADLC_DEV_NAME_SIZE+1]; + ST_INT pollFreqDelta; /* change to poll freq as */ + ST_ULONG usr1; /* user data */ + } i; /* defined above */ + } ADLC_CHANGE_POLL_RATE; + +/************************************************************************/ +/* ADLC_QUERY_POLL_INFO */ +/* This is an event from any task to ADLC */ +/************************************************************************/ +/* Notes on Polling: + Poll groups range from 1 to n (as of 01/17/96 n=3). All devices + associated with a poll group are polled at the pollRate set for + the poll group. The smaller the poll group the more frequently + the devices are polled. */ + +typedef struct tagQueryPollInfo + { + struct /* input parameters */ + { + ST_CHAR devName[ADLC_DEV_NAME_SIZE+1]; + ST_ULONG usr1; /* user data */ + } i; + struct + { + ST_INT pollGroup; /* current poll group for device*/ + ST_DOUBLE pollRate; /* in mili seconds */ + ST_BOOLEAN bPollingSuspended; /* polling was stopped by user */ + } o; + } ADLC_QUERY_POLL_INFO; + +/************************************************************************/ +/* ADLC_EXT_WRITE_PACKET */ +/* This is a bidirectional event */ +/* This could be an event from stack to ADLC and vice versa */ +/************************************************************************/ +typedef struct tagAdlcExtWritePacket + { + struct /* input parameters */ + { + ST_UINT16 remoteAddr; /* device where data is going */ + ST_UINT16 localAddr; /* device where data comes from */ + ST_INT dataSize; + ST_VOID *data; /* allocated memory */ + ST_LONG userId; /* user passes for done func */ + ST_CHAR recTime[SMP_SIZE_OF_REC_TIME]; /* buffer to hold time stamp */ + ST_ULONG usr1; /* user data */ + } i; + } ADLC_EXT_WRITE_PACKET; + +/************************************************************************/ +/* ADLC_EXT_WRITE_PACKET_DONE */ +/* This is event from ADLC to stack */ +/************************************************************************/ +typedef ADLC_EXT_WRITE_PACKET ADLC_EXT_WRITE_PACKET_DONE; + +/* ADLC defined error codes. The error base 0x3600 is defined in glberror.h */ + +#define E_ADLC_INVALID_DEV_NAME 0x3601 +#define E_ADLC_INVALID_DEV_ADDR 0x3602 +#define E_ADLC_DEVICE_EXISTS 0x3603 +#define E_ADLC_DEV_DOES_NOT_EXIST 0x3604 + +#define E_ADLC_INVALID_LOCAL_ADDR 0x3605 +#define E_ADLC_INVALID_CON_PAIR 0x3606 +#define E_ADLC_CON_EXISTS 0x3607 +#define E_ADLC_CON_DOES_NOT_EXIST 0x3608 +#define E_ADLC_TX_BUF_FULL 0x3609 + +#define E_ADLC_CANT_POLL_FASTER 0x360A +#define E_ADLC_CANT_POLL_SLOWER 0x360B +#define E_ADLC_INVALID_POLL_DELTA 0x360C +#define E_ADLC_INTERNAL_ERR 0x360D +#define E_ADLC_DEVICE_NOT_POLLED 0x360E +#define E_ADLC_INVALID_HQUEUE 0x360F +#define E_ADLC_INVALID_PORT 0x3610 +#define E_ADLC_INVALID_POLL_FREQ 0x3611 +#define E_ADLC_DUPLICATE_LOCAL_ADDR 0x3612 +#define E_ADLC_PACKET_LEN_NOT_VALID 0x3613 + +#define E_ADLC_RESPONSE_TIMEOUT 0x3614 +#define E_ADLC_INVALID_CMD 0x3615 +#define E_ADLC_CANT_INIT_PORT 0x3616 + +#define E_ADLC_CREATE_THREAD 0x3617 +#define E_ADLC_CANT_INIT_TAPI 0x3618 +#define E_ADLC_TEL_LINE_UNAVAIL 0x3619 +#define E_ADLC_CANT_INIT_TEL_LINE 0x361A + +#define E_ADLC_PORT_EXISTS 0x361B +#define E_ADLC_PORT_DOES_NOT_EXIST 0x361C + +#define E_ADLC_SERIAL_TX 0x361D +#define E_ADLC_SERIAL_RX 0x361E + +#define E_ADLC_CANT_OPEN_DB 0x361F +ST_RET adlcWrite(ADLC_WRITE_PACKET *adlcPacket); +ADLC_WRITE_PACKET *adlcRead(ST_VOID); +ST_VOID *adlcGetEvent(ST_INT *opcode, ST_RET *retCode); +ST_RET adlcRegisterClient (ST_UINT16 localAddr); + +/* routines to service ADLC commands */ +ST_RET adlcStartLinkManager (ST_VOID); +ST_RET adlcInit(ST_VOID); +ST_RET adlcConnectNode(ADLC_CONNECT_NODE *pstConNode); +ST_RET adlcDisconnectNode(ADLC_DISCONNECT_NODE *pstDiscNode); +ST_RET adlcConnectAll(ADLC_CONNECT_ALL *pstConAll); +ST_RET adlcDisconnectAll(ADLC_DISCONNECT_ALL *pstDiscAll); +ST_RET adlcWritePacket(ADLC_WRITE_PACKET *adlcPacket); +ST_RET adlcGetConStatus(ADLC_GET_CON_STATUS *pstGetConStatus); +ST_RET adlcAddDev(ADLC_ADD_DEV *pstAddDev); +ST_RET adlcRemoveDev(ADLC_REMOVE_DEV *pstRemoveDev); +ST_RET adlcStartPollingDev(ADLC_START_POLL_DEV *pstStartPollDev); +ST_RET adlcStopPollingDev(ADLC_STOP_POLL_DEV *pstStopPollDev); +ST_RET adlcChangePollRate(ADLC_CHANGE_POLL_RATE *pstChangePollRate); +ST_RET adlcQueryPollInfo(ADLC_QUERY_POLL_INFO *pstQueryPollInfo); +ST_VOID adlcExit (ST_VOID); + +ST_RET adlcExtWritePacket(const ADLC_EXT_WRITE_PACKET *pstExtWrite); + +#ifdef __cplusplus +} +#endif + +#endif /* end ADLC_USR */ + + + + + + diff --git a/include/inc/arg.h b/include/inc/arg.h new file mode 100644 index 0000000..49f8161 --- /dev/null +++ b/include/inc/arg.h @@ -0,0 +1,44 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1991 All Rights Reserved */ +/* */ +/* MODULE NAME : arg.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/25/98 MDE 02 Changed numArgStrings to ST_INT */ +/* 06/23/94 MDE 01 Created */ +/************************************************************************/ +/************************************************************************/ + + +ST_INT process_args (ST_INT argc, ST_CHAR **argv); +ST_VOID listValidArgs (ST_VOID); + +/************************************************************************/ + +struct arg_ctrl + { + ST_CHAR *str; /* text to be matched */ + ST_CHAR *help; /* Help text */ + ST_VOID (*fun)(ST_INT argNum, ST_CHAR *str); /* processing function */ + }; + +extern ST_INT argRetVal; +extern ST_INT argStopProc; +extern ST_INT argCurrArg; +extern ST_CHAR **argArgv; + + +/* User must define these variables */ +extern struct arg_ctrl argCtrl[]; +extern ST_INT numArgStrings; + diff --git a/include/inc/asn1defs.h b/include/inc/asn1defs.h new file mode 100644 index 0000000..8c43328 --- /dev/null +++ b/include/inc/asn1defs.h @@ -0,0 +1,40 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : asn1defs.h */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Contains definitions and global variables useful to the ASN1DE */ +/* user. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/19/01 JRB 14 Del everything & use "asn1r.h". */ +/* 11/14/01 EJV 13 Added MMS_UTC_TIME typedef. */ +/* Added asn1_wr_utc_time, asn1_get_utc_time */ +/* 06/22/00 DSF 12 Added asn1_max_bitcount */ +/* 06/16/00 JRB 11 Add #if INT64_SUPP... */ +/* 05/24/00 RKR 10 Deleted a an extra declaration of asn1_tzone */ +/* 09/13/99 MDE 09 Added SD_CONST modifiers */ +/* 10/08/98 MDE 08 Migrated to updated SLOG interface */ +/* 03/18/98 JRB 07 Add ASN1E_* defines. */ +/* Move ASN1 error codes from mmsintr2.h to here*/ +/* Add 0x7000 to all ASN.1 error codes. */ +/* 12/10/97 MDE 06 Changed get_i8 to take ST_INT8 */ +/* 09/29/97 MDE 05 Changed ASN1_LITE to MMS_LITE */ +/* 08/21/97 MDE 04 Added ASN1_ARB_FLOAT define */ +/* 08/13/97 MDE 03 Changed wr_i8 and wr_u8 to take sized int's */ +/* 06/17/97 MDE 02 Removed old debug defines */ +/* 05/20/97 MDE 01 Changes to time handling - renames, etc. */ +/* 04/02/97 7.00 MMSEASE 7.0 release. See ASN1ML70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "asn1r.h" /* Simply use all new defs in this file */ diff --git a/include/inc/asn1log.h b/include/inc/asn1log.h new file mode 100644 index 0000000..4d7676c --- /dev/null +++ b/include/inc/asn1log.h @@ -0,0 +1,106 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 1994, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : asn1log.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains ASN.1 logging definitions */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/16/03 JRB 06 Add more ERR/NERR macros. */ +/* 03/31/03 JRB 05 Use new "Base" macros SLOG_*, SLOGC_*, SLOGH.*/ +/* Add more macros. */ +/* 03/13/02 JRB 04 ALOG_PAUSEDEC, ALOG_DECLF macros do nothing. */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 10/08/98 MDE 02 Migrated to updated SLOG interface */ +/* 09/11/97 DSF 01 Adde ALOG_NERRH */ +/* 04/02/97 7.00 MMSEASE 7.0 release. See ASN1ML70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef ASN1_LOG_INCLUDED +#define ASN1_LOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/* Log type strings */ +extern SD_CONST ST_CHAR *SD_CONST _asn1_log_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _asn1_log_enc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _asn1_log_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _asn1_log_nerr_logstr; + + +#define ALOG_DECLF() +#define ALOG_PAUSEDEC(msg) + +#define ALOG_DEC0(a) \ + SLOG_0 (asn1_debug_sel & ASN1_LOG_DEC,_asn1_log_dec_logstr,a) +#define ALOG_DEC1(a,b) \ + SLOG_1 (asn1_debug_sel & ASN1_LOG_DEC,_asn1_log_dec_logstr,a,b) + +#define ALOG_CDEC0(a) \ + SLOGC_0 (asn1_debug_sel & ASN1_LOG_DEC,a) +#define ALOG_CDEC1(a,b) \ + SLOGC_1 (asn1_debug_sel & ASN1_LOG_DEC,a,b) +#define ALOG_CDEC2(a,b,c) \ + SLOGC_2 (asn1_debug_sel & ASN1_LOG_DEC,a,b,c) +#define ALOG_CDEC3(a,b,c,d) \ + SLOGC_3 (asn1_debug_sel & ASN1_LOG_DEC,a,b,c,d) +#define ALOG_CDEC4(a,b,c,d,e) \ + SLOGC_4 (asn1_debug_sel & ASN1_LOG_DEC,a,b,c,d,e) + +#define ALOG_DECH(a,b) \ + SLOGH (asn1_debug_sel & ASN1_LOG_DEC,a,b) + +#define ALOG_ENC0(a) \ + SLOG_0 (asn1_debug_sel & ASN1_LOG_ENC,_asn1_log_enc_logstr,a) +#define ALOG_ENC1(a,b) \ + SLOG_1 (asn1_debug_sel & ASN1_LOG_ENC,_asn1_log_enc_logstr,a,b) + +#define ALOG_CENC0(a) \ + SLOGC_0 (asn1_debug_sel & ASN1_LOG_ENC,a) +#define ALOG_CENC1(a,b) \ + SLOGC_1 (asn1_debug_sel & ASN1_LOG_ENC,a,b) + +#define ALOG_ENCH(a,b) \ + SLOGH (asn1_debug_sel & ASN1_LOG_ENC,a,b) + +#define ALOG_ERR0(a) \ + SLOG_0 (asn1_debug_sel & ASN1_LOG_ERR,_asn1_log_err_logstr,a) +#define ALOG_ERR1(a,b) \ + SLOG_1 (asn1_debug_sel & ASN1_LOG_ERR,_asn1_log_err_logstr,a,b) +#define ALOG_ERR2(a,b,c) \ + SLOG_2 (asn1_debug_sel & ASN1_LOG_ERR,_asn1_log_err_logstr,a,b,c) +#define ALOG_ERR3(a,b,c,d) \ + SLOG_3 (asn1_debug_sel & ASN1_LOG_ERR,_asn1_log_err_logstr,a,b,c,d) + +#define ALOG_NERR0(a) \ + SLOG_0 (asn1_debug_sel & ASN1_LOG_NERR,_asn1_log_nerr_logstr,a) +#define ALOG_NERR1(a,b) \ + SLOG_1 (asn1_debug_sel & ASN1_LOG_NERR,_asn1_log_nerr_logstr,a,b) +#define ALOG_NERR2(a,b,c) \ + SLOG_2 (asn1_debug_sel & ASN1_LOG_NERR,_asn1_log_nerr_logstr,a,b,c) +#define ALOG_NERR3(a,b,c,d) \ + SLOG_3 (asn1_debug_sel & ASN1_LOG_NERR,_asn1_log_nerr_logstr,a,b,c,d) + +#define ALOG_NERRH(a,b) \ + SLOGH (asn1_debug_sel & ASN1_LOG_NERR,a,b) + +#ifdef __cplusplus +} +#endif + + +/************************************************************************/ +#endif /* End of ASN1_LOG_INCLUDED */ +/************************************************************************/ diff --git a/include/inc/asn1r.h b/include/inc/asn1r.h new file mode 100644 index 0000000..058f6bb --- /dev/null +++ b/include/inc/asn1r.h @@ -0,0 +1,718 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2009, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : asn1r.h */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Contains definitions and global variables useful to the ASN1DE */ +/* user. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/21/09 JRB 31 Add asn1r_bitstr_truncated in ASN1_DEC_CTXT. */ +/* Del GET_CONSTRUCTED_*STRINGS defines. */ +/* 05/28/09 JRB 30 Add asn1r_decode_init, asn1r_get_tag functs. */ +/* Add asn1r_msg_start in ASN1_DEC_CTXT struct. */ +/* Add asn1r_strt_constr_indef. */ +/* 01/15/09 MDE 29 Added asn1_peek, removed asn1r_head_decode */ +/* 11/12/08 MDE 28 Added asn1r_last_byte, asn1r_head_decode rc */ +/* 07/02/07 JRB 26 Chg ..fixlen, ..varlen arg to (ST_UCHAR *). */ +/* 12/20/06 JRB 25 Add bstrcmp. */ +/* 03/17/06 JRB 24 Add asn1r_anytag_fun, ASN1_ANYTAG_METHOD, */ +/* ASN1MASK_*. */ +/* Chg BSTR_BIT_GET macro to return only 0 or 1.*/ +/* 12/05/05 JRB 23 Add asn1r_skip_elmnt & more asn1r_get* protos*/ +/* 08/01/05 JRB 22 Add const on asn1r_wr_vstr, asn1_wr_octstr args.*/ +/* 03/23/05 JRB 21 Move APP_REF from suicacse to here so almost */ +/* any SISCO app can use it. */ +/* 07/08/04 JRB 20 Add define TIME_T_1984_JAN_1 & other defines.*/ +/* Add asn1_convert_timet_to_btime6. */ +/* 10/13/03 JRB 19 Add ASN1E_DECODE_OTHER, ASN1E_ENCODE_OTHER. */ +/* 03/31/03 JRB 18 Add UTF8string support. */ +/* asn1r_get_bitstr: add max_bits arg. */ +/* 12/14/02 JRB 17 Add BSTR_*, MMS_BVSTRING, bstrcpy, bvstrcpy */ +/* 11/11/02 EJV 16 asn1r_tag_add: added type cast */ +/* 11/08/02 JRB 15 Add ASN1_DEC_PTR, ASN1_DEC_LEN macros. */ +/* 10/29/02 JRB 14 Add asn1r_magic to ASN1_ENC_CTXT. */ +/* 10/25/02 JRB 13 Add ASN1_ENC_PTR, ASN1_ENC_LEN macros. */ +/* Add MMS_BTIME6 struct. */ +/* 07/03/02 EJV 12 MMS_UTC_TIME: chg name usec to fraction. */ +/* 01/22/02 JRB 11 Add "asn1r_buf_end" to ASN1_ENC_CTXT. */ +/* Chg asn1r_end_of_buffer to asn1r_buf_start */ +/* & asn1r_field_start to asn1r_field_end */ +/* & _asn1_constr_start to asn1r_constr_end */ +/* in ENC_CTX (start means start, end means end)*/ +/* 01/07/02 EJV 09 Added asn1_ prefix to convert_... functions. */ +/* 01/04/02 EJV 08 Add convert_btod_to_utc, convert_utc_to_btod */ +/* 12/20/01 JRB 07 Split ASN1_CTXT into ASN1_DEC_CTXT, ASN1_ENC_CTXT*/ +/* Del unused calendar stuff. */ +/* Del backward compatibility defines. */ +/* Chg asn1r_objidcmp to asn1_objidcmp. */ +/* Del unused tzhour_diff, tconst, default_dcomp*/ +/* Del unused strt_asn1,asn1_tz_calc,asn1_is_dst*/ +/* 11/09/01 EJV 06 Added MMS_UTC_TIME typedef. */ +/* Added asn1r_wr_utc_time, asn1r_get_utc_time */ +/* ASN1_CTXT: del _save_asn1_len, _save_asn1_ptr*/ +/* 08/15/00 JRB 05 Add asn1_ctxt "forward reference". */ +/* 06/19/00 JRB 04 Add #if INT64_SUPP... */ +/* 05/25/00 RKR 03 Deleted a an extra declaration of asn1_tzone */ +/* 07/29/99 MDE 02 Added TABLE method */ +/* 07/26/99 MDE 01 New, derived from asn1defs.h */ +/************************************************************************/ + +#if !defined(ASN1DEFS_INCLUDED) && !defined(ASN1R_INCLUDED) +#define ASN1R_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ + +#include "slog.h" + +/* Defines for UNICODE local data format. */ +#define UNICODE_UTF8 0 +#define UNICODE_UTF16 1 +#if !defined(UNICODE_LOCAL_FORMAT) +#if defined(_WIN32) +#define UNICODE_LOCAL_FORMAT UNICODE_UTF16 +#else +#define UNICODE_LOCAL_FORMAT UNICODE_UTF8 /*default format */ +#endif +#endif /* !defined(UNICODE_LOCAL_FORMAT) */ + +/************************************************************************/ +/* asn1_debug_sel bit assignments */ + +#define ASN1_LOG_DEC 0x0001 +#define ASN1_LOG_ENC 0x0002 +#define ASN1_LOG_ERR 0x0004 +#define ASN1_LOG_NERR 0x0008 + +/************************************************************************/ +/* These are S_LOG control items for ASN1 logging */ + +extern ST_UINT asn1_debug_sel; + +/************************************************************************/ +/* Support for development time debugging can be enabled here */ +/* #define DEBUG_ASN1_DECODE */ + +/************************************************************************/ +/* Support for seldom needed decode features can be disabled here */ + +#if !defined(MMS_LITE) +#define ASN1_ARB_FLOAT +#endif + +/************************************************************************/ +/* Helpful Time-related defines */ + +#define SECONDS_PER_DAY (60*60*24) +#define MILLISECONDS_PER_DAY (1000 * SECONDS_PER_DAY) +#define DAYS_FROM_1970_TO_1984 ((11*365) + (3*366)) /*includes 3 leap years 1972, 1976, 1980*/ +#define TIME_T_1984_JAN_1 (DAYS_FROM_1970_TO_1984 * SECONDS_PER_DAY) + +/************************************************************************/ +/* Binary Time Of Day */ + +#define MMS_BTOD4 4 +#define MMS_BTOD6 6 + +typedef struct btod_data + { + ST_INT form; /* MMS_BTOD6, MMS_BTOD4 */ + ST_INT32 ms; /* Number of milliseconds since midnight */ + ST_INT32 day; /* Number of days since Jan 1, 1984 */ + } MMS_BTOD; + +/* MMS_BTIME6: this structure is the format used to pass "Btime6" data */ +/* (i.e. ISO/IEC 9506-2 TimeOfDay with size=6) between the user and */ +/* the ASN.1 encoder/decoder (i.e. ms_asn1_to_local & ms_local_to_asn1).*/ +typedef struct + { + ST_INT32 ms; /* Number of milliseconds since midnight */ + ST_INT32 day; /* Number of days since Jan 1, 1984 */ + } MMS_BTIME6; + +/************************************************************************/ +/* UTC Time */ + +typedef struct mms_utc_time_tag + { + ST_UINT32 secs; /* Number of seconds since January 1, 1970 */ + ST_UINT32 fraction; /* Fraction of a second */ + ST_UINT32 qflags; /* Quality flags, 8 least-significant bits only */ + } MMS_UTC_TIME; + +ST_RET asn1_convert_btod_to_utc (MMS_BTOD *btod, MMS_UTC_TIME *utc); +ST_RET asn1_convert_utc_to_btod (MMS_UTC_TIME *utc, MMS_BTOD *btod); +ST_RET asn1_convert_timet_to_btime6 (time_t tThis, MMS_BTIME6 *bTime6); + +/************************************************************************/ +/* Variable Length Bitstring */ +/* This structure defines the format used to pass "variable length */ +/* bitstring" data between the user and */ +/* the ASN.1 encoder/decoder (i.e. ms_asn1_to_local & ms_local_to_asn1).*/ +/* NOTE: For bitstrings longer than 8 bits, the actual data extends */ +/* beyond the end of this struct. */ + +typedef struct + { + ST_INT16 len; + ST_UCHAR data[1]; + } MMS_BVSTRING; + +/************************************************************************/ +/* VMS Float Format select */ + +#define A_D_FLOAT 1 +#define A_G_FLOAT 2 +extern ST_INT asn1_vax_double_type; + +/************************************************************************/ +/* ASN1-DE limitiations */ + +#define ASN1_MAX_PDU 0x7FFF /* maximum decodable message length */ +#define ASN1_MAX_FIELD 0x7FFF /* maximum field (data element) length */ +#define ASN1_MAX_LEVEL 50 /* maximum supported nesting level */ + +/************************************************************************/ +/* ASN.1 Definitions to support identifier construction by bit OR. */ +/* Used to make up and test 'tag' bits. */ + +/* These used in ASN1_ANYTAG_METHOD decode method. */ +#define ASN1MASK_UNI 0x0000 /* universal class */ +#define ASN1MASK_APP 0x4000 /* application wide */ +#define ASN1MASK_CTX 0x8000 /* context specific */ +#define ASN1MASK_PRV 0xC000 /* private use */ +#define ASN1MASK_CONSTR 0x2000 /* constructor */ + +/* These used in other decode methods and in encoder. */ +#define UNI 0x00 /* universal class */ +#define APP 0x40 /* application wide */ +#define CTX 0x80 /* context specific */ +#define PRV 0xC0 /* private use */ +#define CONSTR 0x20 /* constructor */ + +#define DEF 0x00 /* definite length constructor */ +#define INDEF 0xFF /* indefinite length constructor */ + +/* Universal class ASN.1 ID code definitions */ +#define EOC_CODE 0x00 +#define BOOL_CODE 0x01 +#define INT_CODE 0x02 +#define BITS_CODE 0x03 +#define OCT_CODE 0x04 +#define NULL_CODE 0x05 +#define OBJ_ID_CODE 0x06 +#define OBJDSCR_CODE 0x07 +#define EXTERN_CODE 0x08 +#define SEQ_CODE 0x10 +#define SET_CODE 0x11 +#define NUMSTR_CODE 0x12 +#define PRTSTR_CODE 0x13 +#define S61STR_CODE 0x14 +#define S100STR_CODE 0x15 +#define IA5STR_CODE 0x16 +#define UTCTIM_CODE 0x17 +#define GENTIM_CODE 0x18 +#define GRAFSTR_CODE 0x19 +#define VISTR_CODE 0x1A +#define GENSTR_CODE 0x1B + + +/************************************************************************/ +/* ASN.1 decode error definitions */ +/* Used as the argument to "asn1_set_dec_err" function which sets the */ +/* global variable "asn1_pdu_dec_err". */ +/************************************************************************/ + +#define NO_DECODE_ERR 0 /* no decode error */ +#define ASN1E_NEST_TOO_DEEP 0x7001 +#define ASN1E_UNEXPECTED_CLASS 0x7002 +#define ASN1E_UNEXPECTED_TAG 0x7003 +#define ASN1E_ID_TOO_BIG 0x7004 +#define ASN1E_CSTR_INVALID_LEN 0x7005 +#define ASN1E_INVALID_LENGTH 0x7006 +#define ASN1E_UNEXPECTED_FORM 0x7007 +#define ASN1E_PDU_TOO_BIG 0x7008 +#define ASN1E_END_O_BUFFER 0x7009 +#define ASN1E_BITCSTR_TOO_BIG 0x700a +#define ASN1E_INVALID_BITSTR 0x700b +#define ASN1E_OCTSTR_TOO_BIG 0x700c +#define ASN1E_INVALID_BOOLEAN 0x700d +#define ASN1E_END_OF_MESSAGE 0x700e +#define ASN1E_END_OF_CSTR 0x700f + +/* CRITICAL: The rest of the ASN.1 decode error definitions must not */ +/* must not be changed. The lower 2 nibbles are used to set the */ +/* REJECT class and code (mmsdec_map_err saves value to rslt.err_code */ +/* which is used in "mmspdu.c" to generate REJECT class and code). */ + +/************************************************************************/ +/* CONFIRMED REQUEST REJECT DEFINITIONS */ +/************************************************************************/ +#define REQ_UNSPECIFIED 0x7010 +#define REQ_UNREC_SERV 0x7011 +#define REQ_UNREC_MOD 0x7012 +#define REQ_INVAL_INVOKE 0x7013 +#define REQ_INVAL_ARG 0x7014 +#define REQ_INVAL_MOD 0x7015 +#define REQ_OUTSTD_EXCEED 0x7016 +#define REQ_EXCSV_LENGTH 0x7017 +#define REQ_EXCSV_NEST 0x7018 +#define REQ_BAD_VALUE 0x7019 + +/************************************************************************/ +/* CONFIRMED RESPONSE REJECT DEFINITIONS */ +/************************************************************************/ +#define RESP_UNSPECIFIED 0x7020 +#define RESP_UNREC_SERV 0x7021 +#define RESP_INVAL_INVOKE 0x7022 +#define RESP_INVAL_RSLT 0x7023 +#define RESP_EXCSV_LENGTH 0x7024 +#define RESP_EXCSV_NEST 0x7025 +#define RESP_BAD_VALUE 0x7026 + +/************************************************************************/ +/* CONFIRMED ERROR REJECT DEFINITIONS */ +/************************************************************************/ +#define ERR_UNSPECIFIED 0x7030 +#define ERR_UNREC_SERV 0x7031 +#define ERR_INVAL_INVOKE 0x7032 +#define ERR_INVAL_SERV 0x7033 +#define ERR_BAD_VALUE 0x7034 + +/************************************************************************/ +/* UNCONFIRMED PDU REJECT DEFINITIONS */ +/************************************************************************/ +#define UNCONF_UNSPECIFIED 0x7040 +#define UNCONF_UNREC_SERV 0x7041 +#define UNCONF_INVAL_ARG 0x7042 +#define UNCONF_EXCSV_NEST 0x7043 +#define UNCONF_BAD_VALUE 0x7044 + +/************************************************************************/ +/* PDU REJECT DEFINITIONS */ +/************************************************************************/ +#define PDU_UNKNOWN_TYPE 0x7050 +#define PDU_INVALID 0x7051 + +/************************************************************************/ +/* CANCEL REQUEST REJECT DEFINITIONS */ +/************************************************************************/ +#define CANREQ_UNSPECIFIED 0x7060 +#define CANREQ_INVAL_INVOKE 0x7061 + +/************************************************************************/ +/* CANCEL RESPONSE REJECT DEFINITIONS */ +/************************************************************************/ +#define CANRESP_UNSPECIFIED 0x7070 +#define CANRESP_INVAL_INVOKE 0x7071 + +/************************************************************************/ +/* CANCEL ERROR REJECT DEFINITIONS */ +/************************************************************************/ +#define CANERR_UNSPECIFIED 0x7080 +#define CANERR_INVAL_INVOKE 0x7081 +#define CANERR_INVAL_SERV 0x7082 +#define CANERR_BAD_VALUE 0x7083 + +/************************************************************************/ +/* CONCLUDE REQUEST REJECT DEFINITIONS */ +/************************************************************************/ +#define CONREQ_UNSPECIFIED 0x7090 +#define CONREQ_INVAL_ARG 0x7091 + +/************************************************************************/ +/* CONCLUDE RESPONSE REJECT DEFINITIONS */ +/************************************************************************/ +#define CONRESP_UNSPECIFIED 0x70A0 +#define CONRESP_INVAL_RSLT 0x70A1 + +/************************************************************************/ +/* CONCLUDE ERROR REJECT DEFINITIONS */ +/************************************************************************/ +#define CONERR_UNSPECIFIED 0x70B0 +#define CONERR_INVAL_SERV 0x70B1 +#define CONERR_BAD_VALUE 0x70B2 + +/************************************************************************/ +/* OTHER ASN.1 ENCODE/DECODE ERROR DEFINITIONS */ +/************************************************************************/ +#define ASN1E_DECODE_OTHER 0x70C0 +#define ASN1E_ENCODE_OTHER 0x70C1 + +/************************************************************************/ +/* General variables and pointers used by the ASN1 system. */ +/************************************************************************/ + +#define ASN1_TAG_METHOD 0 /* decode by tag method */ +#define ASN1_CLASS_METHOD 1 /* decode by class method */ +#define ASN1_TABLE_METHOD 2 /* decode by table method */ +#define ASN1_ANYTAG_METHOD 3 /* decode by "anytag" method */ + /* same callback for any tag of any class*/ +#define CSTR_DONE_FUN ac->asn1r_c_done_fun[ac->asn1r_msg_level] + +/************************************************************************/ +/* This define is the maximum tag + length for a MMS-EASE encoded data */ +/* element (actually probably is 9), and is used in fin_constr and */ +/* fin_prim to prevent encode buffer overrun */ + +#define ASN1_MAX_ELEMENT_OVERHEAD 10 + +struct asn1_dec_ctxt; /* Forward reference */ +/************************************************************************/ +/************************************************************************/ +/* TAG METHOD STRUCTURES AND DEFINES */ + +#define ASN1R_TAG_VAL(class,code) (((ST_UINT16)(class) << 8) | (code)) + +typedef struct + { + ST_UINT16 _asn1r_tag; + ST_VOID (*_asn1r_tag_fun)(struct asn1_dec_ctxt *ac); + } ASN1R_TAG_PAIR; + +/* Decode users: Select the structure that has sufficient tag capacity */ +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[1]; } ASN1R_TAG_CTRL_1; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[2]; } ASN1R_TAG_CTRL_2; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[3]; } ASN1R_TAG_CTRL_3; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[4]; } ASN1R_TAG_CTRL_4; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[5]; } ASN1R_TAG_CTRL_5; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[6]; } ASN1R_TAG_CTRL_6; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[7]; } ASN1R_TAG_CTRL_7; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[8]; } ASN1R_TAG_CTRL_8; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[9]; } ASN1R_TAG_CTRL_9; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[10];} ASN1R_TAG_CTRL_10; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[11];} ASN1R_TAG_CTRL_11; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[12];} ASN1R_TAG_CTRL_12; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[13];} ASN1R_TAG_CTRL_13; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[14];} ASN1R_TAG_CTRL_14; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[15];} ASN1R_TAG_CTRL_15; + + +/************************************************************************/ +/* ASN.1 Context */ +/* This data structure is used to store all ASN.1 encode/decode context */ +/* information. If an application provides thread safe storage for this */ +/* data structure the ASN.1 tools become thread safe. */ + +#define ASN1_MAX_USR_INFO 5 +#define MAX_TAG_FUN 16 + +typedef struct asn1_dec_ctxt + { +/****** User and Internal Use ******/ + +/* User State */ + ST_VOID *usr_info[ASN1_MAX_USR_INFO]; + +/* General variables and pointers */ + ST_BOOLEAN asn1r_decode_done; + ST_UCHAR *asn1r_field_ptr; + ST_UCHAR *asn1r_field_start; + ST_UCHAR *asn1r_done_ptr; + ST_UCHAR asn1r_constr_elmnt; + ST_UCHAR asn1r_elmnt_class; + ST_UINT16 asn1r_elmnt_id; + ST_INT asn1r_elmnt_len; + ST_INT asn1r_msg_level; + ST_BOOLEAN asn1r_indef_flag; /* flag for indef cstr */ + ST_RET asn1r_pdu_dec_err; + ST_INT asn1r_decode_method; + ST_INT asn1r_save_method; + ST_INT asn1r_max_bits; + ST_INT asn1r_bitcount; + ST_BOOLEAN asn1r_bitstr_truncated; /* SD_TRUE if bitstr truncated */ + /* while decoding. */ + ST_INT asn1r_octetcount; + +/* For ASN1 decode table mode */ + ST_VOID *asn1r_tag_table; + +/* Function pointers used by decoder users */ + ST_VOID (*asn1r_decode_done_fun)(struct asn1_dec_ctxt *ac); + ST_VOID (*asn1r_err_fun)(struct asn1_dec_ctxt *ac, ST_RET err_code); + ST_VOID (*asn1r_c_done_fun[ASN1_MAX_LEVEL])(struct asn1_dec_ctxt *ac); + ST_VOID (*asn1r_u_id_fun)(struct asn1_dec_ctxt *ac, ST_UINT16 id); + ST_VOID (*asn1r_a_id_fun)(struct asn1_dec_ctxt *ac, ST_UINT16 id); + ST_VOID (*asn1r_c_id_fun)(struct asn1_dec_ctxt *ac, ST_UINT16 id); + ST_VOID (*asn1r_p_id_fun)(struct asn1_dec_ctxt *ac, ST_UINT16 id); + /* asn1r_anytag_fun called for ANY tag of ANY class if */ + /* asn1r_decode_method==ASN1_ANYTAG_METHOD. */ + /* "id" argument has bits set to indicate class and/or constructor. */ + ST_VOID (*asn1r_anytag_fun)(struct asn1_dec_ctxt *ac, ST_UINT16 id); + +/****** Internal Use Only ******/ +/* Decode variables */ + ST_INT _asn1_maxoctets; + ST_UCHAR *_asn1_octetptr; + + ST_UCHAR *_ad_bitptr; + +/* Function pointers used internally by the ASN.1 tools */ + ST_VOID (*_asn1r_cstr_done_save)(struct asn1_dec_ctxt *ac); + ST_VOID (*_asn1r_fun_save)(struct asn1_dec_ctxt *ac); + + ST_INT _asn1r_ntag; + ST_UINT16 _asn1r_valid_tags[MAX_TAG_FUN]; + ST_VOID (*_asn1r_tag_fun[MAX_TAG_FUN])(struct asn1_dec_ctxt *ac); + ST_INT _asn1r_old_ntag; + + ST_BOOLEAN _asn1_indef_track[ASN1_MAX_LEVEL]; + ST_UCHAR *_asn1_constr_start[ASN1_MAX_LEVEL]; + ST_INT _asn1_byte_count[ASN1_MAX_LEVEL]; + + ST_INT _ad_parse_method_save; + ST_VOID (*_ad_parse_asn1r_fun_save)(struct asn1_dec_ctxt *ac); + + ST_UCHAR *_contents_done; /* will be here when done parsing cstr contents */ + ST_UCHAR *_parse_begin_ptr; /* pointer to beginning of element being skipped*/ + + ST_UCHAR *asn1r_msg_start; /* ptr to beginning of ASN.1 message */ + /* used to calc offset within message */ + /* set by asn1r_decode_init */ + /* used by asn1r_get_tag */ + } ASN1_DEC_CTXT; + +typedef struct asn1_enc_ctxt + { +/* General variables and pointers */ + ST_UCHAR *asn1r_field_ptr; + ST_UCHAR *asn1r_field_end; + ST_INT asn1r_msg_level; + ST_UCHAR *asn1r_buf_start; /* ptr to first byte of buffer */ + ST_UCHAR *asn1r_buf_end; /* ptr to last byte of buffer */ + ST_BOOLEAN asn1r_encode_overrun; + ST_UINT16 asn1r_magic; /* Use to verify asn1r_strt.. was called*/ + ST_UCHAR *asn1r_constr_end[ASN1_MAX_LEVEL]; + } ASN1_ENC_CTXT; + +/* Set "asn1r_magic" in ASN1_ENC_CTXT to this value in "asn1r_strt_asn1_bld".*/ +/* Check later to be sure asn1r_strt_asn1_bld was called. */ +#define ASN1_ENC_MAGIC_NUMBER 0xABCD +/************************************************************************/ + +ASN1_DEC_CTXT *asn1r_get_ctxt (ST_VOID); + +ST_VOID asn1r_decode_asn1 (ASN1_DEC_CTXT *ac, ST_UCHAR *ptr, ST_INT len); +ST_VOID asn1r_decode_asn1_seq (ASN1_DEC_CTXT *ac, ST_UCHAR *ptr, ST_INT len); +ST_VOID asn1r_set_dec_err (ASN1_DEC_CTXT *ac, ST_RET err_code); +ST_VOID asn1r_done_err (ASN1_DEC_CTXT *ac); +ST_VOID asn1r_cstr_done_err (ASN1_DEC_CTXT *ac); +ST_VOID asn1r_set_all_cstr_done (ASN1_DEC_CTXT *ac); + + +ST_VOID asn1r_class_err (ASN1_DEC_CTXT *ac, ST_UINT16 id); +ST_VOID asn1r_chk_getcstr_done (ASN1_DEC_CTXT *ac); + +#if !defined(ASN1R_FAST_TAG_ADD) + +#define ASN1R_TAG_ADD(ac, class, code, fcn_ptr)\ + asn1r_tag_add (ac, (ST_UINT16)(((ST_UINT16)(class) << 8) | (code)), (fcn_ptr)) + +#else + +#define ASN1R_TAG_ADD(ac, class, code, fcn_ptr)\ + {\ + ac->_asn1r_valid_tags[ac->_asn1r_ntag] = \ + (((ST_UINT16)(class) << 8) | (code));\ + ac->_asn1r_tag_fun[ac->_asn1r_ntag] = (ST_VOID (*)(ASN1_DEC_CTXT *)) fcn_ptr;\ + ac->_asn1r_ntag++;\ + } +#endif + + +#define ASN1R_TAG_DEL(ac, class, code)\ + asn1r_tag_del (ac, (((ST_UINT16)(class) << 8) | (code))) + +ST_VOID asn1r_tag_add (ASN1_DEC_CTXT *ac, ST_UINT16 tag_class, + ST_VOID (*fcn_ptr)(ASN1_DEC_CTXT *ac)); + +ST_VOID asn1r_tag_del (ASN1_DEC_CTXT *ac, ST_UINT16 tag); +ST_VOID asn1r_tag_restore (ASN1_DEC_CTXT *ac); +ST_RET asn1_peek (ASN1_DEC_CTXT *ac, ST_UCHAR *ptr, ST_INT len); + +ST_VOID asn1r_strt_asn1_bld (ASN1_ENC_CTXT *ac, ST_UCHAR *bufptr, ST_INT buflen); +ST_VOID asn1r_fin_prim (ASN1_ENC_CTXT *ac, ST_UINT16 id_code, ST_UINT16 tag); +ST_VOID asn1r_fin_constr (ASN1_ENC_CTXT *ac, ST_UINT16 id_code, ST_UINT16 el_tag, ST_BOOLEAN indef); +ST_VOID asn1r_strt_constr (ASN1_ENC_CTXT *ac); +ST_VOID asn1r_strt_constr_indef (ASN1_ENC_CTXT *ac); /* start indef len constr*/ + +ST_VOID asn1r_wr_u8 (ASN1_ENC_CTXT *ac, ST_UINT8 data); +ST_VOID asn1r_wr_u16 (ASN1_ENC_CTXT *ac, ST_UINT16 data); +ST_VOID asn1r_wr_u32 (ASN1_ENC_CTXT *ac, ST_UINT32 data); +ST_VOID asn1r_wr_i8 (ASN1_ENC_CTXT *ac, ST_INT8 data); +ST_VOID asn1r_wr_bool (ASN1_ENC_CTXT *ac, ST_BOOLEAN data); +ST_VOID asn1r_wr_i16 (ASN1_ENC_CTXT *ac, ST_INT16 data); +ST_VOID asn1r_wr_i32 (ASN1_ENC_CTXT *ac, ST_INT32 data); +ST_VOID asn1r_wr_vstr (ASN1_ENC_CTXT *ac, const ST_CHAR *data); +ST_VOID asn1r_wr_delmnt (ASN1_ENC_CTXT *ac, ST_UCHAR *bufptr, ST_INT buflen); +ST_VOID asn1r_wr_btod (ASN1_ENC_CTXT *ac, MMS_BTOD *data); +ST_VOID asn1r_wr_time (ASN1_ENC_CTXT *ac, time_t data); +ST_VOID asn1r_wr_objid (ASN1_ENC_CTXT *ac, ST_INT16 *data, ST_INT num_el); +ST_VOID asn1r_wr_bitstr (ASN1_ENC_CTXT *ac, ST_UCHAR *bitptr, ST_INT numbits); +ST_VOID asn1r_wr_octstr (ASN1_ENC_CTXT *ac, const ST_UCHAR *octptr, ST_INT numoctets); +ST_VOID asn1r_wr_float (ASN1_ENC_CTXT *ac, ST_FLOAT data); +ST_VOID asn1r_wr_double (ASN1_ENC_CTXT *ac, ST_DOUBLE data); +ST_VOID asn1r_wr_utc_time (ASN1_ENC_CTXT *ac, MMS_UTC_TIME *data); +ST_RET asn1r_wr_utf8 (ASN1_ENC_CTXT *ac, ST_CHAR *data, ST_INT el_len); + +ST_RET asn1r_get_identifier (ASN1_DEC_CTXT *ac, ST_CHAR *dest); +ST_RET asn1r_get_objid (ASN1_DEC_CTXT *ac, ST_INT16 component_list[], ST_INT *num_components); +ST_RET asn1r_get_bool (ASN1_DEC_CTXT *ac, ST_BOOLEAN *dest); +ST_VOID asn1r_get_strn (ASN1_DEC_CTXT *ac, ST_CHAR *dest); +ST_RET asn1r_get_nstr (ASN1_DEC_CTXT *ac, ST_CHAR *dest); +ST_RET asn1r_get_pstr (ASN1_DEC_CTXT *ac, ST_CHAR *dest); +ST_RET asn1r_get_vstr (ASN1_DEC_CTXT *ac, ST_CHAR *dest); +ST_RET asn1r_get_vstr_maxlen (ASN1_DEC_CTXT *aCtx, ST_CHAR *ptr, ST_INT max_len); +ST_RET asn1r_get_i8 (ASN1_DEC_CTXT *ac, ST_INT8 *dest); +ST_RET asn1r_get_i16 (ASN1_DEC_CTXT *ac, ST_INT16 *dest); +ST_RET asn1r_get_i32 (ASN1_DEC_CTXT *ac, ST_INT32 *dest); +ST_RET asn1r_get_u8 (ASN1_DEC_CTXT *ac, ST_UCHAR *dest); +ST_RET asn1r_get_u16 (ASN1_DEC_CTXT *ac, ST_UINT16 *dest); +ST_RET asn1r_get_u32 (ASN1_DEC_CTXT *ac, ST_UINT32 *dest); +ST_RET asn1r_get_btod (ASN1_DEC_CTXT *ac, MMS_BTOD *dest); +ST_RET asn1r_get_time (ASN1_DEC_CTXT *ac, time_t *dest); +ST_RET asn1r_get_bitstr (ASN1_DEC_CTXT *ac, ST_UCHAR *dest, ST_INT max_bits); +ST_VOID asn1r_get_bitstr_cstr (ASN1_DEC_CTXT *ac, ST_INT bits, ST_UCHAR *ptr); +ST_RET asn1r_get_octstr (ASN1_DEC_CTXT *ac, ST_UCHAR *dest); +ST_RET asn1r_get_octstr_fixlen (ASN1_DEC_CTXT *aCtx, ST_UCHAR *ptr, ST_INT len); +ST_RET asn1r_get_octstr_varlen (ASN1_DEC_CTXT *aCtx, ST_UCHAR *ptr, ST_INT maxlen, ST_INT *lenout); +ST_VOID asn1r_get_octstr_cstr (ASN1_DEC_CTXT *ac, ST_INT numoctets, ST_UCHAR *octptr); +ST_VOID asn1r_get_delmnt (ASN1_DEC_CTXT *ac, ST_INT buflen, ST_UCHAR *bufptr, + ST_VOID (*done_fun)(ASN1_DEC_CTXT *ac)); +ST_RET asn1r_get_float (ASN1_DEC_CTXT *ac, ST_FLOAT *dest); +ST_RET asn1r_get_double (ASN1_DEC_CTXT *ac, ST_DOUBLE *dest); +ST_RET asn1r_get_utc_time (ASN1_DEC_CTXT *ac, MMS_UTC_TIME *dest); +ST_RET asn1r_get_utf8 (ASN1_DEC_CTXT *ac, ST_CHAR *ptr, ST_INT el_len); + +#ifdef INT64_SUPPORT +ST_VOID asn1r_wr_i64 (ASN1_ENC_CTXT *ac, ST_INT64 data); +ST_VOID asn1r_wr_u64 (ASN1_ENC_CTXT *ac, ST_UINT64 data); +ST_RET asn1r_get_i64 (ASN1_DEC_CTXT *ac, ST_INT64 *dest); +ST_RET asn1r_get_u64 (ASN1_DEC_CTXT *ac, ST_UINT64 *dest); +#endif /* INT64_SUPPORT */ + +ST_VOID asn1r_parse_next (ASN1_DEC_CTXT *ac, ST_VOID (*done_fun)(ASN1_DEC_CTXT *ac)); +ST_VOID asn1r_parse_cstr_contents (ASN1_DEC_CTXT *ac, ST_VOID (*done_fun)(ASN1_DEC_CTXT *ac)); + +ST_RET asn1r_skip_elmnt (ASN1_DEC_CTXT *aCtx); + +/* Functions for simplified decode scheme (no function pointers). */ +ST_RET asn1r_decode_init (ASN1_DEC_CTXT *ac, + ST_UCHAR *ptr, /* ASN.1 message to decode */ + ST_INT len); /* length of ASN.1 message */ +ST_RET asn1r_get_tag (ASN1_DEC_CTXT *ac, + ST_UINT16 *tag_out); /* out: decoded tag */ + +/************************************************************************/ +/* These macros simplify access to members of the ASN1_ENC_CTXT struct. */ +/************************************************************************/ +/* This macro returns a pointer to the start of the ASN.1 encoded data. */ +#define ASN1_ENC_PTR(aCtx) ((aCtx)->asn1r_field_ptr+1) +/* This macro returns the length (in bytes) of the ASN.1 encoded data. */ +#define ASN1_ENC_LEN(aCtx) ((aCtx)->asn1r_buf_end - (aCtx)->asn1r_field_ptr) + +/* This macro returns a pointer to the start of the ASN.1 DECODED data. */ +#define ASN1_DEC_PTR(aCtx) ((aCtx)->asn1r_field_ptr) +/* This macro returns the length (in bytes) of the ASN.1 DECODED data. */ +#define ASN1_DEC_LEN(aCtx) ((aCtx)->asn1r_elmnt_len) + +/************************************************************************/ +/* OBJECT IDENTIFIER */ +/************************************************************************/ + +#define MAX_OBJID_COMPONENTS 16 + +struct mms_obj_id + { + ST_INT num_comps; /* number of objid components */ + ST_INT16 comps[MAX_OBJID_COMPONENTS]; /* identifier components */ + SD_END_STRUCT + }; +typedef struct mms_obj_id MMS_OBJ_ID; +ST_BOOLEAN asn1_objidcmp (MMS_OBJ_ID *obj1, MMS_OBJ_ID *obj2); + +/************************************************************************/ +/* Application Reference data structure */ +/************************************************************************/ + +#define APP_REF_FORM1 0 +#define APP_REF_FORM2 1 + +struct form1 + { + ST_UCHAR *ptr; /* ptr to something */ + ST_INT16 len; /* length of contents at ptr */ + }; +typedef struct form1 FORM1_T; + +struct app_ref + { + ST_INT16 form; /* tells if form 1 or form 2 */ + ST_BOOLEAN ap_title_pres; /* tells if AP title is there */ + union /* AP title differs in form */ + { + FORM1_T form_1; /* form 1 of AP title is ASN.1 */ + MMS_OBJ_ID form_2; /* form 2 of AP title is objectid*/ + } ap_title; + ST_BOOLEAN ap_invoke_pres; /* tells if AP invoke is there */ + ST_INT32 ap_invoke; + ST_BOOLEAN ae_qual_pres; /* tells if AE qualifier is there*/ + union /* AE qualifier differs in form */ + { + FORM1_T form_1; /* form 1 of AE qual is ASN.1 */ + ST_INT32 form_2; /* form 2 if AE qual is long word*/ + } ae_qual; + ST_BOOLEAN ae_invoke_pres; /* tells if AE invoke is there */ + ST_INT32 ae_invoke; + }; +typedef struct app_ref APP_REF; + +/************************************************************************/ +/* Miscellaneous functions/macros. */ +/************************************************************************/ +/* Functions to copy bitstrings and "variable length bitstrings". */ +ST_VOID bstrcpy (ST_UCHAR *dstptr, ST_UCHAR *srcptr, ST_INT numbits); +ST_VOID bvstrcpy (MMS_BVSTRING *dstptr, MMS_BVSTRING *srcptr); +ST_INT bstrcmp (ST_UCHAR *dstptr, ST_UCHAR *srcptr, ST_INT numbits); + +/* Macros to access each individual bit of any bitstring. */ +#define BSTR_BIT_SET_ON(ptr,bitnum) \ + ( ((ST_UINT8 *)(ptr))[(bitnum)/8] |= (0x80>>((bitnum)&7)) ) +#define BSTR_BIT_SET_OFF(ptr,bitnum) \ + ( ((ST_UINT8 *)(ptr))[(bitnum)/8] &= ~(0x80>>((bitnum)&7)) ) + +/* BSTR_BIT_GET returns 0 if bit is clear, 1 if bit is set. */ +#define BSTR_BIT_GET(ptr,bitnum) \ + (( ((ST_UINT8 *)(ptr))[(bitnum)/8] & (0x80>>((bitnum)&7)) ) ? 1:0) + +#define BSTR_BIT_SET_TRUE BSTR_BIT_SET_ON +#define BSTR_BIT_SET_FALSE BSTR_BIT_SET_OFF + +/* Calculate number of bytes needed to contain number of bits. */ +#define BSTR_NUMBITS_TO_NUMBYTES(numbits) (((numbits)+7)/8) + +/* Functions for conversion from ASN.1 UTF8string to local format. */ +/* Must be ported to each platform. */ +ST_INT asn1r_utf8_to_local (ST_CHAR *dst, ST_INT dst_len, ST_CHAR *src, ST_INT src_len); +ST_INT asn1r_local_to_utf8 (ST_CHAR *dst, ST_INT dst_len, ST_CHAR *src); +#ifdef __cplusplus +} +#endif + +/************************************************************************/ +#endif /* File not already included */ +/************************************************************************/ + diff --git a/include/inc/cfg_util.h b/include/inc/cfg_util.h new file mode 100644 index 0000000..fa005e8 --- /dev/null +++ b/include/inc/cfg_util.h @@ -0,0 +1,112 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1991-2005 All Rights Reserved */ +/* */ +/* MODULE NAME : cfg_util.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/31/05 EJV 05 Chg MAX_NUM_KEYWORDS from 100 to 200. */ +/* 10/08/98 MDE 04 Migrated to updated SLOG interface */ +/* 08/06/98 JRB 03 Added cfg_get_octet_string function. */ +/* 12/04/97 KCR 02 Added cfg_goto_keyword function */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef CFG_UTIL_INCLUDED +#define CFG_UTIL_INCLUDED + +#include "slog.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ + +#define MAX_RVAL_LEN 256 +#define MAX_NUM_KEYWORDS 200 /* just to prevent runaway */ + +/* Keyword table element */ +struct cfg_kw_el + { + ST_CHAR *name; /* string to match on */ + ST_VOID (*extract)(ST_VOID); /* function to call to extract */ + ST_RET (*valid)(ST_VOID); /* call to check if ok to call */ + }; +typedef struct cfg_kw_el CFG_KW_EL; + +/************************************************************************/ +/* Externally visible variables */ + +extern ST_BOOLEAN config_stop; /* Set SD_TRUE to terminate */ +extern ST_RET config_err; /* Set to non-zero for error */ +extern ST_BOOLEAN config_eof; /* Set to SD_SUCCESS when eof is ok */ + +extern ST_CHAR *cfg_line_buf; /* file line read buffer */ +extern ST_INT cfg_curr_line; /* Current line number */ +extern ST_INT cfg_line_offset; /* Offset into cfg_line_buf */ +extern ST_CHAR *cfg_special_char_str; /* Special ravl chars */ +extern ST_CHAR *cfg_end_of_rval_str; /* 'End of rval' chars */ + +/************************************************************************/ +/* Internal CFG_UTIL error codes */ + +#define CFG_CONVERT_ERR 0x8000 +#define CFG_GET_RVAL_ERR 0x8001 +#define CFG_UTIL_ERR 0x8002 + +/************************************************************************/ +/* Externally visible functions */ + +ST_RET cfg_process_file (ST_CHAR *fileName, CFG_KW_EL *root_kw_tbl); +ST_RET cfg_tbl_push (CFG_KW_EL *); +ST_RET cfg_tbl_pop (ST_INT); +ST_CHAR *cfg_get_alloc_string (ST_VOID); +ST_CHAR *cfg_get_string_ptr (ST_VOID); +ST_RET cfg_get_short (ST_INT16 *int_ptr); +ST_RET cfg_get_ushort (ST_UINT16 *int_ptr); +ST_RET cfg_get_int (ST_INT *int_ptr); +ST_RET cfg_get_uint (ST_UINT *int_ptr); +ST_RET cfg_get_long (ST_LONG *int_ptr); +ST_RET cfg_get_ulong (ST_ULONG *int_ptr); +ST_RET cfg_get_hex_ushort (ST_UINT16 *int_ptr); +ST_RET cfg_get_hex_uint (ST_UINT *int_ptr); +ST_RET cfg_get_hex_ulong (ST_ULONG *out_ptr); +ST_RET cfg_get_value (ST_CHAR *format_string, ST_VOID *out_ptr); +ST_VOID cfg_set_config_err(ST_VOID); +ST_VOID cfg_set_endfile_ok(ST_VOID); +ST_RET cfg_get_double (ST_DOUBLE *out_ptr); +ST_RET cfg_goto_keyword (ST_CHAR *keyword); +ST_RET cfg_get_octet_string (ST_UCHAR *ostr, /* ptr to user's ostr */ + ST_UINT *len_out_ptr, /* addr of len var to be set */ + ST_UINT len_max); /* maximum len to allow. */ + +/************************************************************************/ +/* CFG_UTIL logging control */ + +#define CFG_LOG_ERR 0x0001 +#define CFG_LOG_FLOW 0x0002 +extern ST_UINT cfg_log_mask; + +/* For compatibility with older code only */ +#define cfg_sLogCtrl sLogCtrl + +/************************************************************************/ + +#ifdef __cplusplus +} + +#endif + +#endif diff --git a/include/inc/cfglog.h b/include/inc/cfglog.h new file mode 100644 index 0000000..f837414 --- /dev/null +++ b/include/inc/cfglog.h @@ -0,0 +1,101 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1991-1997 All Rights Reserved */ +/* */ +/* MODULE NAME : cfglog.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 10/08/98 MDE 01 Migrated to updated SLOG interface */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef CFGLOG_INCLUDED +#define CFGLOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/************************************************************************/ + +extern SD_CONST ST_CHAR *SD_CONST _cfg_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _cfg_flow_logstr; + +/************************************************************************/ + +#ifdef DEBUG_SISCO + +#define CFG_LOG_ERR0(a) {\ + if (cfg_log_mask & CFG_LOG_ERR)\ + _slog (sLogCtrl,_cfg_err_logstr,\ + thisFileName,__LINE__,a);\ + } +#define CFG_LOG_ERR1(a,b) {\ + if (cfg_log_mask & CFG_LOG_ERR)\ + _slog (sLogCtrl,_cfg_err_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define CFG_LOG_ERR2(a,b,c) {\ + if (cfg_log_mask & CFG_LOG_ERR)\ + _slog (sLogCtrl,_cfg_err_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define CFG_LOG_ERR3(a,b,c,d) {\ + if (cfg_log_mask & CFG_LOG_ERR)\ + _slog (sLogCtrl,_cfg_err_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } + + +#define CFG_LOG_FLOW0(a) {\ + if (cfg_log_mask & CFG_LOG_FLOW)\ + _slog (sLogCtrl,_cfg_flow_logstr,\ + thisFileName,__LINE__,a);\ + } +#define CFG_LOG_FLOW1(a,b) {\ + if (cfg_log_mask & CFG_LOG_FLOW)\ + _slog (sLogCtrl,_cfg_flow_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define CFG_LOG_CFLOW0(a) {\ + if (cfg_log_mask & CFG_LOG_FLOW)\ + _slogc (sLogCtrl,a);\ + } +#define CFG_LOG_CFLOW1(a,b) {\ + if (cfg_log_mask & CFG_LOG_FLOW)\ + _slogc (sLogCtrl,a,b);\ + } + +#else /* no DEBUG */ + +#define CFG_LOG_ERR0(a) +#define CFG_LOG_ERR1(a,b) +#define CFG_LOG_ERR2(a,b,c) +#define CFG_LOG_ERR3(a,b,c,d) +#define CFG_LOG_FLOW0(a) +#define CFG_LOG_FLOW1(a,b) +#define CFG_LOG_CFLOW0(a) +#define CFG_LOG_CFLOW1(a,b) + +#endif + + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/include/inc/checksum.h b/include/inc/checksum.h new file mode 100644 index 0000000..b1ceeff --- /dev/null +++ b/include/inc/checksum.h @@ -0,0 +1,46 @@ +#ifndef CHECKSUM_INCLUDED +#define CHECKSUM_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : checksum.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file contain functionprototypes for */ +/* implemented computation and verification of checksum */ +/* using the algorithm defined in Annex B of the ISO 8073 */ +/* or in the ISO 8473. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* checksum_insert */ +/* checksum_verified */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 06/19/96 EJV 01 Created */ +/************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + + +ST_VOID checksum_insert (ST_UCHAR *buf, ST_UINT16 buf_len, ST_UINT16 position); +ST_BOOLEAN checksum_verified (ST_UCHAR *buf, ST_UINT16 buf_len, ST_UINT16 position, ST_BOOLEAN clnp_csum); + + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ diff --git a/include/inc/clnp.h b/include/inc/clnp.h new file mode 100644 index 0000000..2be27e6 --- /dev/null +++ b/include/inc/clnp.h @@ -0,0 +1,259 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : clnp.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file specifies internal defines and function*/ +/* prototypes for implementation of Connectionless-mode */ +/* Network Protocol (CLNP). */ +/* Note that the CLNP is implemented as non-segmenting */ +/* subset of the full protocol. */ +/* */ +/* For information see the: */ +/* ISO 8473 "Information processing systems - Data communication - */ +/* Protocol providing the connectionless-mode network service"; */ +/* ISO 8348 "Information processing systems - Data communication - */ +/* Network service definition. Addendum 1: Connectionless-mode */ +/* transmission". */ +/* ISO 9542 "Information processing systems - Telecommunications */ +/* and information exchange beetween systems - End system to */ +/* Intermediate system routing exchange protocol for use with */ +/* ISO 8473. */ +/* */ +/* GLOBAL STRUCTURES DEFINED IN THIS MODULE : */ +/* */ +/* CLNP_8473_FHDR struct */ +/* CLNP_9542_FHDR struct */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 07/19/96 EJV 02 Moved CLNP_DEF_LEN_HDR from clnp_usr.h and */ +/* deleted clnpl_all_es_mac */ +/* 05/24/96 EJV 01 Created */ +/************************************************************************/ + +#ifndef CLNP_INCLUDED +#define CLNP_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + + + +/************************************************************************/ +/* Defines and structures below are specific to the ISO 8473 standard */ +/* (DT and ER PDUs for CLNP). */ +/************************************************************************/ + + +/* ISO 8473 protocol id and version */ +#define CLNP_8473_PROT_ID (ST_UCHAR) 0x81 +#define CLNP_8473_PROT_VER (ST_UCHAR) 0x01 + +/* PDU type and flags (they are already in proper bit position) */ +#define CLNP_8473_TYPE_ER (ST_UCHAR) 0x01 +#define CLNP_8473_TYPE_DT (ST_UCHAR) 0x1C + +#define CLNP_SEG_NOT_PERMITTED (ST_UCHAR) 0x00 +#define CLNP_SEG_PERMITTED (ST_UCHAR) 0x80 + /* bit 8 ON */ + +#define CLNP_LAST_SEG (ST_UCHAR) 0x00 +#define CLNP_MORE_SEG (ST_UCHAR) 0x40 + /* bit 7 ON */ + +#define CLNP_ERR_REP_NOT_GEN (ST_UCHAR) 0x00 +#define CLNP_ERR_REP_GENERATE (ST_UCHAR) 0x20 + /* bit 6 ON */ + +#define CLNP_MASK_FLAGS (ST_UCHAR) 0x1F /* mask bit 6,7,8 */ + + + +/*----------------------------------------------------------------------*/ +/* CLNP_8473_FHDR struct */ +/*----------------------------------------------------------------------*/ +/* Structure below define the fixed part in the ISO 8473 PDU header. */ +/* The rest of the header has variable length. */ + +/* NOTE: ! only ST_UCHAR type should be in protocol structs to avoid */ +/* ! packing or problems with sizeof operator. */ + +typedef struct + { + ST_UCHAR protocol_id; /* Network Layer Protocol Identifier */ + ST_UCHAR hdr_len; /* Header length */ + ST_UCHAR protocol_ver; /* Version of the protocol */ + ST_UCHAR pdu_lifetime; /* Remaining lifetime for PDU */ + ST_UCHAR type_flags; /* PDU type & flags */ + ST_UCHAR seg_len[2]; /* Segment length (hdr+data len)swapped */ + ST_UCHAR checksum [2]; /* Checksum of the PDU header */ + }CLNP_8473_FHDR; + +#define CLNP_8473_FHDR_LEN sizeof (CLNP_8473_FHDR) + + +/* structure below defines the Segmenting part in a DT PDU header */ +typedef struct + { + ST_UCHAR pdu_id [2]; /* Data Unit Identiefier */ + ST_UCHAR pdu_offset [2]; /* Offset of the segment in original PDU*/ + ST_UCHAR pdu_total_len [2]; /* Total len of original PDU */ + }CLNP_8473_HDR_SEG; + +#define CLNP_8473_HDR_SEG_LEN sizeof (CLNP_8473_HDR_SEG) + + +#define CLNP_DEF_LEN_HDR (ST_UCHAR) (CLNP_8473_FHDR_LEN+2*(CLNP_MAX_LEN_NSAP+1)) + /* this implementaion assumes */ + /* following parts to be present*/ + /* in header: */ + /* fixedPart +destNSAP +srcNSAP */ + /* (no seg, no options parts); */ + /* 51 bytes or less */ + + +/************************************************************************/ +/* Defines and structures below are specific to the ISO 9542 standard */ +/* (ES-IS HELLOs for CLNP). */ +/************************************************************************/ + + +/* ISO 8473 protocol id and version */ +#define CLNP_9542_PROT_ID (ST_UCHAR) 0x82 +#define CLNP_9542_PROT_VER (ST_UCHAR) 0x01 + +/* PDU type */ +#define CLNP_9542_TYPE_ESH (ST_UCHAR) 0x02 +#define CLNP_9542_TYPE_ISH (ST_UCHAR) 0x04 +#define CLNP_9542_TYPE_RD (ST_UCHAR) 0x06 + + + +/*----------------------------------------------------------------------*/ +/* CLNP_9542_FHDR struct */ +/*----------------------------------------------------------------------*/ +/* Structure below defines the fixed part in the ISO 9542 PDU header. */ +/* The rest of the header has variable length. */ +/* Note that the ISO 9542 (ES HELLO and IS HELLO PDUs) do not contain */ +/* PDU data part. */ + +/* NOTE: ! only ST_UCHAR type should be in protocol structs to avoid */ +/* ! packing or problems with sizeof operator. */ + +typedef struct + { + ST_UCHAR protocol_id; /* Network Layer Protocol Identifier */ + ST_UCHAR hdr_len; /* Header length */ + ST_UCHAR protocol_ver; /* Version of the protocol */ + ST_UCHAR rfu; /* Reserved for future use */ + ST_UCHAR type; /* PDU type, bits 6,7,8 are always 0 */ + ST_UCHAR holding_time[2];/* max time to retain received info */ + ST_UCHAR checksum [2]; /* Checksum of the PDU header */ + }CLNP_9542_FHDR; + +#define CLNP_9542_FHDR_LEN sizeof (CLNP_9542_FHDR) + + + +/************************************************************************/ +/* Internal CLNP function prototypes */ +/************************************************************************/ + +/* clnp_enc.c module */ + +ST_RET clnpl_encode_dt (SN_UNITDATA *sn_req, N_UNITDATA *req); +ST_RET clnpl_encode_esh (ST_UCHAR *enc_buf, ST_UINT16 *enc_len); + + +/* clnp_dec.c module */ + +ST_RET clnpl_decode (SN_UNITDATA *sn_req, N_UNITDATA **req); +ST_VOID clnpl_log_npdu (ST_UCHAR *pdu_buf, ST_UCHAR npdu_type, ST_CHAR *enc_dec_str); + +/* clnp_esh.c module */ + +ST_RET clnpl_init_esh (ST_UINT16 delay_time); +ST_VOID clnpl_check_cfg_timer (ST_VOID); +ST_RET clnpl_send_esh (ST_UCHAR *rem_mac); + + +#if 0 +/* struct below may be needed to implement in the future the ISO 8473 */ +/* header options */ +/*----------------------------------------------------------------------*/ +/* CLNP_OPTIONS struct */ +/*----------------------------------------------------------------------*/ +/* Structure below specifies the options to be used for the PDU. */ +/* The options by default are all turned off at the start-up */ +/* time. In future some functions may be provided to set up the options */ +/* or the structure will be exposed to the CLNP-user for setting the */ +/* parameters. */ +/* NOTE: currently none of the option are implemented. */ + +/* Options for padding_flag */ +#define CLNP_OPT_PAD_NONE 0 /* no header padding */ +#define CLNP_OPT_PAD_TO_SIZE 1 /* pad header to specified size */ +#define CLNP_OPT_PAD_TO_BOUDARY 2 /* pad header so that data */ + /* starts on specified boundary */ +/* Options for security_flag */ +#define CLNP_OPT_SEC_NONE 0 /* no security level specified */ +#define CLNP_OPT_SEC_SRC 1 /* sec. Source Address specific */ +#define CLNP_OPT_SEC_DEST 2 /* sec. Dest Address specific */ +#define CLNP_OPT_SEC_UNIQUE 3 /* security Globally Unique */ + +/* Options for routeing_flag */ +#define CLNP_OPT_ROUTE_NONE 0 /* no routeing specified */ +#define CLNP_OPT_ROUTE_PART 1 /* partial routeing requested */ +#define CLNP_OPT_ROUTE_COMP 2 /* complete routeing requested */ + +/* Options for record_route_flag */ +#define CLNP_OPT_REC_ROUTE_NONE 0 /* no route recording */ +#define CLNP_OPT_REC_ROUTE_PART 1 /* partial route recording */ +#define CLNP_OPT_RCE_ROUTE_COMP 2 /* complete route recording */ + +/* Options for qos_flag (Quality of Service - QoS) */ +#define CLNP_OPT_QoS_NONE 0 /* no QoS specified */ +#define CLNP_OPT_QoS_SRC 1 /* QoS Source Address specific */ +#define CLNP_OPT_QoS_DEST 2 /* QoS Dest Address specific */ +#define CLNP_OPT_QoS_UNIQUE 3 /* QoS Globally Unique */ + +/* Options for priority_flag (use values from 1 to 14 to specified */ +/* priority parameter for the DT PDU. */ +#define CLNP_OPT_PRIORITY_DEF 0 /* default priority */ +#define CLNP_OPT_PRIORITY_MAX 14 /* max priority */ + +typedef struct + { + ST_UCHAR padding_flag; + ST_UCHAR security_flag; + ST_UCHAR routeing_flag; + ST_UCHAR record_route_flag; + ST_UCHAR qos_flag; + ST_UCHAR priority_flag; + }CLNP_OPTIONS; + +extern CLNP_OPTIONS clnpl_options; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + + + diff --git a/include/inc/clnp_llc.h b/include/inc/clnp_llc.h new file mode 100644 index 0000000..cecd0ee --- /dev/null +++ b/include/inc/clnp_llc.h @@ -0,0 +1,66 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : clnp_llc.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file contains defines for the encoding and */ +/* decoding of Logical Link Control (LLC) which is */ +/* implemented with the CLNP layer. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/12/04 JRB 04 Del LLC_LSAP_IEC_GOOSE 0xF5 (obsolete now). */ +/* 01/10/02 JRB 03 Add LLC_LSAP_IEC_GOOSE. */ +/* 09/09/97 EJV 02 Added support for UCA SMP (Station Mgt Prot) */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 06/04/96 EJV 01 Created */ +/************************************************************************/ + +#ifndef CLNP_LLC_INCLUDED +#define CLNP_LLC_INCLUDED + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define LLC_LSAP (ST_UCHAR) 0xFE +#define LLC_CONTROL (ST_UCHAR) 0x03 + +#define LLC_LSAP_SMP (ST_UCHAR) 0xFB /* For UCA SMP (Station Mgt Prot) */ +#define LLC_CONTROL_SMP (ST_UCHAR) 0x03 /* For UCA SMP (Station Mgt Prot) */ + +typedef struct + { + ST_UCHAR dest; /* destination SAP */ + ST_UCHAR src; /* source SAP */ + ST_UCHAR control; /* control field */ + }LLC_HDR; + +#define LLC_HDR_LEN sizeof (LLC_HDR) + + +/* Function prototypes from llc.c module */ + +ST_RET clnpl_llc_encode (ST_UCHAR *enc_buf, ST_UCHAR src_lsap, ST_UCHAR dest_lsap); +ST_RET clnpl_llc_decode (ST_UCHAR *dec_buf, ST_UCHAR *dest_lsap); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + diff --git a/include/inc/clnp_log.h b/include/inc/clnp_log.h new file mode 100644 index 0000000..c53e1f3 --- /dev/null +++ b/include/inc/clnp_log.h @@ -0,0 +1,231 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : clnp_log.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file contains logging macros for CLNP. */ +/* Note: To compile logging functions use the DEBUG_SISCO define */ +/* in the project make file. */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/09/03 JRB 07 Use new "Base" macros SLOG_*, SLOGC_*, SLOGH.*/ +/* Del unused macros. */ +/* 10/02/01 JRB 06 Fix logstr in CLSNS_LOG_* macros. */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 10/08/98 MDE 04 Migrated to updated SLOG interface */ +/* 07/28/97 JRB 03 Added CLNP_LOG_REQ2 / 3 & CLNP_LOG_IND2 / 3 */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/03/97 EJV 02 Corrected ALWAYS macros; */ +/* Removed check if sLogCtrl not NULL */ +/* 06/10/96 EJV 01 Created */ +/************************************************************************/ + +#ifndef CLNP_LOG_INCLUDED +#define CLNP_LOG_INCLUDED + +#include "slog.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* NOTE: CLNP log masks and clnp_debug_sel are defined in clnp_usr.h */ + +extern SD_CONST ST_CHAR *SD_CONST _clnp_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _clnp_nerr_logstr; +extern SD_CONST ST_CHAR *SD_CONST _clnp_req_logstr; +extern SD_CONST ST_CHAR *SD_CONST _clnp_ind_logstr; +extern SD_CONST ST_CHAR *SD_CONST _clnp_enc_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _clnp_llc_enc_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _clsns_req_logstr; +extern SD_CONST ST_CHAR *SD_CONST _clsns_ind_logstr; + +#if defined(DEBUG_SISCO) + /*--------------------------------------------------------------------*/ + /* macros below are used to log REQ or IND by passing mask to select */ + /* the logging macro (this is handy in log function so the macros */ + /* do not have to repeated in function for REQ and then for IND) */ + /*--------------------------------------------------------------------*/ + + #define CLNP_LOGC_RI0(m,a) {if (m == CLNP_LOG_REQ) {CLNP_LOGC_REQ0(a);} else {CLNP_LOGC_IND0(a);}} + #define CLNP_LOGC_RI1(m,a,b) {if (m == CLNP_LOG_REQ) {CLNP_LOGC_REQ1(a,b);} else {CLNP_LOGC_IND1(a,b);}} + + #define CLNP_LOGH_RI(m,a,b) {if (m == CLNP_LOG_REQ) {CLNP_LOGH_REQ(a,b);} else {CLNP_LOGH_IND(a,b);}} + + /*--------------------------------------------------------------------*/ + /* macros below are used to log REQ or IND by passing mask to select */ + /* the logging macro (this is handy in log function so the macros */ + /* do not have to repeated in function for REQ and then for IND) */ + /*--------------------------------------------------------------------*/ + + #define CLSNS_LOGC_RI0(m,a) {if (m == CLSNS_LOG_REQ) {CLSNS_LOGC_REQ0(a);} else {CLSNS_LOGC_IND0(a);}} + #define CLSNS_LOGC_RI1(m,a,b) {if (m == CLSNS_LOG_REQ) {CLSNS_LOGC_REQ1(a,b);} else {CLSNS_LOGC_IND1(a,b);}} + + #define CLSNS_LOGH_RI(m,a,b) {if (m == CLSNS_LOG_REQ) {CLSNS_LOGH_REQ(a,b);} else {CLSNS_LOGH_IND(a,b);}} + +#else /* !defined(DEBUG_SISCO) */ + + /*--------------------------------------------------------------------*/ + /* macros below are used to log REQ or IND by passing mask */ + /*--------------------------------------------------------------------*/ + + #define CLNP_LOGC_RI0(m,a) + #define CLNP_LOGC_RI1(m,a,b) + #define CLNP_LOGH_RI(m,a,b) + + /*--------------------------------------------------------------------*/ + /* macros below are used to log REQ or IND by passing mask */ + /*--------------------------------------------------------------------*/ + + #define CLSNS_LOGC_RI0(m,a) + #define CLSNS_LOGC_RI1(m,a,b) + + #define CLSNS_LOGH_RI(m,a,b) + +#endif /* !defined(DEBUG_SISCO) */ + + /*--------------------------------------------*/ + /* hard errors logging */ + /*--------------------------------------------*/ + +#define CLNP_LOG_ERR0(a) \ + SLOG_0 (clnp_debug_sel & CLNP_LOG_ERR,_clnp_err_logstr,a) +#define CLNP_LOG_ERR1(a,b) \ + SLOG_1 (clnp_debug_sel & CLNP_LOG_ERR,_clnp_err_logstr,a,b) +#define CLNP_LOG_ERR2(a,b,c) \ + SLOG_2 (clnp_debug_sel & CLNP_LOG_ERR,_clnp_err_logstr,a,b,c) +#define CLNP_LOG_ERR3(a,b,c,d) \ + SLOG_3 (clnp_debug_sel & CLNP_LOG_ERR,_clnp_err_logstr,a,b,c,d) + + /*--------------------------------------------*/ + /* normal errors logging */ + /*--------------------------------------------*/ + +#define CLNP_LOG_NERR0(a) \ + SLOG_0 (clnp_debug_sel & CLNP_LOG_NERR,_clnp_nerr_logstr,a) +#define CLNP_LOG_NERR1(a,b) \ + SLOG_1 (clnp_debug_sel & CLNP_LOG_NERR,_clnp_nerr_logstr,a,b) +#define CLNP_LOG_NERR2(a,b,c) \ + SLOG_2 (clnp_debug_sel & CLNP_LOG_NERR,_clnp_nerr_logstr,a,b,c) +#define CLNP_LOG_NERR3(a,b,c,d) \ + SLOG_3 (clnp_debug_sel & CLNP_LOG_NERR,_clnp_nerr_logstr,a,b,c,d) + + /*--------------------------------------------*/ + /* CLNP-user request logging */ + /*--------------------------------------------*/ + +#define CLNP_LOG_REQ0(a) \ + SLOG_0 (clnp_debug_sel & CLNP_LOG_REQ,_clnp_req_logstr,a) +#define CLNP_LOG_REQ1(a,b) \ + SLOG_1 (clnp_debug_sel & CLNP_LOG_REQ,_clnp_req_logstr,a,b) +#define CLNP_LOG_REQ2(a,b,c) \ + SLOG_2 (clnp_debug_sel & CLNP_LOG_REQ,_clnp_req_logstr,a,b,c) +#define CLNP_LOG_REQ3(a,b,c,d) \ + SLOG_3 (clnp_debug_sel & CLNP_LOG_REQ,_clnp_req_logstr,a,b,c,d) + /* continuation log */ +#define CLNP_LOGC_REQ0(a) \ + SLOGC_0 (clnp_debug_sel & CLNP_LOG_REQ,a) +#define CLNP_LOGC_REQ1(a,b) \ + SLOGC_1 (clnp_debug_sel & CLNP_LOG_REQ,a,b) + /* hex logging */ +#define CLNP_LOGH_REQ(a,b) \ + SLOGH (clnp_debug_sel & CLNP_LOG_REQ,a,b) + + /*--------------------------------------------*/ + /* CLNP_user indication logging */ + /*--------------------------------------------*/ + +#define CLNP_LOG_IND0(a) \ + SLOG_0 (clnp_debug_sel & CLNP_LOG_IND,_clnp_ind_logstr,a) +#define CLNP_LOG_IND1(a,b) \ + SLOG_1 (clnp_debug_sel & CLNP_LOG_IND,_clnp_ind_logstr,a,b) +#define CLNP_LOG_IND2(a,b,c) \ + SLOG_2 (clnp_debug_sel & CLNP_LOG_IND,_clnp_ind_logstr,a,b,c) +#define CLNP_LOG_IND3(a,b,c,d) \ + SLOG_3 (clnp_debug_sel & CLNP_LOG_IND,_clnp_ind_logstr,a,b,c,d) + /* continuation log */ +#define CLNP_LOGC_IND0(a) \ + SLOGC_0 (clnp_debug_sel & CLNP_LOG_IND,a) +#define CLNP_LOGC_IND1(a,b) \ + SLOGC_1 (clnp_debug_sel & CLNP_LOG_IND,a,b) + /* hex logging */ +#define CLNP_LOGH_IND(a,b) \ + SLOGH (clnp_debug_sel & CLNP_LOG_IND,a,b) + + /*--------------------------------------------*/ + /* CLNP encoding/decoding of NPDU */ + /*--------------------------------------------*/ + +#define CLNP_LOG_ENC_DEC0(a) \ + SLOG_0 (clnp_debug_sel & CLNP_LOG_ENC_DEC,_clnp_enc_dec_logstr,a) +#define CLNP_LOG_ENC_DEC1(a,b) \ + SLOG_1 (clnp_debug_sel & CLNP_LOG_ENC_DEC,_clnp_enc_dec_logstr,a,b) +#define CLNP_LOG_ENC_DEC2(a,b,c) \ + SLOG_2 (clnp_debug_sel & CLNP_LOG_ENC_DEC,_clnp_enc_dec_logstr,a,b,c) + /* continuation log */ +#define CLNP_LOGC_ENC_DEC0(a) \ + SLOGC_0 (clnp_debug_sel & CLNP_LOG_ENC_DEC,a) +#define CLNP_LOGC_ENC_DEC1(a,b) \ + SLOGC_1 (clnp_debug_sel & CLNP_LOG_ENC_DEC,a,b) + /* hex logging */ +#define CLNP_LOGH_ENC_DEC(a,b) \ + SLOGH (clnp_debug_sel & CLNP_LOG_ENC_DEC,a,b) + + /*--------------------------------------------*/ + /* LLC encoding/decoding of LPDU */ + /*--------------------------------------------*/ + +#define CLNP_LOG_LLC_ENC_DEC3(a,b,c,d) \ + SLOG_3 (clnp_debug_sel & CLNP_LOG_LLC_ENC_DEC,_clnp_llc_enc_dec_logstr,a,b,c,d) + + /*----------------------------------------------*/ + /* sub-network services request (write) logging */ + /*----------------------------------------------*/ + +#define CLSNS_LOG_REQ0(a) \ + SLOG_0 (clnp_debug_sel & CLSNS_LOG_REQ,_clsns_req_logstr,a) +#define CLSNS_LOG_REQ1(a,b) \ + SLOG_1 (clnp_debug_sel & CLSNS_LOG_REQ,_clsns_req_logstr,a,b) + /* continuation log */ +#define CLSNS_LOGC_REQ0(a) \ + SLOGC_0 (clnp_debug_sel & CLSNS_LOG_REQ,a) +#define CLSNS_LOGC_REQ1(a,b) \ + SLOGC_1 (clnp_debug_sel & CLSNS_LOG_REQ,a,b) + /* hex logging */ +#define CLSNS_LOGH_REQ(a,b) \ + SLOGH (clnp_debug_sel & CLSNS_LOG_REQ,a,b) + + /*------------------------------------------------*/ + /* sub-network services indication logging (read) */ + /*------------------------------------------------*/ + +#define CLSNS_LOG_IND0(a) \ + SLOG_0 (clnp_debug_sel & CLSNS_LOG_IND,_clsns_ind_logstr,a) +#define CLSNS_LOG_IND1(a,b) \ + SLOG_1 (clnp_debug_sel & CLSNS_LOG_IND,_clsns_ind_logstr,a,b) + + /* continuation log */ +#define CLSNS_LOGC_IND0(a) \ + SLOGC_0 (clnp_debug_sel & CLSNS_LOG_IND,a) +#define CLSNS_LOGC_IND1(a,b) \ + SLOGC_1 (clnp_debug_sel & CLSNS_LOG_IND,a,b) + /* hex logging */ +#define CLSNS_LOGH_IND(a,b) \ + SLOGH (clnp_debug_sel & CLSNS_LOG_IND,a,b) + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ diff --git a/include/inc/clnp_sne.h b/include/inc/clnp_sne.h new file mode 100644 index 0000000..be7fbee --- /dev/null +++ b/include/inc/clnp_sne.h @@ -0,0 +1,227 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : clnp_sne.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file defines the interface between the */ +/* Connectionless-mode Network Protocol (CLNP) and the */ +/* underlying sub-network. */ +/* */ +/* GLOBAL STRUCTURES DEFINED IN THIS MODULE : */ +/* */ +/* SN_UNITDATA struct */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* clnp_snet_init */ +/* clnp_snet_term */ +/* clnp_snet_read */ +/* clnp_snet_write */ +/* clnp_snet_free */ +/* clnp_snet_add_multicast_mac */ +/* clnp_snet_ext_write */ +/* clnp_snet_timer_tick */ +/* clnp_snet_update_is */ +/* clnp_snet_update_es */ +/* clnp_snet_lookup_mac */ +/* clnp_snet_get_all_is_mac */ +/* clnp_snet_get_all_es_mac */ +/* clnp_snet_get_local_mac */ +/* clnp_snet_get_max_udata_len */ +/* clnp_snet_get_type */ +/* clnp_snet_create_es_table */ +/* clnp_snet_check_mac */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/12/06 JRB 15 Add hPktSock extern. */ +/* 03/20/06 JRB 14 Add clnp_snet_write_raw. */ +/* Include clnp_usr.h (need some defs from it). */ +/* 07/25/05 JRB 13 Add comment explaining "lpdu_len". */ +/* 02/08/05 JRB 12 Increase ETHE_MAX_LEN_LSDU to 1518 to allow */ +/* for 802.1Q QTag Prefix. */ +/* Del ETYPE_UNITDATA, code no longer uses it. */ +/* Add clnp_snet_frame_to_udt. */ +/* Add clnp_snet_read_hook_*. */ +/* 11/20/02 ASK 11 Added ETYPE_UNITDATA struct, clnp_etype_write*/ +/* proto */ +/* 10/24/02 NAV 10 Add clnp_snet_rx_multicast_stop proto. */ +/* 11/15/01 JRB 09 Add more "multicast" functions. */ +/* Add clnpl_log_snsdu proto. */ +/* 02/21/00 JRB 08 Del "free_lpdu" flag from SN_UNITDATA, and */ +/* use portable "clnp_snet_free" instead. */ +/* 01/28/99 MDE 07 Added size to ETHE_ALL_ES, ETHE_ALL_IS */ +/* 11/30/98 JRB 06 Added Ethernet defines. */ +/* Added clnp_snet_add_multicast_mac prototype. */ +/* Added clnp_snet_check_mac prototype. */ +/* 09/23/97 EJV 05 Added clnp_snet_ext_write for UCA_SMP. */ +/* Aligned fields in SN_UNITDATA struct. */ +/* 06/19/97 EJV 04 Added clnp_snet_create_es_table prototype. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 10/17/96 EJV 03 Added define SUBNET_PROFI. */ +/* 07/22/96 EJV 02 Added func clnp_snet_get_type () and defines */ +/* for implemented sub-networks SUBNET_ADLC and */ +/* SUBNET_ETHE. */ +/* 05/23/96 EJV 01 Created */ +/************************************************************************/ + +#ifndef CLNP_SNE_INCLUDED +#define CLNP_SNE_INCLUDED + +#include "clnp_usr.h" /* need CLNP_MAX_LEN_MAC & CLNP_PARAM */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* implemented sub-networks types */ +#define SUBNET_ADLC 1 +#define SUBNET_ETHE 2 +#define SUBNET_PROFI 3 + +/*----------------------------------------------------------------------*/ +/* Structure below is used to pass SN_UNITDATA to/from read/write */ +/* functions between the CLNP and CLNP-Subnetwork interface. */ + +typedef struct + { + ST_UCHAR loc_mac [CLNP_MAX_LEN_MAC]; /* Buffer for local MAC addr */ + ST_UCHAR rem_mac [CLNP_MAX_LEN_MAC]; /* Buffer for remote MAC addr */ + /* WARNING: The "lpdu_len" param does NOT always contain the PDU length.*/ + /* It contains the "Length/Type" field of the MAC frame as defined in */ + /* IEEE 802.3. Any value greater than or equal to 0x600 must be */ + /* interpreted as the "Type" of the MAC frame. */ + /* Renaming this parameter would clarify the code, but too much */ + /* existing code is already using it. */ + ST_UINT16 lpdu_len; /* IEEE 802.3 "Length/Type" field. */ + ST_UCHAR *lpdu; /* Pointer to LPDU buffer to send. */ + }SN_UNITDATA; + +#define SN_UNITDATA_LEN sizeof (SN_UNITDATA) + +/*----------------------------------------------------------------------*/ +/* Defines for type of MAC address in received PDU. */ +/* Returned by "clnp_snet_check_mac". */ +/*----------------------------------------------------------------------*/ +#define CLNP_MAC_INVALID 0 /* Invalid MAC address (not one */ + /* of addresses def below) */ +#define CLNP_MAC_LOCAL 1 /* Our MAC address */ +#define CLNP_MAC_ALL_ES 2 /* All-ES (End Systems) address */ +#define CLNP_MAC_ALL_IS 3 /* All-IS (Intermediate Systems)*/ +#define CLNP_MAC_GOOSE 4 /* Possible GOOSE address */ + +/*----------------------------------------------------------------------*/ +/* Defines and externs for Ethernet Subnetwork (SUBNET_ETHE) only. */ +/*----------------------------------------------------------------------*/ +#define ETHE_MAC_LEN 6 + +#define ETHE_LEN_HEAD (2*ETHE_MAC_LEN + 2) +#define ETHE_MIN_LEN_LSDU 60 +/* Max len for normal frame is 1514, but with QTag Prefix it could be 1518*/ +#define ETHE_MAX_LEN_LSDU 1518 +#define ETHE_MAX_LEN_UDATA 1500 /* max. MAC User data length */ + +#define ETHE_LEN_QTAG_PREFIX 4 /* 802.1Q (VLAN) header length */ +#define ETHE_LEN_LENTYPE 2 /* MAC Len/type field length */ + +/* Ethernet frame structure */ +/* WARNING: This structure is not convenient for representing frames */ +/* containing the IEEE 802.1Q QTag Prefix. The QTag Prefix would come */ +/* between src_addr and frame_len in this structure. */ +/* Most code using this structure was written before QTag existed. */ +/* New code should not use this structure. */ +typedef struct + { + ST_UCHAR dst_addr [ETHE_MAC_LEN]; /* destination MAC address */ + ST_UCHAR src_addr [ETHE_MAC_LEN]; /* source MAC address */ + ST_UCHAR frame_len[2]; /* total frame length */ + ST_UCHAR data_buf [ETHE_MAX_LEN_UDATA]; /* data buffer */ + } ETHE_FRAME; + +#define ETHE_FRAME_LEN sizeof (ETHE_FRAME) + +/*----------------------------------------------------------------------*/ +/* Global variables. */ +/*----------------------------------------------------------------------*/ +/* All ES and all IS addresses */ +extern ST_UCHAR ETHE_ALL_ES [ETHE_MAC_LEN]; +extern ST_UCHAR ETHE_ALL_IS [ETHE_MAC_LEN]; +extern int hPktSock; /* Packet Socket handle (for LINUX, etc.) */ + +/*----------------------------------------------------------------------*/ +/* Interface functions to underlying sub-network */ +/*----------------------------------------------------------------------*/ + +ST_RET clnp_snet_init (CLNP_PARAM *clnp_param); +ST_RET clnp_snet_term (ST_VOID); +ST_RET clnp_snet_read (SN_UNITDATA *sn_req); +ST_RET clnp_snet_write (SN_UNITDATA *sn_req); +ST_RET clnp_etype_write (SN_UNITDATA *sn_req); +/* clnp_snet_write_raw replaces OBSOLETE clnp_snet_write and clnp_etype_write.*/ +ST_RET clnp_snet_write_raw ( + ST_UCHAR *framePtr, /* Pointer to complete frame including MACs*/ + size_t frameLen); /* Length of complete frame */ +ST_VOID clnp_snet_free (SN_UNITDATA *sn_req); +ST_VOID clnpl_log_snsdu (SN_UNITDATA *sn_req, ST_ULONG log_mask); +ST_RET clnp_snet_add_multicast_mac (ST_UCHAR *mac_buf); +ST_RET clnp_snet_set_multicast_filter (ST_UCHAR *mac_list, ST_INT num_macs); +ST_RET clnp_snet_rx_all_multicast_start (ST_VOID); +ST_RET clnp_snet_rx_all_multicast_stop (ST_VOID); +ST_RET clnp_snet_rx_multicast_stop (ST_VOID); + +ST_RET clnp_snet_ext_write (SN_UNITDATA *sn_req, ST_LONG user_id); +ST_VOID clnp_snet_timer_tick (ST_VOID); + +ST_RET clnp_snet_update_is (ST_UCHAR *rem_nsap, ST_UCHAR *rem_mac, ST_UINT16 holding_time); +ST_RET clnp_snet_update_es (ST_UCHAR *rem_nsap, ST_UCHAR *rem_mac, ST_UINT16 holding_time); + +ST_RET clnp_snet_lookup_is (ST_UCHAR *rem_mac); +ST_RET clnp_snet_lookup_es (ST_UCHAR *rem_nsap, ST_UCHAR *rem_mac); + +ST_RET clnp_snet_get_all_is_mac (ST_UCHAR *mac_buf); +ST_RET clnp_snet_get_all_es_mac (ST_UCHAR *mac_buf); +ST_RET clnp_snet_get_local_mac (ST_UCHAR *mac_buf); +ST_UINT16 clnp_snet_get_max_udata_len (ST_VOID); +ST_INT clnp_snet_get_type (ST_VOID); + +ST_RET clnp_snet_create_es_table (ST_UINT max_count); +ST_INT clnp_snet_check_mac (ST_UCHAR *mac_addr); + +/* Add subnetwork read hook function to do custom processing of */ +/* received packets. */ +ST_RET clnp_snet_read_hook_add ( + ST_RET (*usr_fun)(SN_UNITDATA *sn_req)); /* hook function*/ + +/* Remove subnetwork read hook function (i.e. stop custom processing). */ +ST_RET clnp_snet_read_hook_remove ( + ST_RET (*usr_fun)(SN_UNITDATA *sn_req)); /* hook function*/ + +/* Process all subnetwork read hook functions. */ +ST_RET clnp_snet_read_hook_process (SN_UNITDATA *sn_req); + +/* Copy data from raw frame to SN_UNITDATA struct. */ +ST_RET clnp_snet_frame_to_udt (ST_UINT8 *frame_buf, /* ptr to raw frame*/ + ST_INT frame_len, /* len of raw frame*/ + SN_UNITDATA *sn_req, + ST_INT udata_max_len); /* max user data len */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + + + + + + diff --git a/include/inc/clnp_sta.h b/include/inc/clnp_sta.h new file mode 100644 index 0000000..87f3206 --- /dev/null +++ b/include/inc/clnp_sta.h @@ -0,0 +1,125 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : clnp_sta.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file defines the statistics for the */ +/* Connectionless-mode Network Protocol (CLNP). */ +/* */ +/* Note: Compile the whole project with CLNP_STAT define to */ +/* keep statistics of CLNP operation. */ +/* */ +/* GLOBAL STRUCTURES DEFINED IN THIS MODULE : */ +/* */ +/* CLNP_STATS struct */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 05/23/96 EJV 01 Created */ +/************************************************************************/ + + +#ifndef CLNP_STA_INCLUDED +#define CLNP_STA_INCLUDED + + +#ifdef __cplusplus +extern "C" { +#endif + +/* struct below describes the statistics recorded by the CLNP */ + +/* Statistics for PDUs */ +typedef struct + { + ST_UINT cnt_sent; /* Number of sent PDUs */ + ST_UINT cnt_rcvd; /* Number of received PDUs */ + ST_UINT cnt_expired; /* Number of expired PDUs */ + ST_UINT cnt_discarded; /* Number of discarded PDUs */ + }CLNP_PDU_STAT; + +typedef struct + { + CLNP_PDU_STAT all_pdu; /* stats for all PDUs */ + CLNP_PDU_STAT dt_pdu; /* stats for DT PDUs */ + CLNP_PDU_STAT er_pdu; /* stats for ER PDUs */ + }CLNP_STATS; + +#define CLNP_STATS_LEN sizeof (CLNP_STATS) + + +ST_RET clnp_stats_reset (ST_VOID); +CLNP_STATS *clnp_stats_get (ST_VOID); + + +#if defined(CLNP_STAT) + + extern CLNP_STATS clnp_stats; + + /* macros to increment all PDUs statistics */ + + #define CLNP_STAT_INC_PDU_SENT {clnp_stats.all_pdu.cnt_sent += 1;} + #define CLNP_STAT_INC_PDU_RECEIVED {clnp_stats.all_pdu.cnt_rcvd += 1;} + #define CLNP_STAT_INC_PDU_EXPIRED {clnp_stats.all_pdu.cnt_expired += 1;} + #define CLNP_STAT_INC_PDU_DISCARDED {clnp_stats.all_pdu.cnt_discarded += 1;} + + /* macros to increment DT PDU statistics */ + + #define CLNP_STAT_INC_DT_SENT {clnp_stats.dt_pdu.cnt_sent += 1;} + #define CLNP_STAT_INC_DT_RECEIVED {clnp_stats.dt_pdu.cnt_rcvd += 1;} + #define CLNP_STAT_INC_DT_EXPIRED {clnp_stats.dt_pdu.cnt_expired += 1;} + #define CLNP_STAT_INC_DT_DISCARDED {clnp_stats.dt_pdu.cnt_discarded += 1;} + + /* macros to increment ER PDU statistics */ + + #define CLNP_STAT_INC_ER_SENT {clnp_stats.er_pdu.cnt_sent += 1;} + #define CLNP_STAT_INC_ER_RECEIVED {clnp_stats.er_pdu.cnt_rcvd += 1;} + #define CLNP_STAT_INC_ER_EXPIRED {clnp_stats.er_pdu.cnt_expired += 1;} + #define CLNP_STAT_INC_ER_DISCARDED {clnp_stats.er_pdu.cnt_discarded += 1;} + +#else + + /* macros if CLNP_STAT is not defined */ + + /* macros to increment all PDU statistics */ + + #define CLNP_STAT_INC_PDU_SENT + #define CLNP_STAT_INC_PDU_RECEIVED + #define CLNP_STAT_INC_PDU_EXPIRED + #define CLNP_STAT_INC_PDU_DISCARDED + + /* macros to increment DT PDU statistics */ + + #define CLNP_STAT_INC_DT_SENT + #define CLNP_STAT_INC_DT_RECEIVED + #define CLNP_STAT_INC_DT_EXPIRED + #define CLNP_STAT_INC_DT_DISCARDED + + /* macros to increment ER PDU statistics */ + + #define CLNP_STAT_INC_ER_SENT + #define CLNP_STAT_INC_ER_RECEIVED + #define CLNP_STAT_INC_ER_EXPIRED + #define CLNP_STAT_INC_ER_DISCARDED + +#endif /* end of CLNP_STAT defined */ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + diff --git a/include/inc/clnp_tnt.h b/include/inc/clnp_tnt.h new file mode 100644 index 0000000..1eea64d --- /dev/null +++ b/include/inc/clnp_tnt.h @@ -0,0 +1,45 @@ +#ifndef CLNP_TNT_INCLUDED +#define CLNP_TNT_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 2000 All Rights Reserved */ +/* */ +/* MODULE NAME : clnp_tnt.h */ +/* PRODUCT(S) : Lean-T Stack (Phar Lap TNT ETS port only) */ +/* */ +/* MODULE DESCRIPTION : */ +/* Stub function prototypes for Phar Lap TNT ETS. Ethernet drivers */ +/* must be modified to call these functions instead of the normal */ +/* functions in the Phar Lap TCP/IP stack. This allows the SISCO */ +/* OSI stack to intercept these calls and and do any necessary OSI */ +/* processing before passing them on to the Phar Lap TCP/IP stack. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/05/00 JRB 03 Remove last chg. No longer needed. */ +/* 03/19/99 EJV 02 pfXmit has 4 parameters in Phar Lap ver 9.1 */ +/* (with NE2K patch) */ +/* Introduced the _PHARLAP91_PATCHED define */ +/* 10/30/98 JRB 01 Created */ +/************************************************************************/ +int __cdecl stubEtsTCPSetDeviceEthernetInfo(DEVHANDLE hDriver, + char *pEnetStationAddr); +int __cdecl stubEtsTCPRegisterDeviceFuncs(DEVHANDLE hDevice, + int (__cdecl *pfUpDown)(DEVHANDLE hDevice, + unsigned short goingUp, + char *options), + int (__cdecl *pfIoctl)(DEVHANDLE hDevice, int mode), + int (__cdecl *pfXmit)(DEVHANDLE hDevice, + long *pPacket, int packetLen), + int (__cdecl *pfSend)(void *pPacketHdr)); + +void __cdecl stubEtsTCPQueueRecvBuffer(DEVHANDLE hDriver, void *hMsg, + int pkt_len, + char *pRecvBuf); + +#endif /* !CLNP_TNT_INCLUDED */ diff --git a/include/inc/clnp_usr.h b/include/inc/clnp_usr.h new file mode 100644 index 0000000..2357b36 --- /dev/null +++ b/include/inc/clnp_usr.h @@ -0,0 +1,462 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : clnp_usr.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file defines the interface between the */ +/* Connectionless-mode Network Protocol (CLNP) and the */ +/* CLNP-user in order to exchange Network Service Data */ +/* Units (NSDUs). */ +/* Note that the CLNP is implemented as non-segmenting */ +/* subset of the full protocol. */ +/* */ +/* For information see the: */ +/* ISO 8473 "Information processing systems - Data communication - */ +/* Protocol providing the connectionless-mode network service"; */ +/* ISO 8348 "Information processing systems - Data communication - */ +/* Network service definition. Addendum 1: Connectionless-mode */ +/* transmission". */ +/* ISO 9542 "Information processing systems - Telecommunications */ +/* and information exchange beetween systems - End system to */ +/* Intermediate system routing exchange protocol for use with */ +/* ISO 8473. */ +/* */ +/* */ +/* GLOBAL STRUCTURES DEFINED IN THIS MODULE : */ +/* */ +/* CLNP_PARAM struct */ +/* N_UNITDATA struct */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* clnp_init */ +/* clnp_end */ +/* clnp_alloc */ +/* clnp_free */ +/* clnp_read */ +/* clnp_write */ +/* clnp_timer_tick */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/10/07 JRB 09 Add network_device to CLNP_PARAM. */ +/* 10/24/03 JRB 08 Move clnp_debug_sel to slog.h. */ +/* 02/29/00 JRB 07 Add clnp_status proto. */ +/* 08/11/99 JRB 06 Add DBL_LNK to N_UNITDATA for multithreading.*/ +/* 08/05/99 JRB 05 Clean up multithreading. */ +/* 08/02/99 JRB 04 Use glbsem for multithreading. */ +/* 07/30/99 JRB 03 Add "multi-threading" support. */ +/* 12/04/98 JRB 02 Add "loc_nsap" to N_UNITDATA. */ +/* 08/13/98 JRB 01 Lint cleanup. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 04/10/97 JRB 06 Moved error defs from clnp_err.h to here */ +/* and changed to use base from "glberror.h". */ +/* 03/03/97 EJV 05 Removed CLNP_LOG_ALWAYS */ +/* 10/04/96 JRB 04 Added loc_mac to N_UNITDATA. */ +/* 07/22/96 EJV 03 Changed CLNP_DEF_ESH_DELAY from 5 to 0. */ +/* 07/19/96 EJV 02 Removed ns_userdata_len from clnp_param */ +/* Moved CLNP_DEF_LEN_HDR to clnp.h and deleted */ +/* unused defines */ +/* 05/23/96 EJV 01 Created */ +/************************************************************************/ + +#ifndef CLNP_USR_INCLUDED +#define CLNP_USR_INCLUDED + +#include "gen_list.h" /* Need DBL_LNK definition. */ +#include "glbsem.h" /* Need ST_EVENT_SEM definition. */ +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------------------*/ +/* Error codes returned from the CLNP interface funcs to the CLNP-user */ +/* NOTE: Values begin from E_CLNP (found in glberror.h). */ +/*----------------------------------------------------------------------*/ +/* CLNP general errors */ +#define CLNP_ERR_CFG_FILE 0x3400 /* Errors found in cfg file (or required*/ + /* params not configured = local MAC and*/ + /* local NSAP) */ +#define CLNP_ERR_NOT_INIT 0x3401 /* CLNP has not been initialized */ +#define CLNP_ERR_MEM_ALLOC 0x3402 /* allocating memory failed */ +#define CLNP_ERR_NULL_PTR 0x3403 /* NULL pointer passed to clnp_... func */ + +/* CLNP parsing clnp_param structure errors */ +/* -&-&- */ +/* CAN NOT recover from this parameter error !!! */ +#define CLNP_ERR_NSAP_LEN 0x3404 /* NSAP length is 0 or more then allowed*/ +/* CAN recover from parameter errors below */ +#define CLNP_ERR_LIFETIME 0x3405 /* Invalid PDU lifetime */ +#define CLNP_ERR_LIFETIME_DEC 0x3406 /* Invalid PDU lifetime decrement value */ +#define CLNP_ERR_ESH_CFG_TIMER 0x3407 /* Invalid ESH Configuration Timer value*/ +#define CLNP_ERR_ESH_DELAY 0x3408 /* Invalid delay value for first ESH */ +#define CLNP_ERR_MAC_ADDR 0x3409 /* Local MAC address not configured */ + /* (for ADLC sub-network) */ +#define CLNP_ERR_UDATA_LEN 0x3410 /* CLNP-user data length (too big) */ +/* last error code is also used for CLNP PDU encoding error */ +/* -&-&- */ + +/* CLNP PDU parsing (decoding) errors */ +#define CLNP_ERR_PDU_MAC_ADDR 0x3420 /* The NPDU MAC address is not local MAC*/ + /* or All ES MAC. */ +#define CLNP_ERR_PDU_ID 0x3421 /* invalid/not supported PDU identifier */ +#define CLNP_ERR_PDU_VER 0x3422 /* invalid/not supported PDU version */ +#define CLNP_ERR_PDU_TYPE 0x3423 /* invalid/not supported PDU type */ +#define CLNP_ERR_PDU_LEN 0x3424 /* received PDU len does not match the */ + /* len indicated by sub-network */ +#define CLNP_ERR_PDU_EXPIRED 0x3425 /* DT or ER PDU's lifetime expired */ +#define CLNP_ERR_PDU_NSAP_ADDR 0x3426 /* PDU not addressed to our local NSAP */ +#define CLNP_ERR_PDU_SEGMENTING 0x3427 /* Segmented PDUs not supported */ +#define CLNP_ERR_PDU_CHECKSUM 0x3428 /* PDU checksum verification failed */ +#define CLNP_ERR_PDU_LAST_SEG 0x3429 /* Last seg bit not set (unsegmented PDU)*/ +#define CLNP_ERR_PDU_ER_PDU 0x342A /* code turned off for ER PDU processing*/ + +/* LLC encoding/decoding errors */ +#define LLC_ERR_SRC_ADDR 0x3481 /* LLC header Source field invalid */ +#define LLC_ERR_DEST_ADDR 0x3482 /* LLC header Dest filed invalid */ +#define LLC_ERR_CONTROL 0x3483 /* LLC header Control field invalid */ + +/*----------------------------------------------------------------------*/ +/* Error codes returned from the sub-network interface functions. */ +/* NOTE: Values begin from E_SUBNET (found in glberror.h). */ +/*----------------------------------------------------------------------*/ +#define SNET_ERR_INIT 0x3501 /* Init sub-net interface failed*/ +#define SNET_ERR_WRITE 0x3502 /* sub-net write func failed */ +#define SNET_ERR_READ 0x3503 /* sub-net read func failed or no data */ +#define SNET_ERR_MAC_INVALID 0x3504 /* invalid MAC address, unable */ + /* to obtain requested ALL ES, */ + /* ALL IS, or local MAC address.*/ +#define SNET_ERR_FRAME_LEN 0x3505 /* received more data than */ + /* reserved in buffer. */ +#define SNET_ERR_UDATA_LEN 0x3506 /* invalid len of data to send (too large)*/ + +/* sub-net errors specific to the Ethernet driver */ +#define SNET_ERR_DRV_OPEN 0x3520 /* open driver failed */ +#define SNET_ERR_DRV_LOC_MAC 0x3521 /* obtain local MAC addr from driver failed*/ +#define SNET_ERR_DRV_ADD_ES_ADDR 0x3522 /* add All ES Address failed */ +#define SNET_ERR_DRV_BIND_LSAP 0x3523 /* bind to LSAP failed */ +#define SNET_ERR_DRV_POST_BUFS 0x3524 /* post buffers to driver failed*/ + +/*----------------------------------------------------------------------*/ +/* CLNP logging types */ + +#define CLNP_LOG_ERR 0x00000001L +#define CLNP_LOG_NERR 0x00000002L + +/* to log CLNP-user indication or request */ +#define CLNP_LOG_REQ 0x00000010L +#define CLNP_LOG_IND 0x00000020L + +/* to log CLNP encoding/decoding or LLC encoding/decoding */ + +#define CLNP_LOG_ENC_DEC 0x00000100L +#define CLNP_LOG_LLC_ENC_DEC 0x00000200L + +/* to log data read/written to sub-network */ +#define CLSNS_LOG_REQ 0x00001000L +#define CLSNS_LOG_IND 0x00002000L + +/* CLNP is using clnp_debug_sel variable to turn on/off different */ +/* types of logging (see slog.h). */ + +/*----------------------------------------------------------------------*/ +/* The defines with CLNP_MAX_... specify the maximum values the */ +/* ISO 8473 or this implementation allows. The CLNP_DEF_... defines */ +/* specify the default values used to initialize the CLNP_PARAM struct. */ +/* */ +/* Note: The max length of NS-USERDATA is 64512 bytes but this number */ +/* is limited by underlying sub-network to: */ +/* for ADLC -> 32676 - CLNP_DEF_LEN_HDR - LLC_HDR_LEN */ +/* for Ethernet -> 1500 - CLNP_DEF_LEN_HDR - LLC_HDR_LEN */ + + +#define CLNP_MAX_LEN_MAC 6 /* Max len of MAC addr */ +#define CLNP_MAX_LEN_NSAP 20 /* Max len of NSAP addr */ + +#define CLNP_MIN_PDU_LIFETIME (ST_UCHAR) 1 /* min PDU lifetime in 500msec units */ +#define CLNP_MAX_PDU_LIFETIME (ST_UCHAR) 255 /* max PDU lifetime in 500msec units */ +#define CLNP_DEF_PDU_LIFETIME (ST_UCHAR) 50 /* def PDU lifetime in 500msec units */ +#define CLNP_DEF_PDU_LIFETIME_DEC (ST_UCHAR) 1 /* PDU lifetime decrement (in 500msec units) */ + + +#define CLNP_MAX_ESH_CFG_TIMER (ST_UINT16) 32767 /* max value for ESH Configuration Timer, it is */ + /* related to Holding Time in ESH which is */ + /* 2*CfgTimer=2*32767=65534 (must be ST_UINT16) */ +#define CLNP_DEF_ESH_CFG_TIMER (ST_UINT16) 120 /* default ESH Configuration Timer (in seconds) */ +#define CLNP_DEF_ESH_DELAY (ST_UINT16) 0 /* default delay before first ESH will be sent */ + + + +/*----------------------------------------------------------------------*/ +/* CLNP_PARAM struct */ +/* */ +/* This struct is used to supply actual parameters needed for operation */ +/* of the CLNP. */ +/* It is set by the NS-USER during call to clnp_init() function from */ +/* configuration file or from hard coded module clnp_hc.c. */ +/* */ +/* NOTE: The NSAP address is represented as sequence of unsigned bytes. */ +/* The first byte is the length of the NSAP address. This makes */ +/* it easy to put the NSAP to PDU. */ +/* Note: The pdu_lifetime_dec specifies by how many units the lifetime */ +/* value in received DT or ER PDU should be decremented. It has */ +/* to be at least 1. In case the transit delay plus processing */ +/* time is larger then 500msec the pdu_life_time_dec should be */ +/* adjusted accordingly. */ + +typedef struct + { + ST_UCHAR pdu_lifetime; /* PDU lifetime (in 500 msec units) for */ + /* outgoing DT PDUs. */ + /* init to CLNP_DEF_PDU_LIFETIME */ + ST_UCHAR pdu_lifetime_dec; /* PDU lifetime decrement (1=500msec) */ + /* for incomming DT or ER PDUs. */ + /* init to CLNP_DEF_PDU_LIFETIME_DEC */ + ST_UINT16 esh_cfg_timer; /* How often we report our presence to */ + /* other network entities (in seconds) */ + /* init to CLNP_DEF_ESH_CFG_TIMER */ + ST_UINT16 esh_delay; /* Delay time before first ESH is sent */ + /* init to CLNP_DEF_ESH_DELAY */ + ST_UCHAR loc_mac [CLNP_MAX_LEN_MAC]; /* Local MAC address */ + /* For ADLC the NS-USER sets the loc_mac*/ + /* DEBUG: Now the loc_mac has to match */ + /* the address in adlc.cfg !!! */ + /* For the Ethernet this param will be */ + /* read from the driver during init. */ + ST_UCHAR loc_nsap [1+CLNP_MAX_LEN_NSAP];/* Local len & NSAP address */ + ST_CHAR *network_device; /* network device name. May be used to */ + /* select device on some platforms */ + }CLNP_PARAM; + +#define CLNP_PARAM_LEN sizeof (CLNP_PARAM) + + +extern CLNP_PARAM clnp_param; /* This struct holds parameters needed */ + /* for the CLNP operations. */ + /* It is set by the CLNP-user before */ + /* calling the clnp_init() function. */ + + + + +/*----------------------------------------------------------------------*/ +/* N_UNITDATA struct */ +/* */ +/* This struct is used to pass N_UNITDATA request primitive to CLNP */ +/* and to receive N_UNITDATA indication from CLNP. */ +/* This struct uses the following trick to make the size of data buffer */ +/* configurable: */ +/* The last entry in the structure is a tiny (2 bytes) buffer. */ +/* To allow for any size data_buf, we can allocate extra bytes */ +/* after this struct. */ +/* For example if we want data_buf to be 4096 bytes, we could use */ +/* the following malloc call: */ +/* N_UNITDATA *req = malloc (sizeof (N_UNITDATA) + 4096 - 2 ); */ +/* The buffer can then be filled in, for example, as follow: */ +/* memcpy (req->data_buf, raw_data, 4096); */ +/* */ +/* NOTE: The "Local NSAP" is not passed back and forth in this struct. */ +/* Only one local NSAP is allowed. */ +/* */ +/* NOTE: The NSAP address is represented as sequence of unsigned bytes. */ +/* The first byte is the length of the NSAP address. This makes */ +/* it easy to get a NSAP from a NSDU. */ + + +#define CLNP_MIN_LEN_UDATA 2 + /* min length of data_buf defined in */ + /* N_UNITDATA struct. Do not use 1 */ + /* because optimizer may NOT treat this */ + /* field as an array. */ + +typedef struct + { + DBL_LNK link; /* for multithreading, must go on linked list */ + ST_BOOLEAN rem_mac_valid; /* SD_TRUE if MAC addr valid */ + ST_UCHAR loc_mac [CLNP_MAX_LEN_MAC]; /* Local MAC addr */ + ST_UCHAR rem_mac [CLNP_MAX_LEN_MAC]; /* Remote MAC addr */ + ST_UCHAR loc_nsap [1+CLNP_MAX_LEN_NSAP]; /* Local len & NSAP addr*/ + ST_UCHAR rem_nsap [1+CLNP_MAX_LEN_NSAP]; /* Remote len & NSAP addr */ + ST_UINT16 data_len; /* Data length in bytes */ + ST_UCHAR data_buf [CLNP_MIN_LEN_UDATA]; /* Data buffer */ + }N_UNITDATA; + +#define N_UNITDATA_LEN sizeof (N_UNITDATA) + + + + + +/************************************************************************/ +/* clnp_init */ +/*----------------------------------------------------------------------*/ +/* This function will initialize the operation of CLNP and the interface*/ +/* to underlying sub-network. */ +/* The CLNP-user should set the parameters in the clnp_param structure */ +/* before calling this function. */ +/* */ +/* Parameters: */ +/* ST_UINT ns_userdata_len Max size of NS-USERDATA */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if initialization successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET clnp_init (ST_UINT ns_userdata_len); + + +/************************************************************************/ +/* clnp_end */ +/*----------------------------------------------------------------------*/ +/* This function will terminate the operation of the CLNP and cleanup */ +/* the interface to underlying subnetwork. */ +/* */ +/* Parameters: */ +/* ST_VOID none */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if termination successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET clnp_end (ST_VOID); + + +/************************************************************************/ +/* clnp_alloc */ +/*----------------------------------------------------------------------*/ +/* This function will allocate a buffer for N_UNITDATA to pass data */ +/* between the CLNP and the CLNP-user. */ +/* */ +/* Parameters: */ +/* ST_UINT data_len Length of data in bytes. The length */ +/* of CLNP-user data has to be: */ +/* 0 < data_len <= CLNP_MAX_LEN_UDATA */ +/* */ +/* Return: */ +/* N_UNITDATA * pointer to allocated memory */ +/* NULL if function fails to alloc memory */ +/************************************************************************/ +N_UNITDATA *clnp_alloc (ST_UINT data_len); + + +/************************************************************************/ +/* clnp_free */ +/*----------------------------------------------------------------------*/ +/* This function will free buffer allocated for N_UNITDATA passed */ +/* between the CLNP and the CLNP-user. */ +/* */ +/* Parameters: */ +/* N_UNITDATA * memory pointer to free */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID clnp_free (N_UNITDATA *req); + + +/************************************************************************/ +/* clnp_read */ +/*----------------------------------------------------------------------*/ +/* This function is used by the CLNP-user to read N_UNITDATA.indication */ +/* from the CLNP. */ +/* The CLNP-user should free the returned pointer after the indication */ +/* has been processed. */ +/* */ +/* Parameters: */ +/* ST_VOID none */ +/* */ +/* Return: */ +/* N_UNITDATA * ptr to received N_UNITDATA.indication */ +/* NULL if N_UNITDATA.indication not received */ +/************************************************************************/ +N_UNITDATA *clnp_read (ST_VOID); + + +/************************************************************************/ +/* clnp_write */ +/*----------------------------------------------------------------------*/ +/* This function is used by the CLNP-user to write N_UNITDATA.request */ +/* to the CLNP. */ +/* The CLNP will free the req pointer. */ +/* */ +/* Parameters: */ +/* N_UNITDATA *req ptr to N_UNITDATA.request to send */ +/* This pointer should be allocated using */ +/* the clnp_alloc function. */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if N_UNITDATA.request sent successfully */ +/* error code otherwise */ +/************************************************************************/ +ST_RET clnp_write (N_UNITDATA *req); + + +/************************************************************************/ +/* clnp_timer_tick */ +/*----------------------------------------------------------------------*/ +/* This function is called on 1 second intervals by the CLNP-user (TP4) */ +/* When this function is called, CLNP decrements the Configuration */ +/* Timer (used to trigger sending of ES-Hellos), and the Holding Timers */ +/* (used to trigger clearing the {NSAP,MAC} table entries). */ +/* */ +/* Parameters: */ +/* ST_VOID none */ +/* */ +/* Return: */ +/* ST_VOID none */ +/************************************************************************/ +ST_VOID clnp_timer_tick (ST_VOID); + + +/************************************************************************/ +/* clnp_config */ +/*----------------------------------------------------------------------*/ +/* This function will initialize the CLNP parameters. */ +/* */ +/* Parameters: */ +/* ST_VOID none */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if configuration successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET clnp_config (ST_VOID); + +/************************************************************************/ +/* clnp_status */ +/*----------------------------------------------------------------------*/ +/* This function checks to see if CLNP is running. */ +/* */ +/* Return: */ +/* SD_SUCCESS if running, else error code. */ +/************************************************************************/ +ST_RET clnp_status (ST_VOID); + +/************************************************************************/ +/* Multi-threading prototypes and externs. */ +/************************************************************************/ +ST_RET clnp_read_thread_start (ST_VOID); +N_UNITDATA *clnp_read_main (ST_VOID); +N_UNITDATA *clnp_read_goose (ST_VOID); + +extern N_UNITDATA * (*clnp_read_fun_cl) (ST_VOID); /* Function ptr.*/ +extern N_UNITDATA * (*clnp_read_fun_co) (ST_VOID); /* Function ptr.*/ +extern ST_EVENT_SEM hMMSEvent; +extern ST_EVENT_SEM hMainEvent; +extern ST_EVENT_SEM hGooseEvent; + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + diff --git a/include/inc/clnpport.h b/include/inc/clnpport.h new file mode 100644 index 0000000..6b83b2b --- /dev/null +++ b/include/inc/clnpport.h @@ -0,0 +1,52 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : clnpport.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file specifies defines which should be */ +/* ported for use by specific system. */ +/* */ +/* For information see the: */ +/* ISO 8473 "Information processing systems - Data communication - */ +/* Protocol providing the connectionless-mode network service"; */ +/* ISO 8348 "Information processing systems - Data communication - */ +/* Network service definition. Addendum 1: Connectionless-mode */ +/* transmission". */ +/* ISO 9542 "Information processing systems - Telecommunications */ +/* and information exchange beetween systems - End system to */ +/* Intermediate system routing exchange protocol for use with */ +/* ISO 8473. */ +/* */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 05/06/97 EJV 02 Removed SWAP_SHORT macro */ +/* 05/31/96 EJV 01 Created */ +/************************************************************************/ + +#ifndef CLNPPORT_INCLUDED +#define CLNPPORT_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/* NOTE: This file currently is empty. It may be used in the future */ +/* to implement code specific to an operating system. */ + +#endif +#ifdef __cplusplus +} + +#endif /* end of 'already included' */ diff --git a/include/inc/conpack.h b/include/inc/conpack.h new file mode 100644 index 0000000..d237441 --- /dev/null +++ b/include/inc/conpack.h @@ -0,0 +1,101 @@ +#define NDIS_PACKET_TYPE_DIRECTED 0x0001 +#define NDIS_PACKET_TYPE_MULTICAST 0x0002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004 +#define NDIS_PACKET_TYPE_BROADCAST 0x0008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020 +#define NDIS_PACKET_TYPE_SMT 0x0040 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000 +#define NDIS_PACKET_TYPE_GROUP 0x1000 + +#define OID_GEN_SUPPORTED_LIST 0x00010101 +#define OID_GEN_HARDWARE_STATUS 0x00010102 +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_MEDIA_IN_USE 0x00010104 +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +#define OID_GEN_LINK_SPEED 0x00010107 +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +#define OID_GEN_VENDOR_ID 0x0001010C +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +#define OID_GEN_DRIVER_VERSION 0x00010110 +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 +#define OID_GEN_MAC_OPTIONS 0x00010113 + +#define OID_GEN_XMIT_OK 0x00020101 +#define OID_GEN_RCV_OK 0x00020102 +#define OID_GEN_XMIT_ERROR 0x00020103 +#define OID_GEN_RCV_ERROR 0x00020104 +#define OID_GEN_RCV_NO_BUFFER 0x00020105 + +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C + +#define OID_GEN_RCV_CRC_ERROR 0x0002020D +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E + + +// +// 802.3 Objects (Ethernet) +// + +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +#define OID_802_3_MULTICAST_LIST 0x01010103 +#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 + +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 + +#define OID_802_3_XMIT_DEFERRED 0x01020201 +#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define OID_802_3_RCV_OVERRUN 0x01020203 +#define OID_802_3_XMIT_UNDERRUN 0x01020204 +#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 + +// +// WAN objects +// + +#define OID_WAN_PERMANENT_ADDRESS 0x04010101 +#define OID_WAN_CURRENT_ADDRESS 0x04010102 +#define OID_WAN_QUALITY_OF_SERVICE 0x04010103 +#define OID_WAN_PROTOCOL_TYPE 0x04010104 +#define OID_WAN_MEDIUM_SUBTYPE 0x04010105 +#define OID_WAN_HEADER_FORMAT 0x04010106 + +#define OID_WAN_GET_INFO 0x04010107 +#define OID_WAN_SET_LINK_INFO 0x04010108 +#define OID_WAN_GET_LINK_INFO 0x04010109 + +#define OID_WAN_LINE_COUNT 0x0401010A + +#define OID_WAN_GET_BRIDGE_INFO 0x0401020A +#define OID_WAN_SET_BRIDGE_INFO 0x0401020B +#define OID_WAN_GET_COMP_INFO 0x0401020C +#define OID_WAN_SET_COMP_INFO 0x0401020D +#define OID_WAN_GET_STATS_INFO 0x0401020E + + + diff --git a/include/inc/copp.h b/include/inc/copp.h new file mode 100644 index 0000000..d03b1b9 --- /dev/null +++ b/include/inc/copp.h @@ -0,0 +1,68 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : copp.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* COPP internal header file. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/11/01 JRB 04 Convert to use ASN1R. */ +/* 02/20/98 JRB 03 Chg abort_reason to ST_INT8 too. */ +/* 12/22/97 JRB 02 Use ST_INT8. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/05/97 JRB 01 Created. */ +/************************************************************************/ + +#ifndef COPP_INCLUDED +#define COPP_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "copp_usr.h" +#include "copp_log.h" + + /*======================================================*/ + /* C O N N E C T I O N S T A T E S */ + /*======================================================*/ + +/* Valid states, the first IDLE state must be 0) */ +#define COPP_STATE_IDLE 0 +#define COPP_STATE_AWAIT_CPA 1 +#define COPP_STATE_AWAIT_CON_RSP 2 +#define COPP_STATE_CONNECTED 3 + + /*======================================================*/ + /* PRESENTATION INTERNAL FUNCTIONS */ + /*======================================================*/ + +/* Function to encode and send ARP PPDU. */ +ST_VOID copp_p_abort_req (ACSE_CONN *acse_conn, ST_INT8 abort_reason, ST_INT8 event_id); +ST_VOID START_p_user_data (ASN1_DEC_CTXT *aCtx); + + /*======================================================*/ + /* PRESENTATION INTERNAL VARIABLES */ + /*======================================================*/ + +extern ST_UCHAR only_loc_psel []; /* Local len & PSEL */ +extern ST_BOOLEAN p_user_data_is_outer; /* Is P-User-data outermost constr?*/ + /* SD_TRUE or SD_FALSE */ + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* COPP_INCLUDED */ +/************************************************************************/ + diff --git a/include/inc/copp_log.h b/include/inc/copp_log.h new file mode 100644 index 0000000..73b7298 --- /dev/null +++ b/include/inc/copp_log.h @@ -0,0 +1,167 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997 - 2007, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : copp_log.h */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file contains logging macros for COPP. */ +/* Note: To compile logging functions use the DEBUG_SISCO define */ +/* in the project make file. */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/01/07 EJV 05 Updated COPP_LOG_* macros to use SLOG_n. */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 10/08/98 MDE 03 Migrated to updated SLOG interface */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/19/97 JRB 02 General cleanup. */ +/* 02/20/97 EJV 01 Created */ +/************************************************************************/ + +#ifndef COPP_LOG_INCLUDED +#define COPP_LOG_INCLUDED + +#include "slog.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* NOTE: COPP log masks and acse_debug_sel are defined in acse2usr.h */ + +#if defined(DEBUG_SISCO) + +extern SD_CONST ST_CHAR *SD_CONST _copp_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _copp_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _copp_dec_hex_logstr; +extern SD_CONST ST_CHAR *SD_CONST _copp_enc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _copp_enc_hex_logstr; + + /*--------------------------------------------*/ + /* hard errors logging */ + /*--------------------------------------------*/ + + #define COPP_LOG_ERR0(a) \ + SLOG_0 (acse_debug_sel & COPP_LOG_ERR,_copp_err_logstr,a) + + #define COPP_LOG_ERR1(a,b) \ + SLOG_1 (acse_debug_sel & COPP_LOG_ERR,_copp_err_logstr,a,b) + + #define COPP_LOG_ERR2(a,b,c) \ + SLOG_2 (acse_debug_sel & COPP_LOG_ERR,_copp_err_logstr,a,b, c) + + #define COPP_LOG_ERR3(a,b,c,d) \ + SLOG_3 (acse_debug_sel & COPP_LOG_ERR,_copp_err_logstr,a,b, c,d) + + /*--------------------------------------------*/ + /* PS-user req and rsp logging */ + /*--------------------------------------------*/ + + #define COPP_LOG_ENC0(a) \ + SLOG_0 (acse_debug_sel & COPP_LOG_ENC,_copp_enc_logstr,a) + + #define COPP_LOG_ENC1(a,b) \ + SLOG_1 (acse_debug_sel & COPP_LOG_ENC,_copp_enc_logstr,a,b) + + #define COPP_LOG_ENC2(a,b,c) \ + SLOG_2 (acse_debug_sel & COPP_LOG_ENC,_copp_enc_logstr,a,b,c) + + #define COPP_LOG_ENC3(a,b,c,d) \ + SLOG_3 (acse_debug_sel & COPP_LOG_ENC,_copp_enc_logstr,a,b,c,d) + + #define COPP_LOG_ENC4(a,b,c,d,e) \ + SLOG_4 (acse_debug_sel & COPP_LOG_ENC,_copp_enc_logstr,a,b,c,d,e) + + /* continuation macros */ + #define COPP_LOG_ENCC0(a) \ + SLOGC_0 (acse_debug_sel & COPP_LOG_ENC,a) + + #define COPP_LOG_ENCC1(a,b) \ + SLOGC_1 (acse_debug_sel & COPP_LOG_ENC,a,b) + + /* hex logging */ + #define COPP_LOG_ENCH(a,b) \ + SLOGH (acse_debug_sel & COPP_LOG_ENC,a,b) + + /*--------------------------------------------*/ + /* PS-user ind and cnf logging */ + /*--------------------------------------------*/ + + #define COPP_LOG_DEC0(a) \ + SLOG_0 (acse_debug_sel & COPP_LOG_DEC,_copp_dec_logstr,a) + + #define COPP_LOG_DEC1(a,b) \ + SLOG_1 (acse_debug_sel & COPP_LOG_DEC,_copp_dec_logstr,a,b) + + #define COPP_LOG_DEC2(a,b,c) \ + SLOG_2 (acse_debug_sel & COPP_LOG_DEC,_copp_dec_logstr,a,b,c) + + #define COPP_LOG_DEC3(a,b,c,d) \ + SLOG_3 (acse_debug_sel & COPP_LOG_DEC,_copp_dec_logstr,a,b,c,d) + + #define COPP_LOG_DEC4(a,b,c,d,e) \ + SLOG_4 (acse_debug_sel & COPP_LOG_DEC,_copp_dec_logstr,a,b,c,d,e) + + /* continuation macros */ + #define COPP_LOG_DECC0(a) \ + SLOGC_0 (acse_debug_sel & COPP_LOG_DEC,a) + + #define COPP_LOG_DECC1(a,b) \ + SLOGC_1 (acse_debug_sel & COPP_LOG_DEC,a,b) + + /* hex logging */ + #define COPP_LOG_DECH(a,b) \ + SLOGH (acse_debug_sel & COPP_LOG_DEC,a,b) + +#else + /*--------------------------------------------*/ + /* hard errors logging */ + /*--------------------------------------------*/ + + #define COPP_LOG_ERR0(a) + #define COPP_LOG_ERR1(a,b) + #define COPP_LOG_ERR2(a,b,c) + #define COPP_LOG_ERR3(a,b,c,d) + + /*--------------------------------------------*/ + /* PS-user req and rsp logging */ + /*--------------------------------------------*/ + + #define COPP_LOG_ENC0(a) + #define COPP_LOG_ENC1(a,b) + #define COPP_LOG_ENC2(a,b,c) + #define COPP_LOG_ENC3(a,b,c,d) + #define COPP_LOG_ENC4(a,b,c,d,e) + #define COPP_LOG_ENCC0(a) + #define COPP_LOG_ENCC1(a,b) + #define COPP_LOG_ENCH(a,b) + + /*--------------------------------------------*/ + /* PS-user ind and cnf logging */ + /*--------------------------------------------*/ + + #define COPP_LOG_DEC0(a) + #define COPP_LOG_DEC1(a,b) + #define COPP_LOG_DEC2(a,b,c) + #define COPP_LOG_DEC3(a,b,c,d) + #define COPP_LOG_DEC4(a,b,c,d,e) + #define COPP_LOG_DECC0(a) + #define COPP_LOG_DECC1(a,b) + #define COPP_LOG_DECH(a,b) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ diff --git a/include/inc/copp_usr.h b/include/inc/copp_usr.h new file mode 100644 index 0000000..4715da3 --- /dev/null +++ b/include/inc/copp_usr.h @@ -0,0 +1,193 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2001, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : copp_usr.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* COPP user header file. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/11/01 JRB 05 Convert to use ASN1R. */ +/* 08/13/98 JRB 04 Lint cleanup. */ +/* 06/17/98 JRB 03 Add error codes. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/19/97 JRB 02 Add "CALLING" support. General cleanup. */ +/* 03/05/97 JRB 01 Created. */ +/************************************************************************/ + +#ifndef COPP_USR_INCLUDED +#define COPP_USR_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + + /*======================================================*/ + /* PRESENTATION USER DEFINES */ + /* */ + /*======================================================*/ +/* Defines used for encoded values of "Provider-reason". */ +/* Used in encode/decode of CPR (Connect Presentation Reject PPDU). */ +#define PROV_REASON_NOT_SPECIFIED 0 +#define PROV_REASON_CONGESTION 1 +#define PROV_REASON_LOCAL_LIMIT 2 +#define PROV_REASON_CALLED_PRES_ADDR 3 +#define PROV_REASON_VERSION 4 +#define PROV_REASON_DEFAULT_CONTEXT 5 +#define PROV_REASON_USER_DATA 6 +#define PROV_REASON_NO_PSAP 7 + +/* Defines for P-CONNECT.cnf result parameter */ +#define P_CON_RESULT_ACCEPT 0 +#define P_CON_RESULT_USER_REJ 1 +#define P_CON_RESULT_PROVIDER_REJ 2 + + /*======================================================*/ + /* PRESENTATION ERROR CODES */ + /* */ + /*======================================================*/ + +/* NOTE: Values begin from E_COPP (found in glberror.h). */ + +/* COPP general errors */ +#define COPP_ERR_INV_PSEL 0x3101 /* Invalid local PSEL */ +#define COPP_ERR_INV_STATE 0x3102 /* Invalid connect state */ + + /*======================================================*/ + /* PRESENTATION GLOBAL VARIABLES */ + /* */ + /*======================================================*/ +extern ST_CHAR expected_pdv_pci; +extern ST_UCHAR *pdv_data_ptr; +extern ST_INT pdv_data_len; + + /*======================================================*/ + /* PRESENTATION PROVIDER FUNCTIONS */ + /* */ + /* Called by user to encode and send */ + /* Presentation PDUs. */ + /*======================================================*/ + +/************************************************************************/ +/* copp_con_req */ +/* P-Connect Request. */ +/************************************************************************/ +ST_RET copp_con_req (ST_LONG copp_bind_id, ACSE_CONN *acse_conn, PRES_ADDR *rem_addr); + +/************************************************************************/ +/* copp_rel_req */ +/* P-Release Request. */ +/************************************************************************/ +ST_RET copp_rel_req (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* copp_con_rsp_pos */ +/* P-Connect Accept. */ +/************************************************************************/ +ST_RET copp_con_rsp_pos (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* copp_con_rsp_neg */ +/* P-Connect Reject. */ +/* If "provider_reason" < 0, this is "user-reject", else this is */ +/* "provider-reject" and the value of "provider_reason" will be */ +/* encoded in the "Provider-reason" parameter of the PPDU. */ +/************************************************************************/ +ST_RET copp_con_rsp_neg (ACSE_CONN *acse_conn, ST_INT provider_reason); + +/************************************************************************/ +/* copp_rel_rsp_pos */ +/* P-Release Positive Response. */ +/************************************************************************/ +ST_RET copp_rel_rsp_pos (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* copp_u_abort_req */ +/* P-U-Abort Request. */ +/************************************************************************/ +ST_RET copp_u_abort_req (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* copp_data_req */ +/* P-Data Request. */ +/************************************************************************/ +ST_RET copp_data_req (ACSE_CONN *acse_conn); + + + /*======================================================*/ + /* PRESENTATION USER FUNCTIONS */ + /* */ + /* Called by Presentation to pass decoded */ + /* Presentation PDUs up to user. */ + /*======================================================*/ + +/************************************************************************/ +/* u_copp_con_cnf */ +/* P-CONNECT.cnf (Connect Confirm). */ +/* Parameters: */ +/* acse_conn Pointer to connection info */ +/* result P_CON_RESULT_ACCEPT, P_CON_RESULT_USER_REJ or */ +/* P_CON_RESULT_PROVIDER_REJ */ +/* reason Provider-reason (if result=P_CON_RESULT_PROVIDER_REJ)*/ +/************************************************************************/ +ST_VOID u_copp_con_cnf (ACSE_CONN *acse_conn, ST_INT result, ST_INT reason); + +/************************************************************************/ +/* u_copp_rel_cnf_pos */ +/* P-RELEASE.cnf+ (POSITIVE Release Confirm). */ +/************************************************************************/ +ST_VOID u_copp_rel_cnf_pos (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* u_copp_con_ind */ +/* P-Connect Indication. */ +/************************************************************************/ +ST_VOID u_copp_con_ind (ST_LONG user_bind_id, ACSE_CONN *acse_conn); + +/************************************************************************/ +/* u_copp_rel_ind */ +/* P-Release Indication. */ +/************************************************************************/ +ST_VOID u_copp_rel_ind (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* u_copp_p_abort_ind */ +/* P-P-Abort Indication. */ +/************************************************************************/ +ST_VOID u_copp_p_abort_ind (ACSE_CONN *acse_conn, ST_INT reason); + +/************************************************************************/ +/* u_copp_u_abort_ind */ +/* P-U-Abort Indication. */ +/************************************************************************/ +ST_VOID u_copp_u_abort_ind (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* u_copp_data_ind */ +/* P-Data Indication. */ +/************************************************************************/ +ST_VOID u_copp_data_ind (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* START_pdv_list */ +/* ASN.1 decode function that may be used by Presentation-user */ +/* (i.e. ACSE) for decoding a "PDV-list" (same encoding as "EXTERNAL"). */ +/************************************************************************/ +ST_VOID START_pdv_list (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* COPP_USR_INCLUDED */ +/************************************************************************/ + diff --git a/include/inc/cosp.h b/include/inc/cosp.h new file mode 100644 index 0000000..e25d01f --- /dev/null +++ b/include/inc/cosp.h @@ -0,0 +1,199 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : cosp.h */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file defines variable and functions */ +/* internal to the COSP (decoding and encoding). */ +/* */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/12/01 JRB 03 Reverse cosp_enc_cn_ac change (not needed). */ +/* 08/01/01 JRB 02 Del rem_addr from cosp_enc_cn_ac proto. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 01/13/97 EJV 01 Created */ +/************************************************************************/ +#ifndef COSP_INCLUDED +#define COSP_INCLUDED + + +#ifdef __cplusplus +extern "C" { +#endif + + +extern ST_UCHAR cosp_only_ssel [1+MAX_SSEL_LEN]; + + + /*======================================================*/ + /* */ + /* C O N N E C T I O N S T A T E S */ + /* */ + /*======================================================*/ + + +/* Valid states, the first IDLE state must be 0) */ +#define COSP_CSTATE_IDLE 0 /* idle, transport not connected*/ +#define COSP_CSTATE_WAIT_TCON_CNF 1 /* wait T-CONNECT.cnf */ +#define COSP_CSTATE_IDLE_TCON 100 /* idle, transport connected */ +#define COSP_CSTATE_WAIT_AC 2 /* wait for ACCEPT SPDU */ +#define COSP_CSTATE_WAIT_DN 3 /* wait for DISCONNECT SPDU */ +#define COSP_CSTATE_WAIT_CON_RSP 8 /* wait S-CONNECT.rsp */ +#define COSP_CSTATE_WAIT_REL_RSP 9 /* wait for S-RELEASE.rsp */ +#define COSP_CSTATE_WAIT_TDISCON_IND 16 /* wait T-DISCONNECT.ind */ +#define COSP_CSTATE_DATA_XFER 713 /* Data Transfer state */ + + /*======================================================*/ + /* */ + /* C O S P P R O T O C O L D E F I N E S */ + /* */ + /* D E C O D E D S P D U S T R U C T U R E S */ + /* */ + /*======================================================*/ + + +/* Encoding for supported COSP versions codes */ +#define COSP_VER1 (ST_UCHAR) 1 +#define COSP_VER2 (ST_UCHAR) 2 + + +/* Encoding of SPDU Session Identifier (SI) codes */ +#define COSP_SI_DATA (ST_UCHAR) 1 +#define COSP_SI_GIVE_TOKEN (ST_UCHAR) 1 /* this is correct DT=GIVE-TOKEN */ +#define COSP_SI_FINISH (ST_UCHAR) 9 +#define COSP_SI_DISCON (ST_UCHAR) 10 +#define COSP_SI_REFUSE (ST_UCHAR) 12 +#define COSP_SI_CONNECT (ST_UCHAR) 13 +#define COSP_SI_ACCEPT (ST_UCHAR) 14 +#define COSP_SI_ABORT (ST_UCHAR) 25 +#define COSP_SI_AB_ACCEPT (ST_UCHAR) 26 + + +/* struct used to store decoded params from CONNECT or ACCEPT SPDU */ +typedef struct tagCOSP_CN_AC + { + ST_UCHAR prot_option; + ST_UINT16 initiator_tsdu_size; + ST_UINT16 responder_tsdu_size; + ST_UCHAR ver_num; + ST_UCHAR ses_urequir [2]; /* byte0 (bits 9-16), byte1 (bits 1-8)*/ + ST_UCHAR loc_ssel [1+MAX_SSEL_LEN]; + ST_UCHAR rem_ssel [1+MAX_SSEL_LEN]; + ST_UINT udata_len; /* SS-user data length */ + ST_UCHAR *udata_ptr; /* SS-user data pointer */ + }COSP_CN_AC; + + +/* Encoding for Reason Code PI in a REFUSE SPDU generated by SS-user */ +#define COSP_RF_REASON_U_NOT_SPECIFIED (ST_UCHAR) 0 +#define COSP_RF_REASON_U_CONGESTION (ST_UCHAR) 1 +#define COSP_RF_REASON_U_REJECT (ST_UCHAR) 2 +/* Encoding for Reason Code PI in a REFUSE SPDU generated by SS-provider */ +#define COSP_RF_REASON_S_INV_SSEL (ST_UCHAR) 128+1 +#define COSP_RF_REASON_S_NOT_ATTACHED (ST_UCHAR) 128+2 +#define COSP_RF_REASON_S_CONGESTION (ST_UCHAR) 128+3 +#define COSP_RF_REASON_S_INV_VERSION (ST_UCHAR) 128+4 +#define COSP_RF_REASON_S_NOT_SPECIFIED (ST_UCHAR) 128+5 +#define COSP_RF_REASON_S_RESTRICTIONS (ST_UCHAR) 128+6 + + +/* struct used to store decoded params from REFUSE SPDU */ +typedef struct tagCOSP_RF + { + ST_BOOLEAN disconnect; /* if SD_TRUE then disconnect transport */ + ST_UCHAR ver_num; + ST_UCHAR reason; /* reason code for refuse connection */ + ST_UCHAR ses_urequir [2]; /* byte0 (bits 9-16), byte1 (bits 1-8) */ + ST_UINT udata_len; /* SS-user data length */ + ST_UCHAR *udata_ptr; /* SS-user data pointer */ + }COSP_RF; + + +#define COSP_P_AB_SPDU_LEN 9 /* P-ABORT is fixed in size */ + +/* Encoding for Transport Disconnect PI in an ABORT (and FINISH) SPDU */ +#define COSP_TCONN_KEEP (ST_UCHAR) 0x00 +#define COSP_TCONN_RELEASE (ST_UCHAR) 0x01 +/* | with one reason code below */ +#define COSP_AB_REASON_USER_ABORT (ST_UCHAR) 0x02 +#define COSP_AB_REASON_PROT_ERROR (ST_UCHAR) 0x04 +#define COSP_AB_REASON_NO_REASON (ST_UCHAR) 0x08 +#define COSP_AB_REASON_IMPLEMENTATION (ST_UCHAR) 0x10 + + +/* struct used to store decoded params from ABORT SPDU */ +typedef struct tagCOSP_AB + { + ST_BOOLEAN disconnect; /* if SD_TRUE then disconnect transport */ + ST_UCHAR reason; /* reason code for abort connection */ + ST_UINT reflect_par_len; /* Reflect param length */ + ST_UCHAR reflect_par [9]; /* Reflect param */ + ST_UINT udata_len; /* SS-user data length */ + ST_UCHAR *udata_ptr; /* SS-user data pointer */ + }COSP_AB; + + +/* struct used to store decoded params from FINISH SPDU */ +typedef struct tagCOSP_FN_DN + { + ST_BOOLEAN disconnect; /* SD_TRUE to discon transport (FN)*/ + ST_UINT udata_len; /* SS-user data length */ + ST_UCHAR *udata_ptr; /* SS-user data pointer */ + }COSP_FN_DN; + +/* struct used to store decoded params from DATA SPDU */ +typedef struct tagCOSP_DT + { + ST_UINT udata_len; /* SS-user data length */ + ST_UCHAR *udata_ptr; /* SS-user data pointer */ + }COSP_DT; + + + + /*======================================================*/ + /* */ + /* E N C O D E / D E C O D E F U N C T I O N S */ + /* */ + /*======================================================*/ + +/* cosp_enc.c */ +ST_UINT cosp_envelope_len (ACSE_CONN *con, ST_UINT rem_ssel_len, ST_UCHAR spdu_type); + +ST_RET cosp_enc_cn_ac (ACSE_CONN *con, PRES_ADDR *rem_addr, + char **spdu_ptr, ST_UINT *spdu_len, ST_UCHAR spdu_type); +ST_RET cosp_enc_rf (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len, ST_UCHAR reason); +ST_RET cosp_enc_fn_dn (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len, ST_UCHAR spdu_type); +ST_RET cosp_enc_u_ab (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len); +ST_RET cosp_enc_p_ab (char *spdu_ptr, ST_INT err_code); +ST_RET cosp_enc_dt (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len); + +/* cosp_dec.c */ +ST_RET cosp_dec_cn_ac (COSP_CN_AC *dec_par, char *spdu_buf, ST_UINT spdu_len, ST_UCHAR spdu_type); +ST_RET cosp_dec_rf (COSP_RF *dec_par, char *spdu_buf, ST_UINT spdu_len); +ST_RET cosp_dec_fn_dn (COSP_FN_DN *dec_par, char *spdu_buf, ST_UINT spdu_len, ST_UCHAR spdu_type); +ST_RET cosp_dec_ab (COSP_AB *dec_par, char *spdu_buf, ST_UINT spdu_len); +ST_RET cosp_dec_dt (COSP_DT *dec_par, char *spdu_buf, ST_UINT spdu_len); + + + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + + diff --git a/include/inc/cosp_log.h b/include/inc/cosp_log.h new file mode 100644 index 0000000..20c88e6 --- /dev/null +++ b/include/inc/cosp_log.h @@ -0,0 +1,214 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : cosp_log.h */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file contains logging macros for COSP. */ +/* Note: To compile logging functions use the DEBUG_SISCO define */ +/* in the project make file. */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 10/08/98 MDE 04 Migrated to updated SLOG interface */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 04/24/97 JRB 03 Added NO-DEBUG version of COSP_LOG_ERRH. */ +/* 03/20/97 EJV 02 Enhanced logging. */ +/* 02/13/97 EJV 01 Created */ +/************************************************************************/ +#ifndef COSP_LOG_INCLUDED +#define COSP_LOG_INCLUDED + +#include "slog.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* NOTE: COSP log masks and acse_debug_sel are defined in acse2usr.h */ + + +#if defined(DEBUG_SISCO) + + /* this number will identify the log entry as COSP log */ + +extern SD_CONST ST_CHAR *SD_CONST _cosp_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _cosp_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _cosp_dec_hex_logstr; +extern SD_CONST ST_CHAR *SD_CONST _cosp_enc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _cosp_enc_hex_logstr; + + /*--------------------------------------------*/ + /* hard errors logging */ + /*--------------------------------------------*/ + + #define COSP_LOG_ERR0(a) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slog (sLogCtrl,_cosp_err_logstr,thisFileName,__LINE__,a);\ + } + #define COSP_LOG_ERR1(a,b) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slog (sLogCtrl,_cosp_err_logstr,thisFileName,__LINE__,a,b);\ + } + #define COSP_LOG_ERR2(a,b,c) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slog (sLogCtrl,_cosp_err_logstr,thisFileName,__LINE__,a,b,c);\ + } + #define COSP_LOG_ERR3(a,b,c,d) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slog (sLogCtrl,_cosp_err_logstr,thisFileName,__LINE__,a,b,c,d);\ + } + /* continuation macros */ + #define COSP_LOG_ERRC0(a) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slogc (sLogCtrl,a);\ + } + #define COSP_LOG_ERRC1(a,b) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slogc (sLogCtrl,a,b);\ + } + #define COSP_LOG_ERRC2(a,b,c) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c);\ + } + /* hex logging */ + #define COSP_LOG_ERRH(a,b) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slogHex (sLogCtrl,a,b);\ + } + + /*--------------------------------------------*/ + /* SS-user req and rsp logging */ + /*--------------------------------------------*/ + + #define COSP_LOG_ENC0(a) {\ + if (acse_debug_sel & COSP_LOG_ENC)\ + _slog (sLogCtrl,_cosp_enc_logstr,thisFileName,__LINE__,a);\ + } + #define COSP_LOG_ENC1(a,b) {\ + if (acse_debug_sel & COSP_LOG_ENC)\ + _slog (sLogCtrl,_cosp_enc_logstr,thisFileName,__LINE__,a,b);\ + } + #define COSP_LOG_ENC2(a,b,c) {\ + if (acse_debug_sel & COSP_LOG_ENC)\ + _slog (sLogCtrl,_cosp_enc_logstr,thisFileName,__LINE__,a,b,c);\ + } + #define COSP_LOG_ENC3(a,b,c,d) {\ + if (acse_debug_sel & COSP_LOG_ENC)\ + _slog (sLogCtrl,_cosp_enc_logstr,thisFileName,__LINE__,a,b,c,d);\ + } + #define COSP_LOG_ENC4(a,b,c,d,e) {\ + if (acse_debug_sel & COSP_LOG_ENC)\ + _slog (sLogCtrl,_cosp_enc_logstr,thisFileName,__LINE__,a,b,c,d,e);\ + } + /* continuation macros */ + #define COSP_LOG_ENCC0(a) {\ + if (acse_debug_sel & COSP_LOG_ENC)\ + _slogc (sLogCtrl,a);\ + } + #define COSP_LOG_ENCC1(a,b) {\ + if (acse_debug_sel & COSP_LOG_ENC)\ + _slogc (sLogCtrl,a,b);\ + } + /* hex logging */ + #define COSP_LOG_ENCH(a,b) {\ + if (acse_debug_sel & COSP_LOG_ENC_HEX)\ + _slogHex (sLogCtrl,a,b);\ + } + + /*--------------------------------------------*/ + /* SS-user ind and cnf logging */ + /*--------------------------------------------*/ + + #define COSP_LOG_DEC0(a) {\ + if (acse_debug_sel & COSP_LOG_DEC)\ + _slog (sLogCtrl,_cosp_dec_logstr,thisFileName,__LINE__,a);\ + } + #define COSP_LOG_DEC1(a,b) {\ + if (acse_debug_sel & COSP_LOG_DEC)\ + _slog (sLogCtrl,_cosp_dec_logstr,thisFileName,__LINE__,a,b);\ + } + #define COSP_LOG_DEC2(a,b,c) {\ + if (acse_debug_sel & COSP_LOG_DEC)\ + _slog (sLogCtrl,_cosp_dec_logstr,thisFileName,__LINE__,a,b,c);\ + } + #define COSP_LOG_DEC3(a,b,c,d) {\ + if (acse_debug_sel & COSP_LOG_DEC)\ + _slog (sLogCtrl,_cosp_dec_logstr,thisFileName,__LINE__,a,b,c,d);\ + } + #define COSP_LOG_DEC4(a,b,c,d,e) {\ + if (acse_debug_sel & COSP_LOG_DEC)\ + _slog (sLogCtrl,_cosp_dec_logstr,thisFileName,__LINE__,a,b,c,d,e);\ + } + /* continuation macros */ + #define COSP_LOG_DECC0(a) {\ + if (acse_debug_sel & COSP_LOG_DEC)\ + _slogc (sLogCtrl,a);\ + } + #define COSP_LOG_DECC1(a,b) {\ + if (acse_debug_sel & COSP_LOG_DEC)\ + _slogc (sLogCtrl,a,b);\ + } + /* hex logging */ + #define COSP_LOG_DECH(a,b) {\ + if (acse_debug_sel & COSP_LOG_DEC_HEX)\ + _slogHex (sLogCtrl,a,b);\ + } +#else + /*--------------------------------------------*/ + /* hard errors logging */ + /*--------------------------------------------*/ + + #define COSP_LOG_ERR0(a) + #define COSP_LOG_ERR1(a,b) + #define COSP_LOG_ERR2(a,b,c) + #define COSP_LOG_ERR3(a,b,c,d) + #define COSP_LOG_ERRC0(a) + #define COSP_LOG_ERRC1(a,b) + #define COSP_LOG_ERRC2(a,b,c) + #define COSP_LOG_ERRH(a,b) + + /*--------------------------------------------*/ + /* SS-user req and rsp logging */ + /*--------------------------------------------*/ + + #define COSP_LOG_ENC0(a) + #define COSP_LOG_ENC1(a,b) + #define COSP_LOG_ENC2(a,b,c) + #define COSP_LOG_ENC3(a,b,c,d) + #define COSP_LOG_ENC4(a,b,c,d,e) + #define COSP_LOG_ENCC0(a) + #define COSP_LOG_ENCC1(a,b) + #define COSP_LOG_ENCH(a,b) + + /*--------------------------------------------*/ + /* SS-user ind and cnf logging */ + /*--------------------------------------------*/ + + #define COSP_LOG_DEC0(a) + #define COSP_LOG_DEC1(a,b) + #define COSP_LOG_DEC2(a,b,c) + #define COSP_LOG_DEC3(a,b,c,d) + #define COSP_LOG_DEC4(a,b,c,d,e) + #define COSP_LOG_DECC0(a) + #define COSP_LOG_DECC1(a,b) + #define COSP_LOG_DECH(a,b) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ diff --git a/include/inc/cosp_usr.h b/include/inc/cosp_usr.h new file mode 100644 index 0000000..98e603e --- /dev/null +++ b/include/inc/cosp_usr.h @@ -0,0 +1,531 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : cosp_usr.h */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file defines the interface between the */ +/* Connection-oriented Session Protocol (COSP) and the */ +/* Connection-oriented Presentation Layer (COPP) in order */ +/* to exchange Session Service Data Units (SSDU). */ +/* */ +/* For information see the: */ +/* ISO 8326 "Information processing systems - Open Systems */ +/* Interconnection - Basic connection oriented session service */ +/* definition. */ +/* ISO 8327 "Information processing systems - Open Systems */ +/* Interconnection - Basic connection oriented session protocol */ +/* specification. */ +/* ISO 8327/ADD.2 (Draft for Version2). */ +/* */ +/* */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* cosp_bind */ +/* u_cosp_bind_cnf */ +/* cosp_unbind */ +/* u_cosp_unbind_cnf */ +/* */ +/* cosp_con_req */ +/* u_cosp_con_cnf_pos */ +/* u_cosp_con_cnf_neg */ +/* */ +/* u_cosp_con_ind */ +/* cosp_con_rsp_pos */ +/* cosp_con_rsp_neg */ +/* */ +/* cosp_rel_req */ +/* u_cosp_rel_cnf_pos */ +/* */ +/* u_cosp_rel_ind */ +/* cosp_rel_rsp_pos */ +/* */ +/* cosp_u_abort_req */ +/* u_cosp_abort_ind */ +/* */ +/* cosp_data_req */ +/* u_cosp_data_ind */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 04/10/97 JRB 02 Chg error defs to use base from "glberror.h".*/ +/* 01/10/97 EJV 01 Created */ +/************************************************************************/ +#ifndef COSP_USR_INCLUDED +#define COSP_USR_INCLUDED + + +#ifdef __cplusplus +extern "C" { +#endif + + + /*======================================================*/ + /* */ + /* C O S P S P E C I F I C D E F I N E S */ + /* */ + /*======================================================*/ + +/* Defines below specify limits on certain parameters for the COSP MOSI */ +/* Version2 implementation: */ + +#define COSP_MAX_UDATA_CON (ST_UINT) 10240 +#define COSP_MAX_ENVELOPE (ST_UINT) 56 +#define COSP_MAX_UDATA ((ST_UINT) 65535 - COSP_MAX_ENVELOPE) + + /*======================================================*/ + /* */ + /* Result and Reason Codes in S-CONNECT.cnf- */ + /* */ + /*======================================================*/ + +/* Result codes */ +#define COSP_CON_CNF_U_REJECT 1 +#define COSP_CON_CNF_P_REJECT 2 + +/* Reason codes in S-CONNECT.cnf- when result=COSP_CON_CNF_U_REJECT */ +#define COSP_CON_CNF_U_NOT_SPECIFIED 0 +#define COSP_CON_CNF_U_CONGESTION 1 +#define COSP_CON_CNF_U_IN_UDATA 2 /* udata = PPDU */ + +/* Valid reason codes in S-CONNECT.cnf- when result=COSP_CON_CNF_P_REJECT */ +#define COSP_CON_CNF_P_NOT_SPECIFIED 3 /* or version not supported, */ + /* or implementation restrictions */ +#define COSP_CON_CNF_P_CONGESTION 4 +#define COSP_CON_CNF_P_INV_SSEL 5 /* called Session Address unknown */ +#define COSP_CON_CNF_P_NOT_ATTACHED 6 /* called SS-user not attached to SSAP */ + + + /*======================================================*/ + /* */ + /* Reason Codes in S-CONNECT.rsp- */ + /* */ + /*======================================================*/ + +/* Reason codes in S-CONNECT.rsp- (if connection rejected) */ +#define COSP_CON_RSP_U_NOT_SPECIFIED 0 +#define COSP_CON_RSP_U_CONGESTION 1 +#define COSP_CON_RSP_U_IN_UDATA 2 /* udata = PPDU */ + + + /*======================================================*/ + /* */ + /* Reason Codes in S-P-ABORT.ind */ + /* */ + /*======================================================*/ + +#define COSP_P_AB_IND_TP_DISCON 0 +#define COSP_P_AB_IND_PROT_ERR 1 +#define COSP_P_AB_IND_UNDEFINED 2 + + + /*======================================================*/ + /* */ + /* C O S P E R R O R C O D E S */ + /* */ + /*======================================================*/ + +/* NOTE: Values begin from E_COSP (found in glberror.h). */ + +/* COSP general errors */ +#define COSP_ERR_BIND_STATE 0x3201 /* Invalid Bind state->already called*/ +#define COSP_ERR_TP4_RET 0x3202 /* Transport layer returned error */ +#define COSP_ERR_INV_TP4_ADDR 0x3203 /* Transport address invalid */ +#define COSP_ERR_INV_CON_STATE 0x3204 /* Invalid connect state */ +#define COSP_ERR_INV_SSEL 0x3205 /* Invalid local SSEL length */ +#define COSP_ERR_INV_UDATA_LEN 0x3206 /* Invalid User Data length */ +#define COSP_ERR_INV_POINTER 0x3207 /* Invalid pointer to encode buffer */ + +/* COSP PDU decoding errors */ +#define COSP_ERR_DEC_INV_SPDU 0x3210 /* Invalid/not-supp. SPDU SI rcvd */ +#define COSP_ERR_DEC_INV_LEN 0x3211 /* Invalid SPDU len (dec vs fun len) */ +#define COSP_ERR_DEC_INV_PI_CODE 0x3212 /* Invalid/out-of-place PGI/PI code */ +#define COSP_ERR_DEC_INV_LOC_SSEL 0x3213 /* SPDU not addressed to local SSEL */ +#define COSP_ERR_DEC_INV_PROT_OPT 0x3214 /* Extended SPDU concat not supp. */ +#define COSP_ERR_DEC_INV_SEG 0x3215 /* Invalid/not-supp. SSDU Segmenting */ +#define COSP_ERR_DEC_INV_PROT_VER 0x3216 /* Invalid/not-supp. prot version */ +#define COSP_ERR_DEC_INV_FUN_UNITS 0x3217 /* Invalid/not-supp. FU in Ses Req. */ +#define COSP_ERR_DEC_INV_RF_UDATA 0x3218 /* Invalid udata len,len>0 reason!=2 */ +#define COSP_ERR_DEC_INV_AB_RP 0x3219 /* Inv len of Reflect Par in AB SPDU */ + + + /*======================================================*/ + /* */ + /* B I N D I N G F U N C T I O N S */ + /* */ + /*======================================================*/ + +/************************************************************************/ +/* cosp_bind */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to bind to local Session Address. */ +/* The SS-user should implement the u_cosp_bind_cnf function. */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_user_bind_id COSP User's id for this binding.*/ +/* PRES_ADDR *loc_addr Local Address to bind to */ +/* ST_INT sharable Ignored, (for compatibility with*/ +/* ST_INT max_conns Ignored, previous versions) */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if bind successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_bind (ST_LONG cosp_user_bind_id, PRES_ADDR *loc_addr, + ST_INT sharable, ST_INT max_conns); + + +/************************************************************************/ +/* u_cosp_bind_cnf */ +/*----------------------------------------------------------------------*/ +/* This function is called by the SS-provider to indicate the result of */ +/* the bind operation (see cosp_bind func). */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_user_bind_id COSP User's id for this binding. */ +/* ST_LONG cosp_bind_id COSP id for this binding. */ +/* ST_RET result Indicates if the bind was successful: */ +/* = 0 Success */ +/* <> 0 Error code */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_bind_cnf (ST_LONG cosp_user_bind_id, ST_LONG cosp_bind_id, + ST_RET result); + + +/************************************************************************/ +/* cosp_unbind */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to unbind from local Session Address. */ +/* The SS-user should implement the u_cosp_unbind_cnf function. */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_bind_id COSP's id to unbind. */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if unbind successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_unbind (ST_LONG cosp_bind_id); + + +/************************************************************************/ +/* u_cosp_unbind_cnf */ +/*----------------------------------------------------------------------*/ +/* This function is called by the SS-provider to indicate that the */ +/* unbind operation finished (see cosp_unbind func). */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_user_bind_id COSP User's id for this binding.*/ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_unbind_cnf (ST_LONG cosp_user_bind_id); + + + /*======================================================*/ + /* */ + /* C O N N E C T F U N C T I O N S (CALLED SIDE) */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* u_cosp_con_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* remote node wishes to establish a connection. */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_user_bind_id COSP user id bind */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_con_ind (ST_LONG cosp_user_bind_id, ACSE_CONN *con); + + +/************************************************************************/ +/* cosp_con_rsp_pos */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to Accept an incomming connection. */ +/* If SS-user data are sent make sure the reason=COSP_CON_RSP_U_IN_UDATA*/ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to con info struct */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_con_rsp_pos (ACSE_CONN *con); + + +/************************************************************************/ +/* cosp_con_rsp_neg */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to Reject an incomming connection. */ +/* If SS-user data are sent make sure the reason=COSP_CON_RSP_U_IN_UDATA*/ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to con info struct */ +/* ST_INT reason Reason for reject COSP_CON_RSP_U_... */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_con_rsp_neg (ACSE_CONN *con, ST_INT reason); + + + /*======================================================*/ + /* */ + /* C O N N E C T F U N C T I O N S (CALLING SIDE) */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* cosp_con_req */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to establish a Session connection. */ +/* SS-user should implement following functions to confirm to this */ +/* request: u_cosp_con_cnf_pos and u_cosp_con_cnf_neg. */ +/* If this function returns value other then SD_SUCCESS then the function */ +/* u_cosp_con_cnf_xxx will not be called. */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_bind_id COSP bind id (also= TP4 bind id)*/ +/* PRES_ADDR *rem_addr Remote Address */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_con_req (ST_LONG cosp_bind_id, PRES_ADDR *rem_addr, ACSE_CONN *con); + + +/************************************************************************/ +/* u_cosp_con_cnf_pos */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that */ +/* the connection has been established. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_con_cnf_pos (ACSE_CONN *con); + + +/************************************************************************/ +/* u_cosp_con_cnf_neg */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate the */ +/* connection has been rejected by remote. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* ST_INT result see def results COSP_CON_CNF_... above */ +/* ST_INT reason see def reasons COSP_CON_CNF_... above */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_con_cnf_neg (ACSE_CONN *con, ST_INT result, ST_INT reason); + + + /*======================================================*/ + /* */ + /* C O N N E C T I O N R E L E A S E (CALLED SIDE) */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* u_cosp_rel_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* remote node wishes to release a connection. The SS-user should call */ +/* cosp_rel_rsp_pos to release the connection. Negative cnf not allowed.*/ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_rel_ind (ACSE_CONN *con); + + +/************************************************************************/ +/* cosp_rel_rsp_pos */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to respond positively to release of */ +/* connection. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_rel_rsp_pos (ACSE_CONN *con); + + + /*======================================================*/ + /* */ + /* C O N N E C T I O N R E L E A S E (CALLING SIDE)*/ + /* */ + /*======================================================*/ + +/************************************************************************/ +/* cosp_rel_req */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to release a Session connection. */ +/* SS-user should implement the u_cosp_rel_cnf_pos function to receive */ +/* confirm for this request. Negative confirm is not implemented. */ +/* If this function returns value other then SD_SUCCESS then the function */ +/* u_cosp_rel_cnf_pos will not be called. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_rel_req (ACSE_CONN *con); + + +/************************************************************************/ +/* u_cosp_rel_cnf_pos */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate positive */ +/* result of the release operation. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_rel_cnf_pos (ACSE_CONN *con); + + + /*======================================================*/ + /* */ + /* A B O R T F U N C T I O N S */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* cosp_u_abort_req */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to Abort a connection (S-U-ABORT) */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_u_abort_req (ACSE_CONN *con); + + +/************************************************************************/ +/* u_cosp_p_abort_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* connection has been aborted by SS-provider (local or remote). */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* ST_INT reason see def reasons COSP_P_AB_IND_... above */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_p_abort_ind (ACSE_CONN *con, ST_INT reason); + + +/************************************************************************/ +/* u_cosp_u_abort_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* connection has been aborted by remote SS-user. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_u_abort_ind (ACSE_CONN *con); + + + /*======================================================*/ + /* */ + /* D A T A T R A N S F E R F U N C T I O N S */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* cosp_data_req */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to transfer normal data on a previously */ +/* established connection. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_data_req (ACSE_CONN *con); + + +/************************************************************************/ +/* u_cosp_data_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* data have been received. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_data_ind (ACSE_CONN *con); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + diff --git a/include/inc/dibmatch.h b/include/inc/dibmatch.h new file mode 100644 index 0000000..b38b488 --- /dev/null +++ b/include/inc/dibmatch.h @@ -0,0 +1,64 @@ +#ifndef DIBMATCH_H + +#define DIBMATCH_H + +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003 - 2005, All Rights Reserved */ +/* */ +/* MODULE NAME : dibmatch.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/04/06 EJV 04 Added DLLs incompatibility comments. */ +/* 07/19/05 EJV 03 Added gensock2.h include. */ +/* 07/12/05 EJV 02 DIB_MATCH_CTRL: added use_gethostbyname. */ +/* 06/11/03 MDE 01 New */ +/************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gensock2.h" + +/************************************************************************/ +/* General address matching defines, control, functions */ + +/* Compare Results */ +#define DIB_MATCH_NOT 0 +#define DIB_MATCH_CLOSE 1 +#define DIB_MATCH_EXACT 2 + +typedef struct dib_match_ctrl_tag + { + /* Note: adding/removing fields to/from this struct will make older */ + /* !!! applications incompatible with new security DLLs. */ + ST_BOOLEAN match_allow_missing_ae_elements; + ST_BOOLEAN match_allow_extra_ae_elements; + + ST_BOOLEAN match_ap_title; + ST_BOOLEAN match_ae_qualifier; + ST_BOOLEAN match_ap_invoke; + ST_BOOLEAN match_ae_invoke; + ST_BOOLEAN match_psel; + ST_BOOLEAN match_ssel; + ST_BOOLEAN match_tsel; + ST_BOOLEAN match_net_addr; + ST_BOOLEAN use_gethostbyname; /* gethostbyname() call may take LONG */ + /* time when the DNS is not available. */ + } DIB_MATCH_CTRL; + + + +#ifdef __cplusplus +} +#endif + +#endif /* DIBMATCH_H */ diff --git a/include/inc/ethertyp.h b/include/inc/ethertyp.h new file mode 100644 index 0000000..16f6f59 --- /dev/null +++ b/include/inc/ethertyp.h @@ -0,0 +1,72 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2002-2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ethertyp.h */ +/* PRODUCT(S) : MMS-EASE Lite */ +/* */ +/* MODULE DESCRIPTION : Ethertype frame encode functions and constants.*/ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/08/05 JRB 03 Chg first arg to etype_hdr_decode. */ +/* 03/24/03 ASK 02 Updated ETYPE_TYPE_* constant values */ +/* 11/20/02 ASK 01 Created */ +/************************************************************************/ + +#if !defined(ETHERTYP_H_INCLUDED) +#define ETHERTYP_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "clnp_usr.h" +#include "clnp_sne.h" + + +#define ETYPE_VLAN_TYPE_ID 0x8100 +#define ETYPE_TYPE_GOOSE 0x88B8 +#define ETYPE_TYPE_GSE 0x88B9 +#define ETYPE_TYPE_SV 0x88BA +#define ETYPE_TCI_GOOSE 0x8000 +#define ETYPE_TCI_GSE 0x2000 +#define ETYPE_TCI_SV 0x8001 + +#define VLAN_HEAD_LEN 4 +#define ETYPE_HEAD_LEN 8 + +/* Ethertype Frame Info to be filled out by the user */ +typedef struct + { + ST_UINT16 tci; /* VLAN Tag Control Info */ + ST_UINT16 etypeID; /* Ethertype ID */ + ST_UINT16 appID; /* APP ID */ + } ETYPE_INFO; + + +ST_UCHAR *etype_hdr_encode(ST_UCHAR *bufPtr, /* buffer to encode into */ + ST_INT bufLen, /* len of buffer */ + ST_INT *asn1Len, /* ptr to len encoded */ + ETYPE_INFO *info);/* ptr etype struct */ + +ST_UCHAR *vlan_hdr_encode(ST_UCHAR *bufPtr, /* buffer to encode into */ + ST_INT *asn1Len, /* ptr to len encoded */ + ETYPE_INFO *info); /* ptr etype struct */ + +ST_UCHAR *etype_hdr_decode(SN_UNITDATA *sn_req, + ETYPE_INFO *info, /* ptr etype struct */ + ST_INT *bufLen); /* ptr to len decoded */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ diff --git a/include/inc/ethsub.h b/include/inc/ethsub.h new file mode 100644 index 0000000..b7d0a4f --- /dev/null +++ b/include/inc/ethsub.h @@ -0,0 +1,132 @@ +#ifndef ETHSUB_INCLUDED +#define ETHSUB_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2000-2006 All Rights Reserved */ +/* */ +/* MODULE NAME : ethsub.h */ +/* PRODUCT(S) : Lean-T Stack for Windows 95/98/NT */ +/* */ +/* MODULE DESCRIPTION : */ +/* Definitions to allow Subnetwork interface to work with OSI LLC */ +/* Ethernet driver. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/21/06 JRB 04 Chg to use SISCO naming conventions. */ +/* 04/14/06 JRB 03 Add sysincs header. */ +/* 11/20/02 ASK 02 Add ethdown_etype proto */ +/* 04/06/00 JRB 01 Created */ +/************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************/ +/* Include files required to interface with */ +/* OSI LLC NDIS Ethernet Driver */ +/* */ +/****************************************************************/ + +#include "conpack.h" +#include "osillc.h" + +#include "glbtypes.h" +#include "sysincs.h" +#include "slog.h" +#include "stime.h" +#include "clnp_usr.h" /* clnp_sne.h needs this */ +#include "clnp_log.h" +#include "clnp_sne.h" /* for SN_UNITDATA, etc. */ + +/****************************************************************/ +/****************************************************************/ + +typedef struct +{ +/** ----- Following fields are specific to this Access Method */ + HANDLE hFile; /* LLC device driver descriptor */ + + unsigned long seq; /* sequence number to expect */ + void *readlst[10]; /* list of pointers to out of sequence packet blocks */ + + /* ----- Following fields are required for 95/98 */ + struct rd_wr_block *pWriteEvents; /* list of write event structures */ + struct rd_wr_block *pReadEvents; /* list of read event structures */ +} LLC_CONTEXT; + +/************************************************************************/ +/* OSI Event structure - Modified for MMS_LITE */ +/************************************************************************/ + +typedef struct + { + void * nxevt; + SN_UNITDATA sn_req; /* event data in format needed by LEANT CLNP. */ + } SN_EVENT; + +typedef struct rd_wr_block + { + int inuse; + HANDLE hEvent; + OVERLAPPED *ovlp; + ST_UCHAR *framep; /* pointer to raw Ethernet frame */ + void *pb; + LLC_CONTEXT *gccp; + } RD_WR_BLOCK; + +/************************************************************************/ +/* MMS_LITE function to Queue received packet for Lite CLNP. */ +/************************************************************************/ +void QueueRxPacket (ST_UCHAR *framep); + +/************************************************************************/ +/* Functions that may be called from CLNP. */ +/************************************************************************/ +void ethdown (SN_UNITDATA *sn_req); +void ethdown_etype (SN_UNITDATA *sn_req); +void ethsapoff (void); +void ethsapon (ST_CHAR *drvname); +int llcsetup (void); + +BOOL QueryOid (HANDLE hDriver, ULONG ulOid, PBYTE pBuffer, ULONG ulLength); +BOOL SetOid (HANDLE hDriver, ULONG ulOid, PBYTE pBuffer, ULONG ulLength); + +void osifreeevt (SN_EVENT *evt); +SN_EVENT *osiallocevt (); +void osiputevt (SN_EVENT *evt); +SN_EVENT *osigetevt (); + +void OsiReadThread (LPDWORD lpdwParam); +void OsiReadThreadNT (LPDWORD lpdwParam); +void CALLBACK WriteCompletion (DWORD error, DWORD length, OVERLAPPED *ovlp); +void CALLBACK ReadCompletion (DWORD error, DWORD length, OVERLAPPED *ovlp); +void ProcessReadBlock (OVERLAPPED *ovlp); + +/************************************************************************/ +/* Global variables. */ +/************************************************************************/ +extern LLC_CONTEXT GCC; /* General Current Context */ +extern LLC_CONTEXT *GCCP; /* General Current Context Pointer */ + +extern int MaxWriteOut; +extern int MaxReadOut; +extern int FramesPerBlock; +extern int ReceptionMode; +extern int DriverID; +extern int NumWriteOut; +extern CRITICAL_SECTION csOsiList; /* Critical Section object for OSI Event List */ +extern BOOL bServiceControl; +extern BOOL bNT; +extern BOOL bOsiRequired; +extern DWORD Priority; + +#ifdef __cplusplus +} +#endif + +#endif /* !ETHSUB_INCLUDED */ + diff --git a/include/inc/fkeydefs.h b/include/inc/fkeydefs.h new file mode 100644 index 0000000..abc6394 --- /dev/null +++ b/include/inc/fkeydefs.h @@ -0,0 +1,209 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986-2001 All Rights Reserved */ +/* */ +/* MODULE NAME : fkeydefs.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains user application definitions and is not */ +/* directly a part of MMSEASE. It is only used for the sample */ +/* application. */ +/* NOTE: If the ?key.c module is compiled with define UTIL_LIB only */ +/* following functions from wkey.c are exposed: */ +/* nlfn () */ +/* log_hex_bytes () */ +/* wait_debug_log () */ +/* wait_msg () */ +/* flush_keys () */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/18/03 JRB 05 Fix QNX #ifdef. */ +/* 02/17/03 CRM 04 Added "defined(linux)" code. */ +/* 02/17/03 JRB 03 Stop using SYSTEM_SEL define. */ +/* 05/16/01 EJV 02 Added proto for term_init, term_rest. */ +/* 01/22/98 NAV 01 Added funct_menu proto. */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef FKEYDEFS_INCLUDED +#define FKEYDEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#if defined (_WIN32) +#include +#endif + +/************************************************************************/ +/* NOTE: */ +/* For QUICK WIN application the call to kbhit () or getch () functions */ +/* will install our keyboard handling hook function to intercept the */ +/* keyboard input. */ +/* It is not necessary to call strt_Hook function, because the kbhit */ +/* and getch functions are checking for the hook beeing in place. */ +/* It will be wise to call the end_Hook function to clear the Windows */ +/* from our keyboard handling if not needed anymore. */ +/************************************************************************/ +int strt_Hook(ST_VOID); +int end_Hook(ST_VOID); + +/*====================================================================== + Basic functions keyboard functions: + kbhit () checks if keyboard was pressed. It installs also our + keyboard handling hook function for the QUICK WIN apps. + fkey_kbhit () returns SD_FALSE most of the times. Only every KBHIT_PERIOD + (50-th time when called) it will return the return + from the call to the kbhit () function. + This function may be absolete. + getch () returns the ASCII value of a pressed key. The kbhit () + function should be called first to see if the keyboard + was pressed. The function will install our keyboard + handling hook function for the QUICK WIN applications, + if not already installed. + flush_keys () flushes the keyboard character buffer. + get_a_char () will wait for the keyboard hit and return the ascii + code for the character. In addition the function will + echo the character to screen. +======================================================================*/ +#if !defined (_WIN32) +#if defined(__VMS) +/* VMS uses a short return type, and is prototyped in a lot of places */ +ST_INT kbhit (ST_VOID); +ST_INT getch (ST_VOID); +#else +int kbhit (ST_VOID); +int getch (ST_VOID); +#endif +#else +int nt_kbhit (ST_VOID); +#define kbhit nt_kbhit +#endif + +ST_RET fkey_kbhit (ST_VOID); +ST_VOID flush_keys (ST_VOID); +ST_CHAR get_a_char (ST_VOID); + +#define KBHIT_PERIOD 50 +#define KBHIT() fkey_kbhit () + + +/*======================================================================= + Formatting output to stdout (or FILE *) functions: + log_hex_bytes () outputs formatted hex data to a dest (may be stdout). + It will format each line (16 hex numbers) of the output + as follow: + "\noffs hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh *tttttttttttttttt*" + list_bytes () outputs formatted bytes to stdout. It will format each + line (16 hex numbers) of the output as follow: + "\n hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh " + list_ascii () outputs the ascii data to stdout. The ascii data will + be split on more then one line if required. The data in + the ptr do not have to be NULL terminated. + list_words () outputs the formatted words to stdout. The format is + as follow: + "hhhh hhhh hhhh ...." +========================================================================*/ +ST_VOID log_hex_bytes (FILE *dest, ST_UCHAR *ptr, ST_INT len); +ST_VOID list_bytes (ST_UCHAR *ptr, ST_INT len); +ST_VOID list_ascii (ST_CHAR *ptr, ST_INT len); +ST_VOID list_words (ST_UINT *ptr, ST_INT len); + + +/*======================================================================= + Functions to display a message and wait for user to hit a key: + wait_debug_log () outputs the str to a fptr (which may be stdout). + If the output is stdout the function will wait for user + to hit a key. During waiting the function will call + the servefun () to execute background processing. + wait_msg () outputs the str to stdout. The function will wait for + user to hit a key. During waiting the function will call + the servefun () to execute background processing. + wait_key () waits for user to hit a key. During waiting the function + will call the servefun () to execute background processing. + err_msg () outputs the str to stdout. The function will wait for + user to hit a key. Note that this func will NOT call + the servefun () while waiting for the keyboard input. + ask () asks a yes/no question and return the answer. + SD_TRUE will be returned if the answer is 'y' or 'Y'; + SD_FALSE will be returned if the answer is 'n' or 'N'; + if user presses the ENTER key the default answer will + be returned. + key_err () displays a message and returns shortly after, used to + display error messages without waiting for user to hit + a key to continue. +========================================================================*/ +ST_VOID wait_debug_log (FILE *fptr, ST_CHAR *str); +ST_VOID wait_msg (ST_CHAR *msg); +ST_VOID wait_key (ST_VOID); +ST_VOID err_msg (ST_CHAR *str); +ST_BOOLEAN ask (ST_CHAR *question, ST_BOOLEAN default_ans); +ST_VOID key_err (ST_CHAR *msg); + +/*======================================================================== + Pointer to USER's background function called while waiting for keyboard + input in following functions: + wait_key () + wait_msg () + wait_debug_log () + do_fun () + This function is initialized to a nlfn () which returns 0 if called. +========================================================================*/ +extern ST_RET (*servefun) (ST_VOID); + +/*======================================================================== + Pointers to USER's functions handling the actions for key F1 - F10 + This pointers will be initialized at program startup to bad_key () + function, which flushes the keyboard buffer. +========================================================================*/ +extern ST_VOID (*funct_1) (ST_VOID); +extern ST_VOID (*funct_2) (ST_VOID); +extern ST_VOID (*funct_3) (ST_VOID); +extern ST_VOID (*funct_4) (ST_VOID); +extern ST_VOID (*funct_5) (ST_VOID); +extern ST_VOID (*funct_6) (ST_VOID); +extern ST_VOID (*funct_7) (ST_VOID); +extern ST_VOID (*funct_8) (ST_VOID); +extern ST_VOID (*funct_9) (ST_VOID); +extern ST_VOID (*funct_10) (ST_VOID); +extern ST_VOID (*funct_menu) (ST_VOID); /* may be used to refresh menu */ + +ST_VOID fun_null (ST_VOID); /* make all function keys F1-F10 illegal*/ +ST_VOID do_fun (ST_VOID); /* execute functions assigned to funct_n*/ + /* pointers until F10 is pressed. */ +ST_INT check_key (ST_VOID); /* Check for pressed function key and */ + /* execute an action for that key. */ + /* Returns 1 if F10 key was pressed, */ + /* 0 otherwise. */ + +/* functions implemented in ?key.c */ +#if defined(_AIX) || defined(sun) || defined(__hpux) || defined(linux) \ + || (defined(__alpha) && !defined(__VMS)) \ + || defined(VXWORKS) || defined(__QNX__) || defined(__VMS) +ST_VOID term_init (); +ST_VOID term_rest (); +#elif defined (__OS2__) +int term_init (void); +int term_rest (void); +#endif + +#if defined (_WIN32) +ST_RET term_init (ST_VOID); +ST_INT term_rest (ST_VOID); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* FKEYDEFS_INCLUDED */ diff --git a/include/inc/gen_list.h b/include/inc/gen_list.h new file mode 100644 index 0000000..88414a2 --- /dev/null +++ b/include/inc/gen_list.h @@ -0,0 +1,117 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1988-2000, All Rights Reserved */ +/* */ +/* MODULE NAME : gen_list.h */ +/* PRODUCT(S) : General Use */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the definitions as required for */ +/* manipulation of double-linked circular lists */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/04/06 EJV 04 Added DLLs incompatibility comments. */ +/* 04/20/00 JRB 03 Del (ST_VOID **) protos. ANSI doesn't like. */ +/* 10/09/98 JRB 02 Add list_find_prev, list_find_last. */ +/* 08/25/98 EJV 01 Use non-relaxed protos for __hpux. */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef GEN_LIST_INCLUDED +#define GEN_LIST_INCLUDED + + +#ifdef __cplusplus +extern "C" { +#endif + +/*#define FASTLIST */ + +/************************************************************************/ +/* LINKED LIST MECHANISM */ +/************************************************************************/ +/* This following structure is used in all doubly linked circular lists */ +/* as the first component in the structure. This allows one set of list*/ +/* manipulation primitives to be used with any linked structure */ +/* containing it. */ + +typedef struct dbl_lnk + { + /* Note: adding/removing fields to/from this struct will make older */ + /* !!! applications incompatible with new security DLLs. */ + struct dbl_lnk *next; + struct dbl_lnk *prev; + } DBL_LNK; + + +/************************************************************************/ +/* The variable below can be used to do integrity checking of any list */ +/* manipulated in the generic queuing functions by setting it to SD_TRUE */ + +extern ST_BOOLEAN list_debug_sel; + +/* For compatibility with older code only */ +#define list_sLogCtrl sLogCtrl + +/************************************************************************/ + +#ifdef FASTLIST +#define list_get_next(h,p) (((DBL_LNK *)p)->next == (DBL_LNK *)h ? NULL : ((DBL_LNK *)p)->next) +#define list_get_first(h) *(h);list_unlink (h,*h) +#else +/* NOTE: I_AM_THE_TRUE_GEN_LIST is only defined in the module */ +/* genlists.c so it will compile. */ +#if defined(I_AM_THE_TRUE_GEN_LIST) +ST_VOID *list_get_first (DBL_LNK **); +ST_VOID *list_get_next (DBL_LNK *, DBL_LNK *); +#else +ST_VOID *list_get_first (ST_VOID *); +ST_VOID *list_get_next (ST_VOID *, ST_VOID *); +#endif +#endif /* FASTLIST */ + + +/************************************************************************/ +/* Primitive functions for generic queue handling */ + +#if defined(I_AM_THE_TRUE_GEN_LIST) +ST_RET list_unlink (DBL_LNK **, DBL_LNK *); +ST_RET list_add_first (DBL_LNK **, DBL_LNK *); +ST_RET list_add_last (DBL_LNK **, DBL_LNK *); +ST_RET list_move_to_first (DBL_LNK **, DBL_LNK **, DBL_LNK *); +ST_RET list_find_node (DBL_LNK *, DBL_LNK *); +ST_RET list_add_node_after (DBL_LNK *, DBL_LNK *); +ST_INT list_get_sizeof (DBL_LNK *); +ST_VOID *list_get_last (DBL_LNK **); +#else +/* NOTE: these prototypes provide very little argument type checking. */ +/* They allow you to pass almost any argument without casting. */ +/* ANSI compilers automatically cast the arguments to (ST_VOID *). */ +/* This is not a great loss, because if the "real" prototypes were */ +/* used, most code would have to cast arguments to (DBL_LNK *) or */ +/* (DBL_LNK **), which would disable the argument type checking anyway. */ + +ST_RET list_unlink (ST_VOID *pphol, ST_VOID *pnode); +ST_RET list_add_first (ST_VOID *pphol, ST_VOID *pnode); +ST_RET list_add_last (ST_VOID *pphol, ST_VOID *pnode); +ST_RET list_move_to_first (ST_VOID *pphol1, ST_VOID *pphol2, ST_VOID *pnode); +ST_RET list_find_node (ST_VOID *pphol, ST_VOID *pnode); +ST_RET list_add_node_after (ST_VOID *pnode1, ST_VOID *pnode2); +ST_INT list_get_sizeof (ST_VOID *phol); +ST_VOID *list_get_last (ST_VOID *pphol); +#endif + +/* New functions. Abandon the "I_AM_THE_TRUE_GEN_LIST" casting business.*/ +DBL_LNK *list_find_prev (DBL_LNK *list_head_ptr, DBL_LNK *cur_node); +DBL_LNK *list_find_last (DBL_LNK *list_head_ptr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/inc/gensock2.h b/include/inc/gensock2.h new file mode 100644 index 0000000..2c2a3f1 --- /dev/null +++ b/include/inc/gensock2.h @@ -0,0 +1,591 @@ +/************************************************************************/ +/* SOFTWARE MODULE HEADER ***********************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2002 - 2007, All Rights Reserved */ +/* */ +/* MODULE NAME : gensock2.h */ +/* PRODUCT(S) : General Sockets Interface */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/08/08 MDE 29 Allow variable len header, sockEventQueueFlush*/ +/* 03/17/08 EJV 28 Chg MMSEASE_MOSI to !defined(MMS_LITE). */ +/* 12/07/07 EJV 27 Impl SISCO's KeepAlive (disconnect idle cons)*/ +/* GEN_SOCK_CTRL: added lastCheckIdleTime, */ +/* GEN_SOCK_CTXT: added maxIdleTime, */ +/* GEN_SOCK_STATS: added lastActivityTime. */ +/* 11/01/07 EJV 26 Moved include winsock2.h to sysincs.h. */ +/* Added new GS_DISCONNECT_* error codes. */ +/* Added GS_DISCONNECT_REASON_STR macro & vars. */ +/* 09/10/07 MDE 25 Added log_disable, to support IPC logging */ +/* 05/18/07 RKR 24 Ported to Red Hat 5 */ +/* 02/08/07 JRB 23 Add GEN_SOCK_EVENT, sockEventPut/Get. */ +/* Repl uSockConnect with 2 separate pointers */ +/* uSockConnectInd, uSockConnectConf. */ +/* 01/30/07 JRB 22 Del obsolete params & sockServiceFreeList. */ +/* 01/15/07 JRB 21 Del gs_poll_mode flag & poll_mode arg to */ +/* sockStart (no longer supported). */ +/* 01/03/07 EJV 20 GEN_SOCK_CTXT: del gSockMutex, txMutex fields*/ +/* 11/29/06 EJV 19 HP-UX: chg to use socklen_t. */ +/* 10/25/06 EJV 18 Ported to HP-UX. */ +/* 02/17/06 EJV 17 __VMS: added SOCK_OPTLEN,SOCK_ADDRLEN. */ +/* Aligned some defines. */ +/* 12/19/05 EJV 28 sockUsrFun: chg args. */ +/* GEN_SOCK: moved sockId, sockIdStr fields down*/ +/* 09/28/05 EJV 27 Implemented GEN_SOCK_CTXT. */ +/* Moved GENSOCK_MAX_HEADER_SIZE above struct. */ +/* Moved MUTEX macros to gensock2.c and renamed */ +/* GEN_SOCK: added sockId, sockIdStr, sockCtx. */ +/* GEN_SOCK_CTRL: added sockCtx. */ +/* Added GS_DISCONNECT_XXX_ERROR defines. */ +/* _sockAddSock: chg from ST_VOID to ST_RET ret.*/ +/* sockUsrFun: new func. */ +/* 07/11/05 EJV 26 Add convertIPAddr proto. */ +/* 06/10/05 JRB 25 Obsolete "_sockClose" function replaced with */ +/* macro that calls normal "sockClose". */ +/* 05/10/05 EJV 24 Added _sockAllocSock, _sockAddSock protos. */ +/* 03/23/05 EJV 23 Added sockCreateWakeupSockets */ +/* linux MMSEASE_MOSI:add GENSOCK_THREAD_SUPPORT*/ +/* 03/16/05 JRB 22 Add GENSOCK_HUNT_DISCONNECT define. */ +/* 02/21/05 JRB 21 Fix ioctlsocket define (deleted from tp0_sock)*/ +/* 02/10/05 MDE 20 Added sockGetRemAddrInfo */ +/* 07/22/04 EJV 19 sun: added GENSOCK_THREAD_SUPPORT */ +/* 06/18/04 MDE 18 Include winsock2.h if needed */ +/* 03/11/04 EJV 17 SOCK_OPTLEN,SOCK_ADDRLEN diff for each system*/ +/* 02/25/04 EJV 16 _AIX: added GENSOCK_THREAD_SUPPORT */ +/* Added SOCK_OPTLEN and SOCK_ADDRLEN. */ +/* Chg SOCK_NOTSOCK to be EBADF (not ENOTSOCK). */ +/* 01/27/04 EJV 15 Added SOCK_NOTSOCK error. */ +/* 01/14/04 EJV 14 GEN_SOCK: added sockTxQueuedGroupCnt field. */ +/* GEN_SOCK_DATA: added eot field. */ +/* Added sockGetTxQueueGroupCnt proto. */ +/* 10/23/03 JRB 13 Move all system includes to sysincs.h */ +/* 06/25/03 JRB 12 Move log macros to "sock_log.h". */ +/* 06/23/03 EJV 11 Added 'first' param to sockTxQueueAdd. */ +/* 06/20/03 EJV 10 Rem param from gs_mutex_get. */ +/* 06/20/03 EJV 09 Added sockTxQueueDestroy.Chg gSock w/pSock. */ +/* Alligned struct fields. */ +/* 06/19/03 EJV 08 _WIN32: added GENSOCK_THREAD_SUPPORT */ +/* Added comments to struct, #else, #endif */ +/* 06/19/03 JRB 07 Make Rx/Tx names more consistent. */ +/* 06/18/03 JRB 06 Move defines to top & add SOCKADDR*, ioctlsocket*/ +/* Del GENSOCK_THREAD_SUPPORT, define in makefile*/ +/* Add forward reference. */ +/* Add sockTxPend to GEN_SOCK. */ +/* Add GSOCK_LOG_FLOWH. */ +/* Del winsock2.h (windows.h gets right winsock)*/ +/* Use "base" slog macros. */ +/* Add uSockTxBufFree to GEN_SOCK_CONFIG. */ +/* Add sockTxMsg, sockTxQueue* funcs. */ +/* 06/13/03 MDE 05 More user poll featuresAdded sockGetFds */ +/* 06/13/03 EJV 04 Added parameter to gs_mutex_get. */ +/* 05/14/03 MDE 03 Added sockGetFds */ +/* 05/09/03 JRB 02 Add SOCK_* defines for !_WIN32 */ +/* 02/17/03 MDE 01 Created */ +/************************************************************************/ + +#ifndef GENSOCK_INCLUDED +#define GENSOCK_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "gen_list.h" +#include "glbsem.h" +#include "mem_chk.h" +#include "sock_log.h" /* logging macros */ + + +/* Windows vs. the rest of the world ... */ +#ifdef _WIN32 + +#if !defined(GENSOCK_THREAD_SUPPORT) +#define GENSOCK_THREAD_SUPPORT /*RXB*/ +#endif +#define SOCKET_ERRORNO WSAGetLastError() +#define SOCK_EADDRINUSE WSAEADDRINUSE +#define SOCK_WOULDBLOCK WSAEWOULDBLOCK +#define SOCK_INTR WSAEINTR +#define SOCK_NOBUFS WSAENOBUFS +#define SOCK_INPROGRESS WSAEINPROGRESS +#define SOCK_TIMEDOUT WSAETIMEDOUT +#define SOCK_NOTSOCK WSAENOTSOCK +#define CLOSE_SOCKET(x) closesocket(x) + +#define SOCK_OPTLEN ST_INT /* in getsockopt */ +#define SOCK_ADDRLEN ST_INT /* in accept */ + +#else /* !_WIN32 */ + +/* define multithread support for GENSOCK on some platforms */ +#if defined(_AIX) || defined(sun) || defined(__hpux) || \ + (defined(linux) && !defined(MMS_LITE)) +#if !defined(GENSOCK_THREAD_SUPPORT) +#define GENSOCK_THREAD_SUPPORT +#endif +#endif /* defined(_AIX) || ... */ + +#define SOCKET_ERRORNO errno +#define SOCK_EADDRINUSE EADDRINUSE +#define SOCK_WOULDBLOCK EWOULDBLOCK +#define SOCK_INTR EINTR +#define SOCK_NOBUFS ENOBUFS +#define SOCK_INPROGRESS EINPROGRESS +#define SOCK_TIMEDOUT ETIMEDOUT +#define SOCK_NOTSOCK EBADF +#define CLOSE_SOCKET(x) close(x) + +#define SOCKET int +#define INVALID_SOCKET (-1) +#define SOCKADDR struct sockaddr +#define SOCKADDR_IN struct sockaddr_in + +#if defined (__OS2__) /* OS/2 ioctl has extra arg */ +#define ioctlsocket(hSock,opt,valptr) ioctl(hSock, opt, (ST_CHAR *)valptr, sizeof(u_long)) +#elif defined (VXWORKS) /* VXWORKS wants arg to be int */ +#define ioctlsocket(hSock,opt,valptr) ioctl(hSock, opt, (int) valptr) +#else /* all other systems (e.g. UNIX) */ +#define ioctlsocket ioctl +#endif + +#if defined(_AIX) || defined(sun) || defined(__hpux) || defined(linux) +/* Note: __hpux will need these defines when passing access rights SCM_RIGHTS */ +/* through domain socket is working properly for _XOPEN_SOURCE_EXTENDED. */ +#define SOCK_OPTLEN socklen_t /* in getsockopt */ +#define SOCK_ADDRLEN socklen_t /* in accept */ +#elif defined(__VMS) +#define SOCK_OPTLEN __size_t /* in getsockopt */ +#define SOCK_ADDRLEN __size_t /* in accept */ +#else +/* all other no-Windows platforms not defined above */ +#define SOCK_OPTLEN int /* in getsockopt */ +#define SOCK_ADDRLEN int /* in accept */ +#endif +#endif /* !_WIN32 */ + + +struct tag_GEN_SOCK; /* Forward reference */ +/************************************************************************/ +/************************************************************************/ + +typedef struct tag_GEN_SOCK_DATA + { +/* User Send/Receive Queueing */ + DBL_LNK l; + +/* For user management of send/receive buffers */ + ST_UCHAR *usrBufBase; /* Data buffer */ + ST_INT usrBufLen; /* Total send buffer size */ + + ST_VOID *usr1; /* Misc. user use */ + ST_VOID *usr2; /* Misc. user use */ + +/* Data to be sent/Received Data */ + ST_UCHAR *data; /* Recv Data, Send Data */ + ST_INT dataLen; /* Length of data recvd, or to be sent */ + + ST_INT result; /* For receive, SD_SUCCESS or error */ + ST_BOOLEAN eot; /* SD_TRUE - if last msg in a group */ + } GEN_SOCK_DATA; + + + +/************************************************************************/ + +typedef struct + { + time_t createdTime; + time_t activeTime; /* connected or listening */ + ST_LONG numSend; /* num of RFC1006 msgs sent */ + ST_LONG numRecv; /* num of RFC1006 msgs received */ + ST_DOUBLE lastActivityTime; /* for disconnecting idle connections */ + } GEN_SOCK_STATS; + +/************************************************************************/ + +typedef struct tag_GEN_SOCK_CONFIG + { +/* Config parameters */ + ST_INT hdrSize; /* Default sizeof (ST_INT) */ + ST_INT hdrAllocSize; /* Size to allocate for hdrBuf */ + /* in GEN_SOCK struct */ + /* If 0 then hdrSize is used */ + +/* setsockopt parameters */ + ST_BOOLEAN setSockOpts; + ST_INT noDelay; + ST_INT keepAlive; + ST_INT reuseAddr; + ST_INT rcvBufSize; + ST_INT sndBufSize; + +/* User can set to disable receive */ + ST_BOOLEAN pauseRecv; + +/* Listen backlog */ + ST_INT listenBacklog; + +/* User callbacks */ + ST_RET (*uSockConnectInd) (struct tag_GEN_SOCK *pSock); + ST_RET (*uSockConnectConf) (struct tag_GEN_SOCK *pSock); + ST_VOID (*uSockDisconnect) (struct tag_GEN_SOCK *pSock); + ST_VOID (*uSockHunt) (struct tag_GEN_SOCK *pSock, ST_INT *huntStateIo, + ST_CHAR *buf, ST_INT bufCount, ST_INT *lenOut); + ST_VOID (*uSockRx) (struct tag_GEN_SOCK *pSock, GEN_SOCK_DATA *sockData); + ST_VOID (*uSockRxBufAlloc) (struct tag_GEN_SOCK *pSock, ST_INT dataLen, GEN_SOCK_DATA **sockData); + ST_VOID (*uSockTxBufFree) (struct tag_GEN_SOCK *pSock, GEN_SOCK_DATA *sockData); + ST_VOID (*uSockWritable) (struct tag_GEN_SOCK *pSock); + +/* User fields */ + ST_EVENT_SEM recvEvent; + ST_VOID *usr1; + ST_VOID *usr2; + ST_VOID *usr3; + ST_VOID *usr4; + +/* Internal Security Hooks: Set to NULL unless using security plug-in */ + ST_BOOLEAN secEnable; + ST_RET (*secConnectProc) (struct tag_GEN_SOCK *pSock); + ST_VOID (*secDisconnectProc) (struct tag_GEN_SOCK *pSock); + ST_RET (*secRxProc) (struct tag_GEN_SOCK *pSock, ST_CHAR *dest, ST_INT maxRx, + ST_INT flags, ST_INT *rxCountOut, ST_BOOLEAN *secDataLeftOut); + ST_RET (*secTxProc) (struct tag_GEN_SOCK *pSock, GEN_SOCK_DATA *sockData, ST_INT *numSentOut); + ST_VOID (*secWritable) (struct tag_GEN_SOCK *pSock); + ST_VOID (*secSockFree) (struct tag_GEN_SOCK *pSock); + + ST_VOID *secCtrl; + +/* Set to enable write select */ + ST_BOOLEAN chkWritable; + } GEN_SOCK_CONFIG; + +/************************************************************************/ + +/* State defines for GEN_SOCK */ +#define GS_STATE_LISTENING 1 +#define GS_STATE_STOPPING_LISTEN 2 +#define GS_STATE_FAILED_LISTEN 3 +#define GS_STATE_CONNECTING 4 +#define GS_STATE_CONNECTED 5 +#define GS_STATE_CLOSED 6 + +/* Role defines */ +#define GS_ROLE_CALLING 1 +#define GS_ROLE_LISTENING 2 +#define GS_ROLE_CALLED 3 + +/* disconnectReason defines */ +#define GS_DISCONNECT_UNKNOWN 0 +#define GS_DISCONNECT_CONNECT_FAILED 1 +#define GS_DISCONNECT_USR_REFUSED 2 +#define GS_DISCONNECT_SEND_FAILURE 3 +#define GS_DISCONNECT_RECV_FAILED 4 +#define GS_DISCONNECT_ACCEPT_FAILED 5 +#define GS_DISCONNECT_CLOSED 6 +#define GS_DISCONNECT_TERMINATING 7 +#define GS_DISCONNECT_RESOURCES_ERROR 8 +#define GS_DISCONNECT_INTERNAL_ERROR 9 +#define GS_DISCONNECT_NORMAL_DISCONNECT 10 /* normal disconnect */ +/* disconnectReason for SSL connection */ +#define GS_DISCONNECT_SSLE_LICENSE 11 /* SSL Engine licence expired */ +#define GS_DISCONNECT_SSLE_INT_ERR 12 /* SSL Engine internal error */ +#define GS_DISCONNECT_REKEY_FAILED 13 /* failed to rekey SSL conn */ +#define GS_DISCONNECT_CERT_VERIFY_ERR 14 /* certificate not acceptable */ +#define GS_DISCONNECT_CERT_ON_CRL 15 /* certificate on CRL */ +#define GS_DISCONNECT_SEC_PARAM_ERR 16 /* cipher or cert ctrl err */ +/* update gensock2.c sockDisconnReasonStr when more codes added */ + +extern ST_CHAR *sockDisconnReasonStr[]; +extern ST_INT sockDisconnReasonStrCnt; +/* disconnectReason strings for logging */ +#define GS_DISCONNECT_REASON_STR(reason) ((reason < sockDisconnReasonStrCnt) ? sockDisconnReasonStr[reason] : "DISCONNECT REASON: UNKNOWN") + +/* Hunt state defines */ +#define GENSOCK_HUNT_UNDERWAY 1 +#define GENSOCK_HUNT_DONE 2 +#define GENSOCK_HUNT_RESET 3 +#define GENSOCK_HUNT_DISCONNECT 4 /* stop hunting and disconnect */ + +#define RECV_STATE_HUNT 1 +#define RECV_STATE_DATA 2 + +#define GEN_SOCK_CTX_NAME_MAX_STR 32 /* Socket Context max name length */ +#define GEN_SOCK_CTX_ID_MAX_STR 20 +#define GEN_SOCK_SOCK_ID_MAX_STR (GEN_SOCK_CTX_NAME_MAX_STR + GEN_SOCK_CTX_ID_MAX_STR + 20) + +struct tag_GEN_SOCK_CTXT; /* Forward reference */ + +typedef struct tag_GEN_SOCK + { + DBL_LNK l; /* internal use */ + +/* Socket state */ + ST_INT sockState; + ST_INT role; + +/* Valid in user socket disconnet call */ + ST_INT disconnectReason; + +/* Config parameters */ + GEN_SOCK_CONFIG sockCfg; + + GEN_SOCK_STATS sockStats; + +/* For Listen socket only */ + ST_UINT maxActive; + ST_UINT numActive; + +/* For called socket, reference the listen socket */ + struct tag_GEN_SOCK *listenSocket; + + ST_INT callingAddrLen; + SOCKADDR_IN callingAddr; + +/* Internal */ + SOCKET hSock; + + ST_INT recvState; + ST_CHAR *recvBuf; + ST_INT recvDoneCount; + ST_INT recvCurrCount; + ST_CHAR *hdrBuf; /* ptr to buffer allocated after this struct*/ + GEN_SOCK_DATA *sockData; + + struct sockaddr_in sockAddrIn; + ST_BOOLEAN usrCloseCalled; + ST_BOOLEAN recvUsing; + + struct tag_GEN_SOCK_CTRL *serviceCtrl; + + GEN_SOCK_DATA *sockTxPend; /* Queue of data to be sent. */ + ST_UINT sockTxQueueGroupCnt; /* num of queued msgs w/eot to tx */ + + /* Fields added since MMS-SECURE, ICCP-SECURE v1.03 release */ + ST_UINT sockId; /* different id for each socket */ + ST_CHAR sockIdStr[GEN_SOCK_SOCK_ID_MAX_STR]; /* assemble for use in log later */ + + struct tag_GEN_SOCK_CTXT *sockCtx; + } GEN_SOCK; + +/************************************************************************/ + +/* Allow one for wakeup socket */ +#define GS_MAX_SOCK_PER_SERVICE FD_SETSIZE - 1 + +typedef struct tag_GEN_SOCK_CTRL + { + DBL_LNK l; + ST_INT numSock; + GEN_SOCK *sockList; + ST_DOUBLE lastCheckIdleTime; + +#if defined(GENSOCK_THREAD_SUPPORT) + ST_EVENT_SEM serviceEvent; + ST_THREAD_HANDLE thService; + ST_THREAD_ID tIdService; + + ST_UINT16 wakeupPort; + SOCKET xCalledSock; + SOCKET xCallingSock; +#endif /* GENSOCK_THREAD_SUPPORT */ + + struct tag_GEN_SOCK_CTXT *sockCtx; + } GEN_SOCK_CTRL; + +/************************************************************************/ +/* GEN_SOCK_EVENT: Socket event structure to store incoming event. */ + +/* Values for "eventType" member of GEN_SOCK_EVENT structure. */ +#define GS_EVENT_CONNECT_IND 1 /* connect indication */ +#define GS_EVENT_CONNECT_CONF 2 /* connect confirmation */ +#define GS_EVENT_DISCONNECT 3 /* socket disconnected */ +#define GS_EVENT_DATA_IND 4 /* data indication */ + +typedef struct + { + DBL_LNK l; + ST_INT eventType; /* type of event (GS_EVENT_DATA_IND, etc.)*/ + GEN_SOCK *pSock; + GEN_SOCK_DATA *sockData; + } GEN_SOCK_EVENT; + +/************************************************************************/ +/* gensock2 context */ +/* each sockStart() call will create new context with its own lists, */ +/* threads, and events handling. Call sockEnd() to clean. */ + +/* ctxStatus states */ +#define GEN_SOCK_CTX_ACTIVE 0 +#define GEN_SOCK_CTX_TERMINATING 1 + + +typedef struct tag_GEN_SOCK_CTXT + { + DBL_LNK l; /* internal use */ + + ST_UINT ctxId; /* diff id for each context */ + ST_INT ctxStatus; /* GEN_SOCK_CTX_xxx */ + ST_CHAR ctxName[GEN_SOCK_CTX_NAME_MAX_STR + GEN_SOCK_CTX_ID_MAX_STR]; + ST_BOOLEAN log_disable; + + /* Lists */ + GEN_SOCK_CTRL *sockServiceList; + + GEN_SOCK_EVENT *sockEventList; /* socket event list */ + /* maintained by sockEventPut/Get*/ + ST_INT sockEventCount; /* num events on sockEventList */ + /* maintained by sockEventPut/Get*/ + + ST_UINT maxIdleTime; /* ms, if>0 check for idle cons, */ + /* SISCO's KeepAlive implementation */ + + #if defined(GENSOCK_THREAD_SUPPORT) + /* Port used for wakeup sockets */ + ST_UINT16 gs_wakeup_port; /* default >= 55050 */ + + /* Used by list service thread */ + ST_INT gs_select_timeout; /* default = 100000 */ + + ST_BOOLEAN gTerminateService; + + #endif /* defined(GENSOCK_THREAD_SUPPORT) */ + } GEN_SOCK_CTXT; + +extern GEN_SOCK_CTXT *sockCtxList; /* contexts list */ + + +/************************************************************************/ +/* gensock2 user functions */ + +ST_RET sockStart (ST_CHAR *ctxName, GEN_SOCK_CTXT **sockCtxOut); +ST_RET sockStartEx (ST_CHAR *ctxName, GEN_SOCK_CTXT **sockCtxOut, ST_BOOLEAN log_disable); +ST_RET sockEnd (GEN_SOCK_CTXT *sockCtx); + +ST_RET sockInitCalling (GEN_SOCK_CTXT *sockCtx, GEN_SOCK_CONFIG *sockCfg, + ST_UINT16 portNo, ST_CHAR *ipAddr, GEN_SOCK **pSockOut); + +ST_RET sockInitListen (GEN_SOCK_CTXT *sockCtx, GEN_SOCK_CONFIG *sockCfg, + ST_UINT16 portNo, ST_INT maxActive, GEN_SOCK **pListenSockOut); + +ST_RET sockTx (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData, ST_INT *numSentOut); +ST_RET sockTxMsg (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData); +ST_RET sockTxQueueAdd (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData, ST_BOOLEAN first); +ST_RET sockTxQueueDestroy (GEN_SOCK *pSock); +ST_RET sockTxQueueProc (GEN_SOCK *pSock); +ST_UINT sockTxQueueGroupCntGet (GEN_SOCK *pSock); +ST_RET sockStopRecv (GEN_SOCK *pSock); +ST_RET sockClose (GEN_SOCK *pSock); +ST_RET sockFree (GEN_SOCK *pSock); + +/* Polling support */ + +/* Get socket descriptors */ +typedef struct + { + ST_INT totalfds; + ST_UINT selectnfds; + + ST_INT numReadfds; + fd_set readfds; + + ST_INT numWritefds; + fd_set writefds; + + ST_INT numExceptfds; + fd_set exceptfds; + } GENSOCK_FD_SET; + +ST_VOID sockGetFds (GEN_SOCK_CTRL *serviceCtrl, GENSOCK_FD_SET *sockFds); + +/* Return values for sockCtrlService, sockSelectResultProcess */ +#define GS_SELECT_NO_ACTIVE_SOCK 1 +#define GS_SELECT_TIMEOUT 2 +#define GS_SELECT_ERROR 3 +#define GS_SELECT_ACTIVE 4 +#define GS_SELECT_TERMINATED 5 + +ST_VOID sockServiceAll (GEN_SOCK_CTXT *sockCtx, ST_LONG timeOut); +ST_INT sockCtrlService (GEN_SOCK_CTRL *serviceCtrl, ST_LONG timeOut); + +#if !defined(GENSOCK_THREAD_SUPPORT) +ST_VOID sockInitAllFds (GENSOCK_FD_SET *sockFds); +#endif + +ST_VOID sockInitFds (GEN_SOCK_CTRL *serviceCtrl, GENSOCK_FD_SET *sockFds); +ST_VOID sockAddReadFds (GENSOCK_FD_SET *sockFds, SOCKET hSock); +ST_VOID sockAddWriteFds (GENSOCK_FD_SET *sockFds, SOCKET hSock); +ST_VOID sockAddExceptFds (GENSOCK_FD_SET *sockFds, SOCKET hSock); +ST_INT sockSelectResultProcess (GEN_SOCK_CTRL *serviceCtrl, + int nfds, GENSOCK_FD_SET *sockFds); + +/* Thread support */ +ST_RET sockCreateWakeupSockets (GEN_SOCK_CTXT *sockCtx, + ST_UINT16 basePort, ST_UINT portRange, + ST_UINT16 *usedPort, + SOCKET *callingSock, SOCKET *calledSock); +ST_VOID sockServiceWakeAll (GEN_SOCK_CTXT *sockCtx); +ST_VOID sockServiceWake (GEN_SOCK_CTRL *serviceCtrl); + +/* Logging */ +ST_VOID sockLogState (GEN_SOCK_CTXT *sockCtx); +ST_VOID sockLogSockState (GEN_SOCK *pSock, ST_CHAR *prefix); + +/* Socket info */ +ST_RET sockGetRemAddrInfo (GEN_SOCK *pSock, SOCKADDR_IN *remSockAddrDest, + ST_CHAR **remAddrTxtOut, ST_INT *portOut); + +/* Functions to maintain list of GEN_SOCK_EVENT. */ +ST_VOID sockEventPut (GEN_SOCK_CTXT *sockCtx, GEN_SOCK_EVENT *event); /* put on list*/ +GEN_SOCK_EVENT *sockEventGet (GEN_SOCK_CTXT *sockCtx); /* get from list*/ +ST_VOID sockEventQueueFlush (GEN_SOCK_CTXT *sockCtx, GEN_SOCK *pSock); + +/************************************************************************/ +/************************************************************************/ +/* INTERNAL */ +/************************************************************************/ + +/* sockUsrFun calls usrFun for each socket in every context, if the */ +/* usrFun doesn't return SD_SUCCESS then socket will be closed; */ +/* errMsg will be logged on error. */ +ST_VOID sockUsrFun (ST_RET (*usrFun)(ST_VOID *secCtrl), ST_CHAR *errMsg); + +GEN_SOCK *_sockAllocSock (GEN_SOCK_CTXT *sockCtx, + ST_INT role, ST_INT sockState, SOCKET hSock, + GEN_SOCK_CONFIG *sockCfg); +ST_RET _sockAddSock (GEN_SOCK *pSock); + +ST_RET _sockRecv (GEN_SOCK *pSock, ST_CHAR *dest, + ST_INT maxRx, ST_INT flags, ST_INT *rxCountOut); + +ST_RET _sockTx (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData, ST_INT *numSentOut); + +/* OBSOLETE: For backward compatibility only. New code should use "sockClose".*/ +#define _sockClose sockClose + + + /* -------------------------------------------- */ + /* Misc socket related functions */ + /* -------------------------------------------- */ + +ST_ULONG convertIPAddr (ST_CHAR *ipAddrStr, ST_BOOLEAN useGetHostByName); + + +/************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* GENSOCK_INCLUDED */ + + + + + + diff --git a/include/inc/glberror.h b/include/inc/glberror.h new file mode 100644 index 0000000..2890660 --- /dev/null +++ b/include/inc/glberror.h @@ -0,0 +1,117 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : glberror.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains defines for all the entities that may */ +/* generate error code. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/30/98 DSF 02 Added E_ACTIVEMMS */ +/* 03/18/98 JRB 01 Added E_ASN1_DEC. */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + + +/*** NOTE : These defines are for reference only, and are not used in */ +/* creating the actual error code defines. */ + +#ifndef GBLERROR_INCLUDED +#define GBLERROR_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#define E_SUBSYS 0x0 /* underlying MAP subsystem: */ + /* Board or Board Driver (non-SISCO) */ + +#define E_DRIVER 0x100 /* SISCO MAP Board Driver */ +#define E_DH 0x200 /* SISCO Data Highway Driver */ + +#define EX_DRIVER 0x500 /* SISCO MAP Board Driver Exceptions */ +#define EX_DH 0x600 /* SISCO Data Highway Driver Exceptions */ + +#define E_CASESUIC 0xA00 /* CASE SUIC */ +#define E_ACSESUIC 0xB00 /* ACSE SUIC */ + +#define EX_CASESUIC 0xE00 /* CASE SUIC Exceptions */ +#define EX_ACSESUIC 0xF00 /* ACSE SUIC Exceptions */ + +#define E_TP4 0x1200 /* TP4 errors (see tp4api.h) */ + +#define E_CASESUIC_IS 0x1400 /* CASE SUIC Implementation Specific */ +#define E_ACSESUIC_IS 0x1500 /* ACSE SUIC Implementation Specific */ + +#define EX_CASESUIC_IS 0x1900 /* CASE SUIC Implementation Specific Exceptions */ +#define EX_ACSESUIC_IS 0x1A00 /* ACSE SUIC Implementation Specific Exceptions */ + +#define E_SESSIF 0x1E00 /* Session Interface */ +#define E_CASE 0x1F00 /* SISCO CASE Layer Provider */ + +#define EX_SESSIF 0x2400 /* Session Interface Exceptions */ +#define EX_CASE 0x2500 /* SISCO CASE Layer Provider Exceptions */ + +#define E_SESSIF_IS 0x2800 /* Session IF Implementation Spec */ +#define E_CASE_IS 0x2900 /* SISCO CASE Layer Provider Imp. Spec */ + +#define EX_SESSIF_IS 0x2D00 /* Session IF Implementation Spec Exceptions */ +#define EX_CASE_IS 0x2E00 /* SISCO CASE Layer Provider Imp. Spec Exceptions */ + +#define E_ACSE2 0x3000 /* ACSE2 errors (see acse2usr.h) */ +#define E_COPP 0x3100 /* COPP errors (see copp_usr.h) */ +#define E_COSP 0x3200 /* COSP errors (see cosp_usr.h) */ +#define E_CLNP 0x3400 /* CLNP errors (see clnp_usr.h) */ +#define E_SUBNET 0x3500 /* SUBNET errors (see clnp_usr.h) */ +#define E_ADLC 0x3600 /* ADLC errors (see adlc_usr.h) */ +#define E_RLI_IPC 0x3700 /* RLI_IPC errors (see rli_ipce.h) */ + +#define E_CFG_UTIL 0x4000 /* CFG UTIL codes */ +#define E_HLM 0x4100 /* HLM codes */ +#define E_HLM_MMS 0x4200 /* HLM MMS code */ + +#define E_ACTIVEMMS 0x4A00 /* ActiveMMS codes */ + +#define E_CM 0x5100 /* CM error codes base */ +#define E_CRM 0x5200 /* CRM error codes base */ + +#define E_MMS_GEN 0x6400 /* General provider */ +#define E_MMS_PPI 0X6500 /* Paired Primitive Interface */ +#define E_MMS_RESP 0x6600 /* Request Control Block (resp_err) */ +#define E_MMS_VMI 0x6700 /* Virtual Machine Interface */ +#define E_MMS_EXCPT 0x6800 /* MMS exceptions */ +#define E_LLP_ACSE 0x6900 /* ACSE LLP codes */ +#define E_LLP_CASE 0x6A00 /* CASE LLP codes */ +#define E_LLP_LLC 0x6B00 /* LLC LLP codes */ +#define E_MMS_LITE 0x6A00 /* MMS-LITE codes */ + +#define E_MMS_DS 0x6B00 /* MMS Directory Services */ + +#define E_ASN1_DEC 0x7000 /* ASN.1 decode errors */ + +/* The following define indicates the beginning of a range for */ +/* User-Defined error codes. Users may define error codes above this */ +/* value without conflicting with SISCO defined errors. */ + +#define E_USER_APP 0x7E00 /* User Application errors */ + +/* ******** DO NOT DEFINE ANY ERROR CODES ABOVE "0x7E00" ******** */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/inc/glbopt.h b/include/inc/glbopt.h new file mode 100644 index 0000000..5fc5f58 --- /dev/null +++ b/include/inc/glbopt.h @@ -0,0 +1,43 @@ +#ifndef GLBOPT_INCLUDED +#define GLBOPT_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2002-2002 All Rights Reserved */ +/* */ +/* MODULE NAME : glbopt.h */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Global compiler options to be used by all SISCO source modules. */ +/* This file may be used to enable optional features in */ +/* MMSEASE-LITE. Usually this is easier than adding an */ +/* option to several makefiles. If this file is modified, all */ +/* source code should be recompiled. */ +/* */ +/* This file must be included by "glbtypes.h" so that all SISCO */ +/* source modules will indirectly include it. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/09/05 JRB 09 Delete all defines. This file should now be */ +/* used only for "user" customization. */ +/* 09/22/03 EJV 08 Deleted ACSE_AUTH_ENABLED, S_SEC_ENABLED */ +/* 07/16/03 MDE 07 Removed ACSE_AUTH_ENABLED */ +/* 07/15/03 EJV 06 ACSE_AUTH_ENABLED enabled (ICCP Gateway) */ +/* 04/17/03 JRB 05 Chg MVLU_LEAF_FUN_LOOKUP_ENABLE (defined). */ +/* 12/20/02 JRB 04 Add MVLU_LEAF_FUN_LOOKUP_ENABLE (!defined). */ +/* 12/18/02 JRB 03 Add USE_RT_TYPE_2 (defined by default). */ +/* 10/17/02 ASK 02 Added ACSE_AUTH_ENABLED */ +/* 02/27/02 JRB 01 Created */ +/************************************************************************/ + +/* + * NOTE: Insert "global" defines here. These will be used when compiling + * all SISCO code. + */ + +#endif /* !GLBOPT_INCLUDED */ + diff --git a/include/inc/glbsem.h b/include/inc/glbsem.h new file mode 100644 index 0000000..23933b9 --- /dev/null +++ b/include/inc/glbsem.h @@ -0,0 +1,565 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2008, All Rights Reserved */ +/* */ +/* MODULE NAME : glbsem.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : Multi-thread support defines and prototypes. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/01/08 EJV 61 Ported to Windows Vista. */ +/* 01/15/07 EJV 60 Chg S_LOCK_RESOURCES to S_LOCK_UTIL_RESOURCES*/ +/* 12/15/06 MDE 59 Added S_UNLOCK_CR_AND_RETURN_VAL */ +/* 10/25/06 EJV 58 Ported to HP-UX. */ +/* 07/13/06 EJV 57 Sun: changed the test for POSIX define. */ +/* 03/23/06 EJV 56 Added ( ) in #if a || b || (c && d). */ +/* 01/30/06 GLB 55 Integrated porting changes for VMS */ +/* 08/04/05 EJV 54 Reworked defs for UNIX and LINUX */ +/* 04/12/05 DSF 53 Added refCount member to GS_MUTEX (Windows) */ +/* 01/10/05 DSF 52 Added event member to GS_TIMER */ +/* 01/06/05 DSF 51 Added owner member to GS_MUTEX (Windows) */ +/* 01/14/05 EJV 50 Change removed. */ +/* 06/09/04 EJV 49 Added multithread support for sun. */ +/* 08/23/04 EJV 48 GS_TIMER: rpl elapsed w/ ST_DOUBLE expiration*/ +/* 05/10/04 EJV 47 gs_timer_cleanup: added timeout parameter. */ +/* gs_timer_init: added min_workers, max_workers*/ +/* Added GS_TIMER_WORKER_... defines. */ +/* GS_TIMER: added/moved fields. */ +/* 01/21/04 JRB 46 Add LYNX support. */ +/* 01/21/04 EJV 45 Win Timers: changed to use UNIX code. */ +/* Win impl preserved with _WIN32_timers define */ +/* 12/03/03 EJV 44 Add SD_WIN_VER_2003_AND_LATER, replaced */ +/* SD_WIN_VER_NET with SD_WIN_VER_2003; */ +/* gs_is_win_ver(): chg return ST_RET to ST_INT */ +/* 12/01/03 EJV 43 Added SD_WIN_VER_2K_AND_LATER. */ +/* 11/04/03 JRB 42 Del gs_sleep (use sMsSleep). */ +/* 10/24/03 JRB 41 Move gs_debug_sel to slog.h. */ +/* 09/29/03 JRB 40 Add "linux" support. */ +/* Enable gs_timer* functions for ALL systems. */ +/* 06/20/03 EJV 39 Redesigned mutex sems implementation. */ +/* 06/11/03 EJV 38 gs_named_mutex_xxx, gs_get_named_event_sem */ +/* defined for all systems. */ +/* __alpha: removed gs_xxx_sig and related code.*/ +/* 06/10/03 EJV 37 _WIN32: added gs_named_mutex_xxx functions. */ +/* 06/06/03 JRB 36 S_LOCK_RESOURCES use new gs_util_mutex. */ +/* Use new "Base" macros SLOG_*, SLOGC_*, SLOGH.*/ +/* Del GLBSEM_LOG_ALWAYS*, use SLOGALWAYS*. */ +/* 06/03/03 EJV 35 _WIN32: changed for 64-bit compiler: */ +/* ST_THREAD_HANDLE to uintptr_t */ +/* 04/14/03 JRB 34 Chg mutex macros to use gs_mutex_get/free. */ +/* Chg gs_get/free_sem functions to macros. */ +/* 03/03/24 EJV 33 Added _glbem_err_logstr & _glbem_nerr_logstr;*/ +/* S_LOCK_RESOURCES, S_UNLOCK_RESOURCES call */ +/* now non-logging gs_get_sem & gs_free_sem. */ +/* 02/03/03 EJV 32 _WIN32: added gs_is_win_ver(), SD_WIN_.. defs*/ +/* added gs_get_named_event_sem() */ +/* 01/14/03 EJV 31 Added gs_sleep(). */ +/* 11/01/02 EJV 30 Use SISCO's link list in GS_TIMER. */ +/* 07/29/02 EJV 29 Added gs_timer_get_resolution(), */ +/* GS_TIMER: made more fields common to UNIX,Win*/ +/* Added field delay_start for WIN32. */ +/* 04/09/02 EJV 28 __alpha: moved pthread.h up (cleaner code) */ +/* 02/06/02 EJV 27 _AIX: check for _THREAD_SAFE compiler define */ +/* 10/31/01 EJV 26 _WIN32: added code to call _beginthreadex; */ +/* Added gs_close_thread, gs_pulse_event_sem; */ +/* Added _ERR, _NERR log macros */ +/* UNIX: chg predicate to ST_INT from ST_BOOLEAN*/ +/* UNIX: added manualReset to GS_EVENT_SEM. */ +/* 09/20/01 EJV 25 _WIN32: added pending field to GS_TIMER. */ +/* 08/01/01 JRB 24 Add comment explaining S_LOCK_RES.. */ +/* 07/30/01 EJV 23 Added gs_timer_set_resolution().Chg GS_TIMER.*/ +/* Added ST_THREAD_RET, ST_THREAD_RET_VAL macros*/ +/* and changed gs_start_thread arg. */ +/* 07/25/01 DSF 22 Use <> when including windows.h */ +/* 07/24/01 EJV 21 _WIN32: added gs_timer support. */ +/* 04/04/01 DSF 20 Added gs_set_thread_name for WIN32 */ +/* 03/15/01 EJV 19 UNIX: corrected spelling of REENTRANT. */ +/* 03/07/01 EJV 18 Added slog macros for !DEBUG_SISCO */ +/* 02/19/01 EJV 17 _AIX: eliminated need to call gs_timer_init. */ +/* 02/16/01 EJV 16 AIX: added timer functions gs_times_xxx. */ +/* 01/16/01 EJV 15 Moved GET_THREAD_ID define here from glbsem.c*/ +/* 12/20/00 EJV 14 Ported to AIX. Revised DEC UNIX. */ +/* 12/13/00 EJV 13 Added gs_mutex_... funs for multiple mutex */ +/* semaphores support. Added ST_MUTEX_SEM. */ +/* 12/13/00 EJV 12 Removed USE_MANUAL_RESET_SEM. */ +/* 12/06/00 EJV 11 Changed gs_get_event_sem to accept arg. */ +/* 10/25/00 JRB 10 For _WIN32, define S_MT_SUP.. if _MT defined.*/ +/* 10/06/00 EJV 09 Ported to DEC UNIX (__alpha) pthread funcs. */ +/* Added few GLBSEM_LOG_FLOWn macros. */ +/* Deleted gs_chk_thread_id(), check _REENTRANT */ +/* 01/21/00 JRB 08 Del *sem_fun & *sem_funx function pointers. */ +/* Chg macros to call functions directly. */ +/* S_GS_INSTALL, gs_install, S_GS_INIT obsolete.*/ +/* Chg macros if !S_MT_SUPPORT to call gs_chk...*/ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 08/02/99 JRB 06 Chged "gs_get_event_sem" to "auto-reset" & */ +/* #ifdef'd out "gs_reset_event_sem". */ +/* 10/08/98 MDE 05 Migrated to updated SLOG interface */ +/* 05/05/98 DSF 04 Added SD_TIMEOUT */ +/* 12/11/97 KCR 03 Added gs_wait_mult_event_sem for _WIN32 */ +/* 10/06/97 DSF 02 Modified the macros used by SLOG such that */ +/* they could be used by SLOG in DEBUG_SISCO */ +/* mode */ +/* 08/15/97 MDE 01 Changed default ST_xxx to ST_VOID * */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef GBLSEM_INCLUDED +#define GBLSEM_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "slog.h" +#include "stime.h" +#include "gen_list.h" + +/************************************************************************/ +#define SD_TIMEOUT 2 + +/************************************************************************/ +/* Logging masks and variable */ + +#define GS_LOG_FLOW 0x0001 +#define GS_LOG_ERR 0x0002 +#define GS_LOG_NERR 0x0004 + +extern SD_CONST ST_CHAR *SD_CONST _glbem_flow_logstr; +extern SD_CONST ST_CHAR *SD_CONST _glbem_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _glbem_nerr_logstr; + +/* Mutex types: unnamed (local) can be used to synchronize threads in */ +/* a process, and named (global) can be used to synchronize processes */ +/* and threads within a process. */ +#define GS_MUTEX_UNNAMED 0 +#define GS_MUTEX_NAMED 1 + +/************************************************************************/ +/* Just for convenience ... */ +#define S_UNLOCK_CR_AND_RETURN() {S_UNLOCK_COMMON_RESOURCES(); return;} +#define S_UNLOCK_CR_AND_RETURN_VAL(_rc) {S_UNLOCK_COMMON_RESOURCES(); return (_rc);} + +/************************************************************************/ +/************************************************************************/ +/* WINDOWS 95/98/NT/2000 */ +/* These typedefs, defines, and function prototypes are for use with */ +/* Windows only. */ +/************************************************************************/ + +#if defined(_WIN32) /* VC++, 32-Bit */ + +#include + +/* The VC++ compiler automatically defines (_MT) if Multithread libs */ +/* are selected. The user clearly wants multithread support, so */ +/* S_MT_SUPPORT "MUST" be enabled. */ +/* DEBUG: something similar should be done for any system that supports */ +/* multithreading (e.g. OS2). */ + +#if defined(_MT) && !defined(S_MT_SUPPORT) +#define S_MT_SUPPORT +#endif + +#define ST_THREAD_ID unsigned + +typedef struct gs_mutex_tag + { + ST_INT mutexType; /* GS_MUTEX_UNNAMED (_NAMED) */ + ST_THREAD_ID owner; + ST_THREAD_ID refCount; + union + { + HANDLE hMutex; /* for named mutex & unnamed special */ + CRITICAL_SECTION cs; /* for unnamed mutex */ + } u; + } GS_MUTEX; + +#define GET_THREAD_ID() GetCurrentThreadId() +#define ST_MUTEX_SEM GS_MUTEX +#define ST_EVENT_SEM HANDLE +#if (_MSC_VER >= 1300) +#define ST_THREAD_HANDLE uintptr_t +#else +#define ST_THREAD_HANDLE unsigned long +#endif +#define ST_THREAD_ARG void * +#define ST_THREAD_CALL_CONV __stdcall +#define ST_THREAD_RET unsigned +#define ST_THREAD_RET_VAL 0 + +/* defines to distinguish Windows versions passed to gs_is_win_ver() */ +#define SD_WIN_VER_95_98_Me 1 /* 95, 98, Me */ +#define SD_WIN_VER_NT_AND_LATER 2 /* NT 3.51, NT 4.0 and above */ +#define SD_WIN_VER_2K_AND_LATER 3 /* 2000 and above */ +#define SD_WIN_VER_XP_AND_LATER 4 /* XP and above */ +#define SD_WIN_VER_2003_AND_LATER 5 /* 2003 and above */ +#define SD_WIN_VER_VISTA_AND_LATER 6 /* Vista and above */ + +/* specific Windows version */ +#define SD_WIN_VER_95 10 +#define SD_WIN_VER_98 20 +#define SD_WIN_VER_Me 30 +#define SD_WIN_VER_NT_351 40 +#define SD_WIN_VER_NT_40 50 +#define SD_WIN_VER_2000 60 +#define SD_WIN_VER_XP 70 +#define SD_WIN_VER_2003 80 +#define SD_WIN_VER_VISTA 90 + +#endif /* defined(_WIN32) */ + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* UNIX, Linux, ... */ +/* These typedefs, defines, and function prototypes are for use with */ +/* UNIX, Linux,... only */ +/* Implemented functions are complying with the "POSIX 1003.1c" standard.*/ +/************************************************************************/ + +#if defined(_AIX) || defined(sun) || defined(__hpux) || \ + defined(linux) || defined(__LYNX) || \ + (defined(__alpha) && !defined(__VMS)) || /* Tru64 alpha */ \ + (defined(__ALPHA) && defined(__VMS)) /* OpenVMS alpha */ + +#if (defined(__alpha) && !defined(__VMS)) || /* Tru64 alpha */ \ + (defined(__ALPHA) && defined(__VMS)) /* OpenVMS alpha */ +/* If the code is compiled with -pthread switch then the _REENTRANT */ +/* symbol is defined. This means that there should be a multithread */ +/* support for the code (the S_MT_SUPPORT should be defined). */ + +#if defined(_REENTRANT) && !defined(S_MT_SUPPORT) +#define S_MT_SUPPORT +#endif + +/* According to the POSIX standard this define should be included in */ +/* every application module. The included in */ +/* defines the _POSIX_C_SOURCE to be 199506L. */ + +#define _POSIX_C_SOURCE 199506L +#endif /* defined(__alpha) && !defined(__VMS) */ + +#if defined(_AIX) +/* If the compiler defines _THREAD_SAFE we should build the code */ +/* with multithread support (the S_MT_SUPPORT should be defined). */ + +#if defined(_THREAD_SAFE) && !defined(S_MT_SUPPORT) +#define S_MT_SUPPORT +#endif +#endif /* defined(_AIX) */ + +#if defined(sun) || defined(__hpux) +/* On Solaris 9,10 an application must define _POSIX_C_SOURCE >=199506L */ +/* IN EVERY MODULE OF AN APPLICATION to get the multithread support. */ +/* There is no other compiler define that indicates if a module is */ +/* compiled for multithread support. */ + +#define _POSIX_C_SOURCE 199506L + +#if (_POSIX_C_SOURCE-0 >= 199506L) && !defined(S_MT_SUPPORT) +#define S_MT_SUPPORT +#endif +#endif /* defined(sun) || defined(__hpux) */ + +#if defined(linux) || defined(__LYNX) +/* If the compiler defines _THREAD_SAFE, we should build the code */ +/* with multithread support (the S_MT_SUPPORT should be defined). */ + +#if (defined(_THREAD_SAFE) || defined(_REENTRANT)) && !defined(S_MT_SUPPORT) +#define S_MT_SUPPORT +#endif +#endif /* defined(linux) */ + +#if defined(S_MT_SUPPORT) +#include +typedef struct gs_event_sem_tag + { + ST_INT predicate; /* predicate to change value */ + pthread_mutex_t mutex; /* mutex sem protecting the cond*/ + pthread_cond_t cond; /* condition variable */ + ST_BOOLEAN manualReset; /* type os event semaphore */ + } GS_EVENT_SEM; + +#define GET_THREAD_ID() pthread_self() +#define ST_MUTEX_SEM pthread_mutex_t +#define ST_EVENT_SEM GS_EVENT_SEM * +#define ST_THREAD_ID pthread_t +#define ST_THREAD_HANDLE pthread_t +#define ST_THREAD_ARG void * +#define ST_THREAD_CALL_CONV +#define ST_THREAD_RET void * +#define ST_THREAD_RET_VAL NULL +#endif /* defined(S_MT_SUPPORT) */ + +#endif /* defined UNIX, linux,... */ + + +/************************************************************************/ +/************************************************************************/ +/* If no system has defined the required types, do so now. This allows */ +/* the source to include variables of these types w/o errors. */ + +#if !defined (ST_EVENT_SEM) + +#define GET_THREAD_ID() (ST_THREAD_ID) 0xFFFFFFFF +#define ST_MUTEX_SEM ST_VOID * +#define ST_EVENT_SEM ST_VOID * +#define ST_THREAD_ID ST_VOID * +#define ST_THREAD_HANDLE ST_VOID * +#define ST_THREAD_ARG ST_VOID * +#define ST_THREAD_CALL_CONV +#define ST_THREAD_RET ST_VOID +#define ST_THREAD_RET_VAL + +#endif /* !defined (ST_EVENT_SEM) */ + +/************************************************************************/ +/************************************************************************/ +/* Global functions */ + +/* SISCO Single MUTEX functions */ +ST_RET gs_init (ST_VOID); +ST_VOID gs_log_sem_state (ST_VOID); +ST_VOID gs_get_semx (SD_CONST ST_CHAR *srcFile, ST_INT srcLineNum); +ST_VOID gs_free_semx (SD_CONST ST_CHAR *srcFile, ST_INT srcLineNum); + +/* User's MUTEX Semaphore functions */ +ST_RET gs_mutex_create (ST_MUTEX_SEM *ms); +ST_RET gs_named_mutex_create (ST_MUTEX_SEM *ms, ST_CHAR *name); +ST_RET gs_mutex_get_tm (ST_MUTEX_SEM *ms, ST_LONG timeout); +#define gs_mutex_get(ms) gs_mutex_get_tm(ms, -1L) +ST_RET gs_mutex_free (ST_MUTEX_SEM *ms); +ST_RET gs_mutex_destroy (ST_MUTEX_SEM *ms); + +/* Event Semaphores */ +ST_EVENT_SEM gs_get_event_sem (ST_BOOLEAN manualReset); +ST_EVENT_SEM gs_get_named_event_sem (ST_CHAR *name, ST_BOOLEAN manualReset); +ST_RET gs_wait_event_sem (ST_EVENT_SEM es, ST_LONG timeout); +ST_RET gs_wait_mult_event_sem (ST_INT numEvents, ST_EVENT_SEM *esTable, + ST_BOOLEAN *activity, ST_LONG timeout); +ST_VOID gs_signal_event_sem (ST_EVENT_SEM es); +ST_VOID gs_pulse_event_sem (ST_EVENT_SEM es); +ST_VOID gs_reset_event_sem (ST_EVENT_SEM es); +ST_VOID gs_free_event_sem (ST_EVENT_SEM es); + +/* Thread */ +ST_RET gs_start_thread (ST_THREAD_RET (ST_THREAD_CALL_CONV *threadFunc) (ST_THREAD_ARG), + ST_THREAD_ARG threadArg, + ST_THREAD_HANDLE *threadHandleOut, + ST_THREAD_ID *threadIdOut); +ST_RET gs_wait_thread (ST_THREAD_HANDLE threadHandle, + ST_THREAD_ID threadId, ST_LONG timeout); +ST_RET gs_close_thread (ST_THREAD_HANDLE threadHandle); + +#if defined (_WIN32) +ST_VOID gs_set_thread_name (ST_THREAD_ID threadId, ST_CHAR *pThreadName); +#endif + +/* Misc. functions */ +#if defined (_WIN32) +ST_INT gs_is_win_ver (ST_UINT ver); +#endif + +/************************************************************************/ +/* These are the macro's used to call the glbsem get/free functions. */ +/* Note that the behavior depends on the defines used at compile time. */ + +#if defined(S_MT_SUPPORT) /* If code is to have MT support */ + +#if defined(DEBUG_SISCO) /* MT support, debug */ + +#define S_LOCK_COMMON_RESOURCES() gs_get_semx(thisFileName, __LINE__) +#define S_UNLOCK_COMMON_RESOURCES() gs_free_semx(thisFileName, __LINE__) + +/* NOTE: because S_LOCK_UTIL_RESOURCES & S_UNLOCK_UTIL_RESOURCES are called from SLOG, */ +/* the gs_mutex_get and gs_mutex_free (code handling unnamed mutexes) */ +/* should not be logging to avoid infinite loop (i.e. lock funct calling */ +/* log funct which calls lock funct again). */ +#define S_LOCK_UTIL_RESOURCES() gs_mutex_get (&gs_util_mutex) +#define S_UNLOCK_UTIL_RESOURCES() gs_mutex_free (&gs_util_mutex) + +#else /* MT support, no debug */ + +#define S_LOCK_COMMON_RESOURCES() gs_mutex_get (&gs_glb_mutex) +#define S_UNLOCK_COMMON_RESOURCES() gs_mutex_free (&gs_glb_mutex) + +#define S_LOCK_UTIL_RESOURCES() gs_mutex_get (&gs_util_mutex) +#define S_UNLOCK_UTIL_RESOURCES() gs_mutex_free (&gs_util_mutex) + +#endif + +#else /* No MT support is compiled in */ +#define S_LOCK_COMMON_RESOURCES() +#define S_UNLOCK_COMMON_RESOURCES() +#define S_LOCK_UTIL_RESOURCES() +#define S_UNLOCK_UTIL_RESOURCES() +#endif + +/* FOR BACKWARD COMPATIBILITY ONLY. Old code may be calling gs_get_sem, */ +/* gs_free_sem directly. These calls should be replaced with S_LOCK_.. */ +#define gs_get_sem() S_LOCK_UTIL_RESOURCES() +#define gs_free_sem() S_UNLOCK_UTIL_RESOURCES() + +/************************************************************************/ + +#define MAX_SEM_NEST_TRACK 20 +extern ST_MUTEX_SEM gs_glb_mutex; /* the global mutex semaphore */ +extern ST_MUTEX_SEM gs_util_mutex;/* UTILITY MUTEX semaphore: for "low-level"*/ + /* util functs (slog,mem_chk,stime,etc.)*/ +extern ST_BOOLEAN gs_already_inited; +extern ST_UINT gs_track; /* This variable when set to value >0 */ + /* during an application startup allows */ + /* tracking of MUTEX or EVENT sem. */ +extern ST_INT gs_currSemOwnerIndex; +extern ST_CHAR gs_currSemOwnerFile[MAX_SEM_NEST_TRACK][SLOG_MAX_FNAME+1]; +extern ST_INT gs_currSemOwnerLine[MAX_SEM_NEST_TRACK]; + +extern ST_DOUBLE gs_hwMutexTime; +extern ST_DOUBLE gs_hwEventTime; + + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + /* */ + /* Timer functions */ + /* */ + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + + /* Note: On AIX the real-time support is not implemented. */ + /* Functions such as timer_create, sleep, or nanosleep are*/ + /* not available (in AIX version 4.3.2 or 4.3.3). */ + /* This implementation of timers is using the GLBSEM */ + /* gs_wait_event_sem function implemented with phtreads */ + /* to support the timer functionality. */ + +/* The timer support will be initialized automatically when the function*/ +/* gs_timer_start is called for the first time. */ + +/* If the timer is of type SD_TIMER_ONESHOT then the timer resources */ +/* will be automatically deleted after the first time the timer is */ +/* serviced. For the SD_TIMER_PERIODIC timer the user needs to call */ +/* the gs_timer_end function to stop the timer and release resources. */ + +/* Before application exits the function gs_timer_cleanup should be */ +/* called to cleanup all resources associates with timers. */ + +/* NOTE: Since Windows is limiting number of timers to 16 per process */ +/* we have to use the UNIX timer implementation on Windows. */ +/* If the _WIN32_timers is defined then the Windows implementation*/ +/* of timers will be in effect for Windows. */ +#if defined _WIN32 +/* #define _WIN32_timers */ +#endif + +#define SD_TIMER_ONESHOT 1 +#define SD_TIMER_PERIODIC 2 + +#define GS_TIMER_WORKER_MIN 4 /* def min number of timer worker threads */ +#define GS_TIMER_WORKER_MAX 10 /* def max number of timer worker threads */ + +struct gs_timer_tag; /* forward definition */ + +typedef struct gs_timer_tag + { + DBL_LNK link; /* link list */ +#if defined (_WIN32_timers) + UINT timerID; /* timer id returned from timeSetEvent */ + ST_DOUBLE delay_start; /* time when delete timer delay started */ +#endif + ST_BOOLEAN terminate; /* set if timer should be terminated */ + ST_BOOLEAN pending; /* shows if timer processing is already pending */ + ST_ULONG interval; /* milliseconds, time between servicing */ + ST_DOUBLE expiration; /* milliseconds, next expiration time */ + ST_UINT type; /* timer type: oneshot or periodic */ + ST_VOID (*callback_fun)(ST_VOID *); + ST_VOID *arg; /* argument for the callback_fun. */ + ST_EVENT_SEM event; /* user can set this if it wants to be notified */ + /* when the timer object is destroyed */ + } GS_TIMER; + +/* The timer resolution could be set to the lowest value required by an */ +/* application before calling the gs_timer_start function. */ +/* On Windows system if the timer resolution is changed while the */ +/* application is running, only timers started afterwards will be */ +/* affected. On UNIX system all timers will be affected. */ + +ST_RET gs_timer_init (ST_UINT min_workers, ST_UINT max_workers); +ST_RET gs_timer_set_resolution (ST_ULONG timer_resolution); +ST_ULONG gs_timer_get_resolution (ST_VOID); + +GS_TIMER *gs_timer_start (ST_UINT type, + ST_ULONG interval, + ST_VOID (*callback_fun)(ST_VOID *), + ST_VOID *arg); +ST_RET gs_timer_end (GS_TIMER *timer_id); +ST_RET gs_timer_cleanup (ST_LONG timeout); + + +/************************************************************************/ +/* Logging macro's used internally by glbsem.c */ + +#define GLBSEM_LOG_ERR0(a) \ + SLOG_0 (gs_debug_sel & GS_LOG_ERR,_glbem_err_logstr,a) +#define GLBSEM_LOG_ERR1(a,b) \ + SLOG_1 (gs_debug_sel & GS_LOG_ERR,_glbem_err_logstr,a,b) +#define GLBSEM_LOG_ERR2(a,b,c) \ + SLOG_2 (gs_debug_sel & GS_LOG_ERR,_glbem_err_logstr,a,b,c) +#define GLBSEM_LOG_ERR3(a,b,c,d) \ + SLOG_3 (gs_debug_sel & GS_LOG_ERR,_glbem_err_logstr,a,b,c,d) + +#define GLBSEM_LOG_CERR0(a) \ + SLOGC_0 (gs_debug_sel & GS_LOG_ERR,a) +#define GLBSEM_LOG_CERR1(a,b) \ + SLOGC_1 (gs_debug_sel & GS_LOG_ERR,a,b) +#define GLBSEM_LOG_CERR2(a,b,c) \ + SLOGC_2 (gs_debug_sel & GS_LOG_ERR,a,b,c) +#define GLBSEM_LOG_CERR3(a,b,c,d) \ + SLOGC_3 (gs_debug_sel & GS_LOG_ERR,a,b,c,d) + +#define GLBSEM_LOG_NERR0(a) \ + SLOG_0 (gs_debug_sel & GS_LOG_NERR,_glbem_nerr_logstr,a) +#define GLBSEM_LOG_NERR1(a,b) \ + SLOG_1 (gs_debug_sel & GS_LOG_NERR,_glbem_nerr_logstr,a,b) +#define GLBSEM_LOG_NERR2(a,b,c) \ + SLOG_2 (gs_debug_sel & GS_LOG_NERR,_glbem_nerr_logstr,a,b,c) +#define GLBSEM_LOG_NERR3(a,b,c,d) \ + SLOG_3 (gs_debug_sel & GS_LOG_NERR,_glbem_nerr_logstr,a,b,c,d) + +#define GLBSEM_LOG_FLOW0(a) \ + SLOG_0 (gs_debug_sel & GS_LOG_FLOW,_glbem_flow_logstr,a) +#define GLBSEM_LOG_FLOW1(a,b) \ + SLOG_1 (gs_debug_sel & GS_LOG_FLOW,_glbem_flow_logstr,a,b) +#define GLBSEM_LOG_FLOW2(a,b,c) \ + SLOG_2 (gs_debug_sel & GS_LOG_FLOW,_glbem_flow_logstr,a,b,c) +#define GLBSEM_LOG_FLOW3(a,b,c,d) \ + SLOG_3 (gs_debug_sel & GS_LOG_FLOW,_glbem_flow_logstr,a,b,c,d) + +#define GLBSEM_LOG_CFLOW0(a) \ + SLOGC_0 (gs_debug_sel & GS_LOG_FLOW,a) +#define GLBSEM_LOG_CFLOW1(a,b) \ + SLOGC_1 (gs_debug_sel & GS_LOG_FLOW,a,b) +#define GLBSEM_LOG_CFLOW2(a,b,c) \ + SLOGC_2 (gs_debug_sel & GS_LOG_FLOW,a,b,c) +#define GLBSEM_LOG_CFLOW3(a,b,c,d) \ + SLOGC_3 (gs_debug_sel & GS_LOG_FLOW,a,b,c,d) + +/************************************************************************/ +#define gs_install() /* OBSOLETE: for backward compat. only */ +#define S_GS_INSTALL() /* OBSOLETE: for backward compat. only. */ +#define S_GS_INIT() /* OBSOLETE: for backward compat. only. */ + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef GBLSEM_INCLUDED */ + diff --git a/include/inc/glbtypes.h b/include/inc/glbtypes.h new file mode 100644 index 0000000..97e2156 --- /dev/null +++ b/include/inc/glbtypes.h @@ -0,0 +1,691 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2006, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : glbtypes.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/18/08 JRB 30 Use endian.h to set SD_BYTE_ORDER on linux. */ +/* 01/27/06 EJV 29 _WIN32: chg ST_UINT64 to unsigned __int64. */ +/* 08/01/05 JRB 28 Disable SD_CONST for ALL platforms. */ +/* 02/12/04 JRB 27 Disable ST_CONST for LINUX. */ +/* 01/08/04 EJV 26 Checked SD_BIG_ENDIAN on sun, rem pragma msg.*/ +/* 12/09/03 JRB 25 Add LYNX, don't def ST_CONST for LYNX. */ +/* 02/19/03 JRB 24 Define SD_BYTE_ORDER for each system. */ +/* 02/19/03 JRB 23 Del VAX-VMS & PSOS code. */ +/* 02/17/03 CRM 22 Added "defined(linux)" code. */ +/* 02/17/03 JRB 21 Del unsupported __IC86__ */ +/* Del obsolete DEBUG_MMS, DEBUG_SUIC, etc. */ +/* Del NEW_SYSTEM.. defines (not very useful). */ +/* 02/27/02 JRB 20 Include compiler option file "glbopt.h". */ +/* 10/05/01 EJV 19 sun supports ST_INT64 (long long) */ +/* 01/02/01 EJV 18 disabled SD_CONST macro for _AIX */ +/* enabled SD_CONST macro for QNX */ +/* 06/16/00 JRB 17 Define "*INT64" only if INT64_SUPPORT defined*/ +/* 03/13/00 MDE 16 disabled SD_CONST macro for WIN32 */ +/* 09/24/99 JRB 15 disabled SD_CONST macro for QNX */ +/* 09/13/99 MDE 14 Added SD_CONST modifiers */ +/* 04/14/99 MDE 13 Changed SYSTEM_SEL defines */ +/* 01/19/99 EJV 12 AIX: Added 64 bit integer support */ +/* 08/26/98 EJV 11 Deleted CPU_SEL and all releated defines. */ +/* __hpux supports 64-bit integers. */ +/* Eliminated spaces at the end of lines. */ +/* 02/09/98 RKR 10 Removed PRODUCT_ONLY_VMS_ALPHA */ +/* 01/23/98 EJV 09 Digital UNIX: revised. */ +/* 12/11/97 JRB 08 Cleaned up PSOS ifdefs. Define PSOS_SYSTEM */ +/* to compile. Use new SYSTEM_SEL=SYS_PSOS. */ +/* 12/11/97 JRB 07 Deleted _MRI ifdef (for Modicon/MICROTEC) */ +/* Deleted EMBEDDED_6800 SYSTEM_SEL. */ +/* 10/27/97 EJV 06 AIX: revised types, deleted pragma message() */ +/* 09/23/97 JRB 05 QNX: pragma stops unused symbol warnings. */ +/* 08/16/97 EJV 04 For QNX corrected ST_INT16, ST_UINT16. */ +/* 08/15/97 JRB 03 Use MOTO_68000 consistently. */ +/* 08/13/97 EJV 02 Changed #if (A && B) statements to avoid */ +/* warning if A or B has not been defined. */ +/* 06/20/97 MDE 01 Added 64 bit integer support for 95/NT */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef GBLTYPES_INCLUDED +#define GBLTYPES_INCLUDED + +#include "glbopt.h" /* Global compiler options. */ + +#ifdef __cplusplus +extern "C" { +#endif +void logprint(char * fmt,...); +/* +#define VXWORKS + +#define DEBUG_SISCO +#define MOSI +#define LEAN_T +#define MVL_UCA +#define MMS_LITE +#define TP0_ENABLED*/ +//lnk20260611 +#if defined(_WIN32) || defined(__WIN32__) +#ifndef WIN32 +#define WIN32 +#endif +#endif + + + + +/**/ + + + + + + + + + + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* General purpose defines, same for all platforms */ + +#define SD_TRUE 1 +#define SD_FALSE 0 +#define SD_SUCCESS 0 +#define SD_FAILURE 1 +#define SD_BIG_ENDIAN 0 +#define SD_LITTLE_ENDIAN 1 + +/* Define used for 'const' modifier */ +/* DEBUG: someday if all code is changed to consistently use SD_CONST, */ +/* this define may be replaced with the following: */ +/* #define SD_CONST const */ +#define SD_CONST + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +/* SYSTEM_SEL defines - bit masked */ +#define SYSTEM_SEL_MSOFT 0x0001 +#define SYSTEM_SEL_OS2 0x0008 +#define SYSTEM_SEL_OPEN_VMS 0x0010 +#define SYSTEM_SEL_SYS_5 0x0020 +#define SYSTEM_SEL_SYS_BSD 0x0040 +#define SYSTEM_SEL_QNX_C86 0x0100 +#define SYSTEM_SEL_SYSVXWORKS 0x0800 +#define SYSTEM_SEL_SYS_QNX4 0x1000 + +/* For backwards compatibility only, do not use. Will be deleted soon. */ +#if !defined(MSOFT) +#define MSOFT SYSTEM_SEL_MSOFT +#endif +#if !defined(OS2) +#define OS2 SYSTEM_SEL_OS2 +#endif +#if !defined(OPEN_VMS) +#define OPEN_VMS SYSTEM_SEL_OPEN_VMS +#endif +#if !defined(SYS_5) +#define SYS_5 SYSTEM_SEL_SYS_5 +#endif +#if !defined(SYS_BSD) +#define SYS_BSD SYSTEM_SEL_SYS_BSD +#endif +#if !defined(QNX_C86) +#define QNX_C86 SYSTEM_SEL_QNX_C86 +#endif +#if !defined(SYSVXWORKS) +#define SYSVXWORKS SYSTEM_SEL_SYSVXWORKS +#endif +#if !defined(SYS_QNX4) +#define SYS_QNX4 SYSTEM_SEL_SYS_QNX4 +#endif + +/************************************************************************/ +/************************************************************************/ +/* SYSTEM and CPU select defines. These are based on built in compiler */ +/* defines which allow automatic detection of the compiler. */ +/************************************************************************/ + +/************************************************************************/ +/* MS-DOS and WINDOWS */ +/************************************************************************/ +#if defined(MSDOS) || defined(__MSDOS__) /* Microsoft or Borland */ + +#if !defined(_WINDOWS) && !defined(_Windows) +#define PLAIN_DOS /* straight and pure DOS */ +#endif + +#define SD_BYTE_ORDER SD_LITTLE_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_MSOFT +#define SD_END_STRUCT + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long + +/* SD_TRUE or SD_FALSE only */ +#define ST_BOOLEAN unsigned char + + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* WINDOWS 95/NT */ +/************************************************************************/ +#if defined(_WIN32) /* VC++, 32-Bit */ + +#define SD_BYTE_ORDER SD_LITTLE_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_MSOFT +#define SD_END_STRUCT + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_INT64 __int64 +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_UINT64 unsigned __int64 +#define ST_BOOLEAN unsigned char + +/* This define shows that we really have support for 64 bit integers */ +#define INT64_SUPPORT + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* OS/2 - IBM C/SET2 and C/SET++ */ +/************************************************************************/ +#if defined(__OS2__) /* IBM C Set/2 */ + +#pragma message("Please look over the OS/2 system detect & defines") + +#pragma data_seg(alldata) + +#define SD_BYTE_ORDER SD_LITTLE_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_OS2 +#define SD_END_STRUCT + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_BOOLEAN unsigned char + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* SUN */ +/************************************************************************/ +#if defined(sun) /* SUN */ + +#define SD_BYTE_ORDER SD_BIG_ENDIAN +#define SYSTEM_SEL SYS_5 +#define SD_END_STRUCT long end_of; /* force struct to quad word allign */ + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_INT64 signed long long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_UINT64 unsigned long long +#define ST_BOOLEAN unsigned char + +/* This define shows that we really have support for 64 bit integers */ +#define INT64_SUPPORT + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* AIX */ +/************************************************************************/ +#if defined(_AIX) /* AIX */ + +#define SD_BYTE_ORDER SD_BIG_ENDIAN +#define SYSTEM_SEL SYS_5 +#define SD_END_STRUCT long end_of; /* force struct to quad word allign */ + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_INT64 signed long long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_UINT64 unsigned long long +#define ST_BOOLEAN unsigned char + +/* This define shows that we really have support for 64 bit integers */ +#define INT64_SUPPORT + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* OpenVMS AXP */ +/************************************************************************/ +#if defined(__ALPHA) && defined(__VMS) /* OpenVMS AXP uses DECC*/ + +#define SD_BYTE_ORDER SD_LITTLE_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_OPEN_VMS +#define SD_END_STRUCT long end_of; + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_BOOLEAN unsigned char + + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* Digital UNIX */ +/************************************************************************/ + +#if defined(__alpha) && !defined(__VMS) + +#define SD_BYTE_ORDER SD_LITTLE_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_SYS_5 +#define SD_END_STRUCT long end_of; + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed int +#define ST_INT64 signed long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned int +#define ST_UINT64 unsigned long +#define ST_BOOLEAN unsigned char + +/* This define shows that we really have support for 64 bit integers */ +#define INT64_SUPPORT + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* ECOS */ +/************************************************************************/ + +#if defined(__ECOS) + +#define SD_BYTE_ORDER SD_BIG_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_SYSVXWORKS +#define SD_END_STRUCT + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed int +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned int +#define ST_BOOLEAN unsigned char + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif /* __ECOS */ + +/************************************************************************/ +/* VXWORKS - VXWORKS on Motorola 680x0 processor */ +/************************************************************************/ + +#if defined(VXWORKS) + +#define SD_BYTE_ORDER SD_BIG_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_SYSVXWORKS +#define SD_END_STRUCT + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_BOOLEAN unsigned char + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* QNX */ +/************************************************************************/ +#ifdef __QNX__ /* This should be defined automatically by compiler. */ + +#pragma off (unreferenced) /* don't warn about unused symbols. */ + +#define SD_BYTE_ORDER SD_LITTLE_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_SYS_QNX4 +#define SD_END_STRUCT + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_BOOLEAN unsigned char + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* HP-UX */ +/************************************************************************/ +#if defined(__hpux) /* HP-UX */ + +#define SD_BYTE_ORDER SD_BIG_ENDIAN +#define SYSTEM_SEL SYS_5 +#define SD_END_STRUCT long end_of; /* force struct to quad word allign */ + + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_INT64 signed long long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_UINT64 unsigned long long +#define ST_BOOLEAN unsigned char + +/* This define shows that we really have support for 64 bit integers */ +#define INT64_SUPPORT + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* LINUX SYSTEM */ +/* OR LYNXOS SYSTEM (same types) */ +/************************************************************************/ +#if defined(linux) || defined(__LYNX) + +/* NOTE: this may also work for setting SD_BYTE_ORDER on other */ +/* platforms that use the GNU C Library */ +#include +#if (__BYTE_ORDER ==__LITTLE_ENDIAN) + #define SD_BYTE_ORDER SD_LITTLE_ENDIAN +#elif (__BYTE_ORDER ==__BIG_ENDIAN) + #define SD_BYTE_ORDER SD_BIG_ENDIAN +#else + #error unsupported byte order +#endif + +#define SD_END_STRUCT + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +//renxiaobao +#define ST_INT32 signed int +//#define ST_INT32 signed long +#define ST_INT64 signed long long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +//renxiaobao +#define ST_UINT32 unsigned int +//#define ST_UINT32 unsigned long +#define ST_UINT64 unsigned long +//#define ST_UINT64 unsigned long long +#define ST_BOOLEAN unsigned char + +/* This define shows that we really have support for 64 bit integers */ +#define INT64_SUPPORT + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif /* linux */ + +/************************************************************************/ +/************************************************************************/ +/* Make sure that this module has identified the target system */ + +#if !defined(_SISCOTYPES_DEFINED) +#error Warning: System not correctly identified by glbtypes.h +#endif + +#if !defined(SD_BYTE_ORDER) +#error SD_BYTE_ORDER not defined +#endif + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + + +#endif /* #ifndef GBLTYPES_INCLUDED */ diff --git a/include/inc/gse_mgmt.h b/include/inc/gse_mgmt.h new file mode 100644 index 0000000..4c6c97f --- /dev/null +++ b/include/inc/gse_mgmt.h @@ -0,0 +1,252 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999-2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : gse_mgmt.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/03/06 CRM 01 Created */ +/************************************************************************/ + +#ifndef GSE_MGMT_INCLUDED +#define GSE_MGMT_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acse2usr.h" +#include "asn1r.h" +#include "ethertyp.h" + + + +#define MAX_GSE_MGMT_ENCODE_BUF 1540 +#define MAX_VSTRING_BUF 65 +#define NUM_ELEMENTS 500 + +#define GET_GO_REF_REQ_TAG 1 +#define GET_GOOSE_ELE_NUM_REQ_TAG 2 +#define GET_GS_REF_REQ_TAG 3 +#define GET_GSSE_DATA_OFF_REQ_TAG 4 + +#define GET_GO_REF_RSP_TAG 1 +#define GET_GOOSE_ELE_NUM_RSP_TAG 2 +#define GET_GS_REF_RSP_TAG 3 +#define GET_GSSE_DATA_OFF_RSP_TAG 4 + +#define RSP_OTHER 0 +#define RSP_NOT_FOUND 1 + +#define GLB_ERROR 2 +#define GLB_ERR_OTHER 0 +#define GLB_ERR_UNKNOWN_CTRL_BLK 1 +#define GLB_ERR_RSP_TOO_LARGE 2 +#define GLB_ERR_CTRL_BLK_CONFIG_ERR 3 + + +#define GSE_MSG_TYPE_GO_REF_REQ 1 +#define GSE_MSG_TYPE_GOOSE_ELE_REQ 2 +#define GSE_MSG_TYPE_GS_REF_REQ 3 +#define GSE_MSG_TYPE_GSSE_DATA_OFF_REQ 4 + +#define GSE_MSG_TYPE_GLOBAL_ERROR_RSP 10 +#define GSE_MSG_TYPE_GO_REF_RSP 11 +#define GSE_MSG_TYPE_GOOSE_ELE_RSP 12 +#define GSE_MSG_TYPE_GS_REF_RSP 13 +#define GSE_MSG_TYPE_GSSE_DATA_OFF_RSP 14 + + + +/************************************************************************/ +/* BEGIN GSE MGMT DEFINITIONS */ +/************************************************************************/ +typedef struct + { + ST_UINT32 stateID; + ST_CHAR ident[MAX_VSTRING_BUF+1]; + ST_INT numIntegers; + ST_UINT32 *offset; + } GSE_REF_REQ; + +typedef struct + { + ST_UINT32 stateID; + ST_CHAR ident[MAX_VSTRING_BUF+1]; + ST_INT numVStrings; + ST_CHAR **references; + } GSE_OFFSET_REQ; + +/* Global error response sturcture */ +typedef struct + { + ST_UINT32 stateID; + ST_CHAR ident[MAX_VSTRING_BUF+1]; + ST_UINT32 confRev; + ST_UINT32 glbError; + } GSE_GLB_ERR_RSP; + + +/* Offset response sturctures */ +typedef struct + { + ST_INT rsp_type; + ST_UINT32 offset; + ST_UINT32 error; + } OFFSET_REQ_RESULTS; + +typedef struct + { + ST_UINT32 stateID; + ST_CHAR ident[MAX_VSTRING_BUF+1]; + ST_UINT32 confRev; + ST_CHAR datSet[MAX_VSTRING_BUF+1]; + ST_INT numResults; + OFFSET_REQ_RESULTS *result; + } GSE_OFFSET_RSP; + + +/* Reference response sturctures */ +typedef struct + { + ST_INT rsp_type; + ST_CHAR reference[MAX_VSTRING_BUF+1]; + ST_UINT32 error; + } REF_REQ_RESULTS; + + +typedef struct + { + ST_UINT32 stateID; + ST_CHAR ident[MAX_VSTRING_BUF+1]; + ST_UINT32 confRev; + ST_CHAR datSet[MAX_VSTRING_BUF+1]; + ST_INT numResults; + REF_REQ_RESULTS *result; + } GSE_REF_RSP; + + + +/************************************************************************/ +/* STRUCTURE DEFINITIONS */ +/************************************************************************/ + +typedef struct + { + ST_UINT32 stateID; + ST_INT msgType; + + union GSE_MSG + { + GSE_REF_REQ refReq; + GSE_OFFSET_REQ offReq; + GSE_OFFSET_RSP offRsp; + GSE_REF_RSP refRsp; + GSE_GLB_ERR_RSP glbErrRsp; + } msg; + } GSE_MGMT_MSG; + + + + +ST_UCHAR *getGoRefReqEncode (GSE_REF_REQ *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ +ST_UCHAR *getGOOSEEleNumReqEncode (GSE_OFFSET_REQ *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ +ST_UCHAR *getGsRefReqEncode (GSE_REF_REQ *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ +ST_UCHAR *getGSSEDataOffsetReqEncode (GSE_OFFSET_REQ *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ + + + +ST_UCHAR *gse_mgmt_NotSupported (ST_VOID); +ST_UCHAR *getGlbErrorRspEncode (GSE_GLB_ERR_RSP *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ +ST_UCHAR *getGoRefRspEncode (GSE_REF_RSP *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ +ST_UCHAR *getGOOSEEleNumRspEncode (GSE_OFFSET_RSP *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ +ST_UCHAR *getGsRefRspEncode (GSE_REF_RSP *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ +ST_UCHAR *getGSSEDataOffsetRspEncode (GSE_OFFSET_RSP *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ + + + +/************************************************************************/ +/* Functions for receiving GSE_MGMT messages. */ +/* Decode GSE_MGMT message and fill in GSE_MGMT_MSG struct. */ +/************************************************************************/ +GSE_MGMT_MSG *gse_mgmt_msg_decode ( + SN_UNITDATA *sn_req, /* message to decode */ + ETYPE_INFO *etypeInfo); /* where to store decoded Ethertype info*/ + +/* Must be called to free structure returned from gse_mgmt_msg_decode. */ +ST_VOID gse_mgmt_msg_free (GSE_MGMT_MSG *gseMgmtMsg); + + +/************************************************************************/ +/* END GSE MGMT DEFINITIONS */ +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* GSE_MGMT_INCLUDED */ diff --git a/include/inc/gvaldefs.h b/include/inc/gvaldefs.h new file mode 100644 index 0000000..cc8e9cb --- /dev/null +++ b/include/inc/gvaldefs.h @@ -0,0 +1,48 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986-1997 All Rights Reserved */ +/* */ +/* MODULE NAME : gvaldefs.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This include file contains common declarations used throughout */ +/* the user application code. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef GVALDEFS_INCLUDED +#define GVALDEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#define STRGETSTRINGSIZE 256 + +ST_BOOLEAN floatget (ST_FLOAT *dest); +ST_BOOLEAN doubleget( ST_DOUBLE *dest); +ST_BOOLEAN intget (ST_INT *dest); /* int get function */ +ST_BOOLEAN hexget (ST_INT *dest); /* int get function */ +ST_BOOLEAN longget (ST_LONG *dest); /* long int get function */ +ST_BOOLEAN longhexget (ST_LONG *dest); /* long int get function */ +ST_BOOLEAN strget (ST_CHAR *dest); /* string get function */ +ST_INT input_hex (ST_UCHAR *dest_str, ST_INT maxbytes); + +ST_VOID entry1 (ST_INT maxlen, ST_CHAR *str_ptr); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/inc/lean_a.h b/include/inc/lean_a.h new file mode 100644 index 0000000..d7ab0ee --- /dev/null +++ b/include/inc/lean_a.h @@ -0,0 +1,145 @@ +#ifndef LEAN_A_H +#define LEAN_A_H +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996 - 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : lean_a.h */ +/* PRODUCT(S) : Lean-T Stack SUIC */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/13/05 EJV 11 MMSEASE_MOSI: added extern domsock_listener */ +/* 03/15/05 EJV 10 MMSEASE_MOSI: set MAX_SUIC_CHAN to 1000 */ +/* Added mms_event_fd. */ +/* 02/08/02 JRB 09 Move osicfgx prototype to mvl_acse.h. */ +/* 11/27/00 JRB 08 Add osicfgx proto. */ +/* 12/10/97 JRB 07 Add MMSEventName and hMMSEvent for OS2. */ +/* 08/14/97 JRB 06 #include "acse2usr.h" and use PRES_ADDR in */ +/* DIB_ENTRY. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 05/02/97 JRB 05 Del MAX_?_SEL defines. Use suicacse.h defs. */ +/* 05/01/97 JRB 04 Move MAX_SUIC_CHAN define to here. */ +/* 01/02/96 JRB 03 Add MMSEventName and hMMSEvent. */ +/* 10/04/96 JRB 02 #ifdef MCGW, add adlcAddr to DIB_ENTRY. */ +/* Add *_clt7 function prototypes. */ +/* 05/29/96 MDE 01 Changed DIB_ENTRY - name is now a pointer */ +/* 03/27/96 MDE Created */ +/************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (_WIN32) +#include +#endif /* _WIN32 */ + +#if defined (__OS2__) +#define INCL_BASE +#include +#endif /* __OS2__ */ + +#include "asn1defs.h" /* for MMS_OBJ_ID definition */ +#include "acse2usr.h" /* for PRES_ADDR definition */ + +#if defined(MMSEASE_MOSI) +#define MAX_SUIC_CHAN 1024 /* number of channels <=TP_MAX_NUM_CONNS*/ +#include "gensock2.h" /* defines SOCKET */ +extern SOCKET mms_event_fd; /* wakeup socket, indicating TCP Events */ +extern SOCKET domsock_listener; /* domain socket connected to the */ + /* RFC1006_LISTENER task. */ +#else +#define MAX_SUIC_CHAN 256 /* number of channels */ +#endif + +/************************************************************************/ +/* The structure below is used to save Directory and other information */ +/* about local and remote AE's read in from SUIC.DIB */ +/************************************************************************/ + +#define DIB_ENTRY_DEFINED + +struct dib_entry +{ + ST_LONG reserved; /* reserved field */ + ST_CHAR *name; /* user-defined ASCII character string */ + ST_CHAR local; /* local or remote name */ + ST_UCHAR AP_title_pres; /* present flag */ + MMS_OBJ_ID AP_title; /* AP title */ + ST_UCHAR AP_inv_id_pres; /* present flag */ + ST_INT32 AP_invoke_id; /* AP invocation ID */ + ST_UCHAR AE_qual_pres; /* present flag */ + ST_INT32 AE_qual; /* AE qualifier */ + ST_UCHAR AE_inv_id_pres; /* present flag */ + ST_INT32 AE_invoke_id; /* AE invocation ID */ + PRES_ADDR pres_addr; /* Presentation address. */ +} ; +typedef struct dib_entry DIB_ENTRY; + +/************************************************************************/ +/* Channel-oriented control structure used to hold connection-specific */ +/* information */ +/************************************************************************/ + +#define MAX_TX_OUT 10 /* max. outstanding TX requests allowed */ + +struct chanctrl + { + DIB_ENTRY *loc_de; /* Pointer to Local DIB Entry */ + DIB_ENTRY *rem_de; /* Pointer to Remote DIB Entry */ + } ; +extern struct chanctrl *s_chan_ctrl; + +/************************************************************************/ +/* Structure to store incoming associate indication in case no listen */ +/* channel is available */ +/************************************************************************/ + +extern ST_INT num_loc_dib_entries; +extern ST_INT num_rem_dib_entries; +extern DIB_ENTRY *loc_dib_table; +extern DIB_ENTRY *rem_dib_table; + +/************************************************************************/ +/* Event handling variables for WIN32 & OS2. */ +/************************************************************************/ +#ifdef _WIN32 +extern ST_CHAR *MMSEventName; /* Pointer to the globally unique name of Event Object */ +extern HANDLE hMMSEvent; /* Handle to Event Object to be signalled when */ + /* s_serve () needs to be called */ +#endif /* _WIN32 */ +#ifdef __OS2__ +extern ST_CHAR *MMSEventName; /* Pointer to the globally unique name of Event Object */ +extern HEV hMMSEvent; /* Handle to Event Object to be signalled when */ + /* s_serve () needs to be called */ +#endif /* __OS2__ */ + +/************************************************************************/ +/* Prototypes */ +/************************************************************************/ +ST_VOID s_reset_ctrl (ST_INT); +ST_RET init_dirser (ST_VOID); +DIB_ENTRY *find_dib_entry (ST_CHAR *); +DIB_ENTRY *find_loc_dib_entry (ST_CHAR *ar_name); +DIB_ENTRY *find_rem_dib_entry (ST_CHAR *ar_name); + +ST_RET init_dirser_clt7 (ST_VOID); +DIB_ENTRY *find_dib_entry_clt7 (ST_CHAR *); +DIB_ENTRY *find_loc_dib_entry_clt7 (ST_CHAR *ar_name); + +#ifdef __cplusplus +} +#endif + +#endif /* !LEAN_A_H */ + + diff --git a/include/inc/llcio.h b/include/inc/llcio.h new file mode 100644 index 0000000..284435f --- /dev/null +++ b/include/inc/llcio.h @@ -0,0 +1,337 @@ +#ifndef _LLCIO_H +#define _LLCIO_H + +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994, All Rights Reserved */ +/* */ +/* MODULE NAME : llcio.h */ +/* PRODUCT(S) : osillc.sys */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/21/98 IKE 03 Converted to 7.0 Data types, removed */ +/* underscores so it can be compiled */ +/* 11/02/95 DSF 02 Enhanced to retrieve stats information */ +/* 12/08/94 DSF 01 Added SET_OFFSET */ +/* 03/10/94 DSF Initial Release */ +/************************************************************************/ + +/* +** User Functions +*/ + +int LlcOpen (char *Name); +int LlcClose (int fd); +int LlcWrite (int fd, char *buffer, int size); +int LlcRead (int fd, char *buffer, int size); +int LlcIoctl (int fd, void *pArg, int size); + + + + +/* +** IOCTL Management +*/ + +/* +** LLC Driver IOCTL requests +*/ + + +#define LLC_ADD_MULTI 1 +#define LLC_DEL_MULTI 2 +#define LLC_GET_HW_ADDR 3 +#define LLC_SET_FRAME_FILTER 4 +#define LLC_BIND_LSAP 5 +#define LLC_UNBIND_LSAP 6 +#define LLC_TRACE_ON 7 +#define LLC_TRACE_OFF 8 +#define LLC_DEBUG_ON 9 +#define LLC_DEBUG_OFF 10 +#define LLC_GET_PROTO_STATS 11 +#define LLC_GET_MAC_STATS 12 +#define LLC_ARM_SIGNAL 13 +#define LLC_ARM_POST 15 +#define LLC_GET_EMB_PHYS_ADDR 16 +#define LLC_SET_WRITE_CONFIRM_FLAG 17 +#define LLC_GET_DEBUG 18 +#define LLC_POST_BUFS 19 +#define LLC_SET_OFFSET 20 +#define LLC_GET_MAC_CHARS 21 +#define LLC_CLEAR_MAC_STATS 22 +#define LLC_CLEAR_PROTO_STATS 23 + + +/* +** LLC Driver IOCTL Errors +*/ + +#define LLCERR_NO_ERROR 0 +#define LLCERR_LSAP_BOUND 1 +#define LLCERR_LSAP_NOTBOUND 2 +#define LLCERR_ILLEGAL_OPERATION 3 +#define LLCERR_UNKNOWN_COMMAND 4 + +#define MAX_HWADDR_SIZE 12 + +typedef struct + { + int Opcode; + int Status; + } LLCGENERICIOCTL; + + +typedef struct + { + int Opcode; + int Status; + int cSize; + char Multicast[MAX_HWADDR_SIZE]; + } LLCADDMULTI; + +typedef struct + { + int Opcode; + int Status; + int cSize; + char Multicast[MAX_HWADDR_SIZE]; + } LLCDELMULTI; + +typedef struct + { + int Opcode; + int Status; + int cSize; + char HwAddr[MAX_HWADDR_SIZE]; + } LLCGETHWADDR; + +typedef struct + { + int Opcode; + int Status; + unsigned Lsap; + } LLCBINDLSAP; + +typedef struct + { + int Opcode; + int Status; + } LLCUNBINDLSAP; + +typedef struct + { + int Opcode; + int Status; + long EmbPhysAddr; + long EmbSize; + } LLCGETEMBPHYSADDR; + +typedef struct + { + int Opcode; + int Status; + char far *pfWriteConfirm; + } LLCSETWRITECONFIRMFLAG; + +typedef struct + { + int Opcode; + int Status; + int VxDID; + } LLCARMPOST; + +typedef struct + { + int Opcode; + int Status; + long offset; + } LLCSETOFFSET; + + +typedef struct tagUSERBUFDESC + { + struct tagUSERBUFDESC far *Next; + char far *pBuf; + int cBufSize; + int cDataSize; + } USERBUFDESC; + +typedef struct + { + int Opcode; + int Status; + USERBUFDESC far *pBufDesc; + } LLCPOSTBUFS; + +typedef struct + { + int Opcode; + int Status; + int MessageNum; + int Parm1; + int Parm2; + int Parm3; + } LLCGETDEBUG; + + +/* +** NDIS Protocol Driver Stats +*/ + +typedef struct + { + long nFramesReceived; + long nReceiveLookaheadReceived; + long nReceiveChainReceived; + long nFramesDiscardedNotRecognized; + long nFramesDiscardedOutOfResources; + long nTransferDataFailed; + long nTransmitChainIssued; + long nTransmitChainFailed; + long nFramesDelivered; /* DOS only */ + } LLCPROTOSTATS; + +typedef struct + { + int Opcode; + int Status; + LLCPROTOSTATS ProtoStats; + } LLCGETPROTOSTATS; + +typedef struct + { + int Opcode; + int Status; + } LLCCLEARPROTOSTATS; + +/* +** NDIS MAC Driver Characteristics +*/ + +typedef struct /* structure for MAC service specific info */ + { + int cSize; /* length of the characteristic table */ + char TypeName[16]; /* name of the MAC type (eg. 802.3...) */ + int cStationAddr; /* length of station address (MAC) */ + char PermMACAddr[16]; /* hardware default MAC address */ + char CurrMACAddr[16]; /* current MAC address in use */ + long FunctionAddr; /* current functional address of adapter */ + long reserved; /* pointer to multicast table */ + long LinkSpeed; /* link speed bits/sec */ + long fMAC; /* flags of capabilities */ + int MaxFrameSize; /* maximum MAC frame which can be sent */ + long TotalTxSpace; /* total transmit buffer space */ + int cTxBlockSize; /* size of allocated transmission blocks */ + long TotalRxSpace; /*total reception buffer space */ + int cRxBlockSize; /*reception buffer alloc blk size */ + char VendorID[3]; /*vendor IEEE ID */ + char VendorAdapterDesc; /*vendor adapter description */ + long reserved2; /*pointer to vendor serial number */ + int IRQLevel; /*interrupt level */ + int TransmitQueueDepth; + int nMaxDataBlocks; + } LLCMACCHARS; + +typedef struct + { + int Opcode; + int Status; + LLCMACCHARS MacChars; + } LLCGETMACCHARS; + +typedef struct + { + int cSize; /*size of table */ + long LastDiagTime; /*seconds since 1-1-1970 of diags */ + long MACStatus; /*mac status, this is a bit mask */ + /* Bits 0-2: 0 - Hardware Not Installed */ + /* 1 - Hardware Failed Pwrup Diags */ + /* 2 - Hardware Failed CNFG Prob */ + /* 3 - Hardware Faulted */ + /* 4 - Hardware Marginally Operat */ + /* 7 - Fully Operational */ + /* Bit 3: MAC BOUND */ + /* Bit 4: MAC OPEN */ + /* Bit 5: DIAG_IN_PROGRESS */ + int CurrPacketFilter; /* Bit 1: Directed and Multicast Group */ + /* Bit 2: Broadcast */ + /* Bit 3: Promiscuous */ + /* Bit 4: All Source Routing */ + long reserved; /*pointer to media specific stats */ + long LastClearTime; /*seconds since 1-1-1970 */ + long nOkFramesReceived; /*total frames received ok */ + long nCrcErrorFrames; /*total frames received with crc errors */ + long nBytesReceived; /*total number of bytes recieved */ + long nFramesDiscarded; /*total number of frames discarded */ + long nMulticastFramesReceived; /*total number of multicast frames rxd OK */ + long nBroadcastFramesReceived; /*total number of broadcast frames rxd OK */ + long reserved1; + long reserved2; + long reserved3; + long reserved4; + long reserved5; + long nFramesDiscardedHwError; /*total number of frames discarded due to HW err*/ + long nFramesTransmittedOk; /*total number of frames transmitted OK */ + long nBytesTransimittedOk; /*total number of bytes transmitted OK */ + long nMulticastFramesTransmitted; /*total number of multicast transmitted */ + long nBroadcastFramesTransmitted; /*total broadcast frame transmitted */ + long reserved6; + long reserved7; + long nFramesNotTransmittedTimeout; /*total frames not transmitted due to timeout */ + long nFramesNotTransmittedHwError; /*total frames not transmitted due to HW ERR */ + } LLCMACSTATS; + +typedef struct + { + int Opcode; + int Status; + LLCMACSTATS MacStats; + } LLCGETMACSTATS; + +typedef struct + { + int Opcode; + int Status; + } LLCCLEARMACSTATS; + +typedef union + { + LLCADDMULTI AddMulti; + LLCDELMULTI DelMulti; + LLCGETHWADDR GetHwAddr; + LLCBINDLSAP BindLsap; + LLCUNBINDLSAP UnBindLsap; + LLCGETEMBPHYSADDR GetEmbPhysAddr; + LLCSETWRITECONFIRMFLAG SetWriteConfirmFlag; + LLCPOSTBUFS PostBufs; + LLCARMPOST ArmPost; + LLCGETDEBUG GetDebug; + LLCSETOFFSET SetOffset; + LLCGETMACCHARS GetMacChars; + LLCGETMACSTATS GetMacStats; + LLCCLEARMACSTATS ClearMacStats; + LLCGETPROTOSTATS GetProtoStats; + LLCCLEARPROTOSTATS ClearProtoStats; + } LLCIOCTL; + + + +/* +** Function prototypes +*/ + +int llc_getstats (LLCMACCHARS *MacChars, + LLCMACSTATS *MacStats, + LLCPROTOSTATS *ProtoStats); +void llc_clearstats (); + + +#endif diff --git a/include/inc/llcioctl.h b/include/inc/llcioctl.h new file mode 100644 index 0000000..995fac0 --- /dev/null +++ b/include/inc/llcioctl.h @@ -0,0 +1,121 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : llcioctl.c */ +/* PRODUCT(S) : OSI LLC NDIS 3.1 VxD */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/16/97 DSF 05 Added stats */ +/* 09/10/96 DSF 04 Added Length field to SET_MULTI */ +/* 09/05/96 DSF 03 Added SET_FILTER */ +/* 08/14/96 DSF 02 Added Transmit Completion object */ +/* 04/01/96 DSF 01 Initial Release */ +/* */ +/************************************************************************/ + +#define IOCTL_BASE 0x8100 +#define IOCTL_GET_PHYS_ADDR (IOCTL_BASE + 1) +#define IOCTL_SET_MULTI (IOCTL_BASE + 2) +#define IOCTL_ARM_EVENT (IOCTL_BASE + 3) +#define IOCTL_SEND (IOCTL_BASE + 4) +#define IOCTL_RECEIVE (IOCTL_BASE + 5) +#define IOCTL_ARM_COMPLETE (IOCTL_BASE + 6) +#define IOCTL_SET_FILTER (IOCTL_BASE + 7) +#define IOCTL_GET_STATS (IOCTL_BASE + 8) + + +#define PHYS_ADDR_LENGTH 6 +typedef struct _GET_PHYS_ADDR + { + UINT Status; + char PhysAddr[PHYS_ADDR_LENGTH]; + } GET_PHYS_ADDR; + + +typedef struct _SET_MULTI + { + UINT Status; + UINT Length; + char MultiAddr[2 * PHYS_ADDR_LENGTH]; + } SET_MULTI; + +typedef struct _SET_FILTER + { + UINT Status; + } SET_FILTER; + +typedef struct _ARM_EVENT + { + UINT Status; + HANDLE EventHandle; + } ARM_EVENT; + +typedef struct _ARM_COMPLETE + { + UINT Status; + HANDLE CompleteHandle; + } ARM_COMPLETE; + +#if !defined (GET_STATS_DEFINED) +typedef struct _MAC_STATS + { + ULONG HardwareStatus; + ULONG MaxLookahead; + ULONG MaxFrameSize; + ULONG LinkSpeed; + ULONG TransmitBufferSpace; + ULONG ReceiveBufferSpace; + ULONG TransmitBlockSize; + ULONG ReceiveBlockSize; + ULONG MaximumTotalSize; + ULONG MacOptions; + ULONG ConnectStatus; + ULONG XmitOk; + ULONG RcvOk; + ULONG XmitError; + ULONG RcvError; + ULONG RcvNoBuffer; + ULONG RcvCrcError; + ULONG TransmitQueueLength; + } MAC_STATS; + +typedef struct _PROTO_STATS + { + ULONG XmitOk; + ULONG RcvOk; + ULONG XmitError; + ULONG RcvError; + ULONG RcvUnknown; + ULONG XmitInd; + ULONG RcvInd; + ULONG AllocError; + } PROTO_STATS; + +typedef struct _USER_STATS + { + ULONG XmitOk; + ULONG RcvOk; + ULONG XmitError; + ULONG RcvError; + ULONG RcvUnknown; + } USER_STATS; + +typedef struct _GET_STATS + { + UINT Status; + MAC_STATS mac; + PROTO_STATS proto; + USER_STATS user; + } GET_STATS; + +#define GET_STATS_DEFINED +#endif diff --git a/include/inc/mem_chk.h b/include/inc/mem_chk.h new file mode 100644 index 0000000..ff264cf --- /dev/null +++ b/include/inc/mem_chk.h @@ -0,0 +1,339 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986-2004 All Rights Reserved */ +/* */ +/* MODULE NAME : mem_chk.h */ +/* PRODUCT(S) : General Use */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the declarations of the dynamic memory */ +/* handling functions. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/06/04 EJV 16 Added dyn_mem_ptr_status2. */ +/* 04/14/03 DSF 15 Cleanup */ +/* 04/08/03 DSF 14 added m_mem_crt_debug */ +/* 04/04/03 DSF 13 new/delete checks for MFC */ +/* 08/20/01 JRB 12 chk_* functions chged to nd_chk_*. */ +/* chk_* names are now ALWAYS macros. */ +/* Make 4 sets of macros depending on whether */ +/* DEBUG_SISCO and/or SMEM_ENABLE defined. */ +/* Don't define SMEM_ENABLE, do from makefiles. */ +/* Remove logging backward compatibility stuff. */ +/* 08/06/01 RKR 11 S_THISFILE was removed, need a thisFileName */ +/* 03/19/01 JRB 10 Move SMEM context defs to "smem.h". */ +/* 01/25/01 DSF 09 new/delete checks */ +/* 11/01/00 MDE 08 Additional SMEM work */ +/* 01/21/00 MDE 07 Added SMEM support */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 01/26/98 MDE 05 Added 'chk_strdup' */ +/* 12/08/98 MDE 04 Added 'ST_BOOLEAN m_auto_hw_log' */ +/* 10/08/98 MDE 03 Migrated to updated SLOG interface */ +/* 10/14/97 DSF 02 m_bad_ptr_val is now a pointer */ +/* 09/16/97 DSF 01 chk_debug_en is UINT */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MEM_CHK_INCLUDED +#define MEM_CHK_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef SMEM_ENABLE +#include "smem.h" +#endif + +/************************************************************************/ +/* MEM_CHK MACROS and FUNCTION PROTOTYPES */ +/* Memory allocation macros. There are 4 sets of macros depending on */ +/* DEBUG_SISCO and SMEM_ENABLE. Each set of macros calls a unique set */ +/* of functions. */ +/* The DEBUG macros use thisFileName (instead of __FILE__) to reduce */ +/* memory usage. Any file using these macros MUST contain the following */ +/* statement: */ +/* static char *thisFileName = __FILE__; */ +/************************************************************************/ + +#if defined(SMEM_ENABLE) + #if defined(DEBUG_SISCO) + #define M_MALLOC(ctx,x) x_m_malloc (ctx,x, thisFileName,__LINE__) + #define M_CALLOC(ctx,x,y) x_m_calloc (ctx,x,y,thisFileName,__LINE__) + #define M_REALLOC(ctx,x,y) x_m_realloc (ctx,x,y,thisFileName,__LINE__) + #define M_STRDUP(ctx,x) x_m_strdup (ctx,x, thisFileName,__LINE__) + #define M_FREE(ctx,x) x_m_free (ctx,x, thisFileName,__LINE__) + + #define chk_malloc(x) x_m_malloc (MSMEM_GEN,x, thisFileName,__LINE__) + #define chk_calloc(x,y) x_m_calloc (MSMEM_GEN,x,y,thisFileName,__LINE__) + #define chk_realloc(x,y) x_m_realloc (MSMEM_GEN,x,y,thisFileName,__LINE__) + #define chk_strdup(x) x_m_strdup (MSMEM_GEN,x, thisFileName,__LINE__) + #define chk_free(x) x_m_free (MSMEM_GEN,x, thisFileName,__LINE__) + + ST_VOID *x_m_malloc (SMEM_CONTEXT *smem_ctx, ST_UINT size, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + + ST_VOID *x_m_calloc (SMEM_CONTEXT *smem_ctx, ST_UINT num, + ST_UINT size, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + + ST_VOID *x_m_realloc (SMEM_CONTEXT *smem_ctx, ST_VOID *old, + ST_UINT size, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + ST_VOID x_m_free (SMEM_CONTEXT *smem_ctx, ST_VOID *ptr, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + ST_CHAR *x_m_strdup (SMEM_CONTEXT *smem_ctx, ST_CHAR *str, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + + #else /* !DEBUG_SISCO */ + + #define M_MALLOC(ctx,x) nd_m_malloc (ctx,x) + #define M_CALLOC(ctx,x,y) nd_m_calloc (ctx,x,y) + #define M_REALLOC(ctx,x,y) nd_m_realloc (ctx,x,y) + #define M_STRDUP(ctx,x) nd_m_strdup (ctx,x) + #define M_FREE(ctx,x) nd_m_free (ctx,x) + + #define chk_malloc(x) nd_m_malloc (MSMEM_GEN,x) + #define chk_calloc(x,y) nd_m_calloc (MSMEM_GEN,x,y) + #define chk_realloc(x,y) nd_m_realloc (MSMEM_GEN,x,y) + #define chk_strdup(x) nd_m_strdup (MSMEM_GEN,x) + #define chk_free(x) nd_m_free (MSMEM_GEN,x) + + ST_VOID *nd_m_malloc (SMEM_CONTEXT *smem_ctx, ST_UINT size); + ST_VOID *nd_m_calloc (SMEM_CONTEXT *smem_ctx, ST_UINT num, ST_UINT size); + ST_VOID *nd_m_realloc (SMEM_CONTEXT *smem_ctx, ST_VOID *old, ST_UINT size); + ST_VOID nd_m_free (SMEM_CONTEXT *smem_ctx, ST_VOID *ptr); + ST_CHAR *nd_m_strdup (SMEM_CONTEXT *smem_ctx, ST_CHAR *str); + + #endif /* !DEBUG_SISCO */ +#else /* !SMEM_ENABLE */ + #if defined(DEBUG_SISCO) + + #define M_MALLOC(ctx,x) x_chk_malloc (x, thisFileName,__LINE__) + #define M_CALLOC(ctx,x,y) x_chk_calloc (x,y,thisFileName,__LINE__) + #define M_REALLOC(ctx,x,y) x_chk_realloc (x,y,thisFileName,__LINE__) + #define M_STRDUP(ctx,x) x_chk_strdup (x, thisFileName,__LINE__) + #define M_FREE(ctx,x) x_chk_free (x, thisFileName,__LINE__) + + #define chk_malloc(x) x_chk_malloc (x, thisFileName,__LINE__) + #define chk_calloc(x,y) x_chk_calloc (x,y,thisFileName,__LINE__) + #define chk_realloc(x,y) x_chk_realloc (x,y,thisFileName,__LINE__) + #define chk_strdup(x) x_chk_strdup (x, thisFileName,__LINE__) + #define chk_free(x) x_chk_free (x, thisFileName,__LINE__) + + ST_VOID *x_chk_realloc (ST_VOID *old, + ST_UINT size, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + ST_VOID *x_chk_malloc (ST_UINT size, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + ST_VOID *x_chk_calloc (ST_UINT num, + ST_UINT size, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + ST_CHAR *x_chk_strdup (ST_CHAR *str, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + ST_VOID x_chk_free (ST_VOID *old, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + + #else /* !DEBUG_SISCO */ + + #define M_MALLOC(ctx,x) nd_chk_malloc (x) + #define M_CALLOC(ctx,x,y) nd_chk_calloc (x,y) + #define M_REALLOC(ctx,x,y) nd_chk_realloc (x,y) + #define M_STRDUP(ctx,x) nd_chk_strdup (x) + #define M_FREE(ctx,x) nd_chk_free (x) + + #define chk_malloc(x) nd_chk_malloc (x) + #define chk_calloc(x,y) nd_chk_calloc (x,y) + #define chk_realloc(x,y) nd_chk_realloc (x,y) + #define chk_strdup(x) nd_chk_strdup (x) + #define chk_free(x) nd_chk_free (x) + + ST_VOID *nd_chk_malloc (ST_UINT size); + ST_VOID *nd_chk_calloc (ST_UINT num, ST_UINT size); + ST_VOID *nd_chk_realloc (ST_VOID *old, ST_UINT size); + ST_CHAR *nd_chk_strdup (ST_CHAR *str); + ST_VOID nd_chk_free (ST_VOID *ptr); + + #endif /* !DEBUG_SISCO */ +#endif /* !SMEM_ENABLE */ + + +/************************************************************************/ +/* chk_debug_en bit assignments */ +/* These are the defines to be used by all new applications */ +#define MEM_LOG_ERR 0x0001 +#define MEM_LOG_CALLOC 0x0002 +#define MEM_LOG_MALLOC 0x0004 +#define MEM_LOG_REALLOC 0x0008 +#define MEM_LOG_FREE 0x0010 + +extern ST_UINT chk_debug_en; + +/************************************************************************/ +/* Replacement Memory allocation functions. */ +/************************************************************************/ + +ST_VOID init_mem_chk (ST_VOID); +ST_VOID dyn_mem_ptr_status (ST_VOID); +ST_UINT dyn_mem_ptr_status2 (ST_VOID *marker_ptr); +ST_VOID dyn_mem_ptr_statistics (ST_BOOLEAN log_to_screen); +ST_VOID check_mem_list (ST_VOID); +ST_RET chk_alloc_ptr (ST_VOID *ptr); + + +/************************************************************************/ +/* fatal error service function pointers, used for unrecoverable errors */ +/************************************************************************/ +#define MEM_ERR_EXIT_CODE 2001 + +extern ST_VOID *(*m_memerr_fun)(ST_UINT size); /* for malloc */ +extern ST_VOID *(*c_memerr_fun)(ST_UINT num, ST_UINT size); /* for calloc */ +extern ST_VOID *(*r_memerr_fun)(ST_VOID *old, ST_UINT size); /* for realloc*/ + +/************************************************************************/ +/* statistics */ +/************************************************************************/ +extern ST_UINT32 chk_curr_mem_count; +extern ST_UINT32 chk_max_dyn_mem_ptrs; +extern ST_UINT32 chk_max_mem_allocated; +extern ST_UINT32 chk_curr_mem_size; + + +/************************************************************************/ +/************************************************************************/ +/* HEAP checking functions and macros */ + +/* These defines are used to control the level or print in chk_hp */ +#define DEBUG_HEAP_SUM 0x0001 +#define DEBUG_HEAP_ENTRY 0x0002 +#define DEBUG_HEAP_ALL 0x0003 + +#ifdef HEAP_CHECK_ENABLE +#define HEAP_CHECK() chk_hp (0, (ST_CHAR *) __FILE__, __LINE__) +#else +#define HEAP_CHECK() +#endif + +ST_RET msoft_heap_check (ST_INT16); +ST_RET chk_hp (ST_INT16 prt_mask,ST_CHAR *file,ST_INT line); + +/************************************************************************/ + +extern ST_VOID *m_bad_ptr_val; + +/* This variable used to enable MSOFT heap check calls on every alloc */ +/* and free call. Also sets the unused heap memory to 0x55's */ +extern ST_BOOLEAN m_heap_check_enable; + +/* This variable used to enable list validation and overwrite checking */ +/* on every alloc and free call. */ +extern ST_BOOLEAN m_check_list_enable; + +/* Set this = SD_FALSE to speed up the debug version. When SD_TRUE, it */ +/* enables searching the memory list for the element before accessing */ +/* the memory during chk_realloc and chk_free calls */ +extern ST_BOOLEAN m_find_node_enable; + +/* This variable will cause chk_realloc to not realloc when the new */ +/* size is smaller than the old size */ +extern ST_BOOLEAN m_no_realloc_smaller; + +/* Dump memory table whenever high water mark is advanced */ +extern ST_BOOLEAN m_auto_hw_log; + +extern ST_CHAR *m_pad_string; +extern ST_INT m_num_pad_bytes; + +extern ST_BOOLEAN m_fill_en; +extern ST_UCHAR m_fill_byte; + +extern ST_BOOLEAN m_mem_debug; + +extern ST_BOOLEAN m_mem_crt_debug; + +/* This function pointer can be set to select a function to be called */ +/* in case of memory error. */ + +extern ST_VOID (*mem_chk_err)(ST_VOID); + +/* Read only */ +extern ST_UINT m_mem_overhead; + + +/************************************************************************/ +/************************************************************************/ +#ifdef __cplusplus +} +#endif + + + +#ifdef __cplusplus +/************************************************************************/ +/* deal with new and delete */ +/************************************************************************/ +#if defined (DEBUG_SISCO) && defined (DEBUG_NEW_SISCO) + +#include + +void * operator new(size_t nSize) throw (std::bad_alloc); +void * operator new(size_t nSize, const char *fileName, const int lineNum) throw (std::bad_alloc); +void * operator new(size_t nSize, const std::nothrow_t&) throw (); +void * operator new[](size_t nSize) throw (std::bad_alloc); +void * operator new[](size_t nSize, const char *fileName, const int lineNum) throw (std::bad_alloc); +void * operator new[](size_t nSize, const std::nothrow_t&) throw (); +void operator delete(void *p) throw (); +void operator delete(void *p, const char *fileName, const int lineNum) throw (); +void operator delete[](void *p) throw (); +void operator delete[](void *p, const char *fileName, const int lineNum) throw (); + +#ifndef MEM_CHK +#define new new(thisFileName, __LINE__) +#endif + +#endif + +#if defined (DEBUG_SISCO) && defined (DEBUG_NEW_MFC) + +#include + +#if !defined (__AFX_H__) + +#include + +#define THIS_FILE __FILE__ + +void* __cdecl operator new(size_t nSize, LPCSTR lpszFileName, int nLine); +#define DEBUG_NEW new(THIS_FILE, __LINE__) +void __cdecl operator delete(void* p, LPCSTR lpszFileName, int nLine); + +void * __cdecl operator new[](size_t); +void* __cdecl operator new[](size_t nSize, LPCSTR lpszFileName, int nLine); +void __cdecl operator delete[](void* p, LPCSTR lpszFileName, int nLine); +void __cdecl operator delete[](void *); + +#endif /* AFX */ + +#endif /* DEBUG_NEW_MFC */ + +#endif /* __cplusplus */ + + +#endif /* mem_chk.h already included */ diff --git a/include/inc/memlog.h b/include/inc/memlog.h new file mode 100644 index 0000000..ecdb3a3 --- /dev/null +++ b/include/inc/memlog.h @@ -0,0 +1,201 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986, 1987, 1988, 1989, 1990, All Rights Reserved */ +/* */ +/* MODULE NAME : memlog.h */ +/* PRODUCT(S) : General Use */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the declarations of the dynamic memory */ +/* handling functions. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/13/02 JRB 08 MEMLOG_PAUSE*, MEMLOG_LF macros do nothing. */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 10/08/98 MDE 06 Migrated to updated SLOG interface */ +/* 04/17/96 JRB 05 Del #define THISFILE thisFileName. */ +/* 04/17/96 JRB 04 Del mem_sLogCtrl. Use new sLogCtrl in slog.c */ +/* 04/01/94 MDE 03 Removed THISFILE defines, changed THISFILE */ +/* to thisFileName */ +/* 03/29/94 DSF 02 Corrected definition for THISFILE */ +/* 12/10/93 DSF 01 Added MEMLOG_CHERR macro */ +/************************************************************************/ + +#ifndef MEMLOG_INCLUDED +#define MEMLOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "slog.h" + +/************************************************************************/ +/************************************************************************/ + +extern SD_CONST ST_CHAR *SD_CONST _mem_log_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mem_log_calloc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mem_log_malloc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mem_log_realloc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mem_log_free_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mem_log_nerr_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mem_log_dump_logstr; + + +#define MEMLOG_LF() + +#define MEMLOG_CALLSTACK(a) slogCallStack (sLogCtrl,a); + +#define MEMLOG_PAUSE(msg) +#define MEMLOG_PAUSEERR(msg) + +#define MEMLOG_MALLOC2(a,b,c) {\ + if (chk_debug_en & MEM_LOG_MALLOC)\ + _slog (sLogCtrl,_mem_log_malloc_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define MEMLOG_CMALLOC1(a,b) {\ + if (chk_debug_en & MEM_LOG_MALLOC)\ + _slogc (sLogCtrl,a,b);\ + } +#define MEMLOG_CMALLOC2(a,b,c) {\ + if (chk_debug_en & MEM_LOG_MALLOC)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define MEMLOG_CMALLOC3(a,b,c,d) {\ + if (chk_debug_en & MEM_LOG_MALLOC)\ + _slogc (sLogCtrl,a,b,c,d);\ + } + +#define MEMLOG_CALLOC3(a,b,c,d) {\ + if (chk_debug_en & MEM_LOG_CALLOC)\ + _slog (sLogCtrl,_mem_log_calloc_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define MEMLOG_CCALLOC1(a,b) {\ + if (chk_debug_en & MEM_LOG_CALLOC)\ + _slogc (sLogCtrl,a,b);\ + } +#define MEMLOG_CCALLOC2(a,b,c) {\ + if (chk_debug_en & MEM_LOG_CALLOC)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define MEMLOG_CCALLOC3(a,b,c,d) {\ + if (chk_debug_en & MEM_LOG_CALLOC)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define MEMLOG_REALLOC3(a,b,c,d) {\ + if (chk_debug_en & MEM_LOG_REALLOC)\ + _slog (sLogCtrl,_mem_log_realloc_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define MEMLOG_CREALLOC1(a,b) {\ + if (chk_debug_en & MEM_LOG_REALLOC)\ + _slogc (sLogCtrl,a,b);\ + } +#define MEMLOG_CREALLOC2(a,b,c) {\ + if (chk_debug_en & MEM_LOG_REALLOC)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define MEMLOG_CREALLOC3(a,b,c,d) {\ + if (chk_debug_en & MEM_LOG_REALLOC)\ + _slogc (sLogCtrl,a,b,c,d);\ + } + +#define MEMLOG_FREE1(a,b) {\ + if (chk_debug_en & MEM_LOG_FREE)\ + _slog (sLogCtrl,_mem_log_free_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define MEMLOG_CFREE2(a,b,c) {\ + if (chk_debug_en & MEM_LOG_FREE)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define MEMLOG_CFREE3(a,b,c,d) {\ + if (chk_debug_en & MEM_LOG_FREE)\ + _slogc (sLogCtrl,a,b,c,d);\ + } + +#define MEMLOG_ERR0(a) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slog (sLogCtrl,_mem_log_err_logstr,\ + thisFileName,__LINE__,a);\ + } +#define MEMLOG_ERR1(a,b) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slog (sLogCtrl,_mem_log_err_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define MEMLOG_ERR2(a,b,c) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slog (sLogCtrl,_mem_log_err_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define MEMLOG_CERR0(a) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slogc (sLogCtrl,a);\ + } +#define MEMLOG_CERR1(a,b) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slogc (sLogCtrl,a,b);\ + } +#define MEMLOG_CERR2(a,b,c) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define MEMLOG_CERR3(a,b,c,d) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define MEMLOG_CERR5(a,b,c,d,e,f) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c,d,e,f);\ + } +#define MEMLOG_CERR6(a,b,c,d,e,f,g) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c,d,e,f,g);\ + } +#define MEMLOG_CHERR(a,b) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slogHex (sLogCtrl,a,b);\ + } + +#define MEMLOG_DUMP0(a) {\ + _slog (sLogCtrl,_mem_log_dump_logstr,\ + thisFileName,__LINE__,a);\ + } +#define MEMLOG_DUMP1(a,b) {\ + _slog (sLogCtrl,_mem_log_dump_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define MEMLOG_CDUMP4(a,b,c,d,e) {\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } +#define MEMLOG_CDUMP5(a,b,c,d,e,f) {\ + _slogc (sLogCtrl,a,b,c,d,e,f);\ + } +#define MEMLOG_CDUMP0(a) {\ + _slogc (sLogCtrl,a);\ + } +#define MEMLOG_CDUMP1(a,b) {\ + _slogc (sLogCtrl,a,b);\ + } +#define MEMLOG_CDUMP2(a,b,c) {\ + _slogc (sLogCtrl,a,b,c);\ + } +#define MEMLOG_CDUMP3(a,b,c,d) {\ + _slogc (sLogCtrl,a,b,c,d);\ + } + + +#ifdef __cplusplus +} +#endif + + +#endif /* memlog.h already included */ + diff --git a/include/inc/mloguser.h b/include/inc/mloguser.h new file mode 100644 index 0000000..eb55381 --- /dev/null +++ b/include/inc/mloguser.h @@ -0,0 +1,297 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2008 All Rights Reserved */ +/* */ +/* MODULE NAME : mloguser.h */ +/* PRODUCT(S) : MMS-EASE 250-001 */ +/* */ +/* MODULE DESCRIPTION : */ +/* ANSI Protytped Logging Functions for MMS-EASE user code. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/01/08 JRB 16 Del commented code. */ +/* 10/30/06 JRB 15 Add mlog_arb_log_ctrl extern. */ +/* 03/23/05 JRB 14 Del unused m_log_mllp* & m_log_llp* protos. */ +/* 06/10/04 EJV 13 Removed suicacse.h - lber.h conflict on AIX. */ +/* 04/05/02 MDE 12 Cleaned up MMS Lite use of MLOG */ +/* 11/04/98 DSF 11 Added m_get_mms_rej_text () */ +/* 08/13/98 MDE 10 Added m_log_tdl */ +/* 07/16/98 MDE 09 Added ml_log_dec_rslt declaration */ +/* 06/15/98 MDE 08 Changes to allow compile under C++ */ +/* 03/20/98 JRB 07 Del mmsop_en.h. Only user code needs it now. */ +/* 09/29/97 MDE 06 Don't need mlog_en.h */ +/* 08/15/97 MDE 05 BTOD handling changes */ +/* 08/14/97 MDE 04 Removed unused 'm_log_info_print' */ +/* 08/04/97 MDE 03 Added 'no log' function declarations */ +/* 08/04/97 MDE 02 Changes towards breakup */ +/* 06/09/97 MDE 01 Removed several mmv_v???.h includes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MLOGUSER_INCLUDED +#define MLOGUSER_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mmslog.h" +#include "mms_pcon.h" +#include "mms_pdom.h" +#include "mms_pevn.h" +#include "mms_pfil.h" +#include "mms_pjou.h" +#include "mms_pocs.h" +#include "mms_pprg.h" +#include "mms_psem.h" +#include "mms_pvar.h" +#include "mms_pvmd.h" +#include "mms_vvar.h" +#if defined(MMS_LITE) +#include "mmsintr2.h" +#endif +#include "sx_arb.h" /* needed for SXD_ARB_DATA_CTRL */ + + +/************************************************************************/ +/************************************************************************/ + +extern ST_VOID (*m_req_log_fun_tbl [MAX_MMSOP_DIS+1]) (ST_VOID *v); +extern ST_VOID (*m_resp_log_fun_tbl [MAX_MMSOP_DIS+1]) (ST_VOID *v); + +/* Request / Response Data Logging Functions */ +ST_VOID m_log_ackevnot_req (ACKEVNOT_REQ_INFO *info); +ST_VOID m_log_altecm_req (ALTECM_REQ_INFO *info); +ST_VOID m_log_altee_resp (ALTEE_RESP_INFO *info); +ST_VOID m_log_altee_req (ALTEE_REQ_INFO *info); +ST_VOID m_log_crepi_req (CREPI_REQ_INFO *info); +ST_VOID m_log_cancel_req (ST_VOID); +ST_VOID m_log_cancel_resp (ST_VOID); +ST_VOID m_log_defea_req (DEFEA_REQ_INFO *info); +ST_VOID m_log_defec_req (DEFEC_REQ_INFO *info); +ST_VOID m_log_defee_req (DEFEE_REQ_INFO *info); +ST_VOID m_log_defscat_req (DEFSCAT_REQ_INFO *info); +ST_VOID m_log_defsem_req (DEFSEM_REQ_INFO *info); +ST_VOID m_log_deftype_req (DEFTYPE_REQ_INFO *info); +ST_VOID m_log_defvar_req (DEFVAR_REQ_INFO *info); +ST_VOID m_log_defvlist_req (DEFVLIST_REQ_INFO *info); +ST_VOID m_log_deldom_req (DELDOM_REQ_INFO *info); +ST_VOID m_log_delea_resp (DELEA_RESP_INFO *info); +ST_VOID m_log_delea_req (DELEA_REQ_INFO *info); +ST_VOID m_log_delec_req (DELEC_REQ_INFO *info); +ST_VOID m_log_delec_resp (DELEC_RESP_INFO *info); +ST_VOID m_log_delee_resp (DELEE_RESP_INFO *info); +ST_VOID m_log_delee_req (DELEE_REQ_INFO *info); +ST_VOID m_log_delpi_req (DELPI_REQ_INFO *info); +ST_VOID m_log_delsem_req (DELSEM_REQ_INFO *info); +ST_VOID m_log_deltype_resp (DELTYPE_RESP_INFO *info); +ST_VOID m_log_deltype_req (DELTYPE_REQ_INFO *info); +ST_VOID m_log_delvar_resp (DELVAR_RESP_INFO *info); +ST_VOID m_log_delvar_req (DELVAR_REQ_INFO *info); +ST_VOID m_log_delvlist_resp (DELVLIST_RESP_INFO *info); +ST_VOID m_log_delvlist_req (DELVLIST_REQ_INFO *info); +ST_VOID m_log_download_resp (DOWNLOAD_RESP_INFO *info); +ST_VOID m_log_download_req (DOWNLOAD_REQ_INFO *info); +ST_VOID m_log_evnot_req (EVNOT_REQ_INFO *info); +ST_VOID m_log_fclose_req (FCLOSE_REQ_INFO *info); +ST_VOID m_log_fdelete_req (FDELETE_REQ_INFO *info); +ST_VOID m_log_fdir_resp (FDIR_RESP_INFO *info); +ST_VOID m_log_fdir_req (FDIR_REQ_INFO *info); +ST_VOID m_log_fopen_resp (FOPEN_RESP_INFO *info); +ST_VOID m_log_fopen_req (FOPEN_REQ_INFO *info); +ST_VOID m_log_fread_resp (FREAD_RESP_INFO *info); +ST_VOID m_log_fread_req (FREAD_REQ_INFO *info); +ST_VOID m_log_frename_req (FRENAME_REQ_INFO *info); +ST_VOID m_log_getaes_resp (GETAES_RESP_INFO *info); +ST_VOID m_log_getaes_req (GETAES_REQ_INFO *info); +ST_VOID m_log_getas_resp (GETAS_RESP_INFO *info); +ST_VOID m_log_getas_req (GETAS_REQ_INFO *info); +ST_VOID m_log_getcl_resp (GETCL_RESP_INFO *info); +ST_VOID m_log_getcl_req (GETCL_REQ_INFO *info); +ST_VOID m_log_getdom_resp (GETDOM_RESP_INFO *info); +ST_VOID m_log_getdom_req (GETDOM_REQ_INFO *info); +ST_VOID m_log_geteaa_resp (GETEAA_RESP_INFO *info); +ST_VOID m_log_geteaa_req (GETEAA_REQ_INFO *info); +ST_VOID m_log_geteca_resp (GETECA_RESP_INFO *info); +ST_VOID m_log_geteca_req (GETECA_REQ_INFO *info); +ST_VOID m_log_geteea_resp (GETEEA_RESP_INFO *info); +ST_VOID m_log_geteea_req (GETEEA_REQ_INFO *info); +ST_VOID m_log_getpi_resp (GETPI_RESP_INFO *info); +ST_VOID m_log_getpi_req (GETPI_REQ_INFO *info); +ST_VOID m_log_getscat_resp (GETSCAT_RESP_INFO *info); +ST_VOID m_log_getscat_req (GETSCAT_REQ_INFO *info); +ST_VOID m_log_gettype_resp (GETTYPE_RESP_INFO *info); +ST_VOID m_log_gettype_req (GETTYPE_REQ_INFO *info); +ST_VOID m_log_getvar_resp (GETVAR_RESP_INFO *info); +ST_VOID m_log_getvar_req (GETVAR_REQ_INFO *info); +ST_VOID m_log_getvlist_resp (GETVLIST_RESP_INFO *info); +ST_VOID m_log_getvlist_req (GETVLIST_REQ_INFO *info); +ST_VOID m_log_ident_resp (IDENT_RESP_INFO *info); +ST_VOID m_log_info_req (INFO_REQ_INFO *info); +ST_VOID m_log_initdown_req (INITDOWN_REQ_INFO *info); +ST_VOID m_log_initupl_resp (INITUPL_RESP_INFO *info); +ST_VOID m_log_initupl_req (INITUPL_REQ_INFO *info); +ST_VOID m_log_init_info (INIT_INFO *info); +ST_VOID m_log_input_resp (INPUT_RESP_INFO *info); +ST_VOID m_log_input_req (INPUT_REQ_INFO *info); +ST_VOID m_log_jcreate_req (JCREATE_REQ_INFO *info); +ST_VOID m_log_jdelete_req (JDELETE_REQ_INFO *info); +ST_VOID m_log_jinit_resp (JINIT_RESP_INFO *info); +ST_VOID m_log_jinit_req (JINIT_REQ_INFO *info); +ST_VOID m_log_jread_resp (JREAD_RESP_INFO *info); +ST_VOID m_log_jread_req (JREAD_REQ_INFO *info); +ST_VOID m_log_jstat_resp (JSTAT_RESP_INFO *info); +ST_VOID m_log_jstat_req (JSTAT_REQ_INFO *info); +ST_VOID m_log_jwrite_req (JWRITE_REQ_INFO *info); +ST_VOID m_log_kill_req (KILL_REQ_INFO *info); +ST_VOID m_log_loaddom_req (LOADDOM_REQ_INFO *info); +ST_VOID m_log_namelist_resp (NAMELIST_RESP_INFO *info); +ST_VOID m_log_namelist_req (NAMELIST_REQ_INFO *info); +ST_VOID m_log_obtfile_req (OBTFILE_REQ_INFO *info); +ST_VOID m_log_output_req (OUTPUT_REQ_INFO *info); +ST_VOID m_log_rddwn_req (RDDWN_REQ_INFO *info); +ST_VOID m_log_rdupl_req (RDUPL_REQ_INFO *info); +ST_VOID m_log_read_resp (READ_RESP_INFO *info); +ST_VOID m_log_read_req (READ_REQ_INFO *info); +ST_VOID m_log_relctrl_req (RELCTRL_REQ_INFO *info); +ST_VOID m_log_rename_req (RENAME_REQ_INFO *info); +ST_VOID m_log_repeas_resp (REPEAS_RESP_INFO *info); +ST_VOID m_log_repeas_req (REPEAS_REQ_INFO *info); +ST_VOID m_log_repecs_resp (REPECS_RESP_INFO *info); +ST_VOID m_log_repecs_req (REPECS_REQ_INFO *info); +ST_VOID m_log_repees_resp (REPEES_RESP_INFO *info); +ST_VOID m_log_repees_req (REPEES_REQ_INFO *info); +ST_VOID m_log_reset_req (RESET_REQ_INFO *info); +ST_VOID m_log_resume_req (RESUME_REQ_INFO *info); +ST_VOID m_log_rsentry_resp (RSENTRY_RESP_INFO *info); +ST_VOID m_log_rsentry_req (RSENTRY_REQ_INFO *info); +ST_VOID m_log_rspool_resp (RSPOOL_RESP_INFO *info); +ST_VOID m_log_rspool_req (RSPOOL_REQ_INFO *info); +ST_VOID m_log_rsstat_resp (RSSTAT_RESP_INFO *info); +ST_VOID m_log_rsstat_req (RSSTAT_REQ_INFO *info); +ST_VOID m_log_start_req (START_REQ_INFO *info); +ST_VOID m_log_status_resp (STATUS_RESP_INFO *info); +ST_VOID m_log_status_req (STATUS_REQ_INFO *info); +ST_VOID m_log_stop_req (STOP_REQ_INFO *info); +ST_VOID m_log_storedom_req (STOREDOM_REQ_INFO *info); +ST_VOID m_log_takectrl_resp (TAKECTRL_RESP_INFO *info); +ST_VOID m_log_takectrl_req (TAKECTRL_REQ_INFO *info); +ST_VOID m_log_termdown_req (TERMDOWN_REQ_INFO *info); +ST_VOID m_log_termupl_req (TERMUPL_REQ_INFO *info); +ST_VOID m_log_trige_req (TRIGE_REQ_INFO *info); +ST_VOID m_log_upload_resp (UPLOAD_RESP_INFO *info); +ST_VOID m_log_upload_req (UPLOAD_REQ_INFO *info); +ST_VOID m_log_ustatus_req (USTATUS_REQ_INFO *info); +ST_VOID m_log_write_resp (WRITE_RESP_INFO *info); +ST_VOID m_log_write_req (WRITE_REQ_INFO *info); + +/* common component logging */ +ST_VOID m_log_app_ref (APP_REF *info); +ST_VOID m_log_asn1_app_ref (ST_UCHAR *buf_ptr, ST_INT buf_len); +ST_VOID m_log_modifier (MODIFIER *info); +ST_VOID m_log_tdl (ST_UCHAR *asn1, ST_INT asn1_len); + +ST_VOID m_log_error_info (ERR_INFO *err_ptr); +#if !defined(MMS_LITE) +ST_VOID m_log_err_info (MMSREQ_PEND *req_ptr); +#endif + +ST_VOID m_no_log_resp (ST_VOID *resp); +ST_VOID m_no_log_req (ST_VOID *req); + +/************************************************************************/ + +ST_VOID m_get_mms_err_text (ST_INT eclass, ST_INT code, + ST_CHAR *dest, ST_INT dest_len); + +ST_VOID m_get_mms_rej_text (ST_INT rclass, ST_INT code, + ST_CHAR *dest, ST_INT dest_len); + +ST_VOID m_log_reject_info (REJECT_RESP_INFO *rej_ptr); + +ST_VOID m_log_evtime (EVENT_TIME *info); +ST_VOID m_log_evt_tod (MMS_BTOD *info); +ST_VOID m_log_external (EXTERN_INFO *info); + +ST_VOID m_log_objname (OBJECT_NAME *info); +ST_VOID m_log_pi_state (ST_INT state); +ST_VOID m_log_address (VAR_ACC_ADDR *info); +ST_VOID m_log_var_list (VARIABLE_LIST *vl_ptr, ST_INT num_of_vars); +ST_VOID m_log_var_spec (VARIABLE_SPEC *info); +ST_VOID m_log_vaspec (VAR_ACC_SPEC *info); +ST_VOID m_log_data (ST_INT asn1_data_len, ST_UCHAR *asn1_data); + +/************************************************************************/ +/************************************************************************/ +#if defined(MMS_LITE) +/************************************************************************/ + +ST_RET ml_log_dec_rslt (MMSDEC_INFO *rslt); + +ST_VOID _ml_log_req_info (ST_INT invokeId, ST_INT op, ST_VOID *info); +ST_VOID _ml_log_ind_info (ST_INT invokeId, ST_INT op, ST_VOID *info); +ST_VOID _ml_log_resp_info (ST_INT invokeId, ST_INT op, ST_VOID *info); +ST_VOID _ml_log_conf_info (ST_INT invokeId, ST_INT op, ST_VOID *info); +ST_VOID _ml_log_unsol_req_info (ST_INT op, ST_VOID *info); +ST_VOID _ml_log_unsol_ind_info (ST_INT op, ST_VOID *info); +ST_VOID _ml_log_error_resp (ST_INT invokeId, ST_VOID *info); +ST_VOID _ml_log_error_conf (ST_INT invokeId, ST_VOID *info); +ST_VOID _ml_log_reject_send (ST_VOID *info); +ST_VOID _ml_log_reject_recv (ST_VOID *info); + + +/* MLOG integration */ +extern ST_VOID (*ml_log_req_info_fun) (ST_INT invokeId, ST_INT op, ST_VOID *info); +extern ST_VOID (*ml_log_ind_info_fun) (ST_INT invokeId, ST_INT op, ST_VOID *info); + +extern ST_VOID (*ml_log_resp_info_fun) (ST_INT invokeId, ST_INT op, ST_VOID *info); +extern ST_VOID (*ml_log_conf_info_fun) (ST_INT invokeId, ST_INT op, ST_VOID *info); + +extern ST_VOID (*ml_log_unsol_req_info_fun) (ST_INT op, ST_VOID *info); +extern ST_VOID (*ml_log_unsol_ind_info_fun) (ST_INT op, ST_VOID *info); + +extern ST_VOID (*ml_log_error_conf_fun) (ST_INT invokeId, ST_VOID *info); +extern ST_VOID (*ml_log_error_resp_fun) (ST_INT invokeId, ST_VOID *info); + +extern ST_VOID (*ml_log_reject_send_fun) (ST_VOID *info); +extern ST_VOID (*ml_log_reject_recv_fun) (ST_VOID *info); + +ST_VOID ml_mlog_install (ST_VOID); + +/************************************************************************/ +#endif /* MMS_LITE */ +/************************************************************************/ + +/************************************************************************/ +#if !defined(MMS_LITE) +/************************************************************************/ +ST_VOID m_log_ureq_info (ST_INT chan, ST_INT op, ST_VOID *info); +ST_VOID m_log_req_info (MMSREQ_PEND *req, ST_VOID *info); +ST_VOID m_log_resp_info (MMSREQ_IND *ind, ST_VOID *info); +ST_VOID m_log_ind_info (MMSREQ_IND *ind); +ST_VOID m_log_conf_info (MMSREQ_PEND *conf); +ST_VOID m_log_error_resp (MMSREQ_IND *ind, ST_INT16 eclass, ST_INT16 code); +ST_RET m_mlog_install (ST_VOID); +#endif + +/************************************************************************/ +/* Global variables. */ +/************************************************************************/ +extern SXD_ARB_DATA_CTRL mlog_arb_log_ctrl; + +/************************************************************************/ +#ifdef __cplusplus +} +#endif +/************************************************************************/ + + +#endif /* MLOGUSER_INCLUDED */ + diff --git a/include/inc/mms_def2.h b/include/inc/mms_def2.h new file mode 100644 index 0000000..c29ab15 --- /dev/null +++ b/include/inc/mms_def2.h @@ -0,0 +1,308 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_def2.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains miscellaneous definitions and variables. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/12/07 MDE 11 Added MMSOP_RD_USR_HANDLED, etc.. */ +/* 04/24/03 JRB 10 Increase MAX_IDENT_LEN from 32 to 64. */ +/* 07/09/02 MDE 09 Fixed up opcode defines */ +/* 02/24/00 DSF 08 Bumped up MAX_FILES_OPEN to 100 */ +/* 10/06/99 GLB 07 Added file Rename and Obtain File */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 04/14/98 JRB 05 Del MPARAM* defs. Still needed in mmsop_en.h */ +/* 04/03/98 JRB 04 Add check for obsolete version of mmsop_en.h */ +/* 03/20/98 JRB 03 Move defs from "mmsop_en.h" to here. */ +/* 08/15/97 MDE 02 Added xxx_DATA_SUPPORT defines, cleanup */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_DEF2_INCLUDED +#define MMS_DEF2_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (REQ_RESP_DIS) || defined (MAX_MMS_OPCODE) +#error May have obsolete version of "mmsop_en.h". See Release Notes. +#endif + +/************************************************************************/ +/************************************************************************/ +/* define the operation enable switches used by "mmsop_en.h" */ +/************************************************************************/ +#define REQ_RESP_DIS 0x00 /* no support for req or resp */ +#define REQ_EN 0x01 /* support for request */ +#define RESP_EN 0x02 /* support for response */ +#define REQ_RESP_EN 0x03 /* support for resp and req */ + +/************************************************************************/ +/************************************************************************/ +/* The following character array is used to check if a MMS operation is */ +/* to be supported as requestor and/or responder, and whether to expect */ +/* a constructor or primitive after the invoke ID. The operation opcode */ +/* is used as an index into the table. */ +/************************************************************************/ + +#define MAX_MMS_OPCODE 77 /* highest MMS opcode */ +#define MAX_MMSOP_DIS 85 /* highest mmsop_en[] entry */ + +extern SD_CONST ST_UCHAR mmsop_en [MAX_MMSOP_DIS+1]; + +/************************************************************************/ +/************************************************************************/ +/* The following array is used to print the opcode description. The */ +/* operation opcode is used as an index into the table. */ +/************************************************************************/ + +extern ST_CHAR *mms_op_string[106]; +extern ST_INT m_num_mms_op_string; + +/************************************************************************/ +/************************************************************************/ +/* Define the MMS operation opcodes */ +/************************************************************************/ +#define MMSOP_STATUS 0 /* status */ +#define MMSOP_GET_NAMLIST 1 /* get name list */ +#define MMSOP_IDENTIFY 2 /* identify */ +#define MMSOP_RENAME 3 /* rename */ +#define MMSOP_READ 4 /* read */ +#define MMSOP_WRITE 5 /* write */ +#define MMSOP_GET_VAR 6 /* get variable name definition */ +#define MMSOP_DEF_VAR 7 /* define variable name */ +#define MMSOP_DEF_SCAT 8 /* define scattered access */ +#define MMSOP_GET_SCAT 9 /* get scattered access attributes */ +#define MMSOP_DEL_VAR 10 /* delete variable name definition */ +#define MMSOP_DEF_VLIST 11 /* define named variable list */ +#define MMSOP_GET_VLIST 12 /* get named variable list */ +#define MMSOP_DEL_VLIST 13 /* delete named variable list */ +#define MMSOP_DEF_TYPE 14 /* define type name */ +#define MMSOP_GET_TYPE 15 /* get type name definition */ +#define MMSOP_DEL_TYPE 16 /* delete type name */ + +#define MMSOP_INPUT 17 /* input */ +#define MMSOP_OUTPUT 18 /* output */ + +#define MMSOP_TAKE_CONTROL 19 /* take control */ +#define MMSOP_REL_CONTROL 20 /* relinquish control */ +#define MMSOP_DEFINE_SEM 21 /* define semaphore */ +#define MMSOP_DELETE_SEM 22 /* delete semaphore */ +#define MMSOP_REP_SEMSTAT 23 /* report semaphore status */ +#define MMSOP_REP_SEMPOOL 24 /* report semaphore pool status */ +#define MMSOP_REP_SEMENTRY 25 /* report semaphore entry status */ + +#define MMSOP_INIT_DOWNLOAD 26 /* initiate download sequence */ +#define MMSOP_DOWN_LOAD 27 /* download segment */ +#define MMSOP_TERM_DOWNLOAD 28 /* terminate download sequence */ +#define MMSOP_INIT_UPLOAD 29 /* initiate upload sequence */ +#define MMSOP_UP_LOAD 30 /* upload segment */ +#define MMSOP_TERM_UPLOAD 31 /* terminate upload sequence */ +#define MMSOP_REQ_DOM_DOWN 32 /* request domain download */ +#define MMSOP_REQ_DOM_UPL 33 /* request domain upload */ +#define MMSOP_LOAD_DOMAIN 34 /* load domain content */ +#define MMSOP_STORE_DOMAIN 35 /* store domain content */ +#define MMSOP_DELETE_DOMAIN 36 /* delete domain */ +#define MMSOP_GET_DOM_ATTR 37 /* get domain attribute */ + +#define MMSOP_CREATE_PI 38 /* create program invocation */ +#define MMSOP_DELETE_PI 39 /* delete program invocation */ +#define MMSOP_START 40 /* start */ +#define MMSOP_STOP 41 /* stop */ +#define MMSOP_RESUME 42 /* resume */ +#define MMSOP_RESET 43 /* reset */ +#define MMSOP_KILL 44 /* kill */ +#define MMSOP_GET_PI_ATTR 45 /* get program invocation attribute */ + +#define MMSOP_OBTAIN_FILE 46 /* obtain file */ + +#define MMSOP_DEF_EC 47 /* define event condition */ +#define MMSOP_DEL_EC 48 /* delete event condition */ +#define MMSOP_GET_EC_ATTR 49 /* get event condition attributes */ +#define MMSOP_REP_EC_STAT 50 /* report event condition status */ +#define MMSOP_ALT_EC_MON 51 /* alter event condition monitoring */ +#define MMSOP_TRIGGER_EV 52 /* trigger event */ +#define MMSOP_DEF_EA 53 /* define event action status */ +#define MMSOP_DEL_EA 54 /* delete event action */ +#define MMSOP_GET_EA_ATTR 55 /* get event action attributes */ +#define MMSOP_REP_EA_STAT 56 /* report event action status */ +#define MMSOP_DEF_EE 57 /* define event enrollment */ +#define MMSOP_DEL_EE 58 /* delete event enrollment */ +#define MMSOP_ALT_EE 59 /* alter event enrollment */ +#define MMSOP_REP_EE_STAT 60 /* report event enrollment status */ +#define MMSOP_GET_EE_ATTR 61 /* get event enrollment attributes */ +#define MMSOP_ACK_EVENT_NOT 62 /* acknowledge event notification */ +#define MMSOP_GET_ALARM_SUM 63 /* get alarm summary */ +#define MMSOP_GET_ALARM_ESUM 64 /* get alarm enrollment summary */ + +#define MMSOP_READ_JOURNAL 65 /* read journal */ +#define MMSOP_WRITE_JOURNAL 66 /* write journal */ +#define MMSOP_INIT_JOURNAL 67 /* initialize journal */ +#define MMSOP_STAT_JOURNAL 68 /* report journal status */ +#define MMSOP_CREATE_JOURNAL 69 /* create journal */ +#define MMSOP_DELETE_JOURNAL 70 /* delete journal */ + +#define MMSOP_GET_CAP_LIST 71 /* get capability list */ + +#define MMSOP_FILE_OPEN 72 /* file open */ +#define MMSOP_FILE_READ 73 /* file read */ +#define MMSOP_FILE_CLOSE 74 /* file close */ +#define MMSOP_FILE_RENAME 75 /* file rename */ +#define MMSOP_FILE_DELETE 76 /* file delete */ +#define MMSOP_FILE_DIR 77 /* file directory */ + + +/************************************************************************/ +/* The opcodes below are reserved for the unconfirmed services and are */ +/* NOT used on the wire. */ +/************************************************************************/ +#define MMSOP_USTATUS 78 /* unsolicited status, ucs 1 */ +#define MMSOP_INFO_RPT 79 /* information report, ucs 0 */ +#define MMSOP_EVENT_NOT 80 /* unsolicited status, ucs 2 */ + + +/************************************************************************/ +/* These are not really opcodes at all, but simply represent the bit */ +/* positions in the services supported bitstring */ + +#define _MMSOP_ATTACH_TO_EC 81 /* Attach to event condition */ +#define _MMSOP_ATTACH_TO_SEM 82 /* Attach to semaphore */ + +/************************************************************************/ +/* These opcodes are reserved for Initiate, Conclude, etc. and are */ +/* NOT used on the wire, since these operations do not take op codes. */ +/************************************************************************/ + +#define MMSOP_CONCLUDE 83 /* conclude */ +#define MMSOP_CANCEL 84 /* cancel */ + + +/************************************************************************/ +/* MVLU Internal Use */ +#define MMSOP_MVLU_RPT_VA 200 +#define MMSOP_MVLU_GOOSE_UPDATE 201 +#define MMSOP_RD_USR_HANDLED 202 + +/************************************************************************/ +/* The opcodes below are NOT used on the wire, only for completed */ +/* 'Macro' function complete flags. */ +/************************************************************************/ +#define MMSOP_INITIATE 85 /* initiate operation */ + +#define MMSOP_NAMED_READ 90 /* Named Read */ +#define MMSOP_NAMED_WRITE 91 /* Named Write */ +#define MMSOP_REM_FILE_OPEN 93 /* Remote File Open */ +#define MMSOP_REM_FILE_READ 94 /* Remote File Read */ +#define MMSOP_REM_FILE_CLOSE 95 /* Remote File Close */ +#define MMSOP_INIT_CONN 96 /* Initiate */ +#define MMSOP_REM_FILE_COPY 98 /* Remote file copy */ +#define MMSOP_MV_DOWNLOAD 99 /* VM Domain Download */ +#define MMSOP_MV_UPLOAD 100 /* VM Domain Upload */ +#define MMSOP_VM_VAR_READ 101 /* Var Read */ +#define MMSOP_VM_VAR_WRITE 102 /* Var Write */ + +/************************************************************************/ +/************************************************************************/ +/* Various MMS limitations, parameters, etc. */ +/************************************************************************/ + +#define SERVICE_RESP_SIZE 11 /* BYTE size of service resp array */ + +#define MAX_FILES_OPEN 100 /* maximum files open locally/remotely */ +#define MAX_FILE_NAME 255 /* maximum length of a file pathname */ +#define MAX_IDENT_LEN 64 /* length of an Identifier variable */ +#define MAX_AR_LEN 64 /* length of a AR name */ + +/************************************************************************/ +/************************************************************************/ +/* This structure is used to support modifier handling. */ +/************************************************************************/ + +struct list_of_mods + { + ST_BOOLEAN info_pres; /* must be set to get info encoded */ + ST_INT num_of_mods; /* tells how many mods in the list */ + struct modifier *mod_list_ptr;/* ptr to array of contiguous modifiers */ + }; +typedef struct list_of_mods LIST_OF_MODS; + +extern struct list_of_mods modifier_list; +extern ST_INT m_max_mods; + +/************************************************************************/ +/************************************************************************/ +/* COMPANION STANDARD HANDLING */ +/************************************************************************/ +/* This structure is used as a global input parameter to all MMS */ +/* requests and responses sent by the application. To send CS info, the */ +/* 'cs_pres' flag must be set SD_TRUE, the other components refer to the*/ +/* ASN.1 CS INFO to be sent. 'cs_pres' is reset after being used. */ +/************************************************************************/ + + +struct csi + { + ST_BOOLEAN cs_pres; /* SD_TRUE if CS info was received */ + ST_INT cs_len; /* length of ASN.1 */ + ST_UCHAR *cs_ptr; /* pointer to ASN.1 */ + }; +typedef struct csi CSI ; + +extern struct csi cs_send; /* SEND CS info structure */ + +/************************************************************************/ +/************************************************************************/ +/* These defines can be commented out to exclude support for some data */ +/* types if they are not required. */ + +#ifndef MMS_LITE +#define FLOAT_DATA_SUPPORT +#define TIME_DATA_SUPPORT +#define BTOD_DATA_SUPPORT +#else +#define FLOAT_DATA_SUPPORT +#define TIME_DATA_SUPPORT +#define BTOD_DATA_SUPPORT +#endif + +/************************************************************************/ +/************************************************************************/ +/* These defines are the values that the domain state attribute */ +/* named_dom_ctrl.state can take on. */ +/************************************************************************/ + +#define DOM_NON_EXISTENT 0 +#define DOM_LOADING 1 +#define DOM_READY 2 +#define DOM_IN_USE 3 +#define DOM_COMPLETE 4 +#define DOM_INCOMPLETE 5 + +#define DOM_D1 7 +#define DOM_D2 8 +#define DOM_D3 9 +#define DOM_D4 10 +#define DOM_D5 11 +#define DOM_D6 12 +#define DOM_D7 13 +#define DOM_D8 14 +#define DOM_D9 15 + +#ifdef __cplusplus +} +#endif + +#endif /* MMS_DEF2_INCLUDED */ + + diff --git a/include/inc/mms_dfun.h b/include/inc/mms_dfun.h new file mode 100644 index 0000000..b5c0a78 --- /dev/null +++ b/include/inc/mms_dfun.h @@ -0,0 +1,212 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_dfun.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the function declarations required to interface */ +/* with the primitive level decode routines. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 01 Convert to use ASN1R. */ +/* Add mms_err_invoke_fun proto. */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_DFUN_INCLUDED +#define MMS_DFUN_INCLUDED + +#include "asn1r.h" /* need ASN1_DEC_CTXT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/************************************************************************/ +/* MMS service decode functions */ +/************************************************************************/ + +ST_VOID mms_reject (ASN1_DEC_CTXT *ac, ST_UINT16 id_code); +ST_VOID mms_err_invoke_fun (ASN1_DEC_CTXT *aCtx, ST_UINT16); +ST_VOID mms_status_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_status_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_status (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_ustatus_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_namelist_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_namelist_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_identify_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_identify_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rename_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_getcl_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_getcl_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_init_download_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_init_download_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_download_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_download_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_term_download_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_term_download_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_init_upload_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_init_upload_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_upload_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_upload_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_term_upload_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_term_upload_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rddwn_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rddwn_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rdupl_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rdupl_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_load_domain_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_load_domain_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_store_domain_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_store_domain_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delete_domain_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delete_domain_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_dom_attr_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_dom_attr_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_create_pi_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_create_pi_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delete_pi_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delete_pi_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_start_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_stop_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_stop_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_resume_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_resume_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_reset_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_reset_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_kill_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_kill_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_pi_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_pi_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_read_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_read_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_write_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_write_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_info_rpt_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_var_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_var_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_def_var_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_def_var_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_del_var_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_del_var_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_def_scat_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_scat_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_scat_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_def_vlist_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_vlist_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_vlist_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_del_vlist_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_del_vlist_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_type_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_type_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_def_type_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_def_type_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_del_type_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_del_type_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_takectrl_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_takectrl_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_relctrl_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_relctrl_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rsstat_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rsstat_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rspool_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rspool_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rsentry_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rsentry_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_defsem_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_defsem_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delsem_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delsem_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_output_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_output_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_input_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_input_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_defec_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delec_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delec_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_geteca_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_geteca_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_repecs_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_repecs_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_altecm_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_trige_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_defea_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delea_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delea_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_geteaa_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_geteaa_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_repeas_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_repeas_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_defee_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delee_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delee_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_altee_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_altee_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_repees_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_repees_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_geteea_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_geteea_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_evnot_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_ackevnot_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_ackevnot_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_getas_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_getas_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_getaes_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_getaes_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_jwrite_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jwrite_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jread_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jread_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jinit_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jinit_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jstat_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jstat_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jcreate_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jdelete_req (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_obtain_file_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_obtain_file_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_open_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_open_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_read_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_read_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_close_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_close_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_rename_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_rename_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_delete_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_delete_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_dir_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_dir_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_conclude_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_conclude_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_cancel_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_cancel_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_init_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_init_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_rsp_not_supp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_req_not_supp (ASN1_DEC_CTXT *aCtx); +ST_VOID _mms_null_pdu_dec (ASN1_DEC_CTXT *aCtx); + +#ifdef __cplusplus +} +#endif + +#endif /* MMS_DFUN_INCLUDED */ diff --git a/include/inc/mms_err.h b/include/inc/mms_err.h new file mode 100644 index 0000000..38f8bc8 --- /dev/null +++ b/include/inc/mms_err.h @@ -0,0 +1,213 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_err.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains structure & function definitions used for */ +/* decoding and encoding an error response. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/03/06 CRM 03 Add MMS_ERRCLASS_* and MMS_ERRCODE_*. */ +/* 12/20/01 JRB 02 Convert to use ASN1R. */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_ERR_INCLUDED +#define MMS_ERR_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_mp.h" + +/************************************************************************/ +/* MMS Error Codes: */ +/************************************************************************/ + +#define MMS_ERRCODE_OTHER 0 /* same for all classes */ + +/* Defines for "VMD State" error class. */ +#define MMS_ERRCLASS_VMD_STATE 0 +#define MMS_ERRCODE_VMD_STATE_CONFLICT 1 +#define MMS_ERRCODE_VMD_OPERATIONAL_PROBLEM 2 +#define MMS_ERRCODE_DOMAIN_TRANSFER_PROBLEM 3 +#define MMS_ERRCODE_STATE_MACHINE_ID_INVALID 4 + +/* Defines for "Application Reference" error class.*/ +#define MMS_ERRCLASS_APP_REF 1 +#define MMS_ERRCODE_APP_UNREACHABLE 1 +#define MMS_ERRCODE_CONNECTION_LOST 2 +#define MMS_ERRCODE_APP_REF_INVALID 3 +#define MMS_ERRCODE_CONTEXT_UNSUPPORTED 4 + +/* Defines for "Definition" error class. */ +#define MMS_ERRCLASS_DEFINITION 2 +#define MMS_ERRCODE_OBJ_UNDEFINED 1 +#define MMS_ERRCODE_INVALID_ADDRESS 2 +#define MMS_ERRCODE_TYPE_UNSUPPORTED 3 +#define MMS_ERRCODE_TYPE_INCONSISTENT 4 +#define MMS_ERRCODE_OBJ_EXISTS 5 +#define MMS_ERRCODE_OBJ_ATTRIBUTE_INCONSISTENT 6 + +/* Defines for "Resource" error class. */ +#define MMS_ERRCLASS_RESOURCE 3 +#define MMS_ERRCODE_MEM_UNAVAILABLE 1 +#define MMS_ERRCODE_PROCESSOR_RESOURCE_UNAVAILABLE 2 +#define MMS_ERRCODE_MASS_STORAGE_UNAVAILABLE 3 +#define MMS_ERRCODE_CAPABILITY_UNAVAILABLE 4 +#define MMS_ERRCODE_CAPABILITY_UNKOWN 5 + +/* Defines for "Service" error class. */ +#define MMS_ERRCLASS_SERVICE 4 +#define MMS_ERRCODE_PRIMITIVES_OUT_OF_SEQ 1 +#define MMS_ERRCODE_OBJ_STATE_CONFLICT 2 +/* Value 3 reserved for further definition */ +#define MMS_ERRCODE_CONTINUATION_INVALID 4 +#define MMS_ERRCODE_OBJ_CONSTRAINT_CONFLICT 5 + +/* Defines for "Service Preempt" error class. */ +#define MMS_ERRCLASS_SERVICE_PREEMPT 5 +#define MMS_ERRCODE_TIMEOUT 1 +#define MMS_ERRCODE_DEADLOCK 2 +#define MMS_ERRCODE_CANCEL 3 + +/* Defines for "Time Resolution" error class. */ +#define MMS_ERRCLASS_TIME_RESOLUTION 6 +#define MMS_ERRCODE_UNSUPPORTABLE_TIME_RESOLUTION 1 + +/* Defines for "Access" error class. */ +#define MMS_ERRCLASS_ACCESS 7 +#define MMS_ERRCODE_OBJ_ACCESS_UNSUPPORTED 1 +#define MMS_ERRCODE_OBJ_NON_EXISTENT 2 +#define MMS_ERRCODE_OBJ_ACCESS_DENIED 3 +#define MMS_ERRCODE_OBJ_INVALIDATED 4 + +/* Defines for "Initiate" error class. */ +#define MMS_ERRCLASS_INITIATE 8 +/* Value 1 reserved for further definition */ +/* Value 2 reserved for further definition */ +#define MMS_ERRCODE_MAX_SRV_OUTSTD_CALLING_INSUFF 3 +#define MMS_ERRCODE_MAX_SRV_OUTSTD_CALLED_INSUFF 4 +#define MMS_ERRCODE_SERVICE_CBB_INSUFF 5 +#define MMS_ERRCODE_PARAM_CBB_INSUFF 6 +#define MMS_ERRCODE_NESTING_LEVEL_INSUFF 7 + +/* Defines for "Conclude" error class. */ +#define MMS_ERRCLASS_CONCLUDE 9 +#define MMS_ERRCODE_FURTHER_COMM_REQUIRED 1 + +/* Defines for "Cancel" error class. */ +#define MMS_ERRCLASS_CANCEL 10 +#define MMS_ERRCODE_INVOKE_ID_UNKNOWN 1 +#define MMS_ERRCODE_CANCEL_NOT_POSSIBLE 2 + +/* Defines for "File" error class. */ +#define MMS_ERRCLASS_FILE 11 +#define MMS_ERRCODE_FILENAME_AMBIGUOUS 1 +#define MMS_ERRCODE_FILE_BUSY 2 +#define MMS_ERRCODE_FILENAME_SYNTAX_ERROR 3 +#define MMS_ERRCODE_CONTENT_TYPE_INVALID 4 +#define MMS_ERRCODE_POSITION_INVALID 5 +#define MMS_ERRCODE_FILE_ACCESS_DENIED 6 +#define MMS_ERRCODE_FILE_NON_EXISTENT 7 +#define MMS_ERRCODE_DUPLICATE_FILENAME 8 +#define MMS_ERRCODE_INSUFF_SPACE_IN_FILESTORE 9 + +/************************************************************************/ +/* Additional Error Response Information - */ +/* This information is set whenever there is optional additional */ +/* error response information. */ +/************************************************************************/ + +struct adtnl_err_resp_info + { + ST_BOOLEAN mod_pos_pres;/* Confirmed-ErrorPDU only: modifier pos pres */ + ST_INT32 mod_pos; /* Confirmed-ErrorPDU only: modifier position */ + ST_BOOLEAN info_pres; /* global additional info present indicator */ + ST_BOOLEAN code_pres; /* additional code present indicator */ + ST_INT32 code; /* additional code */ + ST_BOOLEAN descr_pres;/* additional description present indicator */ + ST_CHAR *descr; /* pointer to the additional description */ + ST_BOOLEAN ssi_pres; /* service specific info present indicator */ + ST_INT16 service; /* number indicating the service (0-10) */ + ST_UINT32 ss_error_val; /* service specific error value, when service */ + /* is 0-7, or 9 (IS) */ + /* service specific object name, when service */ + /* is 8 (IS-Define Event Enrollment) */ + OBJECT_NAME ss_error_oname; + /* service specific additional service error, */ + /* when service is 10 (IS-Companion Standard) */ + ST_INT ss_error_len; /* service specific additional service length */ + ST_UCHAR *ss_error_data;/* service specific additional service data ptr */ + }; +typedef struct adtnl_err_resp_info ADTNL_ERR_RESP_INFO; + + +/************************************************************************/ +/* RECEIVED ERROR RESPONSE INFORMATION */ +/************************************************************************/ +/* The structure below is filled in when an error message is received, */ +/* before the u_xxxx_conf function is invoked. */ +/************************************************************************/ + +struct err_info + { + ST_INT16 eclass; /* error class */ + ST_INT16 code; /* error code */ + ADTNL_ERR_RESP_INFO adtnl; /* additional error information */ + }; +typedef struct err_info ERR_INFO; + +/************************************************************************/ +/* Error Response Decode Function - */ +/* This routine is called to decode an error response PDU. */ +/************************************************************************/ + +ST_VOID mms_err_rsp (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/* SEND ERROR RESPONSE INFORMATION */ +/************************************************************************/ +/* The structure below is filled in when an error response is to be */ +/* sent that includes the optional additional error information. */ +/* Note : this information must be set prior to issuing the call to */ +/* mp_err_resp, if it is to be included in the response. */ +/************************************************************************/ + +extern ADTNL_ERR_RESP_INFO adtnl_err_info; + +/************************************************************************/ +/* Error Response Encode & Send Functions - */ +/* These routines are called to build and send error response PDU's, */ +/* one for the case of a Cancel indication, the other for all other */ +/* cases. The parameters are : a pointer to the request information, */ +/* the error class, and the error code. */ +/************************************************************************/ + +#ifndef MMS_LITE +ST_RET mp_err_resp (MMSREQ_IND *ind, ST_INT16 err_class, ST_INT16 code); +ST_RET mp_init_err (MMSREQ_IND *ind, ST_INT16 err_class, ST_INT16 code); +ST_RET mp_conclude_err (MMSREQ_IND *ind, ST_INT16 err_class, ST_INT16 code); +ST_RET mp_cancel_err (MMSREQ_IND *ind, ST_INT16 err_class, ST_INT16 code); +#else +ST_RET mpl_err_resp (ST_INT op, ST_UINT32 invoke, ST_INT16 err_class, ST_INT16 code); +ST_RET mpl_init_err (ST_INT16 err_class, ST_INT16 code); +ST_RET mpl_conclude_err (ST_INT16 err_class, ST_INT16 code); +ST_RET mpl_cancel_err (ST_UINT32 invoke, ST_INT16 err_class, ST_INT16 code); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MMS_ERR_INCLUDED */ diff --git a/include/inc/mms_log.h b/include/inc/mms_log.h new file mode 100644 index 0000000..7260b0e --- /dev/null +++ b/include/inc/mms_log.h @@ -0,0 +1,109 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2003, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_log.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains MMS-EASE logging definitions */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/04/03 EJV 04 Chg mms_debug_sel to ST_UINT, and deleted */ +/* L suffix from MMS_LOG_... masks. */ +/* 03/15/01 JRB 03 Added user_debug_sel to control USER logging.*/ +/* 10/08/98 MDE 02 Migrated to updated SLOG interface */ +/* 06/09/97 MDE 01 Added 2 new Log macros */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_LOG_INCLUDED +#define MMS_LOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ + +#include "slog.h" + +/************************************************************************/ +/* mms_debug_sel bit assignments */ +#define MMS_LOG_DEC 0x00000001 +#define MMS_LOG_ENC 0x00000002 +#define MMS_LOG_ACSE 0x00000004 +#define MMS_LOG_LLC 0x00000008 +#define MMS_LOG_IQUE 0x00000010 +#define MMS_LOG_RQUE 0x00000020 + +/* Keep the next two reserved for the user (not used internally) */ +#define MMS_LOG_USR_IND 0x00000040 +#define MMS_LOG_USR_CONF 0x00000080 + +#define MMS_LOG_VM 0x00000100 +#define MMS_LOG_DATA 0x00000200 + +/* Defines used for selecting MMSEASE que servicing debug levels. */ +#define MMSREQQUE_HOLD 0x00004000 +#define MMSINDQUE_HOLD 0x00008000 + +#define MMS_LOG_ERR 0x00010000 +#define MMS_LOG_NERR 0x00020000 +#define MMS_LOG_PDU 0x00040000 +#define MMS_LOG_CONFIG 0x00080000 + +#define MMS_LOG_RT 0x00100000 +#define MMS_LOG_RTAA 0x00200000 +#define MMS_LOG_AA 0x00400000 + +#define MMS_LOG_REQ 0x01000000 +#define MMS_LOG_RESP 0x02000000 +#define MMS_LOG_IND 0x04000000 +#define MMS_LOG_CONF 0x08000000 + +/************************************************************************/ +/* These are S_LOG control items for MMS-EASE logging */ + +extern ST_UINT mms_debug_sel; + +/************************************************************************/ +/* user_debug_sel bit assignments */ +#define USER_LOG_ERR 0x00000001 +#define USER_LOG_CLIENT 0x00000002 +#define USER_LOG_SERVER 0x00000004 + +extern ST_UINT user_debug_sel; /* global var to control USER logging */ + +/************************************************************************/ +/* User selectable function to log MMS actions (MLOG, for instance) */ + +#ifndef MMS_LITE +extern ST_VOID (*m_log_ureq_info_fun) (ST_INT chan, ST_INT op, ST_VOID *info); +extern ST_VOID (*m_log_req_info_fun) (MMSREQ_PEND *req, ST_VOID *info); +extern ST_VOID (*m_log_resp_info_fun) (MMSREQ_IND *ind, ST_VOID *info); +extern ST_VOID (*m_log_ind_info_fun) (MMSREQ_IND *ind); +extern ST_VOID (*m_log_conf_info_fun) (MMSREQ_PEND *conf); +extern ST_VOID (*m_log_error_resp_fun) (MMSREQ_IND *ind, ST_INT16 err_class, ST_INT16 code); +#endif + +/************************************************************************/ +/* Some SLOG Logging control macros */ + +#define MLOG_CLOSE_FILE() {slogCloseFile (sLogCtrl);} +#define MLOG_DUMP_MEM_LOG() {slogDumpMem (sLogCtrl);} +#define MLOG_STOP_FILE_LOGGING() {sLogCtrl->logCtrl &= ~LOG_FILE_EN;} +#define MLOG_START_FILE_LOGGING() {sLogCtrl->logCtrl |= LOG_FILE_EN;} + +#ifdef __cplusplus +} +#endif + +/************************************************************************/ +#endif /* End of MMS_LOG_INCLUDED */ +/************************************************************************/ diff --git a/include/inc/mms_mp.h b/include/inc/mms_mp.h new file mode 100644 index 0000000..26d2682 --- /dev/null +++ b/include/inc/mms_mp.h @@ -0,0 +1,234 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_mp.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the common data structures and general function */ +/* declarations required to interface with MMS at the primitive */ +/* level. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 05 Convert to use ASN1R. */ +/* 08/15/97 MDE 04 BTOD handling changes */ +/* 08/14/97 RKR 03 Format changes */ +/* 06/11/97 RKR 02 Added constants for EXTERNAL encoding tag */ +/* 06/09/97 MDE 01 MMS-LITE define changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_MP_INCLUDED +#define MMS_MP_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "asn1defs.h" +#ifndef MMS_LITE +#include "mms_defs.h" +#endif + +/************************************************************************/ +/* MMS-LITE specific defines */ + +#if defined(MMS_LITE) +/* For MMS-LITE, we will use 'lite' versions of some data structures */ +#define USE_COMPACT_MMS_STRUCTS + +/* For MMS-LITE, we will supply a single static decode info buffer */ +#define M_USR_DEC_BUF +#endif + +/************************************************************************/ +/* Common default values for priority and severity */ +/************************************************************************/ + +#define MMS_NORM_PRIORITY 64 +#define MMS_NORM_SEVERITY 64 + +/************************************************************************/ +/* Object Name - This structure is used to reference MMS objects */ +/************************************************************************/ + +/* These defines may be used for the object_tag element selector */ +#define VMD_SPEC 0 +#define DOM_SPEC 1 +#define AA_SPEC 2 + +#if !defined (USE_COMPACT_MMS_STRUCTS) + +/* Standard form of object name */ +struct object_name + { + ST_INT object_tag; /* See above for legal values */ + union + { + ST_CHAR vmd_spec [MAX_IDENT_LEN+1]; /* vmd specific identifier */ + ST_CHAR item_id [MAX_IDENT_LEN+1]; /* item identifier */ + ST_CHAR aa_spec [MAX_IDENT_LEN+1]; /* aa specific identifier */ + } obj_name; + ST_CHAR domain_id [MAX_IDENT_LEN+1]; /* domain identifier */ + SD_END_STRUCT + }; + +#else /* Use compact form */ + +/* Compact form of object name */ +struct object_name + { + ST_INT object_tag; /* See above for legal values */ + union + { + ST_CHAR *vmd_spec; /* vmd specific identifier */ + ST_CHAR *item_id; /* item identifier */ + ST_CHAR *aa_spec; /* aa specific identifier */ + } obj_name; + ST_CHAR *domain_id; /* domain identifier */ + SD_END_STRUCT + }; +#endif + +typedef struct object_name OBJECT_NAME; + + +/************************************************************************/ +/* timeofday, event_time, attach_to_evcon, attach_to_semaphore and */ +/* modifier structure definitions. */ +/************************************************************************/ + +struct event_time + { + ST_INT16 evtime_tag; /* event time tag */ + /* 0: time of day */ + /* 1: time sequence identifier */ + /* 2: undefined */ + union + { + MMS_BTOD time_of_day; /* time of day */ + ST_UINT32 time_seq_id; /* time sequence identifier */ + } evtime; + }; +typedef struct event_time EVENT_TIME; + +struct attach_to_evcon + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + OBJECT_NAME evcon_name; /* event condition name */ + ST_UCHAR causing_transitions; /* causing transitions: */ + /* bitstring */ + /* 0 : idle to disabled */ + /* 1 : active to disabled */ + /* 2 : disabled to idle */ + /* 3 : active to idle */ + /* 4 : disabled to active */ + /* 5 : idle to active */ + /* 6 : any to deleted */ + ST_BOOLEAN acc_delay_pres; /* acceptable delay present */ + ST_UINT32 acc_delay; /* acceptable delay */ + SD_END_STRUCT + }; +typedef struct attach_to_evcon ATTACH_TO_EVCON; + +struct attach_to_semaphore + { + OBJECT_NAME sem_name; /* semaphore name */ + ST_BOOLEAN named_token_pres; /* named token present ind */ + ST_CHAR named_token[MAX_IDENT_LEN+1];/* named token */ + ST_UCHAR priority; /* priority */ + /* 0 - highest */ + /* 64 - normal (default) */ + /* 127 - lowest */ + ST_BOOLEAN acc_delay_pres; /* acceptable delay present */ + ST_UINT32 acc_delay; /* acceptable delay */ + ST_BOOLEAN ctrl_timeout_pres; /* control timeout present */ + ST_UINT32 ctrl_timeout; /* control timeout */ + ST_BOOLEAN abrt_on_timeout_pres; /* Abort On Timeout present */ + ST_BOOLEAN abrt_on_timeout; /* Abort On Timeout */ + ST_BOOLEAN rel_conn_lost; /* relinquish if connection */ + SD_END_STRUCT + }; /* lost (default = true) */ +typedef struct attach_to_semaphore ATTACH_TO_SEMAPHORE; + +struct modifier + { + ST_INT modifier_tag; /* modifier tag */ + /* 0:attach to event condition */ + /* 1:attach to semaphore */ + union + { + ATTACH_TO_EVCON atec; /* attach to event condition */ + ATTACH_TO_SEMAPHORE atsem; /* attach to semaphore */ + } mod; + SD_END_STRUCT + }; +typedef struct modifier MODIFIER; + +/************************************************************************/ +/* File Name */ +/************************************************************************/ + +struct file_name + { + ST_INT fn_len; /* The length of the string */ + ST_CHAR *fname; /* pointer to actual filename string */ + SD_END_STRUCT + }; +typedef struct file_name FILE_NAME; + +/************************************************************************/ +/* Values for the encoding_tag of an EXTERN_INFO */ +/************************************************************************/ + +#define M_EXT_TAG_ANY 0 +#define M_EXT_TAG_OCT_ALIGNED 1 +#define M_EXT_TAG_ARB 2 + +/************************************************************************/ +/* EXTERNAL */ +/* The structure below is used to store ASN.1 type EXTERNAL in "C" */ +/* format. */ +/************************************************************************/ + +struct extern_info + { + ST_BOOLEAN dir_ref_pres; /* direct reference present */ + MMS_OBJ_ID dir_ref; + + ST_BOOLEAN indir_ref_pres; /* indirect reference present */ + ST_INT32 indir_ref; /* indirect reference value */ + + ST_BOOLEAN dv_descr_pres; /* data value descript pres */ + ST_INT dv_descr_len; /* data value descr. len */ + ST_UCHAR *dv_descr; /* data value descr. ptr */ + + ST_CHAR encoding_tag; /* type of encoding */ + ST_INT num_bits; /* for arbitrary only */ + ST_INT data_len; /* # bytes of data */ + ST_UCHAR *data_ptr; /* data pointer */ + SD_END_STRUCT + }; +typedef struct extern_info EXTERN_INFO; + + +ST_RET ms_encode_extern (EXTERN_INFO *src, + ST_UCHAR *asn1dest, ST_INT destlen, + ST_INT *len_out, ST_UCHAR **asn1_start_out); + +ST_RET ms_decode_extern (ST_UCHAR *asn1, ST_INT asn1len, EXTERN_INFO *dest); + +ST_VOID wr_external (ASN1_ENC_CTXT *aCtx, EXTERN_INFO *ext); + + +#ifdef __cplusplus +} +#endif + +#endif /* MMS_MP_INCLUDED */ diff --git a/include/inc/mms_pcon.h b/include/inc/mms_pcon.h new file mode 100644 index 0000000..4a8fb07 --- /dev/null +++ b/include/inc/mms_pcon.h @@ -0,0 +1,294 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pcon.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS context management services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/13/05 MDE 07 Added defines for reject class and code */ +/* 03/23/05 JRB 06 Include asn1r instead of suicacse because */ +/* APP_REF moved to asn1r. */ +/* 07/10/02 JRB 05 Clarify description of maxreq_calling/called.*/ +/* 12/10/97 MDE 04 Changed max_nest to ST_INT8 */ +/* 11/06/97 MDE 03 Added suicacse.h, use APP_REF typedef */ +/* 08/13/97 RKR 02 Format changes */ +/* 07/29/97 DSF 01 Moved APP_REF to SUIC */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PCON_INCLUDED +#define MMS_PCON_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_err.h" +#include "mms_mp.h" +#include "asn1r.h" /* need APP_REF */ + +/************************************************************************/ +/************************************************************************/ +/* CONTEXT MANAGEMENT SERVICES */ +/************************************************************************/ +/* The structures below are used to pass CONTEXT MANAGEMENT information */ +/* to/from the MMS primitives. */ +/************************************************************************/ + +/************************************************************************/ +/* INITIATE */ +/************************************************************************/ + +struct init_rslt + { + ST_BOOLEAN accept_context; /* SD_TRUE if not error */ + ST_BOOLEAN err_info_pres; /* error information available */ + ERR_INFO err; /* otherwise look here */ + }; +typedef struct init_rslt INIT_RSLT; + + +/* This structure is used for non-core MMS-EASE P-Context's. */ +/* It is attached to the primary initiate info structure as an array */ + +struct cs_init_info + { + ST_UINT p_context; /* P-Context for this init */ + ST_BOOLEAN local_detail_pres; /* flag if local_detail is present */ + ST_INT32 local_detail; /* local detail */ + ST_INT16 maxreq_calling; /* max outst. "ind" allowed at "calling" app*/ + /* DEBUG: chg name to max_ind_calling? */ + ST_INT16 maxreq_called; /* max outst. "ind" allowed at "called" app*/ + /* DEBUG: chg name to max_ind_called? */ + ST_BOOLEAN max_nest_pres; /* indicates if max_nest is present */ + ST_INT8 max_nest; /* maximum data nesting */ + ST_INT init_detail_len; /* init detail */ + ST_UCHAR *init_detail; /* this is an ASN.1 encoded sequence */ + INIT_RSLT rslt; + }; +typedef struct cs_init_info CS_INIT_INFO; + + +/* REQUEST & RESPONSE : */ + +struct init_info + { /* Proposed (req) / Negiotiated (resp) */ + ST_BOOLEAN mms_p_context_pres;/* MMS Core context used */ + ST_BOOLEAN max_segsize_pres; /* flag if max_segsize is present */ + ST_INT32 max_segsize; /* maximum segment size */ + ST_INT16 maxreq_calling; /* max outst. "ind" allowed at "calling" app*/ + /* DEBUG: chg name to max_ind_calling? */ + ST_INT16 maxreq_called; /* max outst. "ind" allowed at "called" app*/ + /* DEBUG: chg name to max_ind_called? */ + ST_BOOLEAN max_nest_pres; /* indicates if max_nest is present */ + ST_INT8 max_nest; /* maximum data nesting */ + ST_BOOLEAN mms_detail_pres; /* mms init detail enable */ + ST_INT16 version; /* version */ + ST_UCHAR param_supp[2]; /* parameter support options: bitstring */ + ST_UCHAR serv_supp[11]; /* service support options: bitstring */ + INIT_RSLT rslt; /* success/failure & error info */ + ST_INT num_cs_init; /* number of CS init info's attached */ + ST_INT core_position; /* Position for CORE CONTEXT in list */ + /* (0 = first, num_cs_init = last, etc. */ +/* followed by CS_INIT_INFO cs_init[num_cs_init] */ + SD_END_STRUCT + }; +typedef struct init_info INIT_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_init (ST_INT chan, ST_CHAR *partner, INIT_INFO *info_ptr); +ST_RET mp_init_resp (MMSREQ_IND *indptr, INIT_INFO *info); +#else +ST_RET mpl_init (INIT_INFO *info); +ST_RET mpl_cs_init (CS_INIT_INFO *info); +ST_RET mpl_init_resp (INIT_INFO *info); +ST_RET mpl_cs_init_resp (CS_INIT_INFO *info); +#endif + +/************************************************************************/ +/* CONCLUDE */ +/************************************************************************/ + +/* REQUEST : NULL */ +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_conclude (ST_INT chan); +ST_RET mp_conclude_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_conclude (ST_VOID); +ST_RET mpl_conclude_resp (ST_VOID); +#endif + +/************************************************************************/ +/* CANCEL */ +/************************************************************************/ + +/* REQUEST : NULL */ +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_cancel (MMSREQ_PEND *req); +ST_RET mp_cancel_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_cancel (ST_VOID); +ST_RET mpl_cancel_resp (ST_VOID); +#endif + +/************************************************************************/ +/* REJECT */ +/************************************************************************/ + + +#define MMS_REJ_CLASS_CONFIRMED_REQUEST_PDU 1 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_OTHER 0 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_UNRECOGNIZED_SERVICE 1 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_UNRECOGNIZED_MODIFIER 2 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_INVALID_INVOKEID 3 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_INVALID_ARGUMENT 4 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_INVALID_MODIFIER 5 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_MAX_SERV_OUTSTANDING_EXCEEDED 6 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_MAX_RECURSION_EXCEEDED 8 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_VALUE_OUT_OF_RANGE 9 + +#define MMS_REJ_CLASS_CONFIRMED_RESPONSE_PDU 2 +#define MMS_REJ_CODE_CONFIRMED_RESPONSE_PDU_OTHER 0 +#define MMS_REJ_CODE_CONFIRMED_RESPONSE_PDU_UNRECOGNIZED_SERVICE 1 +#define MMS_REJ_CODE_CONFIRMED_RESPONSE_PDU_INVALID_INVOKEID 2 +#define MMS_REJ_CODE_CONFIRMED_RESPONSE_PDU_INVALID_RESULT 3 +#define MMS_REJ_CODE_CONFIRMED_RESPONSE_PDU_MAX_RECURSION_EXCEEDED 5 +#define MMS_REJ_CODE_CONFIRMED_RESPONSE_PDU_VALUE_OUT_OF_RANGE 6 + +#define MMS_REJ_CLASS_CONFIRMED_ERROR_PDU 3 +#define MMS_REJ_CODE_CONFIRMED_ERROR_PDU_OTHER 0 +#define MMS_REJ_CODE_CONFIRMED_ERROR_PDU_UNRECOGNIZED_SERVICE 1 +#define MMS_REJ_CODE_CONFIRMED_ERROR_PDU_INVALID_INVOKEID 2 +#define MMS_REJ_CODE_CONFIRMED_ERROR_PDU_INVALID_SERVICEERROR 3 +#define MMS_REJ_CODE_CONFIRMED_ERROR_PDU_VALUE_OUT_OF_RANGE 4 + +#define MMS_REJ_CLASS_UNCONFIRMED_PDU 4 +#define MMS_REJ_CODE_UNCONFIRMED_PDU_OTHER 0 +#define MMS_REJ_CODE_UNCONFIRMED_PDU_UNRECOGNIZED_SERVICE 1 +#define MMS_REJ_CODE_UNCONFIRMED_PDU_INVALID_ARGUMENT 2 +#define MMS_REJ_CODE_UNCONFIRMED_PDU_MAX_RECURSION_EXCEEDED 3 +#define MMS_REJ_CODE_UNCONFIRMED_PDU_VALUE_OUT_OF_RANGE 4 + +#define MMS_REJ_CLASS_PDU_ERROR 5 +#define MMS_REJ_CODE_PDU_ERROR_UNKNOWN_PDU_TYPE 0 +#define MMS_REJ_CODE_PDU_ERROR_INVALID_PDU 1 +#define MMS_REJ_CODE_PDU_ERROR_ILLEGAL_ACSE_MAPPING 2 + +#define MMS_REJ_CLASS_CANCEL_REQUEST_PDU 6 +#define MMS_REJ_CODE_CANCEL_REQUEST_PDU_OTHER 0 +#define MMS_REJ_CODE_CANCEL_REQUEST_PDU_INVALID_INVOKEID 1 + +#define MMS_REJ_CLASS_CANCEL_RESPONSE_PDU 7 +#define MMS_REJ_CODE_CANCEL_RESPONSE_PDU_OTHER 0 +#define MMS_REJ_CODE_CANCEL_RESPONSE_PDU_INVALID_INVOKEID 1 + +#define MMS_REJ_CLASS_CANCEL_ERROR_PDU 8 +#define MMS_REJ_CODE_CANCEL_ERROR_PDU_OTHER 0 +#define MMS_REJ_CODE_CANCEL_ERROR_PDU_INVALID_INVOKEID 1 +#define MMS_REJ_CODE_CANCEL_ERROR_PDU_INVALID_SERVICEERROR 2 +#define MMS_REJ_CODE_CANCEL_ERROR_PDU_VALUE_OUT_OF_RANGE 3 + +#define MMS_REJ_CLASS_CONCLUDE_REQUEST_PDU 9 +#define MMS_REJ_CODE_CONCLUDE_REQUEST_PDU_OTHER 0 +#define MMS_REJ_CODE_CONCLUDE_REQUEST_PDU_INVALID_ARGUMENT 1 + +#define MMS_REJ_CLASS_CONCLUDE_RESPONSE_PDU 10 +#define MMS_REJ_CODE_CONCLUDE_RESPONSE_PDU_OTHER 0 +#define MMS_REJ_CODE_CONCLUDE_RESPONSE_PDU_INVALID_RESULT 1 + +#define MMS_REJ_CLASS_CONCLUDE_ERROR_PDU 11 +#define MMS_REJ_CODE_CONCLUDE_ERROR_PDU_OTHER 0 +#define MMS_REJ_CODE_CONCLUDE_ERROR_PDU_INVALID_SERVICEERROR 1 +#define MMS_REJ_CODE_CONCLUDE_ERROR_PDU_VALUE_OUT_OF_RANGE 2 + + +struct reject_resp_info + { + ST_BOOLEAN detected_here; /* flag indicating where error occurred */ + ST_BOOLEAN invoke_known; /* flag indicating if invoke ID known */ + ST_UINT32 invoke; /* invoke ID of service rejected */ + ST_INT pdu_type; /* pdu type of service rejected */ + ST_INT16 rej_class; /* reject class */ + ST_INT16 rej_code; /* reject code */ + }; +typedef struct reject_resp_info REJECT_RESP_INFO; + +#ifndef MMS_LITE +ST_RET mp_reject_resp (ST_INT chan, REJECT_RESP_INFO *info); +ST_RET mp_reject_ind (MMSREQ_IND *ind,REJECT_RESP_INFO *info); +ST_RET mp_reject_conf (MMSREQ_PEND *req,REJECT_RESP_INFO *info); +#else +ST_RET mpl_reject_resp (REJECT_RESP_INFO *info); +#endif + +/************************************************************************/ +/* ABORT REQUEST FUNCTION */ +/************************************************************************/ + +ST_RET mp_abort (ST_INT chan, ST_INT reason); + +/************************************************************************/ +/************************************************************************/ +/* This function is used to convert convert an AR Name into an ASN.1 */ +/* encoded ApplicationReference based on the TPY DIB information */ +/************************************************************************/ + +ST_RET ms_arname_to_asn1 (ST_CHAR *arname, ST_UCHAR *asn1_buf, ST_INT asn1_buf_len, + ST_UCHAR **asn1_out, ST_INT *asn1_len_out); + +/* This function is used to convert an ASN.1 encoded */ +/* ApplicationReference to the AR Name */ +ST_RET ms_asn1_to_arname (ST_CHAR *arname, ST_UCHAR *asn1, ST_INT asn1len); + +/* This function is used to find an AR Name based on the app_ref */ +/* information. */ +ST_RET ms_appref_to_arname (ST_CHAR *arname, APP_REF *appref); + +/* This function is used to transition between an AR Name and its' */ +/* corresponding app_ref information. */ +ST_RET ms_arname_to_appref (ST_CHAR *arname, APP_REF **appref_out); + +/* This function is used to convert to an ApplicationReference to ASN.1 */ +ST_RET ms_appref_to_asn1 (APP_REF *appref, ST_UCHAR *dest, ST_INT dest_len, + ST_UCHAR **asn1_out, ST_INT *asn1_len_out); + +/* This function is used to convert ASN.1 encoded ApplicationReference */ +/* data to an intermediate form. */ +ST_RET ms_asn1_to_appref (APP_REF *appref, ST_UCHAR *asn1, ST_INT asn1len); + + +#ifdef __cplusplus +} +#endif + +#endif /* MMS_PCON_INCLUDED */ + diff --git a/include/inc/mms_pdom.h b/include/inc/mms_pdom.h new file mode 100644 index 0000000..5562993 --- /dev/null +++ b/include/inc/mms_pdom.h @@ -0,0 +1,419 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pdom.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS domain management services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/13/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PDOM_INCLUDED +#define MMS_PDOM_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_err.h" /* need for service error definition */ +#include "mms_mp.h" + +/************************************************************************/ +/************************************************************************/ +/* DOMAIN MANAGEMENT SERVICES */ +/************************************************************************/ +/* The structures below are used to pass DOMAIN MANAGEMENT information */ +/* to/from the MMS primitives. */ +/************************************************************************/ + +/* use these defines to determine whether load data is coded or not */ +/* If coded, the data pointer points to a complete ASN.1 EXTERNAL */ + +#define LOAD_DATA_NON_CODED 0 +#define LOAD_DATA_CODED 1 + + +/************************************************************************/ +/* INITIATE DOWNLOAD SEQUENCE */ +/************************************************************************/ + +/* REQUEST : */ + +struct initdown_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + ST_BOOLEAN sharable; /* boolean, no default */ + ST_INT num_of_capab; /* number of capabilities */ +/* list of capabilities */ +/* ST_CHAR * capab_list [num_of_capab]; */ + SD_END_STRUCT + }; +typedef struct initdown_req_info INITDOWN_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_initdown (ST_INT chan, INITDOWN_REQ_INFO *info); +ST_RET mp_initdown_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_initdown (INITDOWN_REQ_INFO *info); +ST_RET mpl_initdown_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DOWNLOAD SEGMENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct download_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + }; +typedef struct download_req_info DOWNLOAD_REQ_INFO; + +/* RESPONSE : */ + + +struct download_resp_info + { + ST_INT load_data_type; /* coded/non-coded */ + ST_INT load_data_len; /* number of load data octets */ + ST_UCHAR *load_data; /* pointer to load data octets */ + ST_BOOLEAN more_follows; /* boolean, default to true */ + }; +typedef struct download_resp_info DOWNLOAD_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_download (ST_INT chan, DOWNLOAD_REQ_INFO *info); +ST_RET mp_download_resp (MMSREQ_IND *ind, DOWNLOAD_RESP_INFO *info); +#else +ST_RET mpl_download (DOWNLOAD_REQ_INFO *info); +ST_RET mpl_download_resp (ST_UINT32 invoke, DOWNLOAD_RESP_INFO *info); +#endif + +/************************************************************************/ +/* TERMINATE DOWNLOAD SEQUENCE */ +/************************************************************************/ + +/* REQUEST : */ + +struct termdown_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + ST_BOOLEAN discarded; /* boolean, default to false */ + ERR_INFO *err; /* points to service error */ + }; /* (IS only, for discarded != 0 */ +typedef struct termdown_req_info TERMDOWN_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_termdown (ST_INT chan, TERMDOWN_REQ_INFO *info); +ST_RET mp_termdown_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_termdown (TERMDOWN_REQ_INFO *info); +ST_RET mpl_termdown_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* INITIATE UPLOAD SEQUENCE */ +/************************************************************************/ + +/* REQUEST : */ + +struct initupl_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + }; +typedef struct initupl_req_info INITUPL_REQ_INFO; + +/* RESPONSE : */ + +struct initupl_resp_info + { + ST_INT32 ulsmid; /* upload state machine id */ + ST_INT num_of_capab; /* number of capabilities */ +/* list of capabilities */ +/* ST_CHAR *capab_list [num_of_capab]; */ + SD_END_STRUCT + }; +typedef struct initupl_resp_info INITUPL_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_initupl (ST_INT chan, INITUPL_REQ_INFO *info); +ST_RET mp_initupl_resp (MMSREQ_IND *ind, INITUPL_RESP_INFO *info); +#else +ST_RET mpl_initupl (INITUPL_REQ_INFO *info); +ST_RET mpl_initupl_resp (ST_UINT32 invoke, INITUPL_RESP_INFO *info); +#endif + +/************************************************************************/ +/* UPLOAD SEGMENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct upload_req_info + { + ST_INT32 ulsmid; /* upload state machine id */ + }; +typedef struct upload_req_info UPLOAD_REQ_INFO; + +/* RESPONSE : */ + +struct upload_resp_info + { + ST_INT load_data_type; /* coded/non-coded */ + ST_INT load_data_len; /* number of load data octets */ + ST_UCHAR *load_data; /* pointer to load data octets */ + ST_BOOLEAN more_follows; /* boolean, default to true */ + }; +typedef struct upload_resp_info UPLOAD_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_upload (ST_INT chan, UPLOAD_REQ_INFO *info); +ST_RET mp_upload_resp (MMSREQ_IND *ind, UPLOAD_RESP_INFO *info); +#else +ST_RET mpl_upload (UPLOAD_REQ_INFO *info); +ST_RET mpl_upload_resp (ST_UINT32 invoke, UPLOAD_RESP_INFO *info); +#endif + +/************************************************************************/ +/* TERMINATE UPLOAD SEQUENCE */ +/************************************************************************/ + +/* REQUEST : */ + +struct termupl_req_info + { + ST_INT32 ulsmid; /* upload state machine id */ + }; +typedef struct termupl_req_info TERMUPL_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_termupl (ST_INT chan, TERMUPL_REQ_INFO *info); +ST_RET mp_termupl_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_termupl (TERMUPL_REQ_INFO *info); +ST_RET mpl_termupl_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* REQUEST DOMAIN DOWNLOAD */ +/************************************************************************/ + +/* REQUEST : */ + +struct rddwn_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + ST_BOOLEAN sharable; /* boolean, no default */ + ST_INT num_of_capab; /* number of capabilities */ + ST_INT num_of_fname; /* num of fname elements */ +/* list of capabilities */ +/* ST_CHAR * capab_list [num_of_capab]; */ +/* list of file names */ +/* FILE_NAME fname_list[ num_of_fname ]; */ + SD_END_STRUCT + }; +typedef struct rddwn_req_info RDDWN_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_rddwn (ST_INT chan, RDDWN_REQ_INFO *info); +ST_RET mp_rddwn_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_rddwn (RDDWN_REQ_INFO *info); +ST_RET mpl_rddwn_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* REQUEST DOMAIN UPLOAD */ +/************************************************************************/ + +/* REQUEST : */ + +struct rdupl_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + ST_INT num_of_fname; /* num of fname elements */ +/* list of file names */ +/* FILE_NAME fname_list[ num_of_fname ]; */ + SD_END_STRUCT + }; +typedef struct rdupl_req_info RDUPL_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_rdupl (ST_INT chan, RDUPL_REQ_INFO *info); +ST_RET mp_rdupl_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_rdupl (RDUPL_REQ_INFO *info); +ST_RET mpl_rdupl_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* LOAD DOMAIN CONTENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct loaddom_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + ST_BOOLEAN sharable; /* boolean, no default */ + ST_BOOLEAN third_pty_pres; /* third party used */ + ST_INT third_pty_len; /* the length of third party */ + ST_UCHAR *third_pty; /* ptr to third party ASN.1 */ + ST_INT num_of_capab; /* number of capabilities */ + ST_INT num_of_fname; /* num of fname elements */ +/* list of capabilities */ +/* ST_CHAR *capab_list [num_of_capab]; */ +/* list of file names */ +/* FILE_NAME fname_list[ num_of_fname ]; */ + SD_END_STRUCT + }; +typedef struct loaddom_req_info LOADDOM_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_loaddom (ST_INT chan, LOADDOM_REQ_INFO *info); +ST_RET mp_loaddom_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_loaddom (LOADDOM_REQ_INFO *info); +ST_RET mpl_loaddom_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* STORE DOMAIN CONTENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct storedom_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + ST_INT num_of_fname; /* num of fname elements */ + ST_BOOLEAN third_pty_pres; /* third party used */ + ST_INT third_pty_len; /* the length of third party */ + ST_UCHAR *third_pty; /* ptr to third party ASN.1 */ +/* list of file names */ +/* FILE_NAME fname_list[ num_of_fname ]; */ + SD_END_STRUCT + }; +typedef struct storedom_req_info STOREDOM_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_storedom (ST_INT chan, STOREDOM_REQ_INFO *info); +ST_RET mp_storedom_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_storedom (STOREDOM_REQ_INFO *info); +ST_RET mpl_storedom_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DELETE DOMAIN */ +/************************************************************************/ + +/* REQUEST : */ + +struct deldom_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + }; +typedef struct deldom_req_info DELDOM_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_deldom (ST_INT chan, DELDOM_REQ_INFO *info); +ST_RET mp_deldom_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_deldom (DELDOM_REQ_INFO *info); +ST_RET mpl_deldom_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET DOMAIN ATTRIBUTE */ +/************************************************************************/ + +/* REQUEST : */ + +struct getdom_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + }; +typedef struct getdom_req_info GETDOM_REQ_INFO; + +/* RESPONSE : */ + +struct getdom_resp_info + { + ST_INT num_of_capab; /* number of capabilities */ + ST_BOOLEAN mms_deletable; /* MMS deletable, no default */ + ST_BOOLEAN sharable; /* boolean, no default */ + ST_INT num_of_pinames; /* number of pi names */ + ST_INT16 state; /* 0 : non-existent */ + /* 1 : loaded */ + /* 2 : ready */ + /* 3 : in use */ + /* 4 : complete */ + /* 5 : incomplete */ + /* 6-15 : d1-d8 (IS) */ + ST_INT8 upload_in_progress; /* upload in progress */ +/* list of pointers to capabilities */ +/* ST_CHAR *capab_list [num_of_capab]; */ +/* list of pointers to program invocation names */ +/* ST_CHAR *pinames_list [num_of_pinames]; */ + SD_END_STRUCT + }; +typedef struct getdom_resp_info GETDOM_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getdom (ST_INT chan, GETDOM_REQ_INFO *info); +ST_RET mp_getdom_resp (MMSREQ_IND *ind, GETDOM_RESP_INFO *info); +#else +ST_RET mpl_getdom (GETDOM_REQ_INFO *info); +ST_RET mpl_getdom_resp (ST_UINT32 invoke, GETDOM_RESP_INFO *info); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PDOM_INCLUDED */ + diff --git a/include/inc/mms_perr.h b/include/inc/mms_perr.h new file mode 100644 index 0000000..d387f91 --- /dev/null +++ b/include/inc/mms_perr.h @@ -0,0 +1,248 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2007, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_perr.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains structure & function definitions used for */ +/* decoding and encoding an error response. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/05/07 EJV 03 Removed obsolete LLC30_LLP Type code. */ +/* 07/02/98 NAV 02 Add MVE_JOURNAL_NAME error code */ +/* 06/09/97 MDE 01 Fixed indenting */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PERR_INCLUDED +#define MMS_PERR_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/* Global MMS operation error code, written when error is detected in */ +/* functions which return pointers. */ +/************************************************************************/ + +extern ST_RET mms_op_err; + +/************************************************************************/ +/* Error Codes */ +/* MMSEASE error codes start at E_MMS_GEN(found in glberror.h). */ +/* When the return valus from a user accessable function is a pointer, */ +/* an error is indicated by a pointer value of 0L. In this case the */ +/* error code may be found in the global variable 'mms_op_err'. */ +/* */ +/* Note that SUIC error codes are passed through, and are in the range */ +/* 1 - 99. Refer to SUIC documentation for specific error definitions. */ +/* */ +/* */ +/* Error codes returned from any request or response function */ +/************************************************************************/ + +#define ME_CHAN_STATE 0x6401 +#define ME_CHAN_NUM 0x6402 +#define ME_TITLE_LEN 0x6403 +#define ME_SEND_SIZE 0x6404 +#define ME_REQ_PEND_COUNT 0x6405 +#define ME_INACTIVE_IND 0x6406 +#define ME_PARTNER_NAME 0x6407 +#define ME_AR_NAME 0x6408 +#define ME_OBJ_ID_ERR 0x6409 +#define ME_SEND_ERROR 0x640A +#define ME_ACSE_CHAN_RANGE 0x640B +#define ME_LLC_CHAN_RANGE 0x640D +#define ME_LLP_TYPE 0x640E +#define ME_TRANS_ID_UNAVAILABLE 0x640F +#define ME_CHAN_TYPE 0x6410 +#define ME_TOO_MANY_CONTEXTS 0x6411 +#define ME_UNKNOWN_P_CONTEXT 0x6412 +#define ME_P_CONTEXT_ERROR 0x6413 +#define ME_ASN1_ENCODE_OVERRUN 0x6414 + +/************************************************************************/ +/* Error codes returned from mp_xxx_req functions */ +/* Values begin from E_MMS_PPI(found in glberror.h). */ +/************************************************************************/ + +#define ME_QUEFULL 0x6501 + +/************************************************************************/ +/* Error codes found in resp_err */ +/* Values begin from E_MMS_RESP(found in glberror.h). */ +/************************************************************************/ + +#define CNF_RESP_OK 0 +#define CNF_PARSE_ERR 0x6601 +#define CNF_REJ_ERR 0x6602 +#define CNF_ERR_OK 0x6603 +#define CNF_DISCONNECTED 0x6604 +#define CNF_CHAN_OP_ERR 0x6605 +#define CNF_CANST_ERR 0x6606 +#define CNF_ASS_REQ_REJECTED 0x6607 +#define CNF_ASS_RESP_PARAM 0x6608 +#define CNF_ASS_USER_REJ_CONF 0x6609 +#define CNF_REM_FOPEN 0x660A +#define CNF_INIT_PARAM 0x660B +#define CNF_REM_FREAD 0x660C +#define CNF_LOC_FWRITE 0x660D +#define CNF_REM_FCLOSE 0x660E +#define CNF_LOC_FCLOSE 0x660F +#define CNF_MVREAD_RESP_PARAM 0x6610 +#define CNF_VM_RESP_ERR 0x6611 +#define CNF_LLC_SEND_ERROR 0x6612 +#define CNF_REQ_NOT_DONE 0x6613 + +/************************************************************************/ +/* Error codes returned from 'mv_xxxx_resp' functions. */ +/* Values begin from E_MMS_VMI(found in glberror.h). */ +/************************************************************************/ + +#define MVE_VARNAME 0x6701 +#define MVE_TYPENAME 0x6702 +#define MVE_ADDR 0x6703 +#define MVE_FOPEN 0x6704 +#define MVE_REM_FILE_COUNT 0x6705 +#define MVE_LOC_FILE_COUNT 0x6706 +#define MVE_FILE_REFNUM 0x6707 +#define MVE_FRENAME 0x6708 +#define MVE_FDELETE 0x6709 +#define MVE_FDIR 0x670A +#define MVE_LOC_FOPEN 0x670B +#define MVE_CANCEL_STATE 0x670C +#define MVE_DOM_ERR 0x670D +#define MVE_RT_TYPE 0x670E +#define MVE_DOM_STATE 0x670F +#define MVE_AT_UPPER_LIMIT 0x6710 +#define MVE_DATA_CONVERT 0x6711 +#define MVE_VM_SERVICE_NOTSUPP 0x6712 +#define MVE_MVWRITE_REQ_PARAM 0x6713 +#define MVE_DOMAIN_NAME 0x6714 +#define MVE_OBJECT_SCOPE 0x6715 +#define MVE_VAR_LIST 0x6716 +#define MVE_VAR_NUMBER 0x6717 +#define MVE_NOT_NAMED_VAR 0x6718 +#define MVE_WRONG_OP 0x6719 +#define MVE_MVINFO_ACCESS_ERR 0x671A +#define MVE_TYPEDEF_LEN0 0x671B +#define MVE_TYPEDEF_SYM_GT 0x671C +#define MVE_TYPEDEF_SYM_LT 0x671D +#define MVE_TYPEDEF_OBJNAME 0x671E +#define MVE_TYPEDEF_SYM_RBRACE 0x671F +#define MVE_TYPEDEF_SYM_LBRACE 0x6720 +#define MVE_TYPEDEF_SYM_COMMA 0x6721 +#define MVE_TYPEDEF_SYM_RPAREN 0x6722 +#define MVE_TYPEDEF_SYM_LPAREN 0x6723 +#define MVE_TYPEDEF_SYM_P 0x6724 +#define MVE_TYPEDEF_SYM_PLUS 0x6725 +#define MVE_TYPEDEF_SYM_MINUS 0x6726 +#define MVE_TYPEDEF_SYM_T 0x6727 +#define MVE_TYPEDEF_BADLEN3 0x6728 +#define MVE_TYPEDEF_BADLEN4 0x6729 +#define MVE_TYPEDEF_BADLEN5 0x672A +#define MVE_TYPEDEF_BADLEN7 0x672B +#define MVE_TYPEDEF_BADTYPE 0x672C +#define MVE_TYPEDEF_SYM_COLON 0x672D +#define MVE_TYPEDEF_SYM_RBRACKET 0x672E +#define MVE_TYPEDEF_SYM_LBRACKET 0x672F +#define MVE_TYPEDEF_NUM_ELTS 0x6730 +#define MVE_TYPEDEF_SYM_DIGIT 0x6731 +#define MVE_TYPEDEF_SYM_OTHER 0x6732 +#define MVE_DATA_SPACE 0x6733 +#define MVE_VM_REQ_ERR 0x6734 +#define MVE_VMD_NOT_EMPTY 0x6735 +#define MVE_BAD_APP_REF_FORM 0x6736 +#define MVE_ASN1_TO_RT 0x6737 +#define MVE_ASN1_ENCODE_ERR 0x6738 +#define MVE_ASN1_DECODE_ERR 0x6739 +#define MVE_FP_SAVE_REQ_ERR 0x673A +#define MVE_FP_REQ_DONE_ERR 0x673B +#define MVE_LLP_DIB_FOPEN_ERR 0x673C +#define MVE_ADD_APPREF_ERR 0x673D +#define MVE_RESP_NOT_SUPP 0x673E +#define MVE_REQ_NOT_SUPP 0x673F +#define MVE_INVALID_PDU 0x6740 +#define MVE_DOM_DISCARDED 0x6741 +#define MVE_DOM_PROTECTED 0x6742 +#define MVE_DOM_DEL_ERR 0x6743 +#define MVE_DEL_PI_ERR 0x6744 +#define MVE_RTAA_TYPE 0x6745 +#define MVE_RTAA_SIZE 0x6746 +#define MVE_AA_SELECT 0x6747 +#define MVE_INVALID_ADL 0x6748 +#define MVE_DATA_TO_RT 0x6749 +#define MVE_LOC_FILE_READ 0x6750 + +/************************************************************************/ +/* Errors related to VM Program Invocation handling */ + +#define PI_NAME 0x6770 +#define PI_STATE 0x6771 +#define PI_NOT_REUSABLE 0x6772 +#define PI_NOT_DELETABLE 0x6773 +#define ME_PI_PROTECTION 0x6774 +#define ME_PI_INVALID_ID 0x6775 + +/************************************************************************/ +/* Errors related to VM Journal handling */ + +#define MVE_JOURNAL_NAME 0x6776 +#define MVE_INVALID_DOMAIN_OBJ 0x6777 + +/************************************************************************/ +/* ACSE ERROR CODES */ +/* The codes below are used in the info.ACSE.err_code in the case where */ +/* the event is an ACSE_ERROR. The user defined function */ +/* 'u_llp_error_ind' is called with these codes when this occurs. */ +/* Values begin from E_LLP_ACSE(found in glberror.h). */ +/************************************************************************/ + +#define ACSE_RECEIVE_ERR 0x6901L +#define ACSE_LISTEN_ERR 0x6902L +#define ACSE_DISCONNECT_RCV_ERR 0x6903L +#define ACSE_STOP_LISTEN_ERR 0x6904L +#define ACSE_ASS_REQ_ERR 0x6905L +#define ACSE_ASS_RESP_ERR 0x6906L +#define ACSE_REL_RESP_ERR 0x6907L +#define ACSE_REL_REQ_ERR 0x6908L +#define ACSE_SEND_REQ_ERR 0x6909L +#define ACSE_SET_DEBUG_ERR 0x690AL +#define ACSE_ABORT_ERR 0x690BL + + +/************************************************************************/ +/* MMS Exception Codes */ +/* These codes are passed to the user when the user exception function */ +/* (u_mmsexcept_ind) is called. */ +/* Values begin from E_MMS_EXCPT(found in glberror.h). */ +/************************************************************************/ + +#define MX_REJECT 0x6801 +#define MX_BOARD_ERR 0x6802 +#define MX_LLP_EVENT_ERROR 0x6803 +#define MX_MEMORY_ALLOC 0x6804 +#define MX_RUNTIME_TDEF 0x6805 +#define MX_LLP_QUE_OVERFLOW 0x6806 +#define MX_MMSIND_QUE 0x6807 +#define MX_MMSCONF_QUE 0x6808 +#define MX_INTERNAL_ERROR 0x6809 +#define MX_LLP_ADD_INFO_ALLOC 0x680A + + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PERR_INCLUDED */ + + + diff --git a/include/inc/mms_pevn.h b/include/inc/mms_pevn.h new file mode 100644 index 0000000..f32f230 --- /dev/null +++ b/include/inc/mms_pevn.h @@ -0,0 +1,956 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pevn.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS event management services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/12/02 JRB 03 Add ASN1_ENC_CTXT arg to mpl_evnot */ +/* 07/15/97 MDE 02 Added cur_state defines */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PEVN_INCLUDED +#define MMS_PEVN_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_pvar.h" /* needed for variable specification defs */ +#include "mms_err.h" /* needed for service error definitions */ +#include "mms_mp.h" + + +/************************************************************************/ +/* Event cur_state defines */ + +#define EC_STATE_DISABLED 0 +#define EC_STATE_IDLE 1 +#define EC_STATE_ACTIVE 2 + +#define EC_STATE_ACTIVE_NOACK_A 3 +#define EC_STATE_IDLE_NOACK_I 4 +#define EC_STATE_IDLE_NOACK_A 5 +#define EC_STATE_IDLE_ACKED 6 +#define EC_STATE_ACTIVE_ACKED 7 + +/************************************************************************/ +/* EVENT MANAGEMENT FUNCTIONS */ +/************************************************************************/ +/* The structures below are used to pass EVENT MANAGEMENT operation */ +/* information to/from the MMS primitives. */ +/************************************************************************/ + +struct event_enrollment + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + ST_CHAR evcon_name_tag; /* 0 : event condition name */ + /* 1 : undefined */ + OBJECT_NAME evcon_name; /* event condition name - for */ + /* evcon_name_tag = 0 only */ + ST_BOOLEAN evact_name_pres; /* event action name present */ + ST_CHAR evact_name_tag; /* 0 : event action name */ + /* 1 : undefined */ + OBJECT_NAME evact_name; /* event action name - for */ + /* evact_name_tag = 0 only */ + ST_BOOLEAN client_app_pres; /* client application present */ + ST_INT client_app_len; /* client application length */ + ST_UCHAR *client_app; /* client application reference */ + ST_BOOLEAN mms_deletable; /* mms deletable (def = false) */ + ST_INT16 ee_class; /* event enrollment class: */ + /* 0 - modifier */ + /* 1 - notification */ + ST_INT16 duration; /* duration: */ + /* 0 - current (default) */ + /* 1 - permanent */ + ST_BOOLEAN invoke_id_pres; /* invoke id present */ + ST_UINT32 invoke_id; /* invoke id */ + ST_BOOLEAN rem_acc_delay_pres; /* rem acceptable delay present */ + ST_UINT32 rem_acc_delay; /* remaining acceptable delay */ + ST_BOOLEAN addl_detail_pres; /* additional detail present */ + ST_INT addl_detail_len; /* length of additional detail */ + ST_UCHAR *addl_detail; /* pointer to additional detail */ + ST_BOOLEAN ackec_name_pres; /* ack event cond name present */ + ST_CHAR ackec_name_tag; /* 0 : ack event condition name */ + /* 1 : undefined */ + OBJECT_NAME ackec_name; /* ack event cond name - for */ + /* ackec_name_tag = 0 only */ + SD_END_STRUCT + }; +typedef struct event_enrollment EVENT_ENROLLMENT; + +struct alarm_summary + { + OBJECT_NAME evcon_name; /* event condition name */ + ST_UCHAR severity; /* severity */ + ST_INT16 cur_state; /* current state */ + /* 0 : disabled */ + /* 1 : idle */ + /* 2 : active */ + ST_INT16 unack_state; /* unacknowledged state */ + /* 0 : none */ + /* 1 : active */ + /* 2 : idle */ + /* 3 : both */ + ST_BOOLEAN addl_detail_pres; /* additional detail present */ + ST_INT addl_detail_len; /* length of additional detail */ + ST_UCHAR *addl_detail; /* pointer to additional detail */ + ST_BOOLEAN tta_time_pres; /* transition to active time */ + /* present */ + EVENT_TIME tta_time; /* transition to active time */ + ST_BOOLEAN tti_time_pres; /* transition to idle time */ + /* present */ + EVENT_TIME tti_time; /* transition to idle time */ + SD_END_STRUCT + }; +typedef struct alarm_summary ALARM_SUMMARY; + +struct alarm_enroll_summary + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + ST_BOOLEAN client_app_pres; /* client application present */ + ST_INT client_app_len; /* client application length */ + ST_UCHAR *client_app; /* client application reference */ + ST_UCHAR severity; /* severity */ + ST_INT16 cur_state; /* current state */ + /* 0 : disabled */ + /* 1 : idle */ + /* 2 : active */ + ST_BOOLEAN addl_detail_pres; /* additional detail present */ + ST_INT addl_detail_len; /* length of additional detail */ + ST_UCHAR *addl_detail; /* pointer to additional detail */ + ST_BOOLEAN not_lost; /* notification lost */ + /* (default = false) */ + ST_INT16 alarm_ack_rule; /* alarm acknowledgment rule */ + /* 0 : none */ + /* 1 : simple */ + /* 2 : ack active */ + /* 3 : ack all */ + ST_BOOLEAN ee_state_pres; /* enrollment state present */ + ST_INT16 ee_state; /* enrollment state */ + /* 0 : disabled */ + /* 1 : idle */ + /* 2 : active */ + /* 3 : active, no ack a */ + /* 4 : idle, no ack i */ + /* 5 : idle, no ack a */ + /* 6 : idle, acked */ + /* 7 : active, acked */ + ST_BOOLEAN tta_time_pres; /* transition to active time */ + /* present */ + EVENT_TIME tta_time; /* transition to active time */ + ST_BOOLEAN aack_time_pres; /* active acknowledgment time */ + /* present */ + EVENT_TIME aack_time; /* active acknowledgment time */ + ST_BOOLEAN tti_time_pres; /* transition to idle time */ + /* present */ + EVENT_TIME tti_time; /* transition to idle time */ + ST_BOOLEAN iack_time_pres; /* idle acknowledgment time */ + /* present */ + EVENT_TIME iack_time; /* idle acknowledgment time */ + SD_END_STRUCT + }; +typedef struct alarm_enroll_summary ALARM_ENROLL_SUMMARY; + + +/************************************************************************/ +/************************************************************************/ +/* DEFINE EVENT CONDITION */ +/************************************************************************/ + +/* REQUEST : */ + +struct defec_req_info + { + OBJECT_NAME evcon_name; /* event condition name */ + ST_INT16 eclass; /* event condition class: */ + ST_UCHAR priority; /* priority */ + /* 0 - highest */ + /* 64 - normal (default) */ + /* 127 - lowest */ + ST_UCHAR severity; /* severity (default = 64) */ + ST_BOOLEAN as_reports_pres; /* alarm summaray rpts present */ + ST_BOOLEAN as_reports; /* alarm summaray reports */ + ST_BOOLEAN mon_var_pres; /* monitored variable present */ + VARIABLE_SPEC var_ref; /* variable reference */ + ST_BOOLEAN eval_int_pres; /* evaluation interval present */ + ST_UINT32 eval_interval; /* evaluation interval */ + SD_END_STRUCT + }; +typedef struct defec_req_info DEFEC_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_defec (ST_INT chan, DEFEC_REQ_INFO *info); +ST_RET mp_defec_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_defec (DEFEC_REQ_INFO *info); +ST_RET mpl_defec_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DELETE EVENT CONDITION */ +/************************************************************************/ + +/* REQUEST : */ + +struct delec_req_info + { + ST_INT16 req_tag; /* request tag */ + /* 0 : specific */ + /* 1 : aa specific */ + /* 2 : domain */ + /* 3 : vmd */ + ST_CHAR dname [MAX_IDENT_LEN+1]; /* domain name, if req_tag = 2 */ + ST_INT num_of_names; /* number of names, if tag = 0 */ +/* list of object names */ +/* OBJECT_NAME name_list [num_of_names]; */ + SD_END_STRUCT + }; +typedef struct delec_req_info DELEC_REQ_INFO; + +/* RESPONSE : */ + +struct delec_resp_info + { + ST_UINT32 cand_not_deleted; /* canditates not deleted */ + }; +typedef struct delec_resp_info DELEC_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_delec (ST_INT chan, DELEC_REQ_INFO *info); +ST_RET mp_delec_resp (MMSREQ_IND *ind, DELEC_RESP_INFO *info); +#else +ST_RET mpl_delec (DELEC_REQ_INFO *info); +ST_RET mpl_delec_resp (ST_UINT32 invoke, DELEC_RESP_INFO *info); +#endif + +/************************************************************************/ +/* GET EVENT CONDITION ATTRIBUTES */ +/************************************************************************/ + +/* REQUEST : */ + +struct geteca_req_info + { + OBJECT_NAME evcon_name; /* event condition name */ + }; +typedef struct geteca_req_info GETECA_REQ_INFO; + +/* RESPONSE : */ + +struct geteca_resp_info + { + ST_BOOLEAN mms_deletable; /* mms deletable */ + ST_INT16 eclass; /* event condition class: */ + ST_UCHAR priority; /* priority */ + /* 0 - highest */ + /* 64 - normal (default) */ + /* 127 - lowest */ + ST_UCHAR severity; /* severity */ + /* 0 - highest */ + /* 64 - normal (default) */ + /* 127 - lowest */ + ST_BOOLEAN as_reports; /* alarm summaray reports */ + ST_BOOLEAN mon_var_pres; /* monitored variable present */ + ST_INT16 mon_var_tag; /* monitored variable tag */ + /* 0 : variable reference */ + /* 1 : undefined (NULL) */ + VARIABLE_SPEC var_ref; /* variable reference */ + ST_BOOLEAN eval_int_pres; /* evaluation interval present */ + ST_UINT32 eval_interval; /* evaluation interval */ + SD_END_STRUCT + }; +typedef struct geteca_resp_info GETECA_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_geteca (ST_INT chan, GETECA_REQ_INFO *info); +ST_RET mp_geteca_resp (MMSREQ_IND *ind, GETECA_RESP_INFO *info); +#else +ST_RET mpl_geteca (GETECA_REQ_INFO *info); +ST_RET mpl_geteca_resp (ST_UINT32 invoke, GETECA_RESP_INFO *info); +#endif + +/************************************************************************/ +/* REPORT EVENT CONDITION STATUS */ +/************************************************************************/ + +/* REQUEST : */ + +struct repecs_req_info + { + OBJECT_NAME evcon_name; /* event condition name */ + }; +typedef struct repecs_req_info REPECS_REQ_INFO; + +/* RESPONSE : */ + +struct repecs_resp_info + { + ST_INT16 cur_state; /* event condition state: */ + /* 0 - disabled */ + /* 1 - idle */ + /* 2 - active */ + ST_UINT32 num_of_ev_enroll; /* number of event enrollments */ + ST_BOOLEAN enabled_pres; /* enabled indicator present */ + ST_BOOLEAN enabled; /* enabled indicator */ + ST_BOOLEAN tta_time_pres; /* transition to active present */ + EVENT_TIME tta_time; /* transition to active time */ + ST_BOOLEAN tti_time_pres; /* transition to idle present */ + EVENT_TIME tti_time; /* transition to idle time */ + SD_END_STRUCT + }; +typedef struct repecs_resp_info REPECS_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_repecs (ST_INT chan, REPECS_REQ_INFO *info); +ST_RET mp_repecs_resp (MMSREQ_IND *ind, REPECS_RESP_INFO *info); +#else +ST_RET mpl_repecs (REPECS_REQ_INFO *info); +ST_RET mpl_repecs_resp (ST_UINT32 invoke, REPECS_RESP_INFO *info); +#endif + +/************************************************************************/ +/* ALTER EVENT CONDITION MONITORING */ +/************************************************************************/ + +/* REQUEST : */ + +struct altecm_req_info + { + OBJECT_NAME evcon_name; /* event condition name */ + ST_BOOLEAN enabled_pres; /* enabled present */ + ST_BOOLEAN enabled; /* enabled */ + ST_BOOLEAN priority_pres; /* priority present */ + ST_UCHAR priority; /* priority */ + /* 0 - highest */ + /* 64 - normal */ + /* 127 - lowest */ + ST_BOOLEAN as_reports_pres; /* alarm summaray rpts present */ + ST_BOOLEAN as_reports; /* alarm summaray reports */ + ST_BOOLEAN eval_int_pres; /* evaluation interval present */ + ST_UINT32 eval_int; /* evaluation interval */ + SD_END_STRUCT + }; +typedef struct altecm_req_info ALTECM_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_altecm (ST_INT chan, ALTECM_REQ_INFO *info); +ST_RET mp_altecm_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_altecm (ALTECM_REQ_INFO *info); +ST_RET mpl_altecm_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* TRIGGER EVENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct trige_req_info + { + OBJECT_NAME evcon_name; /* event condition name */ + ST_BOOLEAN priority_pres; /* priority present */ + ST_UCHAR priority; /* priority */ + /* 0 - highest */ + /* 64 - normal */ + /* 127 - lowest */ + SD_END_STRUCT + }; +typedef struct trige_req_info TRIGE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_trige (ST_INT chan, TRIGE_REQ_INFO *info); +ST_RET mp_trige_resp (MMSREQ_IND *info); +#else +ST_RET mpl_trige (TRIGE_REQ_INFO *info); +ST_RET mpl_trige_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DEFINE EVENT ACTION */ +/************************************************************************/ + +/* REQUEST : */ + +struct defea_req_info + { + OBJECT_NAME evact_name; /* event action name */ + ST_INT conf_serv_req_len; /* confirmed service req length */ + ST_UCHAR *conf_serv_req; /* confirmed service request */ + ST_BOOLEAN modlist_pres; /* list of modifiers present */ + ST_INT num_of_modifiers; /* number of modifiers */ + ST_BOOLEAN cs_rdetail_pres; /* CS request detail present */ + ST_INT cs_rdetail_len; /* CS request detail length */ + ST_UCHAR *cs_rdetail; /* CS request detail pointer */ +/* list of modifiers */ +/* MODIFIER mod_list [num_of_modifiers]; */ + SD_END_STRUCT + }; +typedef struct defea_req_info DEFEA_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_defea (ST_INT chan, DEFEA_REQ_INFO *info); +ST_RET mp_defea_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_defea (DEFEA_REQ_INFO *info); +ST_RET mpl_defea_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DELETE EVENT ACTION */ +/************************************************************************/ + +/* REQUEST : */ + +struct delea_req_info + { + ST_INT16 req_tag; /* request tag */ + /* 0 : specific */ + /* 1 : aa specific */ + /* 2 : domain */ + /* 3 : vmd */ + ST_CHAR dname [MAX_IDENT_LEN+1]; /* domain name, if req_tag = 2 */ + ST_INT num_of_names; /* number of names, if tag = 0 */ +/* list of object names */ +/* OBJECT_NAME name_list [num_of_names]; */ + SD_END_STRUCT + }; +typedef struct delea_req_info DELEA_REQ_INFO; + +/* RESPONSE : */ + +struct delea_resp_info + { + ST_UINT32 cand_not_deleted; /* canditates not deleted */ + }; +typedef struct delea_resp_info DELEA_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_delea (ST_INT chan, DELEA_REQ_INFO *info); +ST_RET mp_delea_resp (MMSREQ_IND *ind, DELEA_RESP_INFO *info); +#else +ST_RET mpl_delea (DELEA_REQ_INFO *info); +ST_RET mpl_delea_resp (ST_UINT32 invoke, DELEA_RESP_INFO *info); +#endif + +/************************************************************************/ +/* GET EVENT ACTION ATTRIBUTES */ +/************************************************************************/ + +/* REQUEST : */ + +struct geteaa_req_info + { + OBJECT_NAME evact_name; /* event action name */ + }; +typedef struct geteaa_req_info GETEAA_REQ_INFO; + +/* RESPONSE : */ + +struct geteaa_resp_info + { + ST_BOOLEAN mms_deletable; /* mms deletable (def = false) */ + ST_INT conf_serv_req_len; /* confirmed service req length */ + ST_UCHAR *conf_serv_req; /* confirmed service request */ + ST_BOOLEAN cs_rdetail_pres; /* CS request detail present */ + ST_INT cs_rdetail_len; /* CS request detail length */ + ST_UCHAR *cs_rdetail; /* CS request detail pointer */ + ST_INT num_of_modifiers; /* number of modifiers */ +/* list of modifiers */ +/* MODIFIER mod_list [num_of_modifiers]; */ + SD_END_STRUCT + }; +typedef struct geteaa_resp_info GETEAA_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_geteaa (ST_INT chan, GETEAA_REQ_INFO *info); +ST_RET mp_geteaa_resp (MMSREQ_IND *ind, GETEAA_RESP_INFO *info); +#else +ST_RET mpl_geteaa (GETEAA_REQ_INFO *info); +ST_RET mpl_geteaa_resp (ST_UINT32 invoke, GETEAA_RESP_INFO *info); +#endif + +/************************************************************************/ +/* REPORT EVENT ACTION STATUS */ +/************************************************************************/ + +/* REQUEST : */ + +struct repeas_req_info + { + OBJECT_NAME evact_name; /* event action name */ + }; +typedef struct repeas_req_info REPEAS_REQ_INFO; + +/* RESPONSE : */ + +struct repeas_resp_info + { + ST_UINT32 num_of_ev_enroll; /* number of event enrollments */ + }; +typedef struct repeas_resp_info REPEAS_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_repeas (ST_INT chan, REPEAS_REQ_INFO *info); +ST_RET mp_repeas_resp (MMSREQ_IND *ind, REPEAS_RESP_INFO *info); +#else +ST_RET mpl_repeas (REPEAS_REQ_INFO *info); +ST_RET mpl_repeas_resp (ST_UINT32 invoke, REPEAS_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DEFINE EVENT ENROLLMENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct defee_req_info + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + OBJECT_NAME evcon_name; /* event condition name */ + ST_UCHAR ec_transitions; /* causing transitions: */ + /* bitstring */ + /* 0 : idle to disabled */ + /* 1 : active to disabled */ + /* 2 : disabled to idle */ + /* 3 : active to idle */ + /* 4 : disabled to active */ + /* 5 : idle to active */ + /* 6 : any to deleted */ + ST_INT16 alarm_ack_rule; /* alarm acknowledgment rule */ + /* 0 : none */ + /* 1 : simple */ + /* 2 : ack active */ + /* 3 : ack all */ + ST_BOOLEAN evact_name_pres; /* event action name present */ + OBJECT_NAME evact_name; /* event action name */ + ST_BOOLEAN client_app_pres; /* client application present */ + ST_INT client_app_len; /* client application length */ + ST_UCHAR *client_app; /* client application reference */ + ST_BOOLEAN ackec_name_pres; /* ack event cond name present */ + OBJECT_NAME ackec_name; /* acknowledge event cond name */ + SD_END_STRUCT + }; +typedef struct defee_req_info DEFEE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_defee (ST_INT chan, DEFEE_REQ_INFO *info); +ST_RET mp_defee_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_defee (DEFEE_REQ_INFO *info); +ST_RET mpl_defee_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DELETE EVENT ENROLLMENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct delee_req_info + { + ST_INT16 req_tag; /* request tag */ + /* 0 : specific */ + /* 1 : event condition */ + /* 2 : event action */ + union + { + OBJECT_NAME evcon_name; /* event condition name */ + OBJECT_NAME evact_name; /* event action name */ + ST_INT num_of_names; /* number of object names */ + } sod; +/* list of object names */ +/* OBJECT_NAME name_list [num_of_names]; */ + SD_END_STRUCT + }; +typedef struct delee_req_info DELEE_REQ_INFO; + +/* RESPONSE : */ + +struct delee_resp_info + { + ST_UINT32 cand_not_deleted; /* canditates not deleted */ + }; +typedef struct delee_resp_info DELEE_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_delee (ST_INT chan, DELEE_REQ_INFO *info); +ST_RET mp_delee_resp (MMSREQ_IND *ind, DELEE_RESP_INFO *info); +#else +ST_RET mpl_delee (DELEE_REQ_INFO *info); +ST_RET mpl_delee_resp (ST_UINT32 invoke, DELEE_RESP_INFO *info); +#endif + +/************************************************************************/ +/* GET EVENT ENROLLMENT ATTRIBUTES */ +/************************************************************************/ + +/* REQUEST : */ + +struct geteea_req_info + { + ST_INT16 scope_of_req; /* scope of request */ + /* 0 : specific */ + /* 1 : client (default) */ + /* 2 : event condition */ + /* 3 : event action */ + ST_BOOLEAN client_app_pres; /* client application present */ + ST_INT client_app_len; /* client application length */ + ST_UCHAR *client_app; /* client application reference */ + ST_BOOLEAN evcon_name_pres; /* event condition name present */ + OBJECT_NAME evcon_name; /* event condition name */ + ST_BOOLEAN evact_name_pres; /* event action name present */ + OBJECT_NAME evact_name; /* event action name */ + ST_BOOLEAN ca_name_pres; /* continue after name present */ + OBJECT_NAME ca_name; /* continue after name */ + ST_BOOLEAN eenames_pres; /* event enroll names present */ + ST_INT num_of_eenames; /* number of event enroll names */ +/* list of event enroll names */ +/* OBJECT_NAME name_list [num_of_eenames]; */ + SD_END_STRUCT + }; +typedef struct geteea_req_info GETEEA_REQ_INFO; + +/* RESPONSE : */ + +struct geteea_resp_info + { + ST_BOOLEAN more_follows; /* default = false */ + ST_INT num_of_evenroll; /* number of event enrollments */ +/* list of event enrollments */ +/* EVENT_ENROLLMENT evenroll_list [num_of_evenroll]; */ + SD_END_STRUCT + }; +typedef struct geteea_resp_info GETEEA_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_geteea (ST_INT chan, GETEEA_REQ_INFO *info); +ST_RET mp_geteea_resp (MMSREQ_IND *ind, GETEEA_RESP_INFO *info); +#else +ST_RET mpl_geteea (GETEEA_REQ_INFO *info); +ST_RET mpl_geteea_resp (ST_UINT32 invoke, GETEEA_RESP_INFO *info); +#endif + +/************************************************************************/ +/* REPORT EVENT ENROLLMENT STATUS */ +/************************************************************************/ + +/* REQUEST : */ + +struct repees_req_info + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + }; +typedef struct repees_req_info REPEES_REQ_INFO; + +/* RESPONSE : */ + +struct repees_resp_info + { + ST_UCHAR ec_transitions; /* event condition transitions: */ + /* bitstring */ + /* 0 : idle to disabled */ + /* 1 : active to disabled */ + /* 2 : disabled to idle */ + /* 3 : active to idle */ + /* 4 : disabled to active */ + /* 5 : idle to active */ + /* 6 : any to deleted */ + ST_UCHAR not_lost; /* notification lost */ + /* (default = false) */ + ST_INT16 duration; /* duration: */ + /* 0 - current (default) */ + /* 1 - permanent */ + ST_BOOLEAN alarm_ack_rule_pres; /* alarm ack rule present */ + ST_INT16 alarm_ack_rule; /* alarm acknowledgment rule */ + /* 0 : none */ + /* 1 : simple */ + /* 2 : ack active */ + /* 3 : ack all */ + ST_INT16 cur_state; /* current state */ + /* 0 : disabled */ + /* 1 : idle */ + /* 2 : active */ + /* 3 : active, no ack a */ + /* 4 : idle, no ack i */ + /* 5 : idle, no ack a */ + /* 6 : idle, acked */ + /* 7 : active, acked */ + }; +typedef struct repees_resp_info REPEES_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_repees (ST_INT chan, REPEES_REQ_INFO *info); +ST_RET mp_repees_resp (MMSREQ_IND *ind, REPEES_RESP_INFO *info); +#else +ST_RET mpl_repees (REPEES_REQ_INFO *info); +ST_RET mpl_repees_resp (ST_UINT32 invoke, REPEES_RESP_INFO *info); +#endif + +/************************************************************************/ +/* ALTER EVENT ENROLLMENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct altee_req_info + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + ST_BOOLEAN ec_transitions_pres; /* ec transitions present */ + ST_UCHAR ec_transitions; /* event condition transitions: */ + /* bitstring */ + /* 0 : idle to disabled */ + /* 1 : active to disabled */ + /* 2 : disabled to idle */ + /* 3 : active to idle */ + /* 4 : disabled to active */ + /* 5 : idle to active */ + /* 6 : any to deleted */ + ST_BOOLEAN alarm_ack_rule_pres; /* alarm ack rule present */ + ST_INT16 alarm_ack_rule; /* alarm acknowledgment rule */ + /* 0 : none */ + /* 1 : simple */ + /* 2 : ack active */ + /* 3 : ack all */ + SD_END_STRUCT + }; +typedef struct altee_req_info ALTEE_REQ_INFO; + +/* RESPONSE : */ + +struct altee_resp_info + { + ST_INT16 cur_state_tag; /* current state tag */ + /* 0 : state */ + /* 1 : undefined */ + ST_INT16 state; /* state, if cur_state_tag = 0 */ + /* 0 : disabled */ + /* 1 : idle */ + /* 2 : active */ + /* 3 : active, no ack a */ + /* 4 : idle, no ack i */ + /* 5 : idle, no ack a */ + /* 6 : idle, acked */ + /* 7 : active, acked */ + EVENT_TIME trans_time; /* transition time */ + SD_END_STRUCT + }; +typedef struct altee_resp_info ALTEE_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_altee (ST_INT chan, ALTEE_REQ_INFO *info); +ST_RET mp_altee_resp (MMSREQ_IND *ind, ALTEE_RESP_INFO *info); +#else +ST_RET mpl_altee (ALTEE_REQ_INFO *info); +ST_RET mpl_altee_resp (ST_UINT32 invoke, ALTEE_RESP_INFO *info); +#endif + +/************************************************************************/ +/* EVENT NOTIFICATION, Conformance: MCW1 (EVN3) */ +/************************************************************************/ + +/* REQUEST : */ + +struct evnot_req_info + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + OBJECT_NAME evcon_name; /* event condition name */ + ST_UCHAR severity; /* severity */ + ST_BOOLEAN cur_state_pres; /* current state enable */ + ST_INT16 cur_state; /* current state */ + /* 0 : disabled */ + /* 1 : idle */ + /* 2 : active */ + EVENT_TIME trans_time; /* transition time */ + ST_UCHAR not_lost; /* notification lost */ + /* (default = false) */ + ST_BOOLEAN alarm_ack_rule_pres; /* alarm acknowledge rule pres */ + ST_INT16 alarm_ack_rule; /* alarm acknowledgment rule */ + /* 0 : none */ + /* 1 : simple */ + /* 2 : ack-active */ + /* 3 : ack-all */ + ST_BOOLEAN evact_result_pres; /* action result present */ + OBJECT_NAME evact_name; /* event action name */ + ST_INT16 evact_result_tag; /* event action result tag */ + /* 0 : success */ + /* 1 : failure */ + ST_INT conf_serv_resp_len; /* success: conf serv resp len */ + ST_UCHAR *conf_serv_resp; /* success: conf serv resp ptr */ + ST_BOOLEAN cs_rdetail_pres; /* success: CS resp detail pres */ + ST_INT cs_rdetail_len; /* success: CS resp detail len */ + ST_UCHAR *cs_rdetail; /* success: CS resp detail ptr */ + + ST_BOOLEAN mod_pos_pres; /* failure: mod pos present */ + ST_UINT32 mod_pos; /* failure: modifier position */ + ERR_INFO *serv_err; /* failure: service error ptr */ + + SD_END_STRUCT + }; +typedef struct evnot_req_info EVNOT_REQ_INFO; + +/* RESPONSE : NONE (unconfirmed) */ + +#ifndef MMS_LITE +ST_RET mp_evnot (ST_INT chan, EVNOT_REQ_INFO *info); +#else +ST_RET mpl_evnot (ASN1_ENC_CTXT *aCtx, EVNOT_REQ_INFO *info); +#endif + +/************************************************************************/ +/* ACKNOWLEDGE EVENT NOTIFICATION, Conformance: MCW1 (EVN3) */ +/************************************************************************/ + +/* REQUEST : */ + +struct ackevnot_req_info + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + ST_INT16 ack_state; /* acknowledge state */ + EVENT_TIME evtime; /* event time */ + ST_BOOLEAN ackec_name_pres; /* ack event cond name present */ + OBJECT_NAME ackec_name; /* acknowledge event cond name */ + }; +typedef struct ackevnot_req_info ACKEVNOT_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_ackevnot (ST_INT chan, ACKEVNOT_REQ_INFO *info); +ST_RET mp_ackevnot_resp (MMSREQ_IND *info); +#else +ST_RET mpl_ackevnot (ACKEVNOT_REQ_INFO *info); +ST_RET mpl_ackevnot_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET ALARM SUMMARY, Conformance: EVN5 */ +/************************************************************************/ + +/* REQUEST : */ + +struct getas_req_info + { + ST_BOOLEAN enroll_only; /* enrollments only */ + /* (default = true) */ + ST_BOOLEAN act_alarms_only; /* active alarms only */ + /* (default = true) */ + ST_INT16 ack_filter; /* acknowledgement filter */ + /* 0 : not acked (default) */ + /* 1 : acked */ + /* 2 : all */ + /* severity filter */ + ST_UCHAR most_sev_filter; /* most severe (default=0) */ + ST_UCHAR least_sev_filter; /* least severe (default=127) */ + ST_BOOLEAN ca_pres; /* continue after name present */ + OBJECT_NAME ca_name; /* continue after name */ + }; +typedef struct getas_req_info GETAS_REQ_INFO; + +/* RESPONSE : */ + +struct getas_resp_info + { + ST_BOOLEAN more_follows; /* default = false */ + ST_INT num_of_alarm_sum; /* number of alarm summary */ +/* list of alarm summary data */ +/* ALARM_SUMMARY alarm_sum [num_of_alarm_sum]; */ + SD_END_STRUCT + }; +typedef struct getas_resp_info GETAS_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getas (ST_INT chan, GETAS_REQ_INFO *info); +ST_RET mp_getas_resp (MMSREQ_IND *ind, GETAS_RESP_INFO *info); +#else +ST_RET mpl_getas (GETAS_REQ_INFO *info); +ST_RET mpl_getas_resp (ST_UINT32 invoke, GETAS_RESP_INFO *info); +#endif + +/************************************************************************/ +/* GET ALARM ENROLLMENT SUMMARY */ +/************************************************************************/ + +/* REQUEST : */ + +struct getaes_req_info + { + ST_BOOLEAN enroll_only; /* enrollments only */ + /* (default = true) */ + ST_BOOLEAN act_alarms_only; /* active alarms only */ + /* (default = true) */ + ST_INT16 ack_filter; /* acknowledgement filter */ + /* 0 : not acked (default) */ + /* 1 : acked */ + /* 2 : all */ + /* severity filter */ + ST_UCHAR most_sev_filter; /* most severe (default=0) */ + ST_UCHAR least_sev_filter; /* least severe (default=127) */ + ST_BOOLEAN ca_name_pres; /* continue after name present */ + OBJECT_NAME ca_name; /* continue after name */ + }; +typedef struct getaes_req_info GETAES_REQ_INFO; + +/* RESPONSE : */ + +struct getaes_resp_info + { + ST_BOOLEAN more_follows; /* default = false */ + ST_INT num_of_alarm_esum; /* # of alarm enroll summary */ +/* list of alarm enroll summary */ +/* ALARM_ENROLL_SUMMARY alarm_enroll_sum [num_of_alarm_esum]; */ + SD_END_STRUCT + }; +typedef struct getaes_resp_info GETAES_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getaes (ST_INT chan, GETAES_REQ_INFO *info); +ST_RET mp_getaes_resp (MMSREQ_IND *ind, GETAES_RESP_INFO *info); +#else +ST_RET mpl_getaes (GETAES_REQ_INFO *info); +ST_RET mpl_getaes_resp (ST_UINT32 invoke, GETAES_RESP_INFO *info); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PEVN_INCLUDED */ diff --git a/include/inc/mms_pfil.h b/include/inc/mms_pfil.h new file mode 100644 index 0000000..f1cf773 --- /dev/null +++ b/include/inc/mms_pfil.h @@ -0,0 +1,297 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pfil.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS file services at the primitive */ +/* level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PFIL_INCLUDED +#define MMS_PFIL_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_mp.h" + +/************************************************************************/ +/************************************************************************/ +/* FILE MANAGEMENT SERVICES */ +/************************************************************************/ +/* The structures below are used to pass FILE MANAGEMENT information */ +/* to/from the MMS primitives. */ +/************************************************************************/ + +#define MFSTAT_NO_ACT 0 +#define MFSTAT_PEND_OPEN 1 +#define MFSTAT_OPENED 2 +#define MFSTAT_PEND_CLOSE 3 + +/************************************************************************/ +/* OBTAIN FILE, Conformance: FIL1 */ +/************************************************************************/ + +/* REQUEST : */ + +struct obtfile_req_info + { + ST_BOOLEAN ar_title_pres; /* application title present */ + ST_INT ar_len; /* length of app proc title */ + ST_UCHAR *ar_title; /* application process title */ + ST_INT num_of_src_fname; /* num of source fname elements */ + ST_INT num_of_dest_fname; /* num of dest. fname elements */ +/* list of source file names */ +/* FILE_NAME src_fname_list[ num_of_src_fname ]; */ +/* list of dest. file names */ +/* FILE_NAME dest_fname_list[ num_of_dest_fname ]; */ + SD_END_STRUCT + }; +typedef struct obtfile_req_info OBTFILE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_obtfile (ST_INT chan, OBTFILE_REQ_INFO *info); +ST_RET mp_obtfile_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_obtfile (OBTFILE_REQ_INFO *info); +ST_RET mpl_obtfile_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* FILE OPEN, Conformance: FIL2 */ +/************************************************************************/ + +/* REQUEST : */ + +struct fopen_req_info + { + ST_INT num_of_fname; /* num of fname elements */ + ST_UINT32 init_pos; /* initial position */ +/* list of file names */ +/* FILE_NAME fname_list[ num_of_fname ]; */ + SD_END_STRUCT + }; +typedef struct fopen_req_info FOPEN_REQ_INFO; + +/* RESPONSE : */ + +struct file_attr + { + ST_UINT32 fsize; /* file size (# bytes) */ + ST_BOOLEAN mtimpres; /* last modified time present */ + time_t mtime; /* last modified time */ + }; +typedef struct file_attr FILE_ATTR; + +struct fopen_resp_info + { + ST_INT32 frsmid; /* file read state machine ID */ + FILE_ATTR ent; /* file attributes */ + }; +typedef struct fopen_resp_info FOPEN_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_fopen (ST_INT chan, FOPEN_REQ_INFO *info); +ST_RET mp_fopen_resp (MMSREQ_IND *ind, FOPEN_RESP_INFO *info); +#else +ST_RET mpl_fopen (FOPEN_REQ_INFO *info); +ST_RET mpl_fopen_resp (ST_UINT32 invoke, FOPEN_RESP_INFO *info); +#endif + +/************************************************************************/ +/* FILE READ, Conformance: FIL2 */ +/************************************************************************/ + +/* REQUEST : */ + +struct fread_req_info + { + ST_INT32 frsmid; /* file read state maching ID */ + }; +typedef struct fread_req_info FREAD_REQ_INFO; + +/* RESPONSE : */ + +struct fread_resp_info + { + ST_INT fd_len; /* length of file data octets */ + ST_UCHAR *filedata; /* pointer to file data octets */ + ST_BOOLEAN more_follows; /* additional file content */ + /* default: SD_TRUE */ + SD_END_STRUCT + }; +typedef struct fread_resp_info FREAD_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_fread (ST_INT chan,FREAD_REQ_INFO *info); +ST_RET mp_fread_resp (MMSREQ_IND *ind, FREAD_RESP_INFO *info); +#else +ST_RET mpl_fread (FREAD_REQ_INFO *info); +ST_RET mpl_fread_resp (ST_UINT32 invoke, FREAD_RESP_INFO *info); +#endif + +/************************************************************************/ +/* FILE CLOSE, Conformance: FIL2 */ +/************************************************************************/ + +/* REQUEST : */ + +struct fclose_req_info + { + ST_INT32 frsmid; /* file read state maching ID */ + }; +typedef struct fclose_req_info FCLOSE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_fclose (ST_INT chan, FCLOSE_REQ_INFO *info); +ST_RET mp_fclose_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_fclose (FCLOSE_REQ_INFO *info); +ST_RET mpl_fclose_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* FILE RENAME, Conformance: FIL3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct frename_req_info + { + ST_INT num_of_cur_fname; /* num of current fname elements*/ + ST_INT num_of_new_fname; /* num of new fname elements */ +/* list of current file names */ +/* FILE_NAME cur_fname_list[ num_of_cur_fname ]; */ +/* list of new file names */ +/* FILE_NAME new_fname_list[ num_of_new_fname ]; */ + SD_END_STRUCT + }; +typedef struct frename_req_info FRENAME_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_frename (ST_INT chan, FRENAME_REQ_INFO *info); +ST_RET mp_frename_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_frename (FRENAME_REQ_INFO *info); +ST_RET mpl_frename_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* FILE DELETE, Conformance: FIL3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct fdelete_req_info + { + ST_INT num_of_fname; /* num of fname elements */ +/* list of file names */ +/* FILE_NAME fname_list[ num_of_fname ]; */ + SD_END_STRUCT + }; +typedef struct fdelete_req_info FDELETE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_fdelete (ST_INT chan, FDELETE_REQ_INFO *info); +ST_RET mp_fdelete_resp (MMSREQ_IND *info); +#else +ST_RET mpl_fdelete (FDELETE_REQ_INFO *info); +ST_RET mpl_fdelete_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* FILE DIRECTORY, Conformance: FIL3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct fdir_req_info + { + ST_BOOLEAN filespec_pres; /* file specification present */ + ST_BOOLEAN cont_after_pres; /* continue after name present */ + ST_INT num_of_fs_fname; /* num of fname elements */ + ST_INT num_of_ca_fname; /* num of cont after elements */ +/* list of current file names */ +/* FILE_NAME fs_fname_list[ num_of_fs_fname ]; */ +/* list of new file names */ +/* FILE_NAME ca_fname_list[ num_of_ca_fname ]; */ + SD_END_STRUCT + }; +typedef struct fdir_req_info FDIR_REQ_INFO; + +/* RESPONSE : */ + +struct fdir_dir_ent + { + ST_UINT32 fsize; /* file size (# bytes) */ + ST_BOOLEAN mtimpres; /* last modified time present */ + time_t mtime; /* last modified time */ + ST_INT num_of_fname; /* num of fname elements */ +/* list of file names */ +/* FILE_NAME fname_list[ num_of_fname ]; */ + SD_END_STRUCT + }; +typedef struct fdir_dir_ent FDIR_DIR_ENT; + +struct fdir_resp_info + { + ST_INT num_dir_ent; /* number of directory entries */ + ST_BOOLEAN more_follows; /* more dir entries follow */ + /* default: SD_FALSE */ +/* list of directory entries */ +/* FDIR_DIR_ENT dir_ent_list [num_dir_ent] */ + SD_END_STRUCT + }; +typedef struct fdir_resp_info FDIR_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_fdir (ST_INT chan,FDIR_REQ_INFO *info); +ST_RET mp_fdir_resp (MMSREQ_IND *ind, FDIR_RESP_INFO *info); +#else +ST_RET mpl_fdir (FDIR_REQ_INFO *info); +ST_RET mpl_fdir_resp (ST_UINT32 invoke, FDIR_RESP_INFO *info); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PFIL_INCLUDED */ + + diff --git a/include/inc/mms_pjou.h b/include/inc/mms_pjou.h new file mode 100644 index 0000000..3c7ea62 --- /dev/null +++ b/include/inc/mms_pjou.h @@ -0,0 +1,299 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pjou.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS journal management services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/15/98 MDE 03 Added entry_form_tag defines */ +/* 08/15/97 MDE 02 BTOD handling changes */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PJOU_INCLUDED +#define MMS_PJOU_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_pvar.h" +#include "mms_mp.h" + +/************************************************************************/ +/************************************************************************/ +/* JOURNAL MANAGEMENT SERVICES */ +/************************************************************************/ +/* The structures below are used to pass JOURNAL MANAGEMENT information */ +/* to/from the MMS primitives. */ +/************************************************************************/ + +/* entry_form_tag value defines */ +#define JE_FORM_DATA 2 +#define JE_FORM_ANNOTATION 3 + +struct var_info + { + ST_CHAR *var_tag; /* variable tag */ + VAR_ACC_DATA value_spec; /* value specification data */ + }; +typedef struct var_info VAR_INFO; + +struct entry_content + { + MMS_BTOD occur_time; /* occurrence time */ + ST_BOOLEAN addl_detail_pres; /* additional detail present */ + ST_INT addl_detail_len; /* length of additional detail */ + ST_UCHAR *addl_detail; /* pointer to additional detail */ + ST_INT16 entry_form_tag; /* entry form tag */ + union + { + struct /* entry form is DATA */ + { + ST_BOOLEAN event_pres; /* event present */ + OBJECT_NAME evcon_name; /* event condition name */ + ST_INT16 cur_state; /* current state */ + /* 0 : disabled */ + /* 1 : idle */ + /* 2 : active */ + ST_BOOLEAN list_of_var_pres; /* list of variables present */ + ST_INT num_of_var; /* number of variables */ + } data; + ST_CHAR *annotation; /* pointer to annotation */ + }ef; +/* for form == DATA, need a */ +/* list of variables */ +/* VAR_INFO list_of_var [num_of_var]; */ + SD_END_STRUCT + }; +typedef struct entry_content ENTRY_CONTENT; + +struct journal_entry + { + ST_INT entry_id_len; /* length of entry identifier */ + ST_UCHAR *entry_id; /* ptr to entry identifier */ + ST_INT orig_ae_len; /* originating app entity len */ + ST_UCHAR *orig_ae; /* originating app entity */ + ENTRY_CONTENT ent_content; /* entry content */ + }; +typedef struct journal_entry JOURNAL_ENTRY; + +/************************************************************************/ +/* READ JOURNAL, Conformance: JOU2 */ +/************************************************************************/ + +/* REQUEST : */ + +struct jread_req_info + { + OBJECT_NAME jou_name; /* journal name */ + ST_BOOLEAN range_start_pres; /* range start spec present */ + ST_INT16 start_tag; /* start tag */ + /* 0 - starting time */ + /* 1 - starting entry */ + MMS_BTOD start_time; /* range starting time */ + ST_INT start_entry_len; /* length of starting entry */ + ST_UCHAR *start_entry; /* pointer to starting entry */ + ST_BOOLEAN range_stop_pres; /* range stop spec present */ + ST_INT16 stop_tag; /* stop tag */ + /* 0 - ending time */ + /* 1 - number of entries */ + MMS_BTOD end_time; /* range ending time */ + ST_INT32 num_of_entries; /* number of entries */ + ST_BOOLEAN list_of_var_pres; /* list of variables present */ + ST_INT num_of_var; /* number of variables */ + ST_BOOLEAN sa_entry_pres; /* start after entry present */ + MMS_BTOD time_spec; /* time specification */ + ST_INT entry_spec_len; /* entry specification length */ + ST_UCHAR *entry_spec; /* entry specification */ +/* list of pointers to variables*/ +/* ST_CHAR *list_of_var [num_of_var]; */ + SD_END_STRUCT + }; +typedef struct jread_req_info JREAD_REQ_INFO; + +/* RESPONSE : */ + +struct jread_resp_info + { + ST_INT num_of_jou_entry; /* number of journal entries */ + ST_BOOLEAN more_follows; /* default = false */ +/* list of journal entries */ +/* JOURNAL_ENTRY list_of_jou_entry [num_of_jou_entry]; */ + SD_END_STRUCT + }; +typedef struct jread_resp_info JREAD_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_jread (ST_INT chan, JREAD_REQ_INFO *info); +ST_RET mp_jread_resp (MMSREQ_IND *ind, JREAD_RESP_INFO *info); +#else +ST_RET mpl_jread (JREAD_REQ_INFO *info); +ST_RET mpl_jread_resp (ST_UINT32 invoke, JREAD_RESP_INFO *info); +#endif + +/************************************************************************/ +/* WRITE JOURNAL, Conformance: JOU1 */ +/************************************************************************/ + +/* REQUEST : */ + +struct jwrite_req_info + { + OBJECT_NAME jou_name; /* journal name */ + ST_INT num_of_jou_entry; /* number of journal entries */ +/* list of journal entries */ +/* ENTRY_CONTENT list_of_jou_entry [num_of_jou_entry]; */ + SD_END_STRUCT + }; +typedef struct jwrite_req_info JWRITE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_jwrite (ST_INT chan, JWRITE_REQ_INFO *info); +ST_RET mp_jwrite_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_jwrite (JWRITE_REQ_INFO *info); +ST_RET mpl_jwrite_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* INITIALIZE JOURNAL, Conformance: JOU2 */ +/************************************************************************/ + +/* REQUEST : */ + +struct jinit_req_info + { + OBJECT_NAME jou_name; /* journal name */ + ST_BOOLEAN limit_spec_pres; /* limit specification present */ + MMS_BTOD limit_time; /* limiting time */ + ST_BOOLEAN limit_entry_pres; /* limiting entry present */ + ST_INT limit_entry_len; /* length of limiting entry */ + ST_UCHAR *limit_entry; /* pointer to limiting entry */ + SD_END_STRUCT + }; +typedef struct jinit_req_info JINIT_REQ_INFO; + +/* RESPONSE : */ + +struct jinit_resp_info + { + ST_UINT32 del_entries; /* deleted entries */ + }; +typedef struct jinit_resp_info JINIT_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_jinit (ST_INT chan, JINIT_REQ_INFO *info); +ST_RET mp_jinit_resp (MMSREQ_IND *ind, JINIT_RESP_INFO *info); +#else +ST_RET mpl_jinit (JINIT_REQ_INFO *info); +ST_RET mpl_jinit_resp (ST_UINT32 invoke, JINIT_RESP_INFO *info); +#endif + +/************************************************************************/ +/* REPORT JOURNAL STATUS, Conformance: JOU2 */ +/************************************************************************/ + +/* REQUEST : */ + +struct jstat_req_info + { + OBJECT_NAME jou_name; /* journal name */ + }; +typedef struct jstat_req_info JSTAT_REQ_INFO; + +/* RESPONSE : */ + +struct jstat_resp_info + { + ST_UINT32 cur_entries; /* current entries */ + ST_BOOLEAN mms_deletable; /* MMS deletable */ + SD_END_STRUCT + }; +typedef struct jstat_resp_info JSTAT_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_jstat (ST_INT chan, JSTAT_REQ_INFO *info); +ST_RET mp_jstat_resp (MMSREQ_IND *ind, JSTAT_RESP_INFO *info); +#else +ST_RET mpl_jstat (JSTAT_REQ_INFO *info); +ST_RET mpl_jstat_resp (ST_UINT32 invoke, JSTAT_RESP_INFO *info); +#endif + +/************************************************************************/ +/* CREATE JOURNAL */ +/************************************************************************/ + +/* REQUEST : */ + +struct jcreate_req_info + { + OBJECT_NAME jou_name; /* journal name */ + }; +typedef struct jcreate_req_info JCREATE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_jcreate (ST_INT chan, JCREATE_REQ_INFO *info); +ST_RET mp_jcreate_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_jcreate (JCREATE_REQ_INFO *info); +ST_RET mpl_jcreate_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DELETE JOURNAL */ +/************************************************************************/ + +/* REQUEST : */ + +struct jdelete_req_info + { + OBJECT_NAME jou_name; /* journal name */ + }; +typedef struct jdelete_req_info JDELETE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_jdelete (ST_INT chan, JDELETE_REQ_INFO *info); +ST_RET mp_jdelete_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_jdelete (JDELETE_REQ_INFO *info); +ST_RET mpl_jdelete_resp (ST_UINT32 invoke); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PJOU_INCLUDED */ diff --git a/include/inc/mms_pocs.h b/include/inc/mms_pocs.h new file mode 100644 index 0000000..b52bff2 --- /dev/null +++ b/include/inc/mms_pocs.h @@ -0,0 +1,120 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pocs.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS operator communication services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_POCS_INCLUDED +#define MMS_POCS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_mp.h" + +/************************************************************************/ +/************************************************************************/ +/* OPERATOR COMMUNICATION FUNCTIONS */ +/************************************************************************/ +/* The structures below are used to pass OPERATOR COMMUNICATION */ +/* operation information to/from the MMS primitives. */ +/************************************************************************/ + +/************************************************************************/ +/* OUTPUT OPERATION, Conformance: OCS1 */ +/************************************************************************/ + +/* REQUEST : */ + +struct output_req_info + { + ST_CHAR station_name [MAX_IDENT_LEN+1]; /* operator station name */ + ST_INT data_count; /* number of data strings */ +/* list of pointers to the output data */ +/* ST_CHAR *output_data [data_count]; */ + SD_END_STRUCT + }; +typedef struct output_req_info OUTPUT_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_output (ST_INT chan, OUTPUT_REQ_INFO *info); +ST_RET mp_output_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_output (OUTPUT_REQ_INFO *info); +ST_RET mpl_output_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* INPUT OPERATION, Conformance: OCS2 */ +/************************************************************************/ + +/* REQUEST : */ + +struct input_req_info + { + ST_CHAR station_name [MAX_IDENT_LEN+1]; /* operator station name */ + ST_BOOLEAN echo; /* echo, default: SD_TRUE */ + ST_BOOLEAN timeout_pres; /* input timeout present ind */ + ST_UINT32 timeout; /* input timeout */ + ST_BOOLEAN prompt_pres; /* prompt data present ind */ + ST_INT prompt_count; /* number of prompt strings */ +/* list of pointers to the prompt data */ +/* ST_CHAR *prompt_data [prompt_count]; */ + SD_END_STRUCT + }; +typedef struct input_req_info INPUT_REQ_INFO; + +/* RESPONSE : */ + +struct input_resp_info + { + ST_CHAR *input_resp; /* input response */ + }; +typedef struct input_resp_info INPUT_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_input (ST_INT chan, INPUT_REQ_INFO *info); +ST_RET mp_input_resp (MMSREQ_IND *ind, INPUT_RESP_INFO *info); +#else +ST_RET mpl_input (INPUT_REQ_INFO *info); +ST_RET mpl_input_resp (ST_UINT32 invoke, INPUT_RESP_INFO *info); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_POCS_INCLUDED */ diff --git a/include/inc/mms_pprg.h b/include/inc/mms_pprg.h new file mode 100644 index 0000000..b2259c1 --- /dev/null +++ b/include/inc/mms_pprg.h @@ -0,0 +1,287 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pprg.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS program invocation management */ +/* services at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/14/97 RKR 02 Format changes */ +/* 06/09/97 MDE 01 Added PI State defines (from mms_vprg.h) */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PPRG_INCLUDED +#define MMS_PPRG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/************************************************************************/ +/* PROGRAM INVOCATION MANAGEMENT SERVICES */ +/************************************************************************/ +/* The structures below are used to pass PROGRAM INVOCATION MANAGEMENT */ +/* information to/from the MMS primitives. */ +/************************************************************************/ +/* use these defines to determine whether string is simple or encoded */ +/* If encoded, the data pointer points to a complete ASN.1 EXTERNAL */ + +#define ARG_TYPE_SIMPLE 0 +#define ARG_TYPE_ENCODED 1 + +/************************************************************************/ +/* CREATE PROGRAM INVOCATION */ +/************************************************************************/ + +/* REQUEST : */ + +struct crepi_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + ST_INT num_of_dnames; /* number of domain names */ + ST_BOOLEAN reusable; + ST_BOOLEAN monitor_pres; /* monitoring present */ + ST_BOOLEAN monitor; /* SD_TRUE : permanent monitoring */ + /* SD_FALSE: current monitoring */ + +/* list of ptrs to domain names */ +/* ST_CHAR *dnames_list [num_of_dnames]; */ + SD_END_STRUCT + }; +typedef struct crepi_req_info CREPI_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_crepi (ST_INT chan, CREPI_REQ_INFO *info); +ST_RET mp_crepi_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_crepi (CREPI_REQ_INFO *info); +ST_RET mpl_crepi_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DELETE PROGRAM INVOCATION */ +/************************************************************************/ + +/* REQUEST : */ + +struct delpi_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + }; +typedef struct delpi_req_info DELPI_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_delpi (ST_INT chan, DELPI_REQ_INFO *info); +ST_RET mp_delpi_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_delpi (DELPI_REQ_INFO *info); +ST_RET mpl_delpi_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* START */ +/************************************************************************/ + +/* REQUEST : */ + +struct start_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + + ST_INT16 start_arg_type; /* start argument present */ + ST_BOOLEAN start_arg_pres; /* start argument present */ + ST_INT start_arg_len; /* Only used for ENCODED */ + ST_UCHAR *start_arg; /* pointer to start argument */ + SD_END_STRUCT + }; +typedef struct start_req_info START_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_start (ST_INT chan, START_REQ_INFO *info); +ST_RET mp_start_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_start (START_REQ_INFO *info); +ST_RET mpl_start_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* STOP */ +/************************************************************************/ + +/* REQUEST : */ + +struct stop_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + }; +typedef struct stop_req_info STOP_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_stop (ST_INT chan, STOP_REQ_INFO *info); +ST_RET mp_stop_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_stop (STOP_REQ_INFO *info); +ST_RET mpl_stop_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* RESUME */ +/************************************************************************/ + +/* REQUEST : */ + +struct resume_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + + ST_INT16 resume_arg_type; /* resume argument present */ + ST_BOOLEAN resume_arg_pres; /* resume argument present */ + ST_INT resume_arg_len; /* Only used for ENCODED */ + ST_UCHAR *resume_arg; /* pointer to resume argument */ + }; +typedef struct resume_req_info RESUME_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_resume (ST_INT chan, RESUME_REQ_INFO *info); +ST_RET mp_resume_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_resume (RESUME_REQ_INFO *info); +ST_RET mpl_resume_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* RESET */ +/************************************************************************/ + +/* REQUEST : */ + +struct reset_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + }; +typedef struct reset_req_info RESET_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_reset (ST_INT chan, RESET_REQ_INFO *info); +ST_RET mp_reset_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_reset (RESET_REQ_INFO *info); +ST_RET mpl_reset_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* KILL */ +/************************************************************************/ + +/* REQUEST : */ + +struct kill_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + }; +typedef struct kill_req_info KILL_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_kill (ST_INT chan, KILL_REQ_INFO *info); +ST_RET mp_kill_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_kill (KILL_REQ_INFO *info); +ST_RET mpl_kill_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET PROGRAM INVOCATION ATTRIBUTE */ +/************************************************************************/ + +#define PI_NON_EXISTENT 0 +#define PI_UNRUNNABLE 1 +#define PI_IDLE 2 +#define PI_RUNNING 3 +#define PI_STOPPED 4 +#define PI_STARTING 5 +#define PI_STOPPING 6 +#define PI_RESUMING 7 +#define PI_RESETTING 8 + +/* REQUEST : */ + +struct getpi_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + }; +typedef struct getpi_req_info GETPI_REQ_INFO; + +/* RESPONSE : */ + +struct getpi_resp_info + { + ST_INT16 state; /* program invocation state */ + ST_BOOLEAN mms_deletable; /* MMS deletable */ + ST_BOOLEAN reusable; /* Reusable */ + ST_BOOLEAN monitor; /* SD_TRUE : permanent monitoring */ + /* SD_FALSE: current monitoring */ + + ST_INT16 start_arg_type; /* start argument present */ + ST_INT start_arg_len; /* Only used for ENCODED */ + ST_UCHAR *start_arg; /* pointer to start argument */ + + ST_INT num_of_dnames; /* number of domain names */ +/* list of ptrs to domain names */ +/* ST_CHAR *dnames_list [num_of_dnames]; */ + SD_END_STRUCT + }; +typedef struct getpi_resp_info GETPI_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getpi (ST_INT chan, GETPI_REQ_INFO *info); +ST_RET mp_getpi_resp (MMSREQ_IND *ind, GETPI_RESP_INFO *info); +#else +ST_RET mpl_getpi (GETPI_REQ_INFO *info); +ST_RET mpl_getpi_resp (ST_UINT32 invoke, GETPI_RESP_INFO *info); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PPRG_INCLUDED */ diff --git a/include/inc/mms_psem.h b/include/inc/mms_psem.h new file mode 100644 index 0000000..bdca016 --- /dev/null +++ b/include/inc/mms_psem.h @@ -0,0 +1,338 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_psem.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS semaphore management services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/10/97 MDE 02 Changed entry_class to ST_INT8 */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PSEM_INCLUDED +#define MMS_PSEM_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_mp.h" + +/************************************************************************/ +/************************************************************************/ +/* SEMAPHORE MANAGEMENT FUNCTIONS */ +/************************************************************************/ +/* The structures below are used to pass SEMAPHORE MANAGEMENT operation */ +/* information to/from the MMS primitives. */ +/************************************************************************/ + +/************************************************************************/ +/* TAKE CONTROL, Conformance: SEM1/SEM3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct takectrl_req_info + { + OBJECT_NAME sem_name; /* semaphore name */ + ST_BOOLEAN named_token_pres; /* named token present ind */ + ST_CHAR named_token[MAX_IDENT_LEN+1]; /* named token */ + ST_UCHAR priority; /* priority */ + /* 0 - highest */ + /* 64 - normal (default) */ + /* 127 - lowest */ + ST_BOOLEAN acc_delay_pres; /* acceptable delay present ind */ + ST_UINT32 acc_delay; /* acceptable delay */ + ST_BOOLEAN ctrl_timeout_pres; /* control timeout present */ + ST_UINT32 ctrl_timeout; /* control timeout */ + ST_BOOLEAN abrt_on_timeout_pres; /* Abort on Timeout present */ + ST_BOOLEAN abrt_on_timeout; /* Abort on Timeout */ + ST_BOOLEAN rel_conn_lost; /* relenquish if connection lost*/ + ST_BOOLEAN app_preempt_pres; /* app preempt present ind */ + ST_INT app_len; /* length of app. to preempt */ + ST_UCHAR *app_preempt; /* application to preempt */ + SD_END_STRUCT + }; +typedef struct takectrl_req_info TAKECTRL_REQ_INFO; + +/* RESPONSE : */ + +struct takectrl_resp_info + { + ST_INT16 resp_tag; /* response tag */ + /* 0 : NULL response */ + /* 1 : named token response */ + ST_CHAR named_token [MAX_IDENT_LEN+1]; /* named token identifier */ + SD_END_STRUCT + }; +typedef struct takectrl_resp_info TAKECTRL_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_takectrl (ST_INT chan, TAKECTRL_REQ_INFO *info); +ST_RET mp_takectrl_resp (MMSREQ_IND *ind, TAKECTRL_RESP_INFO *info); +#else +ST_RET mpl_takectrl (TAKECTRL_REQ_INFO *info); +ST_RET mpl_takectrl_resp (ST_UINT32 invoke, TAKECTRL_RESP_INFO *info); +#endif + +/************************************************************************/ +/* RELINQUISH CONTROL, Conformance: SEM1/SEM3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct relctrl_req_info + { + OBJECT_NAME sem_name; /* semaphore name */ + ST_BOOLEAN named_token_pres; /* named token present ind */ + ST_CHAR named_token [MAX_IDENT_LEN+1];/* named token */ + SD_END_STRUCT + }; +typedef struct relctrl_req_info RELCTRL_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_relctrl (ST_INT chan, RELCTRL_REQ_INFO *info); +ST_RET mp_relctrl_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_relctrl (RELCTRL_REQ_INFO *info); +ST_RET mpl_relctrl_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* REPORT SEMAPHORE STATUS, Conformance: SEM1/SEM3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct rsstat_req_info + { + OBJECT_NAME sem_name; /* semaphore name */ + }; +typedef struct rsstat_req_info RSSTAT_REQ_INFO; + +/* RESPONSE : */ + +struct rsstat_resp_info + { + ST_BOOLEAN mms_deletable; /* mms deletable */ + ST_INT16 tclass; /* class: token (0) or pool (1) */ + ST_UINT16 num_of_tokens; /* number of tokens */ + ST_UINT16 num_of_owned; /* number of owned tokens */ + ST_UINT16 num_of_hung; /* number of hung tokens */ + SD_END_STRUCT + }; +typedef struct rsstat_resp_info RSSTAT_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_rsstat (ST_INT chan, RSSTAT_REQ_INFO *info); +ST_RET mp_rsstat_resp (MMSREQ_IND *ind, RSSTAT_RESP_INFO *info); +#else +ST_RET mpl_rsstat (RSSTAT_REQ_INFO *info); +ST_RET mpl_rsstat_resp (ST_UINT32 invoke, RSSTAT_RESP_INFO *info); +#endif + +/************************************************************************/ +/* REPORT POOL SEMAPHORE STATUS, Conformance: SEM1/SEM3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct rspool_req_info + { + OBJECT_NAME sem_name; /* semaphore name */ + ST_BOOLEAN start_after_pres; /* start after name present ind */ + ST_CHAR start_after [MAX_IDENT_LEN+1]; /* name to start after */ + SD_END_STRUCT + }; +typedef struct rspool_req_info RSPOOL_REQ_INFO; + +/* RESPONSE : */ + +#if !defined (USE_COMPACT_MMS_STRUCTS) + +struct token_id + { + ST_INT16 token_tag; /* named token tag */ + /* 0 : free named token */ + /* 1 : owned named token */ + /* 2 : hung named token */ + ST_CHAR named_token[MAX_IDENT_LEN+1];/* named token id */ + SD_END_STRUCT + }; + +#else /* Use compact form */ + +struct token_id + { + ST_INT16 token_tag; /* named token tag */ + /* 0 : free named token */ + /* 1 : owned named token */ + /* 2 : hung named token */ + ST_CHAR *named_token; /* named token id */ + SD_END_STRUCT + }; +#endif + +typedef struct token_id TOKEN_ID; + +struct rspool_resp_info + { + ST_INT16 num_of_tokens; /* number of named tokens */ + ST_BOOLEAN more_follows; /* more follows indicator */ +/* list of named tokens */ +/* TOKEN_ID named_token_list [num_of_tokens]; */ + SD_END_STRUCT + }; +typedef struct rspool_resp_info RSPOOL_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_rspool (ST_INT chan, RSPOOL_REQ_INFO *info); +ST_RET mp_rspool_resp (MMSREQ_IND *ind, RSPOOL_RESP_INFO *info); +#else +ST_RET mpl_rspool (RSPOOL_REQ_INFO *info); +ST_RET mpl_rspool_resp (ST_UINT32 invoke, RSPOOL_RESP_INFO *info); +#endif + + +/************************************************************************/ +/* REPORT SEMAPHORE ENTRY STATUS, Conformance: SEM1/SEM3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct rsentry_req_info + { + OBJECT_NAME sem_name; /* semaphore name */ + ST_INT16 state; /* state: 0 : queued */ + /* 1 : owner */ + /* 2 : hung */ + ST_BOOLEAN start_after_pres; /* start after id present ind */ + ST_INT sa_len; /* length of entry id to start */ + /* after */ + ST_UCHAR *start_after; /* pointer to entry id to start */ + /* after */ + SD_END_STRUCT + }; +typedef struct rsentry_req_info RSENTRY_REQ_INFO; + +/* RESPONSE : */ + +struct semaphore_entry + { + ST_INT ei_len; /* entry id length */ + ST_UCHAR *entry_id; /* entry id */ + ST_INT8 entry_class; /* entry class */ + ST_INT app_ref_len; /* app ref length (obj ident) */ + ST_UCHAR *app_ref; /* application reference */ + ST_BOOLEAN named_token_pres; /* named token present ind */ + ST_CHAR named_token[MAX_IDENT_LEN+1];/* named token */ + ST_UCHAR priority; /* priority */ + /* 0 - highest */ + /* 64 - normal (default) */ + /* 127 - lowest */ + ST_BOOLEAN rem_timeout_pres; /* relinquish timeout present */ + ST_UINT32 rem_timeout; /* relinquish timeout */ + ST_BOOLEAN abrt_on_timeout_pres; /* Abort On Timeout present */ + ST_BOOLEAN abrt_on_timeout; /* Abort On Timeout */ + ST_BOOLEAN rel_conn_lost; /* relenquish if connection lost*/ + SD_END_STRUCT + }; +typedef struct semaphore_entry SEMAPHORE_ENTRY; + +struct rsentry_resp_info + { + ST_INT num_of_sent; /* number of semaphore entries */ + ST_BOOLEAN more_follows; /* more follows indicator */ +/* list of semaphore entries */ +/* SEMAPHORE_ENTRY sent_list [num_of_sent]; */ + SD_END_STRUCT + }; +typedef struct rsentry_resp_info RSENTRY_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_rsentry (ST_INT chan, RSENTRY_REQ_INFO *info); +ST_RET mp_rsentry_resp (MMSREQ_IND *ind, RSENTRY_RESP_INFO *info); +#else +ST_RET mpl_rsentry (RSENTRY_REQ_INFO *info); +ST_RET mpl_rsentry_resp (ST_UINT32 invoke, RSENTRY_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DEFINE SEMAPHORE, Conformance: SEM3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct defsem_req_info + { + OBJECT_NAME sem_name; /* semaphore name */ + ST_UINT16 num_of_tokens; /* number of tokens */ + SD_END_STRUCT + }; +typedef struct defsem_req_info DEFSEM_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_defsem (ST_INT chan, DEFSEM_REQ_INFO *info); +ST_RET mp_defsem_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_defsem (DEFSEM_REQ_INFO *info); +ST_RET mpl_defsem_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DELETE SEMAPHORE, Conformance: SEM3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct delsem_req_info + { + OBJECT_NAME sem_name; /* semaphore name */ + }; +typedef struct delsem_req_info DELSEM_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_delsem (ST_INT chan, DELSEM_REQ_INFO *info); +ST_RET mp_delsem_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_delsem (DELSEM_REQ_INFO *info); +ST_RET mpl_delsem_resp (ST_UINT32 invoke); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PSEM_INCLUDED */ diff --git a/include/inc/mms_pvar.h b/include/inc/mms_pvar.h new file mode 100644 index 0000000..1043150 --- /dev/null +++ b/include/inc/mms_pvar.h @@ -0,0 +1,683 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pvar.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS variable access services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/04/06 JRB 03 Add ARE_OBJ_VALUE_INVALID (new in MMS V2). */ +/* 12/12/02 JRB 02 Add ASN1_ENC_CTXT arg to mpl_info */ +/* 08/13/97 RKR 01 format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PVAR_INCLUDED +#define MMS_PVAR_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_mp.h" + +/************************************************************************/ +/************************************************************************/ +/* DEFINES FOR THE VARIABLE ACCESS SERVICES */ +/************************************************************************/ + +/* defines to be used for addr_tag */ +#define NUM_ADDR 0 /* numeric address */ +#define SYM_ADDR 1 /* symbolic address */ +#define UNCON_ADDR 2 /* unconstrained address */ + +/* #defines to be used for var_spec_tag */ +#define VA_SPEC_NAMED 0 +#define VA_SPEC_ADDRESSED 1 +#define VA_SPEC_DESCRIBED 2 +#define VA_SPEC_SCATTERED 3 +#define VA_SPEC_INVALIDATED 4 + +/* #defines to be used for var_acc_tag */ +#define VAR_ACC_VARLIST 0 /* list of variables */ +#define VAR_ACC_NAMEDLIST 1 /* variable list name */ + +/* defines to be used for 'access result' */ +#define ACC_RSLT_SUCCESS 1 +#define ACC_RSLT_FAILURE 0 + +/* defines to be used for DataAccessError codes */ +#define ARE_OBJ_INVALIDATED 0 +#define ARE_HW_FAULT 1 +#define ARE_TEMP_UNAVAIL 2 +#define ARE_OBJ_ACCESS_DENIED 3 +#define ARE_OBJ_UNDEFINED 4 +#define ARE_INVAL_ADDR 5 +#define ARE_TYPE_UNSUPPORTED 6 +#define ARE_TYPE_INCONSISTENT 7 +#define ARE_OBJ_ATTR_INCONSISTENT 8 +#define ARE_OBJ_ACC_UNSUPPORTED 9 +#define ARE_OBJ_NONEXISTENT 10 +#define ARE_OBJ_VALUE_INVALID 11 + +/* #defines to be used for 'resp_tag' (write response) */ +#define WR_RSLT_SUCCESS 1 +#define WR_RSLT_FAILURE 0 + +/* #defines to be used for 'scope' selector (used for delete var, */ +/* varlist, type requests) */ +#define SPECIFIC_SCOPE 0 +#define ALL_AA_SCOPE 1 +#define ALL_DOM_SCOPE 2 +#define ALL_VMD_SCOPE 3 + + +/************************************************************************/ +/************************************************************************/ +/* The structures below are used to pass VARIABLE ACCESS information */ +/* to/from the MMS primitives. */ +/************************************************************************/ + +struct unconst_addr + { + ST_INT unc_len; /* unconstrained address length */ + ST_UCHAR *unc_ptr; /* unconstrained address ptr */ + SD_END_STRUCT + }; +typedef struct unconst_addr UNCONST_ADDR; + +struct var_acc_addr + { + ST_INT16 addr_tag; /* address tag */ + union + { + ST_UINT32 num_addr; /* numeric address */ + ST_CHAR *sym_addr; /* symbolic address */ + UNCONST_ADDR unc_addr; /* unconstrained address */ + } addr; + }; +typedef struct var_acc_addr VAR_ACC_ADDR; + +struct var_acc_data + { + ST_INT len; /* len of variable access data */ + ST_UCHAR *data; /* ptr to variable access data */ + }; +typedef struct var_acc_data VAR_ACC_DATA; + +struct var_acc_tspec + { + ST_INT len; /* len of type specification */ + ST_UCHAR *data; /* ptr to type specification */ + }; +typedef struct var_acc_tspec VAR_ACC_TSPEC; + +struct scattered_access + { + ST_INT len; /* len of scattered access descr*/ + ST_UCHAR *data; /* ptr to scattered access descr*/ + }; +typedef struct scattered_access SCATTERED_ACCESS; + +struct alternate_access + { + ST_INT len; /* len of alternate access data */ + ST_UCHAR *data; /* ptr to alternate access data */ + }; +typedef struct alternate_access ALTERNATE_ACCESS; + +struct variable_descr + { + VAR_ACC_ADDR address; /* variable address */ + VAR_ACC_TSPEC type; /* variable type */ + }; +typedef struct variable_descr VARIABLE_DESCR; + +struct variable_spec + { + ST_INT16 var_spec_tag; /* variable specification tag */ + union + { + OBJECT_NAME name; /* name */ + VAR_ACC_ADDR address; /* address */ + VARIABLE_DESCR var_descr; /* variable description */ + SCATTERED_ACCESS sa_descr; /* scattered access description */ + } vs; + }; +typedef struct variable_spec VARIABLE_SPEC; + +struct variable_list + { + VARIABLE_SPEC var_spec; /* variable access specification*/ + ST_BOOLEAN alt_access_pres; /* alternate access present */ + ALTERNATE_ACCESS alt_access; /* alternate access */ + }; +typedef struct variable_list VARIABLE_LIST; + +struct var_acc_spec + { + ST_INT16 var_acc_tag; /* variable access tag */ + OBJECT_NAME vl_name; /* variable list name */ + ST_INT num_of_variables; /* number of variables */ +/* list of variables */ +/* VARIABLE_LIST var_list [num_of_variables]; */ + SD_END_STRUCT + }; +typedef struct var_acc_spec VAR_ACC_SPEC; + +struct access_result + { + ST_INT16 acc_rslt_tag; /* access result tag */ + ST_INT16 failure; /* data access error */ + VAR_ACC_DATA va_data; /* success data */ + }; +typedef struct access_result ACCESS_RESULT; + +struct write_result + { + ST_INT16 resp_tag; /* response tag */ + ST_INT16 failure; /* data access error */ + SD_END_STRUCT + }; +typedef struct write_result WRITE_RESULT; + + +/************************************************************************/ +/************************************************************************/ +/* VARIABLE READ */ +/************************************************************************/ + +/* REQUEST : */ + +struct read_req_info + { + ST_BOOLEAN spec_in_result; /* specification with result, */ + /* default to false */ + VAR_ACC_SPEC va_spec; /* variable access spec */ +/* which "includes" */ +/* a list of variables */ +/* VARIABLE_LIST var_list [va_spec.num_of_variables]; */ +/* SD_END_STRUCT */ + }; +typedef struct read_req_info READ_REQ_INFO; + +/* RESPONSE : */ + +struct read_resp_info + { + ST_BOOLEAN va_spec_pres; /* variable access spec present */ + ST_INT num_of_acc_result; /* number of access result */ + ACCESS_RESULT *acc_rslt_list; /* ptr to list of access result */ + VAR_ACC_SPEC va_spec; /* variable access spec */ +/* which "includes" */ +/* a list of variables */ +/* VARIABLE_LIST var_list [va_spec.num_of_variables]; */ +/* list of access result */ +/* ACCESS_RESULT acc_result_list [num_of_acc_result]; */ +/* SD_END_STRUCT */ + }; +typedef struct read_resp_info READ_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_read (ST_INT chan, READ_REQ_INFO *info); +ST_RET mp_read_resp (MMSREQ_IND *ind, READ_RESP_INFO *info); +#else +ST_RET mpl_read (READ_REQ_INFO *info); +ST_RET mpl_read_resp (ST_UINT32 invoke, READ_RESP_INFO *info); +#endif + +/************************************************************************/ +/* VARIABLE WRITE */ +/************************************************************************/ + +/* REQUEST : */ + +struct write_req_info + { + ST_INT num_of_data; /* number of data */ + VAR_ACC_DATA *va_data; /* ptr to list of variable data */ + VAR_ACC_SPEC va_spec; /* variable access spec */ +/* which "includes" */ +/* a list of variables */ +/* VARIABLE_LIST var_list [va_spec.num_of_variables]; */ +/* list of variable data */ +/* VAR_ACC_DATA var_data_list [num_of_data]; */ + }; +typedef struct write_req_info WRITE_REQ_INFO; + +/* RESPONSE : */ + +struct write_resp_info + { + ST_INT num_of_result; +/* WRITE_RESULT wr_result[num_of_result] */ + SD_END_STRUCT + }; +/* Where: */ +/* num_of_result = The number of members in wr_result. This */ +/* number should match the number of */ +/* variables included in the Write request. */ +/* */ +/* wr_result = Array of structures of type write_result */ +/* containing the results of the write */ +/* (success or failure) for each variable */ +/* written. The result array members should */ +/* align with the var_list members that were */ +/* included in the Write request. */ +typedef struct write_resp_info WRITE_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_write (ST_INT chan, WRITE_REQ_INFO *info); +ST_RET mp_write_resp (MMSREQ_IND *ind, WRITE_RESP_INFO *info); +#else +ST_RET mpl_write (WRITE_REQ_INFO *info); +ST_RET mpl_write_resp (ST_UINT32 invoke, WRITE_RESP_INFO *info); +#endif + +/************************************************************************/ +/* INFORMATION REPORT */ +/************************************************************************/ + +/* REQUEST : */ + +struct info_req_info + { + ST_INT num_of_acc_result; /* number of access result */ + ACCESS_RESULT *acc_rslt_list; /* ptr to list of access result */ + VAR_ACC_SPEC va_spec; /* variable access spec */ +/* which "includes" */ +/* a list of variables */ +/* VARIABLE_LIST var_list [va_spec.num_of_variables]; */ +/* list of access result */ +/* ACCESS_RESULT acc_result_list [num_of_acc_result]; */ +/* SD_END_STRUCT */ + }; +typedef struct info_req_info INFO_REQ_INFO; + +/* No Response : (unsolicited) */ + +#ifndef MMS_LITE +ST_RET mp_info (ST_INT chan, INFO_REQ_INFO *info); +#else +ST_RET mpl_info (ASN1_ENC_CTXT *aCtx, INFO_REQ_INFO *info); +#endif + +/************************************************************************/ +/* DEFINE VARIABLE NAME */ +/************************************************************************/ + +/* REQUEST : */ + +struct defvar_req_info + { + OBJECT_NAME name; /* object name */ + VAR_ACC_ADDR address; /* address */ + ST_BOOLEAN type_spec_pres; /* type specification present */ + VAR_ACC_TSPEC type_spec; /* type specification */ + }; +typedef struct defvar_req_info DEFVAR_REQ_INFO; + + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_defvar (ST_INT chan, DEFVAR_REQ_INFO *info); +ST_RET mp_defvar_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_defvar (DEFVAR_REQ_INFO *info); +ST_RET mpl_defvar_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET VARIABLE NAME DEFINITION */ +/************************************************************************/ + +/* REQUEST : */ + +#define GETVAR_NAME 0 +#define GETVAR_ADDR 1 + +struct getvar_req_info + { + ST_INT16 req_tag; /* request tag */ + /* 0 : object name request */ + /* 1 : address request */ + OBJECT_NAME name; /* object name */ + VAR_ACC_ADDR address; /* address */ + }; +typedef struct getvar_req_info GETVAR_REQ_INFO; + +/* RESPONSE : */ + +struct getvar_resp_info + { + ST_BOOLEAN mms_deletable; /* MMS deletable */ + ST_BOOLEAN address_pres; /* address present */ + VAR_ACC_ADDR address; /* address */ + VAR_ACC_TSPEC type_spec; /* type specification */ + }; +typedef struct getvar_resp_info GETVAR_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getvar (ST_INT chan, GETVAR_REQ_INFO *info); +ST_RET mp_getvar_resp (MMSREQ_IND *ind, GETVAR_RESP_INFO *info); +#else +ST_RET mpl_getvar (GETVAR_REQ_INFO *info); +ST_RET mpl_getvar_resp (ST_UINT32 invoke, GETVAR_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DELETE VARIABLE NAME */ +/************************************************************************/ + +/* REQUEST : */ + +#define DELVAR_SPEC 0 +#define DELVAR_AA 1 +#define DELVAR_DOM 2 +#define DELVAR_VMD 3 + +struct delvar_req_info + { + ST_INT16 scope; /* scope of delete (see above) */ + ST_BOOLEAN dname_pres; /* domain name present */ + ST_CHAR dname [MAX_IDENT_LEN+1]; /* domain name */ + ST_BOOLEAN vnames_pres; /* variable names present */ + ST_INT num_of_vnames; /* number of variable names */ +/* list of variable names */ +/* OBJECT_NAME vname_list [num_of_vnames]; */ + SD_END_STRUCT + }; +typedef struct delvar_req_info DELVAR_REQ_INFO; + + +/* RESPONSE : */ + +struct delvar_resp_info + { + ST_UINT32 num_matched; /* Number matched */ + ST_UINT32 num_deleted; /* Number deleted */ + }; +typedef struct delvar_resp_info DELVAR_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_delvar (ST_INT chan, DELVAR_REQ_INFO *info); +ST_RET mp_delvar_resp (MMSREQ_IND *ind,DELVAR_RESP_INFO *info); +#else +ST_RET mpl_delvar (DELVAR_REQ_INFO *info); +ST_RET mpl_delvar_resp (ST_UINT32 invoke, DELVAR_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DEFINE SCATTERED ACCESS */ +/************************************************************************/ + +/* REQUEST : */ + +struct defscat_req_info + { + OBJECT_NAME sa_name; /* scattered access name */ + SCATTERED_ACCESS sa_descr; /* scattered access description */ + }; +typedef struct defscat_req_info DEFSCAT_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_defscat (ST_INT chan, DEFSCAT_REQ_INFO *info); +ST_RET mp_defscat_resp (MMSREQ_IND *info); +#else +ST_RET mpl_defscat (DEFSCAT_REQ_INFO *info); +ST_RET mpl_defscat_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET SCATTERED ACCESS ATTRIBUTES */ +/************************************************************************/ + +/* REQUEST : */ + +struct getscat_req_info + { + OBJECT_NAME sa_name; /* scattered access name */ + }; +typedef struct getscat_req_info GETSCAT_REQ_INFO; + +/* RESPONSE : */ + +struct getscat_resp_info + { + ST_BOOLEAN mms_deletable; /* MMS deletable */ + SCATTERED_ACCESS sa_descr; /* scattered access description */ + }; +typedef struct getscat_resp_info GETSCAT_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getscat (ST_INT chan, GETSCAT_REQ_INFO *info); +ST_RET mp_getscat_resp (MMSREQ_IND *ind, GETSCAT_RESP_INFO *info); +#else +ST_RET mpl_getscat (GETSCAT_REQ_INFO *info); +ST_RET mpl_getscat_resp (ST_UINT32 invoke, GETSCAT_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DEFINE NAMED VARIABLE LIST */ +/************************************************************************/ + +/* REQUEST : */ + +struct defvlist_req_info + { + OBJECT_NAME vl_name; /* variable list name */ + ST_INT num_of_variables; /* number of variables */ +/* list of variables */ +/* VARIABLE_LIST var_list [num_of_variables]; */ + SD_END_STRUCT + }; +typedef struct defvlist_req_info DEFVLIST_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_defvlist (ST_INT chan, DEFVLIST_REQ_INFO *info); +ST_RET mp_defvlist_resp (MMSREQ_IND *info); +#else +ST_RET mpl_defvlist (DEFVLIST_REQ_INFO *info); +ST_RET mpl_defvlist_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET NAMED VARIABLE LIST ATTRIBUTES */ +/************************************************************************/ + +/* REQUEST : */ + +struct getvlist_req_info + { + OBJECT_NAME vl_name; /* variable list name */ + }; +typedef struct getvlist_req_info GETVLIST_REQ_INFO; + +/* RESPONSE : */ + +struct getvlist_resp_info + { + ST_BOOLEAN mms_deletable; /* MMS deletable */ + ST_INT num_of_variables; /* number of variables */ +/* list of variables */ +/* VARIABLE_LIST var_list [num_of_variables]; */ + SD_END_STRUCT + }; +typedef struct getvlist_resp_info GETVLIST_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getvlist (ST_INT chan, GETVLIST_REQ_INFO *info); +ST_RET mp_getvlist_resp (MMSREQ_IND *ind, GETVLIST_RESP_INFO *info); +#else +ST_RET mpl_getvlist (GETVLIST_REQ_INFO *info); +ST_RET mpl_getvlist_resp (ST_UINT32 invoke, GETVLIST_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DELETE NAMED VARIABLE LIST */ +/************************************************************************/ + +/* REQUEST : */ + +#define DELVL_SPEC 0 +#define DELVL_AA 1 +#define DELVL_DOM 2 +#define DELVL_VMD 3 + +struct delvlist_req_info + { + ST_INT16 scope; /* scope of delete (see above) */ + ST_BOOLEAN dname_pres; /* domain name present */ + ST_CHAR dname [MAX_IDENT_LEN+1]; /* domain name */ + ST_BOOLEAN vnames_pres; /* variable names present */ + ST_INT num_of_vnames; /* number of var list names */ +/* list of var list names */ +/* OBJECT_NAME vname_list [num_of_vnames]; */ + SD_END_STRUCT + }; +typedef struct delvlist_req_info DELVLIST_REQ_INFO; + +/* RESPONSE : */ + +struct delvlist_resp_info + { + ST_UINT32 num_matched; /* Number matched */ + ST_UINT32 num_deleted; /* Number deleted */ + }; +typedef struct delvlist_resp_info DELVLIST_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_delvlist (ST_INT chan, DELVLIST_REQ_INFO *info); +ST_RET mp_delvlist_resp (MMSREQ_IND *ind, DELVLIST_RESP_INFO *info); +#else +ST_RET mpl_delvlist (DELVLIST_REQ_INFO *info); +ST_RET mpl_delvlist_resp (ST_UINT32 invoke, DELVLIST_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DEFINE TYPE */ +/************************************************************************/ + +/* REQUEST : */ + +struct deftype_req_info + { + OBJECT_NAME type_name; /* object name */ + VAR_ACC_TSPEC type_spec; /* type specification */ + }; +typedef struct deftype_req_info DEFTYPE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_deftype (ST_INT chan, DEFTYPE_REQ_INFO *info); +ST_RET mp_deftype_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_deftype (DEFTYPE_REQ_INFO *info); +ST_RET mpl_deftype_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET TYPE NAME DEFINITION */ +/************************************************************************/ + +/* REQUEST : */ + +struct gettype_req_info + { + OBJECT_NAME type_name; /* object name */ + }; +typedef struct gettype_req_info GETTYPE_REQ_INFO; + +/* RESPONSE : */ + +struct gettype_resp_info + { + ST_BOOLEAN mms_deletable; /* MMS deletable */ + VAR_ACC_TSPEC type_spec; /* type specification */ + }; +typedef struct gettype_resp_info GETTYPE_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_gettype (ST_INT chan, GETTYPE_REQ_INFO *info); +ST_RET mp_gettype_resp (MMSREQ_IND *ind, GETTYPE_RESP_INFO *info); +#else +ST_RET mpl_gettype (GETTYPE_REQ_INFO *info); +ST_RET mpl_gettype_resp (ST_UINT32 invoke, GETTYPE_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DELETE TYPE NAME */ +/************************************************************************/ + +/* REQUEST : */ + +#define DELTYPE_SPEC 0 +#define DELTYPE_AA 1 +#define DELTYPE_DOM 2 +#define DELTYPE_VMD 3 + +struct deltype_req_info + { + ST_INT16 scope; /* scope of delete (see above) */ + ST_BOOLEAN dname_pres; /* domain name present */ + ST_CHAR dname [MAX_IDENT_LEN+1]; /* domain name */ + ST_BOOLEAN tnames_pres; /* type names present */ + ST_INT num_of_tnames; /* number of type names */ +/* list of type names */ +/* OBJECT_NAME tname_list [num_of_tnames]; */ + SD_END_STRUCT + }; +typedef struct deltype_req_info DELTYPE_REQ_INFO; + +/* RESPONSE : */ + +struct deltype_resp_info + { + ST_UINT32 num_matched; /* Number matched */ + ST_UINT32 num_deleted; /* Number deleted */ + }; +typedef struct deltype_resp_info DELTYPE_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_deltype (ST_INT chan, DELTYPE_REQ_INFO *info); +ST_RET mp_deltype_resp (MMSREQ_IND *ind, DELTYPE_RESP_INFO *info); +#else +ST_RET mpl_deltype (DELTYPE_REQ_INFO *info); +ST_RET mpl_deltype_resp (ST_UINT32 invoke, DELTYPE_RESP_INFO *info); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PVAR_INCLUDED */ diff --git a/include/inc/mms_pvmd.h b/include/inc/mms_pvmd.h new file mode 100644 index 0000000..6024d16 --- /dev/null +++ b/include/inc/mms_pvmd.h @@ -0,0 +1,291 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pvmd.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS vmd management services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/12/02 JRB 02 Add ASN1_ENC_CTXT arg to mpl_ustatus */ +/* 09/09/97 MDE 02 Added 'mms_class' defines */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PVMD_INCLUDED +#define MMS_PVMD_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_mp.h" + +/************************************************************************/ +/************************************************************************/ +/* VMD MANAGEMENT SERVICES */ +/************************************************************************/ +/* The structures below are used to pass VMD MANAGEMENT information */ +/* to/from the MMS primitives. */ +/************************************************************************/ + +/* Defines for 'mms_class' for GNL and RENAME */ +#define MMS_CLASS_VAR 0 +#define MMS_CLASS_SCAT_ACC 1 +#define MMS_CLASS_VARLIST 2 +#define MMS_CLASS_TYPE 3 +#define MMS_CLASS_SEM 4 +#define MMS_CLASS_EV_COND 5 +#define MMS_CLASS_EV_ACT 6 +#define MMS_CLASS_EV_ENROLL 7 +#define MMS_CLASS_JOU 8 +#define MMS_CLASS_DOM 9 +#define MMS_CLASS_PI 10 +#define MMS_CLASS_OPER_STA 11 + +/************************************************************************/ +/************************************************************************/ +/* STATUS */ +/************************************************************************/ + +/* REQUEST : */ + +#define MAX_STAT_DTL_LEN 16 + +struct status_req_info + { + ST_BOOLEAN extended; /* flag indicating if extended status */ + }; /* is desired */ +typedef struct status_req_info STATUS_REQ_INFO; + +/* RESPONSE : */ + +struct status_resp_info + { + ST_INT16 logical_stat; /* logical status - not optional */ + ST_INT16 physical_stat; /* physical status - not optional */ + ST_BOOLEAN local_detail_pres; /* flag if logical detail is present */ + ST_INT local_detail_len; /* length of logical detail (in bits) */ + ST_UCHAR local_detail[MAX_STAT_DTL_LEN]; /* vendor-specific detailed info*/ + }; +typedef struct status_resp_info STATUS_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_status (ST_INT chan,STATUS_REQ_INFO *info); +ST_RET mp_status_resp (MMSREQ_IND *ind,STATUS_RESP_INFO *info); +#else +ST_RET mpl_status (STATUS_REQ_INFO *info); +ST_RET mpl_status_resp (ST_UINT32 invoke, STATUS_RESP_INFO *info); +#endif + +/************************************************************************/ +/* UNSOLICITED STATUS */ +/************************************************************************/ + +/* REQUEST : */ + +struct ustatus_req_info + { + ST_INT16 logical_stat; /* logical status - not optional */ + ST_INT16 physical_stat; /* physical status - not optional */ + ST_BOOLEAN local_detail_pres; /* flag if logical detail is present */ + ST_INT local_detail_len; /* length of logical detail (in bits) */ + ST_UCHAR local_detail[MAX_STAT_DTL_LEN]; /* vendor-specific detailed info*/ + }; +typedef struct ustatus_req_info USTATUS_REQ_INFO; + +/* RESPONSE : No response (unsolicited) */ + +#ifndef MMS_LITE +ST_RET mp_ustatus (ST_INT chan,USTATUS_REQ_INFO *info); +#else +ST_RET mpl_ustatus (ASN1_ENC_CTXT *aCtx, USTATUS_REQ_INFO *info); +#endif + +/************************************************************************/ +/* GET NAME LIST */ +/************************************************************************/ + +/* REQUEST : */ + +struct namelist_req_info + { + ST_BOOLEAN cs_objclass_pres; /* set for use CS object class */ + union + { + ST_INT16 mms_class; /* object class */ + struct /* CS context object sel */ + { + ST_INT len; /* length of ASN.1 CS class */ + ST_UCHAR *cs_class; /* CS object class ASN.1 */ + } cs; + } obj; + + ST_INT16 objscope; /* object scope */ + ST_CHAR dname[MAX_IDENT_LEN+1]; /* domain name, for scope = dom */ + ST_BOOLEAN cont_after_pres; /* flag if continue param pres. */ + ST_CHAR continue_after[MAX_IDENT_LEN+1]; /* continue-after name */ + SD_END_STRUCT + }; +typedef struct namelist_req_info NAMELIST_REQ_INFO; + +/* RESPONSE : */ + +struct namelist_resp_info + { + ST_BOOLEAN more_follows; /* end of list boolean value */ + ST_INT num_names; /* number of names */ + SD_END_STRUCT + }; +/* ST_CHAR *name_list[]; */ /* array of pointers to object names */ + +/* NOTE: Immediately below this structure (contiguous in memory) is a */ +/* list of character pointers, one for each name in the name list. */ +/* Essentially the structure and name pointers are allocated in a */ +/* single call to malloc of size: (sizeof(NAMELIST_RESP_INFO) */ +/* + num_names * sizeof(ST_CHAR *)). The requesting user makes use of */ +/* the contiguous list of pointers as appropriate. The responding */ +/* user must pass the mp_namelist_resp function a pointer to a contig- */ +/* uous block of memory containing the namelist_resp_info structure at */ +/* the top and the list of character pointers below it. */ +typedef struct namelist_resp_info NAMELIST_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_namelist (ST_INT chan,NAMELIST_REQ_INFO *info); +ST_RET mp_namelist_resp (MMSREQ_IND *ind,NAMELIST_RESP_INFO *info); +#else +ST_RET mpl_namelist (NAMELIST_REQ_INFO *info); +ST_RET mpl_namelist_resp (ST_UINT32 invoke, NAMELIST_RESP_INFO *info); +#endif + +/************************************************************************/ +/* IDENTIFY */ +/************************************************************************/ + +/* REQUEST : NULL */ +/* RESPONSE : */ + +/* This is the structure used for the info pass to/from the MMS prims */ + +#define MAX_VEND_LEN 64 /* vendor name max len */ +#define MAX_REV_LEN 16 /* revision max len */ +#define MAX_MOD_LEN 16 /* model max len */ + +struct ident_resp_info + { + ST_CHAR vend[MAX_VEND_LEN+1]; /* vendor */ + ST_CHAR model[MAX_MOD_LEN+1]; /* model */ + ST_CHAR rev[MAX_REV_LEN+1]; /* revision */ + ST_INT num_as; /* number abstract syntax's */ +/* this structure may be followed by the abstract syntax's */ +/* MMS_OBJ_ID as[num_as]; */ + SD_END_STRUCT + }; +typedef struct ident_resp_info IDENT_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_ident (ST_INT chan); +ST_RET mp_ident_resp (MMSREQ_IND *ind,IDENT_RESP_INFO *info); +#else +ST_RET mpl_ident (ST_VOID); +ST_RET mpl_ident_resp (ST_UINT32 invoke, IDENT_RESP_INFO *info); +#endif + +/************************************************************************/ +/* RENAME */ +/************************************************************************/ + +/* REQUEST : */ + +struct rename_req_info + { + ST_BOOLEAN cs_objclass_pres; /* set for use CS object class */ + union + { + ST_INT16 mms_class; /* object class */ + struct /* CS context object sel */ + { + ST_INT len; /* length of ASN.1 CS class */ + ST_UCHAR *cs_class; /* CS object class ASN.1 */ + } cs; + } obj; + + OBJECT_NAME cur_name; /* current name */ + ST_CHAR new_ident [MAX_IDENT_LEN+1]; /* new identifier */ + SD_END_STRUCT + }; +typedef struct rename_req_info RENAME_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_rename (ST_INT chan,RENAME_REQ_INFO *info); +ST_RET mp_rename_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_rename (RENAME_REQ_INFO *info); +ST_RET mpl_rename_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET CAPABILITY LIST */ +/************************************************************************/ + +/* REQUEST : */ + +struct getcl_req_info + { + ST_BOOLEAN cont_after_pres; /* flag if continue param pres. */ + ST_CHAR *continue_after; /* pointer continue-after name */ + }; +typedef struct getcl_req_info GETCL_REQ_INFO; + +/* RESPONSE : */ + +struct getcl_resp_info + { + ST_BOOLEAN more_follows; /* end of list boolean value */ + ST_INT num_of_capab; /* number of capabilities */ +/* list of capabilities */ +/* ST_CHAR * capab_list [num_of_capab]; */ + SD_END_STRUCT + }; +typedef struct getcl_resp_info GETCL_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getcl (ST_INT chan,GETCL_REQ_INFO *info); +ST_RET mp_getcl_resp (MMSREQ_IND *ind,GETCL_RESP_INFO *info); +#else +ST_RET mpl_getcl (GETCL_REQ_INFO *info); +ST_RET mpl_getcl_resp (ST_UINT32 invoke, GETCL_RESP_INFO *info); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PVMD_INCLUDED */ + diff --git a/include/inc/mms_vvar.h b/include/inc/mms_vvar.h new file mode 100644 index 0000000..1896958 --- /dev/null +++ b/include/inc/mms_vvar.h @@ -0,0 +1,1090 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2006, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_vvar.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains data and function definitions associated */ +/* with the MMS virtual machine variable access operations. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/02/07 JRB 58 Add elements to RUNTIME_BUILD_CTXT to allow */ +/* 2 pass build process. Add more ms_rt_bld*. */ +/* 05/10/07 JRB 57 Chg el_size, etc. to ST_INT to avoid warnings*/ +/* 04/30/07 JRB 56 Chg el_size, el_len, etc. in RUNTIME_TYPE to */ +/* ST_INT32 to allow larger primitives, arrays. */ +/* 04/17/07 JRB 55 Add prim_count to MVLU_TYPE_INFO. */ +/* 10/30/06 JRB 54 Add reserved_1 to RUNTIME_CTRL. */ +/* Add "ms_rt_bld_*" prototypes. */ +/* 08/09/06 JRB 53 Add ms_local_to_asn1_2. */ +/* Add ms_adl_to_asn1_2, ms_aa_to_asn1_2. */ +/* 03/22/06 EJV 52 Added GENERAL_TIME_ALGN (time_t is 64-bits in VS 2005)*/ +/* 07/29/05 MDE 51 Select USE_RT_TYPE_3 for USPS_IOS */ +/* 05/09/05 JRB 50 Default to USE_RT_TYPE_2 (was USE_RT_TYPE_3).*/ +/* 03/10/05 JRB 49 Add ms_rt_el_tag_text proto. */ +/* 02/22/05 JRB 48 ms_is_rt_prim: add SD_CONST to arg. */ +/* 01/27/05 JRB 47 Add m_lite_data_algn_tbl extern. */ +/* 07/22/04 JRB 46 Add rt_index_q, rt_index_t, data_offset to */ +/* RUNTIME_TYPE if !MMS_LITE. */ +/* 07/12/04 JRB 45 Chg RT_UTF8_STRING tag from 18 to 16 to */ +/* match latest 61850-8-1. */ +/* 01/22/04 JRB 44 Add ms_local_to_text. */ +/* 10/03/03 JRB 43 Chg offset_to_last & offSet to ST_INT32 in */ +/* RUNTIME_TYPE to handle BIG IEC-61850 types. */ +/* 03/31/03 JRB 42 Add UTF8string support (see RT_UTF8_STRING). */ +/* Add "utf8" to M_ARB_DATA_CTRL. */ +/* 03/13/03 JRB 41 u_ml_get_rt_type: Chg from "func ptr" to func.*/ +/* 01/02/03 JRB 40 Add arg to u_ml_get_rt_type. */ +/* Add ASN1_TO_RT_DEC_INFO struct. */ +/* 12/27/02 MDE 39 Allow use of ms_asn1_to_runtime */ +/* 12/17/02 JRB 38 Del SD_CONST from numMvlRtNames. */ +/* 12/16/02 JRB 37 Chg ms_is_rt_prim from macro to function. */ +/* 11/27/02 MDE 36 Added ms_is_rt_prim */ +/* 11/11/02 JRB 35 Add RUNTIME_CTRL, chg ms_runtime_create & */ +/* ms_runtime_destroy to use it. */ +/* Del ms_asn1_to_runtime (use ms_runtime_create)*/ +/* Add ms_tdl_to_runtime proto. */ +/* 03/01/02 JRB 34 Add SD_CONST to (RUNTIME_TYPE *) in RT_AA_CTRL.*/ +/* 02/06/02 JRB 33 Deleted unused MMS_ALTA_DATA */ +/* 12/20/01 JRB 32 Convert to use ASN1R. */ +/* Add ASN1_ENC_CTXT arg to ms_*_to_asn1*. */ +/* Add new function ms_local_to_asn1_easy. */ +/* 11/13/01 EJV 31 Added support for new MMS type UtcTime: */ +/* Added RT_UTC_TIME, chg RT_STR_END, RT_ARR_END*/ +/* M_ARB_DATA_CTRL: added utc fun proto. */ +/* 06/20/01 EJV 30 Added () around rt in ms_comp_name_xxx macros*/ +/* to handle rt+1, rt-1 arguments. */ +/* 04/11/01 MDE 29 Added ms_comp_name_pres macros */ +/* 01/21/01 EJV 28 M_ARB_DATA_CTRL: changed bool to booln, */ +/* to avoid conflict w/ bool type in C++ files. */ +/* 11/02/00 JRB 27 Del #if MVL_UCA. Use #if MMS_LITE instead. */ +/* 10/25/00 JRB 26 Del MVL_UCA define (define in makefile). */ +/* Move ST_RTREF typedef so always defined. */ +/* 08/29/00 JRB 25 Chg ms_comp_name_find from funct to macro. */ +/* 07/28/00 JRB 24 Simplify RT_TYPE ifdefs. */ +/* Fix SD_CONST in some prototypes. */ +/* Del m_type_nam* externs, only used in 1 file.*/ +/* 07/13/00 JRB 23 Add "#ifdef USE_RT_TYPE_2". */ +/* Add ms_runtime_create, ms_runtime_destroy, */ +/* ms_comp_name_find. */ +/* 06/22/00 MDE 22 Added numMvlRtNames declaration */ +/* 06/16/00 JRB 21 Add #if INT64_SUPP... */ +/* 04/20/00 JRB 20 Del SD_CONST from (RUNTIME_TYPE **) args. */ +/* 09/13/99 MDE 19 Added SD_CONST modifiers */ +/* 09/10/98 MDE 18 Added 'mvlRtNames' declaration */ +/* 08/11/98 MDE 17 Minor changes for Foundry */ +/* 06/30/98 MDE 16 Changed ST_REF to ST_VOID * */ +/* 04/07/98 MDE 15 Added struct/arr start/end alignment mode */ +/* 03/23/98 MDE 14 Now let user supply AA derived type (RD/WR) */ +/* 03/12/98 MDE 13 MMS-Lite related runtime type changes */ +/* 03/11/98 MDE 12 Removed NEST_RT_TYPES */ +/* 02/10/98 MDE 11 Changed runtime type */ +/* 12/29/97 MDE 10 Added 'typeCtrl' to RUNTIME_TYPE for use */ +/* with 'mktypes.exe' only. */ +/* 09/11/97 MDE 09 MMS ARB user funs now return ST_RET */ +/* 09/04/97 NAV 08 Split ARB Btime functions & add */ +/* have them return a ST_BOOLEAN */ +/* 08/15/97 MDE 07 BTOD handling comments */ +/* 08/14/97 RKR 06 Format changes */ +/* 07/16/97 RKR 05 Added more 64 bit integer support */ +/* 06/23/97 RKR 04 Added arbitrary data handling */ +/* 06/20/97 MDE 03 Added 64 bit integer support */ +/* 06/09/97 MDE 02 Changed Runtime Type and it's use */ +/* 06/05/97 RKR 01 Removed AA_OUTER_NEST rearranged AA constants*/ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_VVAR_INCLUDED +#define MMS_VVAR_INCLUDED + +#ifndef MMS_LITE +#include "mms_mv.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************************************/ +/************************************************************************/ +/* BINARY TIME OF DAY NOTES */ +/* There are two forms of TimeOfDay, 4 byte and 6 byte. */ +/* The 6 byte form contains the number of milliseconds since midnight */ +/* and the number of days since Jan 1, 1984. The 4 byte form contains */ +/* only the millisecond number. */ +/* */ +/* In memory, the Btime6 data looks like a pair of 32 bit integers: */ +/* ST_INT32 ms; Number of milliseconds since midnight */ +/* ST_INT32 day; Number of days since Jan 1, 1984 */ +/* */ +/* and the Btime4 data looks like a single 32 bit integer: */ +/* ST_INT32 ms; Number of milliseconds since midnight */ +/* */ +/* Data alignment for either form is that of a ST_INT32. */ +/* Note that MMS-EASE simply encodes/decodes the values to/from the */ +/* MMS PDU and does not perform any local time localization. */ +/************************************************************************/ + +/************************************************************************/ +/************************************************************************/ +/* MMS-LITE */ +/************************************************************************/ + +/* Default to USE_RT_TYPE_2 for MMS Lite (allows dynamic type creation).*/ +/* NOTE: define USE_RT_TYPE_3 only if you need to store RUNTIME_TYPES */ +/* in ROM, and you DO NOT need dynamic type creation. */ + +#if defined(MMS_LITE) && (!defined(USE_RT_TYPE_3)) +#define USE_RT_TYPE_2 +#endif + +/* The IOS Toolkit requires RT_TYPE_3 */ +#ifdef USPS_IOS +#undef USE_RT_TYPE_2 +#define USE_RT_TYPE_3 +#endif + +#if defined(FOUNDRY) /* Overwride defines when compiling Foundry */ +#undef USE_RT_TYPE_2 +#undef USE_RT_TYPE_3 +#endif + +/* RUNTIME TYPE INTEGER FORM */ +/* In MMS-LITE the size of the RUNTIME_TYPE must be minimized, so we */ +/* will use 16 bit integers for the compoments. This puts a 32K limit */ +/* on the size of a variable. */ + +#if !defined(MMS_LITE) +#define ST_RTINT ST_INT +#else +#define ST_RTINT ST_INT16 +#endif + +/************************************************************************/ +/* MMS-LITE UCA SPECIFIC SECTION */ +/************************************************************************/ +/* MMS-LITE uses an extended RUNTIME_TYPE for use with the MVL UCA */ +/* object handling extensions. */ +/* To use the UCA extensions, MVL_UCA must be defined. */ +/* NOTE: MVL_UCA is NOT defined by default. */ + +/* This typedef is for the application use only and can be changed as */ +/* required. Normally it is used to allow the applcation to consolidate */ +/* MVL_UCA read and write indication handler functions. */ +typedef ST_VOID * ST_RTREF; + +/* These elements are designed to be used to assist in implementing the */ +/* UCA device models in MMS-EASE Lite. Note that 'MVL_UCA' must be */ +/* defined when creating the MMS-EASE libraries if these features are */ +/* to be used. */ + +/* You may comment out the defines for those components that will not */ +/* bs used in the target application to reduce the size of the */ +/* RUNTIME_TYPE table. */ +#define MVLU_USE_REF + +typedef struct mvluTypeStruct + { + ST_RTINT prim_count; /* number of prims in this ARR, STRUCT, or prim */ + ST_RTINT sortedNum; /* For use by MVLU GNL code */ + ST_INT32 offSet; /* Offset from start of mother structure */ + ST_RTINT rdIndFunIndex; + ST_RTINT wrIndFunIndex; + +/* These elements can be used by the application as needed, and are */ +/* copied into the derived variable association. MVLU does not use them */ +/* directly. */ +#if defined(MVLU_USE_REF) + ST_RTREF ref; /* set to 'XXX$YYY_REF' by foundry */ +#endif + } MVLU_TYPE_INFO; + +/************************************************************************/ +/* RUNTIME TYPE DEFINITION STRUCTURE */ +/************************************************************************/ +/* The following defines specify the various data parameters */ +/************************************************************************/ + +#define RT_ARR_START 1 +#define RT_STR_START 2 +#define RT_BOOL 3 +#define RT_BIT_STRING 4 +#define RT_INTEGER 5 +#define RT_UNSIGNED 6 +#define RT_FLOATING_POINT 7 +#define RT_OCTET_STRING 9 +#define RT_VISIBLE_STRING 10 +#define RT_GENERAL_TIME 11 +#define RT_BINARY_TIME 12 +#define RT_BCD 13 +#define RT_BOOLEANARRAY 14 +#define RT_UTC_TIME 17 +#define RT_UTF8_STRING 16 /* specified in IEC-61850-8-1 */ +/* ADD new tags here and bump up RT_MAX_PRIM_TAG accordingly. */ +#define RT_MAX_PRIM_TAG 18 /* use when looking for max tag val*/ +#define RT_STR_END (RT_MAX_PRIM_TAG+1) +#define RT_ARR_END (RT_MAX_PRIM_TAG+2) + +struct runtime_type + { + ST_UCHAR el_tag; /* ID tag expected for this element, or special */ + /* values for end of array, end of struct */ + /* or nested runtime types */ + + ST_INT el_size; /* number of bytes occupied by this element */ + ST_INT32 offset_to_last; /* offset in bytes from the start of the */ + /* data to the last element */ + union + { + /* CRITICAL: element types in each structure in this union must */ + /* match. If not, the Foundry would misalign data in this union. */ + struct /* primitive element */ + { + ST_INT el_len; /* precision, in bytes except bitstr, time */ + ST_RTINT pad; /* included to allow aggregate initialization */ + } p; + struct /* structure (top or bottom) */ + { + ST_INT num_rt_blks; /* # runtime blks to get to strt/end elmnt */ + ST_RTINT pad; /* included to allow aggregate initialization */ +#if !defined(USE_RT_TYPE_2) && !defined(USE_RT_TYPE_3) + ST_BOOLEAN packd; /* Indicates if packed or not. */ +#endif + } str; + struct /* Array (top or bottom) */ + { + ST_INT num_elmnts; /* # array elements (index limit) */ + ST_RTINT num_rt_blks; /* # runtime blks to get to strt/end elmnt */ +#if !defined(USE_RT_TYPE_2) && !defined(USE_RT_TYPE_3) + ST_BOOLEAN packd; /* Indicates if packed or not. */ +#endif + } arr; + } u; + +#if defined(USE_RT_TYPE_2) + ST_CHAR *comp_name_ptr; /* ptr to comp name string */ +#elif defined(USE_RT_TYPE_3) + ST_RTINT name_index; /* Index into mvlRtNames table */ +#else /* Default */ + ST_CHAR name[MAX_IDENT_LEN+1]; +#endif + +#if defined(MMS_LITE) + MVLU_TYPE_INFO mvluTypeInfo; /* MMS-LITE UCA handler use */ +#endif +#if defined(FOUNDRY) + ST_CHAR *refBuf; + ST_CHAR *rdIndexBuf; + ST_CHAR *wrIndexBuf; +#endif +#if !defined (MMS_LITE) + ST_RTINT rt_index_q; /* index into RUNTIME_TYPE array for 'q'*/ + /* attribute of IEC-61850 type */ + ST_RTINT rt_index_t; /* index into RUNTIME_TYPE array for 't'*/ + /* attribute of IEC-61850 type */ + ST_INT32 data_offset; /* offset in bytes from start of data */ + /* NOTE: should be same as offSet in */ + /* mvluTypeInfo above for MMS_LITE */ +#endif + }; +typedef struct runtime_type RUNTIME_TYPE; + +/* Runtime type HEAD struct contains info about RUNTIME_TYPE array. */ +typedef struct + { + RUNTIME_TYPE *rt_first; /* ptr to first in array of structs */ + ST_INT rt_num; /* num entries in RUNTIME_TYPE array */ + ST_VOID *reserved_1; /* ptr to any optional info for this type*/ + } RUNTIME_CTRL; + +/************************************************************************/ +/* ASN1_TO_RT_DEC_INFO - structure to store temporary decode info. */ +/************************************************************************/ +typedef struct + { +#if defined(USE_RT_TYPE_2) +/* These are used for saving component names. */ + ST_CHAR *comp_name_buf; /* Alloc'd buf to store ALL component names.*/ + ST_INT comp_name_size; /* Buffer size (in bytes) */ + ST_INT comp_name_used; /* Running count of bytes needed OR used.*/ + + ST_CHAR *comp_name_ptr; /* current position in buffer. */ +#endif + RUNTIME_TYPE *rt_start; /* ptr to runtime table start */ + ST_BOOLEAN calc_only; /* flag to calculate num rt blocks */ + /* DEBUG: add rt_ptr, rt_count, rt_limit, etc. & delete global vars.*/ + } ASN1_TO_RT_DEC_INFO; + +/************************************************************************/ +/* RUNTIME_BUILD_CTXT: info for dynamic building of runtime type defs. */ +/************************************************************************/ +typedef struct + { + RUNTIME_CTRL *rt_ctrl; /* type definition being built */ + RUNTIME_TYPE *rt_type; /* ptr to current type */ + RUNTIME_TYPE *max_rt_type; /* ptr after last RUNTIME_TYPE struct */ + ST_INT nest_level; /* index into "nest_start_ptr" array */ + RUNTIME_TYPE *nest_start_ptr [ASN1_MAX_LEVEL]; /* array of ptrs to*/ + /* STR_START or ARR_START */ + ST_CHAR *comp_name_buf; /* allocated buf to store comp names */ + /* [MAX_IDENT_LEN+1] for each */ + ST_RET errcode; /* Set when first error detected */ + /* Initialized to SD_SUCCESS. */ + + ST_BOOLEAN do_count; /* If SD_TRUE, bld functions just count */ + /* num of RUNTIME_TYPE elements needed */ + /* (nothing allocated or initialized) */ + ST_INT curr_count; /* current count of RUNTIME_TYPE elems */ + /* (used only when do_count=SD_TRUE) */ + ST_INT max_count; /* max count of RUNTIME_TYPE elems */ + /* (used only when do_count=SD_TRUE) */ + } RUNTIME_BUILD_CTXT; + +#if defined(MMS_LITE) +ST_RET u_ml_get_rt_type (ASN1_DEC_CTXT *aCtx, OBJECT_NAME *type_name, + RUNTIME_TYPE **rt_out, ST_INT *num_rt_out); + +extern ST_INT maxMvlRtNames; +extern ST_INT numMvlRtNames; +extern ST_CHAR **mvlRtNames; +#endif + +ST_BOOLEAN ms_is_rt_prim (SD_CONST RUNTIME_TYPE *rt); +ST_CHAR *ms_rt_el_tag_text (SD_CONST RUNTIME_TYPE *rt_type); + +/************************************************************************/ +/* ALTERNATE ACCESS DEFINITION STRUCTURE */ +/************************************************************************/ + +/* Possible values for sel_type */ +#define AA_COMP 0 +#define AA_INDEX 1 +#define AA_INDEX_RANGE 2 +#define AA_ALL 3 +#define AA_COMP_NEST 4 +#define AA_INDEX_NEST 5 +#define AA_INDEX_RANGE_NEST 6 +#define AA_ALL_NEST 7 +#define AA_END_NEST 8 + +#define MAX_NUM_AA_EL 100 + +struct alt_acc_el + { + ST_BOOLEAN comp_name_pres; + ST_CHAR comp_name[MAX_IDENT_LEN+1];/* named component for derived */ + /* type */ + ST_INT sel_type; /* type of access selection */ + union + { + ST_CHAR component[MAX_IDENT_LEN+1]; /* Used for AA_COMP */ + ST_UINT32 index; /* Used for AA_INDEX */ + struct /* Used for AA_INDEX_RANGE */ + { + ST_UINT32 low_index; + ST_UINT32 num_elmnts; + } ir; + } u; + }; +typedef struct alt_acc_el ALT_ACC_EL; + +struct alt_access + { + ST_INT num_aa; + ALT_ACC_EL *aa; + }; +typedef struct alt_access ALT_ACCESS; + + +/* This data structure is used in table form to implement alternate */ +/* access from the server perspective (NEWDATA <-> ASN1DATA) */ +/* It allows re-ordering of elements as well as limited selection */ + +struct rt_aa_ctrl + { + SD_CONST RUNTIME_TYPE *rt; + ST_UINT offset_to_data; /* offset to data element */ + ST_INT el_size; /* Size of the element in memory */ + }; +typedef struct rt_aa_ctrl RT_AA_CTRL; + +ST_RET ms_adl_to_aa (ST_CHAR *adl_str,ALT_ACCESS *alt_acc); +ST_RET ms_adl_to_asn1_2 (ST_CHAR *adl_str, + ST_UCHAR *buf_ptr, + ST_INT buf_len, + ST_UCHAR **asn1_ptr_out, + ST_INT *asn1_len_out); + +ST_RET ms_aa_to_adl (ALT_ACCESS *alt_acc, + ST_CHAR *adl_str, + ST_INT max_adl_len); + +ST_RET ms_local_to_asn1_aa (ASN1_ENC_CTXT *aCtx, SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, + ALT_ACCESS *alt_acc, + ST_CHAR *dptr); + +ST_RET ms_asn1_to_local_aa (SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, + ALT_ACCESS *alt_acc, + ST_UCHAR *asn1ptr, + ST_INT asn1len, + ST_CHAR *dptr); + + +ST_VOID ms_log_alt_access (ALT_ACCESS *alt_acc); + + +ST_RET ms_aa_to_asn1 (ASN1_ENC_CTXT *aCtx, ALT_ACCESS *alt_acc); +/* ms_aa_to_asn1_2 usually easier to use than ms_aa_to_asn1. */ +ST_RET ms_aa_to_asn1_2 (ALT_ACCESS *alt_acc, + ST_UCHAR *buf_ptr, + ST_INT buf_len, + ST_UCHAR **asn1_ptr_out, + ST_INT *asn1_len_out); +ST_RET ms_asn1_to_aa (ST_UCHAR *asn1ptr, ST_INT asn1len, + ALT_ACCESS *alt_acc_out); + + +/************************************************************************/ +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* Type definition structures and manipulation functions */ +/************************************************************************/ + +struct named_type /* type definition table structure */ + { + DBL_LNK link; /* generic list links */ + ST_CHAR type_name[MAX_IDENT_LEN+1]; /* name of data type */ + ST_BOOLEAN deletable; /* set != 0 if deletable */ + ST_UCHAR protection; /* protection afforded for type */ + ST_BOOLEAN erased; /* flags if deleted, but nref !=0 */ + ST_INT nref; /* number of var def'ns referencing this*/ + RUNTIME_CTRL *rt_ctrl; /* May be NULL */ + RUNTIME_TYPE *rt_head; /* ptr to runtime type def head */ + ST_INT rt_num; /* # of rt_blocks in runtime type def */ + ST_INT asn1len; /* # bytes in ASN.1 definition */ + ST_UCHAR *asn1ptr; /* pointer to ASN.1 definition */ + ST_INT blocked_len; /* length of blocked (packed) data type */ + ST_CHAR *(*read_ind_fun)(ST_CHAR *src, ST_INT len); /* std read ind function ptr */ + ST_INT (*write_ind_fun)(ST_CHAR *src, ST_CHAR *dest, ST_INT len); /* std write ind */ + }; +typedef struct named_type NAMED_TYPE; + +ST_RET ms_locl_to_asn1_aa (ASN1_ENC_CTXT *aCtx, NAMED_TYPE *tptr, + ALT_ACCESS *alt_acc, + ST_CHAR *dptr); + +ST_RET ms_asn1_to_locl_aa (NAMED_TYPE *tptr, + ALT_ACCESS *alt_acc, + ST_UCHAR *asn1ptr, + ST_INT asn1len, + ST_CHAR *dptr); + +extern ST_INT max_mmsease_types; /* max number allowed */ +extern ST_INT mms_type_count; /* number currently defined */ + +NAMED_TYPE *ms_add_named_type (DOMAIN_OBJS *dom, ST_CHAR *name, + ST_UCHAR *asn1, ST_INT asn1len); +NAMED_TYPE *ms_find_named_type_obj (OBJECT_NAME *obj, + ST_INT chan); +NAMED_TYPE *ms_find_named_type (DOMAIN_OBJS *dom,ST_CHAR *name); +ST_RET ms_del_named_type (DOMAIN_OBJS *dom,ST_CHAR *name); +ST_RET ms_del_type (DOMAIN_OBJS *dom, NAMED_TYPE *name); +ST_VOID ms_del_all_named_types (DOMAIN_OBJS *dom_objs); +ST_RET ms_del_named_type_obj (OBJECT_NAME *obj, ST_INT chan); +ST_RET ms_add_std_types (DOMAIN_OBJS *dom); + +ST_CHAR *rdind_fun (ST_CHAR *addr, ST_INT len); +ST_RET wrind_fun (ST_CHAR *data, ST_CHAR *addr, ST_INT len); + +ST_RET mv_gettype_resp (MMSREQ_IND *ind); +ST_RET mv_gettype_resp (MMSREQ_IND *ind); +ST_RET mv_deltype_resp (MMSREQ_IND *ind); +ST_RET mv_deftype_resp (MMSREQ_IND *ind); + + +/************************************************************************/ +/* Variable definition structures and manipulation functions */ +/************************************************************************/ + +struct named_var /* name table structure */ + { + DBL_LNK link; /* generic list links */ + ST_CHAR varname[MAX_IDENT_LEN+1];/* variable name */ + ST_BOOLEAN invalid; /* variable invalidated due */ + /* to type or addr deleted */ + NAMED_TYPE *type; /* type name/domain */ + ST_BOOLEAN deletable; /* != 0 if deletable */ + ST_UCHAR rd_pro; /* read protection */ + ST_UCHAR wr_pro; /* write protection */ + VAR_ACC_ADDR addr; /* address */ + ST_CHAR *(*read_ind_fun)(ST_CHAR *src, ST_INT len); /* std read ind function ptr */ + ST_INT (*write_ind_fun)(ST_CHAR *src, ST_CHAR *dest, ST_INT len); /* std write ind */ +/* Followed by the address, for symbolic or unconstrained address */ +/* types. The length of this address is determined when the var added */ + SD_END_STRUCT + }; +typedef struct named_var NAMED_VAR; + +struct named_var_list /* name variable list structure */ + { + DBL_LNK link; /* generic list links */ + ST_CHAR name[MAX_IDENT_LEN+1]; /* variable list name */ + ST_BOOLEAN deletable; /* != 0 if deletable */ + ST_INT num_vars; /* # of vars in Named Variable List. */ + /* VARIABLE_LIST var_list [num_of_variables]; */ + SD_END_STRUCT + }; +typedef struct named_var_list NAMED_VAR_LIST; + +extern ST_INT max_mmsease_vars; /* max number allowed */ +extern ST_INT mms_var_count; /* number currently defined */ +extern ST_INT max_mmsease_nvlists; +extern ST_INT mms_nvlist_count; + +/************************************************************************/ +/* This function selects the binary search mechansisms (default) */ +ST_VOID ms_bs_init (ST_VOID); + +/* This function selects the linked list search mechansisms */ +ST_VOID ms_ll_init (ST_VOID); + +NAMED_VAR *ms_add_named_var (DOMAIN_OBJS *dom, ST_CHAR *name, + OBJECT_NAME *type, VAR_ACC_ADDR *addr, + ST_INT chan); +NAMED_VAR *ms_add_var (DOMAIN_OBJS *dom, ST_CHAR *name, + NAMED_TYPE *type, VAR_ACC_ADDR *addr, ST_INT chan); + +NAMED_VAR *ms_find_named_var (DOMAIN_OBJS *dom, ST_CHAR *name); +NAMED_VAR *ms_find_named_var_obj (OBJECT_NAME *obj, ST_INT chan); + +ST_RET ms_del_named_var (DOMAIN_OBJS *dom, ST_CHAR *name); +ST_RET ms_del_named_var_obj (OBJECT_NAME *obj, ST_INT chan); + +ST_VOID ms_del_all_named_vars (DOMAIN_OBJS *dom); + +NAMED_VAR_LIST *ms_add_nvlist (DOMAIN_OBJS *dom, ST_CHAR *name, + ST_INT num_vars, VARIABLE_LIST *var_list); +NAMED_VAR_LIST *ms_find_nvlist (DOMAIN_OBJS *dom, ST_CHAR *name); +NAMED_VAR_LIST *ms_find_nvlist_obj (OBJECT_NAME *obj, ST_INT chan); + +ST_RET ms_del_nvlist (DOMAIN_OBJS *dom, ST_CHAR *name); +ST_RET ms_del_nvlist_obj (OBJECT_NAME *obj, ST_INT chan); + +ST_VOID ms_del_all_nvlists (DOMAIN_OBJS *dom); + +ST_RET mv_getvar_resp (MMSREQ_IND *ind); +ST_RET mv_delvar_resp (MMSREQ_IND *ind); +ST_RET mv_defvar_resp (MMSREQ_IND *ind); +ST_RET mv_namelist_resp (MMSREQ_IND *ind); + +ST_RET mv_getvlist_resp (MMSREQ_IND *ind); +ST_RET mv_delvlist_resp (MMSREQ_IND *ind); +ST_RET mv_defvlist_resp (MMSREQ_IND *ind); + +/************************************************************************/ +/* VIRTUAL MACHINE READ, WRITE, INFORMATION REPORT */ +/* The structure below are used for most variable access VM req funs, */ +/* and allows multiple variables per transaction. */ +/************************************************************************/ +/* VM defines to be used for DataAccessError codes */ +#define ERROR_RESPONSE 20 /* for error response only */ +#define NUM_VAR_MISMATCH 21 + + +struct mv_vardesc /* virtual machine variable description */ + { + OBJECT_NAME name; /* name of variable */ + OBJECT_NAME type; /* type of variable */ + ST_CHAR *data; /* destination/source pointer */ + }; +typedef struct mv_vardesc MV_VARDESC; + +/* This structure is provided as request information for a MV read req. */ +/* If desired, this info may be examined in the user confirm function. */ + +struct readvars_req_info + { /* virtual machine read req structure */ + ST_INT num_of_vars; /* number of variables */ +/* list of variables */ +/* MV_VARDESC vardesc_list [num_of_vars]; */ + SD_END_STRUCT + }; +typedef struct readvars_req_info READVARS_REQ_INFO; + + +/***** READ REQUEST **** */ + +/* a pointer to an array of these structures are passed into the */ +/* 'mv_read_variables' function */ + +struct mv_read_req_info + { + struct /* input (request) information */ + { + ST_CHAR *data_ptr; /* Dest data buffer (for success) */ + NAMED_TYPE *type; /* pointer to associated type */ + ST_BOOLEAN alt_acc_pres; /* set SD_TRUE if Alt Access is present */ + ST_BOOLEAN alt_acc_type_aa; /* set SD_TRUE if type is Alt Acc ready */ + ST_BOOLEAN alt_acc_data_packed; /* set SD_TRUE if local data is packed */ + ALT_ACCESS alt_acc; /* Alternate Access specification */ + }i; + struct /* output (result) information */ + { + ST_RET result; /* !=0 for success, else SD_FAILURE */ + ST_INT16 err_code; /* DataAccessError (for failure) */ + +/* If a named type is not supplied, and the read was a success, this */ +/* is the derived runtime type. It was allocated using 'chk_calloc' */ +/* and must be free'd using 'chk_free' */ + + ST_INT num_rt; + RUNTIME_TYPE *rt_out; + +/* If a data_ptr is not supplied, and the read was a success, this */ +/* is the buffer allocated for the data. It was allocated using */ +/* 'chk_calloc' and must be free'd using 'chk_free' */ + + ST_CHAR *data_ptr_out; /* Dest data buffer (for success) */ + }o; + }; +typedef struct mv_read_req_info MV_READ_REQ_INFO; + +MMSREQ_PEND *mv_read (ST_INT chan, OBJECT_NAME *name, + OBJECT_NAME *type, ST_CHAR *dest); +MMSREQ_PEND *mv_readvars (ST_INT chan, ST_INT num_var, MV_VARDESC *info); +MMSREQ_PEND *mv_read_variables (ST_INT chan, ST_INT num_var, + READ_REQ_INFO *prim, + MV_READ_REQ_INFO *vminfo); + +/***** READ RESPONSE ***** */ + +/* a pointer to an array of these structures are passed into the */ +/* 'mv_read_response' function */ + +struct mv_read_resp_info + { + ST_INT16 result; /* ACC_RSLT_SUCCESS, ACC_RSLT_FAILURE */ + ST_INT16 err_code; /* DataAccessError (for failure) */ + ST_CHAR *data_ptr; /* Source data buffer (for success) */ + NAMED_TYPE *type; /* pointer to associated type */ + ST_BOOLEAN alt_acc_pres; /* set SD_TRUE if Alt Access is present */ + ST_BOOLEAN alt_acc_data_packed;/* set SD_TRUE if local data is packed */ + ALT_ACCESS alt_acc; /* Alternate Access specification */ + }; +typedef struct mv_read_resp_info MV_READ_RESP_INFO; + +ST_RET mv_read_resp (MMSREQ_IND *ind); +ST_RET mv_read_response (MMSREQ_IND *ind, ST_INT num_var, + MV_READ_RESP_INFO *info); + +/***** WRITE REQUEST **** */ + +/* a pointer to an array of these structures are passed into the */ +/* 'mv_write_variables' function */ + +struct mv_write_req_info + { + ST_CHAR *data_ptr; /* Source data buffer */ + NAMED_TYPE *type; /* pointer to associated type */ + ST_BOOLEAN alt_acc_pres; /* set SD_TRUE if Alt Access is present */ + ST_BOOLEAN alt_acc_type_aa; /* set SD_TRUE if type is Alt Acc ready */ + ST_BOOLEAN alt_acc_data_packed;/* set SD_TRUE if local data is packed */ + ALT_ACCESS alt_acc; /* Alternate Access specification */ + }; +typedef struct mv_write_req_info MV_WRITE_REQ_INFO; + +MMSREQ_PEND *mv_write (ST_INT chan, OBJECT_NAME *var, + OBJECT_NAME *type, ST_CHAR *src); +MMSREQ_PEND *mv_writevars (ST_INT chan, ST_INT num_var, MV_VARDESC *info); +MMSREQ_PEND *mv_write_variables (ST_INT chan, ST_INT num_data, + VAR_ACC_SPEC *reqinfo, + MV_WRITE_REQ_INFO *vminfo); + +/***** WRITE RESPONSE **** */ + +ST_RET mv_write_resp (MMSREQ_IND *ind); +WRITE_RESP_INFO *mv_write_decode (MMSREQ_IND *indptr); +ST_RET ms_extract_write_data (MMSREQ_IND *ind, ST_INT index, + NAMED_TYPE *type, + ST_CHAR *dest, ST_BOOLEAN alt_acc_packed); + +ST_RET ms_extract_wr_data (MMSREQ_IND *indptr, ST_INT i, + NAMED_TYPE *type, ST_CHAR *dest, + ST_BOOLEAN alt_acc_packed, ALT_ACCESS *alt_acc_ptr); + +/***** INFORMATION REPORT REQUEST ***** */ + +/* a pointer to an array of these structures are passed into the */ +/* 'mv_info_req' function */ + +struct mv_info_req_info + { + ST_CHAR *data_ptr; /* Source data buffer */ + NAMED_TYPE *type; /* pointer to associated type */ + ST_BOOLEAN alt_acc_pres; /* set SD_TRUE if Alt Access is present */ + ST_BOOLEAN alt_acc_data_packed;/* set SD_TRUE if local data is packed */ + ALT_ACCESS alt_acc; /* Alternate Access specification */ + }; +typedef struct mv_info_req_info MV_INFO_REQ_INFO; + +ST_RET mv_info (ST_INT chan, OBJECT_NAME *var, OBJECT_NAME *type, + ST_CHAR *src); +ST_RET mv_infovars (ST_INT chan, ST_INT num_vars, MV_VARDESC *vminfo); +ST_RET mv_info_report (ST_INT chan, VAR_ACC_SPEC *req, + ST_INT num_var, MV_INFO_REQ_INFO *vminfo); +ST_RET mv_info_nvlist (ST_INT chan, OBJECT_NAME *obj); + +ST_RET ms_extract_info_data (MMSREQ_IND *ind, ST_INT index, + NAMED_TYPE *type, ST_CHAR *dest, + ST_BOOLEAN alt_acc_packed); + +ST_RET ms_extract_inf_data (MMSREQ_IND *indptr, ST_INT i, + NAMED_TYPE *type, ST_CHAR *dest, + ST_BOOLEAN alt_acc_packed, + ALT_ACCESS *alt_acc_ptr); + +/************************************************************************/ + +OBJECT_NAME *ms_extract_varname (ST_CHAR *reqinfo, ST_INT op, ST_INT indx); + +/************************************************************************/ +/************************************************************************/ +#endif /* end of MMS_LITE not defined */ +/************************************************************************/ +/************************************************************************/ + +#define MMS_EASE_BUILDER 0 +#define UNKNOWN_BUILDER 1 + +extern ST_INT ms_req_bld_id; +extern ST_INT ms_resp_bld_id; + +ST_RET ms_init_va_size (ST_INT chan, ST_UCHAR spec_in_rslt, + ST_INT16 var_acc_tag, OBJECT_NAME *vl_name, + ST_LONG *req_size_out, ST_LONG *resp_size_out); + +#ifndef MMS_LITE +ST_RET ms_va_size (ST_INT op, ST_UCHAR spec_in_rslt, ST_INT16 var_acc_tag, + VARIABLE_LIST *vl, NAMED_TYPE *type, + ST_LONG *req_size_out, ST_LONG *resp_size_out); +#else +ST_RET ms_va_size (ST_INT op, ST_UCHAR spec_in_rslt, ST_INT16 var_acc_tag, + VARIABLE_LIST *vl_ptr, ST_INT type_id, + ST_LONG *req_size, ST_LONG *resp_size); +#endif + +/************************************************************************/ +/************************************************************************/ + +extern ST_INT m_rt_type_limit; /* max num of runtime blks per def */ + + +#ifndef MMS_LITE +ST_INT ms_get_blocked_len (NAMED_TYPE *type); +#endif + +ST_INT ms_get_blocked_length (SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt); + +ST_RET ms_runtime_to_asn1 (ASN1_ENC_CTXT *aCtx, SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt); + +ST_UCHAR *ms_mk_asn1_type (ST_INT *asn1_len, ST_UCHAR *asn1_buf, + ST_CHAR *tdl); + +ST_VOID ms_log_runtime (SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt); + +ST_CHAR *ms_asn1_to_tdl (ST_UCHAR *asn1_ptr, ST_INT asn1_len, + ST_INT max_tdl_len); +ST_INT ms_runtime_to_tdl (SD_CONST RUNTIME_TYPE *rt, ST_INT rt_num, + ST_CHAR *tdl_buf, ST_INT max_tdl_len); + +RUNTIME_CTRL *ms_tdl_to_runtime (ST_CHAR *tdl, /* TDL string */ + ST_UCHAR *asn1_buf, /* ASN.1 buffer */ + ST_INT asn1_buf_len); /* buffer len */ + +ST_RET ms_rt_to_typedef (ST_CHAR *typedefName, SD_CONST RUNTIME_TYPE *rt, + ST_INT numRt, ST_CHAR *dest, ST_INT destSize); + +RUNTIME_CTRL *ms_runtime_create (ST_UCHAR *asn1_data, + ST_UINT asn1_len, + ST_INT max_num_rt); +ST_VOID ms_runtime_destroy (RUNTIME_CTRL *rt_head); + +#if !defined(MMS_LITE) +/* For backward compatibility only. */ +/* New programs should use ms_runtime_create. */ + +ST_INT ms_asn1_to_runtime_x (ST_UCHAR *asn1_data, ST_UINT asn1_len, + RUNTIME_TYPE *rt_table, ST_INT rt_len, + ST_BOOLEAN calc_only); + +#define ms_asn1_to_runtime(asn1,asn1_len,rt,num_rt)\ + ms_asn1_to_runtime_x(asn1,asn1_len,rt, num_rt,m_calc_rt_size) + +/* Note: This variable is no longer used internally by MMS-EASE, but */ +/* can be used in the application space for the following: */ +/* 1. Is used in the macro 'ms_asn1_to_runtime' for the */ +/* 'ms_asn1_to_runtime_x' calc_only parameter. This is done to */ +/* maintain backward compatibility, and users are encouraged to */ +/* use 'ms_runtime_create' instead. */ +extern ST_BOOLEAN m_calc_rt_size; /* flag to calculate num rt blocks */ + /* in ms_asn1_to_runtime */ +#endif /* !MMS_LITE */ + +/************************************************************************/ +/* ms_comp_name_find */ +/* These macros find the component name in a runtime type structure. */ +/* There are different macros for different RUNTIME_TYPE structures. */ +/* Macro argument = ptr to RUNTIME_TYPE struct. */ +/* RETURN: pointer to component name string */ +/************************************************************************/ +#if defined(USE_RT_TYPE_2) + +/* rt->comp_name_ptr = pointer to string */ +/* NOTE: ptr may be NULL. If so return empty string (i.e. "") instead */ +/* of NULL. Caller might not handle NULL. */ +#define ms_comp_name_find(rt) ((rt)->comp_name_ptr ? (rt)->comp_name_ptr : "") +#define ms_comp_name_pres(rt) ((rt)->comp_name_ptr ? SD_TRUE : SD_FALSE) + +#elif defined(USE_RT_TYPE_3) + +/* rt->name_index = index to global array of strings "mvlRtNames" */ +#define ms_comp_name_find(rt) (mvlRtNames[(rt)->name_index]) +#define ms_comp_name_pres(rt) ((rt)->name_index > 0 ? SD_TRUE : SD_FALSE) + +#else /* Default */ + +/* rt->name = character array. */ +#define ms_comp_name_find(rt) ((rt)->name) +#define ms_comp_name_pres(rt) ((rt)->name[0] != 0 ? SD_TRUE : SD_FALSE) + +#endif /* Default */ + + +/************************************************************************/ +/* VIRTUAL MACHINE ASN.1 TO?FROM LOCAL REPRESENTATION FUNCTIONS */ +/* These functions are used to translate ASN.1 encoded data to/from */ +/* local format */ +/************************************************************************/ + +#ifndef MMS_LITE +ST_RET ms_asn1_to_locl (NAMED_TYPE *type, + ST_UCHAR *asn1, ST_INT asn1_len, ST_CHAR *dest); +ST_RET ms_locl_to_asn1 (ASN1_ENC_CTXT *aCtx, NAMED_TYPE *type, ST_CHAR *src); +#endif + +/* These 2 are Re-entrant functions. Based on ASN1R tools. */ +ST_RET ms_asn1_to_local (SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt, + ST_UCHAR *asn1, ST_INT asn1_len, ST_CHAR *dest); +ST_RET ms_local_to_asn1 (ASN1_ENC_CTXT *aCtx, + SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, + ST_CHAR *dptr); +/* "ms_local_to_asn1_2" is almost the same as "ms_local_to_asn1_easy" */ +/* but its arguments are more consistent with other encoding functions. */ +ST_RET ms_local_to_asn1_2 (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + ST_CHAR *dptr, + ST_UCHAR *buf_ptr, + ST_INT buf_len, + ST_UCHAR **asn1_ptr_out, + ST_INT *asn1_len_out); +ST_UCHAR *ms_local_to_asn1_easy (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + ST_CHAR *dptr, + ST_UCHAR *asn1Buf, + ST_INT asn1BufLen, + ST_INT *asn1LenOut); +ST_CHAR *ms_local_to_text (ST_CHAR *datptr, SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + ST_CHAR *textBuf, ST_UINT textBufSize); + + + +/* Index definitions into the alignment table */ +#define ARRSTRT_ALGN 0 +#define ARREND_ALGN 1 +#define STRSTRT_ALGN 2 +#define STREND_ALGN 3 +#define INT8_ALGN 4 +#define INT16_ALGN 5 +#define INT32_ALGN 6 +#define INT64_ALGN 7 +#define FLOAT_ALGN 8 +#define DOUBLE_ALGN 9 +#define OCT_ALGN 10 +#define BOOL_ALGN 11 +#define BCD1_ALGN 12 +#define BCD2_ALGN 13 +#define BCD4_ALGN 14 +#define BIT_ALGN 15 +#define VIS_ALGN 16 + +#define NUM_ALGN_TYPES 17 + +/* define alignment for Generalized Time (in VS 2005 time_t is 64-bits) */ +#define GENERAL_TIME_ALGN (sizeof(time_t) == 8 ? INT64_ALGN : INT32_ALGN) + + +extern SD_CONST ST_INT *m_data_algn_tbl; +extern SD_CONST ST_INT m_packed_data_algn_tbl[NUM_ALGN_TYPES]; +extern SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES]; +extern ST_INT m_lite_data_algn_tbl[NUM_ALGN_TYPES]; /* created by Foundry */ + +#define M_STRSTART_MODE_NONE 0 +#define M_STRSTART_MODE_FIRST 1 +#define M_STRSTART_MODE_LARGEST 2 +extern ST_INT m_struct_start_algn_mode; + +#define M_STREND_MODE_NONE 0 +#define M_STREND_MODE_LARGEST 1 +extern ST_INT m_struct_end_algn_mode; + +/* User defined runtime type post processing function */ +extern ST_VOID (*u_rt_type_process) (SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt); + + +/************************************************************************/ +/************************************************************************/ + +/* For encoding and decoding 'alternateAccess', the outer constructor */ +/* usually has a value of 5. If a different value is required (for */ +/* scattered access, for instance), this value can be modified. */ +/* Used in both encoding and decode of alternateAccess */ +extern ST_INT16 m_alt_acc_outer_tag; + +/* When decoding an ASN.1 alternateAccess, this variable determines the */ +/* size of the table that is allocated for the decoded AA (and so */ +/* limits the complexity of the alternate access that can be handled */ +/* The default value is 50. */ +extern ST_INT m_max_dec_aa; + +/* This variable is the 'high water' mark of how many AA were actually */ +/* required. This can be used to tune memory usage if desired. */ +extern ST_INT m_hw_dec_aa; + +/* When performing ASN1 <-> local data format, the runtime type is */ +/* 'unrolled', and one element is required for each data element and */ +/* structure/array start/end. This variable determines the size of the */ +/* of the table that is allocated for this operation (and so limits the */ +/* size and complexity of the data types that can be handled. */ +/* The default value is 1000. */ +extern ST_INT m_max_rt_aa_ctrl; + +/* This variable is the 'high water' mark of how many elements were */ +/* actually required for m_max_rt_aa_ctrl. This can be used to tune */ +/* memory usage if desired. */ +extern ST_INT m_hw_rt_aa_ctrl; + +/* This variable is used to determine whether the local data format is */ +/* in 'packed type' or 'original type' form. Used in all conversions */ +/* to/from local data form when the AA_DATA library is used. */ +/* Temporarily set to SD_FALSE for the non-AA data conversion functions. */ +extern ST_BOOLEAN m_alt_acc_packed; + +/************************************************************************/ + +extern ST_RET (*ms_asn1_data_to_runtime_fun) (RUNTIME_TYPE **tptr, + ST_INT *t_len, + ST_UCHAR *asn1ptr, + ST_INT asn1_len); + +ST_RET ms_asn1_data_to_runtime (RUNTIME_TYPE **tptr, + ST_INT *t_len, + ST_UCHAR *asn1ptr, + ST_INT asn1_len); + +ST_RET ms_asn1_data_to_locl (ST_UCHAR *asn1_data, + ST_INT asn1_data_len, + ST_VOID **data_dest, + ST_INT *data_dest_len, + RUNTIME_TYPE **rt, + ST_INT *t_len); + +ST_VOID ms_rt_size_calc (RUNTIME_TYPE *rt_head, ST_INT rt_num); + +/************************************************************************/ +/* ARBITRARY DATA HANDLING */ +/************************************************************************/ + +typedef struct m_arb_data_ctrl + { + ST_RET (*arrStart) (RT_AA_CTRL *rtaa); + ST_RET (*arrEnd) (RT_AA_CTRL *rtaa); + ST_RET (*strStart) (RT_AA_CTRL *rtaa); + ST_RET (*strEnd) (RT_AA_CTRL *rtaa); + ST_RET (*int8) (ST_INT8 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*int16) (ST_INT16 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*int32) (ST_INT32 *data_dest, RT_AA_CTRL *rtaa); +#ifdef INT64_SUPPORT + ST_RET (*int64) (ST_INT64 *data_dest, RT_AA_CTRL *rtaa); +#endif + ST_RET (*uint8) (ST_UINT8 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*uint16) (ST_UINT16 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*uint32) (ST_UINT32 *data_dest, RT_AA_CTRL *rtaa); +#ifdef INT64_SUPPORT + ST_RET (*uint64) (ST_UINT64 *data_dest, RT_AA_CTRL *rtaa); +#endif + ST_RET (*flt) (ST_FLOAT *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*dbl) (ST_DOUBLE *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*oct) (ST_UCHAR *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*booln) (ST_BOOLEAN *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*bcd1) (ST_INT8 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*bcd2) (ST_INT16 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*bcd4) (ST_INT32 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*bs) (ST_UCHAR *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*vis) (ST_CHAR *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*bt4) (ST_INT32 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*bt6) (ST_INT32 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*gt) (time_t *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*utc) (MMS_UTC_TIME *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*utf8) (ST_UCHAR *data_dest, RT_AA_CTRL *rtaa); + } M_ARB_DATA_CTRL; + +ST_RET ms_process_arb_data (ST_CHAR *data_base, + SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + ST_BOOLEAN alt_acc_pres, ST_BOOLEAN alt_acc_packed, + ALT_ACCESS *alt_acc, + M_ARB_DATA_CTRL *ac); + +/************************************************************************/ +/* Functions for building a type definition one component at a time. */ +/************************************************************************/ +ST_VOID ms_rt_bld_start (RUNTIME_BUILD_CTXT *rt_ctxt, ST_INT max_rt_num); +ST_VOID ms_rt_bld_cancel (RUNTIME_BUILD_CTXT *rt_ctxt); +ST_VOID ms_rt_bld_finish (RUNTIME_BUILD_CTXT *rt_ctxt); +ST_RET ms_rt_bld_add_str_start (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name); +ST_RET ms_rt_bld_add_str_end (RUNTIME_BUILD_CTXT *ctxt); +ST_RET ms_rt_bld_add_arr_start (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT array_count); +ST_RET ms_rt_bld_add_arr_end (RUNTIME_BUILD_CTXT *ctxt); +ST_RET ms_rt_bld_add_bool (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name); +ST_RET ms_rt_bld_add_int (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_uint (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_float (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_bstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_bvstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_vstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_utctime (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name); +ST_RET ms_rt_bld_add_btime6 (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name); +ST_RET ms_rt_bld_add_ostring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_ovstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_utf8vstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_special (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, RUNTIME_TYPE *special); +ST_RET ms_rt_bld_remove_last (RUNTIME_BUILD_CTXT *ctxt); +ST_RET ms_rt_bld_chk_state (RUNTIME_BUILD_CTXT *ctxt); +ST_INT ms_rt_bld_get_count (RUNTIME_BUILD_CTXT *ctxt); +ST_INT ms_rt_bld_get_max_count (RUNTIME_BUILD_CTXT *ctxt); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/inc/mmsdefs.h b/include/inc/mmsdefs.h new file mode 100644 index 0000000..5caa0c4 --- /dev/null +++ b/include/inc/mmsdefs.h @@ -0,0 +1,235 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2004, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsdefs.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This include file is for MMS-EASE or SMALL-MMS programmer use, */ +/* and calls out all needed include files. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/09/07 JRB 14 Add forward references. */ +/* 04/09/07 MDE 13 Enhanced filtered logging */ +/* 09/17/04 EJV 12 Added mms_chk_resource. */ +/* 10/13/03 EJV 11 Moved MMSEASE_VERSION define to mms_defs.h. */ +/* 10/07/03 EJV 10 Added MMSEASE_VERSION define. */ +/* 12/12/02 JRB 09 Add ASN1_ENC_CTXT arg to _mms_unconf_req_fin */ +/* 01/18/02 JRB 08 Replace _ms_fin_pdu_debug with _ms_fin_pdu */ +/* and _ms_fin_pdu_log. */ +/* 12/20/01 JRB 07 Convert to use ASN1R. */ +/* 09/26/00 JRB 06 Add SD_CONST on ms_mk_rt_aa* */ +/* 06/01/00 RKR 05 Removed prot mms_null_pdu_dec use mms_dfun.h */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 More changes to allow compile under C++ */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/20/98 JRB 01 Del mmsop_en.h. Only user code needs it now. */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMSDEFS_INCLUDED +#define MMSDEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "glberror.h" + +#ifndef MMS_LITE +#include "gen_list.h" +#include "mem_chk.h" +#include "mms_defs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mmsintrn.h" +#include "mms_mp.h" +#include "mms_mv.h" +#include "mms_err.h" +#else +#include "mem_chk.h" +#include "mms_def2.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mmsintr2.h" +#include "mms_mp.h" +#include "mmsldefs.h" +#endif + +#include "mms_dfun.h" +#include "mms_perr.h" +#include "mms_log.h" +#include "mmslog.h" + +#include "mms_pcon.h" +#include "mms_pdom.h" +#include "mms_pevn.h" +#include "mms_pfil.h" +#include "mms_pjou.h" +#include "mms_pocs.h" +#include "mms_pprg.h" +#include "mms_psem.h" +#include "mms_pvmd.h" + +/************************************************************************/ +/* For use when global variables cannot be initialized at compile time */ + +#if defined (NO_GLB_VAR_INIT) +ST_VOID m_init_glb_vars (ST_VOID); +#endif + +/************************************************************************/ +ST_VOID _ms_wr_service_err (ASN1_ENC_CTXT *ac, ST_INT16 eclass, ST_INT16 code, + ADTNL_ERR_RESP_INFO *adtnl_info); + +/************************************************************************/ +/* Variable Access Functions. */ +/************************************************************************/ + +ST_VOID _mms_get_service_err (ASN1_DEC_CTXT *ac, ERR_INFO *dest); +ST_VOID _ms_get_mms_fname (ASN1_DEC_CTXT *ac, FILE_NAME *dest, ST_INT max_fnames, ST_INT *num_out); +ST_VOID _ms_get_mms_app_ref (ASN1_DEC_CTXT *ac, ST_UCHAR **dest, ST_INT *dest_size, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_mms_evtime (ASN1_DEC_CTXT *ac, EVENT_TIME *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_mms_modlist (ASN1_DEC_CTXT *ac, MODIFIER *dest, ST_INT *num_out, ST_INT max_mods, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_mms_objname (ASN1_DEC_CTXT *ac, OBJECT_NAME *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_jou_ent_cont (ASN1_DEC_CTXT *ac, ENTRY_CONTENT *dest, ST_INT dest_size, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_address (ASN1_DEC_CTXT *ac, VAR_ACC_ADDR *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_access_rslt (ASN1_DEC_CTXT *ac, ACCESS_RESULT *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_data (ASN1_DEC_CTXT *ac, VAR_ACC_DATA *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_type_spec (ASN1_DEC_CTXT *ac, VAR_ACC_TSPEC *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_scat_access (ASN1_DEC_CTXT *ac, SCATTERED_ACCESS *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_alt_access (ASN1_DEC_CTXT *ac, ALTERNATE_ACCESS *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_var_spec (ASN1_DEC_CTXT *ac, VARIABLE_SPEC *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_var_list (ASN1_DEC_CTXT *ac, VARIABLE_LIST *dest, ST_INT *num_out, ST_INT max_num, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_spec (ASN1_DEC_CTXT *ac, VAR_ACC_SPEC *dest, ST_INT max_vars, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); + +ST_VOID _ms_wr_mms_fname (ASN1_ENC_CTXT *ac, FILE_NAME *src, ST_INT num); +ST_VOID _ms_wr_mms_evtime (ASN1_ENC_CTXT *ac, EVENT_TIME *src); +ST_VOID _ms_wr_mms_modlist (ASN1_ENC_CTXT *ac, MODIFIER *src, ST_INT num); +ST_VOID _ms_wr_mms_objname (ASN1_ENC_CTXT *ac, OBJECT_NAME *src); +ST_VOID _ms_wr_jou_ent_cont (ASN1_ENC_CTXT *ac, ENTRY_CONTENT *src); +ST_VOID _ms_wr_va_address (ASN1_ENC_CTXT *ac, VAR_ACC_ADDR *src); +ST_VOID _ms_wr_va_access_rslt (ASN1_ENC_CTXT *ac, ACCESS_RESULT *src); +ST_VOID _ms_wr_va_data (ASN1_ENC_CTXT *ac, VAR_ACC_DATA *src); +ST_VOID _ms_wr_va_type_spec (ASN1_ENC_CTXT *ac, VAR_ACC_TSPEC *src); +ST_VOID _ms_wr_va_scat_access (ASN1_ENC_CTXT *ac, SCATTERED_ACCESS *src); +ST_VOID _ms_wr_va_alt_access (ASN1_ENC_CTXT *ac, ALTERNATE_ACCESS *src); +ST_VOID _ms_wr_va_var_spec (ASN1_ENC_CTXT *ac, VARIABLE_SPEC *src); +ST_VOID _ms_wr_va_var_list (ASN1_ENC_CTXT *ac, VARIABLE_LIST *src, ST_INT num); +ST_VOID _ms_wr_va_spec (ASN1_ENC_CTXT *ac, VAR_ACC_SPEC *src); + +ST_VOID _mms_init_dec (ASN1_DEC_CTXT *ac, ST_BOOLEAN req); + +/************************************************************************/ +/* Alternate Access Functions */ +/************************************************************************/ +ST_VOID _ms_log_runtime_aa (RT_AA_CTRL *rt_aa, ST_INT num_aa); + +ST_RET _ms_mk_rt_aa_all (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + RT_AA_CTRL **rt_aa_out, ST_INT *num_aa_out); + +ST_RET _ms_mk_rt_aa (SD_CONST RUNTIME_TYPE *rt, ST_INT rt_num, + ALT_ACCESS *alt_acc, + RT_AA_CTRL **rt_aa_out, ST_INT *num_aa_out); + +ST_INT _ms_get_rtaa_data_size (RT_AA_CTRL *runtime_aa, ST_INT num_rt_aa); + +/************************************************************************/ +/* Special ASN.1 buffer handling functions for VM operations where */ +/* a series of ASN.1 encoded AA must be created. */ + +ST_UCHAR *_m_get_aa_asn1_buf (ST_INT *size_out); +ST_VOID _m_free_aa_asn1_buf (ST_VOID); +ST_VOID _m_set_aa_asn1_buf_end (ST_UCHAR *new_end); + +/************************************************************************/ +/************************************************************************/ +/* General function declarations used by the mp_xxx series. */ +/* These are not of general use to the application programmer. */ +/************************************************************************/ + +ST_VOID _ms_chk_for_extern (ASN1_DEC_CTXT *ac, ST_INT *len_ptr, ST_UCHAR **buf_ptr, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_set_cs_check (ASN1_DEC_CTXT *ac); +ST_VOID _ms_set_cs_check2 (ASN1_DEC_CTXT *ac); +ST_VOID _mms_dec_done_ok (ASN1_DEC_CTXT *ac); + +ST_UCHAR *_ms_fin_pdu (ASN1_ENC_CTXT *aCtx, ST_INT type, ST_INT *pPduLen); +#ifdef DEBUG_SISCO +ST_VOID _ms_fin_pdu_log (ST_INT type, ST_CHAR *txt, + ST_UCHAR *pduPtr, ST_INT pduLen); +#endif + +ST_VOID _mms_dec_buf_free (ASN1_DEC_CTXT *ac, ST_RET err_code); +#ifndef MMS_LITE +ST_RET _mms_send_null_resp (MMSREQ_IND *indptr, ST_INT opcode); +MMSREQ_PEND *_mms_send_null_req (ST_INT chan, ST_INT opcode); + +MMSREQ_PEND *_mms_req_send (ST_INT opcode, + ST_VOID (*mk_ptr)(ASN1_ENC_CTXT *, ST_CHAR *), + ST_INT chan, + ST_CHAR *info_ptr); + +ST_INT _mms_chk_resource (ST_INT chan); +ST_RET _mms_unconf_req_send (ST_INT opcode, + ST_VOID (*mk_ptr)(ASN1_ENC_CTXT *, ST_CHAR *), + ST_INT chan, + ST_CHAR *info_ptr); + +ST_RET _mms_resp_send (ST_INT opcode, + MMSREQ_IND *indptr, + ST_VOID (*mk_fun)(ASN1_ENC_CTXT *, ST_CHAR *), + ST_CHAR *info_ptr); + +#else +ST_RET _mms_fin_null_resp (ST_UINT32 invoke_id, ST_INT opcode); +ST_RET _mms_fin_null_req (ST_INT opcode); + +ST_RET _mms_resp_fin (ST_INT opcode, ST_UINT32 invoke_id, + ST_VOID (*mk_fun)(ASN1_ENC_CTXT *, ST_CHAR *), + ST_CHAR *info_ptr); + +ST_RET _mms_req_fin (ST_INT opcode, + ST_VOID (*mk_ptr)(ASN1_ENC_CTXT *, ST_CHAR *), + ST_CHAR *info_ptr); + +ST_RET _mms_unconf_req_fin (ASN1_ENC_CTXT *aCtx, ST_INT opcode, + ST_VOID (*mk_ptr)(ASN1_ENC_CTXT *, ST_CHAR *), + ST_CHAR *info_ptr); + +struct mvl_req_pend; /* forward reference */ +struct mvl_ind_pend; /* forward reference */ +struct mvl_net_info; /* forward reference */ + +ST_VOID mpl_req_log (struct mvl_req_pend *reqCtrl, ST_VOID *reqInfo); +ST_VOID mpl_resp_log (struct mvl_ind_pend *indCtrl, ST_VOID *respInfo); +ST_VOID mpl_unsol_req_log (struct mvl_net_info *netInfo, ST_INT op, ST_VOID *reqInfo); + +#endif + +/* A casting aid ... */ +#define M_CAST_MK_FUN(x) ((ST_VOID(*)(ASN1_ENC_CTXT *, ST_CHAR *)) x) + + +#ifndef MMS_LITE +#include "mms_llp.h" +#include "mmsllp.h" +#endif + +#include "mmsefun.h" /* Bruder moved this here */ +#ifdef __cplusplus +} +#endif + +#endif /* MMSDEFS_INCLUDED */ + + diff --git a/include/inc/mmsefun.h b/include/inc/mmsefun.h new file mode 100644 index 0000000..4db5135 --- /dev/null +++ b/include/inc/mmsefun.h @@ -0,0 +1,188 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsefun.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the function declarations used by the primitive */ +/* level encode routines (mp_xxxx). */ +/* */ +/* Parameters : pointer to the operation specific data structure. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Convert to use ASN1R. */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMSEFUN_INCLUDED +#define MMSEFUN_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/* primitive encode functions */ +/************************************************************************/ + +ST_UCHAR *_ms_mk_init (ASN1_ENC_CTXT *ac, ST_UCHAR *buf_ptr, ST_INT buf_len, + INIT_INFO *info_ptr, ST_INT pdutype, + ST_BOOLEAN cs_init); + +ST_UCHAR *_ms_mk_conclude (ASN1_ENC_CTXT *ac, ST_UCHAR *buf_ptr,ST_INT buf_len,ST_INT pdutype); + +ST_UCHAR *_ms_mk_cancel (ASN1_ENC_CTXT *ac, ST_BOOLEAN request, ST_UCHAR *msg_ptr, + ST_INT buf_len, ST_UINT32 id); + +ST_UCHAR *_ms_mk_reject (ASN1_ENC_CTXT *ac, ST_UCHAR *msg_ptr, ST_INT buf_len, + REJECT_RESP_INFO *info_ptr); + +ST_UCHAR *_ms_mk_err_resp (ASN1_ENC_CTXT *ac, ST_UCHAR *buf_ptr, ST_INT buf_len, ST_INT op, + ST_UINT32 id, ST_INT16 err_class, ST_INT16 code); + +ST_VOID _ms_mk_stat_req (ASN1_ENC_CTXT *ac, STATUS_REQ_INFO *info); +ST_VOID _ms_mk_stat_resp (ASN1_ENC_CTXT *ac, STATUS_RESP_INFO *info); +ST_VOID _ms_mk_ustat_req (ASN1_ENC_CTXT *ac, USTATUS_REQ_INFO *info); +ST_VOID _ms_mk_namel_req (ASN1_ENC_CTXT *ac, NAMELIST_REQ_INFO *info); +ST_VOID _ms_mk_namel_resp (ASN1_ENC_CTXT *ac, NAMELIST_RESP_INFO *info); +ST_VOID _ms_mk_ident_resp (ASN1_ENC_CTXT *ac, IDENT_RESP_INFO *info); +ST_VOID _ms_mk_rename_req (ASN1_ENC_CTXT *ac, RENAME_REQ_INFO *info); +ST_VOID _ms_mk_getcl_req (ASN1_ENC_CTXT *ac, GETCL_REQ_INFO *info); +ST_VOID _ms_mk_getcl_resp (ASN1_ENC_CTXT *ac, GETCL_RESP_INFO *info); + +ST_VOID _ms_mk_initdown_req (ASN1_ENC_CTXT *ac, INITDOWN_REQ_INFO *info); +ST_VOID _ms_mk_initdown_resp (ASN1_ENC_CTXT *ac, ST_VOID *dummy_info); +ST_VOID _ms_mk_download_req (ASN1_ENC_CTXT *ac, DOWNLOAD_REQ_INFO *info); +ST_VOID _ms_mk_download_resp (ASN1_ENC_CTXT *ac, DOWNLOAD_RESP_INFO *info); +ST_VOID _ms_mk_termdown_req (ASN1_ENC_CTXT *ac, TERMDOWN_REQ_INFO *info); +ST_VOID _ms_mk_initupl_req (ASN1_ENC_CTXT *ac, INITUPL_REQ_INFO *info); +ST_VOID _ms_mk_initupl_resp (ASN1_ENC_CTXT *ac, INITUPL_RESP_INFO *info); +ST_VOID _ms_mk_upload_req (ASN1_ENC_CTXT *ac, UPLOAD_REQ_INFO *info); +ST_VOID _ms_mk_upload_resp (ASN1_ENC_CTXT *ac, UPLOAD_RESP_INFO *info); +ST_VOID _ms_mk_termupl_req (ASN1_ENC_CTXT *ac, TERMUPL_REQ_INFO *info); +ST_VOID _ms_mk_rddwn_req (ASN1_ENC_CTXT *ac, RDDWN_REQ_INFO *info); +ST_VOID _ms_mk_rdupl_req (ASN1_ENC_CTXT *ac, RDUPL_REQ_INFO *info); +ST_VOID _ms_mk_loaddom_req (ASN1_ENC_CTXT *ac, LOADDOM_REQ_INFO *info); +ST_VOID _ms_mk_storedom_req (ASN1_ENC_CTXT *ac, STOREDOM_REQ_INFO *info); +ST_VOID _ms_mk_deldom_req (ASN1_ENC_CTXT *ac, DELDOM_REQ_INFO *info); +ST_VOID _ms_mk_getdom_req (ASN1_ENC_CTXT *ac, GETDOM_REQ_INFO *info); +ST_VOID _ms_mk_getdom_resp (ASN1_ENC_CTXT *ac, GETDOM_RESP_INFO *info); + +ST_VOID _ms_mk_crepi_req (ASN1_ENC_CTXT *ac, CREPI_REQ_INFO *info); +ST_VOID _ms_mk_delpi_req (ASN1_ENC_CTXT *ac, DELPI_REQ_INFO *info); +ST_VOID _ms_mk_start_req (ASN1_ENC_CTXT *ac, START_REQ_INFO *info); +ST_VOID _ms_mk_stop_req (ASN1_ENC_CTXT *ac, STOP_REQ_INFO *info); +ST_VOID _ms_mk_resume_req (ASN1_ENC_CTXT *ac, RESUME_REQ_INFO *info); +ST_VOID _ms_mk_reset_req (ASN1_ENC_CTXT *ac, RESET_REQ_INFO *info); +ST_VOID _ms_mk_kill_req (ASN1_ENC_CTXT *ac, KILL_REQ_INFO *info); +ST_VOID _ms_mk_getpi_req (ASN1_ENC_CTXT *ac, GETPI_REQ_INFO *info); +ST_VOID _ms_mk_getpi_resp (ASN1_ENC_CTXT *ac, GETPI_RESP_INFO *info); + +ST_VOID _ms_mk_read_req (ASN1_ENC_CTXT *ac, READ_REQ_INFO *info); +ST_VOID _ms_mk_read_resp (ASN1_ENC_CTXT *ac, READ_RESP_INFO *info); +ST_VOID _ms_mk_write_req (ASN1_ENC_CTXT *ac, WRITE_REQ_INFO *info); +ST_VOID _ms_mk_write_resp (ASN1_ENC_CTXT *ac, WRITE_RESP_INFO *info); +ST_VOID _ms_mk_info_req (ASN1_ENC_CTXT *ac, INFO_REQ_INFO *info); +ST_VOID _ms_mk_getvar_req (ASN1_ENC_CTXT *ac, GETVAR_REQ_INFO *info); +ST_VOID _ms_mk_getvar_resp (ASN1_ENC_CTXT *ac, GETVAR_RESP_INFO *info); +ST_VOID _ms_mk_defvar_req (ASN1_ENC_CTXT *ac, DEFVAR_REQ_INFO *info); +ST_VOID _ms_mk_delvar_req (ASN1_ENC_CTXT *ac, DELVAR_REQ_INFO *info); +ST_VOID _ms_mk_delvar_resp (ASN1_ENC_CTXT *ac, DELVAR_RESP_INFO *info); +ST_VOID _ms_mk_defscat_req (ASN1_ENC_CTXT *ac, DEFSCAT_REQ_INFO *info); +ST_VOID _ms_mk_getscat_req (ASN1_ENC_CTXT *ac, GETSCAT_REQ_INFO *info); +ST_VOID _ms_mk_getscat_resp (ASN1_ENC_CTXT *ac, GETSCAT_RESP_INFO *info); +ST_VOID _ms_mk_defvlist_req (ASN1_ENC_CTXT *ac, DEFVLIST_REQ_INFO *info); +ST_VOID _ms_mk_getvlist_req (ASN1_ENC_CTXT *ac, GETVLIST_REQ_INFO *info); +ST_VOID _ms_mk_getvlist_resp (ASN1_ENC_CTXT *ac, GETVLIST_RESP_INFO *info); +ST_VOID _ms_mk_delvlist_req (ASN1_ENC_CTXT *ac, DELVLIST_REQ_INFO *info); +ST_VOID _ms_mk_delvlist_resp (ASN1_ENC_CTXT *ac, DELVLIST_RESP_INFO *info); +ST_VOID _ms_mk_gettype_req (ASN1_ENC_CTXT *ac, GETTYPE_REQ_INFO *info); +ST_VOID _ms_mk_gettype_resp (ASN1_ENC_CTXT *ac, GETTYPE_RESP_INFO *info); +ST_VOID _ms_mk_deftype_req (ASN1_ENC_CTXT *ac, DEFTYPE_REQ_INFO *info); +ST_VOID _ms_mk_deltype_req (ASN1_ENC_CTXT *ac, DELTYPE_REQ_INFO *info); +ST_VOID _ms_mk_deltype_resp (ASN1_ENC_CTXT *ac, DELTYPE_RESP_INFO *info); + +ST_VOID _ms_mk_takectrl_req (ASN1_ENC_CTXT *ac, TAKECTRL_REQ_INFO *info); +ST_VOID _ms_mk_takectrl_resp (ASN1_ENC_CTXT *ac, TAKECTRL_RESP_INFO *info); +ST_VOID _ms_mk_relctrl_req (ASN1_ENC_CTXT *ac, RELCTRL_REQ_INFO *info); +ST_VOID _ms_mk_rsstat_req (ASN1_ENC_CTXT *ac, RSSTAT_REQ_INFO *info); +ST_VOID _ms_mk_rsstat_resp (ASN1_ENC_CTXT *ac, RSSTAT_RESP_INFO *info); +ST_VOID _ms_mk_rspool_req (ASN1_ENC_CTXT *ac, RSPOOL_REQ_INFO *info); +ST_VOID _ms_mk_rspool_resp (ASN1_ENC_CTXT *ac, RSPOOL_RESP_INFO *info); +ST_VOID _ms_mk_rsentry_req (ASN1_ENC_CTXT *ac, RSENTRY_REQ_INFO *info); +ST_VOID _ms_mk_rsentry_resp (ASN1_ENC_CTXT *ac, RSENTRY_RESP_INFO *info); +ST_VOID _ms_mk_defsem_req (ASN1_ENC_CTXT *ac, DEFSEM_REQ_INFO *info); +ST_VOID _ms_mk_delsem_req (ASN1_ENC_CTXT *ac, DELSEM_REQ_INFO *info); + +ST_VOID _ms_mk_output_req (ASN1_ENC_CTXT *ac, OUTPUT_REQ_INFO *info); +ST_VOID _ms_mk_input_req (ASN1_ENC_CTXT *ac, INPUT_REQ_INFO *info); +ST_VOID _ms_mk_input_resp (ASN1_ENC_CTXT *ac, INPUT_RESP_INFO *info); + +ST_VOID _ms_mk_defec_req (ASN1_ENC_CTXT *ac, DEFEC_REQ_INFO *info); +ST_VOID _ms_mk_delec_req (ASN1_ENC_CTXT *ac, DELEC_REQ_INFO *info); +ST_VOID _ms_mk_delec_resp (ASN1_ENC_CTXT *ac, DELEC_RESP_INFO *info); +ST_VOID _ms_mk_geteca_req (ASN1_ENC_CTXT *ac, GETECA_REQ_INFO *info); +ST_VOID _ms_mk_geteca_resp (ASN1_ENC_CTXT *ac, GETECA_RESP_INFO *info); +ST_VOID _ms_mk_repecs_req (ASN1_ENC_CTXT *ac, REPECS_REQ_INFO *info); +ST_VOID _ms_mk_repecs_resp (ASN1_ENC_CTXT *ac, REPECS_RESP_INFO *info); +ST_VOID _ms_mk_altecm_req (ASN1_ENC_CTXT *ac, ALTECM_REQ_INFO *info); +ST_VOID _ms_mk_trige_req (ASN1_ENC_CTXT *ac, TRIGE_REQ_INFO *info); +ST_VOID _ms_mk_defea_req (ASN1_ENC_CTXT *ac, DEFEA_REQ_INFO *info); +ST_VOID _ms_mk_delea_req (ASN1_ENC_CTXT *ac, DELEA_REQ_INFO *info); +ST_VOID _ms_mk_delea_resp (ASN1_ENC_CTXT *ac, DELEA_RESP_INFO *info); +ST_VOID _ms_mk_geteaa_req (ASN1_ENC_CTXT *ac, GETEAA_REQ_INFO *info); +ST_VOID _ms_mk_geteaa_resp (ASN1_ENC_CTXT *ac, GETEAA_RESP_INFO *info); +ST_VOID _ms_mk_repeas_req (ASN1_ENC_CTXT *ac, REPEAS_REQ_INFO *info); +ST_VOID _ms_mk_repeas_resp (ASN1_ENC_CTXT *ac, REPEAS_RESP_INFO *info); +ST_VOID _ms_mk_defee_req (ASN1_ENC_CTXT *ac, DEFEE_REQ_INFO *info); +ST_VOID _ms_mk_delee_req (ASN1_ENC_CTXT *ac, DELEE_REQ_INFO *info); +ST_VOID _ms_mk_delee_resp (ASN1_ENC_CTXT *ac, DELEE_RESP_INFO *info); +ST_VOID _ms_mk_altee_req (ASN1_ENC_CTXT *ac, ALTEE_REQ_INFO *info); +ST_VOID _ms_mk_altee_resp (ASN1_ENC_CTXT *ac, ALTEE_RESP_INFO *info); +ST_VOID _ms_mk_repees_req (ASN1_ENC_CTXT *ac, REPEES_REQ_INFO *info); +ST_VOID _ms_mk_repees_resp (ASN1_ENC_CTXT *ac, REPEES_RESP_INFO *info); +ST_VOID _ms_mk_geteea_req (ASN1_ENC_CTXT *ac, GETEEA_REQ_INFO *info); +ST_VOID _ms_mk_geteea_resp (ASN1_ENC_CTXT *ac, GETEEA_RESP_INFO *info); +ST_VOID _ms_mk_evnot_req (ASN1_ENC_CTXT *ac, EVNOT_REQ_INFO *info); +ST_VOID _ms_mk_ackevnot_req (ASN1_ENC_CTXT *ac, ACKEVNOT_REQ_INFO *info); +ST_VOID _ms_mk_getas_req (ASN1_ENC_CTXT *ac, GETAS_REQ_INFO *info); +ST_VOID _ms_mk_getas_resp (ASN1_ENC_CTXT *ac, GETAS_RESP_INFO *info); +ST_VOID _ms_mk_getaes_req (ASN1_ENC_CTXT *ac, GETAES_REQ_INFO *info); +ST_VOID _ms_mk_getaes_resp (ASN1_ENC_CTXT *ac, GETAES_RESP_INFO *info); + +ST_VOID _ms_mk_jwrite_req (ASN1_ENC_CTXT *ac, JWRITE_REQ_INFO *info); +ST_VOID _ms_mk_jread_req (ASN1_ENC_CTXT *ac, JREAD_REQ_INFO *info); +ST_VOID _ms_mk_jread_resp (ASN1_ENC_CTXT *ac, JREAD_RESP_INFO *info); +ST_VOID _ms_mk_jinit_req (ASN1_ENC_CTXT *ac, JINIT_REQ_INFO *info); +ST_VOID _ms_mk_jinit_resp (ASN1_ENC_CTXT *ac, JINIT_RESP_INFO *info); +ST_VOID _ms_mk_jstat_req (ASN1_ENC_CTXT *ac, JSTAT_REQ_INFO *info); +ST_VOID _ms_mk_jstat_resp (ASN1_ENC_CTXT *ac, JSTAT_RESP_INFO *info); +ST_VOID _ms_mk_jcreate_req (ASN1_ENC_CTXT *ac, JCREATE_REQ_INFO *info); +ST_VOID _ms_mk_jdelete_req (ASN1_ENC_CTXT *ac, JDELETE_REQ_INFO *info); + +ST_VOID _ms_mk_obtfile_req (ASN1_ENC_CTXT *ac, OBTFILE_REQ_INFO *info); +ST_VOID _ms_mk_fopen_req (ASN1_ENC_CTXT *ac, FOPEN_REQ_INFO *info); +ST_VOID _ms_mk_fopen_resp (ASN1_ENC_CTXT *ac, FOPEN_RESP_INFO *info); +ST_VOID _ms_mk_fread_req (ASN1_ENC_CTXT *ac, FREAD_REQ_INFO *info); +ST_VOID _ms_mk_fread_resp (ASN1_ENC_CTXT *ac, FREAD_RESP_INFO *info); +ST_VOID _ms_mk_fclose_req (ASN1_ENC_CTXT *ac, FCLOSE_REQ_INFO *info); +ST_VOID _ms_mk_frename_req (ASN1_ENC_CTXT *ac, FRENAME_REQ_INFO *info); +ST_VOID _ms_mk_fdelete_req (ASN1_ENC_CTXT *ac, FDELETE_REQ_INFO *info); +ST_VOID _ms_mk_fdir_req (ASN1_ENC_CTXT *ac, FDIR_REQ_INFO *info); +ST_VOID _ms_mk_fdir_resp (ASN1_ENC_CTXT *ac, FDIR_RESP_INFO *info); + +#ifdef __cplusplus +} +#endif + +#endif /* MMSEFUN_INCLUDED */ diff --git a/include/inc/mmsintr2.h b/include/inc/mmsintr2.h new file mode 100644 index 0000000..5215103 --- /dev/null +++ b/include/inc/mmsintr2.h @@ -0,0 +1,317 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsintr2.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Functions and variables below this point are typically not */ +/* used by the application, and need not be exposed. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/04/02 JRB 11 Use SD_CONST on ALL (RUNTIME_TYPE *) vars. */ +/* 12/20/01 JRB 10 Convert to use ASN1R. */ +/* 04/19/00 JRB 09 Fix SD_CONST for decode funct ptr arrays. */ +/* 09/13/99 MDE 08 Added SD_CONST modifiers */ +/* 03/23/99 MDE 07 Changes to decode buffer allocation scheme */ +/* 03/19/98 JRB 06 Move ASN.1 error codes to "asn1defs.h". */ +/* 03/12/98 MDE 05 '_ms_m_get_rt_info' use change */ +/* 02/10/98 MDE 04 Removed unused 'm_cl_max_event_attributes' */ +/* 07/16/97 MDE 03 Added m_param, m_service_resp for MMS_LITE */ +/* 07/03/97 MDE 02 Removed CALLOC_OS */ +/* 06/09/97 MDE 01 Added decode buffer size control variables */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMSINTR2_INCLUDED +#define MMSINTR2_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/************************************************************************/ +/* Defines for Modifier and Companion Standard support. */ +/* MMSEASE defaults to supporting both, MMSEASE-LITE defaults to */ +/* supporting neither. */ +/************************************************************************/ + +#ifndef MMS_LITE +#define MOD_SUPPORT /* MMSEASE - support modifiers */ +#define CS_SUPPORT /* MMSEASE - support companion standards */ +#endif + +/************************************************************************/ +/************************************************************************/ +/* Operation Specific Decode Buffer Management */ + +extern ST_VOID *(*m_calloc_os_fun)(ST_UINT num, ST_UINT size); +extern ST_VOID *(*m_realloc_os_fun)(ST_VOID *old, ST_UINT new_size); +extern ST_VOID (*m_free_os_fun)(ST_VOID *buf); + +ST_VOID *_m_get_dec_buf (ASN1_DEC_CTXT *aCtx, ST_UINT size); + +/************************************************************************/ +/************************************************************************/ +/* Defines for the fourteen types of MMS PDUs */ +/************************************************************************/ + +#define MMSREQ 0 /* MMS request PDU for normal confirmed services */ +#define MMSRESP 1 /* MMS response PDU for normal confirmed services*/ +#define MMSERROR 2 /* MMS error PDU for normal confirmed services */ +#define MMSUNREQ 3 /* MMS response PDU for unconfirmed services */ +#define MMSREJECT 4 /* MMS reject PDU */ +#define MMSCANREQ 5 /* MMS request PDU for Cancel service */ +#define MMSCANRESP 6 /* MMS response PDU for Cancel service */ +#define MMSCANERR 7 /* MMS error PDU for Cancel service */ +#define MMSINITREQ 8 /* MMS request PDU for Initiate service */ +#define MMSINITRESP 9 /* MMS response PDU for Initiate service */ +#define MMSINITERR 10 /* MMS error PDU for Initiate service */ +#define MMSCNCLREQ 11 /* MMS request PDU for Conclude service */ +#define MMSCNCLRESP 12 /* MMS response PDU for Conclude service */ +#define MMSCNCLERR 13 /* MMS error PDU for Conclude service */ +#define UNKNOWNTYPE 14 /* not known - used in reject info structure */ + +/************************************************************************/ +/************************************************************************/ +/* Define base reserved invoke IDs for the Initiate and Conclude */ +/* services. Allows for up to 4096 associations with reserved */ +/* invoke IDs. */ +/************************************************************************/ + +#define INIT_INVOKE_ID 0x8000 /* base invoke ID for Initiate requests */ +#define CONCL_INVOKE_ID 0x9000 /* base invoke ID for Conclude requests */ + +/************************************************************************/ +/* Define the reserved invoke ID for unconfirmed requests. */ +/************************************************************************/ + +#define UNREQ_INVOKE 0xFFFF /* reserved invoke ID for unconf req's */ + +/************************************************************************/ +/************************************************************************/ +/* The following function pointer arrays are used for the request and */ +/* response decode functions. The operation opcode is used as the index */ +/* into the table. */ +/************************************************************************/ + +#define MAX_REQ_DFUN 85 /* highest request decode array entry */ +#define MAX_RSP_DFUN 85 /* highest response decode array entry */ + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* This structure is used to return the results of a MMS PDU decode. */ +/* The user passes a pointer to a struct of this type to decode_mms, */ +/* and when the decode is complete, the struct info will be filled in. */ +/* */ +/* dec_level : */ +/* 0 - Nothing valid */ +/* 1 - type valid */ +/* 2 - type, invoke ID valid */ +/* 3 - type, invoke ID, op valid */ +/************************************************************************/ + +struct mmsdec_info + { + ST_RET err_code; /* decode error code (NO_DECODE_ERR) */ + ST_INT dec_level; /* indicates valid members */ + ST_INT type; /* MMS pdu type (req,resp,err,rej) */ + ST_INT op; /* operation opcode */ + ST_UINT32 id; /* invoke ID */ + struct list_of_mods mods; /* tracking of modifiers */ + struct csi cs; /* Companion Standard Info */ + ST_BOOLEAN data_pres; /* flag to indicate data buffer present */ + ST_VOID *data_ptr; /* pointer to data if present */ + }; +typedef struct mmsdec_info MMSDEC_INFO; + +extern ST_VOID (* SD_CONST mms_req_decode_fun [MAX_REQ_DFUN+1]) (ASN1_DEC_CTXT *aCtx); +extern ST_VOID (* SD_CONST mms_rsp_decode_fun [MAX_RSP_DFUN+1]) (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mms_decode is used at MMS decode level, not generally used by */ +/* application directly. */ +/************************************************************************/ + +ST_RET _ms_mms_decode (ST_UCHAR *ptr, ST_INT len, MMSDEC_INFO *rslt); + +extern MMSDEC_INFO *_mmsdec_rslt; +extern ST_UINT _mmsdec_ctxt; /* default to core context */ +extern ST_INT _mmsdec_msglen; /* MMS decode message length */ +extern ST_UCHAR *_mmsdec_msgptr; /* MMS decode message ptr */ +extern ST_BOOLEAN _mms_dec_info_pres; +extern ST_VOID *_mms_dec_info; /* operation specific info */ + + +/************************************************************************/ +/************************************************************************/ +/* These variables are used help control decode operation specific data */ +/* structure allocation. For MMS-LITE (M_USR_DEC_BUF), these variables */ +/* are used to tell the decode system how many objects the allocated */ +/* buffer (_mms_dec_info). For MMS-EASE, these are normally not used; */ +/* if they are set non-zero, they will be used in calculating the size */ +/* of the dec info buffer to be allocated. */ + +/* Client Decode Limits. */ +extern ST_INT m_cl_read_spec_in_result; +extern ST_INT m_cl_max_read_var_spec; +extern ST_INT m_cl_max_read_acc_rslt; +extern ST_INT m_cl_max_info_var_spec; +extern ST_INT m_cl_max_info_acc_rslt; +extern ST_INT m_cl_max_getvla_vars; +extern ST_INT m_cl_max_write_rslts; +extern ST_INT m_cl_max_namel_names; +extern ST_INT m_cl_max_getcl_cap; +extern ST_INT m_cl_max_getpi_doms; +extern ST_INT m_cl_max_getdom_cap; +extern ST_INT m_cl_max_getdom_pi; +extern ST_INT m_cl_max_initupl_cap; +extern ST_INT m_cl_max_alarm_summary; +extern ST_INT m_cl_max_journal_entries; +extern ST_INT m_cl_max_entry_content; +extern ST_INT m_cl_max_semaphore_entries; +extern ST_INT m_cl_max_named_tokens; +extern ST_INT m_cl_max_file_directory; +extern ST_INT m_cl_max_event_enrollment; +extern ST_INT m_cl_max_enrollment_summary; + +/* Server Decode Limits. */ +extern ST_INT m_sv_max_loadd_cap; +extern ST_INT m_sv_max_read_var_spec; +extern ST_INT m_sv_max_write_var_spec; +extern ST_INT m_sv_max_write_data; +extern ST_INT m_sv_max_rqdlnl_cap; +extern ST_INT m_sv_max_initdnld_cap; +extern ST_INT m_sv_max_vstr; +extern ST_INT m_sv_max_file_names; +extern ST_INT m_sv_max_obj_name; +extern ST_INT m_sv_max_prompt_count; +extern ST_INT m_sv_max_num_vars; +extern ST_INT m_sv_max_data_count; +extern ST_INT m_sv_max_entry_content; +extern ST_INT m_sv_max_data_vars; +extern ST_INT m_sv_max_jread_vars; + +/************************************************************************/ +/* These bitstrings are located in mmsop_en.c and indicate which */ +/* services and CBB's are supported by this application. */ +#ifdef MMS_LITE +extern SD_CONST ST_UCHAR m_param[2]; /* parameter support */ + /* services supported as responder */ +extern SD_CONST ST_UCHAR m_service_resp[11]; +#endif + +/************************************************************************/ +/************************************************************************/ +/* This variable can be set to force use of the DIS MMS floating point */ +/* type protocol (used in any over the wire and internal ASN.1 type */ +/* definitions). */ + +extern ST_BOOLEAN m_use_dis_float; /* = SD_FALSE; */ + +/************************************************************************/ +/************************************************************************/ +/* ALTERNATE ACCESS */ + +/* This structure is used to control the creation of RTAA types */ +/* and contains state information for the various functions to use */ +/* during the process. */ + +struct aa_apply_ctrl + { +/* Alternate Access spec */ + ST_INT num_aa; /* # elements in AA table */ + struct alt_acc_el *aa_head; /* Head of AA table */ + struct alt_acc_el *aa_end; /* Last element in AA table */ + struct alt_acc_el *curr_aa; /* Current location in table */ + +/* 'All'runtime aa */ + ST_INT num_all_rtaa; + struct rt_aa_ctrl *all_rtaa_head; + struct rt_aa_ctrl *all_rtaa_end; + +/* New (output) runtime aa */ + ST_INT num_rtaa; + struct rt_aa_ctrl *rtaa_head; + struct rt_aa_ctrl *curr_rtaa; + +/* Nest Level */ + ST_INT nest; + }; +typedef struct aa_apply_ctrl AA_APPLY_CTRL; + +/************************************************************************/ +/* Floating point type ASN.1 definition values */ + +#define SNGL_WHOLE 32 +#define SNGL_FRACT 23 +#define SNGL_EXP 8 + +#define DOUBL_WHOLE 64 +#define DOUBL_FRACT 52 +#define DOUBL_EXP 11 + +/* Used to determine number of bytes required to hold a number of bits */ +#define CALC_BIT_LEN(x) (((x)+7)/8) + +/************************************************************************/ +ST_RET _ms_m_get_rt_info (SD_CONST RUNTIME_TYPE *rt, + ST_INT *algn_out, + ST_INT *ellen_out); + +/************************************************************************/ +/* Function pointers for Variable manipulation functions. */ +/* User exposed functions (i.e. ms_add_named_var, etc.) call these */ +/* function pointers which should point to "linked list" functions */ +/* by default (see "_ms_ll_*" functions below). If the "ms_bs_init" */ +/* function is called, these will point to "binary search" functions */ +/* (see "_ms_bs_*" functions below). */ +/************************************************************************/ +#ifndef MMS_LITE + +extern NAMED_VAR *(*_ms_fp_add_named_var) (DOMAIN_OBJS *dom, ST_CHAR *name, + OBJECT_NAME *type, VAR_ACC_ADDR *addr, ST_INT chan); +extern NAMED_VAR *(*_ms_fp_add_var) (DOMAIN_OBJS *dom, ST_CHAR *name, + NAMED_TYPE *type_ptr, VAR_ACC_ADDR *addr, ST_INT chan); +extern NAMED_VAR *(*_ms_fp_find_named_var) + (DOMAIN_OBJS *dom, ST_CHAR *name); +extern ST_RET (*_ms_fp_del_named_var) (DOMAIN_OBJS *dom, ST_CHAR *name); +extern ST_VOID (*_ms_fp_del_all_named_vars) (DOMAIN_OBJS *dom); +extern ST_VOID (*_ms_fp_del_deletable_named_vars) (DOMAIN_OBJS *, DELVAR_RESP_INFO *); +extern NAMED_VAR_LIST *(*_ms_fp_add_nvlist) (DOMAIN_OBJS *dom, + ST_CHAR *name, ST_INT num_vars, VARIABLE_LIST *var_list); +extern NAMED_VAR_LIST *(*_ms_fp_find_nvlist) (DOMAIN_OBJS *dom, ST_CHAR *name); +extern ST_RET (*_ms_fp_del_nvlist) (DOMAIN_OBJS *dom, ST_CHAR *name); +extern ST_VOID (*_ms_fp_del_all_nvlists) (DOMAIN_OBJS *dom); +extern ST_VOID (*_ms_fp_del_deletable_nvlists) (DOMAIN_OBJS *, DELVLIST_RESP_INFO *); + +extern NAMED_DOM_CTRL *(*_ms_fp_add_named_domain) (INITDOWN_REQ_INFO *dom_info, + ST_UCHAR pro); +extern NAMED_DOM_CTRL *(*_ms_fp_find_named_dom)(ST_CHAR dname[MAX_IDENT_LEN+1]); +extern ST_RET (*_ms_fp_del_named_dom) (ST_CHAR *dname); +extern ST_VOID (*_ms_fp_del_all_named_doms)(NAMED_DOM_CTRL *head_of_dom_list); + +extern ST_VOID (*_ms_fp_write_object_names) (ST_VOID *dom_or_vmd, + NAMELIST_REQ_INFO *reqinfo, NAMELIST_RESP_INFO *respinfo, + ST_INT max_names); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* MMSINTR2_INCLUDED */ diff --git a/include/inc/mmsldefs.h b/include/inc/mmsldefs.h new file mode 100644 index 0000000..fe8b2c8 --- /dev/null +++ b/include/inc/mmsldefs.h @@ -0,0 +1,94 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsldefs.h */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Functions and variables below this point are used by the */ +/* application. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/27/09 JRB 26 Updated version. */ +/* 02/18/09 RKR 25 Updated version. */ +/* 01/19/09 RKR 24 Updated version. */ +/* 12/01/08 GLB 23 Updated version. */ +/* 11/10/08 GLB 22 Updated version. */ +/* 04/23/08 GLB 21 Updated version. */ +/* 01/02/07 JRB 20 Updated version. */ +/* 04/10/06 RKR 19 Updated copyright and version for SMV Beta */ +/* 10/28/05 EJV 18 Update ver to 5.0250 for MMS-LITE-SECURE rel.*/ +/* 09/09/05 JRB 17 Update ver to 5.02 & Copyright info. */ +/* BUILD_NUM is OBSOLETE. */ +/* 04/28/05 PLM 16 Update ver to 5.01 Build 1 */ +/* 07/21/04 DWL 15 Update to 5.0052 */ +/* 02/20/04 ASK 14 Chg ver to 5.0051 for USPS release */ +/* 01/26/04 DWL 13 Update copyright date to 2004. */ +/* 09/10/03 EJV 12 Chg ver to 5.0050 (Security ready MMS-LITE) */ +/* 04/29/03 DWL 11 Updated build number */ +/* 04/08/03 DWL 10 Updated copyright/version/build number */ +/* 12/20/02 DWL 09 Updated version/build number */ +/* 03/22/02 DWL 08 Updated build number */ +/* 03/12/02 DWL 07 Updated version */ +/* 02/25/02 MDE 06 Removed mmsl_max_msg_size */ +/* 10/09/01 JRB 05 Add MMSLITE_* product identification defines.*/ +/* 02/20/98 MDE 04 Fixed __cplusplus problem */ +/* 11/05/97 MDE 03 Changed mmsl_msg_start to ST_UCHAR * */ +/* 08/24/97 MDE 02 Added 'mmsl_max_msg_size', 'ml_init_buffers' */ +/* 11/10/93 DGE 01 Initial MMSEASE-LITE Release. */ +/************************************************************************/ + +#ifndef LMMSDEFS_INCLUDED +#define LMMSDEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/* Defines for Product Identification. */ +/* Write these parameters on screen and in log file at startup. */ +/* Use MMSLITE_NAME & MMSLITE_VERSION in MMS Identify response. */ +/************************************************************************/ +#define MMSLITE_COPYRIGHT "Copyright (c) 1986-2008 SISCO, Inc. All Rights Reserved." +#define MMSLITE_NAME "MMS-LITE-80X-001" +#define MMSLITE_VERSION "5.1005" +#define MMSLITE_BUILD_NUM 0 /* OBSOLETE: for backward compatibility only*/ + +/************************************************************************/ +/************************************************************************/ +/* MMSEASE-LITE specific Global Variables */ +/************************************************************************/ +#define MMS_PCI 0x0001 + +extern ST_INT mmsl_enc_buf_size; +extern ST_UCHAR *mmsl_enc_buf; +extern ST_INT mmsl_dec_info_size; + +extern ST_INT16 mmsl_version; +extern ST_UINT32 mmsl_invoke_id; + +extern ST_UCHAR *mmsl_msg_start; +extern ST_INT mmsl_msg_len; + + +/************************************************************************/ +/* This function initializes the encode/decode buffers and the decode */ +/* object limitations, and is normally generated using the 'mbufcalc' */ +/* utility program. */ + +ST_VOID ml_init_buffers (ST_VOID); + + +#ifdef __cplusplus +} +#endif + +#endif /* MMSLDEFS_INCLUDED */ diff --git a/include/inc/mmslog.h b/include/inc/mmslog.h new file mode 100644 index 0000000..cfa0e38 --- /dev/null +++ b/include/inc/mmslog.h @@ -0,0 +1,735 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2007, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmslog.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains MMS-EASE logging macros used */ +/* internally by MMS-EASE for SLOGGING */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/05/07 EJV 07 Removed obsolete LLC30_LLP code. */ +/* 11/01/04 JRB 06 Use new "Base" macros SLOG_*, SLOGC_*, SLOGH.*/ +/* Change MLOG_ALWAYS* like SLOGALWAYS*. */ +/* 03/13/02 JRB 05 MLOG_PAUSE* macros do nothing. */ +/* 10/05/01 EJV 04 Corrected comment. */ +/* 03/15/01 JRB 03 Added USER log macros. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 10/08/98 MDE 01 Migrated to updated SLOG interface */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMSLOG_INCLUDED +#define MMSLOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +extern SD_CONST ST_CHAR *SD_CONST _mms_log_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_enc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_acse_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_ique_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_rque_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_ind_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_conf_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_vm_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_nerr_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_pdu_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_config_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_always_logstr; + +extern SD_CONST ST_CHAR *SD_CONST _user_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _user_client_logstr; +extern SD_CONST ST_CHAR *SD_CONST _user_server_logstr; + +/*********************** PAUSE Macros ***********************************/ +#define MLOG_PAUSEDEC(msg) +#define MLOG_PAUSEENC(msg) +#define MLOG_PAUSEIQUE(msg) +#define MLOG_PAUSERQUE(msg) +#define MLOG_PAUSEPDU(msg) + +/*********************** DECODE Macros **********************************/ +#define MLOG_DEC0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a) +#define MLOG_DEC1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b) +#define MLOG_DEC2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b,c) +#define MLOG_DEC3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b,c,d) +#define MLOG_DEC4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b,c,d,e) +#define MLOG_DEC5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b,c,d,e,f) +#define MLOG_DEC6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b,c,d,e,f,g) +#define MLOG_DEC7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b,c,d,e,f,g,h) +#define MLOG_DEC8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CDEC0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_DEC,a) +#define MLOG_CDEC1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_DEC,a,b) +#define MLOG_CDEC2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_DEC,a,b,c) +#define MLOG_CDEC3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_DEC,a,b,c,d) +#define MLOG_CDEC4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_DEC,a,b,c,d,e) +#define MLOG_CDEC5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_DEC,a,b,c,d,e,f) +#define MLOG_CDEC6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_DEC,a,b,c,d,e,f,g) +#define MLOG_CDEC7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_DEC,a,b,c,d,e,f,g,h) +#define MLOG_CDEC8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_DEC,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_DECH(a,b) \ + +/*********************** ENCODE Macros **********************************/ +#define MLOG_ENC0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a) +#define MLOG_ENC1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b) +#define MLOG_ENC2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b,c) +#define MLOG_ENC3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b,c,d) +#define MLOG_ENC4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b,c,d,e) +#define MLOG_ENC5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b,c,d,e,f) +#define MLOG_ENC6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b,c,d,e,f,g) +#define MLOG_ENC7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b,c,d,e,f,g,h) +#define MLOG_ENC8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CENC0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_ENC,a) +#define MLOG_CENC1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_ENC,a,b) +#define MLOG_CENC2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_ENC,a,b,c) +#define MLOG_CENC3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_ENC,a,b,c,d) +#define MLOG_CENC4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_ENC,a,b,c,d,e) +#define MLOG_CENC5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_ENC,a,b,c,d,e,f) +#define MLOG_CENC6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_ENC,a,b,c,d,e,f,g) +#define MLOG_CENC7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_ENC,a,b,c,d,e,f,g,h) +#define MLOG_CENC8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_ENC,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_ENCH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_ENC,a,b) + +/*********************** ACSE Macros ***********************************/ +#define MLOG_ACSE0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a) +#define MLOG_ACSE1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b) +#define MLOG_ACSE2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b,c) +#define MLOG_ACSE3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b,c,d) +#define MLOG_ACSE4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b,c,d,e) +#define MLOG_ACSE5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b,c,d,e,f) +#define MLOG_ACSE6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b,c,d,e,f,g) +#define MLOG_ACSE7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b,c,d,e,f,g,h) +#define MLOG_ACSE8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CACSE0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_ACSE,a) +#define MLOG_CACSE1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_ACSE,a,b) +#define MLOG_CACSE2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_ACSE,a,b,c) +#define MLOG_CACSE3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_ACSE,a,b,c,d) +#define MLOG_CACSE4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_ACSE,a,b,c,d,e) +#define MLOG_CACSE5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_ACSE,a,b,c,d,e,f) +#define MLOG_CACSE6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_ACSE,a,b,c,d,e,f,g) +#define MLOG_CACSE7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_ACSE,a,b,c,d,e,f,g,h) +#define MLOG_CACSE8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_ACSE,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_ACSEH(a,b) \ + +/*********************** IQUE Macros **************************************/ +#define MLOG_IQUE0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a) +#define MLOG_IQUE1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b) +#define MLOG_IQUE2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b,c) +#define MLOG_IQUE3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b,c,d) +#define MLOG_IQUE4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b,c,d,e) +#define MLOG_IQUE5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b,c,d,e,f) +#define MLOG_IQUE6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b,c,d,e,f,g) +#define MLOG_IQUE7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b,c,d,e,f,g,h) +#define MLOG_IQUE8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CIQUE0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_IQUE,a) +#define MLOG_CIQUE1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_IQUE,a,b) +#define MLOG_CIQUE2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_IQUE,a,b,c) +#define MLOG_CIQUE3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_IQUE,a,b,c,d) +#define MLOG_CIQUE4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_IQUE,a,b,c,d,e) +#define MLOG_CIQUE5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_IQUE,a,b,c,d,e,f) +#define MLOG_CIQUE6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_IQUE,a,b,c,d,e,f,g) +#define MLOG_CIQUE7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_IQUE,a,b,c,d,e,f,g,h) +#define MLOG_CIQUE8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_IQUE,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_IQUEH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_IQUE,a,b) + +/*********************** RQUE Macros **************************************/ +#define MLOG_RQUE0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a) +#define MLOG_RQUE1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b) +#define MLOG_RQUE2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b,c) +#define MLOG_RQUE3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b,c,d) +#define MLOG_RQUE4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b,c,d,e) +#define MLOG_RQUE5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b,c,d,e,f) +#define MLOG_RQUE6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b,c,d,e,f,g) +#define MLOG_RQUE7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b,c,d,e,f,g,h) +#define MLOG_RQUE8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CRQUE0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_RQUE,a) +#define MLOG_CRQUE1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_RQUE,a,b) +#define MLOG_CRQUE2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_RQUE,a,b,c) +#define MLOG_CRQUE3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_RQUE,a,b,c,d) +#define MLOG_CRQUE4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_RQUE,a,b,c,d,e) +#define MLOG_CRQUE5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_RQUE,a,b,c,d,e,f) +#define MLOG_CRQUE6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_RQUE,a,b,c,d,e,f,g) +#define MLOG_CRQUE7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_RQUE,a,b,c,d,e,f,g,h) +#define MLOG_CRQUE8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_RQUE,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_RQUEH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_RQUE,a,b) + +/*********************** REQ Macros **************************************/ +#define MLOG_REQ0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a) +#define MLOG_REQ1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b) +#define MLOG_REQ2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b,c) +#define MLOG_REQ3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b,c,d) +#define MLOG_REQ4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b,c,d,e) +#define MLOG_REQ5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b,c,d,e,f) +#define MLOG_REQ6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b,c,d,e,f,g) +#define MLOG_REQ7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b,c,d,e,f,g,h) +#define MLOG_REQ8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b,c,d,e,f,g,h,i) + +/* DEBUG: Add Continuation log macros? */ + +/* Hex log macro */ +#define MLOG_REQH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_REQ,a,b) + +/*********************** IND Macros **************************************/ +#define MLOG_IND0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a) +#define MLOG_IND1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b) +#define MLOG_IND2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b,c) +#define MLOG_IND3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b,c,d) +#define MLOG_IND4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b,c,d,e) +#define MLOG_IND5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b,c,d,e,f) +#define MLOG_IND6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b,c,d,e,f,g) +#define MLOG_IND7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b,c,d,e,f,g,h) +#define MLOG_IND8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b,c,d,e,f,g,h,i) + +/* DEBUG: Add Continuation log macros? */ + +/* Hex log macro */ +#define MLOG_INDH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_IND,a,b) + +/*********************** RESP Macros **************************************/ +#define MLOG_RESP0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a) +#define MLOG_RESP1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b) +#define MLOG_RESP2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b,c) +#define MLOG_RESP3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b,c,d) +#define MLOG_RESP4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b,c,d,e) +#define MLOG_RESP5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b,c,d,e,f) +#define MLOG_RESP6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b,c,d,e,f,g) +#define MLOG_RESP7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b,c,d,e,f,g,h) +#define MLOG_RESP8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b,c,d,e,f,g,h,i) + +/* DEBUG: Add Continuation log macros? */ + +/* Hex log macro */ +#define MLOG_RESPH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_RESP,a,b) + +/*********************** CONF Macros **************************************/ +#define MLOG_CONF0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a) +#define MLOG_CONF1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b) +#define MLOG_CONF2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b,c) +#define MLOG_CONF3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b,c,d) +#define MLOG_CONF4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b,c,d,e) +#define MLOG_CONF5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b,c,d,e,f) +#define MLOG_CONF6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b,c,d,e,f,g) +#define MLOG_CONF7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b,c,d,e,f,g,h) +#define MLOG_CONF8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b,c,d,e,f,g,h,i) + + +/* DEBUG: Add Continuation log macros? */ + +/* Hex log macro */ +#define MLOG_CONFH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_CONF,a,b) + +/*********************** VM Macros **************************************/ +#define MLOG_VM0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a) +#define MLOG_VM1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b) +#define MLOG_VM2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b,c) +#define MLOG_VM3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b,c,d) +#define MLOG_VM4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b,c,d,e) +#define MLOG_VM5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b,c,d,e,f) +#define MLOG_VM6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b,c,d,e,f,g) +#define MLOG_VM7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b,c,d,e,f,g,h) +#define MLOG_VM8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b,c,d,e,f,g,h,i) + +/* DEBUG: Add Continuation log macros? */ + +/* Hex log macro */ +#define MLOG_VMH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_VM,a,b) + +/*********************** ERR Macros **************************************/ +#define MLOG_ERR0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a) +#define MLOG_ERR1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b) +#define MLOG_ERR2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b,c) +#define MLOG_ERR3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b,c,d) +#define MLOG_ERR4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b,c,d,e) +#define MLOG_ERR5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b,c,d,e,f) +#define MLOG_ERR6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b,c,d,e,f,g) +#define MLOG_ERR7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b,c,d,e,f,g,h) +#define MLOG_ERR8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CERR0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_ERR,a) +#define MLOG_CERR1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_ERR,a,b) +#define MLOG_CERR2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_ERR,a,b,c) +#define MLOG_CERR3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_ERR,a,b,c,d) +#define MLOG_CERR4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_ERR,a,b,c,d,e) +#define MLOG_CERR5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_ERR,a,b,c,d,e,f) +#define MLOG_CERR6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_ERR,a,b,c,d,e,f,g) +#define MLOG_CERR7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_ERR,a,b,c,d,e,f,g,h) +#define MLOG_CERR8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_ERR,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_ERRH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_ERR,a,b) + +/*********************** NERR Macros *************************************/ +#define MLOG_NERR0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a) +#define MLOG_NERR1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b) +#define MLOG_NERR2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b,c) +#define MLOG_NERR3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b,c,d) +#define MLOG_NERR4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b,c,d,e) +#define MLOG_NERR5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b,c,d,e,f) +#define MLOG_NERR6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b,c,d,e,f,g) +#define MLOG_NERR7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b,c,d,e,f,g,h) +#define MLOG_NERR8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CNERR0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_NERR,a) +#define MLOG_CNERR1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_NERR,a,b) +#define MLOG_CNERR2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_NERR,a,b,c) +#define MLOG_CNERR3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_NERR,a,b,c,d) +#define MLOG_CNERR4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_NERR,a,b,c,d,e) +#define MLOG_CNERR5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_NERR,a,b,c,d,e,f) +#define MLOG_CNERR6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_NERR,a,b,c,d,e,f,g) +#define MLOG_CNERR7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_NERR,a,b,c,d,e,f,g,h) +#define MLOG_CNERR8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_NERR,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_NERRH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_NERR,a,b) + +/*********************** PDU Macros **************************************/ +#define MLOG_PDU0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a) +#define MLOG_PDU1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b) +#define MLOG_PDU2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b,c) +#define MLOG_PDU3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b,c,d) +#define MLOG_PDU4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b,c,d,e) +#define MLOG_PDU5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b,c,d,e,f) +#define MLOG_PDU6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b,c,d,e,f,g) +#define MLOG_PDU7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b,c,d,e,f,g,h) +#define MLOG_PDU8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CPDU0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_PDU,a) +#define MLOG_CPDU1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_PDU,a,b) +#define MLOG_CPDU2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_PDU,a,b,c) +#define MLOG_CPDU3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_PDU,a,b,c,d) +#define MLOG_CPDU4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_PDU,a,b,c,d,e) +#define MLOG_CPDU5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_PDU,a,b,c,d,e,f) +#define MLOG_CPDU6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_PDU,a,b,c,d,e,f,g) +#define MLOG_CPDU7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_PDU,a,b,c,d,e,f,g,h) +#define MLOG_CPDU8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_PDU,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_PDUH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_PDU,a,b) + + +/*********************** ALWAYS Macros *********************************/ +/* DEBUG: these are same as "SLOGALWAYS*" except header txt */ +/* "mms_log_always_logstr". If text is not important, just remap */ +/* "MLOG_ALWAYS*" like this (#define MLOG_ALWAYS0 SLOGALWAYS0). */ +#if defined(DEBUG_SISCO) +#define MLOG_ALWAYS0(a) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a) +#define MLOG_ALWAYS1(a,b) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b) +#define MLOG_ALWAYS2(a,b,c) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b,c) +#define MLOG_ALWAYS3(a,b,c,d) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b,c,d) +#define MLOG_ALWAYS4(a,b,c,d,e) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b,c,d,e) +#define MLOG_ALWAYS5(a,b,c,d,e,f) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b,c,d,e,f) +#define MLOG_ALWAYS6(a,b,c,d,e,f,g) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b,c,d,e,f,g) +#define MLOG_ALWAYS7(a,b,c,d,e,f,g,h) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b,c,d,e,f,g,h) +#define MLOG_ALWAYS8(a,b,c,d,e,f,g,h,i) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i) +#else /* !DEBUG_SISCO */ +#define MLOG_ALWAYS0(a) +#define MLOG_ALWAYS1(a,b) +#define MLOG_ALWAYS2(a,b,c) +#define MLOG_ALWAYS3(a,b,c,d) +#define MLOG_ALWAYS4(a,b,c,d,e) +#define MLOG_ALWAYS5(a,b,c,d,e,f) +#define MLOG_ALWAYS6(a,b,c,d,e,f,g) +#define MLOG_ALWAYS7(a,b,c,d,e,f,g,h) +#define MLOG_ALWAYS8(a,b,c,d,e,f,g,h,i) +#endif /* !DEBUG_SISCO */ + +/* Continuation & Hex macros are exactly the same as "SLOG*" macros, so just remap to them.*/ +#define MLOG_CALWAYS0 SLOGCALWAYS0 +#define MLOG_CALWAYS1 SLOGCALWAYS1 +#define MLOG_CALWAYS2 SLOGCALWAYS2 +#define MLOG_CALWAYS3 SLOGCALWAYS3 +#define MLOG_CALWAYS4 SLOGCALWAYS4 +#define MLOG_CALWAYS5 SLOGCALWAYS5 +#define MLOG_CALWAYS6 SLOGCALWAYS6 +#define MLOG_CALWAYS7 SLOGCALWAYS7 +#define MLOG_CALWAYS8 SLOGCALWAYS8 + +#define MLOG_ALWAYSH SLOGALWAYSH + + +/*********************** USER ERR Macros********************************/ +#define USER_LOG_ERR0(a) \ + SLOG_0 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a) +#define USER_LOG_ERR1(a,b) \ + SLOG_1 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b) +#define USER_LOG_ERR2(a,b,c) \ + SLOG_2 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b,c) +#define USER_LOG_ERR3(a,b,c,d) \ + SLOG_3 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b,c,d) +#define USER_LOG_ERR4(a,b,c,d,e) \ + SLOG_4 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b,c,d,e) +#define USER_LOG_ERR5(a,b,c,d,e,f) \ + SLOG_5 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b,c,d,e,f) +#define USER_LOG_ERR6(a,b,c,d,e,f,g) \ + SLOG_6 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b,c,d,e,f,g) +#define USER_LOG_ERR7(a,b,c,d,e,f,g,h) \ + SLOG_7 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b,c,d,e,f,g,h) +#define USER_LOG_ERR8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define USER_LOG_ERRC0(a) \ + SLOGC_0 (user_debug_sel & USER_LOG_ERR,a) +#define USER_LOG_ERRC1(a,b) \ + SLOGC_1 (user_debug_sel & USER_LOG_ERR,a,b) +#define USER_LOG_ERRC2(a,b,c) \ + SLOGC_2 (user_debug_sel & USER_LOG_ERR,a,b,c) +#define USER_LOG_ERRC3(a,b,c,d) \ + SLOGC_3 (user_debug_sel & USER_LOG_ERR,a,b,c,d) +#define USER_LOG_ERRC4(a,b,c,d,e) \ + SLOGC_4 (user_debug_sel & USER_LOG_ERR,a,b,c,d,e) +#define USER_LOG_ERRC5(a,b,c,d,e,f) \ + SLOGC_5 (user_debug_sel & USER_LOG_ERR,a,b,c,d,e,f) +#define USER_LOG_ERRC6(a,b,c,d,e,f,g) \ + SLOGC_6 (user_debug_sel & USER_LOG_ERR,a,b,c,d,e,f,g) +#define USER_LOG_ERRC7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (user_debug_sel & USER_LOG_ERR,a,b,c,d,e,f,g,h) +#define USER_LOG_ERRC8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (user_debug_sel & USER_LOG_ERR,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define USER_LOG_ERRH(a,b) \ + SLOGH (user_debug_sel & USER_LOG_ERR,a,b) + +/*********************** USER Client Macros ****************************/ +#define USER_LOG_CLIENT0(a) \ + SLOG_0 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a) +#define USER_LOG_CLIENT1(a,b) \ + SLOG_1 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b) +#define USER_LOG_CLIENT2(a,b,c) \ + SLOG_2 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b,c) +#define USER_LOG_CLIENT3(a,b,c,d) \ + SLOG_3 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b,c,d) +#define USER_LOG_CLIENT4(a,b,c,d,e) \ + SLOG_4 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b,c,d,e) +#define USER_LOG_CLIENT5(a,b,c,d,e,f) \ + SLOG_5 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b,c,d,e,f) +#define USER_LOG_CLIENT6(a,b,c,d,e,f,g) \ + SLOG_6 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b,c,d,e,f,g) +#define USER_LOG_CLIENT7(a,b,c,d,e,f,g,h) \ + SLOG_7 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b,c,d,e,f,g,h) +#define USER_LOG_CLIENT8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define USER_LOG_CLIENTC0(a) \ + SLOGC_0 (user_debug_sel & USER_LOG_CLIENT,a) +#define USER_LOG_CLIENTC1(a,b) \ + SLOGC_1 (user_debug_sel & USER_LOG_CLIENT,a,b) +#define USER_LOG_CLIENTC2(a,b,c) \ + SLOGC_2 (user_debug_sel & USER_LOG_CLIENT,a,b,c) +#define USER_LOG_CLIENTC3(a,b,c,d) \ + SLOGC_3 (user_debug_sel & USER_LOG_CLIENT,a,b,c,d) +#define USER_LOG_CLIENTC4(a,b,c,d,e) \ + SLOGC_4 (user_debug_sel & USER_LOG_CLIENT,a,b,c,d,e) +#define USER_LOG_CLIENTC5(a,b,c,d,e,f) \ + SLOGC_5 (user_debug_sel & USER_LOG_CLIENT,a,b,c,d,e,f) +#define USER_LOG_CLIENTC6(a,b,c,d,e,f,g) \ + SLOGC_6 (user_debug_sel & USER_LOG_CLIENT,a,b,c,d,e,f,g) +#define USER_LOG_CLIENTC7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (user_debug_sel & USER_LOG_CLIENT,a,b,c,d,e,f,g,h) +#define USER_LOG_CLIENTC8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (user_debug_sel & USER_LOG_CLIENT,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define USER_LOG_CLIENTH(a,b) \ + SLOGH (user_debug_sel & USER_LOG_CLIENT,a,b) + +/*********************** USER Server Macros ****************************/ +#define USER_LOG_SERVER0(a) \ + SLOG_0 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a) +#define USER_LOG_SERVER1(a,b) \ + SLOG_1 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b) +#define USER_LOG_SERVER2(a,b,c) \ + SLOG_2 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b,c) +#define USER_LOG_SERVER3(a,b,c,d) \ + SLOG_3 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b,c,d) +#define USER_LOG_SERVER4(a,b,c,d,e) \ + SLOG_4 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b,c,d,e) +#define USER_LOG_SERVER5(a,b,c,d,e,f) \ + SLOG_5 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b,c,d,e,f) +#define USER_LOG_SERVER6(a,b,c,d,e,f,g) \ + SLOG_6 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b,c,d,e,f,g) +#define USER_LOG_SERVER7(a,b,c,d,e,f,g,h) \ + SLOG_7 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b,c,d,e,f,g,h) +#define USER_LOG_SERVER8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define USER_LOG_SERVERC0(a) \ + SLOGC_0 (user_debug_sel & USER_LOG_SERVER,a) +#define USER_LOG_SERVERC1(a,b) \ + SLOGC_1 (user_debug_sel & USER_LOG_SERVER,a,b) +#define USER_LOG_SERVERC2(a,b,c) \ + SLOGC_2 (user_debug_sel & USER_LOG_SERVER,a,b,c) +#define USER_LOG_SERVERC3(a,b,c,d) \ + SLOGC_3 (user_debug_sel & USER_LOG_SERVER,a,b,c,d) +#define USER_LOG_SERVERC4(a,b,c,d,e) \ + SLOGC_4 (user_debug_sel & USER_LOG_SERVER,a,b,c,d,e) +#define USER_LOG_SERVERC5(a,b,c,d,e,f) \ + SLOGC_5 (user_debug_sel & USER_LOG_SERVER,a,b,c,d,e,f) +#define USER_LOG_SERVERC6(a,b,c,d,e,f,g) \ + SLOGC_6 (user_debug_sel & USER_LOG_SERVER,a,b,c,d,e,f,g) +#define USER_LOG_SERVERC7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (user_debug_sel & USER_LOG_SERVER,a,b,c,d,e,f,g,h) +#define USER_LOG_SERVERC8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (user_debug_sel & USER_LOG_SERVER,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define USER_LOG_SERVERH(a,b) \ + SLOGH (user_debug_sel & USER_LOG_SERVER,a,b) + +#define USER_LOG_SERVER_HEX USER_LOG_SERVERH /* for backward compatibility*/ + +#ifdef __cplusplus +} +#endif + +/************************************************************************/ +#endif /* End of MMS_LOG_INCLUDED */ +/************************************************************************/ + diff --git a/include/inc/mmslusec.h b/include/inc/mmslusec.h new file mode 100644 index 0000000..f0f4b4f --- /dev/null +++ b/include/inc/mmslusec.h @@ -0,0 +1,58 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003 - 2004, All Rights Reserved. */ +/* */ +/* MODULE NAME : mmslusec.h */ +/* PRODUCT(S) : MMS-EASE Lite with LITESECURE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Prototypes for Security related user functions. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/20/04 EJV 03 ulFreeAssocSecurity: del cc param. */ +/* 01/06/04 EJV 02 Merged with MMS-EASE mms_usec.h. */ +/* 07/08/03 EJV 01 Adopted from MMS-EASE mms_usec.h. */ +/************************************************************************/ +#ifndef MMS_USEC_H +#define MMS_USEC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------------------*/ +/* NOTE: The MMS-EASE Lite Secured applications (Client, Server) */ +/* are designed to work with Security Toolkit for MMS-EASE Lite */ +/* (LITESECURE-000-001). */ +/*----------------------------------------------------------------------*/ + +#if defined(S_SEC_ENABLED) + +#include "acseauth.h" +#include "ssec.h" + + +ST_RET ulSetSecurityCalling (ST_CHAR *locArName, + ST_CHAR *remArName, + S_SEC_LOC_AR **locArSecOut, + S_SEC_REM_AR **remArSecOut, + ACSE_AUTH_INFO *locAuthInfo, + S_SEC_ENCRYPT_CTRL *encryptCtrl); +ST_RET ulCheckSecureAssocConf (MVL_NET_INFO *cc); +ST_RET ulCheckSecureAssocInd (MVL_NET_INFO *cc, ACSE_AUTH_INFO *rspAuthInfo); +ST_RET ulFreeAssocSecurity (ACSE_AUTH_INFO *authInfo); +ST_RET ulCheckSecurityConfiguration (ST_VOID); + +#endif /* defined(S_SEC_ENABLED) */ + +#ifdef __cplusplus +} +#endif + +#endif /* MMS_USEC_H */ diff --git a/include/inc/mmsop_en/mmsop_en.h b/include/inc/mmsop_en/mmsop_en.h new file mode 100644 index 0000000..8a9038a --- /dev/null +++ b/include/inc/mmsop_en/mmsop_en.h @@ -0,0 +1,185 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mmsop_en.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the operation enable switches used to */ +/* configure the decode system, the user service system, & the */ +/* supported services bit strings. */ +/* */ +/* Note that by enabling (or disabling) only the desired MMS */ +/* operations, a limited subset may be created (the subset */ +/* creation module is mmsop_en.c), thus allowing the creation of */ +/* a smaller executable because: */ +/* 1) references to the various MMS-EASE functions are removed */ +/* and therefore are not included from the library, and */ +/* 2) operation specific user application code is eliminated. */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/14/98 JRB 04 Put "MPARAM*" defines back. */ +/* Only user code needs them. */ +/* 03/20/98 JRB 03 Move defines used by libraries to mms_def2.h */ +/* Only user code needs this file now. */ +/* 09/16/97 DSF 02 Fixed comments */ +/* 08/18/97 MDE 01 Added parameter support defines */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMSOP_EN_INCLUDED +#define MMSOP_EN_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_def2.h" /* for REQ_RESP_EN, etc. */ + +/************************************************************************/ +/* define the opcode enable switches */ +/************************************************************************/ +#define MMS_INIT_EN REQ_RESP_EN +#define MMS_CONCLUDE_EN REQ_RESP_EN +#define MMS_CANCEL_EN REQ_RESP_EN + +#define MMS_STATUS_EN REQ_RESP_EN +#define MMS_USTATUS_EN REQ_RESP_EN +#define MMS_GETNAMES_EN REQ_RESP_EN +#define MMS_IDENT_EN REQ_RESP_EN +#define MMS_RENAME_EN REQ_RESP_EN +#define MMS_GETCL_EN REQ_RESP_EN +#define MMS_VMD_EN 0 + +#define MMS_NAMED_DOM_EN 0 +#define MMS_MV_DWN_EN REQ_RESP_EN /* VM download */ +#define MMS_INIT_DWN_EN REQ_RESP_EN +#define MMS_DWN_LOAD_EN REQ_RESP_EN +#define MMS_TERM_DWN_EN REQ_RESP_EN +#define MMS_MV_UPL_EN REQ_RESP_EN /* VM upload */ +#define MMS_INIT_UPL_EN REQ_RESP_EN +#define MMS_UP_LOAD_EN REQ_RESP_EN +#define MMS_TERM_UPL_EN REQ_RESP_EN +#define MMS_RDDWN_EN REQ_RESP_EN +#define MMS_RDUPL_EN REQ_RESP_EN +#define MMS_LOAD_DOM_EN REQ_RESP_EN +#define MMS_STR_DOM_EN REQ_RESP_EN +#define MMS_DEL_DOM_EN REQ_RESP_EN +#define MMS_GET_DOM_EN REQ_RESP_EN + +#define MMS_CRE_PI_EN REQ_RESP_EN +#define MMS_DEL_PI_EN REQ_RESP_EN +#define MMS_START_EN REQ_RESP_EN +#define MMS_STOP_EN REQ_RESP_EN +#define MMS_RESUME_EN REQ_RESP_EN +#define MMS_RESET_EN REQ_RESP_EN +#define MMS_KILL_EN REQ_RESP_EN +#define MMS_GET_PI_EN REQ_RESP_EN + +#define MMS_VA_EN 1 +#define MMS_MV_READ_EN REQ_RESP_EN /* VM Read variable(s) */ +#define MMS_MV_RDVARS_EN REQ_RESP_EN /* General VM Rd var's */ +#define MMS_READ_EN REQ_RESP_EN +#define MMS_MV_WRITE_EN REQ_RESP_EN /* VM Write variable(s) */ +#define MMS_MV_WRVARS_EN REQ_RESP_EN /* General VM WR var's */ +#define MMS_WRITE_EN REQ_RESP_EN +#define MMS_INFO_EN REQ_RESP_EN +#define MMS_GETVAR_EN REQ_RESP_EN +#define MMS_DEFVAR_EN REQ_RESP_EN +#define MMS_DEFSCAT_EN REQ_RESP_EN +#define MMS_GETSCAT_EN REQ_RESP_EN +#define MMS_DELVAR_EN REQ_RESP_EN +#define MMS_DEFVLIST_EN REQ_RESP_EN +#define MMS_GETVLIST_EN REQ_RESP_EN +#define MMS_DELVLIST_EN REQ_RESP_EN +#define MMS_MV_DEFTYPE_EN REQ_RESP_EN /* VM DefineType */ +#define MMS_DEFTYPE_EN REQ_RESP_EN +#define MMS_GETTYPE_EN REQ_RESP_EN +#define MMS_DELTYPE_EN REQ_RESP_EN + +#define MMS_TAKECTRL_EN REQ_RESP_EN +#define MMS_RELCTRL_EN REQ_RESP_EN +#define MMS_DEFINE_SEM_EN REQ_RESP_EN +#define MMS_DELETE_SEM_EN REQ_RESP_EN +#define MMS_REP_SEMSTAT_EN REQ_RESP_EN +#define MMS_REP_SEMPOOL_EN REQ_RESP_EN +#define MMS_REP_SEMENTRY_EN REQ_RESP_EN + +#define MMS_JREAD_EN REQ_RESP_EN +#define MMS_JWRITE_EN REQ_RESP_EN +#define MMS_JINIT_EN REQ_RESP_EN +#define MMS_JSTAT_EN REQ_RESP_EN +#define MMS_JCREATE_EN REQ_RESP_EN +#define MMS_JDELETE_EN REQ_RESP_EN + +#define MMS_DEFEC_EN REQ_RESP_EN +#define MMS_DELEC_EN REQ_RESP_EN +#define MMS_GETECA_EN REQ_RESP_EN +#define MMS_REPECS_EN REQ_RESP_EN +#define MMS_ALTECM_EN REQ_RESP_EN +#define MMS_TRIGE_EN REQ_RESP_EN +#define MMS_DEFEA_EN REQ_RESP_EN +#define MMS_DELEA_EN REQ_RESP_EN +#define MMS_GETEAA_EN REQ_RESP_EN +#define MMS_REPEAS_EN REQ_RESP_EN +#define MMS_DEFEE_EN REQ_RESP_EN +#define MMS_DELEE_EN REQ_RESP_EN +#define MMS_GETEEA_EN REQ_RESP_EN +#define MMS_REPEES_EN REQ_RESP_EN +#define MMS_ALTEE_EN REQ_RESP_EN +#define MMS_EVNOT_EN REQ_RESP_EN +#define MMS_ACKEVNOT_EN REQ_RESP_EN +#define MMS_GETAS_EN REQ_RESP_EN +#define MMS_GETAES_EN REQ_RESP_EN + +#define MMS_INPUT_EN REQ_RESP_EN +#define MMS_OUTPUT_EN REQ_RESP_EN + +#define MMS_MV_FOPEN_EN REQ_RESP_EN /* VM FileOpen */ +#define MMS_MV_FREAD_EN REQ_RESP_EN /* VM FileRead */ +#define MMS_MV_FCLOSE_EN REQ_RESP_EN /* VM FileClose */ +#define MMS_MV_FCOPY_EN REQ_RESP_EN /* VM FileCopy */ +#define MMS_OBTAINFILE_EN REQ_RESP_EN +#define MMS_FOPEN_EN REQ_RESP_EN +#define MMS_FREAD_EN REQ_RESP_EN +#define MMS_FCLOSE_EN REQ_RESP_EN +#define MMS_FRENAME_EN REQ_RESP_EN +#define MMS_FDELETE_EN REQ_RESP_EN +#define MMS_FDIR_EN REQ_RESP_EN + + +/************************************************************************/ +/************************************************************************/ +/* PARAMETER SUPPORTED BITSTRING VALUES */ +/************************************************************************/ + +#define MPARAM_STR1 0x80 /* 0x80 arrays */ +#define MPARAM_STR2 0x40 /* 0x40 structures */ +#define MPARAM_VNAM 0x20 /* 0x20 named variables */ +#define MPARAM_VALT 0x10 /* 0x10 alternate access */ +#define MPARAM_VADR 0x08 /* 0x08 address formed variables */ +#define MPARAM_VSCA 0x00 /* 0x04 scattered access */ +#define MPARAM_TPY 0x02 /* 0x02 third party */ +#define MPARAM_VLIS 0x01 /* 0x01 variable list */ +#define MPARAM_REAL 0x00 /* 0x80 real data type */ +#define MPARAM_AKEC 0x00 /* 0x40 ack event cond. */ +#define MPARAM_CEI 0x00 /* 0x20 cond. eval. interval */ + +#define MPARAM0 MPARAM_STR1 | MPARAM_STR2 | MPARAM_VNAM | MPARAM_VALT |\ + MPARAM_VADR | MPARAM_VSCA | MPARAM_TPY | MPARAM_VLIS +#define MPARAM1 MPARAM_REAL | MPARAM_AKEC | MPARAM_CEI + + +#ifdef __cplusplus +} +#endif + +#endif /* MMSOP_EN_INCLUDED */ + diff --git a/include/inc/mvl_acse.h b/include/inc/mvl_acse.h new file mode 100644 index 0000000..0a79fbb --- /dev/null +++ b/include/inc/mvl_acse.h @@ -0,0 +1,234 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2005, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_acse.h */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/10/05 EJV 26 Moved up osicfgx proto. */ +/* 04/06/05 EJV 25 Added MMSEASE_MOSI. */ +/* 03/28/05 JRB 24 Del suicacse header. */ +/* 08/11/04 JRB 23 Del global funct ptr u_mvl_connect_ind_fun. */ +/* Fix mvl_abort_req_ex return (ST_RET). */ +/* 07/08/04 JRB 22 Del unused global var mvl_local_cl_ar_name. */ +/* 07/23/03 MDE 21 Removed ACSE_AUTH_ENABLED */ +/* 06/16/03 EJV 20 Removed m_match.h, s_match.h includes */ +/* Chg M_MATCH_CTRL to DIB_MATCH_CTRL. */ +/* 06/10/03 MDE 19 Added address matching */ +/* 10/11/02 ASK 18 Added mvla_initiate_req_ex and */ +/* u_mvl_connect_*_ex */ +/* 05/13/02 MDE 17 Added structure element comments */ +/* 05/03/02 MDE 16 Added mvl_add_bind_ctrl, associated changes */ +/* 02/25/02 MDE 15 More changes to MVL_CFG_INFO */ +/* 02/20/02 MDE 14 Changes to new MVL_CFG_INFO, for mult. bind */ +/* 02/07/02 JRB 13 Define MVL_CFG_INFO & pass to mvl_start_acse.*/ +/* Move osicfgx proto here, add MVL_CFG_INFO arg*/ +/* Del global var mvl_local_ar_name. */ +/* 01/29/02 JRB 12 Replace mvl_init_cl_netinfo funct with */ +/* mvl_init_audt_addr. */ +/* 11/28/01 MDE 11 mvl_set_num_connections,mvl_set_max_msg_size */ +/* 01/05/01 MDE 10 Changes for use over Marben */ +/* 06/26/00 JRB 09 Del "#define MVL_ACSE". Not used. */ +/* Move "#define COACSE" to mvl_defs.h (avoids */ +/* mvl_defs.h dependence on mvl_acse.h). */ +/* 03/09/00 MDE 08 Added _mvl_init_conn_ctrl */ +/* 07/30/99 JRB 07 Chg ma_clbind_ctrl from static to global. */ +/* 04/13/99 MDE 06 Added '_mvla_initiate_locDe' */ +/* 03/18/99 MDE 05 Made connection limits runtime settable */ +/* 11/16/98 MDE 04 Removed mvl_release, mvla_release (obsolete) */ +/* 07/16/98 MDE 03 Addded 'mvl_dib_entry_to_app_ref' */ +/* 06/19/98 JRB 02 Add tp_type, etc. to NET_BIND_CTRL. */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#ifndef MVL_ACSE_INCLUDED +#define MVL_ACSE_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MMSEASE_MOSI) +/* min includes */ +#include "mms_def2.h" +#else +#include "acse2usr.h" +#include "mvl_defs.h" + +/************************************************************************/ +/* Some error return codes */ +#define REQ_INCOMPLETE 0x100 +#define LOCAL_NAME_NOT_FOUND 0x101 +#define REMOTE_NAME_NOT_FOUND 0x102 + +#define MVLE_LOCAL_NAME 0x101 +#define MVLE_REMOTE_NAME 0x102 +#define MVLE_NUM_CONNECTIONS 0x103 + +/************************************************************************/ +/* Bind and Connection control structures */ + +struct dib_entry; /* Forward declaration */ +#endif /* !defined(MMSEASE_MOSI) */ + +typedef struct net_bind_ctrl + { +/* These parameters must be set before using in mvl_start_acse */ + ST_CHAR ar_name[MAX_AR_LEN+1]; + ST_INT num_calling; + ST_INT num_called; + +/* Internal */ + ST_VOID *user_info; +#ifdef LEAN_T + ST_INT tp_type; + ST_INT32 copp_bind_id_tcp; + ST_INT32 copp_bind_id_tp4; +#else + ST_INT32 copp_bind_id; +#endif + ST_INT32 clpp_bind_id; + struct dib_entry *de; + } NET_BIND_CTRL; + +/************************************************************************/ +/* MVL configuration information. Filled in by user or configuration */ +/* and passed to mvl_start_acse. */ +/************************************************************************/ + +typedef struct + { + ST_INT max_msg_size; /* Max MMS message size */ + ST_INT num_calling; /* total number of calling connections */ + ST_INT num_called; /* total number of called connections */ + +/* Used for single local address binding (LEAN-T) */ + ST_CHAR local_ar_name[MAX_AR_LEN+1]; + +/* Used for multiple local address binding only (MARBEN) */ +#ifdef MAP30_ACSE /* Select bind mode */ + ST_BOOLEAN use_bind_ctrl; /* Set to 0 for single local */ +#endif + +/* User sets these only when use_bind_ctrl is SD_TRUE (MARBEN) */ + ST_INT max_bind_ctrl; /* Max allowed */ + ST_INT num_bind_ctrl; /* Active bindings */ + NET_BIND_CTRL *bind_ctrl; /* Array of NET_BIND_CTRL */ + +/* Internal use */ + ST_INT calling_used; /* Number mvl_calling_conn_ctrl bound */ + ST_INT called_used; /* Number mvl_called_conn_ctrl bound */ + } MVL_CFG_INFO; + +/* Persistant config information; set by MVL during mvl_start_acse */ +extern MVL_CFG_INFO *mvl_cfg_info; + +ST_RET osicfgx (ST_CHAR *xml_filename, MVL_CFG_INFO *mvlCfg); + +#if !defined(MMSEASE_MOSI) + +/************************************************************************/ +/* Global configuration variables */ + +extern INIT_INFO *mvl_init_resp_info; +extern NET_BIND_CTRL ma_clbind_ctrl; /* to save clpp_bind info. */ + +#if defined(MAP30_ACSE) +extern ST_INT mvl_num_bind_ctrl; +extern NET_BIND_CTRL *mvl_bind_ctrl; +#endif +ST_RET mvla_set_init_ar (ST_CHAR *ar_name); + +/************************************************************************/ +/* ACSE interface related MVL ACSE functions */ + +ST_VOID mvl_set_max_msg_size (ST_INT max_msg_size); + +ST_RET mvl_start_acse (MVL_CFG_INFO *cfgInfo); +ST_RET mvl_end_acse (ST_VOID); + + +ST_VOID _mvl_init_conn_ctrl (ST_VOID); + +ST_RET mvl_initiate_req (ST_CHAR *remAr, + INIT_INFO *req_info, + INIT_INFO *resp_info, + MVL_NET_INFO **net_info_out); + +ST_RET mvla_initiate_req (ST_CHAR *remAr, + INIT_INFO *req_info, + INIT_INFO *resp_info, + MVL_NET_INFO **net_info_out, + MVL_REQ_PEND **req_out); + +ST_INT mvla_initiate_req_ex (ST_CHAR *remAr, + INIT_INFO *req_info, + INIT_INFO *resp_info, + MVL_NET_INFO **net_info_out, + MVL_REQ_PEND **req_out, + ACSE_AUTH_INFO *auth_info, + S_SEC_ENCRYPT_CTRL *encrypt_info); + +/* If this variable is not NULL, MVL will use it as the source for the */ +/* local dib entry for an initiate request. */ +extern struct dib_entry *_mvla_initiate_locDe; + +ST_RET mvl_abort_req (MVL_NET_INFO *cc); +ST_RET mvl_abort_req_ex (MVL_NET_INFO *cc, + ST_BOOLEAN diagnostic_pres, + ST_ACSE_AUTH diagnostic); + +ST_RET mvl_init_audt_addr (AUDT_APDU *audt, ST_CHAR *locArName, ST_CHAR *remArName); +ST_VOID mvl_dib_entry_to_app_ref (struct dib_entry *de, struct app_ref *appRef); +ST_RET mvl_add_bind_ctrl (NET_BIND_CTRL *bc); + +/************************************************************************/ +/* User defined function pointer to handle disconnect indications */ + +#define MVL_ACSE_RELEASE_IND 1 +#define MVL_ACSE_ABORT_IND 2 +extern ST_VOID (*u_mvl_disc_ind_fun) (MVL_NET_INFO *cc, ST_INT discType); + +/************************************************************************/ +/* User defined functions to handle connect indications & confirms. */ +/* User must supply these functions. */ + +extern ST_ACSE_AUTH u_mvl_connect_ind_ex (MVL_NET_INFO *cc, INIT_INFO *init_info, ACSE_AUTH_INFO *req_auth_info, ACSE_AUTH_INFO *rsp_auth_info); +extern ST_ACSE_AUTH u_mvl_connect_cnf_ex (MVL_NET_INFO *cc, AARE_APDU *ass_rsp_info); + +/************************************************************************/ + +/* MVL level address matching functions */ +ST_RET mvl_match_remote_ar (DIB_MATCH_CTRL *matchCtrl, struct mvl_net_info *cc, + struct dib_entry **dib_entry_out); +ST_RET mvl_match_local_ar (DIB_MATCH_CTRL *matchCtrl, struct mvl_net_info *cc, + struct dib_entry **dib_entry_out); +ST_INT mvl_cmp_local_addr (DIB_MATCH_CTRL *matchCtrl, struct mvl_net_info *cc, + struct dib_entry *dib_entry); +ST_INT mvl_cmp_remote_addr (DIB_MATCH_CTRL *matchCtrl, struct mvl_net_info *cc, + struct dib_entry *dib_entry); + +#if defined(MAP30_ACSE) +ST_RET mvl_net_info_to_chan (MVL_NET_INFO *cc, ST_INT *chanOut); +#endif + +#endif /* !defined(MMSEASE_MOSI) */ + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* MVL_ACSE_INCLUDED */ +/************************************************************************/ + diff --git a/include/inc/mvl_defs.h b/include/inc/mvl_defs.h new file mode 100644 index 0000000..3c047f5 --- /dev/null +++ b/include/inc/mvl_defs.h @@ -0,0 +1,2552 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2003, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_defs.h */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/27/09 JRB 132 MVLAS_WRITE_CTRL: add ind_funct_done. */ +/* 09/25/08 MDE 131 Added MMS result info for READ/WRITE */ +/* 07/23/08 JRB 130 Move defs from mvl_uca.h to here (need earlier).*/ +/* Fix CntrlObj size. */ +/* 06/24/08 MDE 129 Added _mvl_persist_aa_objs */ +/* 06/04/08 JRB 128 Add file_list to MVL_NET_INFO. */ +/* Add mplas_concl_err. */ +/* Del mvl_type_ctrl from typedef (global var */ +/* with same name confused some debuggers). */ +/* 04/08/08 JRB 127 Chg () to (ST_VOID) in 2 prototypes. */ +/* 02/26/08 JRB 126 Add mvl_var_add_alloc, mvl_var_create_alloc. */ +/* Add mvl_var_create_derived. */ +/* mvl_dom_destroy: chg ret to void (can't fail)*/ +/* Add _mvl_clear_aa_objs. */ +/* 11/12/07 MDE 125 Added _mvl_getpath, changed _mvl_tmpnam */ +/* 04/16/07 JRB 124 Add prim_num to MVL_VAR_ASSOC. */ +/* 03/19/07 JRB 123 Del obsolete "mvl_vmd_*" macros. */ +/* 12/04/06 JRB 122 mvl_vmd_destroy: add arg to specify which VMD.*/ +/* 11/21/06 JRB 121 Move ..LAST_APPL_ERROR struct def to here */ +/* and add it to MVLAS_WR_VA_CTRL. */ +/* 10/30/06 JRB 120 Del #ifdef in structs so they do not change */ +/* with compiler options. */ +/* Del MVL_DYN_ASN1_TYPES option, always use */ +/* dynamic ASN1. Del asn1 from MVL_TYPE_CTRL. */ +/* 10/30/06 JRB 119 New object handling functions take VMD arg */ +/* & have "mvl_vmd_" prefix. Macros provided */ +/* for backward compatibility only. */ +/* mvl_nvl_create: change args. */ +/* Add "mvl_vmd_type_id_*". */ +/* Add mvl_vmd_create, */ +/* mvlu_rpt_ctrl_destroy_all, */ +/* mvl61850_rpt_ctrl_destroy_all. */ +/* u_mvl_get_va_aa: add vmd_ctrl arg. */ +/* u_gnl_ind_*: add net_info arg. */ +/* _mvl_objname_to_va: add vmd_ctrl, net_info args*/ +/* Del global var _mvl_curr_net_info. */ +/* Del global var _mvl_curr_usr_ind_ctrl. */ +/* 10/17/06 MDE 118 Added mvlas_obtfile_resp_ex */ +/* 07/21/06 JRB 117 Add rpt_reason & type_ctrl to MVL_VAR_ASSOC. */ +/* Add already_scanned to MVL_NVLIST_CTRL. */ +/* 07/13/05 MDE 116 Added u_mvl_reject_ind */ +/* 06/29/05 CRM 115 Add mvl_vmd_destroy. */ +/* 06/27/05 JRB 114 MVL_VAR_ASSOC: del mvl_internal, add last_data.*/ +/* 06/27/05 CRM 113 Added mvl_dom_find_last and */ +/* mvl_type_id_destroy_all_dyn. */ +/* 05/04/05 MDE 112 Added mvl_init_ind_hold */ +/* 03/28/05 JRB 111 Del suicacse header. */ +/* 03/14/05 CRM 110 Add mvl_max_dyn global variable. */ +/* Del _mvlu_num_dyn_types, add backward compat def*/ +/* 03/08/05 CRM 109 Add mvlas_fdir_resp(MVL_IND_PEND *ind) */ +/* 03/07/05 MDE 108 Added startTime to stats */ +/* 09/20/04 JRB 107 Add comments. */ +/* 08/30/04 JRB 106 Add sboCtrl to MVLAS_WR_VA_CTRL. */ +/* 06/29/04 JRB 105 Add mvl_type_id_create_from_tdl proto. */ +/* Add use_static_data flag to MVL_VAR_ASSOC. */ +/* Increase MAX_JREAD_RESP_ENTRIES define. */ +/* 07/10/03 EJV 104 Chg loc_ar_sec/rem_ar_sec to (S_SEC_LOC_AR *)*/ +/* 04/11/03 MDE 103 Added security elements */ +/* 04/11/03 MDE 102 Added _mvl_tmpnam */ +/* 04/04/03 JRB 101 MVL_IND_PEND: Add scan_va_done_fun for */ +/* IEC/UCA integrity scan. */ +/* 03/13/03 JRB 100 mvl_type_id_create: Add type_name arg. */ +/* MVL_TYPE_CTRL: Chg type_name to array. */ +/* MVL_TYPE_CTRL: Add rt_ctrl for dynamic types.*/ +/* Add mvl_type_ctrl_find_dyn. */ +/* Add mvl_scope_set proto. */ +/* Del mvlu_add_rt_type_x (not needed). */ +/* 12/12/02 JRB 99 Add usr_resp_fun to MVL_IND_PEND */ +/* Add mvl_internal to MVL_VAR_ASSOC */ +/* Chg acse_conn_id to ST_LONG to match ACSE */ +/* Add net_info arg to mvl_get_va_asn1_data */ +/* Add mvl_encode_info_rpt proto */ +/* Add enc_buf allocation macros. */ +/* 12/10/02 JRB 98 Moved UCA defs to new mvl_uca.h */ +/* 12/09/02 MDE 96 Added mvlu_find_uca_var */ +/* 12/09/02 MDE 96 Changed SBO reference handling */ +/* 11/27/02 MDE 95 Addded runtime leaf parameter manipulation */ +/* Added type_name to MVL_TYPE_CTRL */ +/* Added mvlu_add_rt_type_x */ +/* Added mvlu_proc_rt_type */ +/* 07/17/02 JRB 94 Del _mvla_send_write.. proto. Use static fct.*/ +/* 07/09/02 JRB 93 Add mvl_(u)req_bufs_avail functions. */ +/* 07/09/02 MDE 92 Add maxpend_ind support */ +/* 05/13/02 MDE 91 Added 'skip' arg to _mvl_set_net_req_done */ +/* 03/25/02 MDE 90 Moved error/reject elements outside union */ +/* 02/27/02 JRB 89 Fix mvl_print... proto. */ +/* 02/25/02 MDE 88 Deleted mvl_num_call* vars */ +/* 01/29/02 JRB 87 Del use of MVL_NUM_CALL* & COACSE. */ +/* Del a_unit_data_info,stack_sel from MVL_NET_INFO.*/ +/* 01/23/02 EJV 86 Added journals to MVL_DOM_CTRL */ +/* mvl_init_dom - added max_jou param */ +/* mvl_dom_resize - added max_jou param */ +/* mvl_dom_create - added max_num_jou param */ +/* mvl_dom_add - added max_num_jou param */ +/* 12/20/01 HSF 85 Added usr field to MVLU_RPT_SCAN_CTRL */ +/* 12/12/01 MDE 84 Moved acse_conn_id outside ifdef */ +/* 11/31/01 MDE 83 Added GOOSE scan support */ +/* 11/01/01 JRB 82 Chg mvl_wait_req_done return to ST_RET. */ +/* Add wait_any_event proto (user must supply). */ +/* 07/31/01 MDE 81 Added mvl_conn_filtered_logging support */ +/* 03/19/01 JRB 80 Move SMEM context defs to "smem.h". */ +/* 03/15/01 JRB 79 Add clientUstatus, serverUstatus statistics. */ +/* 03/13/01 JRB 78 Add mvl_ustatus, _mvl_process_ustatus_ind, */ +/* u_mvl_ustatus_ind prototypes. */ +/* 01/19/00 MDE 77 Removed SMEM idx defines (now in mem_chk.h) */ +/* 01/05/01 MDE 76 Changes for use over Marben */ +/* 10/25/00 JRB 75 Del u_mvl*, u_gnl* & _ml_* funct ptrs. */ +/* Add u_mvl_concl_ind, mplas_concl_resp. */ +/* Add req_pend_list to mvl_net_info. */ +/* Del usrNvl from MVLAS_READ_CTRL (not needed).*/ +/* Add "Server" support for Upl/Downl. */ +/* 10/06/00 MDE 74 Added _mvlu_num_dyn_types */ +/* 09/05/00 JRB 73 Add mvl_get_runtime_dyn. */ +/* 08/18/00 JRB 72 Fixed mvl_type_id_cre.. proto. */ +/* 08/18/00 RKR 71 Added rt field to MVLU_ typedefs */ +/* 07/26/00 MDE 70 Added user field to MVL_FGET_REQ_INFO */ +/* 07/12/00 JRB 69 Add dynamic type creation prototypes. */ +/* 07/11/00 MDE 68 Changed seqNum to sqNum, made INT8U */ +/* 06/26/00 JRB 67 Move "#define COACSE" from mvl_acse.h to */ +/* here (avoids dependence on mvl_acse.h). */ +/* 06/12/00 GLB 66 Added info for asynchronous File Get */ +/* 06/01/00 RKR 65 Removed some prototypes redundant in MMS-EASE*/ +/* 05/01/00 JRB 64 Del mvl_init_type_ctrl proto; now it's static*/ +/* 04/14/00 JRB 63 Fix SD_CONST for ??IndFunTbl, mvl_get_run... */ +/* Delete remnants of MVL_REQ_BUF_ENABLED. */ +/* 04/12/00 MDE 62 Added MVL_STATISTICS, _mvl_resize_ptr_tbl */ +/* 04/05/00 RKR 61 Made MVL_XNAME a compile time option */ +/* 04/04/00 RKR 60 Added expanded UCA variable name to RD and WR*/ +/* 03/10/00 JRB 59 Add scan_va_scope to MVLU_RPT_SCAN_CTRL. */ +/* 03/07/00 MDE 58 Added type_id to string declarations */ +/* 01/21/00 MDE 57 Now use MEM_SMEM for dynamic memory */ +/* 10/20/99 NAV 56 Add maxpend_req support */ +/* 09/28/99 NAV 55 Modified UCA Report REASON Bits */ +/* 09/13/99 MDE 54 Added SD_CONST modifiers */ +/* 11/04/99 RKR 53 Removed action_required from MVL_NET_INFO */ +/* 11/03/99 RKR 52 Added MVL error constants */ +/* 10/28/99 RKR 51 Added pending indications to MVL_NET_INFO */ +/* 10/07/99 GLB 50 Added support for file rename & obtain file. */ +/* 10/05/99 RKR 49 Added prototypes for deriving types */ +/* 09/30/99 JRB 48 Added forward declaration to reduce warnings.*/ +/* 09/30/99 RKR 47 Changed the Reason for Inclusion bit strings */ +/* 09/24/99 JRB 46 Added extern to mvlu_rpt_scan_list */ +/* 09/13/99 MDE 45 Added SD_CONST modifiers */ +/* 09/07/99 MDE 44 Revised and enhanced the UCA report system */ +/* 09/07/99 MDE 43 Changed MVL_VA_SCOPE to MVL_SCOPE, added */ +/* scope to MVL_NVLIST_CTRL */ +/* 07/30/99 MDE 42 Removed unused defines */ +/* 04/01/99 MDE 41 Changes to decode buffer allocation scheme */ +/* 03/18/99 MDE 40 Enhanced dynamic object facilities */ +/* 03/18/99 MDE 39 Changes to support runtime connection limits */ +/* 03/09/99 MDE 38 Added ICCP Lite support */ +/* 01/22/99 JRB 37 Chg all objects to array of ptrs so bsearch */ +/* can be used. Add bsearch functs (mvl_obj_*). */ +/* Use "mvl_nvl" prefix on all NVL obj functs. */ +/* Add "flags" to MVL_VAR_ASSOC for UCA. */ +/* 12/08/98 MDE 36 Added client alternate access support */ +/* 12/08/98 MDE 35 Added dynamic object handling */ +/* 11/17/98 MDE 34 Added _mvl_destroy_nvl_entries */ +/* 11/16/98 MDE 33 Cleanup and rearrange for readability */ +/* 11/16/98 MDE 32 Added 'locl_init_info' to MVL_NET_CTRL' */ +/* 11/16/98 MDE 30 Renamed MVL interal functions ('_'prefix) */ +/* 11/16/98 MDE 29 Added mvl_concl, mvla_concl */ +/* 11/16/98 MDE 28 Removed 'wait_any_event', 'read_log_cfg_file'*/ +/* 11/13/98 JRB 27 Add wait_any_event proto. */ +/* 10/12/98 MDE 26 Merged JRB's and MDE's changes */ +/* 10/09/98 JRB 25 Chg MVL_JOURNAL_ENTRY to use VAR_INFO. */ +/* Del MVL_CLI_JOURNAL_ENTRY, use only */ +/* MVL_JOURNAL_ENTRY everywhere. */ +/* Add 'read_log_cfg_file' prototype. */ +/* 10/09/98 DWL 24 Added get_dom stuff */ +/* Added get_nam stuff */ +/* Added status stuff */ +/* 10/09/98 DWL 23 Added get_var stuff */ +/* 10/01/98 MDE 22 Changed 'SD_CONST' define */ +/* 10/01/98 MDE 21 Changed rcb to ptr, removed MVL_NUM_CALLED */ +/* 10/01/98 MDE 20 Changed MVL_JOURNAL_ENTRY entry_id to */ +/* ST_UCHAR[8] */ +/* 09/21/98 MDE 19 Minor lint cleanup */ +/* 09/16/98 MDE 18 Fixed possible UCA report 'reason' overwrite */ +/* Added 'mvlu_rpt_ctrl_ptrs[MVLU_NUM_RPT_CTRL]'*/ +/* Added SBO support */ +/* 09/10/98 MDE 17 Added 'SD_CONST' declaration */ +/* 08/13/98 MDE 16 Removed USE_RT_DATA stuff */ +/* 08/11/98 MDE 15 Added UCA variable array support */ +/* 08/10/98 MDE 14 Changes to UCA report handling */ +/* 07/28/98 MDE 13 Added USE_RT_DATA define, related changes */ +/* 07/16/98 MDE 12 More journal work */ +/* 07/15/98 MDE 11 Changed Journal Read user functions */ +/* 07/13/98 MDE 10 Report and Journal work */ +/* 06/30/98 MDE 09 Added more flexable CLient Info Rpt code */ +/* 06/22/98 MDE 08 SeqNum now ST_UINT16 */ +/* 06/15/98 MDE 07 Changes to allow compile under C++ */ +/* 05/14/98 JRB 06 Add support for more services. */ +/* Add u_mvl_read_ind, u_mvl_write_ind, and */ +/* delete corresponding function ptrs. */ +/* Del mvl_ident_resp_info, mvl_status_resp_info*/ +/* Chg "Conf" function arg to (MVL_REQ_PEND *). */ +/* Chg "Ind" function arg to (MVL_IND_PEND *). */ +/* Add (MVL_REQ_PEND**) to sync client functs. */ +/* 03/15/98 MDE 05 Added support for user loaded Runtime Types, */ +/* dynamic NVL's */ +/* 02/10/98 MDE 04 Always support AA, added 'index' to conn */ +/* control, added UCA support, more. */ +/* 12/22/97 MDE 03 Changed '_mvl_net_service', 'mvl_comm_serv' */ +/* 12/29/97 MDE 02 Added Journal stuff, general cleanup */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#ifndef MVL_DEFS_INCLUDED +#define MVL_DEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mmsdefs.h" +#include "gen_list.h" + +#include "acse2usr.h" + +/************************************************************************/ +/* This define adds items to the MVL_NET_INFO and MVL_REQ_PEND data */ +/* structures. This small memory cost may be eliminated by commenting */ +/* out this define (when ICCP-Lite is not to be used). */ +/* This is being done so we can build a single MVL library for use with */ +/* both ICCP and non-ICCP implementations. */ + +#define ICCP_LITE_SUPP + +/************************************************************************/ +/* COMPILE TIME OPTIONS */ + +/* Comment this out to save code when using only the Async interface */ +/* for client applications. Used in making the MVL library. */ +#define MVL_SYNC_REQ_INTERFACE + +/* These values are used in the MVL object initialization code to allow */ +/* the user to dynamically add additional objects. */ + +#define MVL_NUM_DYN_DOMS 10 + +#if !defined(MVL_NUM_DYN_VMD_VARS) +#define MVL_NUM_DYN_VMD_VARS 0 +#endif + +#define MVL_NUM_DYN_VMD_NVLS 10 +#define MVL_NUM_DYN_JOUS 10 +#define MVL_NUM_DYN_DOM_VARS 10 +#define MVL_NUM_DYN_DOM_NVLS 10 +#define MVL_NUM_DYN_AA_VARS 10 +#define MVL_NUM_DYN_AA_NVLS 10 + +/* MVL_UCA requires dynamic types to function */ +#define MVLU_NUM_DYN_TYPES 100 + +typedef struct + { + ST_INT aa_nvls; + ST_INT aa_vars; + ST_INT doms; + ST_INT dom_nvls; + ST_INT dom_vars; + ST_INT journals; + ST_INT types; + ST_INT vmd_nvls; + ST_INT vmd_vars; + } MVL_MAX_DYN; + +extern MVL_MAX_DYN mvl_max_dyn; + +/* OBSOLETE: For backward compatibility only */ +#define _mvlu_num_dyn_types mvl_max_dyn.types + +/* Comment this out to use statically allocated buffers */ +/* Note that dynamic buffers are required for async server responses. */ +#define MVL_DYN_MEM + +/* This define can be uncomented in order to use binary search for */ +/* MMS-LITE object searches (variables, named variable lists, etc.). */ +/* #define MVL_USE_BSEARCH */ + +/* Define this to support receiving Information Reports */ +#define MVL_INFO_RPT_CLIENT + +/* Uncomment this to enable support for described access as server */ +/* #define MVL_DESCR_SUPP */ /* Warning, not currently supported */ + +/* Uncomment this to enable support for expanded UCA variable names */ +/* This will save some processing and a small bit of code. */ +/* #define MVL_XNAME */ + +/* Comment this to disable Alternate Access support for as server */ +/* This will save a small bit of code. */ +#define MVL_AA_SUPP + +/************************************************************************/ +/* Miscellaneous defines. */ +/************************************************************************/ +/* Max size of some IEC 61850 objects. */ +#define MVL61850_MAX_OBJREF_LEN 129 /* Value specified by Tissue 141*/ +#define MVL61850_MAX_RPTID_LEN 65 + +/************************************************************************/ +/* MMS OBJECT INITIALIZATION */ +/* This function must be called to initialize all MVL types and other */ +/* MMS objects. */ + +ST_VOID mvl_init (ST_VOID); +ST_VOID mvl_init_mms_objs (ST_VOID); + +/* COMMUNICATION SERVICE */ +/* This is the high level function to be called periodicly by the */ +/* application. It will check for communications events and act on them,*/ +/* which will include decoding MMS PDU's and calling service functions. */ +/* The mechanism used to determine when this function should be called */ +/* will depend on the lower layer service provider. */ + +ST_BOOLEAN mvl_comm_serve (ST_VOID); + +/* SYNCHRONOUS REQUEST USER SERVICE/TIMEOUT */ +/* User defined function, called repetitively by MVL client functions */ +/* while waiting for confirm. If this function returns SD_TRUE, the */ +/* request will timeout and return SD_FAILURE. */ + +extern ST_BOOLEAN (*u_mvl_check_timeout)(ST_VOID); + + +/* For use when global variables cannot be initialized at compile time */ +#if defined(NO_GLB_VAR_INIT) +ST_VOID mvl_init_glb_vars (ST_VOID); + +/* Internal use only */ +ST_VOID _mvlop_en_init (ST_VOID); +ST_VOID _s_getnam_init_glb_vars (ST_VOID); +#endif + +/* If set == SD_TRUE, MVL will not delete AA objects when connection */ +/* terminates */ +extern ST_BOOLEAN _mvl_persist_aa_objs; + +/************************************************************************/ +/* CAPACITY/STACK USAGE CONTROL DEFINES */ +/* These defines work along with the MMS PDU buffer sizes to control */ +/* the maximum number of MMS objects and the size of the objects that */ +/* can be handled per MMS PDU. */ + +#define MAX_JREAD_RESP_ENTRIES 10 +/*renxiaobao ÈÕÖ¾¸ü¸Ä*/ +/*#define MAX_JREAD_RESP_VARS 100*/ +#define MAX_JREAD_RESP_VARS 512 + +#define MVL_MAX_GNL_NAMES 100 + +/************************************************************************/ +/* MVL ERROR CODES */ + +/* #define E_MMS_LITE 0x6A00 */ +#define MVL_ERR_USR_TIMEOUT 0x6A01 +#define MVL_ERR_REQ_CONTROL 0x6A02 +#define MVL_ERR_UNKNOWN_PDU_TYPE 0x6A03 +#define MVL_ERR_RUNTIME_TYPE_ID 0x6A04 +#define MVL_ERR_ASN1_TO_RUNTIME 0x6A05 +#define MVL_ERR_NOT_SYM_ADDR 0x6A06 +#define MVL_ERR_ARRAY_ELEMENT_CNT 0x6A07 +#define MVL_ERR_LOCAL_ADDRESS 0x6A08 +#define MVL_ERR_BUFFER_SIZE 0x6A09 +#define MVL_ERR_DOM_CONTROL 0x6A0A +#define MVL_ERR_AA_CONTROL 0x6A0B +#define MVL_ERR_AA_SPECIFIC 0x6A0C +#define MVL_ERR_NVL_NOT_FOUND 0x6A0D +#define MVL_ERR_ALT_ACCESS 0x6A0E +#define MVL_ERR_VA_NOT_FOUND 0x6A0F +#define MVL_ERR_VA_SPEC 0x6A10 +#define MVL_ERR_NO_REQ_CTRL 0x6A11 +#define MVL_ERR_NO_CONN_CTRL 0x6A12 +#define MVL_ERR_ASSOC_REQ 0x6A13 +#define MVL_ERR_COMM_SERVE_ACTIVE 0x6A14 +#define MVL_ERR_REQ_PEND_COUNT 0x6A15 +#define MVL_ERR_CNF_REJ_ERR 0x6A16 +#define MVL_ERR_CNF_ERR_OK 0x6A17 +#define MVL_ERR_CNF_DISCONNECTED 0x6A18 +#define MVL_ERR_BAD_TYPE 0x6A19 +#define MVL_ERR_RESOURCE_NOT_AVAIL 0x6A1A + +/************************************************************************/ +/* Structure used to create linked list of all open files for one */ +/* connection (see connection structure MVL_NET_INFO). */ +typedef struct mvl_net_file + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct mvl_net_file *next; /* CRITICAL: DON'T MOVE. */ + struct mvl_net_file *prev; /* CRITICAL: DON'T MOVE. */ + FILE *fp; /* file pointer from fopen */ + } MVL_NET_FILE; + +/************************************************************************/ +/************************************************************************/ +/* NETWORK CONNECTION CONTROL */ +/* MVL_NET_INFO is used to specify the remote node to which the PDU is */ +/* to be sent, or from which the PDU was received. This element and */ +/* it's use are implementation specific. */ + +struct mvl_ind_pend; /* Forward declare this to eliminate warnings. */ +struct mvl_req_pend; /* Forward declare this to eliminate warnings. */ + +typedef struct mvl_net_info + { + struct mvl_aa_obj_ctrl *aa_objs; /* AA object ctrl */ + struct mvl_vmd_ctrl *rem_vmd; /* Remote VMD */ + struct mvl_ind_pend *pend_ind; + struct mvl_req_pend *req_pend_list; /* link list of pending reqs*/ + + ST_BOOLEAN conn_active; /* Set SD_TRUE when the connection is up */ + ST_INT max_pdu_size; + ST_INT index; /* NET_INFO table index for this elmnt */ + + ST_INT maxpend_req; /* num outstanding reqs negotiated */ + ST_INT numpend_req; /* num reqs currently outstanding */ + + ST_INT maxpend_ind; /* num outstanding inds negotiated */ + ST_INT numpend_ind; /* num inds currently outstanding */ + + ST_BOOLEAN log_enable; /* For use w/mvl_conn_filtered_logging */ + + ST_LONG acse_conn_id; /* ACSE's connection ID, internal */ + + ST_BOOLEAN mi_in_use; /* used only for ICCP_LITE_SUPP */ + struct _mi_conn *mi_conn; /* used only for ICCP_LITE_SUPP */ + + INIT_INFO rem_init_info; /* Services supported by remote device */ + INIT_INFO locl_init_info; /* Initiate info we sent */ + AARQ_APDU ass_ind_info; + /* Items below are used by MVL only */ + ST_BOOLEAN in_use; /* Flag that this 'NET_INFO' is in use */ + struct net_bind_ctrl *bind_ctrl; + + S_SEC_LOC_AR *loc_ar_sec; + S_SEC_REM_AR *rem_ar_sec; + + ST_VOID *user_info; /* MVL user can use this for 'whatever' */ + MVL_NET_FILE *file_list; /* linked list of open files on this conn*/ + } MVL_NET_INFO; + +/* Our connection control structures */ +extern MVL_NET_INFO *mvl_calling_conn_ctrl; +extern MVL_NET_INFO *mvl_called_conn_ctrl; + +/************************************************************************/ +/* MMS COMMUNICATIONS EVENT */ +/* MMS_COMM_EVENT is the data structure used to pass a communication */ +/* event from the lower layer provider to the MVL communication service */ +/* subsystem. This structure may be expanded to fit the needs of the */ +/* application. */ + +#define MMS_MSG_RCVD 1 +#define RECEIVE_ERROR 2 +#define COMM_LINK_UP 3 +#define COMM_LINK_DOWN 4 +#define MVLU_RPT_COMM_EVENT 5 + +typedef struct mvl_comm_event + { + DBL_LNK l; /* For linked list */ + MVL_NET_INFO *net_info; + ST_INT event_type; + union + { + struct /* used for MMS_MSG_RCVD event types */ + { + ST_UCHAR *pdu; + ST_INT pdu_len; + MMSDEC_INFO dec_rslt; + } mms; + struct /* possibly add more structs to handle other event types*/ + { + ST_RET code; + } error; + }u; + } MVL_COMM_EVENT; + +/************************************************************************/ +/************************************************************************/ +/* MVL TYPE HANDLING */ +/* Runtime type handling functions and structures */ +/* Note that the source code to create this table can be generated */ +/* using the 'mktypes' utility */ + +typedef struct + { + RUNTIME_CTRL *rt_ctrl; /* For dyn types ONLY, otherwise = NULL */ + ST_INT num_rt; /* Runtime type table */ + SD_CONST RUNTIME_TYPE *rt; + ST_INT data_size; /* size of data element */ + ST_CHAR type_name [MAX_IDENT_LEN+1]; /* name passed to Foundry (1st after :T)*/ + struct mvl_vmd_ctrl *vmd_ctrl; /* ptr to VMD which uses this type*/ + } MVL_TYPE_CTRL; + +/* These variables can be provided via the source code generated by */ +/* the 'foundry' utility program */ +extern MVL_TYPE_CTRL *mvl_type_ctrl; +extern ST_INT mvl_num_types; + +/* This function takes the type ID and provides a pointer to the runtime*/ +/* type and it's size as output. It returns SD_SUCCESS for success. */ +/* The type information is currently stored internally as ASN.1 encoded */ +/* types. */ + +ST_RET mvl_get_runtime (ST_INT type_id, + RUNTIME_TYPE **rt_ptr_out, + ST_INT *num_rt_out); + +/* Same function but only succeeds if type was dynamically created. */ +ST_RET mvl_get_runtime_dyn (ST_INT type_id, + RUNTIME_TYPE **rt_ptr_out, + ST_INT *num_rt_out); + + + +/* If USR_SUPPLIED_RT is defined (and not USE_RT_DATA) then the user */ +/* will supply the runtime table data structures using local means. */ +ST_VOID u_mvl_start_init_rt_tbl (ST_INT numTypes, ST_INT totalNumRt); +ST_VOID u_mvl_end_init_rt_tbl (ST_VOID); +RUNTIME_TYPE *u_mvl_get_rt_tbl (ST_INT typeId, ST_INT numRt); + +/* global variables in Foundry Object Realization File */ +extern SD_CONST RUNTIME_TYPE * SD_CONST mvl_rt_tables[]; +extern ST_INT rt_table_index; + +/************************************************************************/ +/* This function can be used to modify the number of elements */ +/* in an array runtime type. */ + +ST_VOID mvl_mod_arr_size (RUNTIME_TYPE *rt, ST_RTINT num_elmnts); + +/* This function converts an ASN.1 type definition to a runtime type. */ +/* The runtime type is allocated by chk_calloc and the user must free */ +/* the runtime type when done with it (using chk_free). */ + +ST_RET mvl_mk_rt_from_asn1 (ST_UCHAR *asn1ptr, ST_INT asn1len, + RUNTIME_TYPE **rt_out, ST_INT *num_rt_out); + +/************************************************************************/ +/************************************************************************/ +/* MMS OBJECT CONTROL ELEMENTS */ +/* Functions and structures used to map MMS objects to local elements */ +/************************************************************************/ +/* VARIABLE ASSOCIATION */ +/************************************************************************/ + +/* This structure is used in the Variable Association for use by */ +/* MVL_UCA in handling array alternate access */ + +typedef struct mvl_arr_ctrl + { + ST_BOOLEAN arrAltAccPres; + ST_BOOLEAN nested; /* Furter nesting is done on this arr */ + ST_RTINT low_index; + ST_RTINT num_elmnts; + ST_RTINT curr_index; + ALT_ACCESS alt_acc; /* Nested AA on the array */ + } MVL_ARR_CTRL; + + +/* MVL_VAR_PROC */ +/* The functions selected by these pointers will be called during */ +/* read/write indication processing (NULL pointers are not called, of */ +/* course!). The 'pre' funs must return SD_SUCCESS or SD_FAILURE, which */ +/* will be reflected in the MMS response. */ + +/* Values for 'aa_mode_out' */ +#define MVL_USE_NO_AA 1 +#define MVL_USE_PACKED_AA 2 +#define MVL_USE_UNPACKED_AA 3 + +struct mvl_var_assoc; /* Forward declare this to eliminate warnings. */ + +typedef struct mvl_var_proc + { + ST_RET (*pre_read_aa)(struct mvl_var_assoc **va, + ST_BOOLEAN alt_acc_pres, + ALT_ACCESS *alt_acc, + MVL_NET_INFO *ni, + ST_INT *aa_mode_out); + ST_VOID (*post_read_aa)(struct mvl_var_assoc *va, + ST_BOOLEAN alt_acc_pres, + ALT_ACCESS *alt_acc, + MVL_NET_INFO *ni); + + ST_RET (*proc_write_aa)(struct mvl_var_assoc **va, + ALT_ACCESS *alt_acc, + MVL_NET_INFO *ni, + ST_INT *aa_mode_out); + + ST_RET (*pre_write_aa) (struct mvl_var_assoc *va, + ST_BOOLEAN alt_acc_pres, + ALT_ACCESS *alt_acc, + MVL_NET_INFO *ni, + ST_CHAR *write_data, + ST_INT write_data_size); + ST_VOID (*post_write_aa)(struct mvl_var_assoc *va, + ST_BOOLEAN alt_acc_pres, + ALT_ACCESS *alt_acc, + MVL_NET_INFO *ni); + + ST_RET (*pre_info) (struct mvl_var_assoc *va, MVL_NET_INFO *ni); + ST_VOID (*post_info) (struct mvl_var_assoc *va, MVL_NET_INFO *ni); + } MVL_VAR_PROC; + +#define MVL_VAR_FLAG_UCA 0x01 /* for "flags" of MVL_VAR_ASSOC */ + +/* MVL_VAR_ASSOC */ +typedef struct mvl_var_assoc + { + ST_CHAR *name; /* variable name */ + ST_VOID *data; /* pointer to local data */ + ST_VOID *last_data; /* to save last value of this variable */ + /* only allocated if va is in nvl */ + /* used by IEC/UCA rpt code. */ + /*renxiaobao ÈÕÖ¾ + ST_VOID *last_log_data;*/ + ST_INT type_id; /* type of variable */ + MVL_TYPE_CTRL *type_ctrl; /* type of variable details */ + /* set by mvl_var_create */ + ST_UCHAR flags; /* MVL_VAR_FLAG_UCA, etc. */ + MVL_VAR_PROC *proc; /* User defined pre/post processing */ + ST_VOID *user_info; /* MVL user can use this for 'whatever' */ + ST_VOID *usr_ind_ctrl; + + struct mvl_var_assoc *va_to_free; /* Used in NVL processing */ + + struct mvl_var_assoc *base_va; /* VA from which this was derived */ + ST_INT offset_from_base; /* Used only for static data buffer */ + ST_RTINT prim_num; /* Index to first prim in RUNTIME_TYPE */ + /* (used only when MVL_UCA defined) */ + ST_RTREF ref; + MVL_ARR_CTRL arrCtrl; + + ST_BOOLEAN use_static_data; /* "data" in this struct points to */ + /* permanent data. */ + ST_UCHAR rpt_reason; /* 61850 RPT reason bitstring */ + ST_RET result; /* Used only if MVL_INFO_RPT_CLIENT */ + } MVL_VAR_ASSOC; + + +ST_RET mvl_get_va_asn1_data (MVL_NET_INFO *net_info, + MVL_VAR_ASSOC *va, + ST_BOOLEAN alt_acc_pres, + ALT_ACCESS *alt_acc, + ST_UCHAR *asn1_dest_buffer, + ST_INT asn1_buffer_len, + ST_INT *asn1_len_out); + + +/************************************************************************/ +/* DESCRIBED VARIABLE SUPPORT: Warning, not currently supported */ + +#if defined (MVL_DESCR_SUPP) +typedef struct mvl_descr_addr_assoc + { + ST_CHAR *base_name; /* base part of address */ + ST_VOID *data; /* pointer to local data base */ + ST_INT data_size; /* size of data element */ + ST_INT max_elmnts; + ST_VOID *user_info; /* MVL user can use this for 'whatever' */ + } MVL_DESCR_ADDR_ASSOC; + +ST_RET mvl_get_descr_local_addr (VAR_ACC_ADDR *addr, + RUNTIME_TYPE *rt, + ST_INT mum_rt, + ST_CHAR **data_out, + ST_INT *data_size_out); + +ST_RET mvl_get_descr_asn1_data (VARIABLE_LIST *vl, + ST_UCHAR *asn1_dest_buffer, + ST_INT asn1_buffer_len, + ST_INT *asn1_len_out); +#endif + +/************************************************************************/ +/* NAMED VARIABLE LISTS */ + +typedef struct mvl_scope + { + ST_INT16 scope; + struct mvl_dom_ctrl *dom; + } MVL_SCOPE; + +/* For backward compatibility only */ +#define MVL_VA_SCOPE MVL_SCOPE + +typedef struct mvl_nvlist_ctrl + { + ST_CHAR *name; /* name of the named variable list */ + ST_INT num_of_entries; /* number of variables in the list */ + MVL_VAR_ASSOC **entries; + MVL_SCOPE nvl_scope; /* scope of this NVL */ + MVL_SCOPE *va_scope; + ALT_ACCESS **altAcc; /* Alternate Access array for var's */ + ST_BOOLEAN mms_deletable; + ST_VOID *user_info; /* MVL user can use this for 'whatever' */ + ST_BOOLEAN already_scanned; /* flag to indicate this NVL already */ + /* scanned for rpt changes. Avoids */ + /* scanning same data multiple times. */ + } MVL_NVLIST_CTRL; + + +/************************************************************************/ +/* JOURNALS */ + +typedef struct mvlJouVar + { + ST_CHAR *varTag; /* variable tag */ + MVL_VAR_ASSOC *va; + } MVL_JOU_VAR; + +/* entry_form_tag value defines are in mms_pjou.h */ +/* #define JE_FORM_DATA 2 */ +/* #define JE_FORM_ANNOTATION 3 */ + +/* cur_state value defines are in mms_pevn.h */ +/* #define EC_STATE_DISABLED 0 */ +/* #define EC_STATE_IDLE 1 */ +/* #define EC_STATE_ACTIVE 2 */ + +typedef struct mvlJournalEntry + { + DBL_LNK l; /* for user, not used by MVL */ + + ST_INT entry_id_len; /* Octet string ID, size 1-8 */ + ST_UCHAR entry_id[8]; + + APP_REF orig_app; + MMS_BTOD occur_time; /* occurrence time */ + + ST_INT16 entry_form_tag; /* entry form tag */ + union + { + struct /* entry form is DATA */ + { + ST_BOOLEAN event_pres; /* event present */ + OBJECT_NAME evcon_name; /* event condition name */ + ST_INT16 cur_state; /* current state */ + ST_BOOLEAN list_of_var_pres; /* list of variables present */ + ST_INT num_of_var; /* number of variables */ + VAR_INFO *list_of_var; /* ptr to array */ + } data; + ST_CHAR *annotation; /* pointer to annotation */ + }ef; + } MVL_JOURNAL_ENTRY; + +/* MVL Journal control structure. Used by MVL for GNL response */ +typedef struct mvlJournal + { + ST_CHAR *name; /* journal name */ + ST_BOOLEAN mms_deletable; + ST_INT numEntries; + MVL_JOURNAL_ENTRY *entries; + } MVL_JOURNAL_CTRL; + +/************************************************************************/ +/* MMS OBJECT CONTROL */ +/************************************************************************/ + +/* Application Association Scope Objects */ +typedef struct mvl_aa_obj_ctrl + { + ST_INT max_num_var_assoc; + ST_INT num_var_assoc; + MVL_VAR_ASSOC **var_assoc_tbl; + + ST_INT max_num_nvlist; + ST_INT num_nvlist; + MVL_NVLIST_CTRL **nvlist_tbl; + + ST_INT max_num_jou; + ST_INT num_jou; + MVL_JOURNAL_CTRL **jou_tbl; + + ST_BOOLEAN foundry_objects; /* Flag for internal use */ + ST_VOID *user_info; /* MVL user can use this for 'whatever' */ + } MVL_AA_OBJ_CTRL; + + +/* Domain Scope Objects */ +typedef struct mvl_dom_ctrl + { + ST_CHAR *name; + + ST_INT max_num_var_assoc; + ST_INT num_var_assoc; + MVL_VAR_ASSOC **var_assoc_tbl; + + ST_INT max_num_nvlist; + ST_INT num_nvlist; + MVL_NVLIST_CTRL **nvlist_tbl; + + ST_INT max_num_jou; + ST_INT num_jou; + MVL_JOURNAL_CTRL **jou_tbl; + + GETDOM_RESP_INFO *get_dom_resp_info; /* Optional */ + + ST_BOOLEAN foundry_objects; /* Flag for internal use */ + ST_VOID *user_info; /* MVL user can use this for 'whatever' */ + } MVL_DOM_CTRL; + + +/* VMD Scope Objects */ +typedef struct mvl_vmd_ctrl + { + ST_INT max_num_var_assoc; + ST_INT num_var_assoc; + MVL_VAR_ASSOC **var_assoc_tbl; + +#if defined (MVL_DESCR_SUPP) + ST_INT num_descr_addr; + MVL_DESCR_ADDR_ASSOC *descr_addr_assoc_tbl; +#endif + + ST_INT max_num_nvlist; + ST_INT num_nvlist; + MVL_NVLIST_CTRL **nvlist_tbl; + + ST_INT max_num_dom; + ST_INT num_dom; + MVL_DOM_CTRL **dom_tbl; + + ST_INT max_num_jou; + ST_INT num_jou; + MVL_JOURNAL_CTRL **jou_tbl; + + ST_BOOLEAN foundry_objects; /* Flag for internal use */ + + ST_VOID *user_info; /* MVL user can use this for 'whatever' */ + } MVL_VMD_CTRL; +extern MVL_VMD_CTRL mvl_vmd; + + +/************************************************************************/ +/************************************************************************/ +/* MMS OBJECT CONTROL MANIPULUATION */ +/************************************************************************/ +/************************************************************************/ +/* Naming Conventions */ +/* */ +/* Find: Locate the object, given the object name */ +/* */ +/* Init: Delete all sub objects and resize tables */ +/* Clear: Delete all sub objects */ +/* Resize: Adjust table sizes */ +/* */ +/* Add: Create and Insert */ +/* Create: Allocate & initialize the object */ +/* Insert: Insert into tables */ +/* */ +/* Remove: Delete and Destroy */ +/* Delete: Delete from tables */ +/* Destroy: Free object and sub objects as approptiate */ +/* */ +/* Pairs - Add/Remove, Insert/Delete, Create/Destroy */ +/* */ +/* Usages: */ +/* All dynamic, startup and reconfigure, online object changes */ +/* * Use Foundry for types only */ +/* * Use 'mvl_init_vmd' for startup/reconfigure */ +/* * Use Add/Insert to construct object set */ +/* * Use Remove/Delete to remove unwanted objects */ +/* * Use Resize to modify storage as appropriate */ +/* */ +/* Both Foundry & Dynamic, startup & reconfigure, online changes */ +/* * Use Foundry for types and other objects */ +/* * Use Resize to modify storage for dynamic objects */ +/* * Use Add/Insert to add to object set */ +/* * Use Remove/Delete to remove unwanted objects */ +/* */ +/* Renaming an object */ +/* * Delete, change the name, and insert. Be careful of the name */ +/* buffer handling. */ +/* */ +/************************************************************************/ + +/**** OBJECT BULK UPDATE */ + +/* These defines can be used to speed loading of multiple objects. */ +/* After the 'start' call, MVL stops sorting objects as they are */ +/* inserted. When the 'end' call is made, all objects are sorted. */ + +/* NOTE: The 'end' call must be made before NVL's are added, so that */ +/* the variable associations can be resolved. This rule can be ignored */ +/* if domains and variable associations are added in sorted order. */ + +extern ST_BOOLEAN mvl_obj_nosort; +ST_VOID mvl_sort_objs (ST_VOID); +#define MVL_START_BULK_OBJ_UPDATE() {mvl_obj_nosort = SD_TRUE;} +#define MVL_END_BULK_OBJ_UPDATE() {if (mvl_obj_nosort == SD_TRUE){\ + mvl_obj_nosort = SD_FALSE;\ + mvl_sort_objs ();\ + }}\ + +/**** SCOPE LEVEL - VMD, DOMAIN */ + +/* Deletes all objects in the scope, allocates new object ctrl tables */ +/* NOTE: Works only on scopes with NO foundry objects. */ +ST_RET mvl_init_vmd (ST_INT max_dom, ST_INT max_var, + ST_INT max_nvl, ST_INT max_jou); +ST_RET mvl_init_dom (MVL_DOM_CTRL *dom, ST_INT max_var, + ST_INT max_nvl, ST_INT max_jou); +ST_RET mvl_init_aa (ST_INT max_var, ST_INT max_nvl, ST_INT max_jou); + +/* Deletes all objects in the scope */ +/* NOTE: Works only on scopes with NO foundry objects. */ +ST_RET mvl_clear_vmd_objs (ST_VOID); +ST_RET mvl_clear_dom_objs (MVL_DOM_CTRL *dom); +ST_RET mvl_clear_aa_objs (ST_VOID); +ST_VOID _mvl_clear_aa_objs (MVL_AA_OBJ_CTRL *aa_objs); + +/* Resize scope capacities, w/o affecting objects */ +ST_VOID mvl_vmd_resize (ST_INT max_dom, ST_INT max_var, + ST_INT max_nvl, ST_INT max_jou); +ST_VOID mvl_dom_resize (MVL_DOM_CTRL *dom, ST_INT max_var, + ST_INT max_nvl, ST_INT max_jou); +ST_VOID mvl_aa_resize (ST_INT max_var, ST_INT max_nvl, ST_INT max_jou); +ST_VOID mvl_aa_resize_conn (MVL_AA_OBJ_CTRL *aa_objs, ST_INT max_num_var, ST_INT max_num_nvl, + ST_INT max_num_jou); + +/**** DOMAINS */ + +MVL_DOM_CTRL *mvl_dom_create (ST_CHAR *name, ST_INT max_var, + ST_INT max_nvl, ST_INT max_jou, ST_BOOLEAN copy_name); +ST_VOID mvl_dom_destroy (MVL_DOM_CTRL *dom); + +/* User can be notified when domain is being destroyed */ +extern ST_VOID (*u_mvl_dom_destroy) (MVL_DOM_CTRL *dom); + + +/**** VARIABLE ASSOCIATIONS */ + +MVL_VAR_ASSOC *mvl_var_create (OBJECT_NAME *obj, ST_INT type_id, /* NEW */ + ST_VOID *data, MVL_VAR_PROC *proc, + ST_BOOLEAN copy_name); +MVL_VAR_ASSOC *mvl_var_create_alloc (ST_CHAR *name, + ST_INT type_id, + MVL_VAR_PROC *proc); +MVL_VAR_ASSOC *mvl_var_create_derived (ST_CHAR *name, + ST_INT type_id, + MVL_VAR_ASSOC *baseVa, /* base variable from which to derive */ + ST_INT offset_from_base, + ST_RTINT prim_num); +ST_VOID mvl_var_destroy (MVL_VAR_ASSOC *va); + +/* User can be notified when VA is being destroyed */ +extern ST_VOID (*u_mvl_var_destroy)(MVL_VAR_ASSOC *va); + +/**** NAMED VARIABLE LISTS */ + +MVL_NVLIST_CTRL *mvl_nvl_create (MVL_VMD_CTRL *vmd_ctrl, + ST_CHAR *nvlName, + ST_INT numNames, + OBJECT_NAME *var_obj, /* array of var obj names*/ + MVL_NET_INFO *net_info, /* where to find var_obj*/ + /* if it is AA_SPEC */ + ST_BOOLEAN copy_name); +ST_VOID mvl_nvl_destroy (MVL_NVLIST_CTRL *nvl); + +/* User can be notified when NVL is being destroyed */ +extern ST_VOID (*u_mvl_nvl_destroy) (MVL_NVLIST_CTRL *nvl); + + +/**** JOURNALS */ + +MVL_JOURNAL_CTRL *mvl_jou_create (OBJECT_NAME *obj, MVL_NET_INFO *net_info, + ST_BOOLEAN copy_name); +ST_VOID mvl_jou_destroy (MVL_JOURNAL_CTRL *jou); + +/* User can be notified when journal is being destroyed */ +extern ST_VOID (*u_mvl_jou_destroy) (MVL_JOURNAL_CTRL *jou); + +MVL_VMD_CTRL *mvl_vmd_create (ST_INT max_num_dom, ST_INT max_num_var, ST_INT max_num_nvl, ST_INT max_num_journal); +/* NOTE: old mvl_vmd_destroy function destroyed the global VMD and all */ +/* report controls. If that's what you want, you must now do like this: */ +/* mvlu_rpt_ctrl_destroy_all (); */ +/* mvl61850_rpt_ctrl_destroy_all (); */ +/* mvl_vmd_destroy (&mvl_vmd); */ +ST_RET mvl_vmd_destroy (MVL_VMD_CTRL *vmd_ctrl); +ST_VOID mvlu_rpt_ctrl_destroy_all (ST_VOID); +ST_VOID mvl61850_rpt_ctrl_destroy_all (ST_VOID); + +/************************************************************************/ +/************************************************************************/ +/* MANUFACTURED VARIABLE SUPPORT */ +/* Handlers for manufactured server variable names && lists */ +/************************************************************************/ + +/* This function will be called when an */ +/* undefined object is being accessed using alternate access. */ +/* If '*alt_access_done_out' is set SD_TRUE, MVL will assume that the */ +/* alternate access operation has been addressed by the called function */ + +MVL_VAR_ASSOC *u_mvl_get_va_aa (struct mvl_vmd_ctrl *vmd_ctrl, + ST_INT service, + OBJECT_NAME *obj, + MVL_NET_INFO *netInfo, + ST_BOOLEAN alt_access_pres, + ALT_ACCESS *alt_acc, + ST_BOOLEAN *alt_access_done_out); +ST_VOID u_mvl_free_va (ST_INT service, + MVL_VAR_ASSOC *va, + MVL_NET_INFO *netInfo); + +MVL_NVLIST_CTRL *u_mvl_get_nvl (ST_INT service, + OBJECT_NAME *obj, + MVL_NET_INFO *netInfo); +ST_VOID u_mvl_free_nvl (ST_INT service, + MVL_NVLIST_CTRL *nvl, + MVL_NET_INFO *netInfo); + +/************************************************************************/ +/************************************************************************/ +/* GET NAME LIST INDICATION HANDLERS */ +/* Default versions of these functs are found in s_getnam.c. They may */ +/* be replaced with customized functs (e.g. for UCA, see mvl_uca.c). */ + +ST_INT u_gnl_ind_vars(MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames); + +ST_INT u_gnl_ind_nvls(MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames); + +ST_INT u_gnl_ind_doms(NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames); + +ST_INT u_gnl_ind_jous(MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames); + +ST_VOID u_gnl_done(ST_INT16 mms_class, + NAMELIST_RESP_INFO *resp_info); + + +/************************************************************************/ +/************************************************************************/ +/* MVL SERVER SERVICE SUPPORT */ +/************************************************************************/ +/************************************************************************/ +/* Type for IEC 61850 "LastApplError" var (sent in report when control fails).*/ +/* NOTE: must be before MVLAS_WR_VA_CTRL. */ +/************************************************************************/ +typedef struct + { + ST_CHAR CntrlObj [MVL61850_MAX_OBJREF_LEN+1]; + ST_INT8 Error; + struct + { + ST_INT8 orCat; + struct + { + ST_INT16 len; + ST_UINT8 data[64]; + } orIdent; /* OVstring64 */ + } Origin; + ST_UINT8 ctlNum; + ST_INT8 AddCause; + } MVL61850_LAST_APPL_ERROR; + +/************************************************************************/ +/* INDICATION CONTROL */ +/************************************************************************/ +/* The data structure 'MVL_IND_PEND' is used to keep track of MMS */ +/* indications pending. */ + +/* Identify */ +typedef struct + { + IDENT_RESP_INFO *resp_info; + } MVLAS_IDENT_CTRL; + +/* Status */ +typedef struct + { + STATUS_REQ_INFO *req_info; + STATUS_RESP_INFO *resp_info; + } MVLAS_STATUS_CTRL; + +/* GetNameList */ +typedef struct + { + NAMELIST_REQ_INFO *req_info; + NAMELIST_RESP_INFO *resp_info; + } MVLAS_NAMELIST_CTRL; + +/* Read */ +/* This structure represents one Variable Association being read. The */ +/* user can set the 'acc_rslt_tag' to 'ACC_RSLT_FAILURE' if the read */ +/* does not succeed. */ + +typedef struct mvlas_rd_va_ctrl + { + MVL_VAR_ASSOC *va; + MVL_SCOPE va_scope; + + ST_INT16 acc_rslt_tag; /* ACC_RSLT_SUCCESS or ACC_RSLT_FAILURE */ + ST_INT16 failure; /* DataAccessError code for failure */ + ST_BOOLEAN alt_access_pres; + ALT_ACCESS alt_acc; + + ST_INT numPrimData; /* Total primitive elements for var */ + ST_INT numPrimDataDone; /* Number complete */ + + ST_VOID *usr; /* For user to use as she sees fit */ + } MVLAS_RD_VA_CTRL; + +typedef struct mvlas_read_ctrl + { + ST_INT16 var_acc_tag; /* VAR_ACC_NAMEDLIST or VAR_ACC_VARLIST */ + + ST_INT numVar; /* Variables being read */ + MVLAS_RD_VA_CTRL *vaCtrlTbl; + + MVL_NVLIST_CTRL *nvList; + } MVLAS_READ_CTRL; + + +/* Write */ +/* This structure represents one Variable Assoc being written. The */ +/* user can set the 'acc_rslt_tag' to 'ACC_RSLT_FAILURE' if the read */ +/* does not succeed. */ +struct mvl_sbo_ctrl; /* Forward declaration (defined in mvl_uca.h) */ +typedef struct mvlas_wr_va_ctrl + { + MVL_VAR_ASSOC *va; + MVL_SCOPE va_scope; + ST_INT16 resp_tag; /* WR_RSLT_FAILURE or WR_RSLT_SUCCESS */ + ST_INT16 failure; /* DataAccessError code for failure */ + ST_BOOLEAN alt_access_pres; + ALT_ACCESS alt_acc; /* Alternate Access specification */ + + ST_INT numPrimData; /* Total primitive elements for var */ + ST_INT numPrimDataDone; /* Number complete */ + struct mvl_sbo_ctrl *sboCtrl; /* SBO Control Info. */ + /* NOTE: "sboCtrl" used when writing IEC 61850 "Oper" or "Cancel". */ + /* Not used (i.e. NULL) for all other writes. */ + + ST_UCHAR *oldData; + + /* Used only when writing Oper, Cancel, SBOw (for IEC 61850). */ + MVL61850_LAST_APPL_ERROR LastApplError; + + ST_VOID *usr; /* For user to use as she sees fit */ + } MVLAS_WR_VA_CTRL; + +typedef struct mvlas_write_ctrl + { + ST_INT numVar; /* Variables being written */ + MVLAS_WR_VA_CTRL *vaCtrlTbl; + ST_BOOLEAN ind_funct_done; /* indication function completed? */ + } MVLAS_WRITE_CTRL; + + +/* GetVariableAccessAttributes */ +typedef struct + { + GETVAR_REQ_INFO *req_info; + GETVAR_RESP_INFO *resp_info; + } MVLAS_GETVAR_CTRL; + +/* DefineNamedVariableList */ +typedef struct + { + DEFVLIST_REQ_INFO *req_info; + } MVLAS_DEFVLIST_CTRL; + +/* GetNamedVariableListAttributes */ +typedef struct + { + GETVLIST_REQ_INFO *req_info; + GETVLIST_RESP_INFO *resp_info; /* allocate appropriate size */ + } MVLAS_GETVLIST_CTRL; + +/* DeleteNamedVariableList */ +typedef struct + { + DELVLIST_REQ_INFO *req_info; + DELVLIST_RESP_INFO *resp_info; + } MVLAS_DELVLIST_CTRL; + +/* GetDomainAttributes */ +typedef struct + { + GETDOM_REQ_INFO *req_info; + GETDOM_RESP_INFO *resp_info; + } MVLAS_GETDOM_CTRL; + +/* File Open */ +typedef struct + { + ST_CHAR filename [MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + ST_UINT32 init_pos; + FOPEN_RESP_INFO *resp_info; + } MVLAS_FOPEN_CTRL; + +/* File Read */ +typedef struct + { + FREAD_REQ_INFO *req_info; + ST_INT max_size; + FREAD_RESP_INFO *resp_info; + } MVLAS_FREAD_CTRL; + +/* File Close */ +typedef struct + { + FCLOSE_REQ_INFO *req_info; + } MVLAS_FCLOSE_CTRL; + +/* File Directory */ +typedef struct + { + ST_UINT32 fsize; /* file size (# bytes) */ + ST_BOOLEAN mtimpres; /* last modified time present */ + time_t mtime; /* last modified time */ + ST_CHAR filename [MAX_FILE_NAME+1]; + } MVL_DIR_ENT; + +typedef struct + { + ST_INT num_dir_ent; /* number of directory entries */ + ST_BOOLEAN more_follows; /* more dir entries follow */ + /* default: SD_FALSE */ + MVL_DIR_ENT *dir_ent; /* ptr to array of dir entries */ + } MVL_FDIR_RESP_INFO; + +typedef struct + { + ST_CHAR fs_filename[MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + ST_CHAR ca_filename[MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + MVL_FDIR_RESP_INFO *resp_info; + } MVLAS_FDIR_CTRL; + +/* ObtainFile */ +typedef struct + { + ST_CHAR srcfilename [MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + ST_CHAR destfilename [MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + } MVLAS_OBTFILE_CTRL; + +/* File Delete */ +typedef struct + { + ST_CHAR filename [MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + } MVLAS_FDELETE_CTRL; + +/* File Rename */ +typedef struct + { + ST_CHAR curfilename [MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + ST_CHAR newfilename [MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + } MVLAS_FRENAME_CTRL; + +/* InitializeJournal */ +typedef struct + { + JINIT_REQ_INFO *req_info; + JINIT_RESP_INFO *resp_info; + } MVLAS_JINIT_CTRL; + +/* ReadJournal */ +typedef struct + { + JREAD_REQ_INFO *req_info; + JREAD_RESP_INFO *resp_info; /* Variable size. User or mvlas_* must alloc.*/ + } MVLAS_JREAD_CTRL; + +/* JournalStatus */ +typedef struct + { + JSTAT_REQ_INFO *req_info; + JSTAT_RESP_INFO *resp_info; + } MVLAS_JSTAT_CTRL; + +typedef struct + { + INITUPL_REQ_INFO *req_info; + INITUPL_RESP_INFO *resp_info; + } MVLAS_INITUPL_CTRL; + +typedef struct + { + UPLOAD_REQ_INFO *req_info; + UPLOAD_RESP_INFO *resp_info; + } MVLAS_UPLOAD_CTRL; + +typedef struct + { + TERMUPL_REQ_INFO *req_info; + } MVLAS_TERMUPL_CTRL; + +typedef struct + { + INITDOWN_REQ_INFO *req_info; + } MVLAS_INITDOWN_CTRL; + +typedef struct + { + DELDOM_REQ_INFO *req_info; + } MVLAS_DELDOM_CTRL; + +typedef struct + { + CREPI_REQ_INFO *req_info; + } MVLAS_CREPI_CTRL; + +typedef struct + { + DELPI_REQ_INFO *req_info; + } MVLAS_DELPI_CTRL; + +typedef struct + { + GETPI_REQ_INFO *req_info; + GETPI_RESP_INFO *resp_info; + } MVLAS_GETPI_CTRL; + +typedef struct + { + START_REQ_INFO *req_info; + } MVLAS_START_CTRL; + +typedef struct + { + STOP_REQ_INFO *req_info; + } MVLAS_STOP_CTRL; + +typedef struct + { + RESUME_REQ_INFO *req_info; + } MVLAS_RESUME_CTRL; + +typedef struct + { + RESET_REQ_INFO *req_info; + } MVLAS_RESET_CTRL; + +typedef struct + { + GETCL_REQ_INFO *req_info; + GETCL_RESP_INFO *resp_info; + } MVLAS_GETCL_CTRL; + +/* MVL Indication Control */ +typedef struct mvl_ind_pend + { + DBL_LNK l; + MVL_COMM_EVENT *event; + ST_INT op; /* MMS Opcode (MMSOP_READ, etc.) */ + union + { + MVLAS_READ_CTRL rd; + MVLAS_WRITE_CTRL wr; + MVLAS_IDENT_CTRL ident; + MVLAS_STATUS_CTRL status; + MVLAS_NAMELIST_CTRL namelist; + MVLAS_GETVAR_CTRL getvar; + MVLAS_GETDOM_CTRL getdom; + MVLAS_FOPEN_CTRL fopen; + MVLAS_FREAD_CTRL fread; + MVLAS_FCLOSE_CTRL fclose; + MVLAS_FDIR_CTRL fdir; + MVLAS_OBTFILE_CTRL obtfile; + MVLAS_FDELETE_CTRL fdelete; + MVLAS_FRENAME_CTRL frename; + MVLAS_DEFVLIST_CTRL defvlist; + MVLAS_GETVLIST_CTRL getvlist; + MVLAS_DELVLIST_CTRL delvlist; + MVLAS_JINIT_CTRL jinit; + MVLAS_JREAD_CTRL jread; + MVLAS_JSTAT_CTRL jstat; + MVLAS_INITUPL_CTRL initupl; + MVLAS_UPLOAD_CTRL upload; + MVLAS_TERMUPL_CTRL termupl; + MVLAS_INITDOWN_CTRL initdown; + MVLAS_DELDOM_CTRL deldom; + MVLAS_CREPI_CTRL crepi; + MVLAS_DELPI_CTRL delpi; + MVLAS_GETPI_CTRL getpi; + MVLAS_START_CTRL start; + MVLAS_STOP_CTRL stop; + MVLAS_RESUME_CTRL resume; + MVLAS_RESET_CTRL reset; + MVLAS_GETCL_CTRL getcl; + } u; + /* For IEC/UCA Report scanning: */ + /* This function is called when scan completes for "one" variable */ + /* (i.e. all primitive reads complete for "one" variable of rpt). */ + ST_VOID (*scan_va_done_fun)(struct mvl_ind_pend *ind, MVL_VAR_ASSOC *va); + + /* User function to call INSTEAD of default Response function. */ + /* Currently only allowed for Read service (i.e. replaces call to */ + /* mvlas_read_resp). */ + ST_RET (*usr_resp_fun) (struct mvl_ind_pend *ind_pend); + + ST_VOID *usr_ind_ctrl; + ST_VOID *usr; /* For user to use as she sees fit */ + } MVL_IND_PEND; + +/************************************************************************/ +/* USER INDICATION and MVL RESPONSE FUNCTIONS */ +/* MVL calls the 'u_mvl_xxx_ind' function from within 'mvl_comm_serve' */ +/* to notify the user of the indication. The user must call a response */ +/* function ('mvlas_xxx_resp or 'mplas_xxx_resp') either from within */ +/* the user indication function or some time later. */ + +/* Identify */ +ST_VOID u_mvl_ident_ind (MVL_IND_PEND *ind); +ST_VOID mplas_ident_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* Status */ +ST_VOID u_mvl_status_ind (MVL_IND_PEND *ind); +ST_VOID mplas_status_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* Unsolicited Status */ +ST_VOID u_mvl_ustatus_ind (MVL_COMM_EVENT *event); /* NOTE: different arg*/ + +/* GetNameList */ +ST_VOID u_mvl_namelist_ind (MVL_IND_PEND *ind); +ST_VOID mplas_namelist_resp (MVL_IND_PEND *ind);/* Primitive */ +ST_VOID mvlas_namelist_resp (MVL_IND_PEND *ind);/* Virtual Machine */ + +/* Read */ +ST_VOID u_mvl_read_ind (MVL_IND_PEND *indCtrl); +ST_RET mvlas_read_resp (MVL_IND_PEND *indCtrl); + +/* Write */ +ST_VOID u_mvl_write_ind (MVL_IND_PEND *indCtrl); +ST_VOID mvlas_write_resp (MVL_IND_PEND *indCtrl); + +/* GetVariableAccessAttributes */ +ST_VOID u_mvl_getvar_ind (MVL_IND_PEND *ind); +ST_VOID mplas_getvar_resp (MVL_IND_PEND *ind); /* Primitive */ +ST_VOID mvlas_getvar_resp (MVL_IND_PEND *ind); /* Virtual Machine */ + +/* DefineNamedVariableList */ +ST_VOID u_mvl_defvlist_ind (MVL_IND_PEND *ind); +ST_VOID mplas_defvlist_resp (MVL_IND_PEND *ind);/* Primitive */ +ST_VOID mvlas_defvlist_resp (MVL_IND_PEND *ind);/* Virtual Machine */ + +/* GetNamedVariableListAttributes */ +ST_VOID u_mvl_getvlist_ind (MVL_IND_PEND *ind); +ST_VOID mplas_getvlist_resp (MVL_IND_PEND *ind);/* Primitive */ +ST_VOID mvlas_getvlist_resp (MVL_IND_PEND *ind);/* Virtual Machine */ + +/* DeleteNamedVariableList */ +ST_VOID u_mvl_delvlist_ind (MVL_IND_PEND *ind); +ST_VOID mplas_delvlist_resp (MVL_IND_PEND *ind);/* Primitive */ +ST_VOID mvlas_delvlist_resp (MVL_IND_PEND *ind);/* Virtual Machine */ + +/* GetDomainAttributes */ +ST_VOID u_mvl_getdom_ind (MVL_IND_PEND *ind); +ST_VOID mplas_getdom_resp (MVL_IND_PEND *ind); /* Primitive */ +ST_VOID mvlas_getdom_resp (MVL_IND_PEND *ind); /* Virtual Machine */ + +/* FileOpen */ +ST_VOID u_mvl_fopen_ind (MVL_IND_PEND *ind); +ST_VOID mplas_fopen_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* FileRead */ +ST_VOID u_mvl_fread_ind (MVL_IND_PEND *ind); +ST_VOID mplas_fread_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* FileClose */ +ST_VOID u_mvl_fclose_ind (MVL_IND_PEND *ind); +ST_VOID mplas_fclose_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* FileDirectory */ +ST_VOID u_mvl_fdir_ind (MVL_IND_PEND *ind); +ST_VOID mvlas_fdir_resp (MVL_IND_PEND *ind); +ST_VOID mplas_fdir_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* ObtainFile */ +ST_VOID u_mvl_obtfile_ind (MVL_IND_PEND *ind); +ST_VOID mplas_obtfile_resp (MVL_IND_PEND *ind); /* Primitive */ +ST_VOID mvlas_obtfile_resp (MVL_IND_PEND *ind); /* VirtualMachine */ +ST_VOID mvlas_obtfile_resp_ex (MVL_IND_PEND *indCtrl, ST_UINT32 fileSizeLimit); + +/* FileDelete */ +ST_VOID u_mvl_fdelete_ind (MVL_IND_PEND *ind); +ST_VOID mplas_fdelete_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* FileRename */ +ST_VOID u_mvl_frename_ind (MVL_IND_PEND *ind); +ST_VOID mplas_frename_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* InitializeJournal */ +ST_VOID u_mvl_jinit_ind (MVL_IND_PEND *ind); +ST_VOID mplas_jinit_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* ReadJournal */ +ST_VOID u_mvl_jread_ind (MVL_IND_PEND *ind); +ST_VOID mplas_jread_resp (MVL_IND_PEND *ind); /* Primitive */ +ST_VOID mvlas_jread_resp (MVL_IND_PEND *ind); /* Virtual Machine */ + +/* ReportJournalStatus */ +ST_VOID u_mvl_jstat_ind (MVL_IND_PEND *ind); +ST_VOID mplas_jstat_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* Conclude */ +ST_VOID u_mvl_concl_ind (MVL_COMM_EVENT *event); +ST_VOID mplas_concl_resp (MVL_COMM_EVENT *event); /* Primitive */ +ST_RET mplas_concl_err (MVL_COMM_EVENT *event, ST_INT16 err_class, ST_INT16 err_code); + +ST_VOID u_mvl_initupl_ind (MVL_IND_PEND *ind); +ST_VOID mplas_initupl_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_upload_ind (MVL_IND_PEND *ind); +ST_VOID mplas_upload_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_termupl_ind (MVL_IND_PEND *ind); +ST_VOID mplas_termupl_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_initdown_ind (MVL_IND_PEND *ind); +ST_VOID mplas_initdown_resp (MVL_IND_PEND *ind);/* Primitive */ + +ST_VOID u_mvl_deldom_ind (MVL_IND_PEND *ind); +ST_VOID mplas_deldom_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_crepi_ind (MVL_IND_PEND *ind); +ST_VOID mplas_crepi_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_delpi_ind (MVL_IND_PEND *ind); +ST_VOID mplas_delpi_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_getpi_ind (MVL_IND_PEND *ind); +ST_VOID mplas_getpi_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_start_ind (MVL_IND_PEND *ind); +ST_VOID mplas_start_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_stop_ind (MVL_IND_PEND *ind); +ST_VOID mplas_stop_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_reset_ind (MVL_IND_PEND *ind); +ST_VOID mplas_reset_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_resume_ind (MVL_IND_PEND *ind); +ST_VOID mplas_resume_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_getcl_ind (MVL_IND_PEND *ind); +ST_VOID mplas_getcl_resp (MVL_IND_PEND *ind); /* Primitive */ + +/************************************************************************/ +/* Server Read/Write Start and End Function Pointers */ + +/* These function pointers are invoked to allow the user application */ +/* to prepare for handling the indication. */ +extern ST_RET (*u_mvl_rd_ind_start) (MVL_IND_PEND *indCtrl); +extern ST_RET (*u_mvl_wr_ind_start) (MVL_IND_PEND *indCtrl); + +/* These function pointers are invoked to allow the user application */ +/* to free resources used in VA data buffer management. */ +extern ST_VOID (*u_mvl_rd_resp_sent) (MVL_IND_PEND *indCtrl); +extern ST_VOID (*u_mvl_wr_resp_sent) (MVL_IND_PEND *indCtrl); + + +/************************************************************************/ +/* Server Information Report */ +/* This function is used to send an information report. */ + +ST_RET mvl_info_variables (MVL_NET_INFO *net_info, MVL_NVLIST_CTRL *nvl, + ST_BOOLEAN listOfVariables); + +/************************************************************************/ +/* Server Journal Read */ + +/* Jread User Interaction */ +/* 1. A Journal Read indication is received by MVL. */ +/* 2. MVL calls 'u_mvl_start_jread'. User applies filter to it's journal */ +/* data and returns the number of entries and variables that meet */ +/* the filter as well as JREAD buffer control information and a */ +/* user handle. */ +/* Note that the defines: */ +/* MAX_JREAD_RESP_ENTRIES */ +/* MAX_JREAD_RESP_VARS */ +/* are used to limit the amount of information that MVL will return */ +/* in the MMS response. */ +/* The buffer control allows the user to supply MVL with data buffers */ +/* to be used to save the volitile Journal information (Entry ID, */ +/* Variable Tag, Annotation). */ +/* 3. MVL calls 'u_mvl_get_next_jread_entry' and 'u_mvl_free_jread_entry' */ +/* repetitively until the max MMS PDU size is reached or the number of */ +/* user entries is reached. */ +/* 4. MVL sends the JREAD response. */ +/* 5. MVL calls 'u_mvl_end_jread' and the user may then free resources */ +/* as necessary. */ + +/* These defines control the way that MVL handles the potentially */ +/* volitile information presented by the user via MVL_JOURNAL_ENTRY. */ +/* If these defines are defined, MVL will assume that the pointers */ +/* in MVL_JOURNAL_ENTRY will become invalid after the free call and */ +/* so it must copy the data into a buffer. These buffers are to be */ +/* supplied by the user, and must be large enough for the data. */ + +/* #define MVL_JREAD_ENTRYID_DYNAMIC */ +/* #define MVL_JREAD_VARTAG_DYNAMIC */ +/* #define MVL_JREAD_ANNOTATION_DYNAMIC */ + +typedef struct mvlJreadBufCtrl + { + ST_INT numUsrEntries; /* User must supply */ + ST_INT numVarInfo; /* User must supply */ + +#if defined (MVL_JREAD_ENTRYID_DYNAMIC) + ST_UCHAR *entryIdBuf; /* User must supply */ + ST_UCHAR *nextEntryId; /* MVL use only */ +#endif + +#if defined (MVL_JREAD_VARTAG_DYNAMIC) + ST_CHAR *varTagBuf; /* User must supply */ + ST_CHAR *nextVarTag; /* MVL use only */ +#endif + +#if defined (MVL_JREAD_ANNOTATION_DYNAMIC) + ST_CHAR *annotationBuf; /* User must supply */ + ST_CHAR *nextAnnotation; /* MVL use only */ +#endif + + } MVL_JREAD_BUF_CTRL; + + +/* User defined Journal Read response functions. These functions are */ +/* to be supplied by the application in order to get the information */ +/* required for a Journal Read response. */ + +/* This function should be used to apply the filter and returns the */ +/* total number of Journal Entries and Journal Variables that meet */ +/* the filter criteria. */ +ST_RET u_mvl_start_jread (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo, + MVL_JREAD_BUF_CTRL *bufCtrl, + ST_VOID **usrHandleOut); + +/* MVL calls this function repetitively to get entries from the app. */ +/* MVL will use the entry then will call the free function below to */ +/* allow the application free the resources as required. */ +ST_RET u_mvl_get_next_jread_entry (MVL_JOURNAL_CTRL *jCtrl, + ST_VOID *usrHandle, + ST_BOOLEAN *moreFollowsOut, + MVL_JOURNAL_ENTRY **mvlJeDest); +ST_VOID u_mvl_free_jread_entry (MVL_JOURNAL_CTRL *jCtrl, + ST_VOID *usrHandle, + MVL_JOURNAL_ENTRY *mvlJe); + +/* When complete, MVL will call this function. */ +ST_VOID u_mvl_end_jread (MVL_JOURNAL_CTRL *jCtrl, + ST_VOID *usrHandle, + MVL_JREAD_BUF_CTRL *bufCtrl, + JREAD_REQ_INFO *reqInfo); + +/************************************************************************/ +/************************************************************************/ +/* Temporary file name */ + +/* User can supply path for temp files, prefix for file name */ +/* Typical forms are: */ +/* "/temp/" */ +/* "S:/temp/" */ +/* "//mike/temp/" */ +/* "X:" */ + +#define MVL_MAX_TMPFILE_PATH MAX_FILE_NAME +//extern ST_CHAR *mvl_tmpfile_path; + +/* Users should have a buffer at least this big, unless they can */ +/* control the temp filename path to be used. */ +#define MVL_MAX_TMPNAM_LEN (MVL_MAX_TMPFILE_PATH + 12) +ST_RET _mvl_tmpnam (ST_CHAR *dest, ST_CHAR *tmpfile_path); +ST_VOID _mvl_getpath (ST_CHAR *file_spec, ST_CHAR *dest); + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* MVL CLIENT SERVICE SUPPORT */ +/************************************************************************/ +/* conf_process_mode defines */ +/* When the confirm is received (and ICCP support is enabled) this flag */ +/* is used to tell MVL how to process the confirm. */ +#define MI_CONF_ICCP_DV 0x0001 + + +/* Read */ +typedef struct mvl_read_resp_parse_info + { + ST_RET result; /* SD_SUCCESS for OK */ + + /* MMS level result information */ + ST_INT16 acc_rslt_tag; /* access result tag */ + ST_INT16 failure; /* data access error */ + + ST_VOID *dest; /* Where data is to be put */ + ST_INT type_id; /* type of variable */ + + ST_BOOLEAN alt_acc_pres; + ALT_ACCESS *alt_acc; + ST_BOOLEAN alt_acc_type_aa; /* type_id is derived type */ + ST_BOOLEAN alt_acc_data_packed; + + ST_BOOLEAN descr_arr; /* for described read of array */ + ST_RTINT arr_size; /* number of elements */ + } MVL_READ_RESP_PARSE_INFO; + +/* Write */ +typedef struct mvl_write_req_info + { + ST_RET result; /* SD_SUCCESS for OK */ + + /* MMS level result detail */ + ST_INT16 resp_tag; /* response tag */ + ST_INT16 failure; /* data access error */ + + ST_VOID *local_data; /* Source of local data */ + ST_INT type_id; /* type of variable */ + + ST_BOOLEAN alt_acc_pres; + ALT_ACCESS *alt_acc; + ST_BOOLEAN alt_acc_type_aa; /* type_id is derived type */ + ST_BOOLEAN alt_acc_data_packed; + + ST_BOOLEAN arr; /* SD_TRUE if type is array and the # */ + ST_RTINT num_el; /* elements needs to be set */ + } MVL_WRITE_REQ_INFO ; + +/* JournalRead */ +typedef struct + { + ST_INT num_of_jou_entry; /* number of journal entries */ + ST_BOOLEAN more_follows; /* default = false */ + MVL_JOURNAL_ENTRY *jou_entry; /* ptr to array of entries */ + } MVL_JREAD_RESP_INFO; + +/* Outstanding Request Control */ +typedef struct mvl_req_pend + { + DBL_LNK l; /* For linked list */ + ST_UINT32 invoke_id; + time_t request_time; + MVL_NET_INFO *net_info; /* Who it was sent to */ + ST_INT op; /* MMS Opcode */ + union + { + struct + { + MVL_READ_RESP_PARSE_INFO *parse_info; + ST_INT num_data; + } rd; + struct + { + MVL_WRITE_REQ_INFO *w_info; + ST_INT num_data; + } wr; + struct + { + IDENT_RESP_INFO *resp_info; + } ident; + struct + { + INIT_INFO *resp_info; + } init; + struct + { + FOPEN_RESP_INFO *resp_info; + } fopen; + struct + { + FREAD_RESP_INFO *resp_info; + } fread; + struct + { + MVL_FDIR_RESP_INFO *resp_info; + } fdir; + struct + { + JINIT_RESP_INFO *resp_info; + } jinit; + struct + { + JSTAT_RESP_INFO *resp_info; + } jstat; + struct + { + MVL_JREAD_RESP_INFO *resp_info; + } jread; + struct + { + GETVLIST_RESP_INFO *resp_info; + } getvlist; + struct + { + DELVLIST_RESP_INFO *resp_info; + } delvlist; + struct + { + GETVAR_RESP_INFO *resp_info; + } getvar; + struct + { + GETDOM_RESP_INFO *resp_info; + } getdom; + struct + { + NAMELIST_RESP_INFO *resp_info; + } getnam; + struct + { + STATUS_RESP_INFO *resp_info; + } status; + struct + { + DOWNLOAD_RESP_INFO *resp_info; + } download; /* DownloadSegment resp info */ + } u; + MVL_COMM_EVENT *event; /* save event ptr to free later.*/ + ST_BOOLEAN done; + ST_RET result; /* SD_SUCCESS or error code */ + ERR_INFO *error_info; /* When result == MVL_ERR_CNF_ERR_OK */ + REJECT_RESP_INFO *reject_info; /* When result == MVL_ERR_CNF_REJ_ERR */ + + + /* User done function for async functions */ + ST_VOID (*u_req_done) (struct mvl_req_pend *req); + ST_VOID *v; /* For MVL user's use */ + + struct _mi_req_ctrl *mi_req; /* used for ICCP_LITE_SUPP */ + } MVL_REQ_PEND; + + +struct mvl_fget_req_info; /* forward declaration */ + +typedef struct mvl_fget_req_info + { + ST_BOOLEAN fget_done; + ST_INT fget_error; + /* pointer to user's fget confirm function */ + ST_VOID (*fget_cnf_ptr)(struct mvl_fget_req_info *state); + ST_CHAR srcfilename[MAX_FILE_NAME+1]; + ST_CHAR destfilename[MAX_FILE_NAME+1]; + + ST_VOID *v; /* For MVL user's use */ + + /* The rest of this structure is not normally accessed by the user. */ + char tempfilename[MVL_MAX_TMPNAM_LEN+1]; + FILE *fp; + ST_INT32 frsmid; + ST_UINT32 fsize; + } MVL_FGET_REQ_INFO; + + +ST_RET _mvla_send_status (MVL_NET_INFO *net_info, + STATUS_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_getname (MVL_NET_INFO *net_info, + NAMELIST_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_read_variables (MVL_NET_INFO *net_info, + READ_REQ_INFO *read_info, + ST_INT num_data, + MVL_READ_RESP_PARSE_INFO *parse_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_getvar (MVL_NET_INFO *net_info, + GETVAR_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_defvlist (MVL_NET_INFO *net_info, + DEFVLIST_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_getvlist (MVL_NET_INFO *net_info, + GETVLIST_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_delvlist (MVL_NET_INFO *net_info, + DELVLIST_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_getdom (MVL_NET_INFO *net_info, + GETDOM_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_fopen (MVL_NET_INFO *net_info, + ST_CHAR *filename, + ST_UINT32 init_pos, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_fread (MVL_NET_INFO *net_info, + FREAD_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_fclose (MVL_NET_INFO *net_info, + FCLOSE_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_fdir (MVL_NET_INFO *net_info, + ST_CHAR *filename, + ST_CHAR *ca_filename, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_fdelete (MVL_NET_INFO *net_info, + ST_CHAR *filename, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_jinit (MVL_NET_INFO *net_info, + JINIT_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_jread (MVL_NET_INFO *net_info, + JREAD_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_jstat (MVL_NET_INFO *net_info, + JSTAT_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); + +/* Function to make async function sync */ +ST_RET mvl_wait_req_done (MVL_REQ_PEND *req); + +/* Use this to free a request contrl after the confirm has been rx'd */ +ST_VOID mvl_free_req_ctrl (MVL_REQ_PEND *pend_req); + +/* Use this to free any pending Indication Ctrl structures */ +ST_VOID mvl_clr_ind_que (MVL_NET_INFO *net_info); + +/************************************************************************/ +/* CLIENT REQUEST FUNCTIONS */ +/* Most client request functions come in two versions - synchronous */ +/* and asynchronous. Both have identical arguments - the only */ +/* difference is that the synchronous versions do not return until */ +/* the confirm/error has been received, or the user gives up (via */ +/* the 'u_mvl_check_timeout' function). */ + +/* Identify */ +ST_RET mvl_identify (MVL_NET_INFO *net_info, MVL_REQ_PEND **req_out); +ST_RET mvla_identify (MVL_NET_INFO *net_info, MVL_REQ_PEND **req_out); + +/* Status */ +ST_RET mvl_status (MVL_NET_INFO *net_info, STATUS_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_status (MVL_NET_INFO *net_info, STATUS_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* Unsolicited Status */ +ST_RET mvl_ustatus (MVL_NET_INFO *net_info, USTATUS_REQ_INFO *req_info); + +/* GetNameList */ +ST_RET mvl_getnam (MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_getnam (MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + + +/* Read */ +ST_RET mvl_read_variables (MVL_NET_INFO *net_info, READ_REQ_INFO *read_info, + ST_INT num_data, + MVL_READ_RESP_PARSE_INFO *parse_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_read_variables (MVL_NET_INFO *net_info, READ_REQ_INFO *read_info, + ST_INT num_data, + MVL_READ_RESP_PARSE_INFO *parse_info, + MVL_REQ_PEND **req_out); + + +/* Write */ +ST_RET mvl_write_variables (MVL_NET_INFO *net_info, WRITE_REQ_INFO *write_info, + ST_INT num_data, MVL_WRITE_REQ_INFO *w_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_write_variables (MVL_NET_INFO *net_info, WRITE_REQ_INFO *write_info, + ST_INT num_data, MVL_WRITE_REQ_INFO *w_info, + MVL_REQ_PEND **req_out); + +/* GetVariableAccessAttributes */ +ST_RET mvl_getvar (MVL_NET_INFO *net_info, GETVAR_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_getvar (MVL_NET_INFO *net_info, GETVAR_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* DefineNamedVariableList */ +ST_RET mvl_defvlist (MVL_NET_INFO *net_info, DEFVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_defvlist (MVL_NET_INFO *net_info, DEFVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* GetNamedVariableListAttributes */ +ST_RET mvl_getvlist (MVL_NET_INFO *net_info, GETVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_getvlist (MVL_NET_INFO *net_info, GETVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* DeleteNamedVariableList */ +ST_RET mvl_delvlist (MVL_NET_INFO *net_info, DELVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_delvlist (MVL_NET_INFO *net_info, DELVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* GetDomainAttributes */ +ST_RET mvl_getdom (MVL_NET_INFO *net_info, GETDOM_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_getdom (MVL_NET_INFO *net_info, GETDOM_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* File Open */ +ST_RET mvl_fopen (MVL_NET_INFO *net_info, ST_CHAR *filename, + ST_UINT32 init_pos, MVL_REQ_PEND **req_out); +ST_RET mvla_fopen (MVL_NET_INFO *net_info, ST_CHAR *filename, + ST_UINT32 init_pos, MVL_REQ_PEND **req_out); + +/* File Read */ +ST_RET mvl_fread (MVL_NET_INFO *net_info, FREAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_fread (MVL_NET_INFO *net_info, FREAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* File Close */ +ST_RET mvl_fclose (MVL_NET_INFO *net_info, FCLOSE_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_fclose (MVL_NET_INFO *net_info, FCLOSE_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* File Directory */ +ST_RET mvl_fdir (MVL_NET_INFO *net_info, ST_CHAR *filename, + ST_CHAR *ca_filename, MVL_REQ_PEND **req_out); +ST_RET mvla_fdir (MVL_NET_INFO *net_info, ST_CHAR *filename, + ST_CHAR *ca_filename, MVL_REQ_PEND **req_out); + +/* File Delete */ +ST_RET mvl_fdelete (MVL_NET_INFO *net_info, ST_CHAR *filename, + MVL_REQ_PEND **req_out); +ST_RET mvla_fdelete (MVL_NET_INFO *net_info, ST_CHAR *filename, + MVL_REQ_PEND **req_out); + +/* File Rename */ +ST_RET mvl_frename (MVL_NET_INFO *net_info, ST_CHAR *curfilename, + ST_CHAR *newfilename, MVL_REQ_PEND **req_out); +ST_RET mvla_frename (MVL_NET_INFO *net_info, ST_CHAR *curfilename, + ST_CHAR *newfilename, MVL_REQ_PEND **req_out); + +/* Obtainfile */ +ST_RET mvl_obtfile (MVL_NET_INFO *net_info, ST_CHAR *srcfilename, + ST_CHAR *destfilename, MVL_REQ_PEND **req_out); +ST_RET mvla_obtfile (MVL_NET_INFO *net_info, ST_CHAR *srcfilename, + ST_CHAR *destfilename, MVL_REQ_PEND **req_out); + +/* File Get */ +/* No synchronous File Get function "mvl_fget". Requires multiple reqs, */ +/* so cannot be synchronous. */ +ST_RET mvla_fget (MVL_NET_INFO *net_info, ST_CHAR *srcfilename, + ST_CHAR *destfilename, MVL_FGET_REQ_INFO *fget_req_info); + +/* InitializeJournal */ +ST_RET mvl_jinit (MVL_NET_INFO *net_info, JINIT_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_jinit (MVL_NET_INFO *net_info, JINIT_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* ReadJournal */ +ST_RET mvl_jread (MVL_NET_INFO *net_info, JREAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_jread (MVL_NET_INFO *net_info, JREAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* WriteJournal */ +ST_RET mvl_jwrite (MVL_NET_INFO *net_info, JWRITE_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_jwrite (MVL_NET_INFO *net_info, JWRITE_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* JournalStatus */ +ST_RET mvl_jstat (MVL_NET_INFO *net_info, JSTAT_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_jstat (MVL_NET_INFO *net_info, JSTAT_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* InitiateDownload */ +/* NOT YET IMPLEMENTED! ONLY NEEDED FOR CLIENT */ + +/* DownloadSegment */ +ST_RET mvl_download (MVL_NET_INFO *net_info, DOWNLOAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_download (MVL_NET_INFO *net_info, DOWNLOAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* TerminateDownload */ +ST_RET mvl_termdown (MVL_NET_INFO *net_info, TERMDOWN_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_termdown (MVL_NET_INFO *net_info, TERMDOWN_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* Conclude */ +ST_RET mvl_concl (MVL_NET_INFO *net_info, MVL_REQ_PEND **req_out); +ST_RET mvla_concl (MVL_NET_INFO *net_info, MVL_REQ_PEND **req_out); +ST_RET _mvla_send_concl (MVL_NET_INFO *net_info, MVL_REQ_PEND *req_pend); + +/* Obsolete function, please use mvl_conc or mvla_conc */ +/* ST_RET mvl_conclude (MVL_NET_INFO *net_info ); */ + +/************************************************************************/ +/* ENCODE FUNCTIONS - each encodes a req or resp but does NOT send it. */ +/************************************************************************/ +/* Information Report Request */ +ST_RET mvl_encode_info_rpt (MVL_NET_INFO *net_info, + MVL_NVLIST_CTRL *nvl, + ST_BOOLEAN listOfVariables, + ASN1_ENC_CTXT *aCtx); + +/* NOTE: other encode functions not currently needed. */ + +/************************************************************************/ +/* Client Info Rpt indication */ + +/* This function is called when thje client application received an */ +/* information report */ +extern ST_VOID u_mvl_info_rpt_ind (MVL_COMM_EVENT *event); + +/* This function is used to convert Info Report data to local format */ +/* The user supplies a table of variable associations, which speify the */ +/* data type, destination, and pre/post processing functions. */ +/* This function free's the info report resources when the conversion */ +/* are complete. */ + +ST_VOID mvl_info_data_to_local (MVL_COMM_EVENT *event, + ST_INT num_va, + MVL_VAR_ASSOC **info_va); + +#if defined(MVL_REM_VMD_SUPPORT) +extern MVL_VMD_CTRL *(*u_mvl_get_rem_vmd_fun) (MVL_NET_INFO *net_info); +ST_VOID mvl_info_rpt_rem_process (MVL_COMM_EVENT *event); +#endif + +ST_RET mvlu_add_rt_type (RUNTIME_TYPE *rt, ST_INT numRt, ST_INT *typeIdOut); +ST_VOID mvlu_free_rt_type (ST_INT typeId); + +/* Type to String and visa-versa */ +ST_INT mvl_typename_to_typeid (ST_CHAR *type_id_string); +ST_CHAR *mvl_typeid_to_typename (ST_INT type_id); + + +/************************************************************************/ +/************************************************************************/ + +typedef struct + { + ST_DOUBLE startTime; + ST_INT32 callingConn; /* Calling Connections */ + ST_INT32 callingConnOk; /* Calling Connections Succesful*/ + ST_INT32 callingConnFail; /* Calling Connections Failed */ + ST_INT32 calledConn; /* Called Connections */ + ST_INT32 calledConnOK; /* Called Connections Succesful */ + ST_INT32 calledConnFail; /* Called Connections Failed */ + ST_INT32 clientConcl; /* Client Concludes */ + ST_INT32 serverConcl; /* Server Concludes */ + ST_INT32 localAbort; /* Local Aborts */ + ST_INT32 remoteAbort; /* Remote Aborts */ + ST_INT32 rejectsSent; /* Rejects Sent */ + ST_INT32 rejectsRcvd; /* Rejects Received */ + ST_INT32 clientReq; /* Client Requests */ + ST_INT32 clientReqOk; /* Client Requests OK */ + ST_INT32 clientReqErr; /* Client Requests Error */ + ST_INT32 clientVarRdOk; /* Client Variables Read OK */ + ST_INT32 clientVarRdFail; /* Client Variables Read Error */ + ST_INT32 clientVarWrOk; /* Client Variables Write OK */ + ST_INT32 clientVarWrErr; /* Client Variables Write Error */ + ST_INT32 clientInfoRpt; /* Client Information Reports */ + ST_INT32 clientUstatus; /* Client Unsolicited Status */ + ST_INT32 serverInd; /* Server Indications */ + ST_INT32 serverRespOk; /* Server Responses OK */ + ST_INT32 serverRespErr; /* Server Responses Error */ + ST_INT32 serverVarRdOk; /* Server Variables Read OK */ + ST_INT32 serverVarRdErr; /* Server Variables Read Error */ + ST_INT32 serverVarWrOk; /* Server Variables Write OK */ + ST_INT32 serverVarWrErr; /* Server Variables Write Error */ + ST_INT32 serverInfoRpt; /* Server Information Reports */ + ST_INT32 serverUstatus; /* Server Unsolicited Status */ + } MVL_MMS_STATISTICS; + +extern MVL_MMS_STATISTICS mvl_mms_statistics; + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* MVL INTERNAL DECLARATIONS */ +/************************************************************************/ +/************************************************************************/ + +/* Built in MVL Indication and Confirm functions, typically called */ +/* from "mvlop_en.c" if service is enabled. */ + +ST_VOID _mvl_process_read_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_write_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_ident_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_info_ind (MVL_COMM_EVENT *event); +ST_VOID _mvl_process_status_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_ustatus_ind (MVL_COMM_EVENT *event); +ST_VOID _mvl_process_getnam_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_getvaa_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_getvla_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_getdom_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_fopen_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_fread_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_fclose_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_fdir_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_obtfile_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_fdelete_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_frename_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_jinit_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_jread_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_concl_ind (MVL_COMM_EVENT *event); +ST_VOID _mvl_process_cancel_ind (MVL_COMM_EVENT *event); +ST_VOID _mvl_process_defvlist_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_delvlist_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_jstat_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_initdown_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_download_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_termdown_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_initupl_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_upload_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_termupl_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_deldom_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_crepi_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_delpi_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_start_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_stop_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_resume_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_reset_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_kill_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_getpi_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_getcl_ind (MVL_IND_PEND *ind_pend); + +ST_VOID _mvl_process_read_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_write_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_ident_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_getvar_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_getnam_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_status_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_getdom_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_fopen_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_fread_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_fclose_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_fdir_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_obtfile_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_fdelete_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_frename_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_jinit_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_jread_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_jwrite_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_jstat_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_defvlist_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_getvlist_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_delvlist_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_initdown_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_download_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_termdown_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_initupl_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_upload_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_termupl_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_deldom_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_crepi_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_delpi_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_start_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_stop_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_resume_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_reset_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_kill_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_getpi_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_getcl_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_concl_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_release (MVL_REQ_PEND *req); + +/************************************************************************/ + +ST_VOID mvl_ind_rcvd (MVL_COMM_EVENT *event); +ST_VOID mvl_conf_rcvd (MVL_COMM_EVENT *event); +ST_VOID mvl_cancel_ind_rcvd (MVL_COMM_EVENT *event); +ST_VOID mvl_concl_ind_rcvd (MVL_COMM_EVENT *event); +ST_VOID mvl_concl_conf_rcvd (MVL_REQ_PEND *req_pend); + +ST_VOID _mvl_ind_reject (MVL_IND_PEND *ind); +ST_VOID _mvl_conf_reject (MVL_REQ_PEND *req); +ST_VOID _mvl_send_reject (MVL_COMM_EVENT *event); +ST_RET _mvl_send_error (MVL_COMM_EVENT *event, ST_INT16 eClass, ST_INT16 code); +ST_RET _mvl_send_err_f (MVL_COMM_EVENT *event, ST_INT16 eClass, ST_INT16 code); + +#define mplas_err_resp(indCtrl, eClass, code) _mplas_err_resp(indCtrl, eClass, code) +ST_RET _mplas_err_resp (MVL_IND_PEND *indCtrl, ST_INT16 eClass, ST_INT16 code); + +ST_VOID _mvl_send_resp (MVL_COMM_EVENT *event, ST_RET build_rc); +ST_VOID _mvl_send_resp_i (MVL_IND_PEND *indCtrl, ST_RET build_rc); +ST_RET _mvl_send_req (MVL_NET_INFO *net_info, + MVL_REQ_PEND *req, ST_RET build_rc); + +MVL_VAR_ASSOC *_mvl_objname_to_va (MVL_VMD_CTRL *vmd_ctrl, + MVL_NET_INFO *net_info, + ST_INT service, + OBJECT_NAME *obj, + MVL_SCOPE *va_scope_out, + ST_BOOLEAN alt_access_pres, + ALT_ACCESS *alt_acc, + ST_BOOLEAN *alt_access_done_out); + +/* This function does everything required to send a MMS message - */ +/* adds CLNP/CLTP/HDLC components then does whatever is required to send*/ +/* the complete message. Does not return until done, returns SD_SUCCESS */ +/* or an error code. */ +ST_RET _mvl_send_msg (ST_UCHAR *mms_msg, ST_INT mms_msg_len, MVL_NET_INFO *net_info); + + +/* This function is called to get MMS PDU's that have been received, */ +/* as well as other communications events. Returns a pointer to a */ +/* MMS Comm Event control structure that must be free'd via the */ +ST_BOOLEAN _mvl_net_service (MVL_COMM_EVENT **eventOut); +ST_VOID _mvl_free_comm_event (MVL_COMM_EVENT *event); + +extern ST_BOOLEAN mvl_init_ind_hold; + +/* Functions to manipulate request control list */ +MVL_REQ_PEND *_mvl_get_req_ctrl (MVL_NET_INFO *net_info, ST_INT16 op); +MVL_REQ_PEND *_mvl_find_req_ctrl (MVL_NET_INFO *net_info, + ST_INT op, ST_UINT32 id); +ST_VOID _mvl_set_net_req_done (MVL_REQ_PEND *skip, + MVL_NET_INFO *net_info, ST_RET result); +ST_VOID _mvl_set_req_done (MVL_REQ_PEND *req, ST_RET result); + +/* Alternate Access creation buffer management */ +ST_RET _mvl_get_asn1_aa (ALT_ACCESS *alt_acc, VARIABLE_LIST *vl); + +ST_RET _mvl_concat_filename (ST_CHAR *good_name, ST_INT num_of_fname, + FILE_NAME *fname_arr, ST_INT max_len); + +ST_VOID mvl_log_req (ST_INT opcode, ST_VOID *info); +ST_VOID mvl_log_resp (ST_INT opcode, ST_VOID *info); + +ST_VOID mvl_scope_set (OBJECT_NAME *obj, MVL_SCOPE *mvl_scope_out); + + +/************************************************************************/ + +extern ST_BOOLEAN _mvl_comm_serve_active; + +/************************************************************************/ +/* MVL_OBJ (generic MVL object) */ +/* This structure is used by all the MVL object manipulation functions */ +/* (mvl_obj_insert, mvl_obj_delete, mvl_obj_find, etc.) to represent */ +/* any named object (i.e. Named Variable, Named Variable List, */ +/* Domain, Journal, etc.). */ +/* A pointer to a "real" structure must be cast to (MVL_OBJ *) */ +/* for any call to the functions. */ +/* WARNING: It is assumed that the first item in the "real" structure */ +/* is a pointer to the "name" of the object. */ +/************************************************************************/ + +typedef struct + { + ST_CHAR *name; + } MVL_OBJ; + +/************************************************************************/ + +ST_VOID *_mvl_calloc_os (ST_UINT num, ST_UINT size); +ST_VOID *_mvl_realloc_os (ST_VOID *old, ST_UINT new_size); +ST_VOID _mvl_free_os (ST_VOID *buf); + +/************************************************************************/ +/* MVL object manipulation function prototypes. */ +/************************************************************************/ + +ST_RET mvl_obj_insert (MVL_OBJ **ObjTable, ST_INT *numObj, ST_INT maxObj, + MVL_OBJ *newObj); +MVL_OBJ *mvl_obj_delete (MVL_OBJ **ObjTable, ST_INT *numObj, + ST_CHAR *ObjName); +MVL_OBJ *mvl_obj_find (MVL_OBJ **ObjTable, ST_INT numObj, + ST_CHAR *ObjName); +MVL_OBJ ** mvl_obj_find_key (MVL_OBJ **ObjTable, ST_INT numObj, + ST_CHAR *ObjName); +ST_VOID _mvl_resize_ptr_tbl (ST_INT *p_max_num, + ST_VOID ***p_ptr_tbl, ST_INT new_size); +/************************************************************************/ +/* MVL type derivation functions */ +/************************************************************************/ + +ST_RET mvl_derive_new_type (ST_CHAR *base_name, ST_INT typeIdIn, + ST_INT *typeIdOut, ST_CHAR *handle); +ST_RET mvl_derive_type_members (ST_CHAR *base_name, ST_INT typeIdIn, + ST_UCHAR **membership, ST_RTREF *refs, ST_CHAR *handle); +ST_VOID mvl_print_derived_type( ST_CHAR *base_name, ST_INT typeIdIn, + ST_UCHAR *membership, ST_UCHAR **labels); +ST_RET mvl_add_derived_type( ST_CHAR *base_name, ST_INT typeIdIn, + ST_UCHAR *membership, ST_RTREF *refs, + ST_INT *typeIdOut); +#ifndef __ECOS +ST_BOOLEAN u_mvl_rt_element_supported( RUNTIME_TYPE *rt, + ST_CHAR *element_name, + ST_RTREF *ui, ST_CHAR *handle); +#endif +/************************************************************************/ + +ST_INT mi_connect_ind_fun (MVL_NET_INFO *net_info, + INIT_INFO *init_ind_info, + ACSE_AUTH_INFO *rsp_auth_info); +ST_VOID mi_release_ind_fun (MVL_NET_INFO *mvl_net_info); +ST_VOID mi_abort_ind_fun (MVL_NET_INFO *mvl_net_info); + +ST_VOID _mvl_free_req_pend (ST_VOID); +ST_VOID u_mvl_reject_ind (MVL_NET_INFO *net_info, REJECT_RESP_INFO *rej_info); + +/************************************************************************/ +/* Dynamic type creation functions. */ +/************************************************************************/ +MVL_TYPE_CTRL *mvl_type_ctrl_find (ST_INT TypeId); +MVL_TYPE_CTRL *mvl_type_ctrl_find_dyn (ST_INT TypeId); +ST_INT mvl_type_id_create (ST_CHAR *type_name, ST_UCHAR *asn1_data, ST_UINT asn1_len); +ST_INT mvl_type_id_create_from_tdl (ST_CHAR *type_name, ST_CHAR *tdl); +ST_VOID mvl_type_id_destroy (ST_INT TypeId); +ST_RET mvl_type_id_destroy_all_dyn (ST_VOID); +ST_INT mvl_type_count (ST_VOID); + +/* These take additional "vmd_ctrl" argument. */ +ST_INT mvl_vmd_type_id_create (MVL_VMD_CTRL *vmd_ctrl, ST_CHAR *type_name, RUNTIME_CTRL *rt_ctrl); +ST_RET mvl_vmd_type_id_destroy (MVL_VMD_CTRL *vmd_ctrl, ST_INT TypeId); +ST_RET mvl_vmd_type_id_destroy_all (MVL_VMD_CTRL *vmd_ctrl); +MVL_TYPE_CTRL *mvl_vmd_type_ctrl_find (MVL_VMD_CTRL *vmd_ctrl, ST_INT type_id); + +#define mvlu_install() /* OBSOLETE: For backward compatibility only */ + +/************************************************************************/ +/* Allocation functions/macros. */ +/************************************************************************/ +#define mvl_enc_buf_alloc(size) M_MALLOC (MSMEM_PDU_ENC, size) +#define mvl_enc_buf_free(ptr) M_FREE (MSMEM_PDU_ENC, ptr) + +/************************************************************************/ +/* Miscellaneous functions. */ +/************************************************************************/ +ST_VOID wait_any_event (ST_LONG max_ms_delay); /* called by sync fcts */ + /* user MUST supply this fct*/ +ST_INT mvl_req_bufs_avail (MVL_NET_INFO *net_info); +ST_INT mvl_ureq_bufs_avail (MVL_NET_INFO *net_info); + +/************************************************************************/ +/* Object add/remove functions. */ +/************************************************************************/ +MVL_DOM_CTRL *mvl_vmd_dom_add (MVL_VMD_CTRL *vmd_ctrl, + ST_CHAR *name, + ST_INT max_num_var, + ST_INT max_num_nvl, + ST_INT max_num_jou, + ST_BOOLEAN copy_name); +ST_RET mvl_vmd_dom_remove (MVL_VMD_CTRL *vmd_ctrl, ST_CHAR *dom_name); + +MVL_VAR_ASSOC *mvl_vmd_var_add (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info, + ST_INT type_id, + ST_VOID *data, + MVL_VAR_PROC *proc, + ST_BOOLEAN copy_name); +MVL_VAR_ASSOC *mvl_var_add_alloc (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info, + ST_INT type_id, + MVL_VAR_PROC *proc); +ST_RET mvl_vmd_var_remove (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); + +MVL_NVLIST_CTRL *mvl_vmd_nvl_add (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *nvl_obj, + MVL_NET_INFO *net_info, + ST_INT num_var, + OBJECT_NAME *var_obj, /* array of var names */ + ST_BOOLEAN copy_name); +ST_RET mvl_vmd_nvl_remove (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); + +MVL_JOURNAL_CTRL *mvl_vmd_jou_add (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info, + ST_BOOLEAN copy_name); +ST_RET mvl_vmd_jou_remove (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); + +/************************************************************************/ +/* Object insert/delete functions. */ +/************************************************************************/ +ST_RET mvl_vmd_dom_insert (MVL_VMD_CTRL *vmd_ctrl, + MVL_DOM_CTRL *dom); +MVL_DOM_CTRL *mvl_vmd_dom_delete (MVL_VMD_CTRL *vmd_ctrl, ST_CHAR *dom_name); + +ST_RET mvl_vmd_var_insert (MVL_VMD_CTRL *vmd_ctrl, + MVL_VAR_ASSOC *va, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); /* Only used if AA_SPEC */ +MVL_VAR_ASSOC *mvl_vmd_var_delete (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); + +ST_RET mvl_vmd_nvl_insert (MVL_VMD_CTRL *vmd_ctrl, + MVL_NVLIST_CTRL *nvl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); /* Only used if AA_SPEC */ +MVL_NVLIST_CTRL *mvl_vmd_nvl_delete (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); /* Only used if AA_SPEC */ + +ST_RET mvl_vmd_jou_insert (MVL_VMD_CTRL *vmd_ctrl, + MVL_JOURNAL_CTRL *jou, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); /* Only used if AA_SPEC */ +MVL_JOURNAL_CTRL *mvl_vmd_jou_delete (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); + + +/************************************************************************/ +/* Object "find" functions. */ +/************************************************************************/ +MVL_DOM_CTRL *mvl_vmd_find_dom (MVL_VMD_CTRL *vmd_ctrl, + ST_CHAR *name); +MVL_DOM_CTRL *mvl_vmd_dom_find_last (MVL_VMD_CTRL *vmd_ctrl); +MVL_VAR_ASSOC *mvl_vmd_find_var (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); /* Only used if AA_SPEC */ +MVL_NVLIST_CTRL *mvl_vmd_find_nvl (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); /* Only used if AA_SPEC */ +MVL_JOURNAL_CTRL *mvl_vmd_find_jou (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); /* Only used if AA_SPEC */ + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* MVL_DEFS_INCLUDED */ +/************************************************************************/ + diff --git a/include/inc/mvl_log.h b/include/inc/mvl_log.h new file mode 100644 index 0000000..49f092b --- /dev/null +++ b/include/inc/mvl_log.h @@ -0,0 +1,198 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2002, All Rights Reserved. */ +/* */ +/* MODULE NAME : mvl_log.h */ +/* PRODUCT(S) : Tool */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/22/08 JRB 14 Del unused MVLULOG_TIMING macros. */ +/* 04/09/07 MDE 13 Enhanced filtered logging */ +/* 09/12/05 JRB 12 Added more ERR, NERR macros */ +/* 07/13/05 MDE 11 Added more CNERR macros */ +/* 08/12/04 JRB 10 Fix MVLU_LOG_CTIMING.. macros. */ +/* 12/12/02 JRB 09 Use new "Base" macros SLOG_*, SLOGC_*, SLOGH.*/ +/* 07/31/01 MDE 08 Added mvl_conn_filtered_logging */ +/* 03/28/01 JRB 07 Add ..ACSEDATA3 macro. */ +/* 03/22/01 GLB 06 Added: MVLULOG_DEBUG, MVLULOG_TIMING */ +/* 12/13/99 JRB 05 Delete ";" from non-debug macros. Get extra */ +/* ";" when expanded (doesn't always compile). */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 09/07/99 MDE 03 Added FLOW3, CFLOW3 macros */ +/* 10/08/98 MDE 02 Migrated to updated SLOG interface */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#ifndef MVL_LOG_INCLUDED +#define MVL_LOG_INCLUDED + +#include "slog.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/* MMS-EASE Lite logging control */ + +#define MVLLOG_ERR 0x00000001 +#define MVLLOG_NERR 0x00000002 +#define MVLLOG_ACSE 0x00000040 +#define MVLLOG_ACSEDATA 0x00000080 +#define MVLULOG_FLOW 0x00000200 +#define MVLULOG_DEBUG 0x00000400 + + +/* For backward compatability only */ +#define mvl_log_mask mvl_debug_sel +extern ST_UINT mvl_debug_sel; + +/* Allows filtering of ACSE data logging by connection */ +extern ST_BOOLEAN mvl_conn_filtered_logging; + +/* Log type strings */ +extern SD_CONST ST_CHAR *SD_CONST _mvllog_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mvllog_nerr_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mvllog_acse_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mvllog_acsedata_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mvlulog_flow_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mvlulog_debug_logstr; + + +/*********************** ERR Macros *************************************/ +#define MVL_LOG_ERR0(a) \ + SLOG_0 (mvl_debug_sel & MVLLOG_ERR,_mvllog_err_logstr,a) +#define MVL_LOG_ERR1(a,b) \ + SLOG_1 (mvl_debug_sel & MVLLOG_ERR,_mvllog_err_logstr,a,b) +#define MVL_LOG_ERR2(a,b,c) \ + SLOG_2 (mvl_debug_sel & MVLLOG_ERR,_mvllog_err_logstr,a,b,c) +#define MVL_LOG_ERR3(a,b,c,d) \ + SLOG_3 (mvl_debug_sel & MVLLOG_ERR,_mvllog_err_logstr,a,b,c,d) +#define MVL_LOG_ERR4(a,b,c,d,e) \ + SLOG_4 (mvl_debug_sel & MVLLOG_ERR,_mvllog_err_logstr,a,b,c,d,e) +#define MVL_LOG_ERR5(a,b,c,d,e,f) \ + SLOG_5 (mvl_debug_sel & MVLLOG_ERR,_mvllog_err_logstr,a,b,c,d,e,f) + +#define MVL_LOG_CERR0(a) \ + SLOGC_0 (mvl_debug_sel & MVLLOG_ERR,a) +#define MVL_LOG_CERR1(a,b) \ + SLOGC_1 (mvl_debug_sel & MVLLOG_ERR,a,b) +#define MVL_LOG_CERR2(a,b,c) \ + SLOGC_2 (mvl_debug_sel & MVLLOG_ERR,a,b,c) +#define MVL_LOG_CERR3(a,b,c,d) \ + SLOGC_3 (mvl_debug_sel & MVLLOG_ERR,a,b,c,d) +#define MVL_LOG_CERR4(a,b,c,d,e) \ + SLOGC_4 (mvl_debug_sel & MVLLOG_ERR,a,b,c,d,e) +#define MVL_LOG_CERR5(a,b,c,d,e,f) \ + SLOGC_5 (mvl_debug_sel & MVLLOG_ERR,a,b,c,d,e,f) + + +/*********************** NERR Macros *************************************/ + +#define MVL_LOG_NERR0(a) \ + SLOG_0 (mvl_debug_sel & MVLLOG_NERR,_mvllog_nerr_logstr,a) +#define MVL_LOG_NERR1(a,b) \ + SLOG_1 (mvl_debug_sel & MVLLOG_NERR,_mvllog_nerr_logstr,a,b) +#define MVL_LOG_NERR2(a,b,c) \ + SLOG_2 (mvl_debug_sel & MVLLOG_NERR,_mvllog_nerr_logstr,a,b,c) +#define MVL_LOG_NERR3(a,b,c,d) \ + SLOG_3 (mvl_debug_sel & MVLLOG_NERR,_mvllog_nerr_logstr,a,b,c,d) +#define MVL_LOG_NERR4(a,b,c,d,e) \ + SLOG_4 (mvl_debug_sel & MVLLOG_NERR,_mvllog_nerr_logstr,a,b,c,d,e) +#define MVL_LOG_NERR5(a,b,c,d,e,f) \ + SLOG_5 (mvl_debug_sel & MVLLOG_NERR,_mvllog_nerr_logstr,a,b,c,d,e,f) + +#define MVL_LOG_CNERR0(a) \ + SLOGC_0 (mvl_debug_sel & MVLLOG_NERR,a) +#define MVL_LOG_CNERR1(a,b) \ + SLOGC_1 (mvl_debug_sel & MVLLOG_NERR,a,b) +#define MVL_LOG_CNERR2(a,b,c) \ + SLOGC_2 (mvl_debug_sel & MVLLOG_NERR,a,b,c) +#define MVL_LOG_CNERR3(a,b,c,d) \ + SLOGC_3 (mvl_debug_sel & MVLLOG_NERR,a,b,c,d) +#define MVL_LOG_CNERR4(a,b,c,d,e) \ + SLOGC_4 (mvl_debug_sel & MVLLOG_NERR,a,b,c,d,e) +#define MVL_LOG_CNERR5(a,b,c,d,e,f) \ + SLOGC_5 (mvl_debug_sel & MVLLOG_NERR,a,b,c,d,e,f) + +/*********************** ACSE Macros *************************************/ + +#define MVL_LOG_ACSE0(a) \ + SLOG_0 (mvl_debug_sel & MVLLOG_ACSE,_mvllog_acse_logstr,a) +#define MVL_LOG_ACSE1(a,b) \ + SLOG_1 (mvl_debug_sel & MVLLOG_ACSE,_mvllog_acse_logstr,a,b) + + +#define MVL_LOG_CACSE0(a) \ + SLOGC_0 (mvl_debug_sel & MVLLOG_ACSE,a) +#define MVL_LOG_CACSE1(a,b) \ + SLOGC_1 (mvl_debug_sel & MVLLOG_ACSE,a,b) + + +#define MVL_LOG_ACSEDATA1(a,b) \ + SLOG_1 (mvl_debug_sel & MVLLOG_ACSEDATA,_mvllog_acsedata_logstr,a,b) +#define MVL_LOG_ACSEDATA2(a,b,c) \ + SLOG_2 (mvl_debug_sel & MVLLOG_ACSEDATA,_mvllog_acsedata_logstr,a,b,c) +#define MVL_LOG_ACSEDATA3(a,b,c,d) \ + SLOG_3 (mvl_debug_sel & MVLLOG_ACSEDATA,_mvllog_acsedata_logstr,a,b,c,d) + + +#define MVL_LOG_ACSEDATAH(a,b) \ + SLOGH (mvl_debug_sel & MVLLOG_ACSEDATA,a,b) + + +/*********************** MVLU FLOW Macros *******************************/ + +#define MVLU_LOG_FLOW0(a) \ + SLOG_0 (mvl_debug_sel & MVLULOG_FLOW,_mvlulog_flow_logstr,a) +#define MVLU_LOG_FLOW1(a,b) \ + SLOG_1 (mvl_debug_sel & MVLULOG_FLOW,_mvlulog_flow_logstr,a,b) +#define MVLU_LOG_FLOW2(a,b,c) \ + SLOG_2 (mvl_debug_sel & MVLULOG_FLOW,_mvlulog_flow_logstr,a,b,c) +#define MVLU_LOG_FLOW3(a,b,c,d) \ + SLOG_3 (mvl_debug_sel & MVLULOG_FLOW,_mvlulog_flow_logstr,a,b,c,d) + + +#define MVLU_LOG_CFLOW0(a) \ + SLOGC_0 (mvl_debug_sel & MVLULOG_FLOW,a) +#define MVLU_LOG_CFLOW1(a,b) \ + SLOGC_1 (mvl_debug_sel & MVLULOG_FLOW,a,b) +#define MVLU_LOG_CFLOW2(a,b,c) \ + SLOGC_2 (mvl_debug_sel & MVLULOG_FLOW,a,b,c) +#define MVLU_LOG_CFLOW3(a,b,c,d) \ + SLOGC_3 (mvl_debug_sel & MVLULOG_FLOW,a,b,c,d) + + +/*********************** MVLU DEBUG Macros *******************************/ + +#define MVLU_LOG_DEBUG0(a) \ + SLOG_0 (mvl_debug_sel & MVLULOG_DEBUG,_mvlulog_debug_logstr,a) +#define MVLU_LOG_DEBUG1(a,b) \ + SLOG_1 (mvl_debug_sel & MVLULOG_DEBUG,_mvlulog_debug_logstr,a,b) +#define MVLU_LOG_DEBUG2(a,b,c) \ + SLOG_2 (mvl_debug_sel & MVLULOG_DEBUG,_mvlulog_debug_logstr,a,b,c) +#define MVLU_LOG_DEBUG3(a,b,c,d) \ + SLOG_3 (mvl_debug_sel & MVLULOG_DEBUG,_mvlulog_debug_logstr,a,b,c,d) + + +#define MVLU_LOG_CDEBUG0(a) \ + SLOGC_0 (mvl_debug_sel & MVLULOG_DEBUG,a) +#define MVLU_LOG_CDEBUG1(a,b) \ + SLOGC_1 (mvl_debug_sel & MVLULOG_DEBUG,a,b) +#define MVLU_LOG_CDEBUG2(a,b,c) \ + SLOGC_2 (mvl_debug_sel & MVLULOG_DEBUG,a,b,c) +#define MVLU_LOG_CDEBUG3(a,b,c,d) \ + SLOGC_3 (mvl_debug_sel & MVLULOG_DEBUG,a,b,c,d) + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/inc/mvl_uca.h b/include/inc/mvl_uca.h new file mode 100644 index 0000000..df3aa8d --- /dev/null +++ b/include/inc/mvl_uca.h @@ -0,0 +1,898 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2002, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_uca.h */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/27/09 JRB 39 Add funct ptrs u_mvl_wr_ind_var_start/end. */ +/* 07/23/08 JRB 38 Move some defs to mvl_defs.h (need earlier). */ +/* Add mvl61850_objref_create. */ +/* 06/30/08 JRB 37 MVL_SBO_CTRL: repl cmd_executing w/ ctlState.*/ +/* Add MVL61850_CTLSTATE_* for setting ctlState.*/ +/* Increase size of sbo_var for IEC 61850. */ +/* MVL61850_BRCB_CTRL: Add lastSentTimeOfEntry. */ +/* 05/15/08 JRB 36 Add mvl61850_integrity_timeout for 61850 only*/ +/* 05/08/08 JRB 35 Add ctlModel to MVL_SBO_CTRL. */ +/* 05/06/08 JRB 34 Add cmd_executing to MVL_SBO_CTRL. */ +/* 03/03/08 JRB 33 Add mvl61850_ctl_req_done. */ +/* Add sboClass to MVL_SBO_CTRL. */ +/* Add MVL61850_SBOCLASS_* defines. */ +/* 11/12/07 MDE 32 Moved MMSOP_RDWR_USR_HANDLED to mms_def2.h */ +/* 03/07/07 JRB 31 Add mvlu_get_leaf_val_int_any. */ +/* 02/26/07 JRB 30 initSboCtrl: add use_ms_timer arg. */ +/* MVL_SBO_CTRL: add millisecond timer support. */ +/* 02/13/07 JRB 29 mvl61850_get_rcb: del unused net_info arg. */ +/* Add scan timers to MVL_RPT_CTRL. Add helper fct*/ +/* 11/30/06 JRB 28 Fix *_brcb_entryid_init so user can call it. */ +/* 11/21/06 JRB 27 Add mvl61850_ctl_lastapplerror_send. */ +/* Move ..LAST_APPL_ERROR def to mvl_defs.h. */ +/* 10/10/06 JRB 26 Add mvlu_set_leaf_param_name2. */ +/* 09/27/06 MDE 25 Added MMSOP_RDWR_USR_HANDLED for IOS */ +/* 08/09/06 JRB 24 MVL61850_BRCB_CTRL, BUFLIST_ENTRY: big changes.*/ +/* Add mvl61850_create(free)_rpt_ctrl, */ +/* mvl61850_rpt_service, */ +/* mvl61850_rpt_dataset_create(destroy). */ +/* Chg EntryID storage from ST_INT to Ostring. */ +/* Del obsolete MVLU_RPT_VA_CTRL. */ +/* Chg/add/del several internal report functions.*/ +/* Add vstring129 to MVLU_RPT_TYPEIDS. */ +/* 08/09/06 JRB 23 Fix MVL61850_MAX_OBJREF_LEN per Tissue 141. */ +/* 03/27/06 JRB 22 Add more mvlu_get_leaf_* functions. */ +/* 09/12/05 JRB 21 Add mvl61850_ctl_chk_sbow. */ +/* 07/11/05 JRB 20 Add more "mvl61850_ctl_*" functions. */ +/* 06/27/05 JRB 19 Del mvlu_rpt_nvl_add/destroy. */ +/* 06/27/05 JRB 18 _mvlu_get_rd_rcb: add (MVLU_RPT_CLIENT **) arg.*/ +/* MVL61850_BRCB_CTRL: Add lastSentEntryID. */ +/* 05/27/05 CRM 17 Add mvlu_rpt_destroy_scan_ctrl. */ +/* 05/09/05 JRB 16 Define MVLU_LEAF_FUN_LOOKUP_ENABLE by default*/ +/* 12/09/04 JRB 15 Add "MVL61850_CTLMODEL_*" defines. */ +/* Add MVL61850_LAST_APPL.. struct. */ +/* Add mvlu_trim_branch_name, mvlu_find_comp_type,*/ +/* mvlu_get_leaf_val_*. */ +/* Add mvl61850_ctl_chk_sbo, mvl61850_ctl_chk_state.*/ +/* Add initSboCtrl. */ +/* 09/20/04 JRB 14 More SBO changes for IEC 61850. */ +/* 08/30/04 JRB 13 Add mvlu_sbo_chk_* prototypes. */ +/* 07/06/04 JRB 12 Add mvlu_rpt_create_scan_ctrl2 proto. */ +/* 06/30/04 JRB 11 Add "prim_num", "prim_offset_base" to */ +/* MVLU_RD_VA_CTRL, MVLU_WR_VA_CTRL. */ +/* Del global var mvluUseStaticData. */ +/* Del SCL parsing functions & related structs: */ +/* mvl61850_ln_create_start, mvl61850_do_create,*/ +/* mvl61850_da_create, mvl61850_ln_create_finish,*/ +/* & mvl61850_ln_destroy. New SCL standard */ +/* makes these obsolete. */ +/* 05/13/04 JRB 10 Add SqNumInt16u to MVLU_BASRCB. */ +/* Add define MVL61850_MAX_OBJREF_LEN. */ +/* 04/20/04 JRB 09 Add TRGOPS_BITNUM_* defines. */ +/* 12/17/03 JRB 08 61850-8-1 FDIS changes: */ +/* MVLU_BASRCB: Add TimeofEntry for 61850 BRCB. */ +/* Add OPTFLD_BITNUM_CONFREV = 8. */ +/* Chg OPTFLD_BITNUM_SUBSEQNUM from 8 to 9. */ +/* Increase MVLU_MAX_RPT_OPTS to 11. */ +/* 04/22/03 JRB 07 Add comments to dynamic 61850 type functs. */ +/* 04/17/03 JRB 06 Add mvlu_setup_scan_read. */ +/* 04/04/03 JRB 05 Fix integrity/GI scan code so multiple */ +/* concurrent scans don't corrupt one another. */ +/* u_mvlu_rpt_scan_done deleted. */ +/* 03/13/03 JRB 04 Add funcs for 61850 dynamic type creation. */ +/* Add 61850 URCB support. */ +/* MVLU_RPT_TYPEIDS: Use clearer member names. */ +/* MVLU_RPT_CTRL: Del inclusion_data & all */ +/* MVL_VAR_ASSOC vars. */ +/* MVLU_BASRCB: Add "Resv". */ +/* ucaName: Chg from ptr to array. */ +/* mvlu_proc_rt_type: Chg to use RUNTIME_CTRL. */ +/* TrgOps: Chg to Bvstring (variable len). */ +/* MVLU_RPT_CLIENT: add/delete members. */ +/* Add mvlu_integrity_timeout funct. */ +/* 12/17/02 JRB 03 Chg prefix to "MVLU_STR:" */ +/* Del all *typeId globals, use MVLU_RPT_TYPEIDS*/ +/* 12/14/02 JRB 02 Chg mvlu_create_rpt_ctrl, mvlu_send_report args*/ +/* Add mvlu_integrity_scan_* functions. */ +/* Add callback funct u_mvlu_rpt_time_get. */ +/* Chg OptFlds to BVstring9, add "bitnum" defines*/ +/* Add defs, protos, etc. fof IEC-61850. */ +/* Add ConfRev, EntryID to MVLU_BASRCB */ +/* Add scan_read_ind to MVLU_RPT_CLIENT */ +/* Add MVLU_RPT_TYPEIDS */ +/* Del rptTim_data, rptTim_va, rptTim_typeId */ +/* Del outDat_data, outDat_va, outDat_typeId */ +/* 12/10/02 JRB 01 Created from defs moved here from mvl_defs.h */ +/************************************************************************/ +#ifndef MVL_UCA_INCLUDED +#define MVL_UCA_INCLUDED + +#include "mvl_defs.h" /* This uses many common MVL definitions. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Max number of mandatory and optional variables in IEC/UCA report. + * IEC & UCA share RPT code, so max must accomodate both. + * Includes RptID, OptFlds, SqNum, RptTim, OutDat (DataSetNa), + * & InclusionBitstring (plus BufOvfl, SubSeqNum, MoreSegmentsFollow, + * EntryId, & ConfRev for IEC only). + */ +#define MVLU_MAX_RPT_OPTS 11 + +/* Defines for IEC 61850 control model. */ +#define MVL61850_CTLMODEL_STATUS_ONLY 0 +#define MVL61850_CTLMODEL_DIRECT_NORMAL 1 +#define MVL61850_CTLMODEL_SBO_NORMAL 2 +#define MVL61850_CTLMODEL_DIRECT_ENHANCED 3 +#define MVL61850_CTLMODEL_SBO_ENHANCED 4 + +#define MVL61850_SBOCLASS_OPERATE_ONCE 0 +#define MVL61850_SBOCLASS_OPERATE_MANY 1 + +#define MVL61850_CTLSTATE_UNSELECTED 0 /* SBO only */ +#define MVL61850_CTLSTATE_READY 1 +#define MVL61850_CTLSTATE_WAIT_ACTIVATION_TIME 2 +#define MVL61850_CTLSTATE_WAIT_CHANGE 3 /* enhanced only*/ + +/* renxiaobao ±¨¸æ + ¿ØÖÆ´íÎ󱨸æµÄ¸½¼ÓÔ­ÒòÕï¶Ï(AddCause) + #define NO_ERROR 0 +*/ +#define ServiceError_type 1 /* 7-2±í5Öж¨ÒåµÄ²î´í*/ +#define Blocked_CB 2 /* ±»¿ª¹Ø±ÕËø (Blocked-by-switching-hierarchy) */ +#define Select_fail 3 /* Ñ¡Ôñʧ°Ü (Select-failed)*/ +#define Invalid_Pos 4 /* ²»ÕýȷλÖà (Invalid-position) */ +#define Position_reached 5 /* ¿ª¹ØÒÑ´¦ÓÚÆÚÍûµÄλÖà (Position-reached) */ +#define Parameter_change 6 /* Ö´ÐÐÖвÎÊý¸Ä±ä (Parameter-change-in-execution) */ +#define Step_limit 7 /* ²½ÏÞÖÆ,·Ö½ÓÍ·µÄλÖÃÒÑ´ïµ½ÉÏ/ÏÂÏÞ (Step-limit) */ +#define Blocked_by_Mode 8 /* LN(CSWI¡¢XCBRµÈ)´¦ÓÚ²»ÔÊÐíµÄ²Ù×÷ģʽ (Blocked-by-Mode)*/ +#define Blocked_by_process 9 /* ÓÉÓÚ¹ý³Ì²ãµÄÍⲿʼþ×èÖ¹³É¹¦²Ù×÷ (Blocked-by-process) */ +#define Blocked_by_interlocking 10 /* ÓÉÓÚ¿ª¹ØÉ豸»¥Ëø,±ÕËø¿ØÖƶ¯×÷ (Blocked-by-interlocking) */ +#define Blocked_by_synchrocheck 11 /* ÓÉÓÚ³¬Ê±»òͬÆÚÌõ¼þ²»Âú×ã,ÖÕÖ¹¿ØÖÆ (Blocked-by-synchrocheck) */ +#define Command_already 12 /* ÃüÁîÒѾ­ÔÚÖ´ÐÐÖÐ (Command-already-in-execution)*/ +#define Blocked_by_health 13 /* ±»½¡¿µ×´¿öËù±ÕËø (Blocked-by-health) */ +#define n_of_1_control 14 /* ÓÉÓÚÆäËû¿ØÖƶ¯×÷ÒÑÔËÐÐ,±ÕËø¿ØÖÆ (1-of-n-control) */ +#define Abortion_by_cancel 15 /* ±»Cancel·þÎñÖÐÖ¹ (Abortion-by-cancel) */ +#define Time_limit_over 16 /* ÓÉÓÚ³¬Ê±,ÖÕÖ¹¿ØÖƶ¯×÷ (Time-limit-over) */ +#define Abortion_by_trip 17 /* ÓÉÓÚ±£»¤ÌøÕ¢,ÖÕÖ¹¿ØÖÆ (Abortion-by-trip) */ +#define Object_not_selected 18 /* ¶ÔÏóδ±»Ñ¡Ôñ (Object-not-selected) */ +/*À뿪WaitForChange״̬֮ºó*/ +#define OPERATE_ONCE 0 /* Èç¹ûsboClassΪoperate_once,ÐÂ״̬ΪδѡÔñµÄ*/ +#define OPERATE_MANY 1 /* Èç¹ûsboClassΪoperate_many,ÐÂ״̬Ϊ׼±¸¾ÍÐ÷*/ + +#define WaitForChangeTimer 5000 +/************************************************************************/ +/* UCA SPECIFIC DATA ELEMENTS */ +/************************************************************************/ + +typedef struct mvlu_rd_va_ctrl + { + MVL_IND_PEND *indCtrl; + MVLAS_RD_VA_CTRL *rdVaCtrl; + RUNTIME_TYPE *rt; +#if defined(MVL_UCA) +#if defined(MVL_XNAME) + ST_CHAR xName[MAX_IDENT_LEN+1]; +#endif + ST_CHAR *primData; + ST_RTREF primRef; + ST_UINT prim_num; /* index to data */ + ST_UINT prim_offset_base; /* mem offset from start of "base" var */ +#endif /* defined(MVL_UCA) */ + } MVLU_RD_VA_CTRL; + +typedef struct mvlu_wr_va_ctrl + { + MVL_IND_PEND *indCtrl; + MVLAS_WR_VA_CTRL *wrVaCtrl; + RUNTIME_TYPE *rt; +#if defined(MVL_UCA) +#if defined(MVL_XNAME) + ST_CHAR xName[MAX_IDENT_LEN+1]; +#endif + ST_CHAR *primData; + ST_RTREF primRef; + ST_UINT prim_num; /* index to data */ + ST_UINT prim_offset_base; /* mem offset from start of "base" var */ +#endif /* defined(MVL_UCA) */ + } MVLU_WR_VA_CTRL; + +ST_VOID mvlu_wr_prim_done (MVLU_WR_VA_CTRL *mvluWrVaCtrl, ST_RET rc); +ST_VOID mvlu_rd_prim_done (MVLU_RD_VA_CTRL *mvluRdVaCtrl, ST_RET rc); +ST_VOID mvlu_read_ind (MVL_IND_PEND *indCtrl); + +/* These function pointers are invoked to initialize the va->data */ +/* element for each VariableAssociation required to handle the MMS */ +/* indication. */ + +extern ST_VOID(*mvluAsyncWrIndFun)(struct mvlu_wr_va_ctrl *mvluWrVaCtrl); + +/* Alternate leaf handler function pointers */ +extern ST_VOID (*u_mvlu_leaf_rd_ind_fun)(MVLU_RD_VA_CTRL *mvluRdVaCtrl); +extern ST_VOID (*u_mvlu_leaf_wr_ind_fun)(MVLU_WR_VA_CTRL *mvluWrVaCtrl); + +/* Finding and setting leaf access parameters */ +RUNTIME_TYPE *mvlu_find_rt_leaf (ST_INT type_id, ST_CHAR *leafName); + +#define MVLU_SET_RD_FUN 0x01 +#define MVLU_SET_WR_FUN 0x02 +#define MVLU_SET_REF 0x04 +#define MVLU_SET_ALL (MVLU_SET_RD_FUN | MVLU_SET_WR_FUN | MVLU_SET_REF) + +ST_RET mvlu_set_leaf_param (ST_INT setFlags, ST_CHAR *leafName, + ST_RTINT rdIndFunIndex, ST_RTINT wrIndFunIndex, + ST_RTREF ref); + + +/************************************************************************/ +/************************************************************************/ +/* Leaf Access Function Tables. To be supplied by the user. */ + +/* Comment the following line out to compile out the Foundry supplied */ +/* Leaf Access function pointer tables, so custom tables can be used */ +/*#define MVLU_USR_FUN_TBLS */ + +/* Remove this MVLU_LEAF_FUN_LOOKUP_ENABLE define to save memory, + * but ONLY IF NOT mapping leaf functions at run-time (i.e. not calling + * mvlu_set_leaf_param_name or mvlu_find_rd(wr)_ind_fun_index). + * NOTE: this define is required if SCL configuration is used. + */ +#define MVLU_LEAF_FUN_LOOKUP_ENABLE + +typedef struct + { +#if defined MVLU_LEAF_FUN_LOOKUP_ENABLE + ST_CHAR *fun_name; +#endif + ST_VOID (*fun_ptr) (MVLU_RD_VA_CTRL *rdCtrl); + } MVLU_RD_FUN_INFO; +extern MVLU_RD_FUN_INFO mvluRdFunInfoTbl[]; +extern ST_INT mvluNumRdFunEntries; + +typedef struct + { +#if defined MVLU_LEAF_FUN_LOOKUP_ENABLE + ST_CHAR *fun_name; +#endif + ST_VOID (*fun_ptr) (MVLU_WR_VA_CTRL *wrCtrl); + } MVLU_WR_FUN_INFO; +extern MVLU_WR_FUN_INFO mvluWrFunInfoTbl[]; +extern ST_INT mvluNumWrFunEntries; + +/* Useful for flexible initialization of leaf function tables */ +#if defined MVLU_LEAF_FUN_LOOKUP_ENABLE +#define _MVLU_LEAF_FUN_INIT(_funName) #_funName, _funName +#else +#define _MVLU_LEAF_FUN_INIT(_funName) _funName +#endif +ST_RTINT mvlu_find_rd_ind_fun_index (ST_CHAR *funName); +ST_RTINT mvlu_find_wr_ind_fun_index (ST_CHAR *funName); + + +/************************************************************************/ + +ST_RET mvlu_set_leaf_param_name (ST_INT setFlags, ST_CHAR *leafName, + ST_CHAR *rdIndFunName, ST_CHAR *wrIndFunName, + ST_CHAR *refString); +ST_RET mvlu_set_leaf_param_name2 (ST_INT base_var_type_id, + ST_INT setFlags, + ST_CHAR *leafName, + ST_CHAR *rdIndFunName, + ST_CHAR *wrIndFunName, + ST_CHAR *refString); +ST_RET mvlu_load_xml_leaf_file (ST_CHAR *fileName); +ST_RET u_mvlu_resolve_leaf_ref (ST_CHAR *leafName, ST_INT *setFlags, + ST_CHAR *refText, ST_RTREF *refOut); + +/* Prefix to use in XML LAP file, or when calling "mvlu_set_leaf_param_name" + * if you want a quoted string to be saved as the Reference. + * Following this is the string to be saved. + * This is used for SBO select, in which case the saved string must be + * the name of the protected element. Foundry and the sample "reference + * resolve leaf" function look for this prefix. + */ +#define MVLU_STRING_REF_PREFIX "MVLU_STR:" + +/* Internal */ +ST_VOID _mvlu_null_read_ind (MVLU_RD_VA_CTRL *mvluRdVaCtrl); +ST_VOID _mvlu_null_write_ind (MVLU_WR_VA_CTRL *mvluWrVaCtrl); + + + +typedef struct + { + ST_CHAR ucaName [MAX_IDENT_LEN+1]; + RUNTIME_TYPE *rt; + ST_INT sortedNum; + ST_INT rtIndex; + } MVLU_UCA_NAME_CTRL; + +ST_RET mvlu_proc_rt_type (ST_CHAR *typeName, RUNTIME_CTRL *rtCtrl, + MVLU_UCA_NAME_CTRL **ucaNamesOut); + +/************************************************************************/ +/************************************************************************/ +/* UCA REPORT CONTROL */ +/************************************************************************/ + +#define MVLU_RPT_NUM_VA_DATA_BUF 3 + +/* TrgOpsvalues, also used as Reason values */ +#define MVLU_TRGOPS_DATA 0x40 +#define MVLU_TRGOPS_QUALITY 0x20 +#define MVLU_TRGOPS_FREEZE 0x10 +#define MVLU_TRGOPS_INTEGRITY 0x08 /* Bit 4 */ +#define MVLU_TRGOPS_GI 0x04 /* Bit 5 */ + +/* OptFlds bit masks */ +#define MVLU_SQNUM_MASK 0x40 +#define MVLU_RPTTIM_MASK 0x20 +#define MVLU_REASONS_MASK 0x10 +#define MVLU_OUTDAT_MASK 0x08 + +/* TrgOps bit numbers for IEC-61850. */ +/* Use "bit" macros (BSTR_BIT_*) to access each individual bit. */ +#define TRGOPS_BITNUM_RESERVED 0 +#define TRGOPS_BITNUM_DATA_CHANGE 1 /* "dchg" in some specs */ +#define TRGOPS_BITNUM_QUALITY_CHANGE 2 /* "qchg" in some specs */ +#define TRGOPS_BITNUM_DATA_UPDATE 3 /* "dupd" in some specs */ +#define TRGOPS_BITNUM_INTEGRITY 4 /* "period" in 61850-6 */ +#define TRGOPS_BITNUM_GENERAL_INTERROGATION 5 + +/* OptFlds bit numbers for IEC-61850. */ +/* Use "bit" macros (BSTR_BIT_*) to access each individual bit. */ +/* NOTE: DATSETNAME in IEC-61850 same as OUTDAT in UCA. */ +/* NOTE: bit numbers 1 thru 4 correspond to the masks MVLU_SQNUM_MASK, */ +/* MVLU_RPTTIM_MASK, MVLU_REASONS_MASK, MVLU_OUTDAT_MASK above. */ +/* Bit masks don't work well beyond 8 bits. */ +#define OPTFLD_BITNUM_RESERVED 0 +#define OPTFLD_BITNUM_SQNUM 1 +#define OPTFLD_BITNUM_TIMESTAMP 2 +#define OPTFLD_BITNUM_REASON 3 +#define OPTFLD_BITNUM_DATSETNAME 4 +#define OPTFLD_BITNUM_DATAREF 5 +#define OPTFLD_BITNUM_BUFOVFL 6 +#define OPTFLD_BITNUM_ENTRYID 7 +#define OPTFLD_BITNUM_CONFREV 8 +#define OPTFLD_BITNUM_SUBSEQNUM 9 /* segmentation in 61850-8-1*/ + +/* Flags to pass as "rcb_type" arg to mvlu_create_rpt_ctrl. */ +/* Saved in "rcb_type" parameter of MVLU_RPT_CTRL. */ +#define RCB_TYPE_UCA 0 +#define RCB_TYPE_IEC_BRCB 1 +#define RCB_TYPE_IEC_URCB 2 + +/* Flags to pass as "buftim_action" arg to mvlu_create_rpt_ctrl. */ +/* Saved in "buftim_action" parameter of MVLU_RPT_CTRL. */ +#define MVLU_RPT_BUFTIM_REPLACE 0 +#define MVLU_RPT_BUFTIM_SEND_NOW 1 + +/* Basic Report Control Block data */ +typedef struct + { + ST_BOOLEAN RptEna; + ST_BOOLEAN Resv; /* Used only for 61850 URCB. */ + ST_CHAR RptID[MVL61850_MAX_RPTID_LEN+1]; + /* NOTE: DatSetNa is shorter for UCA, but bigger buffer shouldn't hurt.*/ + ST_CHAR DatSetNa[MVL61850_MAX_OBJREF_LEN+1]; + struct /* BVstring */ + { + ST_INT16 len_1; + ST_UCHAR data_1[2]; /* BVstring9 - need 2 bytes */ + } OptFlds; + ST_UINT32 BufTim; + ST_UINT16 Trgs; + ST_UINT8 SqNum; /* Used for UCA & 61850 URCB */ + ST_UINT16 SqNumInt16u; /* Used for 61850 BRCB */ + struct /* BVstring */ + { + ST_INT16 len; + ST_UCHAR data[1]; /* BVstring8 - need 1 byte */ + } TrgOps; + ST_UINT32 RBEPd; + ST_UINT32 IntgPd; + ST_UINT32 ConfRev; /* Used only for 61850 BRCB/URCB. */ + ST_UCHAR EntryID[8]; /* Used only for 61850 BRCB (Ostring8). */ + MMS_BTIME6 TimeofEntry; /* Used only for 61850 BRCB. */ + } MVLU_BASRCB; + +/* UCA Report Client control */ +typedef struct + { + DBL_LNK l; /* Internal use */ + MVL_NET_INFO *netInfo; + struct mvlu_rpt_ctrl *rpt_ctrl; /* report control */ + MVLU_BASRCB basrcb; /* report data */ + +/* Transmit timing control */ + ST_DOUBLE next_integ_rpt_time; + ST_DOUBLE next_rbe_rpt_time; + ST_DOUBLE buf_time_done; + ST_BOOLEAN integ_scan_in_progress; + +/* Data state control */ + ST_UINT16 numTrgs; + ST_UINT8 *reasons_data; /* array of reasons */ + ST_UINT8 *changed_flags; /* bitstring */ + ST_UINT8 *segmented_inclusion;/* inclusion bitstring for segmented rpt*/ + MVL_IND_PEND *scan_read_ind; /* Indication to pass to u_mvl_read_ind for scan*/ + } MVLU_RPT_CLIENT; + +/************************************************************************/ +/* Structures for saving Buffered report data. */ +/************************************************************************/ +/* VAR_DATA - data for one variable of a Report Dataset. */ +typedef struct var_data + { + ST_VOID *data_ptr; /* ptr to raw MMS Variable data */ + /* (allocated) */ + ST_INT data_len; /* length of raw MMS Variable data */ + ST_UINT8 reason_for_incl; /* reason for inclusion */ + } VAR_DATA; + +/* BUFLIST_ENTRY - data for one buffered rpt (stored on linked list). */ +/* Data in this struct usually changes with each Report, so must be */ +/* saved in the buffer. Other data may be taken directly from the RCB */ +/* when a Report is sent. */ +typedef struct buflist_entry + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct buflist_entry *next; /* CRITICAL: DON'T MOVE. */ + struct buflist_entry *prev; /* CRITICAL: DON'T MOVE. */ + ST_UCHAR EntryID[8]; /* Rpt EntryID (Ostring8) */ + MMS_BTIME6 TimeOfEntry; /* Rpt TimeOfEntry */ + ST_INT num_var; /* Num of var in var_data array */ + VAR_DATA *var_data; /* Ptr to array of structs, one for each*/ + /* var (allocated) */ + ST_INT *asn1_len_array; /* Array of ASN.1 lengths, one for each */ + /* var in Dataset (allocated) */ + ST_INT cur_va_index; /* Index to next var in Dataset to send */ + /* (used when segmenting) */ + ST_UINT16 SubSeqNum; /* SubSeqNum of next segment to send */ + } BUFLIST_ENTRY; + +/* MVL61850_BRCB_CTRL */ +typedef struct + { + /* Optional parameters to send in rpt (if appropriate OptFlds bit set).*/ + ST_BOOLEAN BufOvfl; + /* Internal parameters */ + BUFLIST_ENTRY *rpt_list; /* Linked list of buffered reports */ + BUFLIST_ENTRY *rpt_list_next; /* Next rpt to send from "rpt_list" */ + /* (NULL if list empty or all sent) */ + ST_INT rpt_count; /* count of entries in "rpt_list" */ + /* once buffer's full, shouldn't change much*/ + ST_UINT rpts_lost_count; /* # rpts lost because of overflow */ + ST_INT rpts_sent_total;/*renxiaobao ±¨¸æ*/ + ST_INT brcb_bufsize; + ST_INT cur_bufsize; + ST_BOOLEAN enabled_once; /* TRUE if BRCB was enabled at least once*/ + ST_UCHAR lastSentEntryID[8]; + MMS_BTIME6 lastSentTimeOfEntry; + } MVL61850_BRCB_CTRL; + +/* TypeIDs for special report types created by mvlu_rpt_init_types. */ +typedef struct + { + ST_INT mmsbool; /* named so not confused with C++ 'bool' type */ + ST_INT int8u; /* for SqNum */ + ST_INT int16u; + ST_INT int32u; + ST_INT vstring65; /* for RptID */ + ST_INT btime6; /* for EntryTime */ + ST_INT ostring8; /* for EntryID */ + ST_INT vstring32; /* for RptId */ + ST_INT bvstring6; /* for TrgOps (IEC) */ + ST_INT bvstring8; /* for OptFlds,TrgOps (UCA) */ + ST_INT bvstring10; /* for OptFlds (IEC) */ + ST_INT bstr6; /* for Reason (IEC) */ + ST_INT bstr8; /* for Reason (UCA) */ + ST_INT vstring129; /* for ObjectReference (IEC) */ + } MVLU_RPT_TYPEIDS; + +/* For backward compatibility ... do not use */ +#define MVLU_SEQNUM_MASK MVLU_SQNUM_MASK + +#define MVLU_MAX_RPTID_LEN 65 +#define MVLU_MAX_OUTDAT_LEN 65 + + +/* MVLU_RPT_CTRL */ +typedef struct mvlu_rpt_ctrl + { + DBL_LNK l; /* Internal use */ + +/* Active clients */ + +/* NOTE: "only_client" for 61850 only. */ + MVLU_RPT_CLIENT only_client; /* exactly 1. Don't need list */ + +/* NOTE: "num_rpt_clients", "rpt_client_list", "common_basrcb" for UCA only.*/ + ST_INT num_rpt_clients; + MVLU_RPT_CLIENT *rpt_client_list; + +/* basrcb data for passive read clients */ + MVLU_BASRCB common_basrcb; + ST_CHAR *basrcb_name; + +/* Used in read/write indication functions in finding the report ctrl */ + RUNTIME_TYPE *rcbRtHead; + MVL_VAR_ASSOC *base_va; + +/* Used to support different report schemes */ + ST_INT rcb_type; /* RCB_TYPE_UCA, RCB_TYPE_IEC_BRCB, etc. */ + +/* Action to be taken if var changes twice before buftim expires */ + ST_INT buftim_action; /* MVLU_RPT_BUFTIM_REPLACE/SEND_NOW */ + +/* The information below is used internally by MVLU */ + MVL_NVLIST_CTRL *dsNvl; /* The base dataSet for the report */ + MVL_NVLIST_CTRL rptNvl; /* The NVL used to send the InfoRpt */ + RUNTIME_TYPE incRt; /* Used in building the inclusion_va */ + ST_INT maxNumRptVars; /* Max vars allowed in report. */ + MVLU_RPT_TYPEIDS rpt_typeids; /* Types needed for reports. */ + ST_INT inclusion_typeid; /* One more special type. */ + MVL61850_BRCB_CTRL brcbCtrl; /* Used only for 61850 BRCB. */ + ST_DOUBLE scan_rate; /* Scan rate in milliseconds */ + ST_DOUBLE next_scan_start; /* Time for next scan */ + } MVLU_RPT_CTRL; + +extern MVLU_RPT_CTRL *mvlu_rpt_ctrl_list; /* List of only UCA RCBs.*/ +extern MVLU_RPT_CTRL *mvl61850_rpt_ctrl_list; /* List of only 61850 RCBs.*/ + +/* UCA VA Scan Control */ +typedef struct + { + DBL_LNK l; /* Internal use */ + ST_BOOLEAN enable; + ST_DOUBLE scan_period; + ST_DOUBLE next_scan_start; + ST_BOOLEAN saturated; + ST_INT num_va_changes; + + ST_INT num_scan_va; + MVL_VAR_ASSOC **scan_va; + ST_INT num_va_read_pend; + + MVL_IND_PEND indCtrl; + MVL_COMM_EVENT commEvent; + MVL_SCOPE *scan_va_scope; /* ptr to array of structs. */ + ST_VOID *usr; /* user assignable pointer to use in scan callbacks*/ + } MVLU_RPT_SCAN_CTRL; +extern MVLU_RPT_SCAN_CTRL *mvlu_rpt_scan_list; + + +/* Report Service */ +ST_VOID mvlu_rpt_service (ST_VOID); + +/* Report Variable Scanning */ +MVLU_RPT_SCAN_CTRL *mvlu_rpt_create_scan_ctrl (ST_INT numScanVa); +MVLU_RPT_SCAN_CTRL *mvlu_rpt_create_scan_ctrl2 ( + MVL_NVLIST_CTRL *nvl, + ST_RET (*scan_done_fun) (struct mvl_ind_pend *ind_pend), + ST_UINT report_scan_rate); /* report scan rate (millisec) */ +ST_VOID mvlu_rpt_destroy_scan_ctrl (MVLU_RPT_SCAN_CTRL *scanCtrl); +ST_VOID mvlu_rpt_va_scan (ST_VOID); +ST_VOID mvlu_rpt_scan_read (MVLU_RPT_SCAN_CTRL *scanCtrl); + +/* Asynchronous Change Reporting */ +ST_VOID mvlu_rpt_va_change (MVL_VAR_ASSOC *va, + ST_UCHAR reason, + ST_VOID *new_data); + +/* Creating Report Dataset NVL's */ +MVL_NVLIST_CTRL *mvlu_derive_rpt_ds (ST_CHAR *domName, ST_CHAR *nvlName, + ST_INT numNodes, ST_CHAR **nodeNames); + +/* Structure Element name derivation */ +ST_RET mvlu_derive_ds_va_names (ST_CHAR *domName, + ST_INT numNodes, ST_CHAR **nodeNames, + ST_INT *numObjNamesOut, + OBJECT_NAME **objNameTblOut, + ST_CHAR **nameBufOut); + + +/* Report Control Create/Free */ +/* NOTE: The "buftim_action" arg may be set to + * MVLU_RPT_BUFTIM_REPLACE or MVLU_RPT_BUFTIM_SEND_NOW. + * This arg is only used in the case when buffer + * time (BufTim) is used, and a second data change is detected for the + * same "va", before the BufTim expires. To satisfy the requirements of + * IEC61850-7-2, the caller must set this flag to indicate whether to + * replace the buffered value with the new value and continue timing + * (MVLU_RPT_BUFTIM_REPLACE), OR to send a report immediately with the + * buffered value, save the new value in the buffer, and restart the timer + * (MVLU_RPT_BUFTIM_SEND_NOW). + */ +MVLU_RPT_CTRL *mvlu_create_rpt_ctrl (ST_CHAR *basrcbName, + MVL_NVLIST_CTRL *dsNvl, + MVL_VAR_ASSOC *base_va, + ST_INT rcb_type, + ST_INT buftim_action, /* MVLU_RPT_BUFTIM_* */ + ST_INT brcb_bufsize, /* for BRCB only */ + ST_UINT32 ConfRev); /* for BRCB/URCB only */ +ST_VOID mvlu_free_rpt_ctrl (MVLU_RPT_CTRL *rptCtrl); + +/* Main reporting functions for IEC 61850 only. */ +MVLU_RPT_CTRL *mvl61850_create_rpt_ctrl (ST_CHAR *basrcbName, + MVL_NVLIST_CTRL *dsNvl, + MVL_VAR_ASSOC *base_va, + ST_INT rcb_type, + ST_INT buftim_action, /* MVLU_RPT_BUFTIM_* */ + ST_INT brcb_bufsize, /* for BRCB only */ + ST_UINT32 ConfRev); /* for BRCB/URCB only */ +ST_VOID mvl61850_free_rpt_ctrl (MVLU_RPT_CTRL *rptCtrl); +ST_VOID mvl61850_rpt_service (char *dom,char CHG); +ST_RET mvl61850_rpt_dataset_create (MVLU_RPT_CTRL *rptCtrl, + MVL_NVLIST_CTRL *dsNvl); +ST_VOID mvl61850_rpt_dataset_destroy (MVLU_RPT_CTRL *rptCtrl); + +/************************************************************************/ +/* mvlu_integrity_scan_destroy */ +/* Free temporary MVL_IND_PEND allocated by mvlu_integrity_scan_read. */ +/************************************************************************/ +ST_VOID mvlu_integrity_scan_destroy (MVL_IND_PEND *indCtrl); + +/* + * mvlu_integrity_scan_read + * This function "BEGINS" the scan of ALL data for one Report DataSet (NVL). + * It is called automatically when an Integrity Report or a + * General Interrogation Report needs to be sent. This is much more + * efficient than constantly scanning. + * - It allocates & initializes a temporary MVL_IND_PEND structure. + * - It calls "u_mvl_read_ind" to begin the scan. + * - The scan may complete synchronously or asynchronously. + * - When the scan completes, the funct pointed to by "scan_done_fun" arg + * is called to build the report and cleanup. + * CRITICAL: Function pointed to by "scan_done_fun" must call + * "mvlu_integrity_scan_destroy" to free temporary MVL_IND_PEND struct. + */ + +ST_VOID mvlu_integrity_scan_read (MVLU_RPT_CLIENT *rptClient, + ST_VOID (*scan_va_done_fun)(MVL_IND_PEND *indCtrl, + MVL_VAR_ASSOC *va), + ST_RET (*scan_done_fun)(MVL_IND_PEND *indCtrl) + ); + +MVL_IND_PEND *mvlu_setup_scan_read (MVL_NVLIST_CTRL *nvl, + ST_VOID (*scan_va_done_fun)(MVL_IND_PEND *indCtrl, + MVL_VAR_ASSOC *va), + ST_RET (*scan_done_fun)(MVL_IND_PEND *indCtrl) + ); + +/************************************************************************/ +/* mvlu_integrity_timeout */ +/* Check for Integrity period timeout. If timeout occurred, start */ +/* integrity scan. */ +/* RETURNS: SD_TRUE if IntgPd is set and timeout occurred */ +/* SD_FALSE otherwise */ +/************************************************************************/ +ST_RET mvlu_integrity_timeout (MVLU_RPT_CLIENT *rptClient, ST_DOUBLE timeNow); + +/* Pointer to one of these functions passed to "mvlu_integrity_scan_read", + * saved in "usr_done_fun" in MVL_IND_PEND struct. Called when scan completes. + */ +ST_RET mvlu_integrity_scan_done (MVL_IND_PEND *indCtrl); +ST_RET mvlu_gi_scan_done (MVL_IND_PEND *indCtrl); + +/* Pointer to one of these functions passed to "mvlu_integrity_scan_read", + * stored in global var. Called when each va read completes. + */ +ST_VOID mvlu_integrity_scan_va_done (MVL_IND_PEND *indCtrl, MVL_VAR_ASSOC *va); +ST_VOID mvlu_gi_scan_va_done (MVL_IND_PEND *indCtrl, MVL_VAR_ASSOC *va); + +extern ST_VOID (*_mvlu_rpt_disconnect_rcvd_fun)(MVL_NET_INFO *netInfo); + +MVL_NVLIST_CTRL *mvlu_resolve_uca_nvl (MVL_NVLIST_CTRL *ucaNvl, + OBJECT_NAME *scopeSel); + +/* Defines for UCA/IEC report type, "rpt_type" arg to "mvlu_send_report"*/ +#define MVLU_RPT_TYPE_INTEGRITY_OR_GI 0 +#define MVLU_RPT_TYPE_RBE 1 + +ST_RET mvlu_send_report (MVLU_RPT_CLIENT *rptClient, ST_INT rpt_type); + +/* u_mvlu_rpt_time_get - User callback function to set accurate time + * that UCA/IEC report is built, called by "mvlu_send_report" or + * "mvl61850_rcb_build" when report is being built. + */ +ST_VOID u_mvlu_rpt_time_get (MMS_BTIME6 *TimeOfEntry); + +/* Misc. Helper Functions */ +ST_INT mvlu_rpt_get_va_index (MVLU_RPT_CTRL *rptCtrl, MVL_VAR_ASSOC *va); +MVLU_BASRCB *_mvlu_get_rd_rcb (MVLU_RD_VA_CTRL *mvluRdVaCtrl, + MVLU_RPT_CLIENT **rptClientOut); +MVLU_BASRCB *_mvlu_get_wr_rcb (MVLU_WR_VA_CTRL *mvluWrVaCtrl, + MVLU_RPT_CLIENT **rptClientOut); +MVLU_BASRCB *mvl61850_get_rcb (MVL_VAR_ASSOC *baseVa, + RUNTIME_TYPE *rt, + MVLU_RPT_CLIENT **rptClientOut); + +ST_VOID _mvlu_rpt_disconnect_rcvd (MVL_NET_INFO *netInfo); +ST_RET mvlu_rpt_find_typeids (MVLU_RPT_TYPEIDS *rpt_typeids); +ST_RET mvlu_rpt_rcb_type_find (ST_INT type_id, ST_CHAR *basrcbName, + RUNTIME_TYPE **rcbHeadOut, ST_INT *numRtOut); + + +ST_RET mvlu_find_uca_var (RUNTIME_TYPE **rtIo, ST_INT *numRtIo, + ST_CHAR *varName); + + +/************************************************************************/ +/************************************************************************/ +/* SBO HANDLING ELEMENTS */ + +#define SBO_SELECT_TIMEOUT 30 /* seconds */ +#define MAX_NUM_SBO_PEND 10 /* Number of SBOs to be pending */ +#define MAX_SBO_NAME_SIZE 66 + +typedef struct mvl_sbo_ctrl + { + ST_BOOLEAN in_use; /* control element management */ + ST_INT ctlState; /* Control state (MVL61850_CTLSTATE_*) */ + ST_BOOLEAN use_ms_timer; /* if TRUE, use expire_time_ms below*/ + ST_CHAR sbo_var[MVL61850_MAX_OBJREF_LEN+1]; /* ObjRef of "Oper" attr*/ + MVL_NET_INFO *net_info; /* Connection ID */ + time_t expire_time; /* SELECT expiration time */ + ST_DOUBLE expire_time_ms; /* SELECT expiration time in ms */ + ST_INT8 ctlModel; /* sbo-with-normal-security, etc*/ + ST_INT8 sboClass; /* operate-once or operate-many */ + /* renxiaobao ¿ØÖÆ*/ + double Oper_WaitForChangeTimer; + short Oper_data_len; + void *Oper_map_entry; + void *Oper_ctlVal; + void *Oper_stVal; + MVL61850_LAST_APPL_ERROR LastApplError; + } MVL_SBO_CTRL; + + +ST_VOID u_mvl_sbo_operate (MVL_SBO_CTRL *sboSelect, + MVLU_WR_VA_CTRL *mvluWrVaCtrl); + +ST_VOID mvlu_clr_pend_sbo (MVL_NET_INFO *net_info); + +MVL_SBO_CTRL *mvlu_sbo_chk_state (ST_CHAR *sboName, + MVL_NET_INFO *net_info); +ST_VOID mvlu_sbo_chk_timers (ST_VOID); +ST_VOID mvlu_sbo_ctrl_free (MVL_SBO_CTRL *sboCtrl); +MVL_SBO_CTRL *initSboCtrl (MVL_NET_INFO *net_info, + ST_CHAR *sbo_name, + ST_UINT32 sboTimeout, + ST_BOOLEAN use_ms_timer); + + +/************************************************************************/ +/************************************************************************/ +/* IEC-61850 functions */ +/************************************************************************/ + +/* + * mvl61850_brcb_client_service + * + * Check the BRCB state and, if necessary, + * encode, queue, AND/OR send IEC "Buffered" reports. + */ +ST_VOID mvl61850_brcb_client_service (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + ST_DOUBLE timeNow); + +/** + * mvl61850_urcb_client_service + * + * Check the URCB state and, if necessary, + * encode AND send IEC "Unbuffered" reports. + */ +ST_VOID mvl61850_urcb_client_service (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + ST_DOUBLE timeNow); + +ST_RET mvlu_rpt_ready (MVLU_RPT_CLIENT *rptClient, ST_INT rpt_type); +ST_RET mvl61850_urcb_rpt_send (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + ST_INT rpt_type); +ST_RET mvl61850_brcb_rpt_save (MVLU_RPT_CLIENT *rptClient); +ST_RET mvl61850_brcb_rpt_send (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + BUFLIST_ENTRY *buflist_entry, + ST_BOOLEAN *all_seg_done); +ST_VOID mvl61850_brcb_entryid_init (MVLU_RPT_CTRL *rptCtrl, ST_UINT8 *EntryID); + +ST_VOID mvl61850_brcb_rpt_lists_clean (MVL61850_BRCB_CTRL *brcbCtrl); + +/* Internal IEC 61850 reporting functions (not called by user). */ +ST_RET mvl61850_mk_rptid (MVLU_RPT_CTRL *rptCtrl, ST_CHAR *RptID, size_t max_len); +ST_VOID mvl61850_mk_dataref (MVL_VAR_ASSOC *va, MVL_SCOPE *va_scope, + ST_CHAR *databuf, ST_INT maxlen); +ST_VOID mvl61850_rcb_cleanup (MVLU_RPT_CLIENT *rptClient); +ST_RET mvl61850_brcb_rpt_set_entryid (MVLU_RPT_CLIENT *rptClient, ST_UCHAR *EntryID); +ST_VOID mvl61850_rcb_chk_state (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + ST_DOUBLE timeNow); +ST_RET mvl61850_integrity_timeout (MVLU_RPT_CLIENT *rptClient, ST_DOUBLE timeNow); +ST_BOOLEAN chk_seg_needed (MVLU_RPT_CLIENT *rptClient, + ST_INT *asn1_len_array, + ST_INT cur_va_index, /* input arg */ + ST_INT *next_va_index); /* output arg */ + +/************************************************************************/ +/* IEC 61850 "Control Model" functions. */ +/************************************************************************/ +ST_VOID mvl61850_sbo_create_sboname (MVL_VAR_ASSOC *va, MVL_SCOPE *va_scope, + ST_CHAR *sboName); + +MVL_SBO_CTRL *mvl61850_ctl_chk_sbo (MVLU_RD_VA_CTRL *mvluRdVaCtrl); +MVL_SBO_CTRL *mvl61850_ctl_chk_sbow (MVLU_WR_VA_CTRL *mvluWrVaCtrl); + +ST_RET mvl61850_ctl_chk_state (MVLU_WR_VA_CTRL *mvluWrVaCtrl); + +ST_RET mvl61850_ctl_lastapplerror_create (ST_VOID); +ST_RET mvl61850_ctl_lastapplerror_send (MVL_NET_INFO *net_info, + MVL61850_LAST_APPL_ERROR *last_appl_error); +ST_RET mvl61850_ctl_command_termination (MVL_NET_INFO *net_info, ST_CHAR *oper_ref, + ST_RET status, MVL61850_LAST_APPL_ERROR *last_appl_error); +ST_VOID mvl61850_ctl_req_done (MVLAS_WR_VA_CTRL *wrVaCtrl, MVL_NET_INFO *net_info); + +/* These callback functions must be supplied by user. */ +ST_VOID u_mvl61850_ctl_oper_begin (ST_CHAR *oper_ref); +/*renxiaobao ¿ØÖÆ*/ +/*ST_VOID u_mvl61850_ctl_oper_end (MVL_NET_INFO *net_info, ST_CHAR *oper_ref, MVL_VAR_ASSOC *base_var);*/ +ST_VOID u_mvl61850_ctl_oper_end (MVL_NET_INFO *net_info, ST_CHAR *oper_ref, MVL_VAR_ASSOC *base_var, + void *ctlVal,void *stVal,short len,void *map_entry,MVL61850_LAST_APPL_ERROR *LastApplError); + +ST_RET mvl61850_mkname_ctlmodel (ST_CHAR *var_name, ST_CHAR *flatname, size_t flatname_len); + +/************************************************************************/ +/* Miscellaneous helper functions */ +/************************************************************************/ +ST_VOID mvlu_trim_branch_name (ST_CHAR *branch_name); +ST_RET mvlu_find_comp_type (ST_INT base_type_id, ST_CHAR *flat_name, + RUNTIME_TYPE **sub_rt_type, /* out */ + ST_INT *sub_rt_num); /* out */ + +ST_RET mvlu_get_leaf_val_int8 (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_INT8 *data); +ST_RET mvlu_get_leaf_val_int32 (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_INT32 *data); +ST_RET mvlu_get_leaf_val_int_any (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_INT32 *data); +ST_RET mvlu_get_leaf_val_uint32 (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_UINT32 *data); +ST_RET mvlu_get_leaf_val_boolean (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_BOOLEAN *data); +ST_RET mvlu_get_leaf_val_bvstring (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, + MMS_BVSTRING *data, ST_INT max_num_bits); +ST_VOID *mvlu_get_leaf_data_ptr (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, RUNTIME_TYPE **rt_type); +ST_RET _rcb_writable (MVLU_BASRCB *rcb, MVLU_RPT_CLIENT *rptClient, + MVLU_WR_VA_CTRL *mvluWrVaCtrl); +ST_RET mvl61850_objref_create (ST_CHAR *objName, + MVL_SCOPE *objScope, + ST_CHAR *objRef); /* ptr to ObjectReference */ + +/************************************************************************/ +/* Global variables. */ +/************************************************************************/ +extern MVL_SBO_CTRL sbo_pool[]; /* array of SBO control structures. */ + +/* This function pointer called BEFORE all write leaf functions. */ +/* NOTE: called only for complex variables (struct or array). */ +extern ST_RET (*u_mvl_wr_ind_var_start)(MVL_IND_PEND *indCtrl, + MVLAS_WR_VA_CTRL *wrVaCtrl); /* current var in list of var */ + +/* This function pointer called AFTER all write leaf functions. */ +/* NOTE: called only for complex variables (struct or array). */ +extern ST_RET (*u_mvl_wr_ind_var_end)(MVL_IND_PEND *indCtrl, + MVLAS_WR_VA_CTRL *wrVaCtrl); /* current var in list of var */ + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* MVL_UCA_INCLUDED */ + diff --git a/include/inc/ntddosi.h b/include/inc/ntddosi.h new file mode 100644 index 0000000..0cf01a6 --- /dev/null +++ b/include/inc/ntddosi.h @@ -0,0 +1,114 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : osillc.h */ +/* PRODUCT(S) : OSI LLC NDIS 3.0 Device Driver for NT */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/13/98 DSF 05 Added SeqNumber field to PACKET_BLOCK */ +/* 05/07/98 DSF 04 The size of PACKET_BLOCK is now user-settable*/ +/* 06/19/97 DSF 03 Added Stats */ +/* 09/10/96 DSF 02 Used Length field in SET_MULTI */ +/* 05/22/96 DSF 01 Initial Release */ +/* */ +/************************************************************************/ + +#ifndef __NTDDOSILLC +#define __NTDDOSILLC + +#if defined (_NTDDK_) +#include +#else +#include +#endif + +#pragma pack(1) + +// +// standard 802.3 defines (not defined elsewhere) +// +#define ETH_LENGTH_OF_HEADER 14 +#define ETH_MINIMUM_LENGTH_OF_DATA 46 +#define ETH_MAXIMUM_LENGTH_OF_DATA 1500 +#define ETH_LENGTH_OF_FRAME 1514 + + +// max number of packets that will be returned at a time +#define OSILLC_MAX_RXPACKETS 10 + +typedef struct _NT_PACKET_DATA +{ + ULONG Length; + UCHAR Data[ETH_LENGTH_OF_FRAME]; +} NT_PACKET_DATA, * PNT_PACKET_DATA; + +typedef struct _NT_PACKET_BLOCK +{ + ULONG NumberOfPackets; + ULONG SeqNumber; + NT_PACKET_DATA PacketData[1]; +} NT_PACKET_BLOCK, * PNT_PACKET_BLOCK; + + +#if 0 +typedef struct _NT_ARM_EVENT +{ + UINT Status; +} NT_ARM_EVENT; +#endif + + +typedef struct _PACKET_OID_DATA +{ + ULONG Oid; + ULONG Length; + UCHAR Data[1]; +} PACKET_OID_DATA, * PPACKET_OID_DATA; + + +#if !defined (GET_STATS_DEFINED) +typedef struct _GET_STATS +{ + ULONG XmitOk; + ULONG RcvOk; + ULONG XmitError; + ULONG RcvError; + ULONG RcvUnknown; + ULONG XmitInd; + ULONG RcvInd; + ULONG AllocError; +} GET_STATS; + +#define GET_STATS_DEFINED +#endif + +// base for IOCTLs +#define FILE_DEVICE_PROTOCOL 0x8000 + +#define OSILLC_CONTROL_CODE(request, method) \ + CTL_CODE(FILE_DEVICE_PROTOCOL, request, method, FILE_ANY_ACCESS) + +#define IOCTL_OSILLC_QUERY_OID OSILLC_CONTROL_CODE(0, METHOD_BUFFERED) +#define IOCTL_OSILLC_SET_OID OSILLC_CONTROL_CODE(1, METHOD_BUFFERED) +#define IOCTL_OSILLC_GET_STATS OSILLC_CONTROL_CODE(2, METHOD_BUFFERED) +#define IOCTL_OSILLC_SET_EVENT OSILLC_CONTROL_CODE(3, METHOD_BUFFERED) +#define IOCTL_OSILLC_CLEAR_EVENT OSILLC_CONTROL_CODE(4, METHOD_BUFFERED) +#define IOCTL_OSILLC_GET_MACNAME OSILLC_CONTROL_CODE(5, METHOD_BUFFERED) +#define IOCTL_OSILLC_ARM_EVENT OSILLC_CONTROL_CODE(6, METHOD_BUFFERED) +#define IOCTL_OSILLC_RESET OSILLC_CONTROL_CODE(7, METHOD_BUFFERED) + +#define IOCTL_OSILLC_GET_PACKETS OSILLC_CONTROL_CODE(8, METHOD_OUT_DIRECT) +#define IOCTL_OSILLC_SEND_PACKETS OSILLC_CONTROL_CODE(9, METHOD_IN_DIRECT) + +#endif + +#pragma pack() diff --git a/include/inc/osillc.h b/include/inc/osillc.h new file mode 100644 index 0000000..b433d5c --- /dev/null +++ b/include/inc/osillc.h @@ -0,0 +1,97 @@ +//--------------------------------------------------------------------------- +// +// File: osillc.h +// +// Copyright (c) 1998,1999 SISCO, Inc. All rights reserved. +// +// Description: Driver external definitions. +// +// Author: A. Shajenko/Stratos Technology, Inc. +// +// History: +// 13-Sep-98 A. Shajenko Implemented. +// +//--------------------------------------------------------------------------- + +#ifndef _OSILLC_H +#define _OSILLC_H + +#if defined (_NTDDK_) +#include +#else +#include +#endif + +//////////////////////////////////////////////////////////////////////////////////// + +#pragma pack(1) + +// +// standard 802.3 defines (not defined elsewhere) +// +#define ETH_LENGTH_OF_HEADER 14 +#define ETH_MINIMUM_LENGTH_OF_DATA 46 +#define ETH_MAXIMUM_LENGTH_OF_DATA 1500 +#define ETH_LENGTH_OF_FRAME 1514 + + +// max number of packets that will be returned at a time +#define OSILLC_MAX_RXPACKETS 10 + +typedef struct _OSILLC_PACKET_DATA +{ + ULONG Length; + UCHAR Data[ETH_LENGTH_OF_FRAME]; +} OSILLC_PACKET_DATA, * POSILLC_PACKET_DATA; + +typedef struct _OSILLC_PACKET_BLOCK +{ + ULONG NumberOfPackets; + ULONG SeqNumber; + OSILLC_PACKET_DATA PacketData[OSILLC_MAX_RXPACKETS]; +} OSILLC_PACKET_BLOCK, * POSILLC_PACKET_BLOCK; + + +typedef struct _OSILLC_OID_DATA +{ + ULONG Oid; + ULONG Length; + ULONG BytesProcessed; + ULONG BytesNeeded; + ULONG Status; + UCHAR Data[1]; +} OSILLC_OID_DATA, * POSILLC_OID_DATA; + +typedef struct _OSILLC_GET_STATS +{ + ULONG XmitOk; + ULONG RcvOk; + ULONG XmitError; + ULONG RcvError; + ULONG RcvUnknown; + ULONG XmitInd; + ULONG RcvInd; + ULONG AllocError; +} OSILLC_GET_STATS, * POSILLC_GET_STATS; + +// base for IOCTLs +#define FILE_DEVICE_PROTOCOL 0x8000 + +#define OSILLC_CONTROL_CODE(request, method) \ + CTL_CODE(FILE_DEVICE_PROTOCOL, request, method, FILE_ANY_ACCESS) + +#define IOCTL_OSILLC_QUERY_OID OSILLC_CONTROL_CODE(0, METHOD_BUFFERED) +#define IOCTL_OSILLC_SET_OID OSILLC_CONTROL_CODE(1, METHOD_BUFFERED) +#define IOCTL_OSILLC_GET_STATS OSILLC_CONTROL_CODE(2, METHOD_BUFFERED) +#define IOCTL_OSILLC_GET_MACNAME OSILLC_CONTROL_CODE(3, METHOD_BUFFERED) +#define IOCTL_OSILLC_RESET OSILLC_CONTROL_CODE(4, METHOD_BUFFERED) + +#define IOCTL_OSILLC_BIND OSILLC_CONTROL_CODE(10, METHOD_BUFFERED) +#define IOCTL_OSILLC_UNBIND OSILLC_CONTROL_CODE(11, METHOD_BUFFERED) +#define IOCTL_OSILLC_WRITE OSILLC_CONTROL_CODE(12, METHOD_BUFFERED) +#define IOCTL_OSILLC_READ OSILLC_CONTROL_CODE(13, METHOD_BUFFERED) + +#pragma pack() + +#endif _OSILLC_H + diff --git a/include/inc/qmem.h b/include/inc/qmem.h new file mode 100644 index 0000000..a9bdcbc --- /dev/null +++ b/include/inc/qmem.h @@ -0,0 +1,35 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved */ +/* */ +/* MODULE NAME : qmem.h */ +/* PRODUCT(S) : Quick Memory Allocator */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +ST_RET qMemInit (ST_INT NumElem); +ST_VOID *qMemAlloc (ST_INT size); +ST_VOID qMemFree (ST_VOID *ptr); + +extern ST_INT qMemElemSize; /* default = 126 (must be power */ + /* of 2 - 2) */ + + +#ifdef __cplusplus +} +#endif diff --git a/include/inc/rs_a.h b/include/inc/rs_a.h new file mode 100644 index 0000000..3eec10c --- /dev/null +++ b/include/inc/rs_a.h @@ -0,0 +1,119 @@ +#ifndef RS_A_H +#define RS_A_H + +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993, 1994, All Rights Reserved */ +/* */ +/* MODULE NAME : rs_a.h */ +/* PRODUCT(S) : REDUCED STACK SUIC */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/09/98 JRB 02 Chg MAX_SUIC_CHAN from 256 to 1024. */ +/* 10/20/97 JRB 01 Added #include "asn1defs.h" for MMS_OBJ_ID. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 05/01/97 JRB 03 Move MAX_SUIC_CHAN define to here. */ +/* 01/02/96 JRB 02 Add MMSEventName and hMMSEvent. */ +/* 05/29/96 MDE 01 Changed DIB_ENTRY - name is now a pointer */ +/* 03/27/96 MDE Created */ +/************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (_WIN32) +#include +#endif /* _WIN32 */ + +#if defined (__OS2__) +#define INCL_BASE +#include +#endif /* __OS2__ */ + +#include "asn1defs.h" /* for MMS_OBJ_ID definition */ + +#define MAX_SUIC_CHAN 1024 /* number of channels */ + +/************************************************************************/ +/* The structure below is used to save Directory and other information */ +/* about local and remote AE's read in from SUIC.DIB */ +/************************************************************************/ + +#define DIB_ENTRY_DEFINED + +struct dib_entry +{ + ST_LONG reserved; /* reserved field */ + ST_CHAR *name; /* user-defined ASCII character string */ + ST_CHAR local; /* local or remote name */ + ST_UCHAR AP_title_pres; /* present flag */ + MMS_OBJ_ID AP_title; /* AP title */ + ST_UCHAR AP_inv_id_pres; /* present flag */ + ST_INT32 AP_invoke_id; /* AP invocation ID */ + ST_UCHAR AE_qual_pres; /* present flag */ + ST_INT32 AE_qual; /* AE qualifier */ + ST_UCHAR AE_inv_id_pres; /* present flag */ + ST_INT32 AE_invoke_id; /* AE invocation ID */ + ST_UINT16 adlcAddr; +} ; +typedef struct dib_entry DIB_ENTRY; + +/************************************************************************/ +/* Channel-oriented control structure used to hold connection-specific */ +/* information */ +/************************************************************************/ + +#define MAX_TX_OUT 10 /* max. outstanding TX requests allowed */ + +struct chanctrl + { + DIB_ENTRY *loc_de; /* Pointer to Local DIB Entry */ + DIB_ENTRY *rem_de; /* Pointer to Remote DIB Entry */ + } ; +extern struct chanctrl *s_chan_ctrl; + +/************************************************************************/ +/* Structure to store incoming associate indication in case no listen */ +/* channel is available */ +/************************************************************************/ + +extern ST_INT num_loc_dib_entries; +extern ST_INT num_rem_dib_entries; +extern DIB_ENTRY *loc_dib_table; +extern DIB_ENTRY *rem_dib_table; + +/************************************************************************/ +/* Event handling variables for WIN32. */ +/************************************************************************/ +#ifdef _WIN32 +extern ST_CHAR *MMSEventName; /* Pointer to the globally unique name of Event Object */ +extern HANDLE hMMSEvent; /* Handle to Event Object to be signalled when */ + /* s_serve () needs to be called */ +#endif /* _WIN32 */ + +/************************************************************************/ +/* Prototypes */ +/************************************************************************/ +ST_VOID s_reset_ctrl (ST_INT); +ST_RET init_dirser (ST_VOID); +DIB_ENTRY *find_dib_entry (ST_CHAR *); +DIB_ENTRY *find_loc_dib_entry (ST_CHAR *ar_name); +DIB_ENTRY *find_rem_dib_entry (ST_CHAR *ar_name); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/include/inc/rs_defs.h b/include/inc/rs_defs.h new file mode 100644 index 0000000..bbdb66c --- /dev/null +++ b/include/inc/rs_defs.h @@ -0,0 +1,241 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 All Rights Reserved */ +/* */ +/* MODULE NAME : rs_defs.h */ +/* PRODUCT(S) : TP4/RS API internal include file */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/13/99 MDE 13 Added SD_CONST modifiers */ +/* 02/05/99 JRB 12 Del get_rs_event proto. It is now "static". */ +/* 10/08/98 MDE 11 Migrated to updated SLOG interface */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 01/02/96 EJV 10 Added RS_DEFS_INCLUDED */ +/* 11/12/96 MDE 09 Changed to DEBUG_SISCO */ +/* 07/22/96 MDE 08 Changes towards A-Unit Data support */ +/* 03/26/96 MDE 07 Added REDUCED_STACK support */ +/* 02/16/96 JRB 06 Use thisFileName. */ +/* 01/02/96 JRB 05 Removed ipcuptyp for __OS2__ */ +/* 12/28/95 KCW 04 Removed ipcuptyp for AIX */ +/* 12/14/95 DSF 03 Changes for CONN list management */ +/* 10/06/95 JRB 02 For _DOS16M, add hVipcTp4 global */ +/* so that multiple Stack users allowed. */ +/* 04/17/95 DSF 01 Created */ +/* */ +/************************************************************************/ + +#ifndef RS_DEFS_INCLUDED +#define RS_DEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "gen_list.h" +#include "slog.h" + +/****************************************************************/ + +#undef local + +/****************************************************************/ +/****************************************************************/ +/* Local ADLC Address control variables */ +extern ST_UINT16 rsBaseSrcAdlcAddr; +extern ST_UINT16 rsNumSrcAdlcAddr; + +/****************************************************************/ +/* Internal structure definitions */ +/****************************************************************/ + +typedef struct + { + DBL_LNK *l; + TP4_ADDR localTp4Addr; + ST_LONG user_bind_id; /* User-supplied Bind ID */ + } REGINFO; + +typedef struct + { + DBL_LNK lnk; /* linkage */ + REGINFO *reginfo; /* pointer to Bind Control Info */ + ST_LONG user_conn_id; /* User-supplied Connection ID */ + ST_LONG osi_conn_id; /* Connection ID returned by OSIAM */ + ST_UINT16 localAddr; /* ADLC addresses, which define the */ + ST_UINT16 remAddr; /* ADLC connection. */ + ST_BOOLEAN connFlag; + } CONNINFO; + +extern CONNINFO *conn_list; /* pointer to list of conn structs */ + +/****************************************************************/ +extern REGINFO *reg_list; /* pointer to list of REG structs */ + +/****************************************************************/ + +extern SD_CONST ST_UCHAR rs_co_dest; +extern SD_CONST ST_UCHAR rs_co_src; +extern SD_CONST ST_UCHAR rs_co_qos; + +extern SD_CONST ST_UCHAR rs_cl_dest; +extern SD_CONST ST_UCHAR rs_cl_src; +extern SD_CONST ST_UCHAR rs_cl_qos; + +/****************************************************************/ + +extern ST_VOID *co_rs_event; +extern ST_INT co_rs_op; +extern ST_RET co_rs_rslt; + +extern ST_VOID *cl_rs_event; +extern ST_INT cl_rs_op; +extern ST_RET cl_rs_rslt; + +/****************************************************************/ +/* Log Control macros */ +/****************************************************************/ + +extern SD_CONST ST_CHAR *SD_CONST _tp4_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _tp4_flowup_logstr; +extern SD_CONST ST_CHAR *SD_CONST _tp4_flowdown_logstr; + +/****************************************************************/ +#ifdef DEBUG_SISCO + +#define SFLOWUP0(a) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWUP) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_flowup_logstr,\ + thisFileName,__LINE__,a);\ + } +#define SFLOWUP0C(a) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWUP) && sLogCtrl)\ + _slogc (sLogCtrl,a);\ + } +#define SFLOWUP1(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWUP) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_flowup_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define SFLOWUP1C(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWUP) && sLogCtrl)\ + _slogc (sLogCtrl,a,b);\ + } +#define SFLOWUP2(a,b,c) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWUP) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_flowup_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define SFLOWUP2C(a,b,c) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWUP) && sLogCtrl)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define SFLOWUPH(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWUP) && sLogCtrl)\ + _slogHex (sLogCtrl,a,b);\ + } +#define SFLOWDOWN0(a) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWDOWN) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_flowup_logstr,\ + thisFileName,__LINE__,a);\ + } +#define SFLOWDOWN0C(a) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWDOWN) && sLogCtrl)\ + _slogc (sLogCtrl,a);\ + } +#define SFLOWDOWN1(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWDOWN) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_flowdown_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define SFLOWDOWN1C(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWDOWN) && sLogCtrl)\ + _slogc (sLogCtrl,a,b);\ + } +#define SFLOWDOWN2(a,b,c) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWDOWN) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_flowdown_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define SFLOWDOWN2C(a,b,c) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWDOWN) && sLogCtrl)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define SFLOWDOWNH(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWDOWN) && sLogCtrl)\ + _slogHex (sLogCtrl,a,b);\ + } +#define SERR0(a) {\ + if ((tp4_debug_sel & TP4_LOG_ERR) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_err_logstr,\ + thisFileName,__LINE__,a);\ + } +#define SERR0C(a) {\ + if ((tp4_debug_sel & TP4_LOG_ERR) && sLogCtrl)\ + _slogc (sLogCtrl,a);\ + } +#define SERR1(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_ERR) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_err_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define SERR1C(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_ERR) && sLogCtrl)\ + _slogc (sLogCtrl,a,b);\ + } +#define SERR2(a,b,c) {\ + if ((tp4_debug_sel & TP4_LOG_ERR) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_err_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define SERR2C(a,b,c) {\ + if ((tp4_debug_sel & TP4_LOG_ERR) && sLogCtrl)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define SERRH(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_ERR) && sLogCtrl)\ + _slogHex (sLogCtrl,a,b);\ + } + +#else /* Not DEBUG_SISCO */ + +#define SFLOWUP0(a) +#define SFLOWUP0C(a) +#define SFLOWUP1(a,b) +#define SFLOWUP1C(a,b) +#define SFLOWUP2(a,b,c) +#define SFLOWUP2C(a,b,c) +#define SFLOWUPH(a,b) +#define SFLOWDOWN0(a) +#define SFLOWDOWN0C(a) +#define SFLOWDOWN1(a,b) +#define SFLOWDOWN1C(a,b) +#define SFLOWDOWN2(a,b,c) +#define SFLOWDOWN2C(a,b,c) +#define SFLOWDOWNH(a,b) +#define SERR0(a) +#define SERR0C(a) +#define SERR1(a,b) +#define SERR1C(a,b) +#define SERR2(a,b,c) +#define SERR2C(a,b,c) +#define SERRH(a,b) +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* RS_DEFS_INCLUDED */ + diff --git a/include/inc/scl.h b/include/inc/scl.h new file mode 100644 index 0000000..bd32cef --- /dev/null +++ b/include/inc/scl.h @@ -0,0 +1,715 @@ +#ifndef SCL_INCLUDED +#define SCL_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2004-2004 All Rights Reserved */ +/* */ +/* MODULE NAME : scl.h */ +/* PRODUCT(S) : MMS-EASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* SCL main header file. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/24/08 JRB 17 Fix len of appID in SCL_GCB (maps to GoID). */ +/* 04/23/08 JRB 16 Add SCL_SGCB, scl_sgcb_add. */ +/* 07/03/07 JRB 15 Add scl_gse_find. */ +/* 06/12/07 JRB 14 Add VLANID in SCL_GSE & SCL_SMV. */ +/* 05/21/07 RKR 13 Changed MAC type to ST_UCHAR for GSE and SMV */ +/* 10/30/06 JRB 12 scl2_datatype_create_all: all args changed. */ +/* scl2_ld_create_all: add vmd_ctrl, is_client args.*/ +/* Add type_id to SCL_LN, SCL_LNTYPE. */ +/* Chg SCL2_BTYPE. */ +/* 08/04/06 MDE 11 Added scl_debug_mode, scl2_add_btype, etc. */ +/* 07/26/06 JRB 10 Add structs,functs for parsing Communication.*/ +/* 04/19/06 JRB 09 Add maxClient to SCL_RCB for "RptEnabled max".*/ +/* 03/16/06 JRB 08 Add SCL_SVCB struct & scl_svcb_add proto. */ +/* 03/15/06 JRB 07 Chg almost all function prototypes. */ +/* Del scl_dotype_add_da_val, */ +/* scl_datype_add_bda_val, scl_header_save. */ +/* Add sGroup to SCL_DAI. */ +/* Chg desc to ptr (allocated during parse). */ +/* Increase MAX_CDC_LEN for user-defined CDCs. */ +/* 07/25/05 JRB 12 scl2_ld_create_all: Add brcb_bufsize arg. */ +/* SCL_INFO: add brcb_bufsize element. */ +/* 06/28/05 JRB 11 Del scl2_ld_destroy_all. Use mvl_vmd_destroy.*/ +/* 06/24/05 JRB 10 Chg "ord" from unsigned to signed value. */ +/* 05/27/05 CRM 09 Add scl_info_destroy & scl2_ld_destroy_all. */ +/* 03/22/05 JRB 08 Add ifdef __cplusplus to work with C++ code. */ +/* 02/15/05 JRB 07 Add iedName to SCL_INFO. */ +/* Add domName to SCL_LD & SCL_FCDA. */ +/* Add varName to SCL_LN. */ +/* Define SCL_HEADER struct & add it to SCL_INFO.*/ +/* Add scl_header_save. */ +/* 08/06/04 JRB 06 Add scl_parse. */ +/* Move mapping functions to user header. */ +/* 07/19/04 JRB 05 Add out_filename arg to datamap_cfg_read. */ +/* Add any_cfg_count proto. */ +/* 07/15/04 JRB 04 Clean up SCL_GCB, scl_gcb_add. */ +/* 07/09/04 JRB 03 scl2_ld_create_all: add reportScanRate arg. */ +/* 07/02/04 JRB 02 Add SCL_LCB, SCL_GCB, scl_lcb_add, scl_gcb_add.*/ +/* 06/08/04 JRB 01 Initial Revision. */ +/************************************************************************/ +#include "gen_list.h" +#include "mms_def2.h" /* need MAX_IDENT_LEN */ +#include "mvl_defs.h" /* need MVL_VAR_ASSOC, etc. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_VALKIND_LEN 4 /* Spec, Conf, RO, or Set */ +#define MAX_CDC_LEN 50 /* SPS, DPS, etc. (CURVE is longest */ + /* predefined CDC but user may define others)*/ +#define MAX_FC_LEN 2 /* ST, MX, etc. */ + +/* These defines used in SCL_DA struct to differentiate between structs */ +/* containing DA info and structs containing SDO info. */ +#define SCL_OBJTYPE_DA 0 +#define SCL_OBJTYPE_SDO 1 + +/* This def used for flattened leaf names (longer to allow array indices)*/ +#define MAX_FLAT_LEN (MAX_IDENT_LEN*2) + +/************************************************************************/ +/* Structures to contain information from "Header" section of SCL. */ +/************************************************************************/ +typedef struct + { + /* NOTE: only required elements included here. Add optional elements as needed.*/ + ST_CHAR id [MAX_IDENT_LEN+1]; + + /* Defined values for "nameStructure" attribute */ + #define SCL_NAMESTRUCTURE_IEDNAME 0 /* value="IEDName" */ + #define SCL_NAMESTRUCTURE_FUNCNAME 1 /* value="FuncName" */ + ST_INT nameStructure; + } SCL_HEADER; + +/************************************************************************/ +/* Structures to contain information from "Communications" section of SCL.*/ +/************************************************************************/ +/* Data from "GSE" element (inside "ConnectedAP" element) */ +typedef struct scl_gse + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct scl_gse *next; /* CRITICAL: DON'T MOVE. */ + struct scl_gse *prev; /* CRITICAL: DON'T MOVE. */ + ST_CHAR ldInst[MAX_IDENT_LEN+1]; + ST_CHAR cbName[MAX_IDENT_LEN+1]; + ST_UCHAR MAC[CLNP_MAX_LEN_MAC]; /* Multicast MAC address */ + ST_UINT APPID; + ST_UINT VLANPRI; + ST_UINT VLANID; + /* renxiaobao GSE ½âÎö*/ + ST_UINT MinTime; + ST_UINT MaxTime; + } SCL_GSE; + +/* Data from "SMV" element (inside "ConnectedAP" element) */ +typedef struct scl_smv + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct scl_smv *next; /* CRITICAL: DON'T MOVE. */ + struct scl_smv *prev; /* CRITICAL: DON'T MOVE. */ + ST_CHAR ldInst[MAX_IDENT_LEN+1]; + ST_CHAR cbName[MAX_IDENT_LEN+1]; + ST_UCHAR MAC[CLNP_MAX_LEN_MAC]; /* Multicast MAC address */ + ST_UINT APPID; + ST_UINT VLANPRI; + ST_UINT VLANID; + } SCL_SMV; + +/* Data from "ConnectedAP" element */ +typedef struct scl_cap + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct scl_cap *next; /* CRITICAL: DON'T MOVE. */ + struct scl_cap *prev; /* CRITICAL: DON'T MOVE. */ + ST_CHAR iedName[MAX_IDENT_LEN+1]; + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR apName[MAX_IDENT_LEN+1]; + SCL_GSE *gseHead; /* head of list of GSE defs */ + SCL_SMV *smvHead; /* head of list of SMV defs */ + } SCL_CAP; + +/* Data from "Subnetwork" element */ +typedef struct scl_subnet + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct scl_subnet *next; /* CRITICAL: DON'T MOVE. */ + struct scl_subnet *prev; /* CRITICAL: DON'T MOVE. */ + ST_CHAR name[MAX_IDENT_LEN+1]; + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR type[MAX_IDENT_LEN+1]; + SCL_CAP *capHead; /* head of list of ConnectedAP defs */ + } SCL_SUBNET; + +/************************************************************************/ +/* Structures to contain information from "AccessPoint" section of SCL.*/ +/************************************************************************/ + +/* "scl_fcda_add" allocates this struct, fills it in, */ +/* and adds it to the linked list "fcdaHead" in SCL_DATASET. */ +typedef struct + { + DBL_LNK l; + ST_CHAR domName[MAX_IDENT_LEN+1]; /* domain name (constructed) */ + ST_CHAR ldInst [MAX_IDENT_LEN+1]; + ST_CHAR prefix [MAX_IDENT_LEN+1]; + ST_CHAR lnInst [MAX_IDENT_LEN+1]; + ST_CHAR lnClass [MAX_IDENT_LEN+1]; + ST_CHAR doName [MAX_IDENT_LEN+1]; + ST_CHAR daName [MAX_IDENT_LEN+1]; + ST_CHAR fc [MAX_FC_LEN+1]; /* ST, MX, etc. */ + } SCL_FCDA; + +/* "scl_dai_add" allocates this struct, fills it in, */ +/* and adds it to the linked list "daiHead" in SCL_LN. */ +/* The "flattened" name must be constructed from the "name" & "ix" */ +/* attribute of the DOI and DAI and possibly the intervening SDI, */ +/* where "ix" is an array index (we'll need some new flattened name */ +/* syntax to handle the array index). */ +/* The "accessControl" attr of DOI is ignored (don't know what it means).*/ +/* The "desc" attr of DOI, SDI, & DAI are ignored (not useful). */ +typedef struct + { + DBL_LNK l; + ST_CHAR flattened[MAX_FLAT_LEN+1]; /* flattened attribute name */ + /* constructed from "name" & "ix"*/ + /* from DOI, SDI, & DAI */ + ST_CHAR *Val; /* attribute value text */ + /* allocate appropriate size buffer*/ + ST_UINT sGroup; /* optional Setting Group Number*/ + ST_CHAR sAddr[MAX_IDENT_LEN+1]; /* from DAI */ + ST_CHAR valKind[MAX_VALKIND_LEN+1]; /* from DAI */ + } SCL_DAI; + +/*renxiaobao Êý¾ÝÓ³Éä*/ +typedef struct +{ + DBL_LNK l; + ST_CHAR ldevice[MAX_IDENT_LEN+1]; + ST_CHAR leaf[MAX_IDENT_LEN+1]; + ST_CHAR usr_data_info[MAX_IDENT_LEN+1]; +}DATA_MAP_LINK; +extern DATA_MAP_LINK *DATA_MAP_saddr; + + +/* "scl_dataset_add" allocates this struct, */ +/* and adds it to the linked list "datasetHead" in SCL_LN. */ +typedef struct + { + DBL_LNK l; + ST_CHAR name[MAX_IDENT_LEN+1]; /* dataset name */ + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + SCL_FCDA *fcdaHead; /* head of list of FCDA */ + } SCL_DATASET; + +/* "scl_rcb_add" allocates this struct, fills it in, */ +/* and adds it to the linked list "rcbHead" in SCL_LN. */ +typedef struct + { + DBL_LNK l; + ST_CHAR name[MAX_IDENT_LEN+1]; + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR datSet[MAX_IDENT_LEN+1]; + ST_UINT intgPd; + ST_CHAR rptID[MAX_IDENT_LEN+1]; + ST_UINT confRev; + ST_BOOLEAN buffered; /* TRUE if this is buffered RCB */ + ST_UINT bufTime; + ST_UINT8 TrgOps [1]; /* 8-bit bitstring */ + /* Boolean vals from SCL file */ + /* (dchg, qchg, dupd, & period) */ + /* used to set bits in TrgOps bitstring */ + ST_UINT8 OptFlds [2]; /* 9-bit bitstring */ + /* Boolean vals from SCL file */ + /* (seqNum, timeStamp, dataSet, */ + /* reasonCode, dataRef, bufOvfl, */ + /* entryID, configRef) */ + /* segmentation boolean is ignored */ + /* used to set bits in OptFlds bitstring*/ + ST_UINT maxClient; /* value of "RptEnabled max" attr. */ + } SCL_RCB; /* Report Control Block */ + +typedef struct + { + /* Counters of different types of BRCB. */ + ST_UINT brcb_count_complex; + ST_UINT brcb_count_ST; + ST_UINT brcb_count_MX; + ST_UINT brcb_count_CO; + ST_UINT brcb_count_SP; + ST_UINT brcb_count_SG; + ST_UINT brcb_count_SE; + ST_UINT brcb_count_SV; + ST_UINT brcb_count_CF; + ST_UINT brcb_count_DC; + ST_UINT brcb_count_EX; + + /* Counters of different types of URCB. */ + ST_UINT urcb_count_complex; + ST_UINT urcb_count_ST; + ST_UINT urcb_count_MX; + ST_UINT urcb_count_CO; + ST_UINT urcb_count_SP; + ST_UINT urcb_count_SG; + ST_UINT urcb_count_SE; + ST_UINT urcb_count_SV; + ST_UINT urcb_count_CF; + ST_UINT urcb_count_DC; + ST_UINT urcb_count_EX; + } SCL_RCB_COUNTERS; + +/************************************************************************/ +/* LOG Control Block */ +/* "scl_lcb_add" allocates this struct, fills it in, */ +/* and adds it to the linked list "lcbHead" in SCL_LN. */ +typedef struct + { + DBL_LNK l; + ST_CHAR name[MAX_IDENT_LEN+1]; + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR datSet[MAX_IDENT_LEN+1]; + ST_UINT intgPd; + ST_CHAR logName[MAX_IDENT_LEN+1]; + ST_BOOLEAN logEna; + ST_BOOLEAN reasonCode; + ST_UINT8 TrgOps [1]; /* 8-bit bitstring */ + /* Boolean vals from SCL file */ + /* (dchg, qchg, dupd, & period) */ + /* used to set bits in TrgOps bitstring */ + } SCL_LCB; + +/************************************************************************/ +/* GOOSE Control Block */ +/* "scl_gcb_add" allocates this struct, fills it in, */ +/* and adds it to the linked list "gcbHead" in SCL_LN. */ +typedef struct + { + DBL_LNK l; + ST_CHAR name[MAX_IDENT_LEN+1]; /* Name of CB. Used to construct*/ + /* GoCBRef or GsCBRef */ + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR datSet[MAX_IDENT_LEN+1]; /* for GOOSE only */ + /* used to construct GOOSE DatSet*/ + ST_UINT confRev; /* for GOOSE only */ + ST_BOOLEAN isGoose; /* SD_TRUE if "GOOSE", SD_FALSE if "GSSE"*/ + ST_CHAR appID[MVL61850_MAX_RPTID_LEN+1]; /* for GOOSE only */ + /* maps to GoID in 61850-7-2 */ + /* The SCL file may also contain one or more "IEDName" elements to */ + /* indicate IEDs that should subscribe for GOOSE data. We have no */ + /* way to use this information, so it is ignored. */ + } SCL_GCB; + +/************************************************************************/ +/* Sampled Value Control Block */ +/* "scl_parse" allocates this struct and fills it in. */ +/* "scl_svcb_add" adds it to the linked list "svcbHead" in SCL_LN. */ +typedef struct + { + DBL_LNK l; + ST_CHAR name[MAX_IDENT_LEN+1]; + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR datSet[MAX_IDENT_LEN+1]; + ST_CHAR smvID[MAX_IDENT_LEN+1]; + ST_UINT smpRate; + ST_UINT nofASDU; + ST_UINT confRev; + ST_BOOLEAN multicast; /* TRUE if this is MsvCB */ + ST_UINT8 OptFlds [1]; /* 8-bit bitstring */ + /* Boolean vals from "SmvOpts" in SCL */ + /* (sampleRate, etc.) */ + /* used to set bits in this bitstring */ + ST_BOOLEAN securityPres; /* SmvOpts security flag */ + ST_BOOLEAN dataRefPres; /* SmvOpts dataRef flag */ + } SCL_SVCB; /* Sampled Value Control Block */ + +/************************************************************************/ +/* Setting Group Control Block */ +typedef struct + { + /* NOTE: no DBL_LNK here. Only 2 allowed so never put on a linked list.*/ + ST_CHAR *desc; /* description (optional) */ + /* may be long so allocate if present */ + ST_UINT numOfSGs; /* mandatory */ + ST_UINT actSG; /* optional */ + } SCL_SGCB; + +/************************************************************************/ +/* Logical Node structure */ +/* "scl_ln_add" allocates this struct, fills it in, */ +/* and adds it to the linked list "lnHead" in SCL_LD. */ +typedef struct + { + DBL_LNK l; + ST_CHAR varName[MAX_IDENT_LEN+1]; /* variable name (constructed) */ + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR lnType[MAX_IDENT_LEN+1]; /* LN Type name */ + ST_CHAR lnClass[MAX_IDENT_LEN+1]; /* LN Class name */ + /* for LN0, must be "LLN0" */ + ST_CHAR inst[MAX_IDENT_LEN+1]; /* LN inst name */ + /* for LN0, must be "" (empty string)*/ + ST_CHAR prefix[MAX_IDENT_LEN+1]; /* LN prefix name */ + /* for LNO, ignored */ + SCL_DAI *daiHead; /* head of list of DAI */ + SCL_DATASET *datasetHead; /* head of list of DataSet */ + SCL_RCB *rcbHead; /* head of list of RCB (Report Control) */ + SCL_LCB *lcbHead; /* head of list of LCB (Log Control) */ + SCL_GCB *gcbHead; /* head of list of GCB (GOOSE Control) */ + SCL_SVCB *svcbHead; /* head of list of SVCB (Sampled Value Control)*/ + SCL_SGCB *sgcb; /* SGCB (Setting Group Control)(only 1 allowed)*/ + /* NOTE: In LN or LN0: Inputs ignored */ + /* NOTE: In LN0: SCLControl ignored */ + + ST_INT type_id; /* Initialized by "scl2_datatype_create_all"*/ + MVL_VAR_ASSOC *mvl_var_assoc; /* MVL Variable Association created from LN info*/ + } SCL_LN; /* Logical Node (LN or LN0 in SCL) */ + +/************************************************************************/ +/* Logical Device structure */ +/* "scl_ld_create" allocates this struct */ +/* and adds it to the linked list "ldHead" in SCL_INFO. */ +typedef struct + { + DBL_LNK l; + ST_CHAR domName[MAX_IDENT_LEN+1]; /* domain name (constructed) */ + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR inst[MAX_IDENT_LEN+1]; /* LD inst name */ + SCL_LN *lnHead; /* head of list of LN */ + /* NOTE: AccessControl in LDevice is ignored */ + } SCL_LD; /* Logical Device (LDevice in SCL)*/ + +/************************************************************************/ +/* Structures to contain information from "DataTypeTemplates" section of SCL.*/ +/************************************************************************/ +/* This structure should be allocated and filled in by the function */ +/* "scl_lntype_add_do". */ +typedef struct scl_do + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct scl_do *next; /* CRITICAL: DON'T MOVE. */ + struct scl_do *prev; /* CRITICAL: DON'T MOVE. */ + ST_CHAR name[MAX_IDENT_LEN+1]; /* data object name */ + ST_CHAR type[MAX_IDENT_LEN+1]; /* data object type */ + } SCL_DO; + +typedef struct scl_lntype + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct scl_lntype *next; /* CRITICAL: DON'T MOVE. */ + struct scl_lntype *prev; /* CRITICAL: DON'T MOVE. */ + ST_CHAR id[MAX_IDENT_LEN+1]; /* name used to reference this LN Type*/ + ST_CHAR lnClass[MAX_IDENT_LEN+1]; /* logical node class */ + SCL_DO *doHead; /* head of list of DO */ + /* scl_lntype_add_do adds to list */ + ST_INT type_id; /* Initialized by "scl2_datatype_create_all"*/ + } SCL_LNTYPE; + + +/* This structure should be allocated and filled in by the function */ +/* "scl_dotype_add_da" OR "scl_dotype_add_sdo", and possibly modified by the optional */ +/* function "scl_dotype_add_da_val". */ +/* NOTE: the same structure must be used for DA or SDO because each must */ +/* be put on the same linked list in the order they are read from the SCL file.*/ +/* Most of the parameters are relevant only for DA elements. They are */ +/* ignored if this is an SDO (i.e. objtype=SCL_OBJTYPE_SDO). */ +typedef struct + { + DBL_LNK l; + ST_INT objtype; /* SCL_OBJTYPE_DA or SCL_OBJTYPE_SDO */ + ST_CHAR name[MAX_IDENT_LEN+1]; /* DA or SDO name */ + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR sAddr[MAX_IDENT_LEN+1]; /* for DA only: DA sAddr */ + ST_CHAR bType[MAX_IDENT_LEN+1]; /* for DA only: DA bType */ + ST_CHAR valKind[MAX_VALKIND_LEN+1]; /* for DA only: Spec, Conf, RO, or Set */ + ST_CHAR type[MAX_IDENT_LEN+1]; /* for DA: needed if bType="Struct" or "Enum"*/ + /* for SDO: required */ + ST_UINT count; /* for DA only: num array entries*/ + ST_CHAR fc[MAX_FC_LEN+1]; /* for DA only: functional constraint */ + ST_BOOLEAN dchg; /* for DA only: TrgOp (data change) */ + ST_BOOLEAN qchg; /* for DA only: TrgOp (quality change) */ + ST_BOOLEAN dupd; /* for DA only: TrgOp (data update) */ + + /* The "Val" and "sGroup" parameters are only set if the SCL file contains the + * optional "Val" element, in which case "scl_dotype_add_da_val" is called. + */ + ST_CHAR *Val; /* for DA only: attribute value text */ + /* allocate appropriate size buffer*/ + ST_UINT sGroup; /* for DA only: optional Setting Group Number*/ + } SCL_DA; + +typedef struct scl_dotype + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct scl_dotype *next; /* CRITICAL: DON'T MOVE. */ + struct scl_dotype *prev; /* CRITICAL: DON'T MOVE. */ + ST_CHAR id[MAX_IDENT_LEN+1]; /* name used to reference this DO Type */ + ST_CHAR cdc[MAX_CDC_LEN+1]; /* CDC name */ + SCL_DA *daHead; /* head of list of DA or SDO */ + /* scl_dotype_add_da OR */ + /* scl_dotype_add_sdo adds to list */ + } SCL_DOTYPE; + +/* This structure should be allocated and filled in by the function */ +/* "scl_datype_add_bda". */ +typedef struct + { + DBL_LNK l; + ST_CHAR name[MAX_IDENT_LEN+1]; /* data attribute name */ + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR sAddr[MAX_IDENT_LEN+1]; /* for DA only: DA sAddr */ + ST_CHAR bType[MAX_IDENT_LEN+1]; /* data attribute type */ + ST_CHAR valKind[MAX_VALKIND_LEN+1]; /* Spec, Conf, RO, or Set */ + ST_CHAR type[MAX_IDENT_LEN+1]; /* only used if btype="Struct" or "Enum"*/ + ST_UINT count; /* for DA only: num array entries*/ + + /* The "Val" and "sGroup" parameters are only set if the SCL file contains the + * optional "Val" element, in which case "scl_datype_add_bda_val" is called. + */ + ST_CHAR *Val; /* attribute value text */ + /* allocate appropriate size buffer*/ + ST_UINT sGroup; /* optional Setting Group Number*/ + } SCL_BDA; /* Basic Data Attribute */ +typedef struct + { + DBL_LNK l; + ST_CHAR id[MAX_IDENT_LEN+1]; /* name used to reference this DA Type*/ + SCL_BDA *bdaHead; /* head of list of BDA */ + /* scl_datype_add_bda adds to list */ + } SCL_DATYPE; + + +/* This structure should be allocated and filled in by the function */ +/* "scl_enumtype_add_enumval". */ +typedef struct + { + DBL_LNK l; + ST_INT ord; /* ord attribute */ + ST_CHAR EnumVal[MAX_IDENT_LEN+1]; /* EnumVal element */ + /* TRUNCATED if longer than buffer */ + } SCL_ENUMVAL; +typedef struct + { + DBL_LNK l; + ST_CHAR id[MAX_IDENT_LEN+1]; /* name used to reference this DA Type*/ + SCL_ENUMVAL *enumvalHead; /* head of list of EnumVal */ + /* scl_enumtype_add_enumval adds to list*/ + } SCL_ENUMTYPE; + +/************************************************************************/ +/* SCL_INFO */ +/* This structure contains all information extracted from the SCL file */ +/* to be used for MMS-EASE Lite initialization. */ +/************************************************************************/ +typedef struct + { + ST_CHAR iedName [MAX_IDENT_LEN+1]; /* passed to scl_parse */ + + SCL_HEADER Header; /* Info from "Header" section of SCL file*/ + + /* SubNetwork definitions from (from Communication section) */ + SCL_SUBNET *subnetHead; /* head of list of SubNetwork defs */ + + /* Logical Node Type definitions (from DataTypeTemplates section) */ + SCL_LNTYPE *lnTypeHead; /* head of list of LNodeType defs */ + SCL_DOTYPE *doTypeHead; /* head of list of DOType defs */ + SCL_DATYPE *daTypeHead; /* head of list of DAType defs */ + SCL_ENUMTYPE *enumTypeHead; /* head of list of EnumType defs */ + + /* Logical Device (MMS Domain) definitions (from AccessPoint section) */ + SCL_LD *ldHead; /* head of list of LDevice defs */ + + ST_INT brcb_bufsize; /* BRCB buffer size */ + /* scl2_ld_create_all uses arg to set it*/ + ST_BOOLEAN datatype_create_done; /* flag set by scl2_datatype_create_all*/ + ST_BOOLEAN ld_create_done; /* flag set by scl2_ld_create_all*/ + } SCL_INFO; + + +/************************************************************************/ +/************************************************************************/ +/* FUNCTIONS to store SCL info in "SCL_INFO" structure. */ +/************************************************************************/ +/************************************************************************/ + +SCL_LNTYPE *scl_lntype_create ( + SCL_INFO *scl_info); + +SCL_DO *scl_lntype_add_do ( + SCL_INFO *scl_info); + +SCL_DOTYPE *scl_dotype_create ( + SCL_INFO *scl_info); + +SCL_DA *scl_dotype_add_da ( + SCL_INFO *scl_info); + +SCL_DA *scl_dotype_add_sdo ( + SCL_INFO *scl_info); + +SCL_DATYPE *scl_datype_create ( + SCL_INFO *scl_info); + +SCL_BDA *scl_datype_add_bda ( + SCL_INFO *scl_info); + +SCL_ENUMTYPE *scl_enumtype_create ( + SCL_INFO *scl_info); + +SCL_ENUMVAL *scl_enumtype_add_enumval ( + SCL_INFO *scl_info); + +SCL_FCDA *scl_fcda_add ( + SCL_INFO *scl_info); + +SCL_DAI *scl_dai_add ( + SCL_INFO *scl_info); + +SCL_DATASET *scl_dataset_add ( + SCL_INFO *scl_info); + +SCL_RCB *scl_rcb_add ( + SCL_INFO *scl_info); + +SCL_LCB *scl_lcb_add ( + SCL_INFO *scl_info); + +SCL_GCB *scl_gcb_add ( + SCL_INFO *scl_info); + +SCL_SGCB *scl_sgcb_add ( + SCL_INFO *scl_info); + +SCL_SVCB *scl_svcb_add ( + SCL_INFO *scl_info); + +SCL_LN *scl_ln_add ( + SCL_INFO *scl_info); + +SCL_LD *scl_ld_create ( + SCL_INFO *scl_info); + +SCL_SUBNET *scl_subnet_add ( + SCL_INFO *scl_info); + +SCL_CAP *scl_cap_add ( + SCL_INFO *scl_info); + +SCL_GSE *scl_gse_add ( + SCL_INFO *scl_info); + +SCL_SMV *scl_smv_add ( + SCL_INFO *scl_info); + +/************************************************************************/ +/* scl_parse */ +/* Parses SCL file and stores extracted info in SCL_INFO structure. */ +/************************************************************************/ +ST_RET scl_parse (ST_CHAR *xmlFileName, ST_CHAR *iedName, + ST_CHAR *accessPointName, SCL_INFO *sclInfo); +ST_VOID scl_log_all (SCL_INFO *scl_info); + +/************************************************************************/ +/* scl_info_destroy */ +/* Destroy all info stored in the SCL_INFO structure by "scl_parse". */ +/************************************************************************/ +ST_VOID scl_info_destroy (SCL_INFO *scl_info); + +/************************************************************************/ +/* scl2_datatype_create_all */ +/* Create MMS Data types for all Logical Node Types (LNodeType) */ +/* defined in SCL. */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +ST_RET scl2_datatype_create_all ( + MVL_VMD_CTRL *vmd_ctrl, /* VMD in which to add types. */ + SCL_INFO *sclInfo, /* main struct where all SCL info stored*/ + ST_INT max_rt_num, /* max num of RUNTIME_TYPE for each LNodeType*/ + ST_BOOLEAN use_names, /* if SD_TRUE, generate a name for each type*/ + ST_CHAR *name_prefix); /* unique prefix to add to each type name*/ + /* only used if "use_names==SD_TRUE". */ + +/************************************************************************/ +/* scl2_ld_create_all */ +/* Create all Logical Devices from SCL info saved in "sclInfo". */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +ST_RET scl2_ld_create_all ( + MVL_VMD_CTRL *vmd_ctrl, /* VMD in which to add Logical Devices. */ + SCL_INFO *sclInfo, /* main struct where all SCL info stored*/ + ST_UINT reportScanRate, /* report scan rate (millisec) */ + ST_INT brcb_bufsize, /* BRCB buffer size */ + ST_BOOLEAN is_client); /* If this flag is set, Client model is */ + /* created (i.e. Control Blocks NOT created).*/ + +/************************************************************************/ +/* u_set_all_leaf_functions */ +/* User customizable function to set all leaf functions for a data type.*/ +/************************************************************************/ +ST_RET u_set_all_leaf_functions (RUNTIME_CTRL *rt_ctrl); + + +/************************************************************************/ +/************************************************************************/ + +extern ST_BOOLEAN scl_debug_mode; +extern ST_INT scl_debug_mode_error_count; + +typedef struct + { + DBL_LNK l; + ST_CHAR *btype; + RUNTIME_CTRL *rt_ctrl; + } SCL2_BTYPE; +extern SCL2_BTYPE *scl2_btype_list; +SCL2_BTYPE *scl2_add_btype (ST_CHAR *btype, ST_CHAR *tdl); + + + +typedef struct + { + SCL_INFO *scl_info; + SCL_LD *scl_ld; + SCL_LN *scl_ln; + ST_CHAR *valText; + ST_CHAR *attrib; + ST_VOID *dest; + ST_INT numRt; + SD_CONST RUNTIME_TYPE *rtHead; + } SCL2_IV_TRANSLATE_CTRL; + +ST_RET u_mvl_scl_set_initial_value (SCL2_IV_TRANSLATE_CTRL *sclXlateIv); + +/************************************************************************/ +/* Functions to find objects in SCL_INFO. */ +/************************************************************************/ +SCL_GSE *scl_gse_find (SCL_INFO *scl_info, SCL_LD *scl_ld, SCL_GCB *scl_gcb); + +#ifdef __cplusplus +} +#endif + +#endif /* !SCL_INCLUDED */ diff --git a/include/inc/scrndefs.h b/include/inc/scrndefs.h new file mode 100644 index 0000000..bd1d40b --- /dev/null +++ b/include/inc/scrndefs.h @@ -0,0 +1,97 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2005, All Rights Reserved */ +/* */ +/* MODULE NAME : scrndefs.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : This include file contains definitions needed */ +/* for screen handling */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/06/05 EJV 20 linux: no fancy screen. */ +/* 03/31/03 EJV 19 Removed _WINDOWS code. */ +/* 03/18/03 JRB 18 Fix QNX #ifdefs. */ +/* 02/17/03 CRM 17 Added "defined(linux)" code. */ +/* 02/17/03 JRB 16 Stop using SYSTEM_SEL define. */ +/* Del QNX_C86 support. */ +/* 08/24/98 EJV 15 Eliminated semicoln in some macros. */ +/* 04/29/98 EJV 14 CLEARSCR on sparc beeps. */ +/* 01/08/98 EJV 13 Deleted CLEARSCR specific to sun sparc */ +/* 05/16/97 RKR 12 Changes for HP-UX */ +/* 12/07/95 DSF 11 Minor corrections */ +/* 11/08/95 MDE 10 Tweaked WINDOWS defines a bit */ +/* 05/04/95 JRB 09 Added SYS_QNX4 for QNX 4.x port. */ +/* 05/04/95 JRB 08 Simplified macros: removed LINE?COL?, */ +/* added GOTOLINE(line) an CLEARLINE(line). */ +/* 04/20/95 KCW 07 Changes for SUN Solaris */ +/* 01/05/95 JRB 06 Change BSD to SYS_BSD. */ +/* 12/09/94 JRB 05 Disable ANSI escape sequences for VXWORKS. */ +/* 10/12/93 DSF 04 Changed MMSWIN to _WINDOWS */ +/* 04/08/93 WEO 03 Added MMSWIN defines for screen formatting */ +/* 12/03/92 JRB 02 Added LINE9COL0 for QNX. */ +/* 04/16/92 WEO 01 Added CLEARSCR for SUN */ +/* 06/25/91 5.00 MMSEASE 5.0 release. See UTILML50.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef SCRNDEFS_INCLUDED +#define SCRNDEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__QNX__) + +#define CLEARSCR printf( "\33H\33J" ) +#define SAVESCR printf( "\33S" ) +#define BOTTOMSCR printf( "\33=7 " ) /* "7" means row 23, " " means col 0 */ +#define CLEAREOL printf( "\33K" ) +#define GOTOLINE(line) printf("\33=%c ",line+0x1f) /* line=1 thru 24*/ +#define CLEARLINE(line) printf("\33=%c \33K",line+0x1f) /* line=1 thru 24*/ + +#else /* non QNX system */ + +#if defined (_WIN32) || defined (VXWORKS) || \ + defined(__hpux) || defined(sparc) || defined(linux) +#define CLEARSCR printf("\n") +#define RESTORESCR +#define SAVESCR +#define BOTTOMSCR +#define CLEAREOL +#define GOTOLINE(line) printf("\n") +#define CLEARLINE(line) +#else +#define CLEARSCR printf( "\33[2J\33[0;0H" ) +#define RESTORESCR printf( "\33[u" ) +#define SAVESCR printf( "\33[s" ) +#define BOTTOMSCR printf( "\33[23;0H" ) +#define CLEAREOL printf( "\33[K" ) +#define GOTOLINE(line) printf( "\33[%d;1H", line) /* line= 1 thru 24*/ +#define CLEARLINE(line) printf( "\33[%d;1H\33[K", line) /* line= 1 thru 24*/ +#endif +#endif + +#define PRINTSTR printf( "%s", str_ptr ) +#define ADD_LF printf( "\n" ) + +#if defined(_AIX) || defined(sun) || defined(__hpux) || defined(linux) \ + || (defined(__alpha) && !defined(__VMS)) \ + || defined(VXWORKS) || defined(__QNX__) +#define CR '\012' +#else +#define CR '\015' +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/inc/slog.h b/include/inc/slog.h new file mode 100644 index 0000000..3fccaf8 --- /dev/null +++ b/include/inc/slog.h @@ -0,0 +1,1599 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2008, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : slog.h */ +/* PRODUCT(S) : SLOG */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/01/08 JRB 82 Move forward references to top of file. */ +/* 11/07/08 MDE 82 Added 'Get Log Masks' feature support */ +/* 10/08/08 MDE 81 Added SEAL */ +/* 08/22/08 RKR 80 Added ICCP Lite */ +/* 08/11/08 MDE 79 Added 'initialized' */ +/* 08/04/08 MDE 78 Added slogIpcEventEx */ +/* 07/30/08 DWL 77 Added COMTRADE listening port */ +/* 07/25/08 MDE 76 Moved slogIpcCtx into LOG_CTRL */ +/* 07/07/08 MDE 75 Added slogIpcActiveCount */ +/* 05/09/08 RKR 74 Added new IPC Commands for Clone and Reset */ +/* 03/27/08 EJV 73 slog_get_index_file_name: added destLen param*/ +/* and changed to return result. */ +/* 03/04/08 EJV 72 Added IPC_LOG_PORT_SNAP_LITE_* ports. */ +/* Removed MMSEASE_MOSI def in description. */ +/* Added LogMaskMapCtrl for 142-XXX products, */ +/* revised comments. */ +/* 03/10/08 MDE 71 Added slog_ipc_std_cmd_service */ +/* 03/04/08 RWM 70 Changed MAX_LOG_SIZE to 5000 */ +/* 12/14/07 DSF 69 Added sNonStandardLogMode to support .NET */ +/* Logger class */ +/* 11/30/07 DSF 68 Added IPC_LOG_IOS_GATEWAY */ +/* 11/08/07 MDE 67 Added IPC_LOG_PORT_SDE_OPCUA_SERVER */ +/* 10/23/07 MDE 66 Added ElapsedTime option for Windows */ +/* 10/11/07 MDE 65 Added UAP ports */ +/* 09/20/07 MDE 64 Added slogIpcCallingEnable, listen port */ +/* 03/01/07 MDE 63 Tweaks to SLOGIPC command message types */ +/* 02/20/07 CRM 62 Added SLOGIPCCALLING_NAME */ +/* 01/22/07 MDE 61 Added Standard command message types */ +/* 01/08/07 EJV 60 slogIpcStop: added lc param. */ +/* 04/07/06 MDE 59 Added IPC_LOG_PORT_ICCPCFG */ +/* 03/14/06 MDE 58 Increased SLOG_MAX_FNAME to 64 (was 32) */ +/* 03/30/06 CRM 57 Added _slogXML, and macros */ +/* 02/17/06 MDE 56 Added logcfg_exx, preferredTag, etc.. */ +/* 02/15/06 EJV 55 IPC_LOG_PORT_MMS_EASE - changed comment. */ +/* 02/02/06 EJV 54 LOGCFGX_TAG_VAL: added/changed fields. */ +/* 12/05/05 EJV 53 Added IPC_LOG_PORT_MMS_EASE. Changed comment.*/ +/* 10/28/05 EJV 52 Added MMS-LITE ports */ +/* 10/14/05 EJV 51 Add SLOGIPC_NAME def & slogIpcEvent proto */ +/* 08/10/05 MDE 50 Added slog_start, slog_end, index file */ +/* 08/05/05 EJV 49 Added extern ssleLogMaskMapCtrl. */ +/* 08/02/05 MDE 48 Added IOS ports */ +/* 06/30/05 EJV 47 Added extern genlistDebugMapCtrl. */ +/* Arranged xxxMaskMapCtrl in alphabetical order*/ +/* Del duplicate logCfgAddMaskGroup proto. */ +/* Del logCfgAddAll proto (user must add all). */ +/* Del logcfgx (use logcfgx_ex instead) */ +/* 04/29/05 EJV 46 Added IPC_LOG_PORT_RFC1006_LISTENER def. */ +/* 03/31/05 MDE 45 Added more SLOGALWAYS macros */ +/* 02/22/05 JRB 44 slogIpc: add SD_CONST to some args. */ +/* 02/16/05 JRB 43 Del #if around forward references. */ +/* 02/10/05 MDE 42 Added STRINGBUF and DOUBLE DATATYPE's */ +/* 02/02/05 MDE 41 Smart mode work */ +/* 01/27/05 MDE 40 LINUX warning cleanup */ +/* 01/19/05 MDE 39 Added LogCfg defines, etc.. */ +/* 01/19/05 EJV 38 AIX:del extern in struct tag_GEN_SOCK,C++ err*/ +/* 12/06/04 ASK 37 Added SLOG IPC "smart" client features. Added*/ +/* RUINT define for new logcfgx. */ +/* 11/22/04 JRB 36 Add max_msg_size & msg_buf to LOG_CTRL. */ +/* Add slog_max_msg_size_set proto. */ +/* Add slog_max_msg_size_get macro. */ +/* slogDelBuf: add (LOG_CTRL *) arg. */ +/* 10/12/04 MDE 35 Added logcfgx mask extension mechanism */ +/* 08/04/04 EJV 34 LOGMEM_ITEM: chg log time,related to prev chg*/ +/* Del slogTime, slogMs global variables. */ +/* 07/09/04 EJV 33 Del DATETIME_MILLI_EN,add 'obsolete' comments*/ +/* 06/24/04 DSF 32 Added DATETIME_MILLI_EN */ +/* 06/24/04 EJV 31 IPC_LOG_CTRL: add portUsed. */ +/* 06/21/04 EJV 30 IPC_LOG_CTRL: add portCnt, appId fields. */ +/* 05/26/04 EJV 29 Added comment to keep track on used IPC ports*/ +/* 05/20/04 EJV 28 IPC_LOG_CTRL: limited log message queue. */ +/* 05/18/04 MDE 27 Removed LOG_IPC_SUPPORT #ifdef's */ +/* 05/11/04 EJV 26 Revised LOG_IPC_SUPPORT code to use gensock2.*/ +/* Added SLOG_MAX_LOGTYPESTR, SLOG_MAX_HDR. */ +/* Added slogSetHdr() proto. */ +/* 02/10/04 KCR 25 Added slogDelBuf() */ +/* 10/24/03 JRB 24 Move gs_debug_sel from glbsem.h to here. */ +/* Move clnp_debug_sel from clnp_usr.h to here. */ +/* Del windows.h (see sysincs.h). */ +/* 06/20/03 JRB 23 Del ; from SLOGALWAYS* too. */ +/* 05/08/03 JRB 22 Del {} from SLOGALWAYS* so they work in */ +/* almost any context. */ +/* 05/07/03 DSF 21 Increased the value of SLOG_MAX_FNAME */ +/* Added support for sErrLogCtrl */ +/* 10/17/02 JRB 20 Add "Base" macros SLOG_*, SLOGC_*, SLOGH. */ +/* 03/11/02 JRB 19 SLOG_PAUSE, SLOG_LF, SLOG_CLRSCR do nothing. */ +/* 04/26/01 DSF 18 Define SOCKET if not yet defined */ +/* 04/16/01 DSF 17 Include windows.h instead of including */ +/* winsock.h directly */ +/* 03/23/01 MDE 16 Added _slogStr, SLOGALWAYSS */ +/* 11/27/00 JRB 15 Added read_log_cfg_file, logcfgx protos. */ +/* 08/22/00 KCR 14 Added FIL_CTRL_NO_LOG_HDR */ +/* 03/09/00 MDE 13 Added SD_CONST modifiers to LOGMEM_ITEM */ +/* 09/13/99 MDE 12 Added SD_CONST modifiers */ +/* 11/11/98 DSF 11 Minor changes to _slog_dyn_log_fun */ +/* 10/16/98 DSF 10 Spelling */ +/* 10/08/98 MDE 09 Migrated to updated SLOG interface */ +/* 06/15/98 NAV 08 Conditionally include winsock.h or winsock2.h*/ +/* 06/03/98 MDE 07 Replaced 'winsock.h' with 'windows.h' */ +/* 12/12/97 MDE 06 Added DEBUG_SISCO versions of SLOGALWAYSx */ +/* 11/05/97 DSF 05 Added SYSTIME_EN */ +/* 09/12/97 DSF 04 Expose slogSetTimeText () */ +/* 06/11/97 MDE 03 Include time.h for all */ +/* 05/27/97 DSF 02 Added IPC logging capability */ +/* 05/27/97 DSF 01 Include time.h for sun */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef SLOG_INCLUDED +#define SLOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + + +/*#define SLOGIPC_SEAL Disable for now, phase in ... */ + +#include "gen_list.h" +#ifdef SLOGIPC_SEAL +#include "sseal.h" +#endif + +#include +#include /* for time_t */ + +#define TIME_BUF_LEN 30 + +/************************************************************************/ +struct tag_GEN_SOCK; /* forward reference */ +struct tag_GEN_SOCK_DATA; /* forward reference */ +struct log_ctrl; /* forward reference */ + +/************************************************************************/ +/* Memory logging string buffer size limit */ +/* NOTE : Do not change this lightly! QMEM.C should be looked at */ +/************************************************************************/ + +#define SLOG_MEM_BUF_SIZE 125 + +/* Memory logging item control */ +/* A table of these is established at initialization time */ + +#define LMF_USED 0x0001 +#define LMF_HEADER 0x0002 +#define LMF_HEX 0x0004 + + +typedef struct logmem_item + { + ST_UINT flags; /* see LMF_xxx flags */ + ST_INT logType; /* log type storage */ + SD_CONST ST_CHAR *logTypeStr; /* log type string */ + ST_INT lineNum; /* source file line number */ + SD_CONST ST_CHAR *sourceFile; /* source file name, NULL for none */ + ST_CHAR slogTimeText[TIME_BUF_LEN]; + ST_CHAR *string; /* text */ + } LOGMEM_ITEM; + + +/************************************************************************/ +/* File Logging State flags */ +/************************************************************************/ + +#define FIL_STATE_OPEN 0x0001 +#define FIL_STATE_NEED_WIPE 0x0002 + +/* File Logging Control flags */ + +#define FIL_CTRL_WIPE_EN 0x0001 +#define FIL_CTRL_WRAP_EN 0x0002 +#define FIL_CTRL_MSG_HDR_EN 0x0004 +#define FIL_CTRL_NO_LOG_HDR 0x0040 + +/* File output mode flags */ + +#define FIL_CTRL_NO_APPEND 0x0008 +#define FIL_CTRL_HARD_FLUSH 0x0010 +#define FIL_CTRL_SETBUF_EN 0x0020 + +typedef struct file_log_ctrl + { +/* User sets these elements */ + ST_ULONG maxSize; + ST_CHAR *fileName; /* destination filename */ + ST_UINT ctrl; /* see FIL_CTRL_xxx flags */ + ST_LONG wipeFilePos; + +/* Internal use only */ + ST_UINT state; /* see FIL_STATE_xxx flags */ + FILE *fp; + } FILE_LOG_CTRL; + +/* Memory Logging State flags */ + +#define MEM_STATE_INIT 0x0001 + +/* Memory Logging Control flags */ + +#define MEM_CTRL_MSG_HDR_EN 0x0001 +#define MEM_CTRL_AUTODUMP_EN 0x0002 +#define MEM_CTRL_HEX_LOG 0x0004 + +typedef struct mem_log_ctrl + { +/* User sets these elements */ + ST_INT maxItems; /* # items to allocate at powerup */ + ST_CHAR *dumpFileName; /* where memory dump goes */ + ST_UINT ctrl; /* see MEM_CTRL_xxx flags */ + +/* Internal use only */ + ST_UINT state; /* see MEM_STATE_xxx flags */ + LOGMEM_ITEM *item; /* Item table */ + ST_INT nextPut; /* Current position (where last was put */ + } MEM_LOG_CTRL; + +/************************************************************************/ +/* Socket Slogging Subsystem */ +/************************************************************************/ + +#define SLOGIPC_NAME "SLOGIPC" /* used in GEN_SOCK */ +#define SLOGIPCCALLING_NAME "SLOGIPCCALLING" /* used in GEN_SOCK */ + +/* Default listen port for LogViewer */ +#define IPC_LOG_LOGVIEWER_PORT 55146 + +/* default parameters for socket logging subsystem */ +#define IPC_LOG_BASE_PORT 55147 + +/* ports below are taken by following SISCO applications: */ +#define IPC_LOG_PORT_AXS4ICCP IPC_LOG_BASE_PORT+1 /* 55148 */ +#define IPC_LOG_PORT_OSILL2 IPC_LOG_BASE_PORT+2 /* 55149 */ +#define IPC_LOG_PORT_OSILL2_IPC IPC_LOG_BASE_PORT+3 /* 55150 */ +#define IPC_LOG_PORT_AXS4MMS IPC_LOG_BASE_PORT+4 /* 55151 */ +#define IPC_LOG_PORT_AXS4IEC61850 IPC_LOG_BASE_PORT+5 /* 55152 */ +#define IPC_LOG_PORT_AXS4GOOSE_OLD IPC_LOG_BASE_PORT+6 /* 55153 */ +#define IPC_LOG_PORT_RFC1006_LISTENER IPC_LOG_BASE_PORT+7 /* 55154 */ +#define IPC_LOG_PORT_ICCPCFG IPC_LOG_BASE_PORT+8 /* 55155 */ + +/* UIB ports: reserve 10: 55157-55167 */ +#define IPC_LOG_PORT_UIBBASE IPC_LOG_BASE_PORT+10 /* 55157 */ +#define IPC_LOG_NUMPORTS_UIB 10 + +#define IPC_LOG_PORT_SNAP_LITE_DAEMON IPC_LOG_BASE_PORT+33 /* 55180 */ +#define IPC_LOG_PORT_SNAP_LITE_UTIL IPC_LOG_BASE_PORT+34 /* 55181 */ + +/* MMS-EASE demo programs: reserve 10 55190-55199 */ +#define IPC_LOG_PORT_MMS_EASE IPC_LOG_BASE_PORT+43 /* 55190 */ + +/* MMS-LITE demo programs: reserve 10 55200-55209 */ +#define IPC_LOG_PORT_MMS_LITE IPC_LOG_BASE_PORT+53 /* 55200 */ + +/* ICCP-LITE demo programs: reserve 5 55210-55214 */ +#define IPC_LOG_PORT_ICCP_LITE IPC_LOG_BASE_PORT+63 /* 55210 */ + +/* USPS IOS ports: reserve 100 : 55347-55447 */ +#define IPC_LOG_IOS_MPECOM IPC_LOG_BASE_PORT+200 /* 55347 */ +#define IPC_LOG_IOS_MPE IPC_LOG_BASE_PORT+201 /* 55348 */ +#define IPC_LOG_IOS_GATEWAY IPC_LOG_BASE_PORT+202 /* 55349 */ + +/* UAP related elements */ +#define IPC_LOG_PORT_AXS4GOOSE IPC_LOG_BASE_PORT+300 /* 55447 */ +#define IPC_LOG_PORT_DSPI IPC_LOG_BASE_PORT+301 /* 55448 */ +#define IPC_LOG_PORT_SCLDEVLOADEX IPC_LOG_BASE_PORT+302 /* 55449 */ +#define IPC_LOG_PORT_UAPPC IPC_LOG_BASE_PORT+303 /* 55450 */ +#define IPC_LOG_PORT_GOOSEBLASTER IPC_LOG_BASE_PORT+304 /* 55451 */ +#define IPC_LOG_PORT_GOOSEBLASTERCONTROL IPC_LOG_BASE_PORT+305 /* 55452 */ +#define IPC_LOG_PORT_SDE_ATM IPC_LOG_BASE_PORT+306 /* 55453 */ +#define IPC_LOG_PORT_SDE_MONITOR IPC_LOG_BASE_PORT+307 /* 55454 */ +#define IPC_LOG_PORT_SDE_DRIVER IPC_LOG_BASE_PORT+308 /* 55455 */ +#define IPC_LOG_PORT_SDE_OPCUA_SERVER IPC_LOG_BASE_PORT+309 /* 55456 */ + +/* COMTRADE Utility ports */ +#define IPC_LOG_PORT_COMTRADE_UTILITY IPC_LOG_BASE_PORT+350 /* 55497 */ + + +#define IPC_LOG_MAX_CONNECTIONS 10 +#define IPC_LOG_MAX_QUEUE_CNT 100 + +/* SMART MODE */ +/* Format of smart message is 3 unsigned long integers: */ +/* unsigned long magicNumber = SLOGIPC_MAGIC_NUMBER; */ +/* unsigned long messageType = SLOGIPC_MSG_TYPE_XXX */ +/* unsigned long messageLen = dataLength */ + +/* Followed by one of: */ +/* nothing */ +/* char[messageLen] */ +/* unsigned long missedMessageCount */ + +#define SLOGIPC_MAGIC_NUMBER_SEAL 0x1F2E3D4D +#define SLOGIPC_MAGIC_NUMBER_NOSEAL 0x1F2E3D4C + +typedef struct + { + ST_UINT32 magicNumber; + ST_UINT32 messageType; + ST_UINT32 messageLen; + } SLOGIPC_SMART_MSG_HDR; + +ST_VOID _slogIpcInitHdr (struct tag_GEN_SOCK *pSock, + struct tag_GEN_SOCK_DATA *sockData, + ST_UINT32 msgType, ST_INT dataLen); + +#ifdef SLOGIPC_SEAL +typedef struct + { + ST_UINT32 magicNumber; + ST_UINT32 messageType; + ST_UINT32 messageLen; + S_SEAL seal; + } SLOGIPC_SMART_MSG_HDRS; +ST_VOID _slogIpcSetSeal (SLOGIPC_SMART_MSG_HDRS *sHdrS); +ST_RET _slogIpcCheckSeal (struct log_ctrl *lc, SLOGIPC_SMART_MSG_HDRS *sHdrS); +#endif + +/* message types */ +#define SLOGIPC_MSG_TYPE_LOG 0x00000000 +#define SLOGIPC_MSG_TYPE_RESERVED 0x00000001 +#define SLOGIPC_MSG_TYPE_APPID 0x00000002 +#define SLOGIPC_MSG_TYPE_START 0x00000003 +#define SLOGIPC_MSG_TYPE_STOP 0x00000004 + +/* Standard command message response types */ +#define SLOGIPC_MSG_TYPE_RESP_SUCCESS 0x00000005 +#define SLOGIPC_MSG_TYPE_RESP_FAILURE 0x00000006 + +/* Standard command message types */ +#define SLOGIPC_MSG_TYPE_OPTIONS 0x00000007 +#define SLOGIPC_MSG_TYPE_READ_LOGCFG 0x00000008 +#define SLOGIPC_MSG_TYPE_WRITE_LOGCFG 0x00000009 + +/* IF we missed log messages ... */ +#define SLOGIPC_MSG_TYPE_LOG_MISSED 0x0000000A + +#define SLOGIPC_MSG_TYPE_CLONE_LOG 0x00000010 +#define SLOGIPC_MSG_TYPE_RESET_LOG 0x00000020 +#define SLOGIPC_MSG_TYPE_WRITE_MSGDATA 0x00000030 +#define SLOGIPC_MSG_TYPE_GET_LOGMASKS 0x00000040 + + +/* General application specific command */ +#define SLOGIPC_MSG_TYPE_CMD 0x00000100 + +/* Defines for options (bitmasked) */ +#define LOG_IPC_EDIT_LOGCFG 0x00000001 + +/* configuration parameters for socket logging & command subsystem */ +typedef struct ipc_log_ctrl_tag + { + /* Used for client (calling) connections */ + ST_CHAR *callingIp; /* IP or host name of host to connect to*/ + ST_UINT16 callingPort; /* port of host to connect to */ + ST_ULONG callingBackoff; /* ms */ + ST_INT sealMode; + ST_INT sealTimeWindow; + + /* Used for server (called) connections */ + ST_UINT16 port; /* listening port number */ + ST_UINT16 portCnt; /* num of listening ports starting with */ + /* base port, for multiple app instances*/ + + ST_UINT16 portUsed; /* this the listening port actually used*/ + ST_UINT maxConns; /* max connections that can be accepted */ + + /* Misc parameters */ + ST_UINT maxQueCnt; /* max num of logs that can be queued */ + + ST_CHAR *appId; /* pointer to NULL terminated string */ + /* identifying the application, sent to */ + /* IPC Logging Client in first message */ + + ST_UINT32 options; /* Options supported by the app */ + + /* command processing function pointer - to be set by user application */ + ST_VOID (*slog_ipc_cmd_fun) (struct tag_GEN_SOCK *pSock, struct tag_GEN_SOCK_DATA *sockData, + ST_UINT32 msgType, ST_UINT32 msgDataLen, ST_CHAR *msgData); + + } IPC_LOG_CTRL; + + +/* Standard command handling support */ +typedef struct + { + DBL_LNK l; + struct tag_GEN_SOCK *pSock; + struct tag_GEN_SOCK_DATA *sockData; + ST_UINT32 msgType; + ST_UINT32 msgDataLen; + ST_CHAR *msgData; + } SLOGIPC_CMD; + +extern SLOGIPC_CMD *slogIpcCmdList; +extern ST_INT slogIpcMaxCmdPend; + +ST_VOID slog_ipc_std_cmd_fun (struct tag_GEN_SOCK *pSock, + struct tag_GEN_SOCK_DATA *sockData, + ST_UINT32 msgType, ST_UINT32 msgDataLen, + ST_CHAR *msgData); + +ST_VOID slog_ipc_std_cmd_service (ST_CHAR *logCfgFile, /* As used in logcfgx_exx */ + ST_CHAR *fileNamePrefix, /* ditto */ + ST_CHAR *cName, /* ditto */ + ST_BOOLEAN callingEnable, + ST_RET (*logReloadHandler) (ST_VOID), + ST_RET (*extendedCmdHandler) (SLOGIPC_CMD *slogIpcCmd)); + +ST_VOID slog_ipc_std_cmd_service_ex (struct log_ctrl *lc, + ST_CHAR *logCfgFile, /* As used in logcfgx_exx */ + ST_CHAR *fileNamePrefix, /* ditto */ + ST_CHAR *cName, /* ditto */ + ST_BOOLEAN callingEnable, + ST_RET (*logReloadHandler) (ST_VOID), + ST_RET (*extendedCmdHandler) (SLOGIPC_CMD *slogIpcCmd)); + +ST_VOID slogIpcCallingEnable (ST_BOOLEAN enable); +ST_VOID slogIpcCallingEnableEx (struct log_ctrl *lc, ST_BOOLEAN enable); + +ST_INT slogIpcActiveCount (struct log_ctrl *lc); + +/************************************************************************/ +/* SLOG IPC Context */ + +/* connection states */ +#define SLOGIPC_CON_IDLE 0 +#define SLOGIPC_CONNECTED 1 +#define SLOGIPC_CON_CLOSING 2 + +/* Remote connection info */ +typedef struct slogipc_con_ctrl_tag + { + DBL_LNK link; /* link list */ + struct tag_GEN_SOCK *conSock; /* pointer to socket info */ + ST_UINT conState; /* connection state */ + ST_BOOLEAN txEnable; /* Used in smart mode */ + struct tag_GEN_SOCK_DATA *sendQue; /* Pending send queue to the Remote */ + ST_UINT sendQueCnt; /* number of messages to send in queue */ + struct tag_GEN_SOCK_DATA *rcvBuf; /* alloc buf to drain any rcvd bytes */ + } SLOGIPC_CON_CTRL; + + +/* SLOGIPC context states */ +#define SLOGIPC_CTX_IDLE 0 +#define SLOGIPC_CTX_ACTIVE 1 +#define SLOGIPC_CTX_TERMINATING 2 + +/* This structure holds core parameters */ +typedef struct slogipc_ctx_tag + { + ST_UINT state; /* SLOGIPC_CTX_* */ + ST_BOOLEAN smartMode; /* SD_TRUE if smart mode enabled, SD_FALSE otherwise */ + + ST_INT sealMode; + + SLOGIPC_CON_CTRL *conCtrlList; /* list of connect CTRLs */ + struct tag_GEN_SOCK *listenSock; /* listen socket for conns from remote slog Clients */ + struct tag_GEN_SOCK *callingSock; /* calling socket for conns to remote slog Client */ + struct log_ctrl *lc; /* save to access appId when connected */ + struct tag_GEN_SOCK_CTXT *sockCtx; /* this is gensock2 context for slogipc.c */ + + ST_INT hdrSize; /* Calculated at startup */ + ST_INT magicNumber; + + ST_BOOLEAN callingEnabled; + ST_DOUBLE nextCallingConnectTime; + } SLOGIPC_CTX; + + +/************************************************************************/ +/* LOG CONTROL */ +/* A structure of this type is used for each independent logging entity */ +/************************************************************************/ + +/* Log control mask values */ +#define LOG_MEM_EN 0x0001L +#define LOG_FILE_EN 0x0002L +#define LOG_TIME_EN 0x0008L +#define LOG_ELAPSEDTIME_EN 0x0020L /* Windows only */ + +#define LOG_TIMEDATE_EN 0x0010L /* obsolete - ignored */ +#define LOG_DIFFTIME_EN 0x0020L /* obsolete - ignored */ +#define LOG_TIME_INITIALIZED 0x0040L /* obsolete - ignored */ +#define LOG_SYSTIME_EN 0x0100L /* obsolete - ignored */ + +#define LOG_NO_HEADER_CR 0x0200L +#define LOG_FILENAME_SUPPRESS 0x0400L +#define LOG_LOGTYPE_SUPPRESS 0x0800L + +#define LOG_IPC_LISTEN_EN 0x1000L +#define LOG_IPC_CALL_EN 0x2000L +#define LOG_IPC_SMART 0x4000L +#define LOG_IPC_EN (LOG_IPC_LISTEN_EN|LOG_IPC_CALL_EN) + +#define SLOG_NORMAL 0 +#define SLOG_CONT -1 +/* Dynamic logging standard command definitions */ +#define SLOG_DYN_PAUSE -10 /* OBSOLETE */ +#define SLOG_DYN_LF -11 /* OBSOLETE */ +#define SLOG_DYN_CLRSCR -12 /* OBSOLETE */ + +typedef struct log_ctrl + { +/* User sets these elements */ + ST_UINT32 logCtrl; /* Logging Control flags - see LOG_xxx defines */ + FILE_LOG_CTRL fc; /* File logging control */ + MEM_LOG_CTRL mc; /* Memory logging control */ + IPC_LOG_CTRL ipc; /* IPC logging control */ + + +/* Application specific information */ + ST_UINT32 logMask1; /* These bit masked variables are used by the */ + ST_UINT32 logMask2; /* user application to determine whether a item */ + ST_UINT32 logMask3; /* is to be logged. 6 ST_INT32's == 192 bits */ + ST_UINT32 logMask4; + ST_UINT32 logMask5; + ST_UINT32 logMask6; + +/* Internal variables. */ + ST_BOOLEAN initialized; /* Set when LOG_CTRL has been initializled */ + ST_INT max_msg_size; /* max allowed log msg size. */ + ST_CHAR *msg_buf; /* buffer for log msg */ + +/* static vars */ + SLOGIPC_CTX slogIpcCtx; + } LOG_CTRL; + + +/* Max size of any single log statement (sprintf) */ + +#define MAX_LOG_SIZE 5000 + +/* Set the following variable to a number larger than the default of */ +/* MAX_LOG_SIZE if you want to log more than 500 bytes in a single */ +/* message. */ + +extern ST_INT sl_max_msg_size; + +/************************************************************************/ +/* Main entry points into the SLOG library */ +/************************************************************************/ + +ST_VOID slog (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_CHAR *format, ...); + +ST_VOID slogx (ST_UINT32 doit, LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_CHAR *format, ...); + +ST_VOID slogHex (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST fileName, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT numBytes, + SD_CONST ST_VOID *hexData); + + +ST_VOID _slog (LOG_CTRL *lc, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_CHAR *format, ...); +ST_VOID _slogc (LOG_CTRL *lc, SD_CONST ST_CHAR *format, ...); + +ST_VOID _slogx (ST_UINT32 doit, LOG_CTRL *lc, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_CHAR *format, ...); + +ST_VOID _slogHex (LOG_CTRL *lc, + ST_INT numBytes, + SD_CONST ST_VOID *hexData); + +ST_VOID _slogXML (LOG_CTRL *lc, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + ST_UINT numBytes, + SD_CONST ST_CHAR *textData); + +ST_VOID _slogStr (LOG_CTRL *lc, ST_CHAR *strData); + +ST_RET slog_start (LOG_CTRL *lc, ST_INT max_msg_size); +ST_RET slog_end (LOG_CTRL *lc); + +ST_RET slog_max_msg_size_set (LOG_CTRL *lc, ST_INT max_msg_size); +/* Use macro to get max msg size. Faster. */ +#define slog_max_msg_size_get(log_ctrl) (log_ctrl->max_msg_size) + +ST_VOID slogIpcSendData (struct tag_GEN_SOCK *pSock, ST_UINT32 msgType, + ST_INT dataLen, ST_UCHAR *data); +ST_VOID slogIpcSendRawData (LOG_CTRL *lc, ST_INT bufLen, ST_CHAR *buf, ST_BOOLEAN sendAlways); + + +/************************************************************************/ +/* Main entry points into the SLOG library */ +/************************************************************************/ + +/* File Logging Utility Functions */ + +ST_VOID slogCloseFile (LOG_CTRL *lc); +ST_VOID slogCloneFile (LOG_CTRL *lc, SD_CONST ST_CHAR *newfile); +ST_VOID slogCloneFileEx (LOG_CTRL *lc, SD_CONST ST_CHAR *newFile); +ST_VOID slogDeleteFile (LOG_CTRL *lc); +ST_VOID slogCallStack (LOG_CTRL *lc, SD_CONST ST_CHAR *txt); +ST_VOID slogDelBuf (LOG_CTRL *lc); + +/* Memory Logging Utility Functions */ + +ST_VOID slogDumpMem (LOG_CTRL *lc); +ST_VOID slogResetMem (LOG_CTRL *lc); +ST_CHAR *slogGetMemMsg (LOG_CTRL *lc, SD_CONST ST_INT msgNum); +ST_INT slogGetMemCount (LOG_CTRL *lc); + +/* Internal functions */ + +ST_VOID slogFile (LOG_CTRL *lc, SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, SD_CONST ST_CHAR *buf); + +ST_VOID slogMem (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + ST_INT bufLen, SD_CONST ST_CHAR *buf); + +ST_RET slogIpcInit (LOG_CTRL *lc); +ST_RET slogIpcStop (LOG_CTRL *lc); +ST_RET slogIpcEvent (ST_VOID); +ST_RET slogIpcEventEx (LOG_CTRL *lc); + +ST_VOID slogIpc (LOG_CTRL *lc, ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + ST_INT lineNum, ST_INT bufLen, + ST_CHAR *buf); + +ST_VOID slogMemInit (LOG_CTRL *lc); +ST_RET read_log_cfg_file (ST_CHAR *cfg_filename); +ST_RET slog_get_index_file_name (LOG_CTRL *lc, ST_CHAR *dest, ST_INT destLen); + +/************************************************************************/ + +/* dataType defines */ +#define _LOGCFG_DATATYPE_UINT_MASK 0 +#define _LOGCFG_DATATYPE_UINT32_MASK 1 +#define _LOGCFG_DATATYPE_RUINT32_MASK 2 +#define _LOGCFG_DATATYPE_BOOLEAN 3 +#define _LOGCFG_DATATYPE_INT 4 +#define _LOGCFG_DATATYPE_LONG 5 +#define _LOGCFG_DATATYPE_INT16 6 +#define _LOGCFG_DATATYPE_INT32 7 +#define _LOGCFG_DATATYPE_UINT 8 +#define _LOGCFG_DATATYPE_ULONG 9 +#define _LOGCFG_DATATYPE_UINT16 10 +#define _LOGCFG_DATATYPE_UINT32 11 +#define _LOGCFG_DATATYPE_STRING 12 +#define _LOGCFG_DATATYPE_STRINGBUF 13 +#define _LOGCFG_DATATYPE_DOUBLE 14 +#define _LOGCFG_DATATYPE_FILENAME 15 +#define _LOGCFG_DATATYPE_CALLBACK 16 + + +typedef struct + { + ST_CHAR *tag; /* NULL if must use perferredTag field */ + ST_UINT mask; + ST_VOID *addr; + ST_INT dataType; + ST_CHAR *description; /* NULL for no description */ + ST_CHAR *preferredTag; /* NULL if must use tag field */ + } LOGCFGX_VALUE_MAP; + +typedef struct + { + DBL_LNK l; + ST_CHAR *name; + ST_INT numMaskMap; + LOGCFGX_VALUE_MAP *maskMapTbl; + } LOGCFG_VALUE_GROUP; + + +ST_RET logcfgx_exx (LOG_CTRL *destLogCtrl, ST_CHAR *logFileName, ST_CHAR *fileNamePrefix, + ST_BOOLEAN masksOnly, ST_BOOLEAN saveTagVals, ST_CHAR *compName); +ST_RET logcfgx_ex (LOG_CTRL *destLogCtrl, ST_CHAR *logFileName, ST_CHAR *fileNamePrefix, + ST_BOOLEAN masksOnly, ST_BOOLEAN saveTagVals); +ST_VOID logCfgAddMaskGroup (LOGCFG_VALUE_GROUP *logMaskGroup); +ST_VOID logCfgRemoveMaskGroup (LOGCFG_VALUE_GROUP *logMaskGroup); +ST_VOID logCfgRemoveAllMaskGroups (ST_VOID); +ST_RET _logcfg_get_logmasks (ST_CHAR *xmlBuf, ST_INT *xmlSizeIo); +ST_INT _logcfg_get_logmasks_size (ST_VOID); + +/* ST_VOID (*logCfgCallbackFun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag, LOGCFGX_VALUE_MAP *valMap); */ + + +extern LOGCFG_VALUE_GROUP acseLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP adlcLogMaskMapCtrl; /* MMS-LITE */ +extern LOGCFG_VALUE_GROUP asn1LogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP clnpLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE */ +extern LOGCFG_VALUE_GROUP genlistDebugMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP gsLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP icfgLogMaskMapCtrl; /* ICCP-LITE */ +extern LOGCFG_VALUE_GROUP logcfgMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP logCfgLogCtrlMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP memDebugMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP memLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP miLogMaskMapCtrl; /* ICCP-LITE */ +extern LOGCFG_VALUE_GROUP mmsLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP mvlLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE */ +extern LOGCFG_VALUE_GROUP secLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP ssleLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP ssleASN1LogMaskMapCtrl; +extern LOGCFG_VALUE_GROUP smpLogMaskMapCtrl; /* MMS-LITE */ +extern LOGCFG_VALUE_GROUP sockLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP suicLogMaskMapCtrl; /* MMS-EASE */ +extern LOGCFG_VALUE_GROUP sxLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP tp4LogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP usrLogMaskMapCtrl; /* MMS-LITE */ +/* For 142-XXX products (MMS_EASE over Lite Stack) */ +extern LOGCFG_VALUE_GROUP ipcLogMaskMapCtrl; +extern LOGCFG_VALUE_GROUP sscLogMaskMapCtrl; + + +typedef struct + { + DBL_LNK l; + ST_CHAR *tag; + ST_CHAR *tagPath; + ST_INT dataType; + union + { + ST_BOOLEAN b; + ST_INT sInt; + ST_LONG sLong; + ST_INT16 sInt16; + ST_INT32 sInt32; + ST_UINT uInt; + ST_ULONG uLong; + ST_UINT16 uInt16; + ST_UINT32 uInt32; + ST_DOUBLE dbl; + ST_CHAR *str; + }u; + } LOGCFGX_TAG_VAL; + +LOGCFGX_TAG_VAL *logCfgFindTagVal (ST_CHAR *tag); +ST_VOID logCfgClearTagVals (ST_VOID); + + +/************************************************************************/ +/************************************************************************/ +/* logcfg_debug_sel bit assignments */ +#define LOGCFG_ERR 0x0001 +#define LOGCFG_NERR 0x0002 +#define LOGCFG_FLOW 0x0004 + +extern ST_UINT logcfg_debug_sel; + +/* Log type strings */ +extern SD_CONST ST_CHAR *SD_CONST _logcfg_log_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _logcfg_log_nerr_logstr; +extern SD_CONST ST_CHAR *SD_CONST _logcfg_log_flow_logstr; + +/************************************************************************/ +/* Err log macros */ +#define LOGCFG_ERR0(a) \ + SLOG_0 (logcfg_debug_sel & LOGCFG_ERR,_logcfg_log_err_logstr,a) +#define LOGCFG_ERR1(a,b) \ + SLOG_1 (logcfg_debug_sel & LOGCFG_ERR,_logcfg_log_err_logstr,a,b) +#define LOGCFG_ERR2(a,b,c) \ + SLOG_2 (logcfg_debug_sel & LOGCFG_ERR,_logcfg_log_err_logstr,a,b,c) +#define LOGCFG_ERR3(a,b,c,d) \ + SLOG_3 (logcfg_debug_sel & LOGCFG_ERR,_logcfg_log_err_logstr,a,b,c,d) +#define LOGCFG_ERR4(a,b,c,d,e) \ + SLOG_4 (logcfg_debug_sel & LOGCFG_ERR,_logcfg_log_err_logstr,a,b,c,d,e) + +/* Err continuation log macros */ +#define LOGCFG_CERR0(a) \ + SLOGC_0 (logcfg_debug_sel & LOGCFG_ERR,a) +#define LOGCFG_CERR1(a,b) \ + SLOGC_1 (logcfg_debug_sel & LOGCFG_ERR,a,b) +#define LOGCFG_CERR2(a,b,c) \ + SLOGC_2 (logcfg_debug_sel & LOGCFG_ERR,a,b,c) +#define LOGCFG_CERR3(a,b,c,d) \ + SLOGC_3 (logcfg_debug_sel & LOGCFG_ERR,a,b,c,d) +#define LOGCFG_CERR4(a,b,c,d,e) \ + SLOGC_4 (logcfg_debug_sel & LOGCFG_ERR,a,b,c,d,e) + +/************************************************************************/ +/* NErr log macros */ +#define LOGCFG_NERR0(a) \ + SLOG_0 (logcfg_debug_sel & LOGCFG_NERR,_logcfg_log_nerr_logstr,a) +#define LOGCFG_NERR1(a,b) \ + SLOG_1 (logcfg_debug_sel & LOGCFG_NERR,_logcfg_log_nerr_logstr,a,b) +#define LOGCFG_NERR2(a,b,c) \ + SLOG_2 (logcfg_debug_sel & LOGCFG_NERR,_logcfg_log_nerr_logstr,a,b,c) +#define LOGCFG_NERR3(a,b,c,d) \ + SLOG_3 (logcfg_debug_sel & LOGCFG_NERR,_logcfg_log_nerr_logstr,a,b,c,d) +#define LOGCFG_NERR4(a,b,c,d,e) \ + SLOG_4 (logcfg_debug_sel & LOGCFG_NERR,_logcfg_log_nerr_logstr,a,b,c,d,e) + +/* NErr continuation log macros */ +#define LOGCFG_CNERR0(a) \ + SLOGC_0 (logcfg_debug_sel & LOGCFG_NERR,a) +#define LOGCFG_CNERR1(a,b) \ + SLOGC_1 (logcfg_debug_sel & LOGCFG_NERR,a,b) +#define LOGCFG_CNERR2(a,b,c) \ + SLOGC_2 (logcfg_debug_sel & LOGCFG_NERR,a,b,c) +#define LOGCFG_CNERR3(a,b,c,d) \ + SLOGC_3 (logcfg_debug_sel & LOGCFG_NERR,a,b,c,d) +#define LOGCFG_CNERR4(a,b,c,d,e) \ + SLOGC_4 (logcfg_debug_sel & LOGCFG_NERR,a,b,c,d,e) + +/************************************************************************/ +/* Flow log macros */ +#define LOGCFG_FLOW0(a) \ + SLOG_0 (logcfg_debug_sel & LOGCFG_FLOW,_logcfg_log_flow_logstr,a) +#define LOGCFG_FLOW1(a,b) \ + SLOG_1 (logcfg_debug_sel & LOGCFG_FLOW,_logcfg_log_flow_logstr,a,b) +#define LOGCFG_FLOW2(a,b,c) \ + SLOG_2 (logcfg_debug_sel & LOGCFG_FLOW,_logcfg_log_flow_logstr,a,b,c) +#define LOGCFG_FLOW3(a,b,c,d) \ + SLOG_3 (logcfg_debug_sel & LOGCFG_FLOW,_logcfg_log_flow_logstr,a,b,c,d) +#define LOGCFG_FLOW4(a,b,c,d,e) \ + SLOG_4 (logcfg_debug_sel & LOGCFG_FLOW,_logcfg_log_flow_logstr,a,b,c,d,e) + +/* Flow continuation log macros */ +#define LOGCFG_CFLOW0(a) \ + SLOGC_0 (logcfg_debug_sel & LOGCFG_FLOW,a) +#define LOGCFG_CFLOW1(a,b) \ + SLOGC_1 (logcfg_debug_sel & LOGCFG_FLOW,a,b) +#define LOGCFG_CFLOW2(a,b,c) \ + SLOGC_2 (logcfg_debug_sel & LOGCFG_FLOW,a,b,c) +#define LOGCFG_CFLOW3(a,b,c,d) \ + SLOGC_3 (logcfg_debug_sel & LOGCFG_FLOW,a,b,c,d) +#define LOGCFG_CFLOW4(a,b,c,d,e) \ + SLOGC_4 (logcfg_debug_sel & LOGCFG_FLOW,a,b,c,d,e) + + +/************************************************************************/ +/************************************************************************/ +/* Global variables for the SLOG library. */ +/************************************************************************/ + +/* Log masks for different components of SISCO products. */ +extern ST_UINT gs_debug_sel; +extern ST_UINT clnp_debug_sel; + + +extern LOG_CTRL *sLogCtrl; +extern LOG_CTRL *sErrLogCtrl; + +extern ST_BOOLEAN sNonStandardLogMode; + +/************************************************************************/ +/* These elements are used for creating time strings */ +/************************************************************************/ + +extern ST_CHAR slogTimeText[TIME_BUF_LEN]; +ST_VOID slogSetTimeText (LOG_CTRL *lc); + +/************************************************************************/ +/* slog header defines and buffer */ +/************************************************************************/ + +#define SLOG_MAX_FNAME 64 +#define SLOG_MAX_LOGTYPESTR 40 /* logTypeStr cutoff if too long*/ +#define SLOG_MAX_HDR (2 + \ + TIME_BUF_LEN + \ + SLOG_MAX_LOGTYPESTR+1 + \ + SLOG_MAX_FNAME+14 + \ + 1 + 2) + +/* (2 NL , NL */ +/* TIME_BUF_LEN + slogTimeText buf size */ +/* SLOG_MAX_LOGTYPESTR+1 + limit for logTypeStr */ +/* SLOG_MAX_FNAME+14 + fName & lineNum formatting */ +/* 1 + 2) NL + 2 spaces before msg */ + +ST_VOID slogTrimFileName (ST_CHAR *dest, SD_CONST ST_CHAR *fullName); +ST_VOID slogSetHdr (LOG_CTRL *lc, SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + ST_CHAR *slogHdr, ST_CHAR *lineBreak); + +/************************************************************************/ +/* dynamic loging function */ +/************************************************************************/ + +extern ST_VOID (*slog_dyn_log_fun) (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); +extern ST_VOID (*_slog_dyn_log_fun) (LOG_CTRL *lc, + SD_CONST ST_CHAR *timeStr, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); + +/************************************************************************/ +/* This function pointer is invoked during slow SLOG operations, such */ +/* as 'clone' and 'find oldest message' */ + +extern ST_VOID (*slog_service_fun) (ST_VOID); + +/************************************************************************/ +/* Remote logging function */ +/************************************************************************/ + +extern ST_VOID (*slog_remote_fun) (ST_UINT32 slog_remote_flags, + LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); + +extern ST_VOID (*_slog_remote_fun) (ST_UINT32 slog_remote_flags, + LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); + +/* Parameter for use with remote logging function pointer */ +/* SLOG will pass this global variable to the slog_remote_fun function */ +extern ST_UINT32 slogRemoteFlags; + +/************************************************************************/ +/* Standard dynamic logging control definitions */ +/************************************************************************/ +/* These macros are OBSOLETE. They now do nothing. Previously they */ +/* passed logType values of SLOG_DYN_PAUSE, SLOG_DYN_LF, SLOG_DYN_CLRSCR*/ +/* respectively to slog. */ + +#define SLOG_PAUSE(lc,msg) +#define SLOG_LF(lc) +#define SLOG_CLRSCR(lc) + +/************************************************************************/ +/* Base macro types, useful for typical user logging, to reduce user */ +/* macro verbosity */ +/************************************************************************/ + +#define SLOGH1(lc,mask,id,x,y) {\ + if (lc->logMask1 & mask)\ + slogHex (sLogCtrl,id, thisFileName,__LINE__,x,y);} + + +#define SLOGH2(lc,mask,id,x,y) {\ + if (lc->logMask2 & mask)\ + slogHex (sLogCtrl,id, thisFileName,__LINE__,x,y);} + +#define SLOGH3(lc,mask,id,x,y) {\ + if (lc->logMask3 & mask)\ + slogHex (sLogCtrl,id, thisFileName,__LINE__,x,y);} + +#define SLOGH4(lc,mask,id,x,y) {\ + if (lc->logMask4 & mask)\ + slogHex (sLogCtrl,id, thisFileName,__LINE__,x,y);} + +#define SLOGH5(lc,mask,id,x,y) {\ + if (lc->logMask5 & mask)\ + slogHex (sLogCtrl,id, thisFileName,__LINE__,x,y);} + +#define SLOGH6(lc,mask,id,x,y) {\ + if (lc->logMask6 & mask)\ + slogHex (sLogCtrl,id, thisFileName,__LINE__,x,y);} + + + +/* ******************* LOG MASK 1 MACROS ************************* */ + +#define SLOG1_0(lc,mask,id,a) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a);\ + } + +#define SLOG1_1(lc,mask,id,a,b) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b);\ + } + +#define SLOG1_2(lc,mask,id,a,b,c) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c);\ + } + +#define SLOG1_3(lc,mask,id,a,b,c,d) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d);\ + } + +#define SLOG1_4(lc,mask,id,a,b,c,d,e) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define SLOG1_5(lc,mask,id,a,b,c,d,e,f) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +#define SLOG1_6(lc,mask,id,a,b,c,d,e,f,g) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + +#define SLOG1_7(lc,mask,id,a,b,c,d,e,f,g,h) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h);\ + } + +#define SLOG1_8(lc,mask,id,a,b,c,d,e,f,g,h,i) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i);\ + } + + + +/* ******************* LOG MASK 2 MACROS ************************* */ +#define SLOG2_0(lc,mask,id,a) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a);\ + } + +#define SLOG2_1(lc,mask,id,a,b) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b);\ + } + +#define SLOG2_2(lc,mask,id,a,b,c) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c);\ + } + +#define SLOG2_3(lc,mask,id,a,b,c,d) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d);\ + } + +#define SLOG2_4(lc,mask,id,a,b,c,d,e) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define SLOG2_5(lc,mask,id,a,b,c,d,e,f) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +#define SLOG2_6(lc,mask,id,a,b,c,d,e,f,g) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + +#define SLOG2_7(lc,mask,id,a,b,c,d,e,f,g,h) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h);\ + } + +#define SLOG2_8(lc,mask,id,a,b,c,d,e,f,g,h,i) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i);\ + } + + + +/* ******************* LOG MASK 3 MACROS ************************* */ +#define SLOG3_0(lc,mask,id,a) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a);\ + } + +#define SLOG3_1(lc,mask,id,a,b) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b);\ + } + +#define SLOG3_2(lc,mask,id,a,b,c) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c);\ + } + +#define SLOG3_3(lc,mask,id,a,b,c,d) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d);\ + } + +#define SLOG3_4(lc,mask,id,a,b,c,d,e) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define SLOG3_5(lc,mask,id,a,b,c,d,e,f) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +#define SLOG3_6(lc,mask,id,a,b,c,d,e,f,g) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + +#define SLOG3_7(lc,mask,id,a,b,c,d,e,f,g,h) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h);\ + } + +#define SLOG3_8(lc,mask,id,a,b,c,d,e,f,g,h,i) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i);\ + } + + + +/* ******************* LOG MASK 4 MACROS ************************* */ +#define SLOG4_0(lc,mask,id,a) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a);\ + } + +#define SLOG4_1(lc,mask,id,a,b) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b);\ + } + +#define SLOG4_2(lc,mask,id,a,b,c) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c);\ + } + +#define SLOG4_3(lc,mask,id,a,b,c,d) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d);\ + } + +#define SLOG4_4(lc,mask,id,a,b,c,d,e) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define SLOG4_5(lc,mask,id,a,b,c,d,e,f) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +#define SLOG4_6(lc,mask,id,a,b,c,d,e,f,g) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + +#define SLOG4_7(lc,mask,id,a,b,c,d,e,f,g,h) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h);\ + } + +#define SLOG4_8(lc,mask,id,a,b,c,d,e,f,g,h,i) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i);\ + } + + + + +/* ******************* LOG MASK 5 MACROS ************************* */ +#define SLOG5_0(lc,mask,id,a) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a);\ + } + +#define SLOG5_1(lc,mask,id,a,b) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b);\ + } + +#define SLOG5_2(lc,mask,id,a,b,c) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c);\ + } + +#define SLOG5_3(lc,mask,id,a,b,c,d) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d);\ + } + +#define SLOG5_4(lc,mask,id,a,b,c,d,e) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define SLOG5_5(lc,mask,id,a,b,c,d,e,f) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +#define SLOG5_6(lc,mask,id,a,b,c,d,e,f,g) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + +#define SLOG5_7(lc,mask,id,a,b,c,d,e,f,g,h) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h);\ + } + +#define SLOG5_8(lc,mask,id,a,b,c,d,e,f,g,h,i) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i);\ + } + + + +/* ******************* LOG MASK 6 MACROS ************************* */ +#define SLOG6_0(lc,mask,id,a) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a);\ + } + +#define SLOG6_1(lc,mask,id,a,b) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b);\ + } + +#define SLOG6_2(lc,mask,id,a,b,c) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c);\ + } + +#define SLOG6_3(lc,mask,id,a,b,c,d) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d);\ + } + +#define SLOG6_4(lc,mask,id,a,b,c,d,e) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define SLOG6_5(lc,mask,id,a,b,c,d,e,f) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +#define SLOG6_6(lc,mask,id,a,b,c,d,e,f,g) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + +#define SLOG6_7(lc,mask,id,a,b,c,d,e,f,g,h) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h);\ + } + +#define SLOG6_8(lc,mask,id,a,b,c,d,e,f,g,h,i) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i);\ + } + + + +/************************************************************************/ +/************************************************************************/ +#if defined(DEBUG_SISCO) +/************************************************************************/ + +extern ST_CHAR *_slogAlwaysLogTypeStr; +extern ST_CHAR *_slogXMLLogTypeStr; + +#define SLOGALWAYS0(a) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a) +#define SLOGALWAYS1(a,b) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b) +#define SLOGALWAYS2(a,b,c) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c) +#define SLOGALWAYS3(a,b,c,d) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d) +#define SLOGALWAYS4(a,b,c,d,e) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e) +#define SLOGALWAYS5(a,b,c,d,e,f) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e,f) +#define SLOGALWAYS6(a,b,c,d,e,f,g) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e,f,g) +#define SLOGALWAYS7(a,b,c,d,e,f,g,h) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e,f,g,h) +#define SLOGALWAYS8(a,b,c,d,e,f,g,h,i) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i) +#define SLOGALWAYS9(a,b,c,d,e,f,g,h,i,j) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i,j) +#define SLOGALWAYS10(a,b,c,d,e,f,g,h,i,j,k) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i,j,k) +#define SLOGALWAYS11(a,b,c,d,e,f,g,h,i,j,k,l) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i,j,k,l) + +#define SLOGCALWAYS0(a) \ + _slogc (sLogCtrl,a) +#define SLOGCALWAYS1(a,b) \ + _slogc (sLogCtrl,a,b) +#define SLOGCALWAYS2(a,b,c) \ + _slogc (sLogCtrl,a,b,c) +#define SLOGCALWAYS3(a,b,c,d) \ + _slogc (sLogCtrl,a,b,c,d) +#define SLOGCALWAYS4(a,b,c,d,e) \ + _slogc (sLogCtrl,a,b,c,d,e) +#define SLOGCALWAYS5(a,b,c,d,e,f) \ + _slogc (sLogCtrl,a,b,c,d,e,f) +#define SLOGCALWAYS6(a,b,c,d,e,f,g) \ + _slogc (sLogCtrl,a,b,c,d,e,f,g) +#define SLOGCALWAYS7(a,b,c,d,e,f,g,h) \ + _slogc (sLogCtrl,a,b,c,d,e,f,g,h) +#define SLOGCALWAYS8(a,b,c,d,e,f,g,h,i) \ + _slogc (sLogCtrl,a,b,c,d,e,f,g,h,i) + +#define SLOGALWAYSH(numBytes,dataPtr) \ + _slogHex (sLogCtrl, numBytes, dataPtr) + +#define SLOGALWAYSS(dataPtr) \ + _slogStr (sLogCtrl, dataPtr) + +#define SLOGALWAYSX(numBytes, dataPtr) \ + _slogXML (sLogCtrl, _slogXMLLogTypeStr, thisFileName, __LINE__, numBytes, dataPtr) + +/************************************************************************/ +#else /* #if defined(DEBUG_SISCO) */ +/************************************************************************/ + +#define SLOGALWAYS0(a) +#define SLOGALWAYS1(a,b) +#define SLOGALWAYS2(a,b,c) +#define SLOGALWAYS3(a,b,c,d) +#define SLOGALWAYS4(a,b,c,d,e) +#define SLOGALWAYS5(a,b,c,d,e,f) +#define SLOGALWAYS6(a,b,c,d,e,f,g) +#define SLOGALWAYS7(a,b,c,d,e,f,g,h) +#define SLOGALWAYS8(a,b,c,d,e,f,g,h,i) +#define SLOGALWAYS9(a,b,c,d,e,f,g,h,i,j) +#define SLOGALWAYS10(a,b,c,d,e,f,g,h,i,j,k) +#define SLOGALWAYS11(a,b,c,d,e,f,g,h,i,j,k,l) +#define SLOGCALWAYS0(a) +#define SLOGCALWAYS1(a,b) +#define SLOGCALWAYS2(a,b,c) +#define SLOGCALWAYS3(a,b,c,d) +#define SLOGCALWAYS4(a,b,c,d,e) +#define SLOGCALWAYS5(a,b,c,d,e,f) +#define SLOGCALWAYS6(a,b,c,d,e,f,g) +#define SLOGCALWAYS7(a,b,c,d,e,f,g,h) +#define SLOGCALWAYS8(a,b,c,d,e,f,g,h,i) +#define SLOGALWAYSH(numBytes,dataPtr) +#define SLOGALWAYSS(dataPtr) +#define SLOGALWAYSX(numBytes,dataPtr) + +#endif +/************************************************************************/ + +/************************************************************************/ +/* "Base" set of macros. */ +/* All other LOG macros should call these macros. */ +/* TRICK: These macros all use "do{...}while(0)". */ +/* This works in any context without adding extra {}. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +/* Basic log macros (all call _slog) */ +#define SLOG_0(ena,str,fmt) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt);} while(0) + +#define SLOG_1(ena,str,fmt,a) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a);} while(0) + +#define SLOG_2(ena,str,fmt,a,b) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a,b);} while(0) + +#define SLOG_3(ena,str,fmt,a,b,c) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c);} while(0) + +#define SLOG_4(ena,str,fmt,a,b,c,d) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d);} while(0) + +#define SLOG_5(ena,str,fmt,a,b,c,d,e) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e);} while(0) + +#define SLOG_6(ena,str,fmt,a,b,c,d,e,f) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e,f);} while(0) + +#define SLOG_7(ena,str,fmt,a,b,c,d,e,f,g) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e,f,g);} while(0) + +#define SLOG_8(ena,str,fmt,a,b,c,d,e,f,g,h) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e,f,g,h);} while(0) + +/* Continuation macros (all call _slogc). */ +#define SLOGC_0(ena,fmt) \ + do {if (ena) _slogc (sLogCtrl,fmt);} while(0) + +#define SLOGC_1(ena,fmt,a) \ + do {if (ena) _slogc (sLogCtrl,fmt,a);} while(0) + +#define SLOGC_2(ena,fmt,a,b) \ + do {if (ena) _slogc (sLogCtrl,fmt,a,b);} while(0) + +#define SLOGC_3(ena,fmt,a,b,c) \ + do {if (ena) _slogc (sLogCtrl,fmt,a,b,c);} while(0) + +#define SLOGC_4(ena,fmt,a,b,c,d) \ + do {if (ena) _slogc (sLogCtrl,fmt,a,b,c,d);} while(0) + +#define SLOGC_5(ena,fmt,a,b,c,d,e) \ + do {if (ena) _slogc (sLogCtrl,fmt,a,b,c,d,e);} while(0) + +#define SLOGC_6(ena,fmt,a,b,c,d,e,f) \ + do {if (ena) _slogc (sLogCtrl,fmt,a,b,c,d,e,f);} while(0) + +#define SLOGC_7(ena,fmt,a,b,c,d,e,f,g) \ + do {if (ena) _slogc (sLogCtrl,fmt,a,b,c,d,e,f,g);} while(0) + +#define SLOGC_8(ena,fmt,a,b,c,d,e,f,g,h) \ + do {if (ena) _slogc (sLogCtrl,fmt,a,b,c,d,e,f,g,h);} while(0) + +/* Hex logging macro (calls _slogHex) */ +#define SLOGH(ena,num,ptr) \ + do {if (ena) _slogHex (sLogCtrl,num,ptr);} while(0) + +/* XML logging macro (calls _slogXML) */ +#define SLOGX(ena,num,ptr) \ + do {if (ena) _slogXML (sLogCtrl, _slogXMLLogTypeStr, thisFileName, __LINE__, num, ptr);} while(0) + +#else /* !DEBUG_SISCO */ + +/* Non-DEBUG macros for EVERYONE! Yeah!! Never have to create another one.*/ +/* Basic log macros (do nothing) */ +#define SLOG_0(ena,str,fmt) +#define SLOG_1(ena,str,fmt,a) +#define SLOG_2(ena,str,fmt,a,b) +#define SLOG_3(ena,str,fmt,a,b,c) +#define SLOG_4(ena,str,fmt,a,b,c,d) +#define SLOG_5(ena,str,fmt,a,b,c,d,e) +#define SLOG_6(ena,str,fmt,a,b,c,d,e,f) +#define SLOG_7(ena,str,fmt,a,b,c,d,e,f,g) +#define SLOG_8(ena,str,fmt,a,b,c,d,e,f,g,h) + +/* Continuation macros (do nothing). */ +#define SLOGC_0(ena,fmt) +#define SLOGC_1(ena,fmt,a) +#define SLOGC_2(ena,fmt,a,b) +#define SLOGC_3(ena,fmt,a,b,c) +#define SLOGC_4(ena,fmt,a,b,c,d) +#define SLOGC_5(ena,fmt,a,b,c,d,e) +#define SLOGC_6(ena,fmt,a,b,c,d,e,f) +#define SLOGC_7(ena,fmt,a,b,c,d,e,f,g) +#define SLOGC_8(ena,fmt,a,b,c,d,e,f,g,h) + +/* Hex logging macro (do nothing) */ +#define SLOGH(ena,num,ptr) +/* XML logging macro (do nothing) */ +#define SLOGX(ena,num,ptr) +#endif /* !DEBUG_SISCO */ + + +/************************************************************************/ +/* "Base" set of macros for error log */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +/* Basic log macros (all call _slog) */ +#define SELOG_0(ena,str,fmt) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt);} while(0) + +#define SELOG_1(ena,str,fmt,a) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a);} while(0) + +#define SELOG_2(ena,str,fmt,a,b) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a,b);} while(0) + +#define SELOG_3(ena,str,fmt,a,b,c) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c);} while(0) + +#define SELOG_4(ena,str,fmt,a,b,c,d) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d);} while(0) + +#define SELOG_5(ena,str,fmt,a,b,c,d,e) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e);} while(0) + +#define SELOG_6(ena,str,fmt,a,b,c,d,e,f) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e,f);} while(0) + +#define SELOG_7(ena,str,fmt,a,b,c,d,e,f,g) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e,f,g);} while(0) + +#define SELOG_8(ena,str,fmt,a,b,c,d,e,f,g,h) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e,f,g,h);} while(0) + +/* Continuation macros (all call _slogc). */ +#define SELOGC_0(ena,fmt) \ + do {if (ena) _slogc (sErrLogCtrl,fmt);} while(0) + +#define SELOGC_1(ena,fmt,a) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a);} while(0) + +#define SELOGC_2(ena,fmt,a,b) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a,b);} while(0) + +#define SELOGC_3(ena,fmt,a,b,c) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a,b,c);} while(0) + +#define SELOGC_4(ena,fmt,a,b,c,d) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a,b,c,d);} while(0) + +#define SELOGC_5(ena,fmt,a,b,c,d,e) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a,b,c,d,e);} while(0) + +#define SELOGC_6(ena,fmt,a,b,c,d,e,f) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a,b,c,d,e,f);} while(0) + +#define SELOGC_7(ena,fmt,a,b,c,d,e,f,g) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a,b,c,d,e,f,g);} while(0) + +#define SELOGC_8(ena,fmt,a,b,c,d,e,f,g,h) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a,b,c,d,e,f,g,h);} while(0) + +/* Hex logging macro (calls _slogHex) */ +#define SELOGH(ena,num,ptr) \ + do {if (ena) _slogHex (sErrLogCtrl,num,ptr);} while(0) + +/* XML logging macro (calls _slogXML) */ +#define SELOGX(ena,num,ptr) \ + do {if (ena) _slogXML (sErrLogCtrl, _slogXMLLogTypeStr, thisFileName, __LINE__, num, ptr);} while(0) + +#else /* !DEBUG_SISCO */ + +/* Non-DEBUG macros for EVERYONE! Yeah!! Never have to create another one.*/ +/* Basic log macros (do nothing) */ +#define SELOG_0(ena,str,fmt) +#define SELOG_1(ena,str,fmt,a) +#define SELOG_2(ena,str,fmt,a,b) +#define SELOG_3(ena,str,fmt,a,b,c) +#define SELOG_4(ena,str,fmt,a,b,c,d) +#define SELOG_5(ena,str,fmt,a,b,c,d,e) +#define SELOG_6(ena,str,fmt,a,b,c,d,e,f) +#define SELOG_7(ena,str,fmt,a,b,c,d,e,f,g) +#define SELOG_8(ena,str,fmt,a,b,c,d,e,f,g,h) + +/* Continuation macros (do nothing). */ +#define SELOGC_0(ena,fmt) +#define SELOGC_1(ena,fmt,a) +#define SELOGC_2(ena,fmt,a,b) +#define SELOGC_3(ena,fmt,a,b,c) +#define SELOGC_4(ena,fmt,a,b,c,d) +#define SELOGC_5(ena,fmt,a,b,c,d,e) +#define SELOGC_6(ena,fmt,a,b,c,d,e,f) +#define SELOGC_7(ena,fmt,a,b,c,d,e,f,g) +#define SELOGC_8(ena,fmt,a,b,c,d,e,f,g,h) + +/* Hex logging macro (do nothing) */ +#define SELOGH(ena,num,ptr) +/* XML logging macro (do nothing) */ +#define SELOGX(ena,num,ptr) +#endif /* !DEBUG_SISCO */ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + diff --git a/include/inc/smp.h b/include/inc/smp.h new file mode 100644 index 0000000..739c156 --- /dev/null +++ b/include/inc/smp.h @@ -0,0 +1,110 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : smp.h */ +/* PRODUCT(S) : UCA Station Management Protocol (UCA SMP). */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file specifies internal defines and function */ +/* prototypes for UCA Station Management Protocol (UCA SMP). */ +/* */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/09/96 EJV 01 Created */ +/************************************************************************/ + +#ifndef SMP_INCLUDED +#define SMP_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + + /*--------------------------------------*/ + /* LLC level encoding values */ + /*--------------------------------------*/ + + /* (same in clnp_llc.h) */ +#define LLC_LSAP_SMP (ST_UCHAR) 0xFB /* For UCA SMP (Station Mgt Prot) */ +#define LLC_CONTROL_SMP (ST_UCHAR) 0x03 /* For UCA SMP (Station Mgt Prot) */ + + /*--------------------------------------*/ + /* Max size of Autorization field */ + /*--------------------------------------*/ + +#define SMP_SIZE_OF_AUTH 8 + + /*----------------------------------------------*/ + /* Valid codes SMP UCA PDU type */ + /*----------------------------------------------*/ + +#define SMP_UCA_PDU_ERROR 0 +#define SMP_UCA_PDU_TIMESYNC 1 + +#define SMP_PDU_INVALID_TYPE 255 + + /*----------------------------------------------*/ + /* Valid codes for TimeSync PDU type */ + /*----------------------------------------------*/ + +#define SMP_TIMESYNC_PDU_MEASURE_REQ 0 +#define SMP_TIMESYNC_PDU_MEASURE_RSP 1 +#define SMP_TIMESYNC_PDU_SYNC_REQ 2 +#define SMP_TIMESYNC_PDU_SYNC_RSP 3 +#define SMP_TIMESYNC_PDU_ERROR 4 +#define SMP_TIMESYNC_PDU_PREPARE 5 + + + /*----------------------------------------------*/ + /* Valid error codes in the UCA ErrorPDU */ + /*----------------------------------------------*/ + +#define SMP_ERR_NO_ERROR 0 +#define SMP_ERR_UNSUPPORTED 1 +#define SMP_ERR_UNRECOGNIZED_SERVICE 2 +#define SMP_ERR_PDU_ERROR 3 +#define SMP_ERR_OUT_OF_RESOURCES 4 + + /*----------------------------------------------*/ + /* Valid error codes in the Sync-ErrorPDU */ + /*----------------------------------------------*/ + +#define SMP_SYNC_ERR_NO_ERROR 0 +#define SMP_SYNC_ERR_LOCALLY_SYNCED 1 +#define SMP_SYNC_ERR_NOT_AUTHORIZED 2 +#define SMP_SYNC_ERR_NOT_MEASURED 3 +#define SMP_SYNC_ERR_SEQUENCE_PROBLEM 4 + + /*--------------------------------------*/ + /* globals in smp_dec.c module */ + /*--------------------------------------*/ + +extern ST_UCHAR smp_uca_pdu_type; +extern ST_UCHAR smp_err_code; +extern ST_UCHAR smp_timesync_pdu_type; +extern SMP_TIME smp_time_req; +extern SMP_TIME smp_time_rsp; +extern ST_UCHAR smp_auth [SMP_SIZE_OF_AUTH]; /* authentication */ +extern SMP_TIME smp_delta_time; +extern ST_UCHAR smp_sync_err_code; + +ST_RET smp_dec_uca_pdu (ST_UCHAR *pdu_buf, ST_UINT16 pdu_len); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + diff --git a/include/inc/smp_log.h b/include/inc/smp_log.h new file mode 100644 index 0000000..0b60ca4 --- /dev/null +++ b/include/inc/smp_log.h @@ -0,0 +1,286 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : smp_log.h */ +/* PRODUCT(S) : UCA Station Management Protocol (UCA SMP). */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file contains logging macros for SMP. */ +/* Note: To compile logging functions use the DEBUG_SISCO define */ +/* in the project make file. */ +/* */ +/* MODIFICATION LOG : */ +/* */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 10/08/98 MDE 05 Migrated to updated SLOG interface */ +/* 02/20/98 EJV 04 Corrected non-debug macro def */ +/* 11/17/97 EJV 03 Added check for HEX logging mask */ +/* 10/15/97 MDE 02 Added missing no debug macros */ +/* 09/09/97 EJV 01 Created */ +/************************************************************************/ + +#ifndef SMP_LOG_INCLUDED +#define SMP_LOG_INCLUDED + +#include "slog.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* NOTE: SMP uses log masks defined in the smp_usr.h set in the smp_debug_sel */ + + +#if defined(DEBUG_SISCO) + +/* Log type strings */ +extern SD_CONST ST_CHAR *SD_CONST _smp_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smp_req_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smp_ind_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smp_deb_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smp_hex_logstr; + + /*--------------------------------------------*/ + /* hard errors logging */ + /*--------------------------------------------*/ + + #define SMP_LOG_ERR0(a) {\ + if (smp_debug_sel & SMP_LOG_ERR)\ + _slog (sLogCtrl,_smp_err_logstr,thisFileName,__LINE__,a);\ + } + #define SMP_LOG_ERR1(a,b) {\ + if (smp_debug_sel & SMP_LOG_ERR)\ + _slog (sLogCtrl,_smp_err_logstr,thisFileName,__LINE__,a,b);\ + } + #define SMP_LOG_ERR2(a,b,c) {\ + if (smp_debug_sel & SMP_LOG_ERR)\ + _slog (sLogCtrl,_smp_err_logstr,thisFileName,__LINE__,a,b,c);\ + } + #define SMP_LOG_ERR3(a,b,c,d) {\ + if (smp_debug_sel & SMP_LOG_ERR)\ + _slog (sLogCtrl,_smp_err_logstr,thisFileName,__LINE__,a,b,c,d);\ + } + + /*--------------------------------------------*/ + /* SMP-user request logging */ + /*--------------------------------------------*/ + + #define SMP_LOG_REQ0(a) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slog (sLogCtrl,_smp_req_logstr,thisFileName,__LINE__,a);\ + } + #define SMP_LOG_REQ1(a,b) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slog (sLogCtrl,_smp_req_logstr,thisFileName,__LINE__,a,b);\ + } + #define SMP_LOG_REQ2(a,b,c) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slog (sLogCtrl,_smp_req_logstr,thisFileName,__LINE__,a,b,c);\ + } + #define SMP_LOG_REQ3(a,b,c,d) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slog (sLogCtrl,_smp_req_logstr,thisFileName,__LINE__,a,b,c,d);\ + } + #define SMP_LOG_REQ6(a,b,c,d,e,f,g) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slog (sLogCtrl,_smp_req_logstr,thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + + /* continuation log */ + #define SMP_LOGC_REQ0(a) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slogc (sLogCtrl,a);\ + } + #define SMP_LOGC_REQ1(a,b) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slogc (sLogCtrl,a,b);\ + } + #define SMP_LOGC_REQ2(a,b,c) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slogc (sLogCtrl,a,b,c);\ + } + #define SMP_LOGC_REQ6(a,b,c,d,e,f,g) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slogc (sLogCtrl,a,b,c,d,e,f,g);\ + } + + /* hex logging */ + #define SMP_LOGH_REQ(a,b) {\ + if (smp_debug_sel & SMP_LOG_REQ && \ + smp_debug_sel & SMP_LOG_HEX)\ + _slogHex (sLogCtrl,a,b);\ + } + + /* hex continuation logging */ + #define SMP_LOGHC_REQ(a,b) {\ + if (smp_debug_sel & SMP_LOG_REQ && \ + smp_debug_sel & SMP_LOG_HEX)\ + _slogHex (sLogCtrl,a,b);\ + } + /*--------------------------------------------*/ + /* SMP_user indication logging */ + /*--------------------------------------------*/ + + #define SMP_LOG_IND0(a) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slog (sLogCtrl,_smp_ind_logstr,thisFileName,__LINE__,a);\ + } + #define SMP_LOG_IND1(a,b) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slog (sLogCtrl,_smp_ind_logstr,thisFileName,__LINE__,a,b);\ + } + #define SMP_LOG_IND2(a,b,c) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slog (sLogCtrl,_smp_ind_logstr,thisFileName,__LINE__,a,b,c);\ + } + #define SMP_LOG_IND3(a,b,c,d) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slog (sLogCtrl,_smp_ind_logstr,thisFileName,__LINE__,a,b,c,d);\ + } + #define SMP_LOG_IND6(a,b,c,d,e,f,g) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slog (sLogCtrl,_smp_ind_logstr,thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + /* continuation log */ + #define SMP_LOGC_IND0(a) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slogc (sLogCtrl,a);\ + } + #define SMP_LOGC_IND1(a,b) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slogc (sLogCtrl,a,b);\ + } + #define SMP_LOGC_IND2(a,b,c) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slogc (sLogCtrl,a,b,c);\ + } + #define SMP_LOGC_IND6(a,b,c,d,e,f,g) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slogc (sLogCtrl,a,b,c,d,e,f,g);\ + } + + /* hex logging */ + #define SMP_LOGH_IND(a,b) {\ + if (smp_debug_sel & SMP_LOG_IND && \ + smp_debug_sel & SMP_LOG_HEX)\ + _slogHex (sLogCtrl,a,b);\ + } + + /* hex continuation logging */ + #define SMP_LOGHC_IND(a,b) {\ + if (smp_debug_sel & SMP_LOG_IND && \ + smp_debug_sel & SMP_LOG_HEX)\ + _slogHex (sLogCtrl,a,b);\ + } + + /*--------------------------------------------*/ + /* debugging app logging */ + /*--------------------------------------------*/ + + #define SMP_LOG_DEB0(a) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slog (sLogCtrl,_smp_deb_logstr,thisFileName,__LINE__,a);\ + } + #define SMP_LOG_DEB1(a,b) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slog (sLogCtrl,_smp_deb_logstr,thisFileName,__LINE__,a,b);\ + } + #define SMP_LOG_DEB2(a,b,c) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slog (sLogCtrl,_smp_deb_logstr,thisFileName,__LINE__,a,b,c);\ + } + #define SMP_LOG_DEB3(a,b,c,d) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slog (sLogCtrl,_smp_deb_logstr,thisFileName,__LINE__,a,b,c,d);\ + } + + #define SMP_LOGC_DEB0(a) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slogc (sLogCtrl,a);\ + } + #define SMP_LOGC_DEB1(a,b) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slogc (sLogCtrl,a,b);\ + } + #define SMP_LOGC_DEB2(a,b,c) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slogc (sLogCtrl,a,b,c);\ + } + #define SMP_LOGC_DEB3(a,b,c,d) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slogc (sLogCtrl,a,b,c,d);\ + } + +#else + + /* this are empty macros for compilation without the DEBUG_SISCO define */ + + /*--------------------------------------------*/ + /* hard errors logging */ + /*--------------------------------------------*/ + #define SMP_LOG_ERR0(a) + #define SMP_LOG_ERR1(a,b) + #define SMP_LOG_ERR2(a,b,c) + #define SMP_LOG_ERR3(a,b,c,d) + + /*--------------------------------------------*/ + /* SMP-user request (write) logging */ + /*--------------------------------------------*/ + + #define SMP_LOG_REQ0(a) + #define SMP_LOG_REQ1(a,b) + #define SMP_LOG_REQ2(a,b,c) + #define SMP_LOG_REQ3(a,b,c,d) + #define SMP_LOG_REQ6(a,b,c,d,e,f,g) + #define SMP_LOGC_REQ0(a) + #define SMP_LOGC_REQ1(a,b) + #define SMP_LOGC_REQ2(a,b,c) + #define SMP_LOGC_REQ6(a,b,c,d,e,f,g) + #define SMP_LOGH_REQ(a,b) + #define SMP_LOGHC_REQ(a,b) + + /*--------------------------------------------*/ + /* SMP-user indication (read) logging */ + /*--------------------------------------------*/ + + #define SMP_LOG_IND0(a) + #define SMP_LOG_IND1(a,b) + #define SMP_LOG_IND2(a,b,c) + #define SMP_LOG_IND3(a,b,c,d) + #define SMP_LOG_IND6(a,b,c,d,e,f,g) + #define SMP_LOGC_IND0(a) + #define SMP_LOGC_IND1(a,b) + #define SMP_LOGC_IND2(a,b,c) + #define SMP_LOGC_IND6(a,b,c,d,e,f,g) + #define SMP_LOGH_IND(a,b) + #define SMP_LOGHC_IND(a,b) + + /*--------------------------------------------*/ + /* debugging app logging */ + /*--------------------------------------------*/ + + #define SMP_LOG_DEB0(a) + #define SMP_LOG_DEB1(a,b) + #define SMP_LOG_DEB2(a,b,c) + #define SMP_LOG_DEB3(a,b,c,d) + #define SMP_LOGC_DEB0(a) + #define SMP_LOGC_DEB1(a,b) + #define SMP_LOGC_DEB2(a,b,c) + #define SMP_LOGC_DEB3(a,b,c,d) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ diff --git a/include/inc/smp_usr.h b/include/inc/smp_usr.h new file mode 100644 index 0000000..dc3030e --- /dev/null +++ b/include/inc/smp_usr.h @@ -0,0 +1,344 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997 - 1998, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : smp_usr.h */ +/* PRODUCT(S) : UCA Station Management Protocol (UCA SMP). */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module provides interface function to the SLAVE/MASTER */ +/* side of the UCA Station Management Protocol. */ +/* */ +/* Implemented Services: */ +/* Time Synchronization */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/18/98 EJV 04 Added smp_init function. */ +/* 11/17/97 EJV 03 Added HEX logging. Added par to smp_hc_config*/ +/* 10/13/97 EJV 02 Added defs for DLL. */ +/* 09/09/97 EJV 01 Created */ +/************************************************************************/ + +#ifndef SMP_USR_INCLUDED +#define SMP_USR_INCLUDED + + +#ifdef __cplusplus +extern "C" { +#endif + + /*--------------------------------------*/ + /* Max size of MAC and NSAP */ + /* (same in clnp_llc.h) */ + /*--------------------------------------*/ + +#define SMP_MAX_LEN_MAC 6 +#define SMP_MAX_LEN_NSAP 20 + + + /*--------------------------------------*/ + /* SMP logging types (for debugging) */ + /*--------------------------------------*/ + +#define SMP_LOG_ERR 0x00000001L +#define SMP_LOG_REQ 0x00000010L +#define SMP_LOG_IND 0x00000020L +#define SMP_LOG_DEB 0x00000040L +#define SMP_LOG_HEX 0x00000080L + +extern ST_UINT smp_debug_sel; + + /*--------------------------------------*/ + /* SMP_TIME struct */ + /*--------------------------------------*/ + +#define SMP_SIZE_OF_REC_TIME 32 /* buf size used to record binary time */ + +#define SMP_SIZE_OF_TIME 6 /* TimeOfDay size, see ISO/IEC 9506-2, clause 7.6.1 */ + +typedef struct + { + ST_INT32 days; /* number of days since January 1, 1984 */ + ST_INT32 msec; /* milliseconds since midnight for the current date */ + ST_INT32 usec; /* microseconds whithin current msec, if implemented */ + } SMP_TIME; + +/* This struct is used also to pass the time difference returned from */ +/* remote node after time synchronization */ + + /*--------------------------------------------------------------*/ + /* SLAVE application may disallow Time Synchronization from */ + /* Master by setting the smp_time_locally_sync to SD_TRUE. */ + /*--------------------------------------------------------------*/ + +extern ST_BOOLEAN smp_time_locally_sync; + + + /*======================================================*/ + /* Initialization functions */ + /*======================================================*/ + +/************************************************************************/ +/* smp_init */ +/*----------------------------------------------------------------------*/ +/* This function is called from the user code to initialize all global */ +/* variables used in SMP modules. */ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +ST_RET smp_init (ST_VOID); + + + /*======================================================*/ + /* SMP MASTER functions */ + /*======================================================*/ + +/************************************************************************/ +/* smp_time_sync_req_ar_name */ +/*----------------------------------------------------------------------*/ +/* Function called by Master to request Time Synchronization with */ +/* remote node. Implemented for TRIM7 stack . */ +/* This function will map remote rem_ar_name into a MAC address and call*/ +/* the smp_time_sync_req function. */ +/* */ +/* Parameters: */ +/* ST_LONG user_id */ +/* ST_UCHAR *rem_ar_name */ +/* ST_VOID (*callBackFun) */ +/* (ST_LONG user_id, ST_RET result, SMP_TIME *delta_time));*/ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +ST_RET smp_time_sync_req_ar_name ( + ST_LONG user_id, + ST_UCHAR *rem_ar_name, + ST_VOID (*callBackFun)(ST_LONG user_id, ST_RET result, SMP_TIME *delta_time)); + + + +/************************************************************************/ +/* smp_time_sync_req_chan */ +/*----------------------------------------------------------------------*/ +/* Function called by Master to request Time Synchronization with */ +/* remote node. Implemented for REDUCED STACK (only for ADLC subnet). */ +/* This function will map chan_num into a loc,rem MAC address pair and */ +/* call the smp_time_sync_req function. */ +/* */ +/* Note: A MMS connection must be established before calling this func. */ +/* */ +/* Parameters: */ +/* ST_LONG user_id */ +/* ST_INT chan_num */ +/* ST_VOID (*callBackFun) */ +/* (ST_LONG user_id, ST_RET result, SMP_TIME *delta_time));*/ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +ST_RET smp_time_sync_req_chan ( + ST_LONG user_id, + ST_INT chan_num, + ST_VOID (*callBackFun)(ST_LONG user_id, ST_RET result, SMP_TIME *delta_time)); + + +/************************************************************************/ +/* smp_time_sync_req */ +/*----------------------------------------------------------------------*/ +/* Function called by Master to request Time Synchronization with */ +/* remote node. */ +/* When the time synchronization has been completed or error occurred, */ +/* then the callBackFun will be used to notify the Master application */ +/* about the result of time synchronization request. */ +/* */ +/* !Note: This function requires that the application establishes */ +/* ADLC connection (for REDUCED_STACK) with given node before */ +/* calling this function. For TRIM7 stack ADLC connections are */ +/* maintained by ADLC_ML. */ +/* On the Ethernet there is no need to establish connection. */ +/* */ +/* Parameters: */ +/* ST_LONG user_id; for user to use */ +/* ST_UCHAR *loc_mac; Ptr to Local MAC address */ +/* ST_UCHAR *rem_mac; Ptr to Remote MAC address */ +/* ST_VOID (*callBackFun) */ +/* (ST_LONG user_id, ST_RET result, SMP_TIME *delta_time); */ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +ST_RET smp_time_sync_req ( + ST_LONG user_id, /* for user to use */ + ST_UCHAR *loc_mac, /* Ptr to Local MAC address */ + ST_UCHAR *rem_mac, /* Ptr to Remote MAC address */ + ST_VOID (*callBackFun)(ST_LONG user_id, ST_RET result, SMP_TIME *delta_time)); + + + + /*======================================================*/ + /* SMP common SLAVE/MASTER functions */ + /*======================================================*/ + +typedef struct + { + ST_UCHAR *pdu_buf; + ST_UINT16 pdu_len; + ST_UCHAR *loc_mac; + ST_UCHAR *rem_mac; + ST_UCHAR *rec_time; + } SMP_DATAUNIT; + + +/************************************************************************/ +/* smp_decode_uca_pdu */ +/*----------------------------------------------------------------------*/ +/* Function called by Slave application to decode received UCA Station */ +/* Management Protocol PDU after LLC header has been decoded (dest=0xFB)*/ +/* If the Slave application is a TRIM7 or Reduced Stack application */ +/* this function will be called automatically from proper decoding */ +/* functions. */ +/* */ +/* Parameters: */ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +ST_RET smp_decode_uca_pdu (SMP_DATAUNIT *smp_du); + + +/************************************************************************/ +/* smp_send_pdu_callback */ +/*----------------------------------------------------------------------*/ +/* This callback function called by ADLC sub-network layer when a PDU */ +/* has been sent. Saves time stamp of Measure-Response PDU only. */ +/* */ +/* Parameters: */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID smp_send_pdu_callback (ST_RET result, ST_LONG user_id, + ST_UCHAR *rec_time, ST_UINT rec_time_len); + + + /*======================================================*/ + /* SMP time SLAVE/MASTER functions implemented by user */ + /*======================================================*/ + + +#if defined(SMP_DLL) +#include +#define DllImport __declspec (dllimport) +#define DllExport __declspec (dllexport) +#endif + +/************************************************************************/ +/* u_smp_record_time */ +/*----------------------------------------------------------------------*/ +/* Function implemented by user to record time. */ +/* The rec_time is a buffer of rec_time_len bytes (SMP_SIZE_OF_REC_TIME)*/ +/* */ +/* Parameters: */ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +#if defined(SMP_DLL) +DllExport ST_RET WINAPI u_smp_record_time (ST_UCHAR *rec_time, ST_UINT rec_time_len); +#else +ST_RET u_smp_record_time (ST_UCHAR *rec_time, ST_UINT rec_time_len); +#endif + + +/************************************************************************/ +/* u_smp_convert_time */ +/*----------------------------------------------------------------------*/ +/* Function implemented by user converting recorded time in rec_time */ +/* buffer to the SMP_TIME struct the application uses. */ +/* The rec_time is a buffer of rec_time_len bytes (SMP_SIZE_OF_REC_TIME)*/ +/* */ +/* Parameters: */ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +#if defined(SMP_DLL) +DllExport ST_RET WINAPI u_smp_convert_time (ST_UCHAR *rec_time, + ST_UINT rec_time_len, + SMP_TIME *smp_time); +#else +ST_RET u_smp_convert_time (ST_UCHAR *rec_time, + ST_UINT rec_time_len, + SMP_TIME *smp_time); +#endif + + + /*======================================================*/ + /* SMP SLAVE functions implemented by user */ + /*======================================================*/ + + +/************************************************************************/ +/* u_smp_time_sync_ind */ +/*----------------------------------------------------------------------*/ +/* SLAVE function implemented by user to synchronize time. */ +/* */ +/* Parameters: */ +/* SLAVE side: */ +/* SMP_TIME *a1 recorded time of Measure-RequestPDU reception */ +/* SMP_TIME *a2 recorded time of Measure-ResponsePDU sending */ +/* MASTER side: */ +/* SMP_TIME *b1 recorded time of Measure-RequestPDU sending */ +/* SMP_TIME *b2 recorded time of Measure-ResponsePDU arrival */ +/* SMP_TIME *delta_time return the local_adjustement. */ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +ST_RET u_smp_time_sync_ind (SMP_TIME *a1, SMP_TIME *a2, + SMP_TIME *b1, SMP_TIME *b2, + SMP_TIME *delta_time); + + + + + /*======================================================*/ + /* For applications which do not link with TRIM7 or */ + /* Reduced Stack the smp_hc_config function may be */ + /* called to initialize needed parameters. */ + /*======================================================*/ + +/************************************************************************/ +/* smp_hc_config */ +/*----------------------------------------------------------------------*/ +/* This USER's func provides hard coded initialization of few parameters*/ +/* for applications which DO NOT link to TRIM7 or REDUCED STACK. */ +/* */ +/* Parameters: */ +/* ST_VOID *loc_addr Local ADLC address */ +/* (ignored for other subnet) */ +/* ST_CHAR *smpLogFile Pointer log file name buffer */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if initialization successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET smp_hc_config (ST_VOID *loc_addr, ST_CHAR *smpLogFile); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + diff --git a/include/inc/smpval.h b/include/inc/smpval.h new file mode 100644 index 0000000..c7c2535 --- /dev/null +++ b/include/inc/smpval.h @@ -0,0 +1,138 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2006-2006, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : smpval.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* Structures, functions for sending/receiving IEC 61850 Sampled */ +/* Value messages (according to IEC 61850-9-2). */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/15/08 JRB 03 Fix securityLen type (ST_UINT -> ST_INT). */ +/* 08/09/06 JRB 02 Fix svID len (Vstring65). */ +/* Change DatSet to Vstring129 (ObjectReference)*/ +/* 03/17/05 JRB 01 Created */ +/************************************************************************/ +#ifndef SMPVAL_INCLUDED +#define SMPVAL_INCLUDED + +#include "asn1r.h" /* need MMS_UTC_TIME */ +#include "ethertyp.h" /* need ETYPE_INFO */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_SMPVAL_SVID_LEN 65 /* 61850 MsvID, UsvID len */ +#define MAX_SMPVAL_OBJREF_LEN 129 /* 61850 ObjectReference len */ +#define MAX_SMPVAL_SECURITY_LEN 20 /* max len of security info */ + +/* Bit numbers in OptFlds bitstring (configured by SmvOpts in SCL file) */ +#define SVOPT_BITNUM_SMPRATE 0 +#define SVOPT_BITNUM_REFRTM 1 +#define SVOPT_BITNUM_SMPSYNCH 2 + +/************************************************************************/ +/* STRUCTURE DEFINITIONS */ +/************************************************************************/ +typedef struct + { + ST_UINT8 *SamplePtr; /* pointer to "Sample" data */ + ST_INT SampleLen; /* length of "Sample" data in bytes */ + ST_CHAR svID [MAX_SMPVAL_SVID_LEN+1]; /* MsvID or UsvID - Vstring65 */ + ST_BOOLEAN DatSetPres; /* is "DatSet" present in ASDU? */ + ST_CHAR DatSet [MAX_SMPVAL_OBJREF_LEN+1]; /* Vstring129 (ObjectReference)*/ + /* (Optional) */ + ST_UINT16 SmpCnt; + ST_UINT32 ConfRev; + ST_BOOLEAN SmpSynch; + ST_BOOLEAN RefrTmPres; /* is "RefrTm" present in ASDU? */ + MMS_UTC_TIME RefrTm; /* Optional */ + ST_BOOLEAN SmpRatePres; /* is "SmpRate" present in ASDU? */ + ST_UINT16 SmpRate; /* Optional */ + } SMPVAL_ASDU; + +typedef struct + { + ST_UINT16 numASDU; /* Num of ASDU concatenated into one APDU */ + SMPVAL_ASDU *asduArray; /* array of "numASDU" structs */ + /* allocated by smpval_msg_create OR */ + /* allocated during decode */ + ST_UCHAR securityBuf [MAX_SMPVAL_SECURITY_LEN]; /* security info*/ + ST_INT securityLen; /* len of security info */ + }SMPVAL_MSG; + + +/************************************************************************/ +/* Functions for sending SMPVAL messages. */ +/************************************************************************/ +SMPVAL_MSG *smpval_msg_create ( + ST_UINT numASDU); /* Num of ASDU concatenated into one APDU*/ + +ST_VOID smpval_msg_destroy (SMPVAL_MSG *smpvalMsg); + +/* Updates data stored for one ASDU to be sent in a SMPVAL message */ +ST_RET smpval_asdu_data_update ( + SMPVAL_MSG *smpvalMsg, /* SMPVAL msg info structure */ + ST_INT asduIdx, /* index into array of ASDU for this SMPVAL msg*/ + ST_UINT8 *SamplePtr, /* pointer to data */ + ST_INT SampleLen, /* length of data in bytes */ + ST_CHAR *svID, + ST_INT SmpCnt, + ST_BOOLEAN DatSetPres, /* SD_TRUE if optional DatSet should be sent*/ + ST_CHAR *DatSet, /* Optional (chk DatSetPres arg) */ + ST_UINT32 ConfRev, + ST_BOOLEAN SmpSynch, + ST_BOOLEAN RefrTmPres, /* SD_TRUE if optional RefrTm should be sent*/ + MMS_UTC_TIME *RefrTm, /* Optional (chk_RefrTmPres arg) */ + ST_BOOLEAN SmpRatePres, /* SD_TRUE if optional SmpRate should be sent*/ + ST_UINT16 SmpRate); /* Optional (chk SmpRatePres arg) */ + +/* Encodes complete SMPVAL message (APDU plus Ethertype header). */ +/* RETURNS: ptr to start of encoded message (or NULL on error) */ +ST_UCHAR *smpval_msg_encode ( + SMPVAL_MSG *smpvalMsg, /* SMPVAL msg info structure */ + ETYPE_INFO *etypeInfo, /* Ethertype info */ + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut);/* ptr to len encoded */ +ST_RET smpval_msg_send ( + SMPVAL_MSG *smpvalMsg, /* SMPVAL msg info structure */ + ETYPE_INFO *etypeInfo, /* Ethertype info */ + ST_UCHAR *dstMac); /* Destination (Multicast) MAC address */ + +/************************************************************************/ +/* Functions for receiving SMPVAL messages. */ +/************************************************************************/ +/* Decode SMPVAL message and fill in SMPVAL_MSG struct.*/ +SMPVAL_MSG *smpval_msg_decode ( + SN_UNITDATA *sn_req, /* message to decode */ + ETYPE_INFO *etypeInfo); /* where to store decoded Ethertype info*/ + +/* Must be called to free structure returned from smpval_msg_decode. */ +ST_VOID smpval_msg_free (SMPVAL_MSG *smpvalMsg); + +/************************************************************************/ +/* Utility functions */ +/************************************************************************/ +/* Copies data from source to destination but reverses the order of the */ +/* bytes (i.e. converts Big-Endian to Little-Endian or vice versa). */ +ST_VOID reverse_bytes ( + ST_UINT8 *dst, /* ptr to destination buffer */ + ST_UINT8 *src, /* ptr to source buffer */ + ST_INT numbytes); /* number of bytes to copy */ + +#ifdef __cplusplus +} +#endif +#endif /* included */ diff --git a/include/inc/sock_log.h b/include/inc/sock_log.h new file mode 100644 index 0000000..67c1ebb --- /dev/null +++ b/include/inc/sock_log.h @@ -0,0 +1,210 @@ +/************************************************************************/ +/* SOFTWARE MODULE HEADER ***********************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2002 - 2003, All Rights Reserved */ +/* */ +/* MODULE NAME : sock_log.h */ +/* PRODUCT(S) : General Sockets Interface logging */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/20/07 MDE 02 Modified macros to take ctx, log_disable */ +/* 06/25/03 JRB 01 Move log macros from "gensock2.h". */ +/************************************************************************/ +#ifndef SOCK_LOG_INCLUDED +#define SOCK_LOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define SOCK_LOG_ERR 0x0001 +#define SOCK_LOG_NERR 0x0002 +#define SOCK_LOG_FLOW 0x0004 +#define SOCK_LOG_RX 0x0008 +#define SOCK_LOG_TX 0x0010 + +extern ST_UINT sock_debug_sel; + +/* Log type strings */ +extern SD_CONST ST_CHAR *SD_CONST SOCK_LOG_ERR_TEXT; +extern SD_CONST ST_CHAR *SD_CONST SOCK_LOG_NERR_TEXT; +extern SD_CONST ST_CHAR *SD_CONST SOCK_LOG_FLOW_TEXT; +extern SD_CONST ST_CHAR *SD_CONST SOCK_LOG_RX_TEXT; +extern SD_CONST ST_CHAR *SD_CONST SOCK_LOG_TX_TEXT; + +/*********************** SOCK_LOG_ERR Macros *****************************/ + +#define SOCK_LOG_ERR0(ctx,a) \ + SLOG_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),SOCK_LOG_ERR_TEXT,a) +#define SOCK_LOG_ERR1(ctx,a,b) \ + SLOG_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),SOCK_LOG_ERR_TEXT,a,b) +#define SOCK_LOG_ERR2(ctx,a,b,c) \ + SLOG_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),SOCK_LOG_ERR_TEXT,a,b,c) +#define SOCK_LOG_ERR3(ctx,a,b,c,d) \ + SLOG_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),SOCK_LOG_ERR_TEXT,a,b,c,d) +#define SOCK_LOG_ERR4(ctx,a,b,c,d,e) \ + SLOG_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),SOCK_LOG_ERR_TEXT,a,b,c,d,e) +#define SOCK_LOG_ERR5(ctx,a,b,c,d,e,f) \ + SLOG_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),SOCK_LOG_ERR_TEXT,a,b,c,d,e,f) + +/* Continuation log macros */ +#define SOCK_LOG_ERRC0(ctx,a) \ + SLOGC_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),a) +#define SOCK_LOG_ERRC1(ctx,a,b) \ + SLOGC_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),a,b) +#define SOCK_LOG_ERRC2(ctx,a,b,c) \ + SLOGC_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),a,b,c) +#define SOCK_LOG_ERRC3(ctx,a,b,c,d) \ + SLOGC_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),a,b,c,d) +#define SOCK_LOG_ERRC4(ctx,a,b,c,d,e) \ + SLOGC_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),a,b,c,d,e) +#define SOCK_LOG_ERRC5(ctx,a,b,c,d,e,f) \ + SLOGC_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),a,b,c,d,e,f) + +/* Hex log macro */ +#define SOCK_LOG_ERRH(ctx,a,b) \ + SLOGH ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),a,b) + +/*********************** SOCK_LOG_NERR Macros *****************************/ + +#define SOCK_LOG_NERR0(ctx,a) \ + SLOG_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),SOCK_LOG_NERR_TEXT,a) +#define SOCK_LOG_NERR1(ctx,a,b) \ + SLOG_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),SOCK_LOG_NERR_TEXT,a,b) +#define SOCK_LOG_NERR2(ctx,a,b,c) \ + SLOG_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),SOCK_LOG_NERR_TEXT,a,b,c) +#define SOCK_LOG_NERR3(ctx,a,b,c,d) \ + SLOG_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),SOCK_LOG_NERR_TEXT,a,b,c,d) +#define SOCK_LOG_NERR4(ctx,a,b,c,d,e) \ + SLOG_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),SOCK_LOG_NERR_TEXT,a,b,c,d,e) +#define SOCK_LOG_NERR5(ctx,a,b,c,d,e,f) \ + SLOG_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),SOCK_LOG_NERR_TEXT,a,b,c,d,e,f) + +/* Continuation log macros */ +#define SOCK_LOG_NERRC0(ctx,a) \ + SLOGC_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),a) +#define SOCK_LOG_NERRC1(ctx,a,b) \ + SLOGC_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),a,b) +#define SOCK_LOG_NERRC2(ctx,a,b,c) \ + SLOGC_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),a,b,c) +#define SOCK_LOG_NERRC3(ctx,a,b,c,d) \ + SLOGC_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),a,b,c,d) +#define SOCK_LOG_NERRC4(ctx,a,b,c,d,e) \ + SLOGC_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),a,b,c,d,e) +#define SOCK_LOG_NERRC5(ctx,a,b,c,d,e,f) \ + SLOGC_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),a,b,c,d,e,f) + +/* Hex log macro */ +#define SOCK_LOG_NERRH(ctx,a,b) \ + SLOGH ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),a,b) + +/*********************** SOCK_LOG_FLOW Macros *****************************/ + +#define SOCK_LOG_FLOW0(ctx,a) \ + SLOG_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),SOCK_LOG_FLOW_TEXT,a) +#define SOCK_LOG_FLOW1(ctx,a,b) \ + SLOG_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),SOCK_LOG_FLOW_TEXT,a,b) +#define SOCK_LOG_FLOW2(ctx,a,b,c) \ + SLOG_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),SOCK_LOG_FLOW_TEXT,a,b,c) +#define SOCK_LOG_FLOW3(ctx,a,b,c,d) \ + SLOG_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),SOCK_LOG_FLOW_TEXT,a,b,c,d) +#define SOCK_LOG_FLOW4(ctx,a,b,c,d,e) \ + SLOG_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),SOCK_LOG_FLOW_TEXT,a,b,c,d,e) +#define SOCK_LOG_FLOW5(ctx,a,b,c,d,e,f) \ + SLOG_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),SOCK_LOG_FLOW_TEXT,a,b,c,d,e,f) + +/* Continuation log macros */ +#define SOCK_LOG_FLOWC0(ctx,a) \ + SLOGC_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),a) +#define SOCK_LOG_FLOWC1(ctx,a,b) \ + SLOGC_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),a,b) +#define SOCK_LOG_FLOWC2(ctx,a,b,c) \ + SLOGC_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),a,b,c) +#define SOCK_LOG_FLOWC3(ctx,a,b,c,d) \ + SLOGC_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),a,b,c,d) +#define SOCK_LOG_FLOWC4(ctx,a,b,c,d,e) \ + SLOGC_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),a,b,c,d,e) +#define SOCK_LOG_FLOWC5(ctx,a,b,c,d,e,f) \ + SLOGC_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),a,b,c,d,e,f) + +/* Hex log macro */ +#define SOCK_LOG_FLOWH(ctx,a,b) \ + SLOGH ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),a,b) + +/*********************** SOCK_LOG_RX Macros *****************************/ + +#define SOCK_LOG_RX0(ctx,a) \ + SLOG_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),SOCK_LOG_RX_TEXT,a) +#define SOCK_LOG_RX1(ctx,a,b) \ + SLOG_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),SOCK_LOG_RX_TEXT,a,b) +#define SOCK_LOG_RX2(ctx,a,b,c) \ + SLOG_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),SOCK_LOG_RX_TEXT,a,b,c) +#define SOCK_LOG_RX3(ctx,a,b,c,d) \ + SLOG_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),SOCK_LOG_RX_TEXT,a,b,c,d) +#define SOCK_LOG_RX4(ctx,a,b,c,d,e) \ + SLOG_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),SOCK_LOG_RX_TEXT,a,b,c,d,e) +#define SOCK_LOG_RX5(ctx,a,b,c,d,e,f) \ + SLOG_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),SOCK_LOG_RX_TEXT,a,b,c,d,e,f) + +/* Continuation log macros */ +#define SOCK_LOG_RXC0(ctx,a) \ + SLOGC_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),a) +#define SOCK_LOG_RXC1(ctx,a,b) \ + SLOGC_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),a,b) +#define SOCK_LOG_RXC2(ctx,a,b,c) \ + SLOGC_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),a,b,c) +#define SOCK_LOG_RXC3(ctx,a,b,c,d) \ + SLOGC_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),a,b,c,d) +#define SOCK_LOG_RXC4(ctx,a,b,c,d,e) \ + SLOGC_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),a,b,c,d,e) +#define SOCK_LOG_RXC5(ctx,a,b,c,d,e,f) \ + SLOGC_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),a,b,c,d,e,f) + +/* Hex log macro */ +#define SOCK_LOG_RXH(ctx,a,b) \ + SLOGH ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),a,b) + +/*********************** SOCK_LOG_TX Macros *****************************/ + +#define SOCK_LOG_TX0(ctx,a) \ + SLOG_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),SOCK_LOG_TX_TEXT,a) +#define SOCK_LOG_TX1(ctx,a,b) \ + SLOG_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),SOCK_LOG_TX_TEXT,a,b) +#define SOCK_LOG_TX2(ctx,a,b,c) \ + SLOG_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),SOCK_LOG_TX_TEXT,a,b,c) +#define SOCK_LOG_TX3(ctx,a,b,c,d) \ + SLOG_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),SOCK_LOG_TX_TEXT,a,b,c,d) +#define SOCK_LOG_TX4(ctx,a,b,c,d,e) \ + SLOG_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),SOCK_LOG_TX_TEXT,a,b,c,d,e) +#define SOCK_LOG_TX5(ctx,a,b,c,d,e,f) \ + SLOG_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),SOCK_LOG_TX_TEXT,a,b,c,d,e,f) + +/* Continuation log macros */ +#define SOCK_LOG_TXC0(ctx,a) \ + SLOGC_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),a) +#define SOCK_LOG_TXC1(ctx,a,b) \ + SLOGC_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),a,b) +#define SOCK_LOG_TXC2(ctx,a,b,c) \ + SLOGC_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),a,b,c) +#define SOCK_LOG_TXC3(ctx,a,b,c,d) \ + SLOGC_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),a,b,c,d) +#define SOCK_LOG_TXC4(ctx,a,b,c,d,e) \ + SLOGC_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),a,b,c,d,e) +#define SOCK_LOG_TXC5(ctx,a,b,c,d,e,f) \ + SLOGC_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),a,b,c,d,e,f) + +/* Hex log macro */ +#define SOCK_LOG_TXH(ctx,a,b) \ + SLOGH ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),a,b) + +#ifdef __cplusplus +} +#endif + +#endif /* SOCK_LOG_INCLUDED */ diff --git a/include/inc/ssec.h b/include/inc/ssec.h new file mode 100644 index 0000000..123907c --- /dev/null +++ b/include/inc/ssec.h @@ -0,0 +1,1182 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003 - 2008, All Rights Reserved */ +/* */ +/* MODULE NAME : ssec.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : This module provides user defines for SISCO's */ +/* Security Extensions for MMS-EASE, MMS-EASE Lite,*/ +/* ICCP, AXS4-MMS, AXS4-ICCP products. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/01/08 EJV 87 Chg S_SEC_VERSION_STR to 1.20 (for Win Vista)*/ +/* 05/14/08 EJV 86 Merged with non-Marben version. */ +/* 03/27/08 EJV 85 Use S_MAX_PATH instead of MAX_PATH. */ +/* 02/18/08 EJV 84 Changed to V2.00 for Sun Solaris. */ +/* 02/01/08 EJV 83 Added tags to typedef structs */ +/* 12/04/07 EJV 82 Added updateCRLists, ssleLoadCRLists (sh lib)*/ +/* 11/21/07 EJV 81 Added ssleSetCertStorePath */ +/* 09/05/07 EJV 80 Port to SNAP-Lite and LEAN-T stack. Cleanup. */ +/* cfgId is now CRC-32 computed on S_CERT_ID. */ +/* Merged S_SEC_LOC_AR and S_SEC_REM_AR into */ +/* S_SEC_LOC_REM_AR struct. */ +/* Merged sslLocalCertList and sslRemoteCertList*/ +/* into locRemCertList in S_SEC_CFG. */ +/* Del secManGetDebugSel (secman.dll eliminated)*/ +/* 03/06/07 EJV 79 Moved extern ssle_debug_sel from sslelog.h. */ +/* Changed to V1.9950 for MMS-SECURE-145-015. */ +/* 04/08/08 JRB 79 Chg () to (ST_VOID) in several prototypes. */ +/* 08/28/06 EJV 78 MMS-LITE SECURE: chg version to 1.10. */ +/* 03/02/06 EJV 77 Chg S_SEC_VERSION_STR to 1.10 (VS .NET 2005) */ +/* 01/04/06 EJV 76 Added DLLs incompatibility comments. */ +/* 10/25/05 EJV 75 Chg S_SEC_LITESECURE_NAME to fit identify */ +/* 09/22/05 EJV 74 Any new build use S_SEC_VERSION_STR 1.04 */ +/* 08/09/05 EJV 73 MMS-LITE SECURE: chg version to 1.0050. */ +/* Add extern LocalCertStorePath,CACertStorePath*/ +/* 02/25/05 MDE 72 Added sSecAssocConfChkEx */ +/* 01/31/05 ASK 71 Fix ST_MUTEX_SEM_SSEC to compile on QNX */ +/* 01/18/05 ASK 70 Chg ver back to 1.03 for (Win release) */ +/* 01/11/05 ASK 69 Added ST_MUTEX_SEM_SSEC for non-Windows */ +/* 01/10/05 ASK 68 Added ST_MUTEX_SEM_SSEC struct to ensure */ +/* alignment between S_SEC_CFG between */ +/* secman.dll and calling application */ +/* 01/06/05 ASK 67 Temporarily Chg ver to 1.0260 for Symantec */ +/* release. */ +/* 09/29/04 EJV 66 Chg ver to 1.03 for (Win release) */ +/* 09/02/04 EJV 65 Added S_SEC_PATH for sun. */ +/* 08/24/04 EJV 64 Chg from WIN32 to _WIN32. */ +/* Chg ver to 1.0251 for Windows ICCP-SECURE. */ +/* 04/08/04 EJV 63 _AIX: added S_SEC_PATH. */ +/* Chg ver to 1.02 for (AIX release) */ +/* 04/01/04 EJV 62 Chg ver to 1.0051 for (AIX beta) */ +/* 03/30/04 ASK 61 Added secManLckEnd proto */ +/* Added ssleCertFileToText proto for AIX */ +/* 03/12/04 ASK 60 Added ssleCertFileToXml proto for AIX */ +/* 03/10/04 EJV 59 Corr ver to 1.0050 for (AIX beta) */ +/* 03/05/04 MDE 58 Added AE Title for AR Security mode */ +/* 02/16/04 EJV 57 Chg S_SEC_DEF_SSL_PORT to 3782. */ +/* Added S_SEC_PORT_DELIM_CHAR. */ +/* Chg ver to 1.0150 for (AIX beta) */ +/* 02/09/04 EJV 56 Changed S_SEC_LITESECURE_NAME. */ +/* 01/16/04 EJV 55 Del forward reference to DIB_MATCH_CTRL. */ +/* Added _WIN32 for dllimport secManCfgChange. */ +/* 01/12/04 EJV 54 Added secManCfgChange proto for MMS_LITE */ +/* 12/04/03 ASK 53 Added secManCfgChange proto */ +/* 10/31/03 ASK 52 Rem CName type 'Unknown' */ +/* 10/21/03 EJV 51 Rem sSecFreeSecParam, sSecFreePartSecParam */ +/* 10/20/03 ASK 50 Added params to sSecUpdate, added */ +/* secManGetDebugSel proto, added */ +/* crlDropExisting to cfg */ +/* 10/16/03 ASK 49 Added sSecEnd and stopSSLEngine protos, */ +/* Chg ver to 1.00 */ +/* 10/10/03 MDE 48 Added crlCheckTime */ +/* 09/30/03 EJV 47 MMS-LITE: added S_SEC_LITESECURE_VERSION_STR */ +/* and S_SEC_LITESECURE_NAME. */ +/* Redefined macros SECLOG..._ to SEC_LOG_... */ +/* Added S_SEC_SSLE_LOG_DATA, S_SEC_SOCK_LOG_TX,*/ +/* S_SEC_SOCK_LOG_RX (reworked numbers). */ +/* Chg secLogMasks from ST_ULONG to ST_UINT. */ +/* MMS_LITE: Added global secManCfgXmlFile */ +/* 09/29/03 EJV 46 Chg ver to 0.9955 (snap.exe fix) */ +/* 08/25/03 EJV 45 Moved protos with GEN_SOCK to ssec_int.h */ +/* 08/21/03 ASK 44 Add clearTime to S_MACE_INFO struct. Chg some*/ +/* protos to pass this to verify time sig */ +/* 08/21/03 EJV 43 Added setGenSockSSL, ssecGetCipherSuite, */ +/* sSecGetCertId, sSecGetCertCtrl protos. */ +/* Chg ver to 0.9954 */ +/* 07/28/03 EJV 42 Chg MMS_LITE protos. */ +/* 07/18/03 ASK 41 Add software lock protos from secmanlck.c */ +/* 07/16/03 MDE 40 Changes to appAuthRequired values */ +/* 07/14/03 ASK 39 Add sSecUpdate and sslUpdate protos */ +/* 06/30/03 ASK 38 Added secManAccessCfg and secManReleaseCfg */ +/* protos. #include glbsem.h. Add mutex to */ +/* S_SEC_CONFIG struct. */ +/* 06/26/03 EJV 37 Chg GSOCK_... to SOCK_... log macros */ +/* 06/25/03 EJV 36 Chg ver to 0.9953 */ +/* 06/24/03 ASK 35 Added dynamic config API func protos */ +/* 06/20/03 EJV 34 Added SNAP_EXIT_EVENT_NAME. */ +/* 06/20/03 ASK 33 add S_SEC_EVENT_REKEY_FAILURE define */ +/* 06/19/03 MDE 32 Added rekeying to S_CERT_CTRL */ +/* 06/16/03 EJV 31 Del m_match.h, s_match.h; added suicacse.h; */ +/* Changed M_MATCH_CTRL to DIB_MATCH_CTRL. */ +/* 06/12/03 MDE 30 sSecAssocConfChk added srcChkDest parameter. */ +/* 06/12/03 MDE 29 Fixed up MMS_LITE over Marben */ +/* 06/12/03 MDE 28 Added M_MATCH support */ +/* 05/27/03 EJV 27 Chg ver to 0.9952 */ +/* 05/27/03 EJV 26 sSecAssocIndChk added parameter srcChkDest. */ +/* 05/27/03 EJV 25 S_SEC_PORT_DELIM_STR chg to '+' for compatib.*/ +/* 05/23/03 ASK 24 Changed secManLog to secManEventLog. Added */ +/* event define S_SEC_EVENT_SSL_FAILURE. Change */ +/* sSecPrintSrlNum to secManPrintSrlNum. */ +/* 05/14/03 MDE 23 Fixed up rekey parameters */ +/* 05/09/03 MDE 22 Corrected S_CIPHER_0C04xx, _0D02xx to use MD5*/ +/* 05/06/03 ASK 21 Add sSecUsrStart proto, changed secManStart */ +/* and startSSLEngine protos for new logging. */ +/* 05/01/03 ASK 20 Change to use S_SEC_SPARAMS for SUIC */ +/* 04/30/03 ASK 19 Add public key to S_CERT_INFO. Changed */ +/* S_SEC_MAX_SIGNED_TIME_LEN to 128 bytes. */ +/* Added protos for new signing time functions. */ +/* Added sSecCmpIssuer proto. */ +/* 04/29/03 EJV 18 Added S_SEC_MAX_IP_ADDR_LEN */ +/* Chg ver to 0.9951 */ +/* 04/21/03 MDE 17 Added cipher suites */ +/* 04/18/03 MDE 16 S_SEC_CONFIG changes */ +/* 04/18/03 MDE 15 Added S_APP_AUTHREQ_xxx defines */ +/* 04/18/03 MDE 14 Added Masks for Cipher Suite elements */ +/* 04/17/03 EJV 13 Moved asn1log.h. */ +/* 04/16/03 EJV 12 Added version string. */ +/* 04/15/03 JRB 11 Add forward ref for mvl_net_info. */ +/* 04/15/03 ASK 10 Added sSecPrintSrlNum proto. */ +/* 04/11/03 EJV 09 sSecAuthChk: changed ret to ST_RET */ +/* 04/10/03 EJV 08 Added sSecCmpCertId proto. */ +/* 04/10/03 MDE 07 Added ArSec support */ +/* 04/09/03 MDE 06 Merged ssecusr.c function protos */ +/* 04/09/03 MDE 05 Added AR security context declarations */ +/* 04/08/03 EJV 05 Added defs for all log masks in secLogMasks. */ +/* Changed secLogMasks to ST_ULONG. */ +/* 04/07/03 EJV 04 Added protos from ssecusr.c */ +/* 04/04/03 ASK 03 Changed serial number format. Added */ +/* SECLOG_DATA and SECLOG_DEBUG masks. Added */ +/* startSSLEngine proto. */ +/* 03/04/03 EJV 02 Added IPAddr string parsing tokens */ +/* 02/21/03 MDE 01 Created */ +/************************************************************************/ + +#ifndef S_SEC_INCLUDED +#define S_SEC_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "glbsem.h" +#include "acseauth.h" +#include "gen_list.h" +#include "asn1r.h" +#include "dibmatch.h" + +#if !defined(MMS_LITE) || defined(MAP30_ACSE) +/* for MMS-EASE, MMS-EASE Lite based products over Marben Stack */ +#define S_SEC_VERSION_STR "1.20" +#else +/* for MMS-EASE Lite products over LEAN-T Stack */ +#define S_SEC_LITESECURE_NAME "MMS-LITE-SECURE" +#define S_SEC_LITESECURE_VERSION_STR "1.10" +#endif + +#if !defined(MMS_LITE) || defined(MAP30_ACSE) +/* for MMS-EASE, MMS-EASE Lite based products over Marben Stack */ +#if !defined(_WIN32) +/* Security installation path on UNIX systems is fixed but diff on each system */ +#if defined(_AIX) +#define S_SEC_PATH "/usr/lpp/osill2/security" +#else /* other UNIX systems */ +#define S_SEC_PATH "/usr/osill2/security" +#endif +#endif /* !defined(_WIN32) */ +#endif /* !defined(MMS_LITE) || defined(MAP30_ACSE) */ + +#if defined(_WIN32) + #if defined(MMS_LITE) + #define SISCO_REGISTRY_SECURITY "SOFTWARE\\SISCO\\Secure MMS-EASE Lite\\CurrentVersion" + #else /* !defined(MMS_LITE) */ + #define SISCO_REGISTRY_SECURITY "SOFTWARE\\SISCO\\Security\\CurrentVersion" + #endif /* !defined(MMS_LITE) */ +#endif /* defined(_WIN32) */ + + + +/************************************************************************/ +/************************************************************************/ +/* NOTES ON CERTIFICATE NAME MATCHING */ +/* This sSec API has a number of functions that must match certificates */ +/* based on a S_CERT_ID data structure. In all cases the matching */ +/* process works as follows: */ +/* */ +/* The matching can be based on certificate number, subject, */ +/* issuer, or any combination of these as specified in the certId. */ +/* For instance, the following specifications are valid: */ +/* 1. Serial Number only */ +/* 2. Subject only */ +/* 3. Issuer only */ +/* 4. Subject and Issuer */ +/* 5. Subject and Serial Number */ +/* 6. Issuer and Serial Number */ +/* 7. Subject, Issuer, Serial Number */ + +/* Note that the all elements of the input 'certId' must be present and */ +/* match exactly in the local certificate. That is, all elements of the */ +/* certificate name must be present and in the specified order. */ + +/************************************************************************/ +/************************************************************************/ +#define SEC_LOG_ERR 0x00000001 +#define SEC_LOG_NERR 0x00000002 +#define SEC_LOG_FLOW 0x00000004 +#define SEC_LOG_DATA 0x00000008 +#define SEC_LOG_DEBUG 0x00000010 + +extern ST_UINT sec_debug_sel; + +/************************************************************************/ +/* LOGGING */ +/* The logging masks defined here are used to set the secLogMasks field */ +/* in the S_SEC_CONFIG (defined below). The application can set the */ +/* proper module logging masks by examining the secLogMasks. */ +/* Note that ERR logging is set by default to ON in all modules. */ +/* The name of masks have been copied here and prefixed with S_SEC_... */ +/* for easy reference. */ + +/* log masks for sec_debug_sel (ssec.h) */ +#define S_SEC_SEC_LOG_NERR 0x00000001 +#define S_SEC_SEC_LOG_FLOW 0x00000002 +#define S_SEC_SEC_LOG_DATA 0x00000004 +#define S_SEC_SEC_LOG_DEBUG 0x00000008 +/* log masks for ssle_debug_sel (sslEngine.h) */ +#define S_SEC_SSLE_LOG_NERR 0x00000010 +#define S_SEC_SSLE_LOG_FLOW 0x00000020 +#define S_SEC_SSLE_LOG_DATA 0x00000040 +#define S_SEC_SSLE_LOG_DEBUG 0x00000080 +/* log masks for snap_debug_sel (snaplog.h) */ +#define S_SEC_SNAP_LOG_NERR 0x00000100 +#define S_SEC_SNAP_LOG_FLOW 0x00000200 +/* log masks for sock_debug_sel (gensock2.h) */ +#define S_SEC_SOCK_LOG_NERR 0x00000400 +#define S_SEC_SOCK_LOG_FLOW 0x00000800 +#define S_SEC_SOCK_LOG_TX 0x00001000 +#define S_SEC_SOCK_LOG_RX 0x00002000 +/* log masks for sx_debug_sel (sx_defs.h) */ +#define S_SEC_SX_LOG_NERR 0x00004000 +#define S_SEC_SX_LOG_DEC 0x00008000 +#define S_SEC_SX_LOG_ENC 0x00010000 +#define S_SEC_SX_LOG_FLOW 0x00020000 +#define S_SEC_SX_LOG_DEBUG 0x00040000 +/* log masks for asn1_debug_sel (asn1r.h) */ +#define S_SEC_ASN1_LOG_NERR 0x00080000 +#define S_SEC_ASN1_LOG_DEC 0x00100000 +#define S_SEC_ASN1_LOG_ENC 0x00200000 +/* log masks for gs_debug_sel (glbsem.h) */ +#define S_SEC_GS_LOG_NERR 0x00400000 +#define S_SEC_GS_LOG_FLOW 0x00800000 +/* log masks for chk_debug_en (mem_chk.h) */ +#define S_SEC_MEM_LOG_CALLOC 0x01000000 +#define S_SEC_MEM_LOG_MALLOC 0x02000000 +#define S_SEC_MEM_LOG_REALLOC 0x04000000 +#define S_SEC_MEM_LOG_FREE 0x08000000 +/* the rest of bits are used for memory debugging flags: */ +#define S_SEC_m_check_list_enable 0x10000000 +#define S_SEC_m_find_node_enable 0x20000000 +#define S_SEC_m_no_realloc_smaller 0x40000000 +/* 0x80000000 free */ + +/************************************************************************/ +/* SNAP Startup Event Names */ + +#if defined(_WIN32) +#define SNAP_STARTED_EVENT_NAME "snap.started" +#define SNAP_RUNNING_EVENT_NAME "snap.running" +#define SNAP_EXIT_EVENT_NAME "snap.exit" +#endif + +/************************************************************************/ +/* Allowed authType values */ + +#define S_SEC_AUTHTYPE_NONE 0 +#define S_SEC_AUTHTYPE_CERTIFICATE 1 +#define S_SEC_AUTHTYPE_SYMMETRIC 2 + +/************************************************************************/ +/* General Defines */ + +/* Maximum signed time data size */ +#define S_SEC_MAX_SIGNED_TIME_LEN 128 + +/* Help in sizing the asn1 buffer (really more like 25 ...) */ +#define S_SEC_ASN1_BUF_OH 50 + +/* Maximum size of the certificate serial number (in bytes) */ +#define S_SEC_MAX_SERIAL_LEN 64 + +/************************************************************************/ +/* MACE decode error codes */ + +#define MACE_ASN1_INCOMPLETE 0x9102 +#define MACE_ASN1_SYMMETRIC_NOT_SUPPORTED 0x9103 + +/************************************************************************/ +/* Default Ports */ + +/* SSL Port */ +#define S_SEC_DEF_SSL_PORT 3782 + +/* IPC Ports */ +#define S_SEC_DEF_STACK_PORT 10042 +#define S_SEC_DEF_SNAP_PORT 10043 +#define S_SEC_DEF_SNAP_CONTROL_PORT 10044 +#define S_SEC_DEF_SNAP_MONITOR_PORT 10045 + + +/************************************************************************/ +/* Remote address and security info formatting tokens */ + +#define S_SEC_IP_ADDR_DELIM_STR "SSL:" +#define S_SEC_PORT_DELIM_STR "+" +#define S_SEC_PORT_DELIM_CHAR '+' /* same as above but in ' ' */ +#define S_SEC_CIPHER_DELIM_STR "+" +#define S_SEC_CERT_ID_DELIM_STR "," + +#define S_SEC_MAX_IP_ADDR_LEN 20 + +/************************************************************************/ +/* Security Subsystem Error Codes */ + +#define S_SEC_ERR_VALIDITY_TOOSOON 0xA001 /* 40961 */ +#define S_SEC_ERR_VALIDITY_EXPIRED 0xA002 /* 40962 */ +#define S_SEC_ERR_CNAME_TYPE_UNKNOWN 0xA003 /* 40963 */ +#define S_SEC_ERR_CNAME_MISSING 0xA004 /* 40964 */ +#define S_SEC_ERR_CNAME_EXTRA 0xA005 /* 40965 */ +#define S_SEC_ERR_CNAME_MISMATCH 0xA006 /* 40966 */ +#define S_SEC_ERR_TIME_SEAL_INVALID 0xA007 /* 40967 */ +#define S_SEC_ERR_TIME_SEAL_TIME_WINDOW 0xA008 /* 40968 */ +#define S_SEC_ERR_READ_INSTALL_PATH 0xA009 /* 40969 */ +/* DEBUG: these codes are not appearing anywhere */ + +/************************************************************************/ +/* Cipher Suite Selection Defines */ + +#define S_MAX_ALLOWED_CIPHER_SUITES 49 + +/* Masks for Cipher Suite elements */ +#define S_KEYX_MASK 0xff0000 +#define S_CRYPT_MASK 0x00ff00 +#define S_HASH_MASK 0x0000ff + + +/* Key Exchange Algorithms */ +#define S_KEYX_NONE 0x000000 +#define S_KEYX_NULL 0x010000 +#define S_KEYX_RSA 0x020000 +#define S_KEYX_RSA_EX 0x030000 +#define S_KEYX_DH_DSS 0x040000 +#define S_KEYX_DH_DSS_EX 0x050000 +#define S_KEYX_DH_RSA 0x060000 +#define S_KEYX_DH_RSA_EX 0x070000 +#define S_KEYX_DHE_DSS 0x080000 +#define S_KEYX_DHE_DSS_EX 0x090000 +#define S_KEYX_DHE_RSA 0x0A0000 +#define S_KEYX_DHE_RSA_EX 0x0B0000 +#define S_KEYX_DH_ANON 0x0C0000 +#define S_KEYX_DH_ANON_EX 0x0D0000 +#define S_KEYX_FORTEZZA_DMS 0x0E0000 + +/* Encryption Algorithms */ +#define S_CRYPT_NONE 0x000000 +#define S_CRYPT_NULL 0x000100 +#define S_CRYPT_RC4_40 0x000200 +#define S_CRYPT_RC4_56 0x000300 +#define S_CRYPT_RC4_128 0x000400 +#define S_CRYPT_RC2_CBC_40 0x000500 +#define S_CRYPT_IDEA_CBC 0x000600 +#define S_CRYPT_DES40_CBC 0x000700 +#define S_CRYPT_DES_CBC 0x000800 +#define S_CRYPT_3DES_EDE_CBC 0x000900 +#define S_CRYPT_FORTEZZA_CBC 0x000A00 +#define S_CRYPT_AES_128_CBC 0x000B00 +#define S_CRYPT_AES_256_CBC 0x000C00 + +/* Hash Algorithms */ +#define S_HASH_NONE 0x000000 +#define S_HASH_NULL 0x000001 +#define S_HASH_MD5 0x000002 +#define S_HASH_SHA 0x000003 + +/* Cipher Suite Seletion */ +#define S_CIPHER_NOSSL 0x000000 +#define S_CIPHER_ANY 0xFFFFFF + +/* 49 Cipher Suites are defined by SSL 3.0 and TLS 1.0 */ +/* Bit fields: Key Exchange Encryption Hash */ +#define S_CIPHER_NONE (S_KEYX_NONE | S_CRYPT_NONE | S_HASH_NONE) +#define S_CIPHER_010103 (S_KEYX_NULL | S_CRYPT_NULL | S_HASH_SHA) +#define S_CIPHER_020102 (S_KEYX_RSA | S_CRYPT_NULL | S_HASH_MD5) +#define S_CIPHER_020103 (S_KEYX_RSA | S_CRYPT_NULL | S_HASH_SHA) +#define S_CIPHER_020402 (S_KEYX_RSA | S_CRYPT_RC4_128 | S_HASH_MD5) +#define S_CIPHER_020403 (S_KEYX_RSA | S_CRYPT_RC4_128 | S_HASH_SHA) +#define S_CIPHER_020603 (S_KEYX_RSA | S_CRYPT_IDEA_CBC | S_HASH_SHA) +#define S_CIPHER_020803 (S_KEYX_RSA | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_020903 (S_KEYX_RSA | S_CRYPT_3DES_EDE_CBC | S_HASH_SHA) +#define S_CIPHER_020B03 (S_KEYX_RSA | S_CRYPT_AES_128_CBC | S_HASH_SHA) +#define S_CIPHER_020C03 (S_KEYX_RSA | S_CRYPT_AES_256_CBC | S_HASH_SHA) +#define S_CIPHER_030202 (S_KEYX_RSA_EX | S_CRYPT_RC4_40 | S_HASH_MD5) +#define S_CIPHER_030303 (S_KEYX_RSA_EX | S_CRYPT_RC4_56 | S_HASH_SHA) +#define S_CIPHER_030502 (S_KEYX_RSA_EX | S_CRYPT_RC2_CBC_40 | S_HASH_MD5) +#define S_CIPHER_030703 (S_KEYX_RSA_EX | S_CRYPT_DES40_CBC | S_HASH_SHA) +#define S_CIPHER_030803 (S_KEYX_RSA_EX | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_040803 (S_KEYX_DH_DSS | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_040903 (S_KEYX_DH_DSS | S_CRYPT_3DES_EDE_CBC | S_HASH_SHA) +#define S_CIPHER_040B03 (S_KEYX_DH_DSS | S_CRYPT_AES_128_CBC | S_HASH_SHA) +#define S_CIPHER_040C03 (S_KEYX_DH_DSS | S_CRYPT_AES_256_CBC | S_HASH_SHA) +#define S_CIPHER_050703 (S_KEYX_DH_DSS_EX | S_CRYPT_DES40_CBC | S_HASH_SHA) +#define S_CIPHER_060803 (S_KEYX_DH_RSA | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_060903 (S_KEYX_DH_RSA | S_CRYPT_3DES_EDE_CBC | S_HASH_SHA) +#define S_CIPHER_060B03 (S_KEYX_DH_RSA | S_CRYPT_AES_128_CBC | S_HASH_SHA) +#define S_CIPHER_060C03 (S_KEYX_DH_RSA | S_CRYPT_AES_256_CBC | S_HASH_SHA) +#define S_CIPHER_070703 (S_KEYX_DH_RSA_EX | S_CRYPT_DES40_CBC | S_HASH_SHA) +#define S_CIPHER_080403 (S_KEYX_DHE_DSS | S_CRYPT_RC4_128 | S_HASH_SHA) +#define S_CIPHER_080803 (S_KEYX_DHE_DSS | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_080903 (S_KEYX_DHE_DSS | S_CRYPT_3DES_EDE_CBC | S_HASH_SHA) +#define S_CIPHER_090303 (S_KEYX_DHE_DSS_EX | S_CRYPT_RC4_56 | S_HASH_SHA) +#define S_CIPHER_090703 (S_KEYX_DHE_DSS_EX | S_CRYPT_DES40_CBC | S_HASH_SHA) +#define S_CIPHER_090803 (S_KEYX_DHE_DSS_EX | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_080B03 (S_KEYX_DHE_DSS | S_CRYPT_AES_128_CBC | S_HASH_SHA) +#define S_CIPHER_080C03 (S_KEYX_DHE_DSS | S_CRYPT_AES_256_CBC | S_HASH_SHA) +#define S_CIPHER_0A0803 (S_KEYX_DHE_RSA | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_0A0903 (S_KEYX_DHE_RSA | S_CRYPT_3DES_EDE_CBC | S_HASH_SHA) +#define S_CIPHER_0A0B03 (S_KEYX_DHE_RSA | S_CRYPT_AES_128_CBC | S_HASH_SHA) +#define S_CIPHER_0A0C03 (S_KEYX_DHE_RSA | S_CRYPT_AES_256_CBC | S_HASH_SHA) +#define S_CIPHER_0B0703 (S_KEYX_DHE_RSA_EX | S_CRYPT_DES40_CBC | S_HASH_SHA) +#define S_CIPHER_0C0402 (S_KEYX_DH_ANON | S_CRYPT_RC4_128 | S_HASH_MD5) +#define S_CIPHER_0C0803 (S_KEYX_DH_ANON | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_0C0903 (S_KEYX_DH_ANON | S_CRYPT_3DES_EDE_CBC | S_HASH_SHA) +#define S_CIPHER_0C0B03 (S_KEYX_DH_ANON | S_CRYPT_AES_128_CBC | S_HASH_SHA) +#define S_CIPHER_0C0C03 (S_KEYX_DH_ANON | S_CRYPT_AES_256_CBC | S_HASH_SHA) +#define S_CIPHER_0D0202 (S_KEYX_DH_ANON_EX | S_CRYPT_RC4_40 | S_HASH_MD5) +#define S_CIPHER_0D0703 (S_KEYX_DH_ANON_EX | S_CRYPT_DES40_CBC | S_HASH_SHA) +#define S_CIPHER_0E0103 (S_KEYX_FORTEZZA_DMS | S_CRYPT_NULL | S_HASH_SHA) +#define S_CIPHER_0E0403 (S_KEYX_FORTEZZA_DMS | S_CRYPT_RC4_128 | S_HASH_SHA) +#define S_CIPHER_0E0A03 (S_KEYX_FORTEZZA_DMS | S_CRYPT_FORTEZZA_CBC | S_HASH_SHA) + +/************************************************************************/ +/* Certificate Names */ + +/* nameType defines */ +#define S_CERT_NAME_TYPE_ANY 0 +#define S_CERT_NAME_TYPE_COMMON_NAME 1 +#define S_CERT_NAME_TYPE_COUNTRY 2 +#define S_CERT_NAME_TYPE_STATE_OR_PROVINCE 3 +#define S_CERT_NAME_TYPE_LOCALITY 4 +#define S_CERT_NAME_TYPE_ORGANIZATION 5 +#define S_CERT_NAME_TYPE_EMAIL 6 +#define S_CERT_NAME_TYPE_ORGANIZATIONAL_UNIT 7 + +#define S_CERT_NAME_MAX_LEN 255 + +/* A name in a certificate is a list of names and nane types */ +typedef struct S_CERT_NAME_tag + { + DBL_LNK l; + ST_INT nameType; + ST_CHAR *nameText; + } S_CERT_NAME; + + +/************************************************************************/ +/* Identifying a Certificate */ + +#define S_SERIAL_NUM_NONE -1 + +typedef struct S_CERT_ID_tag + { + /* Note: adding/removing fields to/from this struct will make older */ + /* !!! applications incompatible with new security DLLs. */ + ST_INT serialLen; /* 0 == wildcard */ + ST_UCHAR serialNumber[S_SEC_MAX_SERIAL_LEN]; /* reverse from mmc */ + S_CERT_NAME *issuerCName; /* NULL == wildcard */ + S_CERT_NAME *subjectCName; /* NULL == wildcard */ + } S_CERT_ID; + + +/************************************************************************/ +/* Certificate BLOB, X.509 format */ + +typedef struct S_CERT_BLOB_tag + { + /* Note: adding/removing fields to/from this struct will make older */ + /* !!! applications incompatible with new security DLLs. */ + ST_INT certDataLen; + ST_UCHAR *certData; + } S_CERT_BLOB; + +/************************************************************************/ +/* Signed Time */ + +typedef struct S_SIGNED_TIME_tag + { + /* Note: adding/removing fields to/from this struct will make older */ + /* !!! applications incompatible with new security DLLs. */ + ST_INT signedTimeLen; + ST_UCHAR *signedTimeData; + } S_SIGNED_TIME; + +/************************************************************************/ +/* MACE authentication information */ + +typedef struct S_MACE_INFO_tag + { + ST_INT authType; + union + { + struct + { + S_CERT_BLOB certBlob; + time_t signedTimeT; + + /* UTC NULL-terminated time string to be verified */ + ST_UCHAR clearTime[S_SEC_MAX_SIGNED_TIME_LEN]; + /* UTC time string signed by the sender */ + S_SIGNED_TIME signedTime; + + } certBased; + struct + { + ST_INT placeHolder; + } symmetric; + } u; + } S_MACE_INFO; + + +/************************************************************************/ +/************************************************************************/ +/* Certificate Content Information */ + +typedef struct S_CERT_INFO_tag + { + /* Note: adding/removing fields to/from this struct will make older */ + /* applications incompatible with new security DLLs. */ + ST_INT version; + S_CERT_ID certId; + struct + { + time_t validNotBefore; + time_t validNotAfter; + } validity; + +#if 0 + struct + { + ST_INT publicKeyAlgorithm; + ST_INT algorithmIdentifier; + } algorithms; +#endif + + ST_UCHAR *publicKey; + ST_INT publicKeyLen; + } S_CERT_INFO; + + +/************************************************************************/ +/************************************************************************/ +/* Security Configuration */ +/************************************************************************/ + +/* List of Certificate ID's */ +typedef struct S_CERT_CTRL_tag + { + DBL_LNK l; + ST_CHAR *certName; /* Null if no associated name */ + S_CERT_ID certId; + +/* Rekey Control. These override the global rekey parameters if != 0 */ +/* They apply only to remote certificates */ + ST_UINT32 maxTransactionsPerKey; + ST_UINT32 maxTimePerKey; /* in seconds */ + ST_INT rekeyTimeout; /* In seconds */ + +/* Internal use */ + ST_UINT32 cfgId; /* computed 32-bit CRC on certId */ + /* enabled fields (for matching) */ + } S_CERT_CTRL; + +/************************************************************************/ +/* AR Security Mapping Defines */ + +/* appAuthRequired defines */ +/* These defines come into play only if 'Remote AR Security' is not */ +/* found for an incoming connection */ + +/* 'Remote AR Security' is required; reject all other indications */ +#define S_APP_AUTHREQ_AR_SEC 0 +/* A configured MACE certificate is required */ +#define S_APP_AUTHREQ_MACE 1 +/* A configured MACE certificate is required and encryption is required */ +#define S_APP_AUTHREQ_MACE_ENCRYPTED 2 +/* Encryption is required */ +#define S_APP_AUTHREQ_ENCRYPTED 3 +/* There are no requirements; all connections are acceptable */ +#define S_APP_AUTHREQ_NONE 4 + + + +#define S_AR_AUTH_MODE_AETITLE 0 +#define S_AR_AUTH_MODE_MACE 1 +#define S_AR_AUTH_MODE_SSL 2 +/* For backward compatibility only */ +#define S_AR_AUTH_MODE_NONE S_AR_AUTH_MODE_AETITLE + +/* Note that the Local is used to select the local MACE certificate for */ +/* connections to a remote with arAuthMode == S_AR_AUTH_MODE_MACE */ +typedef struct S_SEC_LOC_AR_tag + { + DBL_LNK l; + ST_CHAR *arName; /* Local or Remote AR Name */ + S_CERT_CTRL *maceCert; /* NULL if none configured */ + +/* User */ + ST_VOID *usr; + } S_SEC_LOC_AR; + +/* Remote AR Security Configuration */ +/* Note that the Remote is used to determine the ACSE authentication */ +/* and encryption to be used for both calling and called connections, */ +/* and is used in identifying the remote for called connections */ +typedef struct S_SEC_REM_AR_tag + { + DBL_LNK l; + ST_CHAR *arName; /* Local or Remote AR Name */ + + /* Authentication */ + ST_INT arAuthMode; + +/* Authentication Certificate: */ +/* arAuthMode == S_AR_AUTH_MODE_MACE : Remote MACE cert */ +/* arAuthMode == S_AR_AUTH_MODE_SSL : Remote SSL cert */ +/* arAuthMode == S_AR_AUTH_MODE_NONE : NULL */ + S_CERT_CTRL *authCert; + +/* Encryption */ + ST_INT encryptMode; + ST_UINT16 sslPort; /* For S_SEC_ENCRYPT_SSL */ + +/* User */ + ST_VOID *usr; + } S_SEC_REM_AR; + +#if defined(_WIN32) +/* Placeholder struct kept only for compatibility purposes with older + * applications. Used in main S_SEC_CFG struct below. + */ +typedef struct + { + ST_INT mutexType; /* GS_MUTEX_UNNAMED (_NAMED) */ + union + { + HANDLE hMutex; /* for named mutex */ + CRITICAL_SECTION cs; /* for unnamed mutex */ + } u; + } ST_MUTEX_SEM_SSEC; +#else +#define ST_MUTEX_SEM_SSEC ST_MUTEX_SEM +#endif + +/************************************************************************/ +/**** Main Configuration Structure ****/ + +#define S_SSL_MAX_LISTEN_PORTS 10 +typedef struct + { + /* Note: adding/removing fields to/from this struct will make older */ + /* !!! applications incompatible with new security DLLs. */ + + /****** General Configuration ******/ + ST_BOOLEAN secureModeEnabled; + + /* Old struct kept around for alignment purposes with old(er) apps */ + ST_MUTEX_SEM_SSEC obsoleteCfgMutex; + + /****** MACE Level Configuration ******/ + /* Time Signature Window */ + ST_UINT32 timeSealWindow; + + /****** Certificate Lists ******/ + /* Remote Certificates and associated AR Names */ + S_CERT_CTRL *sslRemoteCertList; + + /* Local Certificates and associated AR Names */ + S_CERT_CTRL *sslLocalCertList; + + /* Acceptable CA Certificates */ + S_CERT_CTRL *sslTrustedCaCertList; + + /****** SSL Configuration ******/ + /* Local Certificate to be used */ + S_CERT_CTRL *sslLocalCertCtrl; + + /* Listen Port Numbers */ + ST_INT numSslListenPorts; + ST_UINT16 sslListenPorts[S_SSL_MAX_LISTEN_PORTS]; + + /* Allowed Ciphers, ordered by preference */ + ST_INT numAllowedCipherSuites; + ST_INT allowedCipherSuites[S_MAX_ALLOWED_CIPHER_SUITES]; + + /* Flags */ + ST_BOOLEAN certAuthCalling; /* verify that peer certificate is configured */ + ST_BOOLEAN certAuthCalled; /* verify that peer certificate is configured */ + ST_BOOLEAN encryptReqCalling; /* encryption required on calling connection */ + ST_BOOLEAN encryptReqCalled; /* encryption required on called connection */ + + /* Rekey Control */ + ST_UINT32 maxTransactionsPerKey; + ST_UINT32 maxTimePerKey; /* in seconds */ + ST_INT rekeyTimeout; /* In seconds */ + + /* CRL Control */ + ST_INT crlCheckTime; /* In minutes */ + ST_BOOLEAN crlDropExisting; + + /****** Application Configuation */ + ST_INT appAuthRequired; + DIB_MATCH_CTRL dibMatch; + + /* Well Known AR Names */ + S_SEC_LOC_AR *secLocArList; + S_SEC_REM_AR *secRemArList; + + /****** SNAP Configuation */ + ST_UINT16 defCallingSslPort; /* Default SSL Calling Port Number */ + + /* Misc */ + ST_UINT maxCalling; + ST_UINT maxCalled; + + ST_INT cpuAffinity; + + /* Calling connection timeout, used by SNAP. Default 10000ms */ + ST_INT callingConnectTimeout; /* In milliseconds */ + + /****** IPC: SNAP/Stack Ports & IP Addresses */ + ST_CHAR *stackIPAddress; + ST_UINT16 stackListenPort; + + ST_CHAR *snapIPAddress; + ST_UINT16 snapListenPort; + ST_UINT16 snapControlListenPort; + ST_UINT16 snapMonitorListenPort; + + /* SNAP/STACK Connect-to-Ctrl timeout, bidirectional. Default 500ms */ + ST_INT snapStackCtrlTimeout; /* In milliseconds */ + + /****** Security Logging ******/ + ST_INT secEventLogTimeStampMode; + ST_INT secEventLogFileSize; + ST_CHAR *secEventLogFile; + ST_INT diagLogTimeStampMode; + ST_INT diagLogFileSize; + ST_CHAR *diagLogFileName; + ST_UINT secLogMasks; + } S_SEC_CONFIG; + + +/************************************************************************/ +/************************************************************************/ + +#define S_SEC_ENCRYPT_NONE 0 +#define S_SEC_ENCRYPT_SSL 1 +typedef struct S_SEC_ENCRYPT_CTRL_tag + { + ST_INT encryptMode; + union + { + struct + { + ST_UINT16 port; + ST_BOOLEAN sslCertMatched; /* The Subject-to-CertId succeded */ + S_CERT_CTRL *sslCert; /* The matched SSL cert ctrl */ + ST_INT cipherSuite; /* Cipher suite in use */ + } ssl; + } u; + } S_SEC_ENCRYPT_CTRL; + +/* Struct passed back and forth to SUIC */ +typedef struct S_SEC_SPARAMS_tag + { + ACSE_AUTH_INFO *authInfo; + ACSE_AUTH_INFO *partAuthInfo; + S_SEC_ENCRYPT_CTRL *encryptCtrl; + } S_SEC_SPARAMS; + +/************************************************************************/ + +/* Application Level Authentication Check Result */ +typedef struct S_SEC_AUTHCHK_RSLT_tag + { +/* Encryption in use */ + S_SEC_ENCRYPT_CTRL encryptInfo; + +/* Authentication in use */ + ST_INT authPres; + ST_INT mechType; + union + { + struct + { + ST_BOOLEAN timeSealOk; /* Timeseal not reused, in window */ + ST_BOOLEAN maceCertTimeValid; /* Certificate validity times OK */ + ST_BOOLEAN maceCertIssuerOk; /* The issuer is in the OK list */ + ST_BOOLEAN maceCertMatched; /* The Subject-to-CertId succeded */ + S_CERT_CTRL *maceCert; /* The matched MACE cert ctrl */ + } certBased; + struct + { + ST_INT placeHolder; + } symmetric; + struct + { + ST_INT placeHolder2; + } passsword; + } u; + } S_SEC_AUTHCHK_RSLT; + +/************************************************************************/ +/* Look up configured security information by AR Name */ +ST_RET sSecRemArNameToArSec (ST_CHAR *arName, S_SEC_REM_AR **arSecOut); +ST_RET sSecLocArNameToArSec (ST_CHAR *arName, S_SEC_LOC_AR **arSecOut); + +/************************************************************************/ +/* These functions can be used to select and examine SSL level info */ +/* for the selected connection */ +#if defined(MMS_LITE) && !defined(MAP30_ACSE) +/* ssecusr.c functions */ +struct mvl_net_info; /* forward reference */ +ST_RET sSecAssocIndChk (struct mvl_net_info *cc, DIB_MATCH_CTRL *matchCtrl, + S_SEC_REM_AR **arSecOut, S_SEC_AUTHCHK_RSLT *srcChkDest); +ST_RET sSecAssocConfChkEx (struct mvl_net_info *cc, DIB_MATCH_CTRL *matchCtrl, + S_SEC_REM_AR *remArSec, S_SEC_AUTHCHK_RSLT *srcChkDest); +ST_RET sSecAuthChk (struct mvl_net_info *cc, S_SEC_AUTHCHK_RSLT *srcChkDest); +ST_RET sSecGetSecParam (struct mvl_net_info *cc, S_SEC_SPARAMS *secParams); +ST_RET sSecFreeSecParam (ACSE_AUTH_INFO *authInfo); +ST_RET sSecFreePartSecParam (struct mvl_net_info *cc); + +/* For backward compatability */ +#define sSecAssocConfChk(cc,remArSec,secChkDest) sSecAssocConfChkEx(cc,NULL,remArSec,secChkDest) +#else /* !defined(MMS_LITE) || defined(MAP30_ACSE) */ +/* ssecusr.c functions */ +ST_RET sSecAssocIndChk (ST_INT chan, DIB_MATCH_CTRL *matchCtrl, + S_SEC_REM_AR **arSecOut, S_SEC_AUTHCHK_RSLT *srcChkDest); +ST_RET sSecAssocConfChkEx (ST_INT chan, DIB_MATCH_CTRL *matchCtrl, + S_SEC_REM_AR *remArSec, S_SEC_AUTHCHK_RSLT *srcChkDest); +ST_INT sSecAuthChk (ST_INT chan, S_SEC_AUTHCHK_RSLT *srcChkDest); +ST_RET sSecSetSecParam (ST_INT chan, S_SEC_SPARAMS *secParams); +ST_RET sSecGetSecParam (ST_INT chan, S_SEC_SPARAMS *secParams); + +/* For backward compatability */ +#define sSecAssocConfChk(chan,remArSec,secChkDest) sSecAssocConfChkEx(chan,NULL,remArSec,secChkDest) +#endif /* !defined(MMS_LITE) || defined(MAP30_ACSE) */ + + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* Initialize/Terminate */ + +ST_RET sSecUsrStart (S_SEC_CONFIG **secCfgOut); +ST_RET sSecUsrEnd (ST_VOID); +ST_RET sSecStart (S_SEC_CONFIG **secCfg); +ST_RET sSecEnd (ST_VOID); + +/************************************************************************/ +/* Configuration */ + +/* Used by configuration app to get SEC_MAN config information */ +ST_CHAR *secManGetXmlCfg (ST_VOID); +ST_RET secManSetXmlCfg (ST_CHAR *pw, ST_CHAR *xmlCfg); +ST_RET secManExportLocalCerts (ST_CHAR *pw, ST_INT *destFile); + +/* Used by app to reload security components */ +ST_RET sSecUpdate(S_SEC_CONFIG *currCfg, S_SEC_CONFIG *newCfg); + +/************************************************************************/ +/* MACE Authentication */ + +/* Create/Free MACE Authentication Information for a local CertId */ +ST_RET sSecMaceAuthInfoCreate (S_CERT_ID *certId, ACSE_AUTH_INFO *authInfo); + +ST_VOID sSecMaceAuthInfoFree (ACSE_AUTH_INFO *auth_info); + +/* Decode MACE Authentication Information */ +ST_RET sSecMaceAuthInfoDec (ACSE_AUTH_INFO *authInfo, + S_MACE_INFO **maceInfoOut, + S_CERT_INFO **certInfoOut); +ST_VOID sSecFreeCertInfo (S_CERT_INFO *certInfo); + +/************************************************************************/ +/************************************************************************/ +/* Finding things in the Security Configuration */ + +/**** Find configured local CertCtrl for given certName ****/ +ST_RET sSecCertNameToLocCertCtrl (ST_CHAR *certName, S_CERT_CTRL **certCtrlOut); + +/**** Find configured remote CertCtrl for given certName ****/ +ST_RET sSecCertNameToRemCertCtrl (ST_CHAR *certName, S_CERT_CTRL **certCtrlOut); + +/**** Find configured remote CertCtrl for given CertId ****/ +ST_RET sSecCertIdToRemCertCtrl (S_CERT_ID *certId, S_CERT_CTRL **certCtrlOut); + +/**** Find configured remote CertCtrl for given cfgId ****/ +ST_RET sSecCertCfgIdToRemCertCtrl (ST_INT cfgId, S_CERT_CTRL **CertCtrlOut); + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/**** Certificate Blob Handling ****/ + +/* Retrieve local Certificate Blob from Certifcate Store */ +ST_RET sSecGetLocalCert (S_CERT_ID *certId, S_CERT_BLOB *certDataOut); + +/* Decoding a Certificate blob */ +ST_RET sSecCertDec (S_CERT_BLOB *certBlob, S_CERT_INFO **certInfoOut); + +/************************************************************************/ +/**** Signed Time Handling ****/ + +/* Verify a Signed Time signature */ +ST_RET sSecSignedTimeVerify (S_CERT_INFO *remCert, S_SIGNED_TIME *signedTime, ST_UCHAR *clearTime); + +/* Sign a time_t */ +ST_RET sSecSignTimeT (S_CERT_ID *localCert, S_SIGNED_TIME *signedTime, time_t timeToSign); + +/************************************************************************/ +/**** MACE ASN.1 Encode/Decode ****/ + +/* Encode MACE ACSE Authentication */ +ST_RET sSecMaceAsn1Enc (S_MACE_INFO *maceInfo, + ST_CHAR *asn1Buf, ST_INT asn1BufLen, + ST_CHAR **maceAsn1Out, ST_INT *maceAsn1LenOut); + +/* Decode Certificate based ACSE Authentication */ +ST_RET sSecMaceAsn1Dec (ST_CHAR *maceAsn1, ST_INT maceAsn1Len, + S_MACE_INFO **maceInfoOut); + +/************************************************************************/ +/**** Remote Certificate Validity Checking ****/ + +/* Make sure the certificate issuer is OK */ +ST_RET sSecChkIssuer (S_CERT_INFO *certInfo); + +/* Make sure the certificate validity times are OK */ +ST_RET sSecChkValidityTimes (S_CERT_INFO *certInfo); + +/* Validate a MACE time seal */ +ST_RET sSecChkTimeSeal (S_CERT_INFO *remCert, + time_t signedTimeT, + ST_UCHAR *clearTime, + S_SIGNED_TIME *signedTime); + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* Common functions declarations */ + +/**** Compare remote cert issuer names with ones that we trust ****/ +ST_BOOLEAN sSecCmpIssuer (S_CERT_ID *remCert, S_CERT_ID *trustedCert); +/**** Compare two CertIds ****/ +ST_BOOLEAN sSecCmpCertId (S_CERT_ID *certId1, S_CERT_ID *certId2); + +/* Export a certificate to XML */ +#if !defined(_WIN32) +ST_INT ssleCertFileToXml (ST_CHAR *fileName, ST_CHAR *buf, ST_INT bufLen, ST_CHAR *pass); +/* Export a certificate to Text */ +ST_INT ssleCertFileToText (ST_CHAR *fileName, ST_CHAR *buf, ST_INT bufLen, ST_CHAR *pass); +#endif /* !defined(_WIN32) */ + +ST_RET ssleLoadCRLists(ST_VOID *ssl_ctx, ST_BOOLEAN *newCrlOut); + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* secMan Declarations */ +/************************************************************************/ + +/* Set log masks */ +ST_UINT* secManGetDebugSel(ST_VOID); + +/* Start/Stop */ +ST_RET secManStart (S_SEC_CONFIG **secCfg, ST_VOID *secLog); +ST_RET secManEnd (ST_VOID); + +/* Start the SSL Engine in ssec.lib (genssl.c) */ +ST_RET startSSLEngine(S_SEC_CONFIG *sSecCfg, ST_VOID *secLog); +/* Stop the SSL Engine in ssec.lib (genssl.c) */ +ST_RET stopSSLEngine(ST_VOID); +/* Called by SNAP to reload the security configuration (genssl.c) */ +ST_RET sslUpdate(ST_VOID); +/* Called by SNAP-Lite to reload the CRLs (genssl.c) */ +ST_RET updateCRLists (ST_VOID); + +/* Used by SNAP and user apps to get the configuration. + * The release function MUST be called when the app is done using the + * configuration. + */ +ST_RET secManAccessCfg (S_SEC_CONFIG **secCfgOut); +ST_RET secManReleaseCfg (ST_VOID); + +/* Used by the stack to get the configuration */ +ST_RET secManAccessCfgByStack (S_SEC_CONFIG **secCfgOut); + +/* Dynamic Configuration functions */ +ST_BOOLEAN secManChkNewCfgAvail(ST_VOID); +ST_RET secManLoadCfg(S_SEC_CONFIG *secCfgOut); +ST_RET secManUpdateCfg(S_SEC_CONFIG *currCfg, S_SEC_CONFIG *newCfg); +ST_RET secManFreeCfg(S_SEC_CONFIG *secCfg); + +#if !defined(MMS_LITE) || defined(MAP30_ACSE) +#if defined (_WIN32) +/* Called by app or SecCfg to signal change in configuration file */ +__declspec(dllimport) ST_VOID WINAPI secManCfgChange(ST_VOID); +/* __declspec(dllexport) ST_VOID WINAPI secManCfgChange(ST_VOID);*/ +#endif +#else /* MMS_LITE */ +ST_VOID secManCfgChange(ST_VOID); +#endif /* MMS_LITE */ + +#if !defined(MMS_LITE) || defined(MAP30_ACSE) +/* Software Lock access */ +ST_RET secManLckStart(ST_VOID); +ST_VOID secManLckEnd(ST_VOID); +ST_RET secManLckCheck(ST_VOID); +#else +/* MMS_LITE */ +extern ST_CHAR *secManCfgXmlFile; +#endif + +#if !defined(_WIN32) +/* --- For UNIX & LINUX define default path to Certificate Stores --- */ +/* --- under the SISCO_PATH_INSTALL/SISCO_PATH_SECURITY directory --- */ +#define CERT_STORE_LOCAL "certstore/local" +#define CERT_STORE_CA "certstore/ca" +#define CERT_STORE_REMOTE "certstore/remote" + +/* If needed these paths can be changed by app before sSecStart() is called */ +extern ST_CHAR LocalCertStorePath[S_MAX_PATH]; /* defaults to CERT_STORE_LOCAL */ +extern ST_CHAR CACertStorePath[S_MAX_PATH]; /* defaults to CERT_STORE_CA */ + +/* Exported function from libsecpass shared library (provided by the user) */ +ST_RET secPassGetPassword(S_CERT_ID *certId, ST_CHAR *certPass, ST_INT certPassLen); +#endif /* !defined(_WIN32) */ + +/* Logging */ +/* destLog defines */ +#define S_SEC_LOGTYPE_NONE 0 +#define S_SEC_LOGTYPE_DIAG 1 +#define S_SEC_LOGTYPE_SECURITY 2 + +/* eventType defines */ +#define S_SEC_EVENT_NO_CIPHERS 1 +#define S_SEC_EVENT_UNKNOWN_CA 2 +#define S_SEC_EVENT_UNKNOWN_REMOTE 3 +#define S_SEC_EVENT_SSL_FAILURE 4 +#define S_SEC_EVENT_REKEY_FAILURE 5 + +typedef struct S_SEC_EVENT_tag + { + /* Note: adding/removing fields to/from this struct will make older */ + /* !!! applications incompatible with new security DLLs. */ + ST_INT destLog; /* Select Diagnoistic or Security log */ + + /* This section needs work */ + ST_BOOLEAN logSystemEvent; /* Log to System event system */ + ST_INT eventType; + ST_INT8 numArgs; + ST_CHAR *eventArgs[32]; + + ST_BOOLEAN logToSlog; /* Log to SLOG file */ + ST_INT logType; /* Standard SLOG information */ + ST_CHAR *SD_CONST logTypeStr; + ST_CHAR *SD_CONST sourceFile; + ST_INT lineNum; + ST_INT bufLen; + ST_CHAR *buf; + } S_SEC_EVENT; + +/* Logging to Event Viewer via secman.dll */ +ST_VOID secManEventLog (S_SEC_EVENT *secEvent, S_CERT_INFO *cert); + +/**** Output the serial number as a string ****/ +ST_VOID secManPrintSrlNum (S_CERT_ID *certId, ST_CHAR *outBuf, ST_INT outBufLen); + +/* Log configuration to diagnostic log */ +ST_VOID secManLogCfg (ST_VOID); + +/* Clone the log file */ +ST_VOID secManCloneLog (ST_INT logType); + +/************************************************************************/ +/************************************************************************/ +/* Log Macros */ + +/* Log type strings */ +extern SD_CONST ST_CHAR *SD_CONST _sec_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sec_nerr_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sec_flow_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sec_data_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sec_debug_logstr; + +#define SECLOG_ERR0(a) \ + SLOG_0 (sec_debug_sel & SEC_LOG_ERR, _sec_err_logstr, a) +#define SECLOG_ERR1(a,b) \ + SLOG_1 (sec_debug_sel & SEC_LOG_ERR, _sec_err_logstr, a,b) +#define SECLOG_ERR2(a,b,c) \ + SLOG_2 (sec_debug_sel & SEC_LOG_ERR, _sec_err_logstr, a,b,c) +#define SECLOG_ERR3(a,b,c,d) \ + SLOG_3 (sec_debug_sel & SEC_LOG_ERR, _sec_err_logstr, a,b,c,d) + +#define SECLOG_CERR0(a) \ + SLOGC_0 (sec_debug_sel & SEC_LOG_ERR,a) +#define SECLOG_CERR1(a,b) \ + SLOGC_1 (sec_debug_sel & SEC_LOG_ERR,a,b) +#define SECLOG_CERR2(a,b,c) \ + SLOGC_2 (sec_debug_sel & SEC_LOG_ERR,a,b,c) + +#define SECLOG_NERR0(a) \ + SLOG_0 (sec_debug_sel & SEC_LOG_NERR, _sec_nerr_logstr, a) +#define SECLOG_NERR1(a,b) \ + SLOG_1 (sec_debug_sel & SEC_LOG_NERR, _sec_nerr_logstr, a,b) +#define SECLOG_NERR2(a,b,c) \ + SLOG_2 (sec_debug_sel & SEC_LOG_NERR, _sec_nerr_logstr, a,b,c) +#define SECLOG_NERR3(a,b,c,d) \ + SLOG_3 (sec_debug_sel & SEC_LOG_NERR, _sec_nerr_logstr, a,b,c,d) + +#define SECLOG_FLOW0(a) \ + SLOG_0 (sec_debug_sel & SEC_LOG_FLOW, _sec_flow_logstr, a) +#define SECLOG_FLOW1(a,b) \ + SLOG_1 (sec_debug_sel & SEC_LOG_FLOW, _sec_flow_logstr, a,b) +#define SECLOG_FLOW2(a,b,c) \ + SLOG_2 (sec_debug_sel & SEC_LOG_FLOW, _sec_flow_logstr, a,b,c) +#define SECLOG_FLOW3(a,b,c,d) \ + SLOG_3 (sec_debug_sel & SEC_LOG_FLOW, _sec_flow_logstr, a,b,c,d) + +#define SECLOG_CFLOW0(a) \ + SLOGC_0 (sec_debug_sel & SEC_LOG_FLOW,a) +#define SECLOG_CFLOW1(a,b) \ + SLOGC_1 (sec_debug_sel & SEC_LOG_FLOW,a,b) + +#define SECLOG_DEBUG0(a) \ + SLOG_0 (sec_debug_sel & SEC_LOG_DEBUG, _sec_debug_logstr, a) +#define SECLOG_DEBUG1(a,b) \ + SLOG_1 (sec_debug_sel & SEC_LOG_DEBUG, _sec_debug_logstr, a,b) +#define SECLOG_DEBUG2(a,b,c) \ + SLOG_2 (sec_debug_sel & SEC_LOG_DEBUG, _sec_debug_logstr, a,b,c) +#define SECLOG_DEBUG3(a,b,c,d) \ + SLOG_3 (sec_debug_sel & SEC_LOG_DEBUG, _sec_debug_logstr, a,b,c,d) + +#define SECLOG_CDEBUG0(a) \ + SLOGC_0 (sec_debug_sel & SEC_LOG_DEBUG,a) +#define SECLOG_CDEBUG1(a,b) \ + SLOGC_1 (sec_debug_sel & SEC_LOG_DEBUG,a,b) + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* S_SEC_INCLUDED */ +/************************************************************************/ diff --git a/include/inc/ssec_int.h b/include/inc/ssec_int.h new file mode 100644 index 0000000..b8445d4 --- /dev/null +++ b/include/inc/ssec_int.h @@ -0,0 +1,56 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003 - 2007, All Rights Reserved */ +/* */ +/* MODULE NAME : ssec_int.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains internal security functions, defines,... */ +/* that are not exposed to user. */ +/* It also contains function that are passing GEN_SOCK parameter. */ +/* Having these protos in ssec.h caused compile conflicts in */ +/* project using old gensock.h */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/06/07 EJV 02 Chg sSecGetCertId param to ST_UINT32. */ +/* Added few prototypes. */ +/* 08/25/03 EJV 01 Moved protos with GEN_SOCK from ssec.h */ +/************************************************************************/ + +#ifndef SSEC_INT_INCLUDED +#define SSEC_INT_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gensock2.h" + + +/* internal functions for secure socket interface */ +ST_RET setGenSockSSL (GEN_SOCK_CONFIG *sockCfg); +ST_RET sSecGetCipherSuite (GEN_SOCK *pSock, ST_INT *cipherSuiteOut); +ST_RET sSecGetCertId (GEN_SOCK *pSock, ST_UINT32 *cfgIdOut); +ST_RET sSecGetCertCtrl (GEN_SOCK *pSock, S_CERT_CTRL **certCtrlOut); + +ST_RET _secManGetCfg (S_SEC_CONFIG **secCfgOut); + +ST_INT sslGetCipherSuite (GEN_SOCK *pSock); +S_CERT_INFO *sslGetPeerCert (GEN_SOCK *pSock); +ST_VOID sslFreePeerCert (S_CERT_INFO *remCert); + + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* SSEC_INT_INCLUDED */ +/************************************************************************/ diff --git a/include/inc/ssleLog.h b/include/inc/ssleLog.h new file mode 100644 index 0000000..76490b9 --- /dev/null +++ b/include/inc/ssleLog.h @@ -0,0 +1,154 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003 - 2008, All Rights Reserved */ +/* */ +/* MODULE NAME : sslLog.h */ +/* PRODUCT(S) : Sisco MMS Security Toolkit */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* SSL Toolkit logging macros */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/28/08 EJV 24 Merged with non-Marben code. */ +/* 04/08/08 JRB 05 Chg () to (ST_VOID) in prototype. */ +/* 10/20/03 ASK 04 Added ssleGetDebugSel proto. Modlog cleanup. */ +/* 09/03/03 EJV 03 Made ssle_debug_sel ST_UINT */ +/* Moved SSLE_LOG_* masks from sslEngine.h */ +/* 08/21/03 EJV 02 Made ssle_debug_sel extern */ +/* 08/21/02 ASK 01 Created */ +/************************************************************************/ + +#ifndef SSLE_LOG_INCLUDED +#define SSLE_LOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "slog.h" + +/* Log control masks */ +#define SSLE_LOG_ERR 0x00000001 +#define SSLE_LOG_NERR 0x00000002 +#define SSLE_LOG_FLOW 0x00000004 +#define SSLE_LOG_DATA 0x00000008 +#define SSLE_LOG_DEBUG 0x00000010 + +extern ST_UINT ssle_debug_sel; + +/* Function so user can set log masks */ +ST_UINT* ssleGetDebugSel(ST_VOID); +ST_UINT *ssleGetASN1DebugSel(ST_VOID); +/* Function so user can set memory debug flag */ +ST_BOOLEAN *ssleGetMemDebug (ST_VOID); + +/* Internal SSL Toolkit Utility Functions */ +ST_VOID _ssleLogError(ST_ULONG err); + +/* The log macros */ +#define SSLE_LOG_ERR0(a) \ + SLOG_0 (ssle_debug_sel & SSLE_LOG_ERR, "SSLE_LOG_ERR", a) +#define SSLE_LOG_ERR1(a,b) \ + SLOG_1 (ssle_debug_sel & SSLE_LOG_ERR, "SSLE_LOG_ERR", a,b) +#define SSLE_LOG_ERR2(a,b,c) \ + SLOG_2 (ssle_debug_sel & SSLE_LOG_ERR, "SSLE_LOG_ERR", a,b,c) +#define SSLE_LOG_ERR3(a,b,c,d) \ + SLOG_3 (ssle_debug_sel & SSLE_LOG_ERR, "SSLE_LOG_ERR", a,b,c,d) +#define SSLE_LOG_ERR4(a,b,c,d,e) \ + SLOG_4 (ssle_debug_sel & SSLE_LOG_ERR, "SSLE_LOG_ERR", a,b,c,d,e) + +#define SSLE_LOG_NERR0(a) \ + SLOG_0 (ssle_debug_sel & SSLE_LOG_NERR, "SSLE_LOG_NERR", a) +#define SSLE_LOG_NERR1(a,b) \ + SLOG_1 (ssle_debug_sel & SSLE_LOG_NERR, "SSLE_LOG_NERR", a,b) +#define SSLE_LOG_NERR2(a,b,c) \ + SLOG_2 (ssle_debug_sel & SSLE_LOG_NERR, "SSLE_LOG_NERR", a,b,c) +#define SSLE_LOG_NERR3(a,b,c,d) \ + SLOG_3 (ssle_debug_sel & SSLE_LOG_NERR, "SSLE_LOG_NERR", a,b,c,d) +#define SSLE_LOG_NERR4(a,b,c,d,e) \ + SLOG_4 (ssle_debug_sel & SSLE_LOG_NERR, "SSLE_LOG_NERR", a,b,c,d,e) + +#define SSLE_LOG_FLOW0(a) \ + SLOG_0 (ssle_debug_sel & SSLE_LOG_FLOW, "SSLE_LOG_FLOW", a) +#define SSLE_LOG_FLOW1(a,b) \ + SLOG_1 (ssle_debug_sel & SSLE_LOG_FLOW, "SSLE_LOG_FLOW", a,b) +#define SSLE_LOG_FLOW2(a,b,c) \ + SLOG_2 (ssle_debug_sel & SSLE_LOG_FLOW, "SSLE_LOG_FLOW", a,b,c) +#define SSLE_LOG_FLOW3(a,b,c,d) \ + SLOG_3 (ssle_debug_sel & SSLE_LOG_FLOW, "SSLE_LOG_FLOW", a,b,c,d) +#define SSLE_LOG_FLOW4(a,b,c,d,e) \ + SLOG_4 (ssle_debug_sel & SSLE_LOG_FLOW, "SSLE_LOG_FLOW", a,b,c,d,e) + +#define SSLE_LOG_DEBUG0(a) \ + SLOG_0 (ssle_debug_sel & SSLE_LOG_DEBUG, "SSLE_LOG_DEBUG", a) +#define SSLE_LOG_DEBUG1(a,b) \ + SLOG_1 (ssle_debug_sel & SSLE_LOG_DEBUG, "SSLE_LOG_DEBUG", a,b) +#define SSLE_LOG_DEBUG2(a,b,c) \ + SLOG_2 (ssle_debug_sel & SSLE_LOG_DEBUG, "SSLE_LOG_DEBUG", a,b,c) +#define SSLE_LOG_DEBUG3(a,b,c,d) \ + SLOG_3 (ssle_debug_sel & SSLE_LOG_DEBUG, "SSLE_LOG_DEBUG", a,b,c,d) +#define SSLE_LOG_DEBUG4(a,b,c,d,e) \ + SLOG_4 (ssle_debug_sel & SSLE_LOG_DEBUG, "SSLE_LOG_DEBUG", a,b,c,d,e) + +#define SSLE_LOG_DATAH(a,b) \ + SLOGH (ssle_debug_sel & SSLE_LOG_DATA,a,b) + +/* 'C' macros stand for 'Continuation' */ +#define SSLE_LOG_CERR0(a) \ + SLOGC_0 (ssle_debug_sel & SSLE_LOG_ERR, a) +#define SSLE_LOG_CERR1(a,b) \ + SLOGC_1 (ssle_debug_sel & SSLE_LOG_ERR, a,b) +#define SSLE_LOG_CERR2(a,b,c) \ + SLOGC_2 (ssle_debug_sel & SSLE_LOG_ERR, a,b,c) +#define SSLE_LOG_CERR3(a,b,c,d) \ + SLOGC_3 (ssle_debug_sel & SSLE_LOG_ERR, a,b,c,d) +#define SSLE_LOG_CERR4(a,b,c,d,e) \ + SLOGC_4 (ssle_debug_sel & SSLE_LOG_ERR, a,b,c,d,e) + +#define SSLE_LOG_CNERR0(a) \ + SLOGC_0 (ssle_debug_sel & SSLE_LOG_NERR, a) +#define SSLE_LOG_CNERR1(a,b) \ + SLOGC_1 (ssle_debug_sel & SSLE_LOG_NERR, a,b) +#define SSLE_LOG_CNERR2(a,b,c) \ + SLOGC_2 (ssle_debug_sel & SSLE_LOG_NERR, a,b,c) +#define SSLE_LOG_CNERR3(a,b,c,d) \ + SLOGC_3 (ssle_debug_sel & SSLE_LOG_NERR, a,b,c,d) +#define SSLE_LOG_CNERR4(a,b,c,d,e) \ + SLOGC_4 (ssle_debug_sel & SSLE_LOG_NERR, a,b,c,d,e) + +#define SSLE_LOG_CFLOW0(a) \ + SLOGC_0 (ssle_debug_sel & SSLE_LOG_FLOW, a) +#define SSLE_LOG_CFLOW1(a,b) \ + SLOGC_1 (ssle_debug_sel & SSLE_LOG_FLOW, a,b) +#define SSLE_LOG_CFLOW2(a,b,c) \ + SLOGC_2 (ssle_debug_sel & SSLE_LOG_FLOW, a,b,c) +#define SSLE_LOG_CFLOW3(a,b,c,d) \ + SLOGC_3 (ssle_debug_sel & SSLE_LOG_FLOW, a,b,c,d) +#define SSLE_LOG_CFLOW4(a,b,c,d,e) \ + SLOGC_4 (ssle_debug_sel & SSLE_LOG_FLOW, a,b,c,d,e) + +#define SSLE_LOG_CDEBUG0(a) \ + SLOGC_0 (ssle_debug_sel & SSLE_LOG_DEBUG, a) +#define SSLE_LOG_CDEBUG1(a,b) \ + SLOGC_1 (ssle_debug_sel & SSLE_LOG_DEBUG, a,b) +#define SSLE_LOG_CDEBUG2(a,b,c) \ + SLOGC_2 (ssle_debug_sel & SSLE_LOG_DEBUG, a,b,c) +#define SSLE_LOG_CDEBUG3(a,b,c,d) \ + SLOGC_3 (ssle_debug_sel & SSLE_LOG_DEBUG, a,b,c,d) +#define SSLE_LOG_CDEBUG4(a,b,c,d,e) \ + SLOGC_4 (ssle_debug_sel & SSLE_LOG_DEBUG, a,b,c,d,e) + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* SSLE_LOG_INCLUDED */ +/************************************************************************/ diff --git a/include/inc/stdtime.h b/include/inc/stdtime.h new file mode 100644 index 0000000..5cb2504 --- /dev/null +++ b/include/inc/stdtime.h @@ -0,0 +1,1446 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtime.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Header file for Standard Time Management Library Functions */ +/* */ +/* Note: most functions a produce a return-code value STDTIME_RC. */ +/* the return code is zero if successful, otherwise it is a structured */ +/* value in which the low-order 10 bits enumerates an error reason, */ +/* and the upper 20 bits enumerates the high-level and low-level */ +/* functions where the error was detected. */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 04/08/08 JRB 15 Chg () to (ST_VOID) in several prototypes. */ +/* 03/13/08 JRB 14 Chg #error to #warning for STDTIME_UNICODE. */ +/* 02/28/08 JRB 13 Incl "timeb.h" only in "sysincs.h". */ +/* 02/20/08 JRB 12 Chg STDTIME same as FILETIME (simplifies a lot). */ +/* Delete MANY unused functions and definitions. */ +/* Simplify TimeTypeEx, StrucTmEx args. */ +/* 04/03/07 RLH 11 Additional conversion functions to/from FILETIME. */ +/* 03/18/07 RLH 10 Remove tabs from source code inadvertantly added. */ +/* 03/16/07 RLH 09 Normalize struct tm, SYSTEMTIME, and STDTIME_FIELDS */ +/* after rounding is applied; no rounding for formatting */ +/* functions. */ +/* 02/16/07 RLH 08 Clean up minor warnings under Linux */ +/* 01/10/07 RLH 07 Add TruncStdTimeString functions */ +/* 11/29/06 RLH 06 Correction to STDTIME_TIME_T64_ENABLED setting */ +/* 10/18/06 RLH 05 Enhanced capabilities for timezone rules */ +/* 10/27/06 RLH 04 Change STDTIME_RET, STDTIME_IF, STDTIME_IFNOT macros */ +/* 09/13/06 RLH 03 Ensure local time conversions work when TZ not set */ +/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */ +/* 01/18/06 RLH 01 Created */ +/*****************************************************************************/ + +#ifndef _STDTIME_H_7583ECB2_DB3F_48B3_8A97_2D1D2A38C84A_ +#define _STDTIME_H_7583ECB2_DB3F_48B3_8A97_2D1D2A38C84A_ + +#define SECONDS_FROM_1601_TO_1970_HIGH 2 +#define SECONDS_FROM_1601_TO_1970_LOW 0xB6109100 + +#define FILETIME_1970_HIGH 0x019DB1DE +#define FILETIME_1970_LOW 0xD53E8000 + +#undef STDTIME_MSVC6 +#undef STDTIME_MSVC7 +#undef STDTIME_MSVC8 + +#ifdef _MSC_VER + +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE +#endif + + +#if (_MSC_VER >= 1400) +#define STDTIME_MSVC8 +#elif (_MSC_VER >= 1300) +#define STDTIME_MSVC7 +#elif (_MSC_VER >= 1200) +#define STDTIME_MSVC6 +#endif + + +#if 0 + +#if (_MSC_VER >= 1400) +#pragma comment(lib, "stdtimelib.lib") +#elif (_MSC_VER >= 1300) +#pragma comment(lib, "stdtimelib.lib") +#elif (_MSC_VER >= 1200) +#pragma comment(lib, "stdtimelib.lib") +#endif + +#endif /* 0 */ + + +#endif /* _MSC_VER */ + +/* to test for STDTIME library being used */ +#undef STDTIME_DEFINED +#define STDTIME_DEFINED 1 + +/*****************************************************************************/ +/* LIBRARY HEADERS */ +/*****************************************************************************/ + +/* UNICODE or ANSI, but not both */ + +#if defined(STDTIME_UNICODE) && defined(STDTIME_ANSI) +#error Both STDTIME_UNICODE and STDTIME_ANSI defined +#undef STDTIME_UNICODE +#endif + +/* UNICODE or _UNICODE implies STDTIME_UNICODE, but not if ANSI defined */ + +#if (!defined(STDTIME_UNICODE)) && (!defined(STDTIME_ANSI)) +#if defined(UNICODE) || defined(_UNICODE) +#define STDTIME_UNICODE +#endif +#endif + +#if defined(STDTIME_UNICODE) +#pragma message("Warning: STDTIME_UNICODE option no longer supported. Try using ANSI functions mbstowcs and wcstombs.") +#undef STDTIME_UNICODE +#endif + +/* DEBUG: system include should come from "sysincs.h". Fix that later */ +#ifdef _WIN32 +#include +#endif + +#include +#include +#include +#include +#include +#include + +/*****************************************************************************/ +/* with support for gmtime_r and localtime_r if possible */ +/*****************************************************************************/ + +#undef STDTIME_REENTRANT_GMTIME_LOCALTIME + +#undef STDTIME_DEFINED_LINUX__USE_POSIX +#if defined(linux) +#define STDTIME_REENTRANT_GMTIME_LOCALTIME +#ifndef __USE_POSIX +#define __USE_POSIX +#define STDTIME_DEFINED_LINUX__USE_POSIX +#endif +#endif + +#undef STDTIME_DEFINED_SOLARIS_REENTRANT +#if defined(sun) +#define STDTIME_REENTRANT_GMTIME_LOCALTIME +#ifndef _REENTRANT +#define _REENTRANT +#define STDTIME_DEFINED_SOLARIS_REENTRANT +#endif +#endif + +#undef STDTIME_DEFINED_SOLARIS_POSIX_PTHREAD_SEMANTICS +#if defined(sun) +#ifndef _POSIX_PTHREAD_SEMANTICS +#define _POSIX_PTHREAD_SEMANTICS +#define STDTIME_DEFINED_SOLARIS_POSIX_PTHREAD_SEMANTICS +#endif +#endif + +#undef STDTIME_DEFINED_AIX_THREAD_SAFE +#if defined(_AIX) +#define STDTIME_REENTRANT_GMTIME_LOCALTIME +#ifndef _THREAD_SAFE +#define _THREAD_SAFE +#define STDTIME_DEFINED_AIX_THREAD_SAFE +#endif +#endif + +#undef STDTIME_DEFINED_DEC_UNIX_REENTRANT +#if defined(__alpha) && !defined(__VMS) +#define STDTIME_REENTRANT_GMTIME_LOCALTIME +#ifndef _REENTRANT +#define _REENTRANT +#define STDTIME_DEFINED_DEC_UNIX_REENTRANT +#endif +#endif + + +#include + + +#if defined(sun) +struct tm * gmtime_r (const time_t * pTimeT, struct tm * pStructTm); +struct tm * localtime_r (const time_t * pTimeT, struct tm * pStructTm); +#endif + + +/* clean up macro namespace */ + +#ifdef STDTIME_DEFINED_LINUX__USE_POSIX +#undef STDTIME_DEFINED_LINUX__USE_POSIX +#undef __USE_POSIX +#endif + +#ifdef STDTIME_DEFINED_SOLARIS_REENTRANT +#undef STDTIME_DEFINED_SOLARIS_REENTRANT +#undef _REENTRANT +#endif + +#ifdef STDTIME_DEFINED_SOLARIS_POSIX_PTHREAD_SEMANTICS +#undef STDTIME_DEFINED_SOLARIS_POSIX_PTHREAD_SEMANTICS +#undef _POSIX_PTHREAD_SEMANTICS +#endif + +#ifdef STDTIME_DEFINED_DEC_UNIX_REENTRANT +#undef STDTIME_DEFINED_DEC_UNIX_REENTRANT +#undef _REENTRANT +#endif + +#ifdef STDTIME_DEFINED_AIX_THREAD_SAFE +#undef STDTIME_DEFINED_AIX_THREAD_SAFE +#undef _THREAD_SAFE +#endif + + +/*****************************************************************************/ +/* support _T notation on non-Windows platforms */ +/*****************************************************************************/ + +#if (!defined(_T)) && (!defined(__T)) +#ifdef STDTIME_UNICODE +#define __T(x) L##x +#define _T(x) __T(x) +#else +#define __T(x) x +#define _T(x) x +#endif +#endif /* not defined _T and __T */ + +#include "stdtime_config.h" + + +/*****************************************************************************/ +/* determine if "stdtime_timezone_csv.h" file is "merged" or not. */ +/* */ +/* the csv file gets "merged" if there is no comma separating one line */ +/* from the next. a "merged" file is the normal format for a csv data */ +/* file, but when used as part of a C program, the lack of a comma causes */ +/* the last string value on one line to get concatenated by the compiler */ +/* to the first string value on the next line. we need to know if the */ +/* file is "merged" or "unmerged" to know how to 'undo' the merging. */ +/* */ +/* an unmerged file is easier and faster to process, while a merged file */ +/* maintains source compatibility with the original Boost.org timezone */ +/* database file from which it originated. */ +/* */ +/*****************************************************************************/ + +#if defined(STDTIME_MERGED_CSV) && defined(STDTIME_UNMERGED_CSV) +#error Both STDTIME_MERGED_CSV and STDTIME_UNMERGED_CSV defined +#undef STDTIME_UNMERGED_CSV +#endif + +#if !defined(STDTIME_MERGED_CSV) && !defined(STDTIME_UNMERGED_CSV) +#define STDTIME_MERGED_CSV /* default */ +#endif + + +/*****************************************************************************/ +/* determine how GMT is converted to local time, and vice-versa. */ +/* */ +/* using a system API for a definition of what "local" is will be faster, */ +/* but if the SYSTEMTIMEZONE or TZ environment variable does not agree */ +/* with the OS's understanding of what "local" is, there will be a */ +/* conflict. if the time library is likely to be used for a non-local */ +/* time zone, defining STDTIME_LOCAL_USES_TZDB is necessary. */ +/* otherwise, define STDTIME_LOCAL_USES_SYSAPI for speed. */ +/* */ +/*****************************************************************************/ + +#if defined(STDTIME_LOCAL_USES_TZDB) && defined(STDTIME_LOCAL_USES_SYSAPI) +#error Both STDTIME_LOCAL_USES_TZDB and STDTIME_LOCAL_USES_SYSAPI defined +#undef STDTIME_LOCAL_USES_SYSAPI +#endif + +#if !defined(STDTIME_LOCAL_USES_TZDB) && !defined(STDTIME_LOCAL_USES_SYSAPI) +#define STDTIME_LOCAL_USES_SYSAPI /* default */ +#endif + + +/*****************************************************************************/ +/* C++ ONLY ENABLED OR DISABLED */ +/* */ +/* use StdTimeConfig.h to set STDTIME_CPP_ONLY_ENABLED/DISABLED */ +/*****************************************************************************/ + + +#ifdef __cplusplus + +#if defined(STDTIME_CPP_ONLY_ENABLED) && defined(STDTIME_CPP_ONLY_DISABLED) +#error Both STDTIME_CPP_ONLY_ENABLED and STDTIME_CPP_ONLY_DISABLED defined +#undef STDTIME_CPP_ONLY_ENABLED +#endif + +#if !defined(STDTIME_CPP_ONLY_ENABLED) && !defined(STDTIME_CPP_ONLY_DISABLED) +#define STDTIME_CPP_ONLY_ENABLED /* default */ +#endif + +#else /* not __cplusplus */ + +#undef STDTIME_CPP_ONLY_ENABLED +#undef STDTIME_CPP_ONLY_DISABLED +#define STDTIME_CPP_ONLY_DISABLED + +#endif /* __cplusplus */ + + +/* StdTimeW32.h needs the bool definition */ + + +#define STDTIME_BOOL int +#define STDTIME_TRUE 1 +#define STDTIME_FALSE 0 + +typedef int32_t STDTIME_RC; + +/* STDTIME return codes are divided as follows: */ +/* 2 bits unused */ +/* 10 bits = highest level function where error detected */ +/* 10 bits = lowest level function where error detected */ +/* 10 bits = error reason code (nature of problem) */ + + +/* create error code enumeration from enum_stdtime_func.h */ +/* this is done by temporary macro and include file */ + +#define STDTIME_ENUM_FUNC(x) STDTIME_FUNC__##x, + +enum + { + STDTIME_FUNC__0000, /* dummy 0 entry */ +#include "stdtime_enum_func.h" + STDTIME_FUNC__SIZE + }; + +/* temporary macro has served its purpose, so undefine it */ +#undef STDTIME_ENUM_FUNC + + +/* now redefine macro for main purpose, to declare 'rc' and 'func' */ +/* within each function that returns a STDTIME_RC return code. */ + + +#define STDTIME_ENUM_FUNC(x) \ + STDTIME_RC rc; \ + STDTIME_RC func; \ + rc = -1; \ + func = (STDTIME_RC) STDTIME_FUNC__##x; + + +/* create error code enumeration from enum_stdtime_err.h */ +/* this is done by temporary macro and include file */ + +#define STDTIME_ENUM_ERR(x) STDTIME_ERR__##x, + +enum + { + STDTIME_ERR__0000, /* dummy 0 entry */ +#include "stdtime_enum_err.h" + STDTIME_ERR__SIZE + }; + +/* temporary macro has served its purpose, so undefine it */ +#undef STDTIME_ENUM_ERR + + +#define STDTIME_10_BITS 0x3FF +#define STDTIME_20_BITS 0xFFFFF + +#define STDTIME_OK 0 +#define STDTIME_RET(x) return StdTimeRet (func, x) + +#define STDTIME_RET_RC STDTIME_RET(rc) +#define STDTIME_RET_OK return STDTIME_OK + +#define STDTIME_EC(x) ((func << 10) | (STDTIME_ERR__##x)) + +#define STDTIME_RET_EC(x) STDTIME_RET(STDTIME_EC(x)) + +#include "stdtime_quadlib.h" +#include "stdtime_w32.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*****************************************************************************/ +/* TYPES AND STRUCTURES */ +/*****************************************************************************/ + + +#if defined(_MSC_VER) && defined(_WCHAR_T_DEFINED) +typedef wchar_t STDTIME_WCHAR; +#elif defined(sun) && defined(_WCHAR_T) +typedef wchar_t STDTIME_WCHAR; +#else +typedef unsigned short STDTIME_WCHAR; +#endif + +#ifndef STDTIME_TIME_T64_WIN +#if defined(_TIME_T_DEFINED) && defined(_WIN64) +#define STDTIME_TIME_T64_WIN +#endif +#endif + +#ifndef STDTIME_TIME_T64_WIN +#ifdef _TIME64_T_DEFINED +#define STDTIME_TIME_T64_WIN +#endif +#endif + + +#ifndef STDTIME_TIME_T64_ENABLED +#ifdef STDTIME_TIME_T64_WIN +#define STDTIME_TIME_T64_ENABLED +#endif +#endif + + +#ifdef STDTIME_TIME_T64_ENABLED +#ifdef STDTIME_TIME_T64_WIN + +#ifdef _TIME64_T_DEFINED +typedef __time64_t STDTIME_WIN_TIME_T; +#else +typedef time_t STDTIME_WIN_TIME_T; +#endif /* _TIME64_T_DEFINED */ + +#else /* not STDTIME_TIME_T64_WIN */ +typedef QUADLIB_I64N STDTIME_WIN_TIME_T; +#endif /* STDTIME_TIME_T64_WIN */ + + + + +#else /* not STDTIME_TIME_T64_ENABLED */ +typedef time_t STDTIME_WIN_TIME_T; +#endif /* STDTIME_TIME_T64_ENABLED */ + + +#define STDTIME_SCALE_NSEC 100 /* only 1 digit of nsec precision */ +#define STDTIME_PREC_NSEC 10 /* only 1 digit of nsec precision */ + +#define STDTIME_WIN_EPOCH_YEAR 1601 +#define STDTIME_UNIX_EPOCH_YEAR 1970 +#define STDTIME_DST_CUTOFF_YEAR 1945 + +#define STDTIME_YEAR_MIN STDTIME_WIN_EPOCH_YEAR /* base/epoch year */ +#define STDTIME_YEAR_MAX 9999 /* to avoid overflow in STDTIME_STRING */ + +#define STDTIME_INVALID {0,0} +#define STDTIME_FIELDS_INVALID {0,0,0,0,0,0,0,0,0} +#define STDTIME_STRING_INVALID {0} + +#define STDTIME_SPAN_INVALID QUADLIB_I64_MAX + +#define STDTIME_DELTA_DAY_MAX (8400*366) + + +#define STDTIME_DELTA_INVALID { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, \ + 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF } /**/ + + +/* an invalid span exceeds +/- 2,656,281,600,000,000,000 */ +/* which is 8400*366 days in terms of 100-nanosecond intervals */ +/* the pos value in hex is 24DD 020A A768 0000 */ +/* the neg value in hex is DB22 FDF5 5898 0000 */ + +#define STDTIME_SPAN_MAX_HI 0x24DD020A +#define STDTIME_SPAN_MAX_LO 0xA7680000 + +#define STDTIME_SPAN_MIN_HI 0xDB22FDF5 +#define STDTIME_SPAN_MIN_LO 0x58980000 + +#define STDTIME_ERR (-2) +#define STDTIME_LT (-1) +#define STDTIME_EQ 0 +#define STDTIME_GT 1 + +/* Main StdTime structure identical to Windows FILETIME. */ +typedef STDTIME_WIN_FILETIME STDTIME; + +typedef struct + { + int32_t year; + int32_t mon; + int32_t day; + int32_t hour; + int32_t min; + int32_t sec; + int32_t msec; /* milliseconds */ + int32_t usec; /* microseconds */ + int32_t nsec; /* nanoseconds */ + } +STDTIME_FIELDS; + + +typedef struct + { + int32_t day; + int32_t hour; + int32_t min; + int32_t sec; + int32_t msec; + int32_t usec; + int32_t nsec; + } +STDTIME_DELTA; + + +typedef struct + { + QUADLIB_I64 value; + } +STDTIME_SPAN; + + +/* 1 2 3 */ +/* 0123456789012345678901234567890123456 */ +/* STRING format: yyyy-mm-ddThh:mi:ss.fffffff# */ +/* TZO format: +hh:mm:ss# */ +/* 0123456789 */ + +#define STDTIME_STRING_DATE_LEN 10 +#define STDTIME_STRING_TIME_LEN 8 +#define STDTIME_STRING_FRAC_LEN 7 + +#define STDTIME_STRING_DATE_POS 0 +#define STDTIME_STRING_TIME_POS 11 +#define STDTIME_STRING_FRAC_POS 20 + +#define STDTIME_STRING_DLM_D1 4 +#define STDTIME_STRING_DLM_D2 7 +#define STDTIME_STRING_DLM_S1 10 +#define STDTIME_STRING_DLM_T1 13 +#define STDTIME_STRING_DLM_T2 16 +#define STDTIME_STRING_DLM_F1 19 + +#define STDTIME_STRING_LEN 27 +#define STDTIME_TZO_LEN 9 +#define STDTIME_STRING_MAXLEN (STDTIME_STRING_LEN+STDTIME_TZO_LEN) + + +typedef struct + { + char str [STDTIME_TZO_LEN + 1]; + } +STDTIME_TZOA; + +/* embTzo represents an 'embedded' timezone offset, a suffix to the time */ +/* string 'str' in STDTIME_STRINGA and STDTIME_STRINGW. */ +/* embTzo may be a null string, the letter Z or an offset like -05:00 */ + +/* extTzo represents an 'external' timezone offset, created as an output */ +/* value by the STDTIME library. the library creates, but does not */ +/* directly use, the extTzo field. */ + +typedef struct + { + char str [STDTIME_STRING_LEN]; + char embTzo [STDTIME_TZO_LEN + 1]; + STDTIME_TZOA extTzo; /* external TimeZone Offset */ + } +STDTIME_STRINGA; + +#ifdef STDTIME_UNICODE +#else +#define STDTIME_STRING STDTIME_STRINGA +#define STDTIME_TZO STDTIME_TZOA +#endif /* STDTIME_UNICODE */ + +typedef struct + { + STDTIME_WIN_TIME_T t; + } +STDTIME_TIMETYPE; + +#define STDTIME_API_MKTIME mktime + +/* Round/Trunc field selectors */ + +#define STDTIME_FIELD_DAY 0 +#define STDTIME_FIELD_HOUR 1 +#define STDTIME_FIELD_MIN 2 +#define STDTIME_FIELD_SEC 3 +#define STDTIME_FIELD_MSEC 4 +#define STDTIME_FIELD_USEC 5 +#define STDTIME_FIELD_NSEC 6 + + +#define STDTIME_ERRCODE_LEN 27 + +/* an error code has the form 0xNNNNNNNN = HHHH.LLLL.RRRR# */ +/* 0123456789012345678901234567 */ +/* this holds a raw hex RC value, and the RC as subfields */ + +#define STDTIME_ERRMSG_LEN 80 + +typedef struct + { + char errcode [STDTIME_ERRCODE_LEN+1]; + char hilevel [STDTIME_ERRMSG_LEN+1]; + char lolevel [STDTIME_ERRMSG_LEN+1]; + char reason [STDTIME_ERRMSG_LEN+1]; + } +STDTIME_ERRMSGA; + +#define STDTIME_IF(x) ((rc=(x)) == STDTIME_OK) +#define STDTIME_IFNOT(x) ((rc=(x)) != STDTIME_OK) + + +/*** helper function to assemble a STDTIME return code ***********************/ + +STDTIME_RC StdTimeRet ( + const STDTIME_RC /*I*/ func, + const STDTIME_RC /*I*/ ec); + + +/*** StdTime/StdTimeFields conversions ***************************************/ + + +STDTIME_RC StdTimeToStdTimeFields ( + const STDTIME * /*I*/ pStdTime, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + +STDTIME_RC StdTimeFieldsToStdTime ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME * /*O*/ pStdTime); + + +/*** StdTime/external conversions ********************************************/ + + +STDTIME_RC StdTimeToStdTimeStringA ( + const STDTIME * /*I*/ pStdTime, + STDTIME_STRINGA * /*O*/ pStdTimeString); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeToStdTimeString StdTimeToStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** external/StdTime conversions ********************************************/ + + +STDTIME_RC StdTimeStringAToStdTime ( + const STDTIME_STRINGA * /*I*/ pStdTimeString, + STDTIME * /*O*/ pStdTime); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeStringToStdTime StdTimeStringAToStdTime +#endif /* STDTIME_UNICODE */ + + +/*** StdTimeFields/external conversions **************************************/ + + +STDTIME_RC StdTimeFieldsToStdTimeStringA ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_STRINGA * /*O*/ pStdTimeString); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeFieldsToStdTimeString StdTimeFieldsToStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** external/StdTimeFields conversions **************************************/ + + +STDTIME_RC StdTimeStringAToStdTimeFields ( + const STDTIME_STRINGA * /*I*/ pStdTimeString, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeStringToStdTimeFields StdTimeStringAToStdTimeFields +#endif /* STDTIME_UNICODE */ + +/*** StdTime to/from Local ***************************************************/ + + +STDTIME_RC StdTimeToLocalStdTime ( + const STDTIME * /*I*/ pStdTime, + STDTIME * /*O*/ pStdTimeLocal); + +STDTIME_RC LocalStdTimeToStdTime ( + const STDTIME * /*I*/ pStdTimeLocal, + STDTIME * /*O*/ pStdTime); + + +/*** StdTimeFields to/from Local *********************************************/ + + +STDTIME_RC StdTimeFieldsToLocalStdTimeFields ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_FIELDS * /*O*/ pStdTimeFieldsLocal); + +STDTIME_RC LocalStdTimeFieldsToStdTimeFields ( + const STDTIME_FIELDS * /*I*/ pStdTimeFieldsLocal, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + + +/*** StdTimeString to/from Local *********************************************/ + + +STDTIME_RC StdTimeStringAToLocalStdTimeStringA ( + const STDTIME_STRINGA * /*I*/ pStdStdTimeString, + STDTIME_STRINGA * /*O*/ pLocStdTimeString); + +STDTIME_RC LocalStdTimeStringAToStdTimeStringA ( + const STDTIME_STRINGA * /*I*/ pLocStdTimeString, + STDTIME_STRINGA * /*O*/ pStdStdTimeString); + +#define StdTimeStringToLocalStdTimeStringA StdTimeStringAToLocalStdTimeStringA +#define LocalStdTimeStringToStdTimeStringA LocalStdTimeStringAToStdTimeStringA + + +#ifdef STDTIME_UNICODE +#else +#define StdTimeStringToLocalStdTimeString StdTimeStringAToLocalStdTimeStringA +#define LocalStdTimeStringToStdTimeString LocalStdTimeStringAToStdTimeStringA +#endif /* STDTIME_UNICODE */ + +/*** Get (current UTC/GMT time) functions ************************************/ + + +STDTIME_RC GetStdTime ( + STDTIME * /*O*/ pStdTime); + +STDTIME_RC GetStdTimeFields ( + STDTIME_FIELDS * /*O*/ pStdTimeFields); + +STDTIME_RC GetStdTimeStringA ( + STDTIME_STRINGA * /*O*/ pStdTimeString); + +#ifdef STDTIME_UNICODE +#else +#define GetStdTimeString GetStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** GetLocal (current time) functions ***************************************/ + + +STDTIME_RC GetLocalStdTime ( + STDTIME * /*O*/ pStdTime); + +STDTIME_RC GetLocalStdTimeFields ( + STDTIME_FIELDS * /*O*/ pStdTimeFields); + +STDTIME_RC GetLocalStdTimeStringA ( + STDTIME_STRINGA * /*O*/ pStdTimeString); + +#ifdef STDTIME_UNICODE +#else +#define GetLocalStdTimeString GetLocalStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** validation functions ****************************************************/ + + +STDTIME_RC ValidStdTime ( + const STDTIME * /*I*/ pStdTime); + +STDTIME_RC ValidStdTimeFields ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields); + +STDTIME_RC ValidStdTimeStringA ( + const STDTIME_STRINGA * /*I*/ pStdTimeString); + +STDTIME_RC ValidStdTimeDelta ( + const STDTIME_DELTA * /*I*/ pDelta); + +STDTIME_RC ValidStdTimeSpan ( + const STDTIME_SPAN * /*I*/ pSpan); + + +#ifdef STDTIME_UNICODE +#else +#define ValidStdTimeString ValidStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** Format functions ********************************************************/ + + +STDTIME_RC FormatStdTimeA ( + char * /*O*/ pTarget, + size_t /*I*/ nMaxsize, + const char * /*I*/ pFormat, + const STDTIME * /*I*/ pStdTime); + +STDTIME_RC FormatStdTimeFieldsA ( + char * /*O*/ pTarget, + size_t /*I*/ nMaxsize, + const char * /*I*/ pFormat, + const STDTIME_FIELDS * /*I*/ pStdTimeFields); + +STDTIME_RC FormatStdTimeStringA ( + char * /*O*/ pTarget, + size_t /*I*/ nMaxsize, + const char * /*I*/ pFormat, + const STDTIME_STRINGA * /*I*/ pStdTimeString); + +STDTIME_RC TrimStdTimeStringA ( + STDTIME_STRINGA * /*IO*/ pStdTimeString, + int32_t /*I*/ nSize); + +STDTIME_RC TruncStdTimeStringA ( + STDTIME_STRINGA * /*IO*/ pStdTimeString, + int32_t /*I*/ nSize); + +#ifdef STDTIME_UNICODE +#else +#define FormatStdTime FormatStdTimeA +#define FormatStdTimeFields FormatStdTimeFieldsA +#define FormatStdTimeString FormatStdTimeStringA + +#define TrimStdTimeString TrimStdTimeStringA +#define TruncStdTimeString TruncStdTimeStringA + +#endif /* STDTIME_UNICODE */ + + +/*** delimiter functions *****************************************************/ + + +STDTIME_RC SetStdTimeStringDelimitersA ( + const char * /*I*/ pDelimiters); + +STDTIME_RC RepairStdTimeStringA ( + STDTIME_STRINGA * /*O*/ pStdTimeString); + +STDTIME_RC DelimitStdTimeStringA ( + STDTIME_STRINGA * /*O*/ pStdTimeString, + const char * /*I*/ pDelim); + +#ifdef STDTIME_UNICODE +#else +#define SetStdTimeStringDelimiters SetStdTimeStringDelimitersA +#define RepairStdTimeString RepairStdTimeStringA +#define DelimitStdTimeString DelimitStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** AddFraction adjustment function *****************************************/ + + +STDTIME_RC StdTimeFields_AddFraction ( + STDTIME_FIELDS * /*IO*/ pStdTimeFields, + int32_t /*I*/ nMsec, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec); + + +/*** AddSpan functions *******************************************************/ + + +STDTIME_RC StdTime_AddSpan ( + STDTIME * /*IO*/ pStdTime, + const STDTIME_SPAN * /*I*/ pSpan); + +STDTIME_RC StdTimeFields_AddSpan ( + STDTIME_FIELDS * /*IO*/ pStdTimeFields, + const STDTIME_SPAN * /*I*/ pSpan); + +STDTIME_RC StdTimeStringA_AddSpan ( + STDTIME_STRINGA * /*IO*/ pStdTimeString, + const STDTIME_SPAN * /*I*/ pSpan); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeString_AddSpan StdTimeStringA_AddSpan +#endif /* STDTIME_UNICODE */ + + +/*** SubSpan functions *******************************************************/ + + +STDTIME_RC StdTime_SubSpan ( + STDTIME * /*IO*/ pStdTime, + const STDTIME_SPAN * /*I*/ pSpan); + +STDTIME_RC StdTimeFields_SubSpan ( + STDTIME_FIELDS * /*IO*/ pStdTimeFields, + const STDTIME_SPAN * /*I*/ pSpan); + +STDTIME_RC StdTimeStringA_SubSpan ( + STDTIME_STRINGA * /*IO*/ pStdTimeString, + const STDTIME_SPAN * /*I*/ pSpan); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeString_SubSpan StdTimeStringA_SubSpan +#endif /* STDTIME_UNICODE */ + + +/*** GetSpan functions *******************************************************/ + + +STDTIME_RC StdTime_GetSpan ( + const STDTIME * /*I*/ pStdTimeOne, + const STDTIME * /*I*/ pStdTimeTwo, + STDTIME_SPAN * /*O*/ pSpan); + +STDTIME_RC StdTimeFields_GetSpan ( + const STDTIME_FIELDS * /*I*/ pStdTimeFieldsOne, + const STDTIME_FIELDS * /*I*/ pStdTimeFieldsTwo, + STDTIME_SPAN * /*O*/ pSpan); + +STDTIME_RC StdTimeStringA_GetSpan ( + const STDTIME_STRINGA * /*I*/ pStdTimeStringOne, + const STDTIME_STRINGA * /*I*/ pStdTimeStringTwo, + STDTIME_SPAN * /*O*/ pSpan); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeString_GetSpan StdTimeStringA_GetSpan +#endif /* STDTIME_UNICODE */ + + +/*** AddDelta functions ******************************************************/ + +STDTIME_RC StdTime_AddDelta ( + STDTIME * /*IO*/ pStdTime, + const STDTIME_DELTA * /*I*/ pDelta); + +STDTIME_RC StdTimeFields_AddDelta ( + STDTIME_FIELDS * /*IO*/ pStdTimeFields, + const STDTIME_DELTA * /*I*/ pDelta); + +STDTIME_RC StdTimeStringA_AddDelta ( + STDTIME_STRINGA * /*IO*/ pStdTimeString, + const STDTIME_DELTA * /*I*/ pDelta); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeString_AddDelta StdTimeStringA_AddDelta +#endif /* STDTIME_UNICODE */ + + +/*** SubDelta functions ******************************************************/ + + +STDTIME_RC StdTime_SubDelta ( + STDTIME * /*IO*/ pStdTime, + const STDTIME_DELTA * /*I*/ pDelta); + +STDTIME_RC StdTimeFields_SubDelta ( + STDTIME_FIELDS * /*IO*/ pStdTimeFields, + const STDTIME_DELTA * /*I*/ pDelta); + +STDTIME_RC StdTimeStringA_SubDelta ( + STDTIME_STRINGA * /*IO*/ pStdTimeString, + const STDTIME_DELTA * /*I*/ pDelta); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeString_SubDelta StdTimeStringA_SubDelta +#endif /* STDTIME_UNICODE */ + + +/*** GetDelta functions ******************************************************/ + + +STDTIME_RC StdTime_GetDelta ( + const STDTIME * /*I*/ pStdTimeOne, + const STDTIME * /*I*/ pStdTimeTwo, + STDTIME_DELTA * /*O*/ pDelta); + +STDTIME_RC StdTimeFields_GetDelta ( + const STDTIME_FIELDS * /*I*/ pStdTimeFieldsOne, + const STDTIME_FIELDS * /*I*/ pStdTimeFieldsTwo, + STDTIME_DELTA * /*O*/ pDelta); + +STDTIME_RC StdTimeStringA_GetDelta ( + const STDTIME_STRINGA * /*I*/ pStdTimeStringOne, + const STDTIME_STRINGA * /*I*/ pStdTimeStringTwo, + STDTIME_DELTA * /*O*/ pDelta); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeString_GetDelta StdTimeStringA_GetDelta +#endif /* STDTIME_UNICODE */ + + +/*** Delta/Span conversion functions *****************************************/ + + +STDTIME_RC StdTimeDeltaToStdTimeSpan ( + const STDTIME_DELTA * /*I*/ pDelta, + STDTIME_SPAN * /*O*/ pSpan); + +STDTIME_RC StdTimeSpanToStdTimeDelta ( + const STDTIME_SPAN * /*I*/ pSpan, + STDTIME_DELTA * /*O*/ pDelta); + + +/*** Delta/Span sign-related functions ***************************************/ + + +int32_t SgnStdTimeDelta ( + const STDTIME_DELTA * /*I*/ pDelta); + +STDTIME_RC AbsStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta); + +STDTIME_RC NegStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta); + + +int32_t SgnStdTimeSpan ( + const STDTIME_SPAN * /*I*/ pSpan); + +STDTIME_RC AbsStdTimeSpan ( + STDTIME_SPAN * /*IO*/ pSpan); + +STDTIME_RC NegStdTimeSpan ( + STDTIME_SPAN * /*IO*/ pSpan); + + +/*** Compare functions *******************************************************/ + + +int32_t CompareStdTime ( + const STDTIME * /*I*/ pStdTimeOne, + const STDTIME * /*I*/ pStdTimeTwo); + +int32_t CompareStdTimeFields ( + const STDTIME_FIELDS * /*I*/ pStdTimeFieldsOne, + const STDTIME_FIELDS * /*I*/ pStdTimeFieldsTwo); + +int32_t CompareStdTimeStringA ( + const STDTIME_STRINGA * /*I*/ pStdTimeStringOne, + const STDTIME_STRINGA * /*I*/ pStdTimeStringTwo); + +#ifdef STDTIME_UNICODE +#else +#define CompareStdTimeString CompareStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** FileTime functions ******************************************************/ + + + +STDTIME_RC StdTimeToFileTime ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_FILETIME * /*O*/ pFileTime); + +STDTIME_RC FileTimeToStdTime ( + const STDTIME_WIN_FILETIME * /*I*/ pFileTime, + STDTIME * /*O*/ pStdTime); + + + +STDTIME_RC StdTimeFieldsToFileTime ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_FILETIME * /*O*/ pFileTime); + +STDTIME_RC FileTimeToStdTimeFields ( + const STDTIME_WIN_FILETIME * /*I*/ pFileTime, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + + + +STDTIME_RC StdTimeStringAToFileTime ( + const STDTIME_STRINGA * /*I*/ pStdTimeString, + STDTIME_WIN_FILETIME * /*O*/ pFileTime); + +STDTIME_RC FileTimeToStdTimeStringA ( + const STDTIME_WIN_FILETIME * /*I*/ pFileTime, + STDTIME_STRINGA * /*O*/ pStdTimeString); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeStringToFileTime StdTimeStringAToFileTime +#define FileTimeToStdTimeString FileTimeToStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** SystemTimeEx functions **************************************************/ + + +STDTIME_RC StdTimeToSystemTimeEx ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime, + int32_t * /*O*/ pUsec, /* optional */ + int32_t * /*O*/ pNsec); /* optional */ + + +STDTIME_RC SystemTimeExToStdTime ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec, + STDTIME * /*O*/ pStdTime); + + +STDTIME_RC StdTimeFieldsToSystemTimeEx ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime, + int32_t * /*O*/ pUsec, /* optional */ + int32_t * /*O*/ pNsec); /* optional */ + + +STDTIME_RC SystemTimeExToStdTimeFields ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + + +/*** SystemTime functions ****************************************************/ + + +STDTIME_RC StdTimeToSystemTime ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime); + + +STDTIME_RC SystemTimeToStdTime ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + STDTIME * /*O*/ pStdTime); + + +STDTIME_RC StdTimeFieldsToSystemTime ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime); + + +STDTIME_RC SystemTimeToStdTimeFields ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + +#ifdef _WIN32 /* DbTimeStamp functions only for _WIN32 */ +/*** DbTimeStamp functions ***************************************************/ + +/* NOTE: can't include "oledb.h" for DBTIMESTAMP so just define our own struct here.*/ +typedef struct + { + STDTIME_WIN_SHORT year; + STDTIME_WIN_USHORT month; + STDTIME_WIN_USHORT day; + STDTIME_WIN_USHORT hour; + STDTIME_WIN_USHORT minute; + STDTIME_WIN_USHORT second; + STDTIME_WIN_ULONG fraction; + } STDTIME_WIN_DBTIMESTAMP; + +STDTIME_WIN_DBTIMESTAMP StdTimeApiZeroDbTimeStamp (ST_VOID); + +STDTIME_RC StdTimeToDbTimeStamp ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_DBTIMESTAMP * /*O*/ pDbTimeStamp); + +STDTIME_RC DbTimeStampToStdTime ( + const STDTIME_WIN_DBTIMESTAMP * /*I*/ pDbTimeStamp, + STDTIME * /*O*/ pStdTime); + +STDTIME_RC StdTimeFieldsToDbTimeStamp ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_DBTIMESTAMP * /*O*/ pDbTimeStamp); + +STDTIME_RC DbTimeStampToStdTimeFields ( + const STDTIME_WIN_DBTIMESTAMP * /*I*/ pDbTimeStamp, + STDTIME_FIELDS * /*O*/ pStdTimeFields); +#endif /* DbTimeStamp functions only for _WIN32 */ + + +/*** StructTmEx functions ****************************************************/ + + +STDTIME_RC StdTimeToStructTmEx ( + const STDTIME * /*I*/ pStdTime, + struct tm * /*O*/ pStructTm, + int32_t * /*O*/ pNsec); /* optional */ + +STDTIME_RC StructTmExToStdTime ( + const struct tm * /*I*/ pStructTm, + int32_t /*I*/ nNsec, + STDTIME * /*O*/ pStdTime); + +/*** TimeTypeEx functions ****************************************************/ + + +STDTIME_RC StdTimeToTimeTypeEx ( + const STDTIME * /*I*/ pStdTime, + time_t * /*O*/ pTimeT, + int32_t * /*O*/ pNsec); /* optional */ + +STDTIME_RC TimeTypeExToStdTime ( + time_t /*I*/ timet, + int32_t /*I*/ nsec, + STDTIME * /*O*/ pStdTime); + +/*** Constructor-like functions **********************************************/ + + +STDTIME_FIELDS StdTimeFields ( + int32_t /*I*/ year, + int32_t /*I*/ mon, + int32_t /*I*/ day, + int32_t /*I*/ hour, + int32_t /*I*/ min, + int32_t /*I*/ sec, + int32_t /*I*/ msec, + int32_t /*I*/ usec, + int32_t /*I*/ nsec); + + +STDTIME_STRINGA StdTimeStringA ( + const char * /*I*/ str); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeString StdTimeStringA +#endif /* STDTIME_UNICODE */ + + +STDTIME_DELTA StdTimeDelta ( + int32_t /*I*/ day, + int32_t /*I*/ hour, + int32_t /*I*/ min, + int32_t /*I*/ sec, + int32_t /*I*/ msec, + int32_t /*I*/ usec, + int32_t /*I*/ nsec); + + +STDTIME_SPAN StdTimeSpan ( + QUADLIB_I64 /*I*/ value); + + +/*** Initializer functions ***************************************************/ + + +STDTIME ZeroStdTime (ST_VOID); +STDTIME_FIELDS ZeroStdTimeFields (ST_VOID); +STDTIME_DELTA ZeroStdTimeDelta (ST_VOID); +STDTIME_SPAN ZeroStdTimeSpan (ST_VOID); + +STDTIME_STRINGA ZeroStdTimeStringA (ST_VOID); + +STDTIME_TZOA ZeroStdTimeTzoA (ST_VOID); + +STDTIME_ERRMSGA ZeroStdTimeErrMsgA (ST_VOID); + +#ifdef STDTIME_UNICODE +#else +#define ZeroStdTimeString ZeroStdTimeStringA +#define ZeroStdTimeTzo ZeroStdTimeTzoA +#define ZeroStdTimeErrMsg ZeroStdTimeErrMsgA +#endif /* STDTIME_UNICODE */ + +/* initializers for outside types use 'StdTimeApi' prefix */ + +STDTIME_TIMETYPE StdTimeApiZeroTimeType (ST_VOID); +STDTIME_WIN_FILETIME StdTimeApiZeroFileTime (ST_VOID); +STDTIME_WIN_SYSTEMTIME StdTimeApiZeroSystemTime (ST_VOID); +struct tm StdTimeApiZeroStructTm (ST_VOID); + + +/*****************************************************************************/ +/* NORMALIZE, ROUND, TRUNC */ +/*****************************************************************************/ + + +STDTIME_RC NormalizeStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta); + + +STDTIME_RC TruncStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta, + int32_t /*I*/ field); + + +STDTIME_RC RoundStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta, + int32_t /*I*/ field); + + +/*** convenience calendar functions ******************************************/ + + +STDTIME_RC StdTimeGetDayofWeekAndYear ( + int32_t /*I*/ nYear, + int32_t /*I*/ nMon, + int32_t /*I*/ nDayofMon, + int32_t * /*O*/ pDayofWeek, + int32_t * /*O*/ pDayofYear); + + +int32_t StdTimeYearIsLeap ( + int32_t /*I*/ year); + + +int32_t StdTimeDaysInYearMon ( + int32_t /*I*/ year, + int32_t /*I*/ mon); + + +/*** DateEx functions ********************************************************/ + + +STDTIME_RC StdTimeToDateEx ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_DATE * /*O*/ pDate, + int32_t * /*O*/ pMsec, /* optional */ + int32_t * /*O*/ pUsec, /* optional */ + int32_t * /*O*/ pNsec); /* optional */ + + +STDTIME_RC DateExToStdTime ( + const STDTIME_WIN_DATE * /*I*/ pDate, + int32_t /*I*/ nMsec, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec, + STDTIME * /*O*/ pStdTime); + + +STDTIME_RC StdTimeFieldsToDateEx ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_DATE * /*O*/ pDate, + int32_t * /*O*/ pMsec, /* optional */ + int32_t * /*O*/ pUsec, /* optional */ + int32_t * /*O*/ pNsec); /* optional */ + + +STDTIME_RC DateExToStdTimeFields ( + const STDTIME_WIN_DATE * /*I*/ pDate, + int32_t /*I*/ nMsec, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + + +/*** Date functions ***************************************************/ + + +STDTIME_RC StdTimeToDate ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_DATE * /*O*/ pDate); + + +STDTIME_RC DateToStdTime ( + const STDTIME_WIN_DATE * /*I*/ pDate, + STDTIME * /*O*/ pStdTime); + + +STDTIME_RC StdTimeFieldsToDate ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_DATE * /*O*/ pDate); + + +STDTIME_RC DateToStdTimeFields ( + const STDTIME_WIN_DATE * /*I*/ pDate, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + + +/*** timezone-offset support functions ***************************************/ + + +STDTIME_RC StdTimeStringAToTzoA ( + const STDTIME_STRINGA * /*I*/ pStdTimeString, + STDTIME_TZOA * /*O*/ pTzo); + +STDTIME_RC TzoAToStdTimeStringA ( + const STDTIME_TZOA * /*I*/ pTzo, + STDTIME_STRINGA * /*O*/ pStdTimeString); + +STDTIME_RC ValidStdTimeTzoA ( + const STDTIME_TZOA * /*I*/ pTzo); + +STDTIME_RC NormalizeStdTimeTzoA ( + STDTIME_TZOA * /*I*/ pTzo); + +STDTIME_RC GetLocalStdTimeTzoA ( + STDTIME_TZOA * /*O*/ pTzo); + +#define StdTimeStringToTzoA StdTimeStringAToTzoA +#define TzoToStdTimeStringA TzoAToStdTimeStringA + + +#ifdef STDTIME_UNICODE +#else +#define StdTimeStringToTzo StdTimeStringAToTzoA +#define TzoToStdTimeString TzoAToStdTimeStringA +#define ValidStdTimeTzo ValidStdTimeTzoA +#define NormalizeStdTimeTzo NormalizeStdTimeTzoA +#define GetLocalStdTimeTzo GetLocalStdTimeTzoA +#endif /* STDTIME_UNICODE */ + + +/*** error message decoding functions ****************************************/ + + +STDTIME_RC StdTimeRcToErrMsgA ( + const STDTIME_RC /*I*/ stdTimeRc, + STDTIME_ERRMSGA * /*O*/ pErrMsg); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeRcToErrMsg StdTimeRcToErrMsgA +#endif /* STDTIME_UNICODE */ + + +/*** normalization functions; primarily private functions ********************/ + + +STDTIME_RC Rc_NormalizeStdTimeFields ( + STDTIME_FIELDS * pFields); + +STDTIME_RC Rc_StdTime_NormalizeSystemTimeEx ( + STDTIME_WIN_SYSTEMTIME * /*IO*/ pSystemTime, + int32_t * /*IO*/ pUsec, + int32_t * /*IO*/ pNsec); + +STDTIME_RC Rc_StdTime_NormalizeStructTmEx ( + struct tm * /*IO*/ pStructTm, + int32_t * /*IO*/ pMsec, + int32_t * /*IO*/ pUsec, + int32_t * /*IO*/ pNsec); + + +/* Utility functions */ +STDTIME_BOOL Bool_StdTimeGmTimeR ( + time_t * pTimeT, + struct tm * pStructTm); + +/*****************************************************************************/ +/* END */ +/*****************************************************************************/ + + +#ifdef __cplusplus +} +#endif + + +#endif /* _STDTIME_H_7583ECB2_DB3F_48B3_8A97_2D1D2A38C84A_ */ + diff --git a/include/inc/stdtime_config.h b/include/inc/stdtime_config.h new file mode 100644 index 0000000..2be7639 --- /dev/null +++ b/include/inc/stdtime_config.h @@ -0,0 +1,153 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtimeconfig.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Configuration of Standard Time Management Library Functions */ +/* This file is used to set the required symbols to generate a STDTIME */ +/* Library for a desired environment */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 02/22/08 JRB 05 Add glbtypes.h for SD_BYTE_ORDER & del stdtime_endian.h*/ +/* 03/18/07 RLH 04 Add QNX support. */ +/* 01/10/07 RLH 03 Add STDTIME_HPDATE_MSEC_ROUNDED define */ +/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */ +/* 01/18/06 RLH 01 Created */ +/*****************************************************************************/ + + +#ifndef _STDTIME_CONFIG_H_7BF1A3F7_495B_4EEE_A2B3_02D65FDF88B6_ +#define _STDTIME_CONFIG_H_7BF1A3F7_495B_4EEE_A2B3_02D65FDF88B6_ + +#include "glbtypes.h" /* Need this for SD_BYTE_ORDER */ + +#if 0 /* put disabled option inside the #if/#endif block */ + + +#define STDTIME_UNICODE /* default time strings are UNICODE */ +#define STDTIME_UNICODE_SUBSTITUTE_CHAR '\x1A' /* a value instead of '\x1A' */ +#define STDTIME_TIME_T64_ENABLED /* if system time_t is 64 bits */ +#define STDTIME_CPP_ONLY_DISABLED /* if library may be compiled as C */ +#define STDTIME_CPP_ONLY_ENABLED /* if library only compiled as C++ */ +#define STDTIME_MERGED_CSV /* csv has NO commas between records */ +#define STDTIME_LOCAL_USES_SYSAPI /* how to get local time from GMT */ + + +#define STDTIME_ISO_DLM_STR "-T:." /* default STDTIME_STRING delimiters */ +/* STDTIME_ISO_DLM_STR must be exactly 4 Ansi characters */ + + +#define QUADLIB_ENABLED /* if 64-bit math is simulated */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ +#define QUADLIB_NATIVE64_DISABLED /* if compiler has no 64-bit support */ +#define QUADLIB_STATIC static /* to make QUADLIB functions local */ +#define QUADLIB_I64N myI64Type /* explicit 64-bit signed int type */ +#define QUADLIB_U64N myUnsignedI64Type /* explicit 64-bit unsigned int type */ + + +#define STDTIMEW32_STATIC /* makes STDTIMEW32 functions local */ +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on Unix */ +#define STDTIMEW32_USE_GETTIMEOFDAY /* to use gettimeofday() on Unix */ +#define STDTIMEW32_USE_TIMEB /* to use ftime() and timeb on Unix */ + +#endif /* disabled */ + +/* put enabled options after this point */ + +#define STDTIME_TM_ISDST_DEFAULT (-1) /* struct tm_isdst default setting */ + +#define STDTIME_UNMERGED_CSV /* csv HAS commas between records */ + +#undef STDTIME_LOCAL_USES_TZDB /* how to get local time from GMT */ + +#define QUADLIB_NATIVE64_ENABLED /* if compiler has 64-bit support */ +#define STDTIME_HPDATE_MSEC_ROUNDED /* if HpDate msec are rounded */ + +/* include appropriate stdint.h header for target system */ + +#ifdef _AIX +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on Unix */ +#define STDTIMEW32_ENABLED /* enable WIN32 compatibility layer */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ +#include "stdint.h" + +#elif defined(linux) +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on Unix */ +#define STDTIMEW32_ENABLED /* enable WIN32 compatibility layer */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ +#include "stdint.h" + +#elif defined(__ECOS) +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on Unix */ +#define STDTIMEW32_ENABLED /* enable WIN32 compatibility layer */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ +//#include "stdint.h" + +/*renxiaobao add*/ +#elif defined(VXWORKS) +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on Unix */ +#define STDTIMEW32_ENABLED /* enable WIN32 compatibility layer */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ + + + + + + + + + +#elif defined(sun) +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on Unix */ +#define STDTIMEW32_ENABLED /* enable WIN32 compatibility layer */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ +#include + +#elif defined(__alpha) && !defined(__VMS) /* digital unix */ +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on Unix */ +#define STDTIMEW32_ENABLED /* enable WIN32 compatibility layer */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ +#include + +#elif defined(_WIN32) +#define STDTIMEW32_DISABLED /* disable WIN32 compatibility layer */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ +#include "stdtime_stdint.h" + +#elif defined(__QNX__) +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on QNX */ +#define STDTIMEW32_ENABLED /* enable WIN32 compatibility layer */ +#undef QUADLIB_DISABLED /* if 64-bit math done in hardware */ +#define QUADLIB_ENABLED /* if 64-bit math is simulated */ +#undef QUADLIB_NATIVE64_ENABLED /* if compiler has 64-bit support */ +#define QUADLIB_NATIVE64_DISABLED /* if compiler has no 64-bit support */ + +/* QNX has no stdint.h or equivalent */ +/* bare minimum definitions located here */ + + +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + + +#else + +#define STDTIMEW32_DISABLED /* disable WIN32 compatibility layer */ +#include "stdtime_stdint.h" + +#endif + +#endif /* _STDTIME_CONFIG_H_7BF1A3F7_495B_4EEE_A2B3_02D65FDF88B6_ */ + diff --git a/include/inc/stdtime_endian.h b/include/inc/stdtime_endian.h new file mode 100644 index 0000000..221adb9 --- /dev/null +++ b/include/inc/stdtime_endian.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/* + * Copyright notice reproduced from , from + * which this code was originally taken. + * + * Modified by Caleb Epstein to use with GNU libc and to + * define the BOOST_ENDIAN macro. + */ + +/* + * Modified 2006-02-25 By SISCO, Inc. from Boost source. + * source code simplified, made C compliant, and BOOST_BYTE_ORDER removed + */ + + +#ifndef _STDTIME_ENDIAN_H_9F8D5A2A_B2F9_4F41_A9A0_D2D3912E3082_ +#define _STDTIME_ENDIAN_H_9F8D5A2A_B2F9_4F41_A9A0_D2D3912E3082_ + + +#undef HOST_BIG_ENDIAN +#undef HOST_LITTLE_ENDIAN + +/* GNU libc offers the helpful header which defines __BYTE_ORDER */ + +#ifdef __GLIBC__ +#include + +#if (__BYTE_ORDER == __LITTLE_ENDIAN) /* 1234 */ +#define HOST_LITTLE_ENDIAN +#elif (__BYTE_ORDER == __BIG_ENDIAN) /* 4321 */ +#define HOST_BIG_ENDIAN +#elif (__BYTE_ORDER == __PDP_ENDIAN) +#error PDP_ENDIAN order not supported +#else +#error unknown machine endian order +#endif + + +#elif defined(_MIPSEB) \ + || defined(_POWER) \ + || defined(__hppa) \ + || defined(__powerpc__) \ + || defined(__ppc__) \ + || defined(__s390__) \ + || defined(__sparc) \ + || defined(__sparc__) \ + || defined(sun) \ + || defined(_AIX) \ + || defined(VXWORKS) \ + || defined(__hpux) /**/ +#define HOST_BIG_ENDIAN + + +#elif defined(_M_ALPHA) \ + || defined(_M_IA64) \ + || defined(_M_IX86) \ + || defined(__alpha__) \ + || defined(__i386__) \ + || defined(__ia64) \ + || defined(__ia64__) \ + || defined(MSDOS) \ + || defined(_WIN32) \ + || defined(__LYNX) \ + || defined(__MSDOS__) \ + || defined(__OS2__) \ + || defined(__QNX__) \ + || defined(linux) \ + || (defined(__ALPHA) && defined(__VMS)) \ + || (defined(__alpha) && !defined(__VMS)) /**/ +#define HOST_LITTLE_ENDIAN + + +#else +#error the file host_endian.h needs to be configured for your CPU type +#endif + +#endif /* _STDTIME_ENDIAN_H_9F8D5A2A_B2F9_4F41_A9A0_D2D3912E3082_ */ + diff --git a/include/inc/stdtime_enum_err.h b/include/inc/stdtime_enum_err.h new file mode 100644 index 0000000..34671a2 --- /dev/null +++ b/include/inc/stdtime_enum_err.h @@ -0,0 +1,65 @@ + STDTIME_ENUM_ERR (BTOD_form_code_not_4_or_6) + STDTIME_ENUM_ERR (CComSpan_range_is_invalid) + STDTIME_ENUM_ERR (COleDateTimeSpan_status_is_invalid) + STDTIME_ENUM_ERR (COleDateTimeSpan_status_is_null) + STDTIME_ENUM_ERR (MMS_year_LT_1984) + STDTIME_ENUM_ERR (VARIANT_BYREF_type_not_DATE) + STDTIME_ENUM_ERR (VARIANT_type_not_DATE) + STDTIME_ENUM_ERR (argument_out_of_range) + STDTIME_ENUM_ERR (buffer_size_exceeded) + STDTIME_ENUM_ERR (cannot_determine_local_timezone) + STDTIME_ENUM_ERR (cannot_determine_local_timezone_offset) + STDTIME_ENUM_ERR (cannot_extract_timezone_field) + STDTIME_ENUM_ERR (cannot_find_timezone_entry) + STDTIME_ENUM_ERR (cannot_find_timezone_name) + STDTIME_ENUM_ERR (cannot_open_timezone_file) + STDTIME_ENUM_ERR (conflicting_sign_delta) + STDTIME_ENUM_ERR (data_out_of_range) + STDTIME_ENUM_ERR (day_out_of_range) + STDTIME_ENUM_ERR (failure_in_api_FileTimeToLocalFileTime) + STDTIME_ENUM_ERR (failure_in_api_FileTimeToSystemTime) + STDTIME_ENUM_ERR (failure_in_api_LocalFileTimeToFileTime) + STDTIME_ENUM_ERR (failure_in_api_SetStdTimeStringDelimitersA) + STDTIME_ENUM_ERR (failure_in_api_SetStdTimeStringDelimitersW) + STDTIME_ENUM_ERR (failure_in_api_SgnStdTimeDelta) + STDTIME_ENUM_ERR (failure_in_api_StdTimeGetDayofWeekAndYear) + STDTIME_ENUM_ERR (failure_in_api_StdTimeW32GetDayofWeekAndYear) + STDTIME_ENUM_ERR (failure_in_api_SystemTimeToFileTime) + STDTIME_ENUM_ERR (failure_in_api_strftime) + STDTIME_ENUM_ERR (field_selector_out_of_range) + STDTIME_ENUM_ERR (invalid_FileTime) + STDTIME_ENUM_ERR (invalid_StdTime) + STDTIME_ENUM_ERR (invalid_day) + STDTIME_ENUM_ERR (invalid_delimiter) + STDTIME_ENUM_ERR (invalid_hh_mm) + STDTIME_ENUM_ERR (invalid_hour) + STDTIME_ENUM_ERR (invalid_min) + STDTIME_ENUM_ERR (invalid_mon) + STDTIME_ENUM_ERR (invalid_msec) + STDTIME_ENUM_ERR (invalid_nsec) + STDTIME_ENUM_ERR (invalid_sec) + STDTIME_ENUM_ERR (invalid_sign) + STDTIME_ENUM_ERR (invalid_ss) + STDTIME_ENUM_ERR (invalid_stdtime_rc_value) + STDTIME_ENUM_ERR (invalid_timezone_offset) + STDTIME_ENUM_ERR (invalid_timezone_rule) + STDTIME_ENUM_ERR (invalid_usec) + STDTIME_ENUM_ERR (invalid_year) + STDTIME_ENUM_ERR (length_out_of_range) + STDTIME_ENUM_ERR (missing_timezone_name) + STDTIME_ENUM_ERR (negative_dst_end_time) + STDTIME_ENUM_ERR (negative_dst_start_time) + STDTIME_ENUM_ERR (null_VARIANT_pdate) + STDTIME_ENUM_ERR (null_argument) + STDTIME_ENUM_ERR (overflow_in_delta_day) + STDTIME_ENUM_ERR (overflow_in_delta_hour) + STDTIME_ENUM_ERR (overflow_in_delta_min) + STDTIME_ENUM_ERR (overflow_in_delta_msec) + STDTIME_ENUM_ERR (overflow_in_delta_nsec) + STDTIME_ENUM_ERR (overflow_in_delta_sec) + STDTIME_ENUM_ERR (overflow_in_delta_usec) + STDTIME_ENUM_ERR (span_out_of_range) + STDTIME_ENUM_ERR (time_GT_2038_01_18__19_14_07) + STDTIME_ENUM_ERR (time_LT_1970_01_01) + STDTIME_ENUM_ERR (unexpected_condition) + STDTIME_ENUM_ERR (year_out_of_range) diff --git a/include/inc/stdtime_enum_func.h b/include/inc/stdtime_enum_func.h new file mode 100644 index 0000000..ea9943b --- /dev/null +++ b/include/inc/stdtime_enum_func.h @@ -0,0 +1,425 @@ + STDTIME_ENUM_FUNC (AbsStdTimeDelta) + STDTIME_ENUM_FUNC (AbsStdTimeSpan) + STDTIME_ENUM_FUNC (CComDateExToStdTime) + STDTIME_ENUM_FUNC (CComDateExToStdTimeFields) + STDTIME_ENUM_FUNC (CComDateToStdTime) + STDTIME_ENUM_FUNC (CComDateToStdTimeFields) + STDTIME_ENUM_FUNC (CComSpanExToStdTime) + STDTIME_ENUM_FUNC (CComSpanExToStdTimeDelta) + STDTIME_ENUM_FUNC (CComSpanExToStdTimeFields) + STDTIME_ENUM_FUNC (CComSpanExToStdTimeSpan) + STDTIME_ENUM_FUNC (CComSpanToStdTime) + STDTIME_ENUM_FUNC (CComSpanToStdTimeDelta) + STDTIME_ENUM_FUNC (CComSpanToStdTimeFields) + STDTIME_ENUM_FUNC (CComSpanToStdTimeSpan) + STDTIME_ENUM_FUNC (CFileTimeSpanToStdTime) + STDTIME_ENUM_FUNC (CFileTimeSpanToStdTimeDelta) + STDTIME_ENUM_FUNC (CFileTimeSpanToStdTimeFields) + STDTIME_ENUM_FUNC (CFileTimeSpanToStdTimeSpan) + STDTIME_ENUM_FUNC (CFileTimeToStdTime) + STDTIME_ENUM_FUNC (CFileTimeToStdTimeFields) + STDTIME_ENUM_FUNC (COleDateTimeExToStdTime) + STDTIME_ENUM_FUNC (COleDateTimeExToStdTimeFields) + STDTIME_ENUM_FUNC (COleDateTimeSpanExToStdTime) + STDTIME_ENUM_FUNC (COleDateTimeSpanExToStdTimeDelta) + STDTIME_ENUM_FUNC (COleDateTimeSpanExToStdTimeFields) + STDTIME_ENUM_FUNC (COleDateTimeSpanExToStdTimeSpan) + STDTIME_ENUM_FUNC (COleDateTimeSpanToStdTime) + STDTIME_ENUM_FUNC (COleDateTimeSpanToStdTimeDelta) + STDTIME_ENUM_FUNC (COleDateTimeSpanToStdTimeFields) + STDTIME_ENUM_FUNC (COleDateTimeSpanToStdTimeSpan) + STDTIME_ENUM_FUNC (COleDateTimeToStdTime) + STDTIME_ENUM_FUNC (COleDateTimeToStdTimeFields) + STDTIME_ENUM_FUNC (CTimeExToStdTime) + STDTIME_ENUM_FUNC (CTimeExToStdTimeFields) + STDTIME_ENUM_FUNC (CTimeSpanExToStdTime) + STDTIME_ENUM_FUNC (CTimeSpanExToStdTimeDelta) + STDTIME_ENUM_FUNC (CTimeSpanExToStdTimeFields) + STDTIME_ENUM_FUNC (CTimeSpanExToStdTimeSpan) + STDTIME_ENUM_FUNC (CTimeSpanToStdTime) + STDTIME_ENUM_FUNC (CTimeSpanToStdTimeDelta) + STDTIME_ENUM_FUNC (CTimeSpanToStdTimeFields) + STDTIME_ENUM_FUNC (CTimeSpanToStdTimeSpan) + STDTIME_ENUM_FUNC (CTimeToStdTime) + STDTIME_ENUM_FUNC (CTimeToStdTimeFields) + STDTIME_ENUM_FUNC (DateExToStdTime) + STDTIME_ENUM_FUNC (DateExToStdTimeFields) + STDTIME_ENUM_FUNC (DateToStdTime) + STDTIME_ENUM_FUNC (DateToStdTimeFields) + STDTIME_ENUM_FUNC (DbTimeStampToStdTime) + STDTIME_ENUM_FUNC (DbTimeStampToStdTimeFields) + STDTIME_ENUM_FUNC (DelimitStdTimeStringA) + STDTIME_ENUM_FUNC (DelimitStdTimeStringW) + STDTIME_ENUM_FUNC (FileTimeToStdTime) + STDTIME_ENUM_FUNC (FileTimeToStdTimeFields) + STDTIME_ENUM_FUNC (FileTimeToStdTimeHexStrA) + STDTIME_ENUM_FUNC (FileTimeToStdTimeHexStrW) + STDTIME_ENUM_FUNC (FileTimeToStdTimeStringA) + STDTIME_ENUM_FUNC (FileTimeToStdTimeStringW) + STDTIME_ENUM_FUNC (FormatStdTimeA) + STDTIME_ENUM_FUNC (FormatStdTimeFieldsA) + STDTIME_ENUM_FUNC (FormatStdTimeFieldsW) + STDTIME_ENUM_FUNC (FormatStdTimeHexStrA) + STDTIME_ENUM_FUNC (FormatStdTimeHexStrW) + STDTIME_ENUM_FUNC (FormatStdTimeStringA) + STDTIME_ENUM_FUNC (FormatStdTimeStringW) + STDTIME_ENUM_FUNC (FormatStdTimeW) + STDTIME_ENUM_FUNC (GetLocalStdTime) + STDTIME_ENUM_FUNC (GetLocalStdTimeFields) + STDTIME_ENUM_FUNC (GetLocalStdTimeHexStrA) + STDTIME_ENUM_FUNC (GetLocalStdTimeHexStrW) + STDTIME_ENUM_FUNC (GetLocalStdTimeStringA) + STDTIME_ENUM_FUNC (GetLocalStdTimeStringW) + STDTIME_ENUM_FUNC (GetLocalStdTimeTzoA) + STDTIME_ENUM_FUNC (GetLocalStdTimeTzoW) + STDTIME_ENUM_FUNC (GetStdTime) + STDTIME_ENUM_FUNC (GetStdTimeFields) + STDTIME_ENUM_FUNC (GetStdTimeHexStrA) + STDTIME_ENUM_FUNC (GetStdTimeHexStrW) + STDTIME_ENUM_FUNC (GetStdTimeStringA) + STDTIME_ENUM_FUNC (GetStdTimeStringW) + STDTIME_ENUM_FUNC (GetStdTimeZoneInfo) + STDTIME_ENUM_FUNC (HpCComDateExToStdTime) + STDTIME_ENUM_FUNC (HpCComDateExToStdTimeFields) + STDTIME_ENUM_FUNC (HpCComDateToStdTime) + STDTIME_ENUM_FUNC (HpCComDateToStdTimeFields) + STDTIME_ENUM_FUNC (HpCComSpanExToStdTime) + STDTIME_ENUM_FUNC (HpCComSpanExToStdTimeDelta) + STDTIME_ENUM_FUNC (HpCComSpanExToStdTimeFields) + STDTIME_ENUM_FUNC (HpCComSpanExToStdTimeSpan) + STDTIME_ENUM_FUNC (HpCComSpanToStdTime) + STDTIME_ENUM_FUNC (HpCComSpanToStdTimeDelta) + STDTIME_ENUM_FUNC (HpCComSpanToStdTimeFields) + STDTIME_ENUM_FUNC (HpCComSpanToStdTimeSpan) + STDTIME_ENUM_FUNC (HpCOleDateTimeExToStdTime) + STDTIME_ENUM_FUNC (HpCOleDateTimeExToStdTimeFields) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanExToStdTime) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanExToStdTimeDelta) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanExToStdTimeFields) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanExToStdTimeSpan) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanToStdTime) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanToStdTimeDelta) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanToStdTimeFields) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanToStdTimeSpan) + STDTIME_ENUM_FUNC (HpCOleDateTimeToStdTime) + STDTIME_ENUM_FUNC (HpCOleDateTimeToStdTimeFields) + STDTIME_ENUM_FUNC (HpDateExToStdTime) + STDTIME_ENUM_FUNC (HpDateExToStdTimeFields) + STDTIME_ENUM_FUNC (HpDateToStdTime) + STDTIME_ENUM_FUNC (HpDateToStdTimeFields) + STDTIME_ENUM_FUNC (IccpTimeStampExToStdTime) + STDTIME_ENUM_FUNC (IccpTimeStampExToStdTimeFields) + STDTIME_ENUM_FUNC (IccpTimeStampToStdTime) + STDTIME_ENUM_FUNC (IccpTimeStampToStdTimeFields) + STDTIME_ENUM_FUNC (LocalStdTimeFieldsToStdTimeFields) + STDTIME_ENUM_FUNC (LocalStdTimeHexStrAToStdTimeHexStrA) + STDTIME_ENUM_FUNC (LocalStdTimeHexStrWToStdTimeHexStrW) + STDTIME_ENUM_FUNC (LocalStdTimeStringAToStdTimeStringA) + STDTIME_ENUM_FUNC (LocalStdTimeStringWToStdTimeStringW) + STDTIME_ENUM_FUNC (LocalStdTimeToStdTime) + STDTIME_ENUM_FUNC (MmsBtodExToStdTime) + STDTIME_ENUM_FUNC (MmsBtodExToStdTimeFields) + STDTIME_ENUM_FUNC (MmsBtodToStdTime) + STDTIME_ENUM_FUNC (MmsBtodToStdTimeFields) + STDTIME_ENUM_FUNC (MmsTimeOfDay4ExToStdTime) + STDTIME_ENUM_FUNC (MmsTimeOfDay4ExToStdTimeFields) + STDTIME_ENUM_FUNC (MmsTimeOfDay4ToStdTime) + STDTIME_ENUM_FUNC (MmsTimeOfDay4ToStdTimeFields) + STDTIME_ENUM_FUNC (MmsTimeOfDay6ExToStdTime) + STDTIME_ENUM_FUNC (MmsTimeOfDay6ExToStdTimeFields) + STDTIME_ENUM_FUNC (MmsTimeOfDay6ToStdTime) + STDTIME_ENUM_FUNC (MmsTimeOfDay6ToStdTimeFields) + STDTIME_ENUM_FUNC (MmsUtcTimeToStdTime) + STDTIME_ENUM_FUNC (MmsUtcTimeToStdTimeFields) + STDTIME_ENUM_FUNC (NegStdTimeDelta) + STDTIME_ENUM_FUNC (NegStdTimeSpan) + STDTIME_ENUM_FUNC (NormalizeStdTimeDelta) + STDTIME_ENUM_FUNC (NormalizeStdTimeTzoA) + STDTIME_ENUM_FUNC (NormalizeStdTimeTzoW) + STDTIME_ENUM_FUNC (Rc_ArgDateExToStdTime) + STDTIME_ENUM_FUNC (Rc_ArgDateExToStdTimeFields) + STDTIME_ENUM_FUNC (Rc_FixStdTimeZoneRules) + STDTIME_ENUM_FUNC (Rc_NormalizeStdTimeFields) + STDTIME_ENUM_FUNC (Rc_ParseStdTimeZoneData) + STDTIME_ENUM_FUNC (Rc_QuadLibI64ToStdTime) + STDTIME_ENUM_FUNC (Rc_StdTimeFieldsToArgDateEx) + STDTIME_ENUM_FUNC (Rc_StdTimeToArgDateEx) + STDTIME_ENUM_FUNC (Rc_StdTimeToQuadLibI64) + STDTIME_ENUM_FUNC (Rc_StdTimeTz_GetRule) + STDTIME_ENUM_FUNC (Rc_StdTimeTz_GetTime) + STDTIME_ENUM_FUNC (Rc_StdTime_DateToVariant) + STDTIME_ENUM_FUNC (Rc_StdTime_FileTimeSplit) + STDTIME_ENUM_FUNC (Rc_StdTime_FileTimeToSystemTimeEx) + STDTIME_ENUM_FUNC (Rc_StdTime_Formatter) + STDTIME_ENUM_FUNC (Rc_StdTime_NormalizeStructTmEx) + STDTIME_ENUM_FUNC (Rc_StdTime_NormalizeSystemTimeEx) + STDTIME_ENUM_FUNC (Rc_StdTime_SystemTimeExToFileTime) + STDTIME_ENUM_FUNC (Rc_StdTime_TimeTBase) + STDTIME_ENUM_FUNC (Rc_StdTime_TimeTypeToFileTime) + STDTIME_ENUM_FUNC (Rc_StdTime_ValidFileTime) + STDTIME_ENUM_FUNC (Rc_StdTime_VariantToDate) + STDTIME_ENUM_FUNC (ReadStdTimeZoneInfo) + STDTIME_ENUM_FUNC (RepairStdTimeStringA) + STDTIME_ENUM_FUNC (RepairStdTimeStringW) + STDTIME_ENUM_FUNC (RoundStdTimeDelta) + STDTIME_ENUM_FUNC (SetStdTimeStringDelimitersA) + STDTIME_ENUM_FUNC (SetStdTimeStringDelimitersW) + STDTIME_ENUM_FUNC (StdTimeApiFileTimeIsDST) + STDTIME_ENUM_FUNC (StdTimeApiFileTimeToZonedFileTime) + STDTIME_ENUM_FUNC (StdTimeApiZonedFileTimeIsDST) + STDTIME_ENUM_FUNC (StdTimeApiZonedFileTimeToFileTime) + STDTIME_ENUM_FUNC (StdTimeDeltaToCComSpan) + STDTIME_ENUM_FUNC (StdTimeDeltaToCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeDeltaToCFileTimeSpan) + STDTIME_ENUM_FUNC (StdTimeDeltaToCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeDeltaToCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeDeltaToCTimeSpan) + STDTIME_ENUM_FUNC (StdTimeDeltaToCTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeDeltaToHpCComSpan) + STDTIME_ENUM_FUNC (StdTimeDeltaToHpCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeDeltaToHpCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeDeltaToHpCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeDeltaToStdTimeSpan) + STDTIME_ENUM_FUNC (StdTimeDelta_AddDelta) + STDTIME_ENUM_FUNC (StdTimeDelta_AddSpan) + STDTIME_ENUM_FUNC (StdTimeDelta_SubDelta) + STDTIME_ENUM_FUNC (StdTimeDelta_SubSpan) + STDTIME_ENUM_FUNC (StdTimeFieldsToCComDate) + STDTIME_ENUM_FUNC (StdTimeFieldsToCComDateEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToCComSpan) + STDTIME_ENUM_FUNC (StdTimeFieldsToCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToCFileTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToCFileTimeSpan) + STDTIME_ENUM_FUNC (StdTimeFieldsToCOleDateTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToCOleDateTimeEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeFieldsToCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToCTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToCTimeEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToCTimeSpan) + STDTIME_ENUM_FUNC (StdTimeFieldsToCTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToDate) + STDTIME_ENUM_FUNC (StdTimeFieldsToDateEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToDbTimeStamp) + STDTIME_ENUM_FUNC (StdTimeFieldsToFileTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCComDate) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCComDateEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCComSpan) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCOleDateTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCOleDateTimeEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpDate) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpDateEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToIccpTimeStamp) + STDTIME_ENUM_FUNC (StdTimeFieldsToIccpTimeStampEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToLocalStdTimeFields) + STDTIME_ENUM_FUNC (StdTimeFieldsToMmsBtod) + STDTIME_ENUM_FUNC (StdTimeFieldsToMmsBtodEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToMmsTimeOfDay4) + STDTIME_ENUM_FUNC (StdTimeFieldsToMmsTimeOfDay4Ex) + STDTIME_ENUM_FUNC (StdTimeFieldsToMmsTimeOfDay6) + STDTIME_ENUM_FUNC (StdTimeFieldsToMmsTimeOfDay6Ex) + STDTIME_ENUM_FUNC (StdTimeFieldsToMmsUtcTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToStdTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToStdTimeHexStrA) + STDTIME_ENUM_FUNC (StdTimeFieldsToStdTimeHexStrW) + STDTIME_ENUM_FUNC (StdTimeFieldsToStdTimeStringA) + STDTIME_ENUM_FUNC (StdTimeFieldsToStdTimeStringW) + STDTIME_ENUM_FUNC (StdTimeFieldsToStructTm) + STDTIME_ENUM_FUNC (StdTimeFieldsToStructTmEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToSystemTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToSystemTimeEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToTimeType) + STDTIME_ENUM_FUNC (StdTimeFieldsToTimeTypeEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToUdate) + STDTIME_ENUM_FUNC (StdTimeFieldsToUdateEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToVariant) + STDTIME_ENUM_FUNC (StdTimeFieldsToVariantEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToZonedStdTimeFields) + STDTIME_ENUM_FUNC (StdTimeFields_AddDelta) + STDTIME_ENUM_FUNC (StdTimeFields_AddFraction) + STDTIME_ENUM_FUNC (StdTimeFields_AddSpan) + STDTIME_ENUM_FUNC (StdTimeFields_GetDelta) + STDTIME_ENUM_FUNC (StdTimeFields_GetSpan) + STDTIME_ENUM_FUNC (StdTimeFields_SubDelta) + STDTIME_ENUM_FUNC (StdTimeFields_SubSpan) + STDTIME_ENUM_FUNC (StdTimeGetDayofWeekAndYear) + STDTIME_ENUM_FUNC (StdTimeHexStrAToFileTime) + STDTIME_ENUM_FUNC (StdTimeHexStrAToLocalStdTimeHexStrA) + STDTIME_ENUM_FUNC (StdTimeHexStrAToStdTime) + STDTIME_ENUM_FUNC (StdTimeHexStrAToStdTimeFields) + STDTIME_ENUM_FUNC (StdTimeHexStrAToStdTimeStringA) + STDTIME_ENUM_FUNC (StdTimeHexStrAToZonedStdTimeHexStrA) + STDTIME_ENUM_FUNC (StdTimeHexStrA_AddDelta) + STDTIME_ENUM_FUNC (StdTimeHexStrA_AddSpan) + STDTIME_ENUM_FUNC (StdTimeHexStrA_GetDelta) + STDTIME_ENUM_FUNC (StdTimeHexStrA_GetSpan) + STDTIME_ENUM_FUNC (StdTimeHexStrA_SubDelta) + STDTIME_ENUM_FUNC (StdTimeHexStrA_SubSpan) + STDTIME_ENUM_FUNC (StdTimeHexStrWToFileTime) + STDTIME_ENUM_FUNC (StdTimeHexStrWToLocalStdTimeHexStrW) + STDTIME_ENUM_FUNC (StdTimeHexStrWToStdTime) + STDTIME_ENUM_FUNC (StdTimeHexStrWToStdTimeFields) + STDTIME_ENUM_FUNC (StdTimeHexStrWToStdTimeStringW) + STDTIME_ENUM_FUNC (StdTimeHexStrWToZonedStdTimeHexStrW) + STDTIME_ENUM_FUNC (StdTimeHexStrW_AddDelta) + STDTIME_ENUM_FUNC (StdTimeHexStrW_AddSpan) + STDTIME_ENUM_FUNC (StdTimeHexStrW_GetDelta) + STDTIME_ENUM_FUNC (StdTimeHexStrW_GetSpan) + STDTIME_ENUM_FUNC (StdTimeHexStrW_SubDelta) + STDTIME_ENUM_FUNC (StdTimeHexStrW_SubSpan) + STDTIME_ENUM_FUNC (StdTimeRcToErrMsgA) + STDTIME_ENUM_FUNC (StdTimeRcToErrMsgW) + STDTIME_ENUM_FUNC (StdTimeSpanToCComSpan) + STDTIME_ENUM_FUNC (StdTimeSpanToCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeSpanToCFileTimeSpan) + STDTIME_ENUM_FUNC (StdTimeSpanToCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeSpanToCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeSpanToCTimeSpan) + STDTIME_ENUM_FUNC (StdTimeSpanToCTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeSpanToHpCComSpan) + STDTIME_ENUM_FUNC (StdTimeSpanToHpCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeSpanToHpCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeSpanToHpCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeSpanToStdTimeDelta) + STDTIME_ENUM_FUNC (StdTimeSpan_AddDelta) + STDTIME_ENUM_FUNC (StdTimeSpan_AddSpan) + STDTIME_ENUM_FUNC (StdTimeSpan_SubDelta) + STDTIME_ENUM_FUNC (StdTimeSpan_SubSpan) + STDTIME_ENUM_FUNC (StdTimeStringAToFileTime) + STDTIME_ENUM_FUNC (StdTimeStringAToLocalStdTimeStringA) + STDTIME_ENUM_FUNC (StdTimeStringAToStdTime) + STDTIME_ENUM_FUNC (StdTimeStringAToStdTimeFields) + STDTIME_ENUM_FUNC (StdTimeStringAToStdTimeHexStrA) + STDTIME_ENUM_FUNC (StdTimeStringAToTzoA) + STDTIME_ENUM_FUNC (StdTimeStringAToZonedStdTimeStringA) + STDTIME_ENUM_FUNC (StdTimeStringA_AddDelta) + STDTIME_ENUM_FUNC (StdTimeStringA_AddSpan) + STDTIME_ENUM_FUNC (StdTimeStringA_GetDelta) + STDTIME_ENUM_FUNC (StdTimeStringA_GetSpan) + STDTIME_ENUM_FUNC (StdTimeStringA_SubDelta) + STDTIME_ENUM_FUNC (StdTimeStringA_SubSpan) + STDTIME_ENUM_FUNC (StdTimeStringWToFileTime) + STDTIME_ENUM_FUNC (StdTimeStringWToLocalStdTimeStringW) + STDTIME_ENUM_FUNC (StdTimeStringWToStdTime) + STDTIME_ENUM_FUNC (StdTimeStringWToStdTimeFields) + STDTIME_ENUM_FUNC (StdTimeStringWToStdTimeHexStrW) + STDTIME_ENUM_FUNC (StdTimeStringWToTzoW) + STDTIME_ENUM_FUNC (StdTimeStringWToZonedStdTimeStringW) + STDTIME_ENUM_FUNC (StdTimeStringW_AddDelta) + STDTIME_ENUM_FUNC (StdTimeStringW_AddSpan) + STDTIME_ENUM_FUNC (StdTimeStringW_GetDelta) + STDTIME_ENUM_FUNC (StdTimeStringW_GetSpan) + STDTIME_ENUM_FUNC (StdTimeStringW_SubDelta) + STDTIME_ENUM_FUNC (StdTimeStringW_SubSpan) + STDTIME_ENUM_FUNC (StdTimeToCComDate) + STDTIME_ENUM_FUNC (StdTimeToCComDateEx) + STDTIME_ENUM_FUNC (StdTimeToCComSpan) + STDTIME_ENUM_FUNC (StdTimeToCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeToCFileTime) + STDTIME_ENUM_FUNC (StdTimeToCFileTimeSpan) + STDTIME_ENUM_FUNC (StdTimeToCOleDateTime) + STDTIME_ENUM_FUNC (StdTimeToCOleDateTimeEx) + STDTIME_ENUM_FUNC (StdTimeToCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeToCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeToCTime) + STDTIME_ENUM_FUNC (StdTimeToCTimeEx) + STDTIME_ENUM_FUNC (StdTimeToCTimeSpan) + STDTIME_ENUM_FUNC (StdTimeToCTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeToDate) + STDTIME_ENUM_FUNC (StdTimeToDateEx) + STDTIME_ENUM_FUNC (StdTimeToDbTimeStamp) + STDTIME_ENUM_FUNC (StdTimeToFileTime) + STDTIME_ENUM_FUNC (StdTimeToHpCComDate) + STDTIME_ENUM_FUNC (StdTimeToHpCComDateEx) + STDTIME_ENUM_FUNC (StdTimeToHpCComSpan) + STDTIME_ENUM_FUNC (StdTimeToHpCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeToHpCOleDateTime) + STDTIME_ENUM_FUNC (StdTimeToHpCOleDateTimeEx) + STDTIME_ENUM_FUNC (StdTimeToHpCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeToHpCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeToHpDate) + STDTIME_ENUM_FUNC (StdTimeToHpDateEx) + STDTIME_ENUM_FUNC (StdTimeToIccpTimeStamp) + STDTIME_ENUM_FUNC (StdTimeToIccpTimeStampEx) + STDTIME_ENUM_FUNC (StdTimeToLocalStdTime) + STDTIME_ENUM_FUNC (StdTimeToMmsBtod) + STDTIME_ENUM_FUNC (StdTimeToMmsBtodEx) + STDTIME_ENUM_FUNC (StdTimeToMmsTimeOfDay4) + STDTIME_ENUM_FUNC (StdTimeToMmsTimeOfDay4Ex) + STDTIME_ENUM_FUNC (StdTimeToMmsTimeOfDay6) + STDTIME_ENUM_FUNC (StdTimeToMmsTimeOfDay6Ex) + STDTIME_ENUM_FUNC (StdTimeToMmsUtcTime) + STDTIME_ENUM_FUNC (StdTimeToStdTimeField) + STDTIME_ENUM_FUNC (StdTimeToStdTimeHexStrA) + STDTIME_ENUM_FUNC (StdTimeToStdTimeHexStrW) + STDTIME_ENUM_FUNC (StdTimeToStdTimeStringA) + STDTIME_ENUM_FUNC (StdTimeToStdTimeStringW) + STDTIME_ENUM_FUNC (StdTimeToStructTm) + STDTIME_ENUM_FUNC (StdTimeToStructTmEx) + STDTIME_ENUM_FUNC (StdTimeToSystemTime) + STDTIME_ENUM_FUNC (StdTimeToSystemTimeEx) + STDTIME_ENUM_FUNC (StdTimeToTimeType) + STDTIME_ENUM_FUNC (StdTimeToTimeTypeEx) + STDTIME_ENUM_FUNC (StdTimeToUdate) + STDTIME_ENUM_FUNC (StdTimeToUdateEx) + STDTIME_ENUM_FUNC (StdTimeToVariant) + STDTIME_ENUM_FUNC (StdTimeToVariantEx) + STDTIME_ENUM_FUNC (StdTimeToZonedStdTime) + STDTIME_ENUM_FUNC (StdTimeTzTimeToDelta) + STDTIME_ENUM_FUNC (StdTimeW32GetDayofWeekAndYear) + STDTIME_ENUM_FUNC (StdTimeZoneDataToInfo) + STDTIME_ENUM_FUNC (StdTimeZoneDayOfRule) + STDTIME_ENUM_FUNC (StdTime_AddDelta) + STDTIME_ENUM_FUNC (StdTime_AddSpan) + STDTIME_ENUM_FUNC (StdTime_GetDelta) + STDTIME_ENUM_FUNC (StdTime_GetSpan) + STDTIME_ENUM_FUNC (StdTime_SubDelta) + STDTIME_ENUM_FUNC (StdTime_SubSpan) + STDTIME_ENUM_FUNC (StructTmExToStdTime) + STDTIME_ENUM_FUNC (StructTmExToStdTimeFields) + STDTIME_ENUM_FUNC (StructTmToStdTime) + STDTIME_ENUM_FUNC (StructTmToStdTimeFields) + STDTIME_ENUM_FUNC (SystemTimeExToStdTime) + STDTIME_ENUM_FUNC (SystemTimeExToStdTimeFields) + STDTIME_ENUM_FUNC (SystemTimeToStdTime) + STDTIME_ENUM_FUNC (SystemTimeToStdTimeFields) + STDTIME_ENUM_FUNC (TimeTypeExToStdTime) + STDTIME_ENUM_FUNC (TimeTypeExToStdTimeFields) + STDTIME_ENUM_FUNC (TimeTypeToStdTime) + STDTIME_ENUM_FUNC (TimeTypeToStdTimeFields) + STDTIME_ENUM_FUNC (TranslateStdTimeWinZoneName) + STDTIME_ENUM_FUNC (TranslateStdTimeZoneName) + STDTIME_ENUM_FUNC (TrimStdTimeStringA) + STDTIME_ENUM_FUNC (TrimStdTimeStringW) + STDTIME_ENUM_FUNC (TruncStdTimeDelta) + STDTIME_ENUM_FUNC (TruncStdTimeStringA) + STDTIME_ENUM_FUNC (TruncStdTimeStringW) + STDTIME_ENUM_FUNC (TzoAToStdTimeStringA) + STDTIME_ENUM_FUNC (TzoWToStdTimeStringW) + STDTIME_ENUM_FUNC (UdateExToStdTime) + STDTIME_ENUM_FUNC (UdateExToStdTimeFields) + STDTIME_ENUM_FUNC (UdateToStdTime) + STDTIME_ENUM_FUNC (UdateToStdTimeFields) + STDTIME_ENUM_FUNC (ValidStdTime) + STDTIME_ENUM_FUNC (ValidStdTimeDelta) + STDTIME_ENUM_FUNC (ValidStdTimeFields) + STDTIME_ENUM_FUNC (ValidStdTimeHexStrA) + STDTIME_ENUM_FUNC (ValidStdTimeHexStrW) + STDTIME_ENUM_FUNC (ValidStdTimeSpan) + STDTIME_ENUM_FUNC (ValidStdTimeStringA) + STDTIME_ENUM_FUNC (ValidStdTimeStringW) + STDTIME_ENUM_FUNC (ValidStdTimeTzoA) + STDTIME_ENUM_FUNC (ValidStdTimeTzoW) + STDTIME_ENUM_FUNC (VariantExToStdTime) + STDTIME_ENUM_FUNC (VariantExToStdTimeFields) + STDTIME_ENUM_FUNC (VariantToStdTime) + STDTIME_ENUM_FUNC (VariantToStdTimeFields) + STDTIME_ENUM_FUNC (ZonedStdTimeFieldsToStdTimeFields) + STDTIME_ENUM_FUNC (ZonedStdTimeHexStrAToStdTimeHexStrA) + STDTIME_ENUM_FUNC (ZonedStdTimeHexStrWToStdTimeHexStrW) + STDTIME_ENUM_FUNC (ZonedStdTimeStringAToStdTimeStringA) + STDTIME_ENUM_FUNC (ZonedStdTimeStringWToStdTimeStringW) + STDTIME_ENUM_FUNC (ZonedStdTimeToStdTime) diff --git a/include/inc/stdtime_mms_btime.h b/include/inc/stdtime_mms_btime.h new file mode 100644 index 0000000..e1b09c0 --- /dev/null +++ b/include/inc/stdtime_mms_btime.h @@ -0,0 +1,81 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2006 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtime_mms_btime.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Support for MMS Btime4, BTime6 and BTOD conversions to/from STDTIME */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 04/08/08 JRB 03 Chg () to (ST_VOID) in prototype. */ +/* 02/20/08 JRB 02 Add T84_* defines. */ +/* Del TimeOfDay4, Btod, and StdTimeFields functions. */ +/* 10/05/06 RLH 01 Created */ +/*****************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#define T84_HIGHDATETIME 0x01ad63ae /* high word of 1984 FILETIME*/ +#define T84_LOWDATETIME 0xef5a4000 /* low word of 1984 FILETIME*/ + +#if defined(ASN1R_INCLUDED) && defined(MMS_BTOD4) && defined(MMS_BTOD6) +#define STDTIME_MMS_TIMEOFDAY6 MMS_BTIME6 + +#else + +typedef struct + { + int32_t ms; /* milliseconds since midnight */ + int32_t day; /* days since January 1, 1984 */ + } +STDTIME_MMS_TIMEOFDAY6; + +#endif + + + +/*** MmsTimeOfDay4/6 initialization functions ********************************/ + +STDTIME_MMS_TIMEOFDAY6 StdTimeApiZeroMmsTimeOfDay6 (ST_VOID); + +/*** MmsTimeOfDay6Ex functions ***********************************************/ + + +STDTIME_RC StdTimeToMmsTimeOfDay6Ex ( + const STDTIME * /*I*/ pStdTime, + STDTIME_MMS_TIMEOFDAY6 * /*O*/ pMmsTimeOfDay6, + int32_t * /*O*/ pUsec, /* optional */ + int32_t * /*O*/ pNsec); /* optional */ + + +STDTIME_RC MmsTimeOfDay6ExToStdTime ( + const STDTIME_MMS_TIMEOFDAY6 * /*I*/ pMmsTimeOfDay6, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec, + STDTIME * /*O*/ pStdTime); + + +/*** MmsTimeOfDay6 functions *************************************************/ + + +STDTIME_RC StdTimeToMmsTimeOfDay6 ( + const STDTIME * /*I*/ pStdTime, + STDTIME_MMS_TIMEOFDAY6 * /*O*/ pMmsTimeOfDay6); + + +STDTIME_RC MmsTimeOfDay6ToStdTime ( + const STDTIME_MMS_TIMEOFDAY6 * /*I*/ pMmsTimeOfDay6, + STDTIME * /*O*/ pStdTime); + +#ifdef __cplusplus +} +#endif + diff --git a/include/inc/stdtime_mms_utctime.h b/include/inc/stdtime_mms_utctime.h new file mode 100644 index 0000000..1ea703e --- /dev/null +++ b/include/inc/stdtime_mms_utctime.h @@ -0,0 +1,61 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2006 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtime_mms_utctime.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Support for MMS UTC TIME conversions to/from STDTIME */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 04/08/08 JRB 03 Chg () to (ST_VOID) in prototype. */ +/* 02/20/08 JRB 02 Delete StdTimeFields functions. */ +/* 10/05/06 RLH 01 Created */ +/*****************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(ASN1R_INCLUDED) +#define STDTIME_MMS_UTC_TIME MMS_UTC_TIME + +#else + +typedef struct + { + int32_t secs; /* seconds since January 1, 1970 */ + int32_t fraction; /* 24-bit binary fraction of second */ + int32_t qflags; /* 8-bit quality flags */ + } +STDTIME_MMS_UTC_TIME; + +#endif + + +/*** MmsUtcTime initialization function **************************************/ + +STDTIME_MMS_UTC_TIME StdTimeApiZeroMmsUtcTime (ST_VOID); + + +/*** MmsUtcTime functions *************************************************/ + + +STDTIME_RC StdTimeToMmsUtcTime ( + const STDTIME * /*I*/ pStdTime, + STDTIME_MMS_UTC_TIME * /*O*/ pMmsUtcTime); + + +STDTIME_RC MmsUtcTimeToStdTime ( + const STDTIME_MMS_UTC_TIME * /*I*/ pMmsUtcTime, + STDTIME * /*O*/ pStdTime); + +#ifdef __cplusplus +} +#endif + diff --git a/include/inc/stdtime_quadlib.h b/include/inc/stdtime_quadlib.h new file mode 100644 index 0000000..fa45097 --- /dev/null +++ b/include/inc/stdtime_quadlib.h @@ -0,0 +1,1081 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : QuadLib.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* 64-bit Math Simulation Library - header file */ +/* Provided for platforms without native 64-bit support. */ +/* */ +/* When QUADLIB_ENABLED is defined, definitions relevant to the */ +/* simulations library are generated. Otherwise, definitions are */ +/* selected to develop code on 64-bit enabled platforms without going */ +/* through the QuadLib library. */ +/* */ +/* Define QUADLIB_STATIC as 'static' to make the declarations local. */ +/* */ +/* Define QUADLIB_I64N as the native signed 64-bit data type. */ +/* Define QUADLIB_U64N as the native unsigned 64-bit data type. */ +/* If not defined, an assumption is made based on existence of _WIN32. */ +/* */ +/* The include file "host_endian.h" defines the native host endian order. */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 02/22/08 JRB 03 Use SD_BYTE_ORDER like all other SISCO code. */ +/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */ +/* 01/18/06 RLH 01 Created */ +/*****************************************************************************/ + + +#ifndef _STDTIME_QUADLIB_H_B07CB807_8BFC_41B3_872E_EDD251FD6AEB_ +#define _STDTIME_QUADLIB_H_B07CB807_8BFC_41B3_872E_EDD251FD6AEB_ + + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ +/* ENABLED or DISABLED: SUPPORT FOR 64-BIT EMULATION */ +/* */ +/* use StdTimeConfig.h to set QUADLIB_ENABLED or QUADLIB_DISABLED */ +/*****************************************************************************/ + +#if defined(QUADLIB_ENABLED) && defined(QUADLIB_DISABLED) +#error Both QUADLIB_ENABLED and QUADLIB_DISABLED defined +#undef QUADLIB_ENABLED +#endif + +#if !defined(QUADLIB_ENABLED) && !defined(QUADLIB_DISABLED) +#define QUADLIB_DISABLED /* default */ +#endif + +/*****************************************************************************/ +/* ENABLED or DISABLED: EXISTENCE OF 64-BIT SUPPORT IN COMPILER */ +/* */ +/* use StdTimeConfig.h to set QUADLIB_NATIVE64_ENABLED or */ +/* QUADLIB_NATIVE64_DISABLED */ +/*****************************************************************************/ + +/* these defines are used mainly to avoid compile errors on platforms */ +/* that have no support at all for 64-bit types */ + +#if defined(QUADLIB_NATIVE64_ENABLED) && defined(QUADLIB_NATIVE64_DISABLED) +#error Both QUADLIB_NATIVE64_ENABLED and QUADLIB_NATIVE64_DISABLED defined +#undef QUADLIB_NATIVE64_ENABLED +#undef QUADLIB_NATIVE64_DISABLED +#endif + +#if !defined(QUADLIB_NATIVE64_ENABLED) && !defined(QUADLIB_NATIVE64_DISABLED) +#ifdef _WIN32 +#define QUADLIB_NATIVE64_ENABLED +#else +#define QUADLIB_NATIVE64_DISABLED +#endif +#endif + +/*****************************************************************************/ +/* VALIDATE NATIVE SUPPORT VS. EMULATION SUPPORT */ +/*****************************************************************************/ + +/* either the host must support 64-bit mode or we must emulate it */ +/* otherwise, the code that manages 64-bit FILETIME values will not work */ + +#if defined(QUADLIB_DISABLED) && defined(QUADLIB_NATIVE64_DISABLED) +#error QUADLIB_DISABLED and QUADLIB_NATIVE64_DISABLED, cannot generate code +#endif + + +/*****************************************************************************/ +/* STATIC (LOCAL) FUNCTION QUALIFIER */ +/* */ +/* use StdTimeConfig.h to set QUADLIB_STATIC */ +/*****************************************************************************/ + +#ifndef QUADLIB_STATIC +#define QUADLIB_STATIC +#endif + +/* stdtimeconfig.h includes appropriate stdint.h header for 32/64 bit types */ + +#define QUADLIB_U32_HIGHBIT 0x80000000 + +/*****************************************************************************/ +/* NATIVE 64 BIT TYPES */ +/*****************************************************************************/ + +#ifdef QUADLIB_NATIVE64_ENABLED +#define QUADLIB_I64N int64_t +#define QUADLIB_U64N uint64_t + +#else /* not QUADLIB_NATIVE64_ENABLED */ + +/* host has NO 64-bit data types */ +/* the following defines are just for compatibility */ +/* but lack 64-bit capacity. _WIN32 always supports I64 */ +/* so this is just a non-Windows issue. */ + +#ifndef QUADLIB_I64N +#define QUADLIB_I64N int32_t /* 32-bit */ +#endif + +#ifndef QUADLIB_U64N +#define QUADLIB_U64N uint32_t /* 32-bit */ +#endif + +#endif /* QUADLIB_NATIVE64_ENABLED */ + +/*****************************************************************************/ +/* QUADLIB_I64 - hi/lo member ordering based on ENDIAN definition above */ +/* QUADLIB_U64 has the same representation as QUADLIB_I64 */ +/* two names are used mainly to document the intended usage */ +/*****************************************************************************/ + +/* Make sure SD_BYTE_ORDER is defined (in glbtypes.h) */ +#if !defined(SD_BYTE_ORDER) +#error SD_BYTE_ORDER not defined +#endif +#if (SD_BYTE_ORDER==SD_LITTLE_ENDIAN) + +typedef struct + { + union + { + int32_t i; + uint32_t u; + } lo; + + union + { + int32_t i; + uint32_t u; + } hi; + } + QUADLIB_I64_TYPE; + +#else /* BIG_ENDIAN */ + +typedef struct + { + union + { + int32_t i; + uint32_t u; + } hi; + + union + { + int32_t i; + uint32_t u; + } lo; + } + QUADLIB_I64_TYPE; + +#endif /* BIG_ENDIAN */ + +#define QUADLIB_U64_TYPE QUADLIB_I64_TYPE + +#ifdef QUADLIB_ENABLED + +/* enabled means 64-bit operations are simulated in software */ + +#define QUADLIB_I64 QUADLIB_I64_TYPE +#define QUADLIB_U64 QUADLIB_I64_TYPE +#define QUADLIB_ZERO {0,0} +#define QUADLIB_U64_MAX {0xFFFFFFFF, 0xFFFFFFFF} + +#if (SD_BYTE_ORDER==SD_LITTLE_ENDIAN) + +#define QUADLIB_I64_MAX {0xFFFFFFFF, 0x7FFFFFFF} +#define QUADLIB_I64_MIN {0x00000000, 0x80000000} + +#else /* BIG_ENDIAN */ + +#define QUADLIB_I64_MAX {0x7FFFFFFF, 0xFFFFFFFF} +#define QUADLIB_I64_MIN {0x00000000, 0x00000000} + +#endif /* BIG_ENDIAN */ + +#else /* not QUADLIB_ENABLED */ + +/* use native 64-bit values for a few compatibility functions */ + +#define QUADLIB_I64 QUADLIB_I64N +#define QUADLIB_U64 QUADLIB_U64N +#define QUADLIB_ZERO 0 +#define QUADLIB_U64_MAX (QUADLIB_U64)0xFFFFFFFFFFFFFFFF +#define QUADLIB_I64_MAX (QUADLIB_I64)0x7FFFFFFFFFFFFFFF +#define QUADLIB_I64_MIN (QUADLIB_I64)0x8000000000000000 + +#endif /* QUADLIB_ENABLED */ + + +#ifdef _WCHAR_T_DEFINED +typedef wchar_t QUADLIB_WCHAR; +#else +typedef unsigned short QUADLIB_WCHAR; +#endif + +#define QUADLIB_STRING_LEN 20 + + +typedef struct + { + char str [QUADLIB_STRING_LEN+1]; + } +QUADLIB_STRINGA; + + +typedef struct + { + QUADLIB_WCHAR str [QUADLIB_STRING_LEN+1]; + } +QUADLIB_STRINGW; + + +/*****************************************************************************/ +/* NOT */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_NOT(x) QuadLibI64Not(x) +#define QUADLIB_U64_NOT(x) QuadLibU64Not(x) + +#define QuadLibI64Not(x) QuadLibU64Not(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Not (QUADLIB_U64 x); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_NOT(x) (~x) +#define QUADLIB_U64_NOT(x) (~x) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* AND */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_AND(x,y) QuadLibI64And(x,y) +#define QUADLIB_U64_AND(x,y) QuadLibU64And(x,y) +#define QUADLIB_I64_AND_EQ(x,y) x = QuadLibI64And(x,y) +#define QUADLIB_U64_AND_EQ(x,y) x = QuadLibU64And(x,y) + +#define QUADLIB_I64_ANDNOT(x,y) QuadLibI64AndNot(x,y) +#define QUADLIB_U64_ANDNOT(x,y) QuadLibU64AndNot(x,y) +#define QUADLIB_I64_ANDNOT_EQ(x,y) x = QuadLibI64AndNot(x,y) +#define QUADLIB_U64_ANDNOT_EQ(x,y) x = QuadLibU64AndNot(x,y) + +#define QuadLibI64And(x,y) QuadLibU64And(x,y) +#define QuadLibI64AndNot(x) QuadLibU64AndNot(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64And ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64AndNot ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_AND(x,y) (x & y) +#define QUADLIB_U64_AND(x,y) (x & y) +#define QUADLIB_I64_AND_EQ(x,y) x &= y +#define QUADLIB_U64_AND_EQ(x,y) x &= y + +#define QUADLIB_I64_ANDNOT(x,y) (x & (~y)) +#define QUADLIB_U64_ANDNOT(x,y) (x & (~y)) +#define QUADLIB_I64_ANDNOT_EQ(x,y) x = x & (~y) +#define QUADLIB_U64_ANDNOT_EQ(x,y) x = x & (~y) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* OR */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_OR(x,y) QuadLibI64Or(x,y) +#define QUADLIB_U64_OR(x,y) QuadLibU64Or(x,y) +#define QUADLIB_I64_OR_EQ(x,y) x = QuadLibI64Or(x,y) +#define QUADLIB_U64_OR_EQ(x,y) x = QuadLibU64Or(x,y) + +#define QUADLIB_I64_ORNOT(x,y) QuadLibI64OrNot(x,y) +#define QUADLIB_U64_ORNOT(x,y) QuadLibU64OrNot(x,y) +#define QUADLIB_I64_ORNOT_EQ(x,y) x = QuadLibI64OrNot(x,y) +#define QUADLIB_U64_ORNOT_EQ(x,y) x = QuadLibU64OrNot(x,y) + +#define QuadLibI64Or(x,y) QuadLibU64Or(x,y) +#define QuadLibI64OrNot(x) QuadLibU64OrNot(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Or ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64OrNot ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_OR(x,y) (x | y) +#define QUADLIB_U64_OR(x,y) (x | y) +#define QUADLIB_I64_OR_EQ(x,y) x |= y +#define QUADLIB_U64_OR_EQ(x,y) x |= y + +#define QUADLIB_I64_ORNOT(x,y) (x | (~y)) +#define QUADLIB_U64_ORNOT(x,y) (x | (~y)) +#define QUADLIB_I64_ORNOT_EQ(x,y) x = x | (~y) +#define QUADLIB_U64_ORNOT_EQ(x,y) x = x | (~y) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* XOR */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_XOR(x,y) QuadLibI64Xor(x,y) +#define QUADLIB_U64_XOR(x,y) QuadLibU64Xor(x,y) +#define QUADLIB_I64_XOR_EQ(x,y) x = QuadLibI64Xor(x,y) +#define QUADLIB_U64_XOR_EQ(x,y) x = QuadLibU64Xor(x,y) + +#define QUADLIB_I64_XORNOT(x,y) QuadLibI64XorNot(x,y) +#define QUADLIB_U64_XORNOT(x,y) QuadLibU64XorNot(x,y) +#define QUADLIB_I64_XORNOT_EQ(x,y) x = QuadLibI64XorNot(x,y) +#define QUADLIB_U64_XORNOT_EQ(x,y) x = QuadLibU64XorNot(x,y) + +#define QuadLibI64Xor(x,y) QuadLibU64Xor(x,y) +#define QuadLibI64XorNot(x) QuadLibU64XorNot(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Xor ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64XorNot ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_XOR(x,y) (x ^ y) +#define QUADLIB_U64_XOR(x,y) (x ^ y) +#define QUADLIB_I64_XOR_EQ(x,y) x ^= y +#define QUADLIB_U64_XOR_EQ(x,y) x ^= y + +#define QUADLIB_I64_XORNOT(x,y) (x ^ (~y)) +#define QUADLIB_U64_XORNOT(x,y) (x ^ (~y)) +#define QUADLIB_I64_XORNOT_EQ(x,y) x = x ^ (~y) +#define QUADLIB_U64_XORNOT_EQ(x,y) x = x ^ (~y) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* ADD */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_ADD(x,y) QuadLibI64Add(x,y) +#define QUADLIB_U64_ADD(x,y) QuadLibU64Add(x,y) +#define QUADLIB_I64_ADD_EQ(x,y) x = QuadLibI64Add(x,y) +#define QUADLIB_U64_ADD_EQ(x,y) x = QuadLibU64Add(x,y) + +#define QUADLIB_I64_ADD1(x) QuadLibI64Add1(x) +#define QUADLIB_U64_ADD1(x) QuadLibU64Add1(x) +#define QUADLIB_I64_ADD1_EQ(x) x = QuadLibI64Add1(x) +#define QUADLIB_U64_ADD1_EQ(x) x = QuadLibU64Add1(x) + +#define QuadLibI64Add(x,y) QuadLibU64Add(x,y) +#define QuadLibI64Add1(x) QuadLibU64Add1(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Add ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Add1 ( + QUADLIB_U64 /*I*/ x); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_ADD(x,y) (x + y) +#define QUADLIB_U64_ADD(x,y) (x + y) +#define QUADLIB_I64_ADD_EQ(x,y) x += y +#define QUADLIB_U64_ADD_EQ(x,y) x += y + +#define QUADLIB_I64_ADD1(x) (x + y) +#define QUADLIB_U64_ADD1(x) (x + y) +#define QUADLIB_I64_ADD1_EQ(x) x++ +#define QUADLIB_U64_ADD1_EQ(x) x++ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* SUB */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_SUB(x,y) QuadLibI64Sub(x,y) +#define QUADLIB_U64_SUB(x,y) QuadLibU64Sub(x,y) +#define QUADLIB_I64_SUB_EQ(x,y) x = QuadLibI64Sub(x,y) +#define QUADLIB_U64_SUB_EQ(x,y) x = QuadLibU64Sub(x,y) + +#define QUADLIB_I64_SUB1(x) QuadLibI64Sub1(x) +#define QUADLIB_U64_SUB1(x) QuadLibU64Sub1(x) +#define QUADLIB_I64_SUB1_EQ(x) x = QuadLibI64Sub1(x) +#define QUADLIB_U64_SUB1_EQ(x) x = QuadLibU64Sub1(x) + +#define QuadLibI64Sub(x,y) QuadLibU64Sub(x,y) +#define QuadLibI64Sub1(x) QuadLibU64Sub1(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Sub ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Sub1 ( + QUADLIB_U64 /*I*/ x); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_SUB(x,y) (x - y) +#define QUADLIB_U64_SUB(x,y) (x - y) +#define QUADLIB_I64_SUB_EQ(x,y) x -= y +#define QUADLIB_U64_SUB_EQ(x,y) x -= y + +#define QUADLIB_I64_SUB1(x) (x - y) +#define QUADLIB_U64_SUB1(x) (x - y) +#define QUADLIB_I64_SUB1_EQ(x) x-- +#define QUADLIB_U64_SUB1_EQ(x) x-- + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* NEG */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_NEG(x) QuadLibI64Neg(x) +#define QUADLIB_U64_NEG(x) QuadLibU64Neg(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Neg (QUADLIB_U64 x); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_NEG(x) (-x) +#define QUADLIB_U64_NEG(x) (-x) + +#endif /* QUADLIB_ENABLED */ + +#define QuadLibI64Neg(x) QuadLibU64Neg(x) + +/*****************************************************************************/ +/* ABS */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_ABS(x) QuadLibI64Abs(x) +#define QUADLIB_U64_ABS(x) QuadLibU64Abs(x) + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_ABS(x) ((x) >= 0 ? (x) : -(x)) +#define QUADLIB_U64_ABS(x) ((x) >= 0 ? (x) : -(x)) + +#endif /* QUADLIB_ENABLED */ + +#define QuadLibI64Abs(x) QuadLibU64Abs(x) + +/* quad abs function always defined */ + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Abs (QUADLIB_U64 x); + +/*****************************************************************************/ +/* CMP */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_EQ(x,y) QuadLibI64EQ(x,y) +#define QUADLIB_I64_NE(x,y) QuadLibI64NE(x,y) +#define QUADLIB_I64_GT(x,y) QuadLibI64GT(x,y) +#define QUADLIB_I64_GE(x,y) QuadLibI64GE(x,y) +#define QUADLIB_I64_LT(x,y) QuadLibI64LT(x,y) +#define QUADLIB_I64_LE(x,y) QuadLibI64LE(x,y) + +#define QUADLIB_U64_EQ(x,y) QuadLibU64EQ(x,y) +#define QUADLIB_U64_NE(x,y) QuadLibU64NE(x,y) +#define QUADLIB_U64_GT(x,y) QuadLibU64GT(x,y) +#define QUADLIB_U64_GE(x,y) QuadLibU64GE(x,y) +#define QUADLIB_U64_LT(x,y) QuadLibU64LT(x,y) +#define QUADLIB_U64_LE(x,y) QuadLibU64LE(x,y) + +#define QuadLibI64EQ(x,y) (QuadLibI64Cmp(x,y)==0) +#define QuadLibI64NE(x,y) (QuadLibI64Cmp(x,y)!=0) +#define QuadLibI64GT(x,y) (QuadLibI64Cmp(x,y)> 0) +#define QuadLibI64GE(x,y) (QuadLibI64Cmp(x,y)>=0) +#define QuadLibI64LT(x,y) (QuadLibI64Cmp(x,y)< 0) +#define QuadLibI64LE(x,y) (QuadLibI64Cmp(x,y)<=0) + +#define QuadLibU64EQ(x,y) (QuadLibU64Cmp(x,y)==0) +#define QuadLibU64NE(x,y) (QuadLibU64Cmp(x,y)!=0) +#define QuadLibU64GT(x,y) (QuadLibU64Cmp(x,y)> 0) +#define QuadLibU64GE(x,y) (QuadLibU64Cmp(x,y)>=0) +#define QuadLibU64LT(x,y) (QuadLibU64Cmp(x,y)< 0) +#define QuadLibU64LE(x,y) (QuadLibU64Cmp(x,y)<=0) + +QUADLIB_STATIC int32_t QuadLibU64Cmp ( + /*I*/ QUADLIB_U64 x, + /*I*/ QUADLIB_U64 y); + +QUADLIB_STATIC int32_t QuadLibI64Cmp ( + /*I*/ QUADLIB_I64 x, + /*I*/ QUADLIB_I64 y); + +#define QUADLIB_I64_EQ_0(x) (! QUADLIB_I64_NE_0(x)) +#define QUADLIB_I64_NE_0(x) (QUADLIB_U64_HI(x) | QUADLIB_U64_LO(x)) +#define QUADLIB_I64_GT_0(x) (QUADLIB_I64_GE_0(x) && QUADLIB_I64_NE_0(x)) +#define QUADLIB_I64_GE_0(x) (QUADLIB_I64_HI(x) >= 0) +#define QUADLIB_I64_LT_0(x) (QUADLIB_I64_HI(x) < 0) +#define QUADLIB_I64_LE_0(x) (QUADLIB_I64_LT_0(x) || QUADLIB_I64_EQ_0(x)) + +#define QUADLIB_U64_EQ_0(x) (! QUADLIB_U64_NE_0(x)) +#define QUADLIB_U64_NE_0(x) (QUADLIB_U64_HI(x) | QUADLIB_U64_LO(x)) +#define QUADLIB_U64_GT_0(x) (QUADLIB_U64_GE_0(x) && QUADLIB_U64_NE_0(x)) +#define QUADLIB_U64_GE_0(x) (QUADLIB_U64_HI(x) >= 0) + +#if 0 +#define QUADLIB_U64_LT_0(x) (QUADLIB_U64_HI(x) < 0) +#define QUADLIB_U64_LE_0(x) (QUADLIB_U64_LT_0(x) || QUADLIB_U64_EQ_0(x)) +#endif + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_EQ(x,y) ((x) == (y)) +#define QUADLIB_I64_NE(x,y) ((x) != (y)) +#define QUADLIB_I64_GT(x,y) ((x) > (y)) +#define QUADLIB_I64_GE(x,y) ((x) >= (y)) +#define QUADLIB_I64_LT(x,y) ((x) < (y)) +#define QUADLIB_I64_LE(x,y) ((x) <= (y)) + +#define QUADLIB_U64_EQ(x,y) ((x) == (y)) +#define QUADLIB_U64_NE(x,y) ((x) != (y)) +#define QUADLIB_U64_GT(x,y) ((x) > (y)) +#define QUADLIB_U64_GE(x,y) ((x) >= (y)) +#define QUADLIB_U64_LT(x,y) ((x) < (y)) +#define QUADLIB_U64_LE(x,y) ((x) <= (y)) + +#define QUADLIB_I64_EQ_0(x) ((x) == 0) +#define QUADLIB_I64_NE_0(x) ((x) != 0) +#define QUADLIB_I64_GT_0(x) ((x) > 0) +#define QUADLIB_I64_GE_0(x) ((x) >= 0) +#define QUADLIB_I64_LT_0(x) ((x) < 0) +#define QUADLIB_I64_LE_0(x) ((x) <= 0) + +#define QUADLIB_U64_EQ_0(x) ((x) == 0) +#define QUADLIB_U64_NE_0(x) ((x) != 0) +#define QUADLIB_U64_GT_0(x) ((x) > 0) +#define QUADLIB_U64_GE_0(x) ((x) >= 0) + +#if 0 +#define QUADLIB_U64_LT_0(x) ((x) < 0) +#define QUADLIB_U64_LE_0(x) ((x) <= 0) +#endif + +#endif /* QUADLIB_ENABLED */ + + +/*****************************************************************************/ +/* I32 OVERFLOW CHECK */ +/*****************************************************************************/ + + +#define QUADLIB_I64_NOT_OVERFLOW_I32(x) \ + ( ((QUADLIB_I64_HI(x) == 0) && (QUADLIB_I64_LO(x) >= 0)) \ + || ((QUADLIB_I64_HI(x) == -1) && (QUADLIB_I64_LO(x) < 0)) ) /**/ + + +#define QUADLIB_I64_OVERFLOW_I32(x) (! QUADLIB_I64_NOT_OVERFLOW_I32(x)) + + +#define QUADLIB_U64_NOT_OVERFLOW_I32(x) \ + ((QUADLIB_I64_HI(x) == 0) && (QUADLIB_I64_LO(x) >= 0)) /**/ + + +#define QUADLIB_U64_OVERFLOW_I32(x) (! QUADLIB_U64_NOT_OVERFLOW_I32(x)) + + +#define QUADLIB_I64_OVERFLOW_U32(x) (QUADLIB_I64_HI(x) != 0) +#define QUADLIB_U64_OVERFLOW_U32(x) (QUADLIB_I64_HI(x) != 0) + + +/*****************************************************************************/ +/* SHL */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_SHL(x,n) QuadLibU64SHL(x,n) +#define QUADLIB_U64_SHL(x,n) QuadLibU64SHL(x,n) + +#define QUADLIB_I64_SHL1(x) QuadLibU64SHL1(x) +#define QUADLIB_U64_SHL1(x) QuadLibU64SHL1(x) + +#define QUADLIB_I64_SHL4(x) QuadLibU64SHL4(x) +#define QUADLIB_U64_SHL4(x) QuadLibU64SHL4(x) + +#define QUADLIB_I64_SHL_EQ(x,n) x = QUADLIB_I64_SHL(x,n) +#define QUADLIB_U64_SHL_EQ(x,n) x = QUADLIB_U64_SHL(x,n) + +#define QUADLIB_I64_SHL1_EQ(x) x = QUADLIB_I64_SHL1(x) +#define QUADLIB_U64_SHL1_EQ(x) x = QUADLIB_U64_SHL1(x) + +#define QUADLIB_I64_SHL4_EQ(x) x = QUADLIB_I64_SHL4(x) +#define QUADLIB_U64_SHL4_EQ(x) x = QUADLIB_U64_SHL4(x) + +#define QUADLIB_I64_SHL1_EQ_INLINE(x) QUADLIB_U64_SHL1_EQ_INLINE(x) + + +#define QUADLIB_U64_SHL1_EQ_INLINE(x) \ + { \ + x.hi.u <<= 1; \ + if (x.lo.i < 0) \ + { \ + x.hi.u++; \ + } \ + x.lo.u <<= 1; \ + } /**/ + + +#define QUADLIB_I64_SHL4_EQ_INLINE(x) QUADLIB_U64_SHL4_EQ_INLINE(x) + + +#define QUADLIB_U64_SHL4_EQ_INLINE(x) \ + { \ + x.hi.u = (x.hi.u << 4) | (x.lo.u >> 28); \ + x.lo.u <<= 4; \ + } /**/ + + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHL ( + QUADLIB_U64 /*I*/ value, + int32_t /*I*/ shift); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHL1 ( + QUADLIB_U64 /*I*/ value); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHL4 ( + QUADLIB_U64 /*I*/ value); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_SHL(x,n) ((x) << n) +#define QUADLIB_U64_SHL(x,n) ((x) << n) + +#define QUADLIB_I64_SHL1(x) ((x) << 1) +#define QUADLIB_U64_SHL1(x) ((x) << 1) + +#define QUADLIB_I64_SHL4(x) ((x) << 4) +#define QUADLIB_U64_SHL4(x) ((x) << 4) + +#define QUADLIB_I64_SHL_EQ(x,n) x = ((x) << n) +#define QUADLIB_U64_SHL_EQ(x,n) x = ((x) << n) + +#define QUADLIB_I64_SHL1_EQ(x) x <<= 1 +#define QUADLIB_U64_SHL1_EQ(x) x <<= 1 + +#define QUADLIB_I64_SHL1_EQ_INLINE(x) QUADLIB_I64_SHL1_EQ(x) +#define QUADLIB_U64_SHL1_EQ_INLINE(x) QUADLIB_U64_SHL1_EQ(x) + +#define QUADLIB_I64_SHL4_EQ(x) x <<= 4 +#define QUADLIB_U64_SHL4_EQ(x) x <<= 4 + +#define QUADLIB_I64_SHL4_EQ_INLINE(x) QUADLIB_I64_SHL4_EQ(x) +#define QUADLIB_U64_SHL4_EQ_INLINE(x) QUADLIB_U64_SHL4_EQ(x) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* SHR */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_SHR(x,n) QuadLibI64SHR(x,n) +#define QUADLIB_U64_SHR(x,n) QuadLibU64SHR(x,n) + +#define QUADLIB_I64_SHR1(x) QuadLibI64SHR1(x) +#define QUADLIB_U64_SHR1(x) QuadLibU64SHR1(x) + +#define QUADLIB_I64_SHR4(x) QuadLibI64SHR4(x) +#define QUADLIB_U64_SHR4(x) QuadLibU64SHR4(x) + +#define QUADLIB_I64_SHR_EQ(x,n) x = QUADLIB_I64_SHR(x,n) +#define QUADLIB_U64_SHR_EQ(x,n) x = QUADLIB_U64_SHR(x,n) + +#define QUADLIB_I64_SHR1_EQ(x) x = QUADLIB_I64_SHR1(x) +#define QUADLIB_U64_SHR1_EQ(x) x = QUADLIB_U64_SHR1(x) + +#define QUADLIB_I64_SHR4_EQ(x) x = QUADLIB_I64_SHR4(x) +#define QUADLIB_U64_SHR4_EQ(x) x = QUADLIB_U64_SHR4(x) + + +#define QUADLIB_I64_SHR1_EQ_INLINE(x) \ + { \ + x.lo.u >>= 1; \ + if (x.hi.u & 1) \ + { \ + x.lo.u |= QUADLIB_U32_HIGHBIT; \ + } \ + x.hi.i >>= 1; /* signed */ \ + } /**/ + + +#define QUADLIB_U64_SHR1_EQ_INLINE(x) \ + { \ + x.lo.u >>= 1; \ + if (x.hi.u & 1) \ + { \ + x.lo.u |= QUADLIB_U32_HIGHBIT; \ + } \ + x.hi.u >>= 1; /* unsigned */ \ + } /**/ + + +#define QUADLIB_I64_SHR4_EQ_INLINE(x) \ + { \ + x.lo.u = (x.lo.u >> 4) | (x.hi.u << 28); \ + x.hi.i >>= 4; /* signed */ \ + } /**/ + + +#define QUADLIB_U64_SHR4_EQ_INLINE(x) \ + { \ + x.lo.u = (x.lo.u >> 4) | (x.hi.u << 28); \ + x.hi.u >>= 4; /* unsigned */ \ + } /**/ + + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64SHR ( + QUADLIB_U64 /*I*/ value, + int32_t /*I*/ shift); + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64SHR1 ( + QUADLIB_U64 /*I*/ value); + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64SHR4 ( + QUADLIB_U64 /*I*/ value); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHR ( + QUADLIB_U64 /*I*/ value, + int32_t /*I*/ shift); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHR1 ( + QUADLIB_U64 /*I*/ value); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHR4 ( + QUADLIB_U64 /*I*/ value); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_SHR(x,n) ((QUADLIB_I64)x) >> n +#define QUADLIB_U64_SHR(x,n) ((QUADLIB_U64)x) >> n + +#define QUADLIB_I64_SHR1(x) ((QUADLIB_I64)x) >> 1 +#define QUADLIB_U64_SHR1(x) ((QUADLIB_U64)x) >> 1 + +#define QUADLIB_I64_SHR4(x) ((QUADLIB_I64)x) >> 4 +#define QUADLIB_U64_SHR4(x) ((QUADLIB_U64)x) >> 4 + +#define QUADLIB_I64_SHR_EQ(x,n) x = ((QUADLIB_I64)x) >> n +#define QUADLIB_U64_SHR_EQ(x,n) x = ((QUADLIB_U64)x) >> n + +#define QUADLIB_I64_SHR1_EQ(x) x = ((QUADLIB_I64)x) >> 1 +#define QUADLIB_U64_SHR1_EQ(x) x = ((QUADLIB_U64)x) >> 1 + +#define QUADLIB_I64_SHR4_EQ(x) x = ((QUADLIB_I64)x) >> 4 +#define QUADLIB_U64_SHR4_EQ(x) x = ((QUADLIB_U64)x) >> 4 + +#define QUADLIB_I64_SHR1_EQ_INLINE(x) QUADLIB_I64_SHR1_EQ(x) +#define QUADLIB_U64_SHR1_EQ_INLINE(x) QUADLIB_U64_SHR1_EQ(x) + +#define QUADLIB_I64_SHR4_EQ_INLINE(x) QUADLIB_I64_SHR4_EQ(x) +#define QUADLIB_U64_SHR4_EQ_INLINE(x) QUADLIB_U64_SHR4_EQ(x) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* CONVERT */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_CASTI64N(x) QuadLibI64CastI64N(&x,sizeof(x)) +#define QUADLIB_U64_CASTU64N(x) QuadLibU64CastU64N(&x,sizeof(x)) + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64CastI64N(void * x, size_t n); +QUADLIB_STATIC QUADLIB_U64 QuadLibU64CastU64N(void * x, size_t n); + +#define QUADLIB_I64N_CASTI64(x) QuadLibI64NCastI64(x) +#define QUADLIB_U64N_CASTU64(x) QuadLibU64NCastU64(x) + +QUADLIB_STATIC QUADLIB_I64N QuadLibI64NCastI64(QUADLIB_I64 x); +QUADLIB_STATIC QUADLIB_U64N QuadLibU64NCastU64(QUADLIB_U64 x); + + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_CASTI64N(x) ((QUADLIB_I64)x) +#define QUADLIB_U64_CASTU64N(x) ((QUADLIB_U64)x) +#define QUADLIB_I64N_CASTI64(x) ((QUADLIB_I64N)x) +#define QUADLIB_U64N_CASTU64(x) ((QUADLIB_U64N)x) + +#endif /* QUADLIB_ENABLED */ + + +/*****************************************************************************/ +/* CAST */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_CASTI32(x) QuadLibI64CastI32((int32_t)x) +#define QUADLIB_I64_CASTU32(x) QuadLibI64CastI32((uint32_t)x) + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64CastI32 (int32_t x); + +#define QUADLIB_U64_CASTU32(x) QuadLibU64CastU32((uint32_t)x) +#define QUADLIB_U64_CASTI32(x) QuadLibU64CastU32((int32_t)x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64CastU32 (uint32_t x); + +#define QUADLIB_I32_CASTI64(x) QuadLibI32CastI64(x) +#define QUADLIB_U32_CASTI64(x) ((QUADLIB_U64) QuadLibI32CastI64(x)) + +QUADLIB_STATIC int32_t QuadLibI32CastI64 (QUADLIB_I64 x); + +#define QUADLIB_U32_CASTU64(x) QuadLibU32CastU64(x) +#define QUADLIB_I32_CASTU64(x) ((int32_t) QuadLibU32CastU64(x)) + +QUADLIB_STATIC uint32_t QuadLibU32CastU64 (QUADLIB_U64 x); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_CASTI32(x) ((QUADLIB_I64) (x)) +#define QUADLIB_I64_CASTU32(x) ((QUADLIB_I64) (x)) + +#define QUADLIB_U64_CASTI32(x) ((QUADLIB_U64) (x)) +#define QUADLIB_U64_CASTU32(x) ((QUADLIB_U64) (x)) + +#define QUADLIB_I32_CASTI64(x) ((int32_t) (x)) +#define QUADLIB_I32_CASTU64(x) ((int32_t) (x)) + +#define QUADLIB_U32_CASTI64(x) ((uint32_t) (x)) +#define QUADLIB_U32_CASTU64(x) ((uint32_t) (x)) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* GET/SET */ +/*****************************************************************************/ + +#define QUADLIB_I64_HI(x) (*(QUADLIB_I64_TYPE *)(&x)).hi.i +#define QUADLIB_U64_HI(x) (*(QUADLIB_U64_TYPE *)(&x)).hi.u +#define QUADLIB_I64_LO(x) (*(QUADLIB_I64_TYPE *)(&x)).lo.i +#define QUADLIB_U64_LO(x) (*(QUADLIB_U64_TYPE *)(&x)).lo.u + +#define FILETIME_TO_QUADLIB_I64 FILETIME_TO_QUADLIB_U64 + + +#define FILETIME_TO_QUADLIB_U64(f,q) \ + (*(QUADLIB_U64_TYPE *)(q)).lo.u = (f)->dwLowDateTime; \ + (*(QUADLIB_U64_TYPE *)(q)).hi.u = (f)->dwHighDateTime /**/ + + +#define QUADLIB_I64_TO_FILETIME QUADLIB_U64_TO_FILETIME + + +#define QUADLIB_U64_TO_FILETIME(q,f) \ + (f)->dwLowDateTime = (*(QUADLIB_U64_TYPE *)(q)).lo.u; \ + (f)->dwHighDateTime = (*(QUADLIB_U64_TYPE *)(q)).hi.u /**/ + + +/*****************************************************************************/ +/* MUL */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_MUL(x,y) QuadLibI64Mul(x,y) +#define QUADLIB_U64_MUL(x,y) QuadLibU64Mul(x,y) +#define QUADLIB_I64_MUL_EQ(x,y) x = QuadLibI64Mul(x,y) +#define QUADLIB_U64_MUL_EQ(x,y) x = QuadLibU64Mul(x,y) + +#define QUADLIB_I64_MUL10(x) QuadLibI64Mul10(x) +#define QUADLIB_U64_MUL10(x) QuadLibU64Mul10(x) +#define QUADLIB_I64_MUL10_EQ(x) x = QuadLibI64Mul10(x) +#define QUADLIB_U64_MUL10_EQ(x) x = QuadLibU64Mul10(x) + +#define QuadLibI64Mul(x,y) QuadLibU64Mul(x,y) +#define QuadLibI64Mul10(x) QuadLibU64Mul10(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Mul ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Mul10 ( + QUADLIB_U64 /*I*/ x); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_MUL(x,y) (x * y) +#define QUADLIB_U64_MUL(x,y) (x * y) +#define QUADLIB_I64_MUL_EQ(x,y) x *= y +#define QUADLIB_U64_MUL_EQ(x,y) x *= y + +#define QUADLIB_I64_MUL10(x) (x * ((QUADLIB_I64) 10)) +#define QUADLIB_U64_MUL10(x) (x * ((QUADLIB_U64) 10)) +#define QUADLIB_I64_MUL10_EQ(x) x *= ((QUADLIB_I64) 10) +#define QUADLIB_U64_MUL10_EQ(x) x *= ((QUADLIB_U64) 10) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* STR TO I64/U64 */ +/*****************************************************************************/ + +QUADLIB_STATIC QUADLIB_I64 StrAToQuadLibI64 ( + char * /*I*/ str); + +QUADLIB_STATIC QUADLIB_U64 StrAToQuadLibU64 ( + char * /*I*/ str); + +#ifdef QUADLIB_NATIVE64_ENABLED + +#define QUADLIB_I64_NUM(x) (x) +#define QUADLIB_U64_NUM(x) (x) + +#else /* not QUADLIB_NATIVE64_ENABLED */ + +#define QUADLIB_I64_NUM(x) StrAToQuadLibI64 (#x) +#define QUADLIB_U64_NUM(x) StrAToQuadLibU64 (#x) + +#endif /* QUADLIB_NATIVE64_ENABLED */ + + +/*****************************************************************************/ +/* I64/U64 TO STR */ +/*****************************************************************************/ + + +QUADLIB_STATIC void QuadLibU64ToFixedStrA ( + QUADLIB_U64 /*I*/ qValue, + QUADLIB_STRINGA * /*O*/ pString); + + +QUADLIB_STATIC void QuadLibI64ToFixedStrA ( + QUADLIB_I64 /*I*/ qValue, + QUADLIB_STRINGA * /*O*/ pString); + + +QUADLIB_STATIC void QuadLibU64ToStrA ( + QUADLIB_U64 /*I*/ qValue, + QUADLIB_STRINGA * /*O*/ pString); + + +QUADLIB_STATIC void QuadLibI64ToStrA ( + QUADLIB_I64 /*I*/ qValue, + QUADLIB_STRINGA * /*O*/ pString); + + +/*****************************************************************************/ +/* DIV/MOD */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_DIV(x,y) QuadLibI64Div(x,y) +#define QUADLIB_U64_DIV(x,y) QuadLibU64Div(x,y) +#define QUADLIB_I64_DIV_EQ(x,y) x = QuadLibI64Div(x,y) +#define QUADLIB_U64_DIV_EQ(x,y) x = QuadLibU64Div(x,y) + +#define QUADLIB_I64_MOD(x,y) QuadLibI64Mod(x,y) +#define QUADLIB_U64_MOD(x,y) QuadLibU64Mod(x,y) +#define QUADLIB_I64_MOD_EQ(x,y) x = QuadLibI64Mod(x,y) +#define QUADLIB_U64_MOD_EQ(x,y) x = QuadLibU64Mod(x,y) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64DivMod ( + QUADLIB_U64 u64Dividend, + QUADLIB_U64 u64Divisor, + QUADLIB_U64 *pu64Remainder); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Div ( + QUADLIB_U64 u64Dividend, + QUADLIB_U64 u64Divisor); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Mod ( + QUADLIB_U64 u64Dividend, + QUADLIB_U64 u64Divisor); + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64DivMod ( + QUADLIB_I64 s64Dividend, + QUADLIB_I64 s64Divisor, + QUADLIB_I64 *ps64Remainder); + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64Div ( + QUADLIB_I64 s64Dividend, + QUADLIB_I64 s64Divisor); + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64Mod ( + QUADLIB_I64 s64Dividend, + QUADLIB_I64 s64Divisor); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_DIV(x,y) (x / y) +#define QUADLIB_U64_DIV(x,y) (x / y) +#define QUADLIB_I64_DIV_EQ(x,y) x /= y +#define QUADLIB_U64_DIV_EQ(x,y) x /= y + +#define QUADLIB_I64_MOD(x,y) (x % y) +#define QUADLIB_U64_MOD(x,y) (x % y) +#define QUADLIB_I64_MOD_EQ(x,y) x %= y +#define QUADLIB_U64_MOD_EQ(x,y) x %= y + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64DivMod ( + QUADLIB_U64 u64Dividend, + QUADLIB_U64 u64Divisor, + QUADLIB_U64 *pu64Remainder); + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64DivMod ( + QUADLIB_I64 s64Dividend, + QUADLIB_I64 s64Divisor, + QUADLIB_I64 *ps64Remainder); + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* END */ +/*****************************************************************************/ + +#ifdef __cplusplus +} +#endif + + +#endif /* _STDTIME_QUADLIB_H_B07CB807_8BFC_41B3_872E_EDD251FD6AEB_ */ + diff --git a/include/inc/stdtime_stdint.h b/include/inc/stdtime_stdint.h new file mode 100644 index 0000000..8aab3e8 --- /dev/null +++ b/include/inc/stdtime_stdint.h @@ -0,0 +1,237 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : stdint.h */ +/* PLATFORM : Microsoft Windows W32 platform */ +/* PRODUCT(S) : general usage */ +/* */ +/* MODULE DESCRIPTION: */ +/* Implementation of C99 standard header file "stdint.h" */ +/* */ +/* Implementation is based on ISO/IEC 9899:1999 TC2 Programming Language C */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */ +/* 02/25/06 RLH 01 Created */ +/*****************************************************************************/ + +/* STDINT.H for Microsoft Windows */ + + +#ifndef _STDTIME_STDINT_H_1BA49070_CC19_4880_8283_69F38C4F8F59_ +#define _STDTIME_STDINT_H_1BA49070_CC19_4880_8283_69F38C4F8F59_ + + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +#if 1 /*defined() */ +/* +// typedef int8_t char; +// typedef int16_t short; +// typedef int32_t int; + +// typedef uint8_t unsigned char; +// typedef uint16_t unsigned short ; +// typedef uint32_t unsigned int; +*/ +/* exact-wide integer types */ + +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; + +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; + +/* minimum-wide integer types */ + +typedef __int8 int_least8_t; +typedef __int16 int_least16_t; +typedef __int32 int_least32_t; +typedef __int64 int_least64_t; + +typedef unsigned __int8 uint_least8_t; +typedef unsigned __int16 uint_least16_t; +typedef unsigned __int32 uint_least32_t; +typedef unsigned __int64 uint_least64_t; + +/* fastest minimum-wide integer types */ + +typedef __int8 int_fast8_t; +typedef __int16 int_fast16_t; +typedef __int32 int_fast32_t; +typedef __int64 int_fast64_t; + +typedef unsigned __int8 uint_fast8_t; +typedef unsigned __int16 uint_fast16_t; +typedef unsigned __int32 uint_fast32_t; +typedef unsigned __int64 uint_fast64_t; + +/* integer types capable of holding object pointers */ + +/* intptr_t, uintptr_t : see stddef.h */ + +/* greatest-width integer types */ + +typedef __int64 intmax_t; +typedef unsigned __int64 uintmax_t; + +#endif +/* macros for limits of exact-width integer types */ +/* only define in C++ if user-requested per C99 standard */ + +#if (!defined(__cplusplus)) || defined(__STDC_LIMIT_MACROS) + +/* fundamental limits : see limits.h */ + +#define INT8_MIN ((int8_t)(SCHAR_MIN)) +#define INT8_MAX ((int8_t)(SCHAR_MAX)) +#define UINT8_MAX ((uint8_t)(UCHAR_MAX)) + +#define INT16_MIN ((int16_t)(SHRT_MIN)) +#define INT16_MAX ((int16_t)(SHRT_MAX)) +#define UINT16_MAX ((uint16_t)(USHRT_MAX)) + +#define INT32_MIN ((int32_t)(INT_MIN)) +#define INT32_MAX ((int32_t)(INT_MAX)) +#define UINT32_MAX ((uint32_t)(UINT_MAX)) + +#define INT64_MIN ((int64_t)(_I64_MIN)) +#define INT64_MAX ((int64_t)(_I64_MAX)) +#define UINT64_MAX ((uint64_t)(_UI64_MAX)) + +/* limits of minimum-width integer types */ + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define UINT_LEAST8_MAX UINT8_MAX + +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define UINT_LEAST16_MAX UINT16_MAX + +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define UINT_LEAST32_MAX UINT32_MAX + +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* limits of fastest minimum-width integer types */ + +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define UINT_FAST8_MAX UINT8_MAX + +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define UINT_FAST16_MAX UINT16_MAX + +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST64_MAX UINT64_MAX + +/* limits of greatest-width integer types */ + +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +/* limits of other integer types */ + +#ifndef PTRDIFF_MIN +#ifdef _WIN64 +#define PTRDIFF_MIN INT64_MIN +#else +#define PTRDIFF_MIN INT32_MIN +#endif +#endif + +#ifndef PTRDIFF_MAX +#ifdef _WIN64 +#define PTRDIFF_MAX INT64_MAX +#else +#define PTRDIFF_MAX INT32_MAX +#endif +#endif + +#ifndef SIG_ATOMIC_MIN +#define SIG_ATOMIC_MIN INT32_MIN +#endif + +#ifndef SIG_ATOMIC_MAX +#define SIG_ATOMIC_MAX INT32_MAX +#endif + +#ifndef SIZE_MAX +#ifdef _WIN64 +#define SIZE_MAX UINT64_MAX +#else +#define SIZE_MAX UINT32_MAX +#endif +#endif + +#ifndef WCHAR_MIN +#define WCHAR_MIN ((wchar_t)(0)) +#endif + +#ifndef WCHAR_MAX +#define WCHAR_MAX ((wchar_t)(USHRT_MAX)) +#endif + +#ifndef WINT_MIN +#define WINT_MIN ((wint_t)(0)) +#endif + +#ifndef WINT_MAX +#define WINT_MAX ((wint_t)(USHRT_MAX)) +#endif + +#endif /* (!defined(__cplusplus)) || defined(__STDC_LIMIT_MACROS) */ + + +/* macros for minimum-width integer constants */ +/* only define in C++ if user-requested per C99 standard */ + +#if (!defined(__cplusplus)) || defined(__STDC_CONSTANT_MACROS) + +#define INT8_C(x) (int8_t)(x) +#define INT16_C(x) (int16_t)(x) +#define INT32_C(x) (int32_t)(x) +#define INT64_C(x) (int64_t)(x##i64) + +#define UINT8_C(x) (uint8_t)(x##u) +#define UINT16_C(x) (uint16_t)(x##u) +#define UINT32_C(x) (uint32_t)(x##u) +#define UINT64_C(x) (uint64_t)(x##ui64) + +#define INTMAX_C(x) INT64_C(x) +#define UINTMAX_C(x) UINT64_C(x) + +#endif /* (!defined(__cplusplus)) || defined(__STDC_CONSTANT_MACROS) */ + + +#ifdef __cplusplus +} +#endif + +#endif /* _STDTIME_STDINT_H_1BA49070_CC19_4880_8283_69F38C4F8F59_ */ + diff --git a/include/inc/stdtime_timezone_csv.h b/include/inc/stdtime_timezone_csv.h new file mode 100644 index 0000000..cdf2c26 --- /dev/null +++ b/include/inc/stdtime_timezone_csv.h @@ -0,0 +1,381 @@ +{{"ID;CC","STDABBR","STDNAME","DSTABBR","DSTNAME","GMToffset","DSTadjustment","DSTStartDaterule","Starttime","DSTEnddaterule","Endtime"}}, +{{"Africa/Abidjan;CI","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Accra;GH","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Addis_Ababa;ET","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Algiers;DZ","CET","CET","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Asmera;ER","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Bamako;ML","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Bangui;CF","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Banjul;GM","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Bissau;GW","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Blantyre;MW","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Brazzaville;CG","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Bujumbura;BI","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Cairo;EG","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;5;4","+00:00:00","-1;5;9","+00:00:00"}}, +{{"Africa/Casablanca;MA","WET","WET","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Ceuta;ES","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Africa/Conakry;GN","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Dakar;SN","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Dar_es_Salaam;TZ","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Djibouti;DJ","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Douala;CM","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/El_Aaiun;EH","WET","WET","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Freetown;SL","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Gaborone;BW","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Harare;ZW","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Johannesburg;ZA","SAST","SAST","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Kampala;UG","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Khartoum;SD","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Kigali;RW","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Kinshasa;CF","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Lagos;NG","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Libreville;GA","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Lome;TG","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Luanda;AO","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Lubumbashi;CF","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Lusaka;ZM","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Malabo;GQ","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Maputo;MZ","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Maseru;LS","SAST","SAST","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Mbabane;SZ","SAST","SAST","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Mogadishu;SO","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Monrovia;LR","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Nairobi;KE","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Ndjamena;TD","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Niamey;NE","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Nouakchott;MR","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Ouagadougou;BF","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Porto-Novo;BJ","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Sao_Tome;ST","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Timbuktu;ML","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Tripoli;LY","EET","EET","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Tunis;TN","CET","CET","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Windhoek;NA","WAT","WAT","WAST","WAST","+01:00:00","+01:00:00","1;0;9","+02:00:00","1;0;4","+02:00:00"}}, +{{"America/Adak;US/AK","HAST","HAST","HADT","HADT","-10:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Anchorage;US/AK","AKST","AKST","AKDT","AKDT","-09:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Anguilla;AI","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Antigua;AG","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Araguaina;BR","BRT","BRT","BRST","BRST","-03:00:00","+01:00:00","1;0;11","+00:00:00","-1;0;2","+00:00:00"}}, +{{"America/Aruba;AW","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Asuncion;PY","PYT","PYT","PYST","PYST","-04:00:00","+01:00:00","1;0;10","+00:00:00","1;0;3","+00:00:00"}}, +{{"America/Barbados;BB","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Belem;BR","BRT","BRT","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Belize;BZ","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Boa_Vista;BR","AMT","AMT","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Bogota;CO","COT","COT","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Boise;US/ID","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Buenos_Aires;AR","ART","ART","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Cambridge_Bay;CA/NU","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Cancun;MX","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;5","+02:00:00","-1;0;9","+02:00:00"}}, +{{"America/Caracas;VE","VET","VET","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Catamarca;AR","ART","ART","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Cayenne;GF","GFT","GFT","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Cayman;KY","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Chicago;US/IL","CST","Central Standard Time","CDT","Central Daylight Time","-06:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Chihuahua;MX","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;5","+02:00:00","-1;0;9","+02:00:00"}}, +{{"America/Cordoba;AR","ART","ART","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Costa_Rica;CR","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Cuiaba;BR","AMT","AMT","AMST","AMST","-04:00:00","+01:00:00","1;0;11","+00:00:00","-1;0;2","+00:00:00"}}, +{{"America/Curacao;AN","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Danmarkshavn;GL","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Dawson;CA/YT","PST","PST","PDT","PDT","-08:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Dawson_Creek;CA/BC","MST","MST","","","-07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Denver;US/CO","MST","Mountain Standard Time","MDT","Mountain Daylight Time","-07:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Detroit;US/MI","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Dominica;DM","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Edmonton;CA/AB","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Eirunepe;BR","ACT","ACT","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/El_Salvador;SV","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Fortaleza;BR","BRT","BRT","BRST","BRST","-03:00:00","+01:00:00","1;0;11","+00:00:00","-1;0;2","+00:00:00"}}, +{{"America/Glace_Bay;CA/NS","AST","AST","ADT","ADT","-04:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Godthab;GL","WGT","WGT","WGST","WGST","-03:00:00","+01:00:00","-1;6;3","+22:00:00","-1;6;10","+23:00:00"}}, +{{"America/Goose_Bay;CA/NL","AST","AST","ADT","ADT","-04:00:00","+01:00:00","1;0;4","+00:01:00","-1;0;10","+00:01:00"}}, +{{"America/Grand_Turk;TC","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+00:00:00","-1;0;10","+00:00:00"}}, +{{"America/Grenada;GD","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Guadeloupe;GP","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Guatemala;GT","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Guayaquil;EC","ECT","ECT","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Guyana;GY","GYT","GYT","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Halifax;CA/NS","AST","AST","ADT","ADT","-04:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Havana;CU","CST","CST","CDT","CDT","-05:00:00","+01:00:00","1;0;4","+00:00:00","-1;0;10","+01:00:00"}}, +{{"America/Hermosillo;MX","MST","MST","","","-07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Indiana/Indianapolis;US/IN","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Indiana/Knox;US/IN","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Indiana/Marengo;US/IN","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Indiana/Vevay;US/IN","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Indianapolis;US/IN","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Inuvik;CA/NT","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Iqaluit;CA/NU","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Jamaica;JM","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Jujuy;AR","ART","ART","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Juneau;US/AK","AKST","AKST","AKDT","AKDT","-09:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Kentucky/Louisville;US/KY","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Kentucky/Monticello;US/KY","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/La_Paz;BO","BOT","BOT","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Lima;PE","PET","PET","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Los_Angeles;US/CA","PST","Pacific Standard Time","PDT","Pacific Daylight Time","-08:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Louisville;US/KY","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Maceio;BR","BRT","BRT","BRST","BRST","-03:00:00","+01:00:00","1;0;11","+00:00:00","-1;0;2","+00:00:00"}}, +{{"America/Managua;NI","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Manaus;BR","AMT","AMT","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Martinique;MQ","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Mazatlan;MX","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;5","+02:00:00","-1;0;9","+02:00:00"}}, +{{"America/Mendoza;AR","ART","ART","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Menominee;US/MI","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Merida;MX","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;5","+02:00:00","-1;0;9","+02:00:00"}}, +{{"America/Mexico_City;MX","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Miquelon;PM","PMST","PMST","PMDT","PMDT","-03:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Monterrey;MX","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;5","+02:00:00","-1;0;9","+02:00:00"}}, +{{"America/Montevideo;UY","UYT","UYT","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Montreal;CA/QC","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Montserrat;MS","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Nassau;BS","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/New_York;US/NY","EST","Eastern Standard Time","EDT","Eastern Daylight Time","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Nipigon;CA/ON","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Nome;US/AK","AKST","AKST","AKDT","AKDT","-09:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Noronha;BR","FNT","FNT","","","-02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/North_Dakota/Center;US/ND","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Panama;PA","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Pangnirtung;CA/NU","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Paramaribo;SR","SRT","SRT","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Phoenix;US/AZ","MST","Mountain Standard Time","","","-07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Port-au-Prince;HT","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Port_of_Spain;TT","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Porto_Velho;BR","AMT","AMT","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Puerto_Rico;PR","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Rainy_River;CA/ON","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Rankin_Inlet;CA/NU","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Recife;BR","BRT","BRT","BRST","BRST","-03:00:00","+01:00:00","1;0;11","+00:00:00","-1;0;2","+00:00:00"}}, +{{"America/Regina;CA/SK","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Rio_Branco;BR","ACT","ACT","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Rosario;AR","ART","ART","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Santiago;CL","CLT","CLT","CLST","CLST","-04:00:00","+01:00:00","+9;0;10","+00:00:00","+9;0;3","+00:00:00"}}, +{{"America/Santo_Domingo;DO","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Sao_Paulo;BR","BRT","BRT","BRST","BRST","-03:00:00","+01:00:00","1;0;11","+00:00:00","-1;0;2","+00:00:00"}}, +{{"America/Scoresbysund;GL","EGT","EGT","EGST","EGST","-01:00:00","+01:00:00","-1;0;3","+00:00:00","-1;0;10","+01:00:00"}}, +{{"America/Shiprock;US/NM","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/St_Johns;CA/NL","NST","NST","NDT","NDT","-03:30:00","+01:00:00","1;0;4","+00:01:00","-1;0;10","+00:01:00"}}, +{{"America/St_Kitts;KN","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/St_Louis;US/MO","CST","Central Standard Time","CDT","Central Daylight Time","-06:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/St_Lucia;LC","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/St_Thomas;VI","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/St_Vincent;VC","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Swift_Current;CA/SK","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Tegucigalpa;HN","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Thule;GL","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Thunder_Bay;CA/ON","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Tijuana;MX","PST","PST","PDT","PDT","-08:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Toronto;CA/ON","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Tortola;VG","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Vancouver;CA/BC","PST","PST","PDT","PDT","-08:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Whitehorse;CA/YT","PST","PST","PDT","PDT","-08:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Winnipeg;CA/MB","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+03:00:00"}}, +{{"America/Yakutat;US/AK","AKST","AKST","AKDT","AKDT","-09:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Yellowknife;CA/NT","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"Antarctica/Casey;AQ","WST","WST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Antarctica/Davis;AQ","DAVT","DAVT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Antarctica/DumontDUrville;AQ","DDUT","DDUT","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Antarctica/Mawson;AQ","MAWT","MAWT","","","+06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Antarctica/McMurdo;AQ","NZST","NZST","NZDT","NZDT","+12:00:00","+01:00:00","1;0;10","+02:00:00","3;0;3","+03:00:00"}}, +{{"Antarctica/Palmer;AQ","CLT","CLT","CLST","CLST","-04:00:00","+01:00:00","2;0;10","+00:00:00","2;0;3","+00:00:00"}}, +{{"Antarctica/South_Pole;AQ","NZST","NZST","NZDT","NZDT","+12:00:00","+01:00:00","1;0;10","+02:00:00","3;0;3","+03:00:00"}}, +{{"Antarctica/Syowa;AQ","SYOT","SYOT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Antarctica/Vostok;AQ","VOST","VOST","","","+06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Arctic/Longyearbyen;SJ","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Aden;YE","AST","AST","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Almaty;KZ","ALMT","ALMT","ALMST","ALMST","+06:00:00","+01:00:00","-1;0;3","+00:00:00","-1;0;10","+00:00:00"}}, +{{"Asia/Amman;JO","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;4;3","+00:00:00","-1;4;9","+01:00:00"}}, +{{"Asia/Anadyr;RU","ANAT","ANAT","ANAST","ANAST","+12:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Aqtau;KZ","AQTT","AQTT","AQTST","AQTST","+04:00:00","+01:00:00","-1;0;3","+00:00:00","-1;0;10","+00:00:00"}}, +{{"Asia/Aqtobe;KZ","AQTT","AQTT","AQTST","AQTST","+05:00:00","+01:00:00","-1;0;3","+00:00:00","-1;0;10","+00:00:00"}}, +{{"Asia/Ashgabat;TM","TMT","TMT","","","+05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Baghdad;IQ","AST","AST","ADT","ADT","+03:00:00","+01:00:00","1;0;4","+03:00:00","1;0;10","+04:00:00"}}, +{{"Asia/Bahrain;BH","AST","AST","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Baku;AZ","AZT","AZT","AZST","AZST","+04:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+01:00:00"}}, +{{"Asia/Bangkok;TH","ICT","ICT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Beirut;LB","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+00:00:00","-1;0;10","+00:00:00"}}, +{{"Asia/Bishkek;KG","KGT","KGT","KGST","KGST","+05:00:00","+01:00:00","-1;0;3","+02:30:00","-1;0;10","+02:30:00"}}, +{{"Asia/Brunei;BN","BNT","BNT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Calcutta;IN","IST","IST","","","+05:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Choibalsan;MN","CHOT","CHOT","","","+09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Chongqing;CN","CST","CST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Colombo;LK","LKT","LKT","","","+06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Damascus;SY","EET","EET","EEST","EEST","+02:00:00","+01:00:00","1;0;4","+00:00:00","1;0;10","+00:00:00"}}, +{{"Asia/Dhaka;BD","BDT","BDT","","","+06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Dili;TP","TPT","TPT","","","+09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Dubai;AE","GST","GST","","","+04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Dushanbe;TJ","TJT","TJT","","","+05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Gaza;PS","EET","EET","EEST","EEST","+02:00:00","+01:00:00","3;5;4","+00:00:00","3;5;10","+00:00:00"}}, +{{"Asia/Harbin;CN","CST","CST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Hong_Kong;HK","HKT","HKT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Hovd;MN","HOVT","HOVT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Irkutsk;RU","IRKT","IRKT","IRKST","IRKST","+08:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Istanbul;TR","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Asia/Jakarta;ID","WIT","WIT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Jayapura;ID","EIT","EIT","","","+09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Jerusalem;IL","IST","IST","IDT","IDT","+02:00:00","+01:00:00","1;0;4","+01:00:00","1;0;10","+01:00:00"}}, +{{"Asia/Kabul;AF","AFT","AFT","","","+04:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Kamchatka;RU","PETT","PETT","PETST","PETST","+12:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Karachi;PK","PKT","PKT","","","+05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Kashgar;CN","CST","CST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Katmandu;NP","NPT","NPT","","","+05:45:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Krasnoyarsk;RU","KRAT","KRAT","KRAST","KRAST","+07:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Kuala_Lumpur;MY","MYT","MYT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Kuching;MY","MYT","MYT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Kuwait;KW","AST","AST","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Macao;MO","CST","CST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Magadan;RU","MAGT","MAGT","MAGST","MAGST","+11:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Manila;PH","PHT","PHT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Muscat;OM","GST","GST","","","+04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Nicosia;EU/CY","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Asia/Novosibirsk;RU","NOVT","NOVT","NOVST","NOVST","+06:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Omsk;RU","OMST","OMST","OMSST","OMSST","+06:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Phnom_Penh;KH","ICT","ICT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Pontianak;ID","WIT","WIT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Pyongyang;KP","KST","KST","","","+09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Qatar;QA","AST","AST","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Rangoon;MM","MMT","MMT","","","+06:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Riyadh;SA","AST","AST","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Saigon;VN","ICT","ICT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Sakhalin;RU","SAKT","SAKT","SAKST","SAKST","+10:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Samarkand;UZ","UZT","UZT","","","+05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Seoul;KR","KST","KST","","","+09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Shanghai;CN","CST","CST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Singapore;SG","SGT","SGT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Taipei;TW","CST","CST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Tashkent;UZ","UZT","UZT","","","+05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Tbilisi;GE","GET","GET","GEST","GEST","+04:00:00","+01:00:00","-1;0;3","+00:00:00","-1;0;10","+00:00:00"}}, +{{"Asia/Tehran;IR","IRT","IRT","","","+03:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Thimphu;BT","BTT","BTT","","","+06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Tokyo;JP","JST","JST","","","+09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Ujung_Pandang;ID","CIT","CIT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Ulaanbaatar;MN","ULAT","ULAT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Urumqi;CN","CST","CST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Vientiane;LA","ICT","ICT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Vladivostok;RU","VLAT","VLAT","VLAST","VLAST","+10:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Yakutsk;RU","YAKT","YAKT","YAKST","YAKST","+09:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Yekaterinburg;RU","YEKT","YEKT","YEKST","YEKST","+05:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Yerevan;AM","AMT","AMT","AMST","AMST","+04:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Atlantic/Azores;PT","AZOT","AZOT","AZOST","AZOST","-01:00:00","+01:00:00","-1;0;3","+00:00:00","-1;0;10","+01:00:00"}}, +{{"Atlantic/Bermuda;BM","AST","AST","ADT","ADT","-04:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"Atlantic/Canary;ES","WET","WET","WEST","WEST","+00:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+02:00:00"}}, +{{"Atlantic/Cape_Verde;CV","CVT","CVT","","","-01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Atlantic/Faeroe;FO","WET","WET","WEST","WEST","+00:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+02:00:00"}}, +{{"Atlantic/Jan_Mayen;SJ","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Atlantic/Madeira;PT","WET","WET","WEST","WEST","+00:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+02:00:00"}}, +{{"Atlantic/Reykjavik;IS","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Atlantic/South_Georgia;GS","GST","GST","","","-02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Atlantic/St_Helena;SH","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Atlantic/Stanley;FK","FKT","FKT","FKST","FKST","-04:00:00","+01:00:00","1;0;9","+02:00:00","3;0;4","+02:00:00"}}, +{{"Australia/Adelaide;AU","CST","CST","CST","CST","+09:30:00","+01:00:00","-1;0;10","+02:00:00","-1;0;3","+03:00:00"}}, +{{"Australia/Brisbane;AU","EST","EST","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Australia/Broken_Hill;AU","CST","CST","CST","CST","+09:30:00","+01:00:00","-1;0;10","+02:00:00","-1;0;3","+03:00:00"}}, +{{"Australia/Darwin;AU","CST","CST","","","+09:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Australia/Hobart;AU","EST","EST","EST","EST","+10:00:00","+01:00:00","1;0;10","+02:00:00","-1;0;3","+03:00:00"}}, +{{"Australia/Lindeman;AU","EST","EST","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Australia/Lord_Howe;AU","LHST","LHST","LHST","LHST","+10:30:00","+00:30:00","-1;0;10","+02:00:00","-1;0;3","+02:00:00"}}, +{{"Australia/Melbourne;AU","EST","EST","EST","EST","+10:00:00","+01:00:00","-1;0;10","+02:00:00","-1;0;3","+03:00:00"}}, +{{"Australia/Perth;AU","WST","WST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Australia/Sydney;AU","EST","EST","EST","EST","+10:00:00","+01:00:00","-1;0;10","+02:00:00","-1;0;3","+03:00:00"}}, +{{"Europe/Amsterdam;EU/NL","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Andorra;AD","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Athens;EU/GR","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Belfast;IE","GMT","GMT","BST","BST","+00:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+02:00:00"}}, +{{"Europe/Belgrade;CS","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Berlin;EU/DE","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Bratislava;EU/SK","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Brussels;EU/BE","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Bucharest;RO","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Budapest;EU/HU","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Chisinau;MD","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Copenhagen;EU/DK","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Dublin;EU/IE","GMT","GMT","IST","IST","+00:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+02:00:00"}}, +{{"Europe/Gibraltar;GI","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Helsinki;EU/FI","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Istanbul;TR","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Kaliningrad;RU","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Kiev;UA","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Lisbon;EU/PT","WET","WET","WEST","WEST","+00:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+02:00:00"}}, +{{"Europe/Ljubljana;EU/SI","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/London;EU/GB","GMT","GMT","BST","BST","+00:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+02:00:00"}}, +{{"Europe/Luxembourg;EU/LU","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Madrid;EU/ES","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Malta;EU/MT","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Minsk;BY","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Monaco;MC","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Moscow;RU","MSK","MSK","MSD","MSD","+03:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Nicosia;CY","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Oslo;NO","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Paris;EU/FR","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Prague;EU/CZ","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Riga;EU/LV","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Rome;EU/IT","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Samara;RU","SAMT","SAMT","SAMST","SAMST","+04:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/San_Marino;SM","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Sarajevo;BA","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Simferopol;UA","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Skopje;MK","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Sofia;BG","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Stockholm;EU/SE","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Tallinn;EU/EE","EET","EET","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Europe/Tirane;AL","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Uzhgorod;UA","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Vaduz;LI","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Vatican;VA","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Vienna;EU/AT","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Vilnius;EU/LT","EET","EET","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Europe/Warsaw;EU/PL","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Zagreb;HR","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Zaporozhye;UA","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Zurich;CH","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Indian/Antananarivo;MG","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Chagos;IO","IOT","IOT","","","+06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Christmas;CX","CXT","CXT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Cocos;CC","CCT","CCT","","","+06:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Comoro;KM","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Kerguelen;TF","TFT","TFT","","","+05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Mahe;SC","SCT","SCT","","","+04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Maldives;MV","MVT","MVT","","","+05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Mauritius;MU","MUT","MUT","","","+04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Mayotte;YT","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Reunion;RE","RET","RET","","","+04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Apia;WS","WST","WST","","","-11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Auckland;NZ","NZST","NZST","NZDT","NZDT","+12:00:00","+01:00:00","1;0;10","+02:00:00","3;0;3","+03:00:00"}}, +{{"Pacific/Chatham;NZ","CHAST","CHAST","CHADT","CHADT","+12:45:00","+01:00:00","1;0;10","+02:45:00","3;0;3","+03:45:00"}}, +{{"Pacific/Easter;CL","EAST","EAST","EASST","EASST","-06:00:00","+01:00:00","2;6;10","+22:00:00","2;6;3","+22:00:00"}}, +{{"Pacific/Efate;VU","VUT","VUT","","","+11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Enderbury;KI","PHOT","PHOT","","","+13:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Fakaofo;TK","TKT","TKT","","","-10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Fiji;FJ","FJT","FJT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Funafuti;TV","TVT","TVT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Galapagos;EC","GALT","GALT","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Gambier;PF","GAMT","GAMT","","","-09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Guadalcanal;SB","SBT","SBT","","","+11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Guam;GU","ChST","ChST","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Honolulu;US/HI","HST","HST","","","-10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Johnston;UM","HST","HST","","","-10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Kiritimati;KI","LINT","LINT","","","+14:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Kosrae;FM","KOST","KOST","","","+11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Kwajalein;MH","MHT","MHT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Majuro;MH","MHT","MHT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Marquesas;PF","MART","MART","","","-09:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Midway;UM","SST","SST","","","-11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Nauru;NR","NRT","NRT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Niue;NU","NUT","NUT","","","-11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Norfolk;NF","NFT","NFT","","","+11:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Noumea;NC","NCT","NCT","","","+11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Pago_Pago;AS","SST","SST","","","-11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Palau;PW","PWT","PWT","","","+09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Pitcairn;PN","PST","PST","","","-08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Ponape;FM","PONT","PONT","","","+11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Port_Moresby;PG","PGT","PGT","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Rarotonga;CK","CKT","CKT","","","-10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Saipan;MP","ChST","ChST","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Tahiti;PF","TAHT","TAHT","","","-10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Tarawa;KI","GILT","GILT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Tongatapu;TO","TOT","TOT","","","+13:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Truk;FM","TRUT","TRUT","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Wake;UM","WAKT","WAKT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Wallis;WF","WFT","WFT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Yap;FM","YAPT","YAPT","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"US/Michigan;US","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}} diff --git a/include/inc/stdtime_tzrules.h b/include/inc/stdtime_tzrules.h new file mode 100644 index 0000000..30548ad --- /dev/null +++ b/include/inc/stdtime_tzrules.h @@ -0,0 +1,58 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtime_tzrules.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Data file to fix historical rules for daylight saving time. */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 06/07/06 RLH 01 Created */ +/*****************************************************************************/ + +/* this data is part of a table of type STDTIME_FIX_TZ_RULES */ +/* the struct defining type STDTIME_FIX_TZ_RULES is in stdtime.h */ +/* entries with region codes must appear before entries without them */ + + + {"US", "IN", 2007, 9999, {2,0,3}, {1, 2,0,0}, {1,0,11}, {1, 2,0,0}}, + {"US", "IN", 1945, 2006, {0,0,0}, {0, 0,0,0}, {0,0,00}, {0, 0,0,0}}, + {"US", "HI", 1945, 9999, {0,0,0}, {0, 0,0,0}, {0,0,00}, {0, 0,0,0}}, + {"US", "AZ", 1945, 9999, {0,0,0}, {0, 0,0,0}, {0,0,00}, {0, 0,0,0}}, + + {"US", "", 2007, 9999, {2,0,3}, {1, 2,0,0}, {1,0,11}, {1, 2,0,0}}, + {"US", "", 1987, 2006, {1,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"US", "", 1976, 1986, {5,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"US", "", 1975, 1975, {5,0,2}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"US", "", 1974, 1974, {1,0,1}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"US", "", 1967, 1973, {5,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"US", "", 1945, 1966, {5,0,4}, {1, 2,0,0}, {5,0, 9}, {1, 2,0,0}}, + + + {"CA", "SK", 1945, 9999, {0,0,0}, {0, 0,0,0}, {0,0,00}, {0, 0,0,0}}, + + /* for now, CA and MX just duplicate US rules */ + + {"CA", "", 2007, 9999, {2,0,3}, {1, 2,0,0}, {1,0,11}, {1, 2,0,0}}, + {"CA", "", 1987, 2006, {1,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"CA", "", 1976, 1986, {5,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"CA", "", 1975, 1975, {5,0,2}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"CA", "", 1974, 1974, {1,0,1}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"CA", "", 1967, 1973, {5,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"CA", "", 1945, 1966, {5,0,4}, {1, 2,0,0}, {5,0, 9}, {1, 2,0,0}}, + + + {"MX", "", 2007, 9999, {2,0,3}, {1, 2,0,0}, {1,0,11}, {1, 2,0,0}}, + {"MX", "", 1987, 2006, {1,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"MX", "", 1976, 1986, {5,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"MX", "", 1975, 1975, {5,0,2}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"MX", "", 1974, 1974, {1,0,1}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"MX", "", 1967, 1973, {5,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"MX", "", 1945, 1966, {5,0,4}, {1, 2,0,0}, {5,0, 9}, {1, 2,0,0}} /**/ + diff --git a/include/inc/stdtime_w32.h b/include/inc/stdtime_w32.h new file mode 100644 index 0000000..008f58f --- /dev/null +++ b/include/inc/stdtime_w32.h @@ -0,0 +1,353 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtime_w32.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Header file for Standard Time Management Library Win32 Compatibility */ +/* Layer. This header is compiled with STDTIMEW32_ENABLED on Windows to */ +/* generate debugging code or to run emulation on Unix. To run on */ +/* Windows, compile with STDTIMEW32_DISABLED. STDTIMEW32_ENABLED is */ +/* required on Unix/Linux (that is, non-Windows) platforms. */ +/* */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 12/17/07 JRB 04 Del STDTIME_WIN_VARIANT, ..DBTIMESTAMP, ..UDATE */ +/* structs (no longer used). */ +/* 04/03/07 RLH 03 Make UDOT definition compatible with Linux 8.0 */ +/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */ +/* 01/18/06 RLH 01 Created */ +/*****************************************************************************/ + + +#ifndef _STDTIME_W32_H_29560654_4DD5_47A5_9B07_559DA09B36A3_ +#define _STDTIME_W32_H_29560654_4DD5_47A5_9B07_559DA09B36A3_ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*****************************************************************************/ +/* ENABLED or DISABLED */ +/*****************************************************************************/ + +#undef STDTIMEW32_DEBUGGING +#undef STDTIMEW32_UNIX + +#if defined(STDTIMEW32_ENABLED) && defined(STDTIMEW32_DISABLED) +#error Both STDTIMEW32_ENABLED and STDTIMEW32_DISABLED defined +#undef STDTIMEW32_ENABLED +#endif + +#if !defined(STDTIMEW32_ENABLED) && !defined(STDTIMEW32_DISABLED) + +#if defined(STDTIMEW32_USE_CLOCKGETTIME) \ + || defined(STDTIMEW32_USE_GETTIMEOFDAY) \ + || defined(STDTIMEW32_USE_TIMEB) /**/ +#define STDTIMEW32_ENABLED +#else +#define STDTIMEW32_DISABLED +#endif + +#endif + +#if defined(STDTIMEW32_DISABLED) && !defined(_WIN32) +#error StdTime Windows Compatibility Layer disabled on non-Windows platform +#endif + +#if defined(STDTIMEW32_ENABLED) && defined(_WIN32) +#define STDTIMEW32_DEBUGGING +#endif + +#if defined(STDTIMEW32_ENABLED) && !defined(_WIN32) +#define STDTIMEW32_UNIX +#endif + + +/*****************************************************************************/ +/* STATIC (LOCAL) FUNCTION QUALIFIER */ +/*****************************************************************************/ + +#ifndef STDTIMEW32_STATIC +#define STDTIMEW32_STATIC +#endif + + +/*****************************************************************************/ +/* PORTABILITY API NAME DEFINITIONS */ +/*****************************************************************************/ + + +#if defined(STDTIMEW32_USE_CLOCKGETTIME) +#define STDTIME_API_GETSYSTEMTIMEASFILETIME StdTimeW32ClockGetTimeToFileTime + +#elif defined(STDTIMEW32_USE_GETTIMEOFDAY) +#define STDTIME_API_GETSYSTEMTIMEASFILETIME StdTimeW32GetTimeOfDayToFileTime + +#elif defined(STDTIMEW32_USE_TIMEB) +#define STDTIME_API_GETSYSTEMTIMEASFILETIME StdTimeW32TimeBToFileTime + +#else + +#ifdef STDTIMEW32_UNIX +#error No API defined for GetSystemTimeAsFileTime Unix interface +#endif + +#endif /* STDTIMEW32_USE_CLOCKGETTIME */ + + +#ifdef STDTIMEW32_ENABLED +#define STDTIME_API_FILETIMETOLOCALFILETIME StdTimeW32FileTimeToLocalFileTime +#define STDTIME_API_LOCALFILETIMETOFILETIME StdTimeW32LocalFileTimeToFileTime +#else +#define STDTIME_API_FILETIMETOLOCALFILETIME FileTimeToLocalFileTime +#define STDTIME_API_LOCALFILETIMETOFILETIME LocalFileTimeToFileTime +#endif /* STDTIMEW32_ENABLED */ + + +#ifdef STDTIMEW32_ENABLED +#define STDTIME_API_FILETIMETOSYSTEMTIME StdTimeW32FileTimeToSystemTime +#define STDTIME_API_SYSTEMTIMETOFILETIME StdTimeW32SystemTimeToFileTime +#else +#define STDTIME_API_SYSTEMTIMETOFILETIME SystemTimeToFileTime +#define STDTIME_API_FILETIMETOSYSTEMTIME FileTimeToSystemTime +#endif /* STDTIMEW32_ENABLED */ + + +/*****************************************************************************/ +/* BASIC DEFINITIONS */ +/*****************************************************************************/ + + +#define STDTIME_WIN_EPOCH_YEAR 1601 +#define STDTIME_UNIX_EPOCH_YEAR 1970 + +#undef STDTIME_WIN_VT_DATE_DEFINED + +#ifdef _WIN32 + +/* if debugging non-Windows code on Windows, use compatibility typedefs */ + +typedef SHORT STDTIME_WIN_SHORT; +typedef USHORT STDTIME_WIN_USHORT; +typedef WORD STDTIME_WIN_WORD; +typedef DWORD STDTIME_WIN_DWORD; +typedef LONG STDTIME_WIN_LONG; +typedef ULONG STDTIME_WIN_ULONG; +typedef LONGLONG STDTIME_WIN_LONGLONG; +typedef ULONGLONG STDTIME_WIN_ULONGLONG; +typedef BOOL STDTIME_WIN_BOOL; + +#define STDTIME_WIN_TRUE TRUE +#define STDTIME_WIN_FALSE FALSE + + +typedef SYSTEMTIME STDTIME_WIN_SYSTEMTIME; +typedef FILETIME STDTIME_WIN_FILETIME; +typedef LARGE_INTEGER STDTIME_WIN_LARGE_INTEGER; +typedef ULARGE_INTEGER STDTIME_WIN_ULARGE_INTEGER; + +#else /* not _WIN32 */ + +typedef int16_t STDTIME_WIN_SHORT; +typedef uint16_t STDTIME_WIN_USHORT; +typedef uint16_t STDTIME_WIN_WORD; +typedef uint32_t STDTIME_WIN_DWORD; +typedef int32_t STDTIME_WIN_LONG; +typedef uint32_t STDTIME_WIN_ULONG; +typedef QUADLIB_I64 STDTIME_WIN_LONGLONG; +typedef QUADLIB_U64 STDTIME_WIN_ULONGLONG; +typedef int32_t STDTIME_WIN_BOOL; + +#define STDTIME_WIN_TRUE 1 +#define STDTIME_WIN_FALSE 0 + + +#endif /* _WIN32 */ + + +/*****************************************************************************/ +/* SYSTEMTIME structure - compatibility definition */ +/*****************************************************************************/ + +#ifdef STDTIMEW32_UNIX + +typedef struct + { + STDTIME_WIN_WORD wYear; + STDTIME_WIN_WORD wMonth; + STDTIME_WIN_WORD wDayOfWeek; + STDTIME_WIN_WORD wDay; + STDTIME_WIN_WORD wHour; + STDTIME_WIN_WORD wMinute; + STDTIME_WIN_WORD wSecond; + STDTIME_WIN_WORD wMilliseconds; + } STDTIME_WIN_SYSTEMTIME; + +#endif /* STDTIMEW32_UNIX */ + + +/*****************************************************************************/ +/* VT_DATE compatibility definitions */ +/*****************************************************************************/ + +#ifndef STDTIME_WIN_VT_DATE_DEFINED + +typedef uint16_t STDTIME_WIN_VARTYPE; +typedef double STDTIME_WIN_DATE; + +enum STDTIME_WIN_VARENUM + { + STDTIME_WIN_VT_EMPTY = 0, + STDTIME_WIN_VT_DATE = 7, + STDTIME_WIN_VT_BYREF = 0x4000 + }; + +#endif /* STDTIME_WIN_VT_DATE_DEFINED */ + +/*****************************************************************************/ +/* FILETIME structure - compatibility definition */ +/*****************************************************************************/ + +#ifdef STDTIMEW32_UNIX + +typedef struct + { + STDTIME_WIN_DWORD dwLowDateTime; + STDTIME_WIN_DWORD dwHighDateTime; + } STDTIME_WIN_FILETIME; + +#endif /* STDTIMEW32_UNIX */ + +/*****************************************************************************/ +/* LARGE_INTEGER structure - compatibility definition */ +/*****************************************************************************/ + +#ifdef STDTIMEW32_UNIX + +typedef union _STDTIME_WIN_LARGE_INTEGER + { + /* to maximize compatibility, the anonymous struct is omitted */ + /* references to LARGE_INTEGER fields will require 'u' qualifier */ + /* use of the anonymous struct is a non-portable Microsoft extension. */ + + /* the order of LowPart and HighPart should agree with endian */ + /* ordering on the host platform */ + + /* if compiled under I64 compatibility, QuadPart is a QuadLib structure */ + /* QUADLIB_I64 and QUADLIB_U64 are the same type, but have different */ + /* names to document their intended usage */ + + struct + { + STDTIME_WIN_DWORD LowPart; + STDTIME_WIN_LONG HighPart; + } u; + + QUADLIB_I64 QuadPart; + + } STDTIME_WIN_LARGE_INTEGER; + +#endif /* STDTIMEW32_UNIX */ + +/*****************************************************************************/ +/* ULARGE_INTEGER structure - compatibility definition */ +/*****************************************************************************/ + +#ifdef STDTIMEW32_UNIX + +typedef union _STDTIME_WIN_ULARGE_INTEGER + { + /* to maximize compatibility, the anonymous struct is omitted */ + /* references to ULARGE_INTEGER fields will require 'u' qualifier */ + /* use of the anonymous struct is a non-portable Microsoft extension. */ + + /* the order of LowPart and HighPart should agree with endian */ + /* ordering on the host platform */ + + /* if compiled under I64 compatibility, QuadPart is a QuadLib structure */ + /* QUADLIB_I64 and QUADLIB_U64 are the same type, but have different */ + /* names to document their intended usage */ + + struct + { + STDTIME_WIN_DWORD LowPart; + STDTIME_WIN_DWORD HighPart; + } u; + + QUADLIB_U64 QuadPart; + + } STDTIME_WIN_ULARGE_INTEGER; + +#endif /* STDTIMEW32_UNIX */ + + +/*****************************************************************************/ +/* compatibility-layer API functions */ +/*****************************************************************************/ + +#ifndef STDTIME_API_GETSYSTEMTIMEASFILETIME +#define STDTIME_API_GETSYSTEMTIMEASFILETIME GetSystemTimeAsFileTime + +#else +STDTIMEW32_STATIC void STDTIME_API_GETSYSTEMTIMEASFILETIME ( + STDTIME_WIN_FILETIME * /*O*/ pFileTime); +#endif + + +#ifdef STDTIMEW32_ENABLED + + +STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32SystemTimeToFileTime ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + STDTIME_WIN_FILETIME * /*O*/ pFileTime); + + +STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32FileTimeToSystemTime ( + const STDTIME_WIN_FILETIME * /*I*/ pFileTime, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime); + + +STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32FileTimeToLocalFileTime ( + const STDTIME_WIN_FILETIME * /*I*/ pGmtFileTime, + STDTIME_WIN_FILETIME * /*O*/ pLocFileTime); + + +STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32LocalFileTimeToFileTime ( + const STDTIME_WIN_FILETIME * /*I*/ pLocFileTime, + STDTIME_WIN_FILETIME * /*O*/ pGmtFileTime); + + +#endif /* STDTIMEW32_ENABLED */ + + +/*****************************************************************************/ +/* OBTAIN DAY OF WEEK AND DAY OF WEEK */ +/*****************************************************************************/ + +STDTIME_RC StdTimeW32GetDayofWeekAndYear ( + int32_t /*I*/ nYear, + int32_t /*I*/ nMon, + int32_t /*I*/ nDayofMon, + int32_t * /*O*/ pDayofWeek, + int32_t * /*O*/ pDayofYear); + +/*****************************************************************************/ +/* END */ +/*****************************************************************************/ + +#ifdef __cplusplus +} +#endif + + +#endif /* _STDTIME_W32_H_29560654_4DD5_47A5_9B07_559DA09B36A3_ */ + diff --git a/include/inc/stime.h b/include/inc/stime.h new file mode 100644 index 0000000..303d53f --- /dev/null +++ b/include/inc/stime.h @@ -0,0 +1,38 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved */ +/* */ +/* MODULE NAME : stime.h */ +/* PRODUCT(S) : SLOG */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/14/05 EJV 03 Del sGetMsStartTime, sSetMsStartTime */ +/* 11/04/03 JRB 02 Add sMsSleep (replaces gs_sleep). */ +/* 11/05/97 DSF 01 Added sGetSysMsTime () */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +ST_RET stimeInit (ST_VOID); +ST_DOUBLE sGetMsTime (ST_VOID); +ST_DOUBLE sGetSysMsTime (ST_VOID); +ST_VOID sResetMsTime (ST_VOID); +ST_VOID stimeExit (ST_VOID); +ST_VOID sMsSleep (ST_LONG ms); + +#ifdef __cplusplus +} +#endif + diff --git a/include/inc/sx_arb.h b/include/inc/sx_arb.h new file mode 100644 index 0000000..907a8a1 --- /dev/null +++ b/include/inc/sx_arb.h @@ -0,0 +1,119 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999 - 2004, All Rights Reserved */ +/* */ +/* MODULE NAME : sx_arb.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/19/07 JRB 04 Add TEXT_FORMAT_COMMA, sxaTextToLocalEx. */ +/* 10/24/06 JRB 03 Add sxaLocalToText2 proto. */ +/* 12/06/04 JRB 02 Add "sx_defs.h". */ +/* 08/30/04 DSF 01 Module created */ +/************************************************************************/ +/************************************************************************/ + +#ifndef SX_ARB_INCLUDED +#define SX_ARB_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************************************/ + +#include "mms_def2.h" +#include "mms_mp.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "sx_defs.h" /* need SX_ENC_CTRL */ + +ST_RET sxd_decode_rtdata_el (SD_CONST ST_CHAR *elName, + ST_CHAR *xml, ST_INT xmlLen, ST_INT *xmlUsed, + ST_VOID *vdp, SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, ST_BOOLEAN *elPres, + ST_INT sxdXmlStyle, ST_BOOLEAN checkDt); +ST_RET sxd_wr_rtdata (SX_ENC_CTRL *sxEncCtrl, RUNTIME_TYPE *rt, ST_INT numRt, + ST_CHAR *elName, ST_VOID *data, ST_INT sxdXmlStyle, + ST_BOOLEAN encodeDt, ST_BOOLEAN *elPres); + +/************************************************************************/ +/************************************************************************/ +/* Arbitrary data processing, for use in traversing the RUNTIME_TYPE */ + +typedef struct + { + ST_RET (*arrStart) (ST_VOID *usr, RUNTIME_TYPE *rt); + ST_RET (*arrEnd) (ST_VOID *usr, RUNTIME_TYPE *rt); + ST_RET (*strStart) (ST_VOID *usr, RUNTIME_TYPE *rt, SD_CONST RUNTIME_TYPE *rt_head); + ST_RET (*strEnd) (ST_VOID *usr, RUNTIME_TYPE *rt); + ST_RET (*int8) (ST_VOID *usr, ST_INT8 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*int16) (ST_VOID *usr, ST_INT16 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*int32) (ST_VOID *usr, ST_INT32 *data_dest, RUNTIME_TYPE *rt); +#ifdef INT64_SUPPORT + ST_RET (*int64) (ST_VOID *usr, ST_INT64 *data_dest, RUNTIME_TYPE *rt); +#endif + ST_RET (*uint8) (ST_VOID *usr, ST_UINT8 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*uint16) (ST_VOID *usr, ST_UINT16 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*uint32) (ST_VOID *usr, ST_UINT32 *data_dest, RUNTIME_TYPE *rt); +#ifdef INT64_SUPPORT + ST_RET (*uint64) (ST_VOID *usr, ST_UINT64 *data_dest, RUNTIME_TYPE *rt); +#endif + ST_RET (*flt) (ST_VOID *usr, ST_FLOAT *data_dest, RUNTIME_TYPE *rt); + ST_RET (*dbl) (ST_VOID *usr, ST_DOUBLE *data_dest, RUNTIME_TYPE *rt); + ST_RET (*oct) (ST_VOID *usr, ST_UCHAR *data_dest, RUNTIME_TYPE *rt); + ST_RET (*booln) (ST_VOID *usr, ST_BOOLEAN *data_dest, RUNTIME_TYPE *rt); + ST_RET (*bcd1) (ST_VOID *usr, ST_INT8 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*bcd2) (ST_VOID *usr, ST_INT16 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*bcd4) (ST_VOID *usr, ST_INT32 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*bs) (ST_VOID *usr, ST_UCHAR *data_dest, RUNTIME_TYPE *rt); + ST_RET (*vis) (ST_VOID *usr, ST_CHAR *data_dest, RUNTIME_TYPE *rt); + ST_RET (*bt4) (ST_VOID *usr, ST_INT32 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*bt6) (ST_VOID *usr, ST_INT32 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*gt) (ST_VOID *usr, time_t *data_dest, RUNTIME_TYPE *rt); + ST_RET (*utc) (ST_VOID *usr, MMS_UTC_TIME *data_dest, RUNTIME_TYPE *rt); + ST_RET (*utf8) (ST_VOID *usr, ST_UCHAR *data_dest, RUNTIME_TYPE *rt); + } SXD_ARB_DATA_CTRL; + +ST_RET sxd_process_arb_data (ST_CHAR *datptr, SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, ST_VOID *usr, + SXD_ARB_DATA_CTRL *ac, ST_BOOLEAN *elPres); + +ST_RET sxaTextToLocal (ST_CHAR *pSource, ST_VOID *pDest, ST_INT numRt, SD_CONST RUNTIME_TYPE *rtHead); +ST_CHAR *sxaLocalToText (ST_VOID *dataPtr, SD_CONST RUNTIME_TYPE *rtHead, ST_INT numRt); +/* sxaLocalToText2 is thread-safe (does not use global buffer). */ +ST_CHAR *sxaLocalToText2 (ST_VOID *dataPtr, SD_CONST RUNTIME_TYPE *rtHead, ST_INT numRt, + ST_CHAR *textBuf, /* User buffer in which to write text */ + ST_UINT textBufSize); /* size of user buffer */ + +/* Defines to use for textFormat argument of sxaTextToLocalEx. */ +/* DEBUG: currently only ONE format supported (TEXT_FORMAT_COMMA), but */ +/* this should make it easier to add other formats later. */ +#define TEXT_FORMAT_COMMA 1 /* Comma-separated text format */ + /* Each value in the text may */ + /* also be surrounded by "". */ + /* Examples of text: */ + /* "0","1.1","2","3.3","4" */ + /* 0,1.1,2,3.3,4 */ +ST_RET sxaTextToLocalEx ( + ST_CHAR *pSource, /* source text */ + ST_VOID *pDest, /* destination data */ + ST_INT numRt, + SD_CONST RUNTIME_TYPE *rtHead, + ST_INT textFormat); /* text format from which to convert */ + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* SX_ARB_INCLUDED */ diff --git a/include/inc/sx_defs.h b/include/inc/sx_defs.h new file mode 100644 index 0000000..e6ee545 --- /dev/null +++ b/include/inc/sx_defs.h @@ -0,0 +1,611 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999 - 2008, All Rights Reserved */ +/* */ +/* MODULE NAME : sx_defs.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/01/08 EJV 66 Added SX_PARSING_OK, sx_err_str* (for slogs).*/ +/* 01/14/08 MDE 65 Fixed numOcc multithread problem */ +/* 07/30/07 RWM 64 Added numAlloced4 to sx_dec_ctrl */ +/* For early MODLOGS see previous revision of this file on PVCS. */ +/************************************************************************/ + +#ifndef SX_DEFS_INCLUDED +#define SX_DEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************************************/ + +#include "glbtypes.h" + +/************************************************************************/ +/* This is the amount of overhead required to ensure no overwrite */ + +#define SX_ENC_BUFFER_OH 20 + +/************************************************************************/ +/* Capacities */ + +#if !defined(SX_MAX_XML_NEST) +#define SX_MAX_XML_NEST 30 +#endif + +#if !defined(SX_MAX_STACK_LEVEL) +#define SX_MAX_STACK_LEVEL 50 +#endif + +#if !defined(SX_MAX_TAG_LEN) +#define SX_MAX_TAG_LEN 100 +#endif + +#if !defined(SX_MAX_ATTRIB) +#define SX_MAX_ATTRIB 20 +#endif + +#if !defined(SX_MAX_ATTR_NAME) +#define SX_MAX_ATTR_NAME 100 +#endif + +#if !defined(SX_MAX_ATTR_VALUE) +#define SX_MAX_ATTR_VALUE 1000 +#endif + +#if !defined(SX_MAX_ELEM_LEN) +#define SX_MAX_ELEM_LEN 2000 +#endif + +#if !defined SX_MAX_ITEMS_PER_TABLE +#define SX_MAX_ITEMS_PER_TABLE 50 +#endif + + +/************************************************************************/ +/* Error codes - stop parsing */ +#define SX_PARSING_OK 0 +#define SX_USER_ERROR 1 +#define SX_STRUCT_NOT_FOUND 2 +#define SX_REQUIRED_TAG_NOT_FOUND 3 +#define SX_DUPLICATE_NOT_ALLOWED 4 +#define SX_EMPTY_TAG_NOT_ALLOWED 5 +#define SX_XML_NEST_TOO_DEEP 6 +#define SX_XML_BUFFER_OVER_MAX 7 +#define SX_XML_MALFORMED 8 +#define SX_FILE_NOT_FOUND 9 +#define SX_END_PARSING 10 /* for partial parsing */ +#define SX_ELEMENT_TBL_TOO_BIG 11 +/* NOTE: when adding more error codes update also the sx_err_str[] in the sx_dec.c */ + +/* Normal errors - continue with parse */ +#define SX_ERR_CONVERT 100 + +#ifdef DEBUG_SISCO +extern ST_CHAR *sx_err_str[]; /* tbl of error strings, used in slogs */ +extern ST_INT sx_err_str_cnt; + +/* macro to get the error string logged */ +#define SX_ERR_STR(errCode) ((errCode < sx_err_str_cnt) ? sx_err_str[errCode] : "UNKNOWN SX ERROR") +#endif /* DEBUG_SISCO */ + +/************************************************************************/ +/************************************************************************/ +/* SX_DURATION */ +/* Duration is an ISO 8601 date/time standard in the following format: */ +/* PnYnMnDTnHnMnS */ +/* where P = period, Y = years, M = months, D = days, T = date/time */ +/* seperator, H = hours, M = minutes, S = seconds. Seconds may be any */ +/* decimal number of arbitrary precision. n represents a number. */ +/* For example: or */ +/* */ +typedef struct sx_duration + { + ST_BOOLEAN negative; /* true = negative duration */ + ST_INT years; /* number of years in duration */ + ST_INT months; /* number of months in duration */ + ST_INT days; /* number of days in duration */ + ST_INT hours; /* number of hours in duration */ + ST_INT minutes; /* number of minutes in duration */ + ST_INT seconds; /* integer part of seconds */ + ST_LONG microseconds; /* decimal part of seconds */ + ST_BOOLEAN inUse; /* easy way to tell if this optional */ + /* attribute is present */ + } SX_DURATION; + +/************************************************************************/ +/************************************************************************/ +/* SX_DATE_TIME */ + +typedef struct sx_date_time + { + time_t dateTime; /* number of local or UTC/GMT/Zule seconds since 1/1/1970 */ + long microseconds; /* decimal fraction or microseconds */ + int tz; /* minutes specified in time zone "+hh:mm or -hh:mm" */ + ST_BOOLEAN useMicroseconds; /* indicates decimal fraction of microseconds is present */ + ST_BOOLEAN useTZ; /* if true "yyyy-mm-ddThh:mm:ss.fffff+/-hh:mm" or */ + /* "yyyy-mm-ddThh:mm:ss+/-hh:mm" or */ + /* "yyyy-mm-ddThh:mm:ss.fffffZ" or */ + /* "yyyy-mm-ddThh:mm:ssZ" */ + /* if false "yyyy-mm-ddThh:mm:ss.fffff or */ + /* "yyyy-mm-ddThh:mm:ss */ + } SX_DATE_TIME; + +/************************************************************************/ +/************************************************************************/ +/* XML <-> Local XML Style Selection */ + +/* Note: Style A must have the value 0 */ +#define SXD_XML_STYLE_A 0 /* Values as attrib, single element/struct */ +#define SXD_XML_STYLE_C 1 /* CDATA value encoding */ +#define SXD_XML_STYLE_V 2 /* Each value has own element, attrib encoded */ + +extern ST_INT sxdDefXmlStyle; /* Note: 0 is style A */ + +/* Examples: */ +/* A: */ +/* A: */ + +/* C: 1248044 */ +/* C: BinFull78Good */ + +/* V: */ +/* V: */ + +/************************************************************************/ +/************************************************************************/ +extern ST_BOOLEAN sxUseSax; +extern ST_BOOLEAN sxUseFormatting; +extern ST_BOOLEAN sxIgnoreNS; +extern ST_BOOLEAN sxLogOverrunAsFlow; + +/* elementFlags defines; bitmasked */ +#define SX_ELF_CSTART 0x0001 +#define SX_ELF_CEND 0x0002 +#define SX_ELF_CSTARTEND 0x0003 + +#define SX_ELF_RPT 0x0008 +#define SX_ELF_OPT 0x0004 +#define SX_ELF_OPTRPT 0x000C + +#define SX_ELF_EMPTYOK 0x0010 + +struct sx_dec_ctrl; /* forward definition */ + +typedef struct sx_element + { + char *tag; + ST_INT elementFlags; + void (*funcPtr)(struct sx_dec_ctrl *sxDecCtrl); + + char *user; + +/* Runtime elements: */ + ST_INT notUsed; + } SX_ELEMENT; + +/************************************************************************/ + +/* defines for string formatting */ +#define CODE_APOS "'" +#define CODE_QUOT """ +#define CODE_AMP "&" +#define CODE_LT "<" +#define CODE_GT ">" + +#define CODE_APOS_LEN (sizeof (CODE_APOS) - 1) +#define CODE_QUOT_LEN (sizeof (CODE_QUOT) - 1) +#define CODE_AMP_LEN (sizeof (CODE_AMP) - 1) +#define CODE_LT_LEN (sizeof (CODE_LT) - 1) +#define CODE_GT_LEN (sizeof (CODE_GT) - 1) + +#define CHAR_APOS '\'' +#define CHAR_QUOT '\"' +#define CHAR_AMP '&' +#define CHAR_LT '<' +#define CHAR_GT '>' + +/************************************************************************/ + +/* defines for 'reason' */ +#define SX_ELEMENT_START 1 +#define SX_ELEMENT_END 2 + + +typedef struct sx_element_tbl_ctrl + { + ST_INT numItems; + SX_ELEMENT *itemTbl; + ST_INT numOccTbl[SX_MAX_ITEMS_PER_TABLE]; + } SX_ELEMENT_TBL_CTRL; + +typedef struct sxe_attr_pair + { + ST_CHAR *name; + ST_CHAR *value; + } SXE_ATTR_PAIR; + +typedef struct sxd_attr_pair + { + ST_CHAR name[SX_MAX_ATTR_NAME]; + ST_CHAR value[SX_MAX_ATTR_VALUE]; + } SXD_ATTR_PAIR; + +typedef struct sx_dec_element_info + { + ST_CHAR tag[SX_MAX_TAG_LEN]; /* start/end */ + ST_CHAR *tagStart; /* tag start pointer */ + /* NOTE: "entityStart" is NOT used if USE_EXPAT defined */ + ST_CHAR *entityStart; /* start (and simple end) */ + ST_UINT attrCount; /* start (and simple end) */ + SXD_ATTR_PAIR attr[SX_MAX_ATTRIB]; /* start (and simple end) */ + /* NOTE: "entityEnd" is NOT used if USE_EXPAT defined */ + ST_CHAR *entityEnd; /* end */ + } SX_DEC_ELEMENT_INFO; + +typedef struct sx_dec_ctrl + { + /* NOTE: the following five params are used ONLY if USE_EXPAT defined */ + ST_VOID *parser; /* save XML_Parser here (cast to (ST_VOID *)) */ + ST_INT skipNestLevel; /* skip tags until back at this nest level */ + ST_INT entityLen; /* len of current entity */ + ST_INT entityBufSize; /* len of entity buffer */ + ST_CHAR *entityBuf; /* ptr to entity buffer */ + +/* XML being decoded */ + ST_CHAR *xmlStart; + ST_INT xmlLen; + + ST_BOOLEAN useFp; + ST_BOOLEAN ignoreNS; + FILE *fp; +/* Decoded element information */ + ST_INT reason; /* SX_ELEMENT_START, SX_ELEMENT_END */ + SX_DEC_ELEMENT_INFO sxDecElInfo; + ST_CHAR elemBuf[SX_MAX_ELEM_LEN+1]; /* tmp buffer for an element */ + +/* Set to != SD_SUCCESS for error */ + ST_RET errCode; /* defined above */ + ST_BOOLEAN termFlag; /* set if you want to terminate decode */ + +/* Set to SD_TRUE to disable numOcc checks */ + ST_BOOLEAN noOccCheck; + +/* Internal use */ + SX_ELEMENT *item; + ST_INT itemStackLevel; + SX_ELEMENT_TBL_CTRL items[SX_MAX_STACK_LEVEL]; + ST_BOOLEAN auto_pop[SX_MAX_STACK_LEVEL]; + + ST_INT xmlNestLevel; + SX_ELEMENT *elTbl[SX_MAX_XML_NEST]; + /* NOTE: "xmlPos" is NOT used if USE_EXPAT defined */ + ST_CHAR *xmlPos; + + ST_INT numAlloced; /* Used to keep track of dynamically allocated message buffers */ + ST_INT numAlloced2; + ST_INT numAlloced3; + ST_INT numAlloced4; + +/* User fields */ + ST_VOID *usr; + ST_VOID *elUser; + ST_VOID *unkElUser; + + /* The initial values for these pointers are passed to the functions */ + /* sx_parse_mt or sx_parseEx_mt. */ + ST_RET (*u_sx_el_start) (struct sx_dec_ctrl *sxDecCtrl, ST_CHAR *tag); + ST_RET (*u_sx_el_end) (struct sx_dec_ctrl *sxDecCtrl, ST_CHAR *tag); + } SX_DEC_CTRL ; + +/************************************************************************/ + +#define SX_PUSH(itemTbl)\ + sx_push (sxDecCtrl, sizeof(itemTbl)/sizeof(SX_ELEMENT), itemTbl, SD_TRUE) + +/* Thread safe versions of XML parsing */ +/* They are using the u_sx_el_xxx defined in the SX_DEC_CTRL) */ +ST_RET sx_parse_mt (ST_LONG lMsgLen, ST_CHAR *xml, ST_INT numItems, + SX_ELEMENT *itemTbl, ST_VOID *usr, + ST_RET (*u_sx_el_start_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag), + ST_RET (*u_sx_el_end_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag)); +ST_RET sx_parseEx_mt (ST_CHAR *fileName, ST_INT numItems, + SX_ELEMENT *itemTbl, ST_VOID *usr, + ST_RET (*u_sx_el_start_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag), + ST_RET (*u_sx_el_end_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag)); +ST_RET sx_parseExx_mt (ST_CHAR *fileName, ST_INT numItems, + SX_ELEMENT *itemTbl, ST_VOID *usr, + ST_RET (*u_sx_el_start_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag), + ST_RET (*u_sx_el_end_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag)); + +ST_VOID sx_push (SX_DEC_CTRL *sxDecCtrl, ST_INT numItems, + SX_ELEMENT *itemTbl, ST_BOOLEAN auto_pop); +ST_VOID sx_pop (SX_DEC_CTRL *sxDecCtrl); + + +ST_RET sx_get_entity (SX_DEC_CTRL *sxDecCtrl, + ST_CHAR *destBuf, ST_INT destLen, + ST_INT *lenOut); +ST_RET sx_get_int (SX_DEC_CTRL *sxDecCtrl, ST_INT *out_ptr); +ST_RET sx_get_float (SX_DEC_CTRL *sxDecCtrl, ST_FLOAT *out_ptr); +ST_RET sx_get_double (SX_DEC_CTRL *sxDecCtrl, ST_DOUBLE *out_ptr); +ST_RET sx_get_uchar (SX_DEC_CTRL *sxDecCtrl, ST_UCHAR *out_ptr); +ST_RET sx_get_int16 (SX_DEC_CTRL *sxDecCtrl, ST_INT16 *out_ptr); +ST_RET sx_get_uint16 (SX_DEC_CTRL *sxDecCtrl, ST_UINT16 *out_ptr); +ST_RET sx_get_int32 (SX_DEC_CTRL *sxDecCtrl, ST_INT32 *out_ptr); +ST_RET sx_get_uint32 (SX_DEC_CTRL *sxDecCtrl, ST_UINT32 *out_ptr); +ST_RET sx_get_uint32_hex (SX_DEC_CTRL *sxDecCtrl, ST_UINT32 *out_ptr); +ST_RET sx_get_long (SX_DEC_CTRL *sxDecCtrl, ST_LONG *out_ptr); +ST_RET sx_get_ulong (SX_DEC_CTRL *sxDecCtrl, ST_ULONG *out_ptr); +ST_RET sx_get_bool (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN *out_ptr); +ST_RET sx_get_duration (SX_DEC_CTRL *sxDecCtrl, SX_DURATION *sxDuration); +ST_RET sx_get_xtime (SX_DEC_CTRL *sxDecCtrl, SX_DATE_TIME *sxDateTime); +ST_RET sx_get_tm (SX_DEC_CTRL *sxDecCtrl, struct tm *out_ptr); +ST_RET sx_get_tm_ex (SX_DEC_CTRL *sxDecCtrl, struct tm *out_ptr, ST_LONG *microseconds); +ST_RET sx_get_time (SX_DEC_CTRL *sxDecCtrl, time_t *out_ptr); +ST_RET sx_get_time_ex (SX_DEC_CTRL *sxDecCtrl, time_t *out_ptr, ST_LONG *microseconds); +ST_RET sx_get_uint (SX_DEC_CTRL *sxDecCtrl, ST_UINT *out_ptr); +ST_RET sx_get_alloc_string (SX_DEC_CTRL *sxDecCtrl, ST_CHAR **strOut); +ST_RET sx_get_string_ptr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR **strOut, ST_INT *lenOut); +ST_RET sx_get_string (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *dest, ST_INT *lenOut); +ST_RET sx_get_string_YesNo (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN *dest, ST_RET errCode); +ST_RET sx_get_string_OnOff_mask (SX_DEC_CTRL *sxDecCtrl, ST_UINT *mask, ST_UINT maskBit, + ST_RET errCode); +ST_RET sx_get_string_OnOff_bool (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN *dest, ST_RET errCode); +ST_VOID sx_format_string_dec (ST_CHAR *dest, ST_CHAR *src); +ST_VOID sx_format_string_enc (ST_CHAR *dest, ST_CHAR *src); +ST_VOID sx_format_nstring_enc (ST_CHAR *dest, ST_CHAR *src, ST_INT len); +ST_RET sx_get_bitstring (SX_DEC_CTRL *sxDecCtrl, ST_INT *dest, ST_INT *lenOut); +ST_RET sx_get_element_contents (SX_DEC_CTRL *sxDecCtrl, + ST_CHAR *destBuf, ST_INT destLen, + ST_INT *lenOut); +ST_RET sx_find_element_contents (SX_DEC_CTRL *sxDecCtrl, + ST_CHAR **elStartOut, ST_INT *lenOut); + +ST_RET sx_get_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *value, ST_CHAR *name); +ST_RET sx_get_attr_ptr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR **ptrOut, ST_CHAR *name); +ST_RET sx_get_bool_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_BOOLEAN *out_ptr); +ST_RET sx_get_int_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_INT *out_ptr); +ST_RET sx_get_float_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_FLOAT *out_ptr); +ST_RET sx_get_double_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_DOUBLE *out_ptr); +ST_RET sx_get_uchar_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UCHAR *out_ptr); +ST_RET sx_get_int16_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_INT16 *out_ptr); +ST_RET sx_get_uint16_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UINT16 *out_ptr); +ST_RET sx_get_int32_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_INT32 *out_ptr); +ST_RET sx_get_uint32_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UINT32 *out_ptr); +ST_RET sx_get_long_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_LONG *out_ptr); +ST_RET sx_get_ulong_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_ULONG *out_ptr); +ST_RET sx_get_uint_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UINT *out_ptr); +ST_RET sx_get_duration_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, SX_DURATION *out_ptr); +ST_RET sx_get_xtime_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, SX_DATE_TIME *out_ptr); +ST_RET sx_get_tm_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, struct tm *out_ptr); + +#define sxd_decode_data_el(elName,xml,xmlLen,xmlUsed,vdp,typeId,elPres,checkDt)\ + _sxd_decode_data_el(elName,xml,xmlLen,xmlUsed,vdp,typeId,elPres,sxdDefXmlStyle,checkDt) + + +ST_RET _sxd_decode_data_el (ST_CHAR *elName, + ST_CHAR *xml, ST_INT xmlLen, ST_INT *xmlUsed, + ST_VOID *vdp, ST_INT typeId, + ST_BOOLEAN *elPres, ST_INT sxdXmlStyle, ST_BOOLEAN checkDt); + +ST_VOID sxStartElement (SX_DEC_CTRL *sxDecCtrl); +ST_VOID sxEndElement (SX_DEC_CTRL *sxDecCtrl); +ST_RET sx_get_value (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *format_string, ST_VOID *out_ptr); +ST_RET sx_get_attr_value (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, + ST_CHAR *format_string, ST_VOID *out_ptr); + +ST_VOID sx_load_characters (ST_CHAR *lineBuf, ST_BOOLEAN *eof, FILE *fp, ST_INT numToRead); + + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +/* max prefix length in SXD_XML_STYLE_A */ +#define SXD_MAX_PREFIX 100 + +typedef struct sx_enc_ctrl + { + ST_INT xmlBufLen; + ST_CHAR *xmlBuf; + ST_CHAR *xmlBufEnd; + + ST_BOOLEAN useFp; + FILE *fp; + + ST_CHAR *nextWritePos; + + ST_INT currNestLevel; + ST_CHAR tags[SX_MAX_STACK_LEVEL][SX_MAX_TAG_LEN+1]; + ST_RET errCode; + + ST_BOOLEAN bUseFormatting; + ST_BOOLEAN bOneLineEl; + + ST_BOOLEAN bUnformattedStrings; + +/* Used for data encoding */ + ST_BOOLEAN encDt; + ST_CHAR *outerElement; + ST_INT sxdXmlStyle; + ST_CHAR sxdPrefix[SXD_MAX_PREFIX+1]; /* only for SXD_XML_STYLE_A */ + ST_INT sxdStructNestLevel; /* only for SXD_XML_STYLE_A */ + + ST_VOID *usr; + } SX_ENC_CTRL; + +/* Macro for getting current encoded length */ +#define SX_ENC_LEN(__sxEncCtrl) ((__sxEncCtrl)->nextWritePos - (__sxEncCtrl)->xmlBuf) + +/************************************************************************/ +/************************************************************************/ + +SX_ENC_CTRL *sx_start_encode (ST_CHAR *xmlBuf, ST_INT xmlBufLen); +SX_ENC_CTRL *sx_start_encodeEx (ST_CHAR *fileName); +ST_VOID sx_end_encode (SX_ENC_CTRL *sxEncCtrl); +ST_VOID sx_init_encode (SX_ENC_CTRL *sxEncCtrl, + ST_CHAR *xmlBuf, ST_INT xmlBufLen); +ST_RET sx_init_encodeEx (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *fileName); + +#define sx_start_element(sxEncCtrl,tag,numAttr,attr)\ + sx_write_element(sxEncCtrl,tag,numAttr,attr,SD_FALSE,SD_FALSE); + +#define sx_write_empty_element(sxEncCtrl,tag,numAttr,attr)\ + sx_write_element(sxEncCtrl,tag,numAttr,attr,SD_FALSE,SD_TRUE); + +ST_VOID sx_end_element (SX_ENC_CTRL *sxEncCtrl); +ST_VOID sx_write_element (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *tag, + ST_INT numAttr, SXE_ATTR_PAIR *attr, + ST_BOOLEAN end, ST_BOOLEAN empty); + +/* Defines for 'no attribute' cases */ +#define sx_wr_string_el(sxEncCtrl,tag,str)\ + sx_wrx_string_el(sxEncCtrl,tag,str,0,NULL) + +#define sx_wr_nstring_el(sxEncCtrl,tag,str,len)\ + sx_wrx_nstring_el(sxEncCtrl,tag,str,len,0,NULL) + +#define sx_wr_int_el(sxEncCtrl,tag,val)\ + sx_wrx_int_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_uint_el(sxEncCtrl,tag,val)\ + sx_wrx_uint_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_ulong_el(sxEncCtrl,tag,val)\ + sx_wrx_ulong_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_uint32_hex_el(sxEncCtrl,tag,val)\ + sx_wrx_uint32_hex_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_float_el(sxEncCtrl,tag,val)\ + sx_wrx_float_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_double_el(sxEncCtrl,tag,val)\ + sx_wrx_double_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_long_el(sxEncCtrl,tag,val)\ + sx_wrx_long_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_bool_el(sxEncCtrl,tag,val)\ + sx_wrx_bool_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_tm_el(sxEncCtrl,tag,val)\ + sx_wrx_tm_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_time_el(sxEncCtrl,tag,val)\ + sx_wrx_time_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_duration_el(sxEncCtrl,tag,val)\ + sx_wrx_duration_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_xtime_el(sxEncCtrl,tag,val)\ + sx_wrx_xtime_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_cdata_el(sxEncCtrl,tag,str, len)\ + sx_wrx_cdata_el(sxEncCtrl,tag,str,len,0,NULL) + +/* Functions to write elements and element contents */ +ST_VOID sx_wr_string (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *str); +ST_VOID sx_wrx_string_el (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *tag, ST_CHAR *str, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_nstring (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *str, ST_INT len); +ST_VOID sx_wrx_nstring_el (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *tag, ST_CHAR *str, ST_INT len, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_bitstring (SX_ENC_CTRL *sxEncCtrl, ST_INT numBits, + ST_UINT8 *bitStr); +ST_VOID sx_wrx_bitstring_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, + ST_INT numBits, ST_UINT8 *bitStr, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_int (SX_ENC_CTRL *sxEncCtrl, ST_INT val); +ST_VOID sx_wrx_int_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_INT val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_uint (SX_ENC_CTRL *sxEncCtrl, ST_UINT val); +ST_VOID sx_wrx_uint_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_UINT val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_ulong (SX_ENC_CTRL *sxEncCtrl, ST_ULONG val); +ST_VOID sx_wrx_ulong_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_ULONG val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_uint32_hex (SX_ENC_CTRL *sxEncCtrl, ST_UINT32 val); +ST_VOID sx_wrx_uint32_hex_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_UINT32 val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_float (SX_ENC_CTRL *sxEncCtrl, ST_FLOAT val); +ST_VOID sx_wrx_float_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_FLOAT val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_double (SX_ENC_CTRL *sxEncCtrl, ST_DOUBLE val); +ST_VOID sx_wrx_double_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_DOUBLE val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_long (SX_ENC_CTRL *sxEncCtrl, ST_LONG val); +ST_VOID sx_wrx_long_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_LONG val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_bool (SX_ENC_CTRL *sxEncCtrl, ST_BOOLEAN val); +ST_VOID sx_wrx_bool_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_BOOLEAN val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_tm (SX_ENC_CTRL *sxEncCtrl, struct tm *val); +ST_VOID sx_wrx_tm_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, struct tm *val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_time (SX_ENC_CTRL *sxEncCtrl, time_t val); +ST_VOID sx_wrx_time_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, time_t val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_duration (SX_ENC_CTRL *sxEncCtrl, SX_DURATION *sxDuration); +ST_VOID sx_wrx_duration_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, SX_DURATION *val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_xtime (SX_ENC_CTRL *sxEncCtrl, SX_DATE_TIME *sxDateTime); +ST_VOID sx_wrx_xtime_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, SX_DATE_TIME *val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_cdata (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *str, ST_INT len); +ST_VOID sx_wrx_cdata_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, + ST_CHAR *str, ST_INT len, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +#define sxd_wr_data(ec,typeId,elName,data,encodeDt,elPres)\ + _sxd_wr_data(ec,typeId,elName,data,sxdDefXmlStyle,encodeDt,elPres)\ + +ST_RET _sxd_wr_data (SX_ENC_CTRL *sxEncCtrl, ST_INT typeId, + ST_CHAR *elName, ST_VOID *data, ST_INT sxdXmlStyle, + ST_BOOLEAN encodeDt, ST_BOOLEAN *elPres); + + +ST_VOID sx_add_string (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *_src, + ST_CHAR **writePosIo); +ST_RET sx_add_buf (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *_src, ST_INT _srcLen, + ST_CHAR **writePosIo); +ST_VOID sx_wr_comment (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *str); + +ST_RET XmlStringToDuration (ST_CHAR *src, SX_DURATION *out_ptr); +ST_RET XmlDurationToString (ST_CHAR *buffer, ST_LONG size, SX_DURATION *sxDuration); + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* SX_DEFS_INCLUDED */ + diff --git a/include/inc/sx_log.h b/include/inc/sx_log.h new file mode 100644 index 0000000..36a3670 --- /dev/null +++ b/include/inc/sx_log.h @@ -0,0 +1,337 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999 - 2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : sx_log.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/02/05 EJV 07 Add sx_debug_sel_cfg to save SX masks while */ +/* logging configuration is parsed. */ +/* 05/06/04 DWL 06 Use new "Base" macros SLOG_*, SLOGC_*, SLOGH.*/ +/* 06/06/01 GLB 05 Added SXLOG_CFLOW2 */ +/* 04/26/01 EJV 04 Added/rearranged slog macros for !DEBUG_SISCO*/ +/* 01/25/01 JRB 03 Added SXLOG_ERR2,3 */ +/* 10/30/99 MDE 02 Added SXLOG_NERR3 */ +/* 09/17/99 MDE 01 New */ +/************************************************************************/ + +#ifndef SX_LOG_INCLUDED +#define SX_LOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ + +#include "slog.h" + +/************************************************************************/ +/* sx_debug_sel bit assignments */ + +#define SX_LOG_DEC 0x0001 +#define SX_LOG_ENC 0x0002 +#define SX_LOG_FLOW 0x0004 +#define SX_LOG_DEBUG 0x0008 +#define SX_LOG_ERR 0x0010 +#define SX_LOG_NERR 0x0020 + +extern ST_UINT sx_debug_sel; +extern ST_UINT sx_debug_sel_cfg; /* saves SX masks while logging configuration is parsed */ + +/* Log type strings */ +extern SD_CONST ST_CHAR *SD_CONST _sx_log_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sx_log_enc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sx_log_flow_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sx_log_debug_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sx_log_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sx_log_nerr_logstr; + +/************************************************************************/ +/* Decode log macros */ +#define SXLOG_DEC0(a) \ + SLOG_0 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a) +#define SXLOG_DEC1(a,b) \ + SLOG_1 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b) +#define SXLOG_DEC2(a,b,c) \ + SLOG_2 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b,c) +#define SXLOG_DEC3(a,b,c,d) \ + SLOG_3 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b,c,d) +#define SXLOG_DEC4(a,b,c,d,e) \ + SLOG_4 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b,c,d,e) +#define SXLOG_DEC5(a,b,c,d,e,f) \ + SLOG_5 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b,c,d,e,f) +#define SXLOG_DEC6(a,b,c,d,e,f,g) \ + SLOG_6 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b,c,d,e,f,g) +#define SXLOG_DEC7(a,b,c,d,e,f,g,h) \ + SLOG_7 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b,c,d,e,f,g,h) +#define SXLOG_DEC8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b,c,d,e,f,g,h,i) + +/* Decode continuation log macros */ +#define SXLOG_CDEC0(a) \ + SLOGC_0 (sx_debug_sel & SX_LOG_DEC,a) +#define SXLOG_CDEC1(a,b) \ + SLOGC_1 (sx_debug_sel & SX_LOG_DEC,a,b) +#define SXLOG_CDEC2(a,b,c) \ + SLOGC_2 (sx_debug_sel & SX_LOG_DEC,a,b,c) +#define SXLOG_CDEC3(a,b,c,d) \ + SLOGC_3 (sx_debug_sel & SX_LOG_DEC,a,b,c,d) +#define SXLOG_CDEC4(a,b,c,d,e) \ + SLOGC_4 (sx_debug_sel & SX_LOG_DEC,a,b,c,d,e) +#define SXLOG_CDEC5(a,b,c,d,e,f) \ + SLOGC_5 (sx_debug_sel & SX_LOG_DEC,a,b,c,d,e,f) +#define SXLOG_CDEC6(a,b,c,d,e,f,g) \ + SLOGC_6 (sx_debug_sel & SX_LOG_DEC,a,b,c,d,e,f,g) +#define SXLOG_CDEC7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (sx_debug_sel & SX_LOG_DEC,a,b,c,d,e,f,g,h) +#define SXLOG_CDEC8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (sx_debug_sel & SX_LOG_DEC,a,b,c,d,e,f,g,h,i) + +/* Decode Hex log macro */ +#define SXLOG_DECH(a,b) \ + SLOGH (sx_debug_sel & SX_LOG_DEC,a,b) + +/************************************************************************/ +/* Encode log macros */ +#define SXLOG_ENC0(a) \ + SLOG_0 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a) +#define SXLOG_ENC1(a,b) \ + SLOG_1 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b) +#define SXLOG_ENC2(a,b,c) \ + SLOG_2 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b,c) +#define SXLOG_ENC3(a,b,c,d) \ + SLOG_3 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b,c,d) +#define SXLOG_ENC4(a,b,c,d,e) \ + SLOG_4 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b,c,d,e) +#define SXLOG_ENC5(a,b,c,d,e,f) \ + SLOG_5 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b,c,d,e,f) +#define SXLOG_ENC6(a,b,c,d,e,f,g) \ + SLOG_6 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b,c,d,e,f,g) +#define SXLOG_ENC7(a,b,c,d,e,f,g,h) \ + SLOG_7 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b,c,d,e,f,g,h) +#define SXLOG_ENC8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b,c,d,e,f,g,h,i) + +/* Encode continuation log macros */ +#define SXLOG_CENC0(a) \ + SLOGC_0 (sx_debug_sel & SX_LOG_ENC,a) +#define SXLOG_CENC1(a,b) \ + SLOGC_1 (sx_debug_sel & SX_LOG_ENC,a,b) +#define SXLOG_CENC2(a,b,c) \ + SLOGC_2 (sx_debug_sel & SX_LOG_ENC,a,b,c) +#define SXLOG_CENC3(a,b,c,d) \ + SLOGC_3 (sx_debug_sel & SX_LOG_ENC,a,b,c,d) +#define SXLOG_CENC4(a,b,c,d,e) \ + SLOGC_4 (sx_debug_sel & SX_LOG_ENC,a,b,c,d,e) +#define SXLOG_CENC5(a,b,c,d,e,f) \ + SLOGC_5 (sx_debug_sel & SX_LOG_ENC,a,b,c,d,e,f) +#define SXLOG_CENC6(a,b,c,d,e,f,g) \ + SLOGC_6 (sx_debug_sel & SX_LOG_ENC,a,b,c,d,e,f,g) +#define SXLOG_CENC7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (sx_debug_sel & SX_LOG_ENC,a,b,c,d,e,f,g,h) +#define SXLOG_CENC8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (sx_debug_sel & SX_LOG_ENC,a,b,c,d,e,f,g,h,i) + +/* Encode Hex log macro */ +#define SXLOG_ENCH(a,b) \ + SLOGH (sx_debug_sel & SX_LOG_ENC,a,b) + +/************************************************************************/ +/* Flow log macros */ +#define SXLOG_FLOW0(a) \ + SLOG_0 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a) +#define SXLOG_FLOW1(a,b) \ + SLOG_1 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b) +#define SXLOG_FLOW2(a,b,c) \ + SLOG_2 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b,c) +#define SXLOG_FLOW3(a,b,c,d) \ + SLOG_3 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b,c,d) +#define SXLOG_FLOW4(a,b,c,d,e) \ + SLOG_4 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b,c,d,e) +#define SXLOG_FLOW5(a,b,c,d,e,f) \ + SLOG_5 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b,c,d,e,f) +#define SXLOG_FLOW6(a,b,c,d,e,f,g) \ + SLOG_6 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b,c,d,e,f,g) +#define SXLOG_FLOW7(a,b,c,d,e,f,g,h) \ + SLOG_7 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b,c,d,e,f,g,h) +#define SXLOG_FLOW8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b,c,d,e,f,g,h,i) + +/* Flow continuation log macros */ +#define SXLOG_CFLOW0(a) \ + SLOGC_0 (sx_debug_sel & SX_LOG_FLOW,a) +#define SXLOG_CFLOW1(a,b) \ + SLOGC_1 (sx_debug_sel & SX_LOG_FLOW,a,b) +#define SXLOG_CFLOW2(a,b,c) \ + SLOGC_2 (sx_debug_sel & SX_LOG_FLOW,a,b,c) +#define SXLOG_CFLOW3(a,b,c,d) \ + SLOGC_3 (sx_debug_sel & SX_LOG_FLOW,a,b,c,d) +#define SXLOG_CFLOW4(a,b,c,d,e) \ + SLOGC_4 (sx_debug_sel & SX_LOG_FLOW,a,b,c,d,e) +#define SXLOG_CFLOW5(a,b,c,d,e,f) \ + SLOGC_5 (sx_debug_sel & SX_LOG_FLOW,a,b,c,d,e,f) +#define SXLOG_CFLOW6(a,b,c,d,e,f,g) \ + SLOGC_6 (sx_debug_sel & SX_LOG_FLOW,a,b,c,d,e,f,g) +#define SXLOG_CFLOW7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (sx_debug_sel & SX_LOG_FLOW,a,b,c,d,e,f,g,h) +#define SXLOG_CFLOW8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (sx_debug_sel & SX_LOG_FLOW,a,b,c,d,e,f,g,h,i) + +/* Flow Hex log macro */ +#define SXLOG_FLOWH(a,b) \ + SLOGH (sx_debug_sel & SX_LOG_FLOW,a,b) + +/************************************************************************/ +/* Debug log macros */ +#define SXLOG_DEBUG0(a) \ + SLOG_0 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a) +#define SXLOG_DEBUG1(a,b) \ + SLOG_1 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b) +#define SXLOG_DEBUG2(a,b,c) \ + SLOG_2 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b,c) +#define SXLOG_DEBUG3(a,b,c,d) \ + SLOG_3 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b,c,d) +#define SXLOG_DEBUG4(a,b,c,d,e) \ + SLOG_4 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b,c,d,e) +#define SXLOG_DEBUG5(a,b,c,d,e,f) \ + SLOG_5 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b,c,d,e,f) +#define SXLOG_DEBUG6(a,b,c,d,e,f,g) \ + SLOG_6 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b,c,d,e,f,g) +#define SXLOG_DEBUG7(a,b,c,d,e,f,g,h) \ + SLOG_7 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b,c,d,e,f,g,h) +#define SXLOG_DEBUG8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b,c,d,e,f,g,h,i) + +/* Debug continuation log macros */ +#define SXLOG_CDEBUG0(a) \ + SLOGC_0 (sx_debug_sel & SX_LOG_DEBUG,a) +#define SXLOG_CDEBUG1(a,b) \ + SLOGC_1 (sx_debug_sel & SX_LOG_DEBUG,a,b) +#define SXLOG_CDEBUG2(a,b,c) \ + SLOGC_2 (sx_debug_sel & SX_LOG_DEBUG,a,b,c) +#define SXLOG_CDEBUG3(a,b,c,d) \ + SLOGC_3 (sx_debug_sel & SX_LOG_DEBUG,a,b,c,d) +#define SXLOG_CDEBUG4(a,b,c,d,e) \ + SLOGC_4 (sx_debug_sel & SX_LOG_DEBUG,a,b,c,d,e) +#define SXLOG_CDEBUG5(a,b,c,d,e,f) \ + SLOGC_5 (sx_debug_sel & SX_LOG_DEBUG,a,b,c,d,e,f) +#define SXLOG_CDEBUG6(a,b,c,d,e,f,g) \ + SLOGC_6 (sx_debug_sel & SX_LOG_DEBUG,a,b,c,d,e,f,g) +#define SXLOG_CDEBUG7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (sx_debug_sel & SX_LOG_DEBUG,a,b,c,d,e,f,g,h) +#define SXLOG_CDEBUG8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (sx_debug_sel & SX_LOG_DEBUG,a,b,c,d,e,f,g,h,i) + +/* Debug Hex log macro */ +#define SXLOG_DEBUGH(a,b) \ + SLOGH (sx_debug_sel & SX_LOG_DEBUG,a,b) + +/************************************************************************/ +/* Err log macros */ +#define SXLOG_ERR0(a) \ + SLOG_0 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a) +#define SXLOG_ERR1(a,b) \ + SLOG_1 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b) +#define SXLOG_ERR2(a,b,c) \ + SLOG_2 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b,c) +#define SXLOG_ERR3(a,b,c,d) \ + SLOG_3 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b,c,d) +#define SXLOG_ERR4(a,b,c,d,e) \ + SLOG_4 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b,c,d,e) +#define SXLOG_ERR5(a,b,c,d,e,f) \ + SLOG_5 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b,c,d,e,f) +#define SXLOG_ERR6(a,b,c,d,e,f,g) \ + SLOG_6 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b,c,d,e,f,g) +#define SXLOG_ERR7(a,b,c,d,e,f,g,h) \ + SLOG_7 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b,c,d,e,f,g,h) +#define SXLOG_ERR8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b,c,d,e,f,g,h,i) + +/* Err continuation log macros */ +#define SXLOG_CERR0(a) \ + SLOGC_0 (sx_debug_sel & SX_LOG_ERR,a) +#define SXLOG_CERR1(a,b) \ + SLOGC_1 (sx_debug_sel & SX_LOG_ERR,a,b) +#define SXLOG_CERR2(a,b,c) \ + SLOGC_2 (sx_debug_sel & SX_LOG_ERR,a,b,c) +#define SXLOG_CERR3(a,b,c,d) \ + SLOGC_3 (sx_debug_sel & SX_LOG_ERR,a,b,c,d) +#define SXLOG_CERR4(a,b,c,d,e) \ + SLOGC_4 (sx_debug_sel & SX_LOG_ERR,a,b,c,d,e) +#define SXLOG_CERR5(a,b,c,d,e,f) \ + SLOGC_5 (sx_debug_sel & SX_LOG_ERR,a,b,c,d,e,f) +#define SXLOG_CERR6(a,b,c,d,e,f,g) \ + SLOGC_6 (sx_debug_sel & SX_LOG_ERR,a,b,c,d,e,f,g) +#define SXLOG_CERR7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (sx_debug_sel & SX_LOG_ERR,a,b,c,d,e,f,g,h) +#define SXLOG_CERR8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (sx_debug_sel & SX_LOG_ERR,a,b,c,d,e,f,g,h,i) + +/* Err Hex log macro */ +#define SXLOG_ERRH(a,b) \ + SLOGH (sx_debug_sel & SX_LOG_ERR,a,b) + +/************************************************************************/ +/* NErr log macros */ +#define SXLOG_NERR0(a) \ + SLOG_0 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a) +#define SXLOG_NERR1(a,b) \ + SLOG_1 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b) +#define SXLOG_NERR2(a,b,c) \ + SLOG_2 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b,c) +#define SXLOG_NERR3(a,b,c,d) \ + SLOG_3 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b,c,d) +#define SXLOG_NERR4(a,b,c,d,e) \ + SLOG_4 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b,c,d,e) +#define SXLOG_NERR5(a,b,c,d,e,f) \ + SLOG_5 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b,c,d,e,f) +#define SXLOG_NERR6(a,b,c,d,e,f,g) \ + SLOG_6 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b,c,d,e,f,g) +#define SXLOG_NERR7(a,b,c,d,e,f,g,h) \ + SLOG_7 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b,c,d,e,f,g,h) +#define SXLOG_NERR8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b,c,d,e,f,g,h,i) + +/* NErr continuation log macros */ +#define SXLOG_CNERR0(a) \ + SLOGC_0 (sx_debug_sel & SX_LOG_NERR,a) +#define SXLOG_CNERR1(a,b) \ + SLOGC_1 (sx_debug_sel & SX_LOG_NERR,a,b) +#define SXLOG_CNERR2(a,b,c) \ + SLOGC_2 (sx_debug_sel & SX_LOG_NERR,a,b,c) +#define SXLOG_CNERR3(a,b,c,d) \ + SLOGC_3 (sx_debug_sel & SX_LOG_NERR,a,b,c,d) +#define SXLOG_CNERR4(a,b,c,d,e) \ + SLOGC_4 (sx_debug_sel & SX_LOG_NERR,a,b,c,d,e) +#define SXLOG_CNERR5(a,b,c,d,e,f) \ + SLOGC_5 (sx_debug_sel & SX_LOG_NERR,a,b,c,d,e,f) +#define SXLOG_CNERR6(a,b,c,d,e,f,g) \ + SLOGC_6 (sx_debug_sel & SX_LOG_NERR,a,b,c,d,e,f,g) +#define SXLOG_CNERR7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (sx_debug_sel & SX_LOG_NERR,a,b,c,d,e,f,g,h) +#define SXLOG_CNERR8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (sx_debug_sel & SX_LOG_NERR,a,b,c,d,e,f,g,h,i) + +/* NErr Hex log macro */ +#define SXLOG_NERRH(a,b) \ + SLOGH (sx_debug_sel & SX_LOG_NERR,a,b) +/************************************************************************/ + + +#ifdef __cplusplus +} +#endif + +/************************************************************************/ +#endif /* End of SX_LOG_INCLUDED */ +/************************************************************************/ diff --git a/include/inc/sysincs.h b/include/inc/sysincs.h new file mode 100644 index 0000000..bbba924 --- /dev/null +++ b/include/inc/sysincs.h @@ -0,0 +1,468 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2008, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : sysincs.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* The purpose of this include file is to bring in include files */ +/* that come with one of the various C compilers. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/27/08 EJV 48 Defined S_MAX_PATH for all systems. */ +/* 01/15/08 EJV 47 Added S_FMT_* helper macros for (s)printf. */ +/* 11/01/07 EJV UNIX, Linux: added define MAX_PATH. */ +/* 02/28/08 JRB 46 Add timeb.h for _WIN32, linux, QNX. */ +/* 10/03/07 JRB 45 Add winsock2.h BEFORE windows.h */ +/* Add #pragma for _WIN32. */ +/* 11/08/06 EJV 44 HP-UX: use */ +/* 07/10/06 EJV 43 Sun: chg inlude to . */ +/* 06/19/06 EJV 42 VXWORKS, QNX: added . */ +/* UNIX, Linux: added . */ +/* 02/28/06 EJV 41 Added pragma to disable warning C4996 (about */ +/* deprecated functions). */ +/* 01/30/06 GLB 33 Integrated porting changes for VMS */ +/* 02/13/06 DSF 39 Migrate to VS.NET 2005 */ +/* 12/16/05 GLB 38 Added "unix.h" for "ftruncate" */ +/* 11/21/05 DSF 37 Do not enforce definition of ASSERT */ +/* 09/28/05 EJV 36 Moved filio.h for sun (from gensock2.c). */ +/* 08/10/05 JRB 35 Fixed a few newline characters. */ +/* 07/15/05 DSF 34 Fixed SASSERT warnings for release builds */ +/* 05/24/05 EJV 33 UNIX, Linux: added include */ +/* 03/18/05 DSF 32 Log asserts */ +/* 12/07/04 JRB 31 Define larger FD_SETSIZE for QNX. */ +/* 09/22/04 EJV 30 Added INADDR_NONE (needed on sun) */ +/* 07/08/04 DSF 29 Fixed SASSERT macro */ +/* 01/26/04 JRB 28 Fix LYNX includes. */ +/* 01/22/04 DSF 27 Added/modified ASSERT macros */ +/* 01/19/04 EJV 26 __hpux 10.20 does not have sys/select.h. */ +/* 12/09/03 JRB 25 Add LYNX support. Add () to max,min macros. */ +/* 10/23/03 JRB 24 Move socket includes to here. */ +/* For _WIN32, add windows.h, process.h */ +/* Del unused CDECL define. */ +/* 04/28/03 DSF 23 Make sure expression inside VERIFY is always */ +/* executed */ +/* 04/15/03 DSF 22 Don't define/undef NDEBUG */ +/* 03/18/03 JRB 21 Fix QNX #ifdef. */ +/* 02/20/03 JRB 20 Del PSOS code. */ +/* 02/17/03 CRM 19 Added "defined(linux)" code. */ +/* 02/17/03 JRB 18 Stop using SYSTEM_SEL define. */ +/* Add conio.h for WIN32. */ +/* Add sys/time.h, sys/select.h for UNIX. */ +/* Add termio.h for UNIX & QNX. */ +/* 02/27/02 EJV 17 Added limits.h to most of systems. */ +/* Check if LONG_MAX and INT_MAX defined. */ +/* 07/27/01 DSF 16 crtdbg.h should only be included if _DEBUG */ +/* is defined */ +/* 03/16/01 DSF 15 Make sure VERIFY is not defined before */ +/* defining it */ +/* 02/02/01 DSF 14 Added asserts */ +/* 01/19/01 EJV 13 Added for SYSTEM_SEL_SYS_5. */ +/* 01/03/01 EJV 12 Added for SYSTEM_SEL_SYS_5. */ +/* 10/13/00 EJV 11 Added for some SYSTEM_SEL_SYS_5. */ +/* 05/05/00 JRB 10 Added "select.h" for some systems. */ +/* 04/20/00 EJV 09 Added stdarg.h for SYSTEM_SEL_SYS_5. */ +/* 02/04/99 JRB 08 Added types.h & stat.h for most systems. */ +/* 07/01/98 JRB 07 Added stdarg.h & ctype.h for some systems. */ +/* 12/29/97 JRB 06 Cleaned up OS2 (include os2.h). More PSOS. */ +/* 12/11/97 JRB 05 Cleaned up PSOS includes. Use SYS_PSOS. */ +/* 12/11/97 JRB 04 Deleted EMBEDDED_6800 includes. */ +/* 10/29/97 EJV 03 Corrected max maro definition */ +/* 10/28/97 EJV 02 Added *.h files specific for SYS_5 */ +/* 08/15/97 EJV 01 Added *.h files specific for SYS_QNX4 */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef SYSINCS_INCLUDED +#define SYSINCS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__OS2__) +#define INCL_BASE /* include all OS2 definitions. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef kbhit /* The OS/2 2.0 version is not what we want */ +#undef kbhit +#endif +#include /* for _beginthread, _endthread */ +#include /* for "kill", etc. */ +/* Sockets related includes */ +#include +#include /* IPPROTO_*, etc. */ +#include /* gethostbyname, etc. */ +#include /* defines FIONBIO */ +#endif /* OS2 */ + +#if defined (_WIN32) +#if !defined (_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE +#endif +#pragma warning(disable : 4996) +#pragma warning(disable : 4786 4800) + +#if defined (_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) +#undef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 +#endif + + + +/* winsock2.h MUST ALWAYS BE BEFORE windows.h to override defs in */ +/* winsock.h (included by windows.h). Any module that includes windows.h*/ +/* before sysincs.h, must also include winsock2.h before windows.h. */ +#include /* must be before windows.h */ +#include +#include /* for _beginthread, _endthread */ +#include /* for ftime, timeb */ +#endif /* defined(_WIN32) */ + +#if defined(_WIN32) || defined(MSDOS) || defined(__MSDOS__) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#if defined(VXWORKS) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for "kill", etc. */ +/* Sockets related includes */ +#include +#include +#include +#include +#include +/*#include */ +#include /* IPPROTO_*, etc. */ +#include /* inet_addr, etc. */ +#include /* TCP_NODELAY, etc. */ +#include +#endif + +#if defined(__QNX__) +/* FD_SETSIZE default is only 32 on QNX. Must define larger value */ +/* here (before any system includes) to allow more TCP connections. */ +#define FD_SETSIZE 600 +#include +#include +#include +#include +#include +#include +#include +#include /* S_IFIFO, S_IRUSR, S_IWUSR, etc. */ +#include +#include +#include /* mknod, etc. */ +#include /* added for "ftruncate" */ +#include /* open, O_RDONLY, O_WRONLY, etc. */ +#include /* execlp, etc. */ +#include +#include +#include +#include +#include +#include /* for "kill", etc. */ +#include /* for ftime, timeb */ +/* Sockets related includes */ +#include +#include /* gethostbyname, etc. */ +#include /* IPPROTO_*, etc. */ +#include /* inet_addr, etc. */ +#include /* TCP_NODELAY, etc. */ +#include +#endif + +/* UNIX or "UNIX-like" systems */ +#if defined(_AIX) || defined(sun) || defined(__hpux) || defined(linux) \ + || (defined(__alpha) && !defined(__VMS)) || defined(__LYNX) +#include /* SHOULD be before any other include files */ +#include +#include +#include +#include +#if (!defined(__LYNX)) +#include +#include +#endif + +//lnk20260611 +#ifndef __cplusplus +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif +#endif +#include +#include +#include +#include +#include +#include /* open, O_RDONLY, O_WRONLY, etc. */ +#include +#include + +#if defined(linux) +#include /* for ftime, timeb */ +#endif + +#if defined(__hpux) +#include +#else +#include +#endif + +#if (!defined (__hpux)) && (!defined(__LYNX)) +#include +#endif +#include /* for "kill", etc. */ +#include +#if defined(sun) +#include +#endif +/* Sockets related includes */ +#if defined(__LYNX) +#include +#else +#include +#endif +#include /* gethostbyname, etc. */ +#include /* IPPROTO_*, etc. */ +#include /* for sockaddr_un */ +/* Forward references are supplied to eliminate xlC_r compiler warnings */ +struct ether_addr; /* forward reference */ +struct sockaddr_dl; /* forward reference */ +#include /* inet_addr, etc. */ +#include /* TCP_NODELAY, etc. */ +#ifndef INADDR_NONE +#define INADDR_NONE ((in_addr_t) 0xffffffff) +#endif +#endif /* defined(_AIX) || defined(sun) || defined(__hpux) || defined(linux) ... */ + +#if defined(__ECOS) +#include +#include +#include +#include +#include +#include +#include +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#if defined(__VMS) +#include +#include +#include +#include +#include +#include + +#include /* VMS descriptor stuff */ +#include /* I/O FUNCTION CODE DEFS */ +#include /* LIB$ RTL-routine signatures. */ +#include /* LIB$ RTL-routine signatures. */ +#include /* LIB$ RTL-routine signatures. */ +#include /* SS$_ sys ser return stati <8-) */ +#include /* Sys ser calls */ +#include /* ... */ +#include /* Convert floating-point data type */ +#include /* ... */ +#include /* UNIX style Signal Value Definitions */ +#include +#include +#include + +#include "stdarg.h" +#include "iostream.h" +#include +#include +#include + +#include /* TCP descriptions */ +#include /* internet system Constants and structures. */ +#include /* Network address info. */ +#include /* Network database library info. */ +#include /* TCP/IP socket definitions. */ +#include +#include /* Operations on socket (?) */ + +#define max(a,b) ((a > b) ? a : b) +#define min(a,b) ((a < b) ? a : b) +#endif + +#if (!defined(INT_MAX)) || (!defined(LONG_MAX)) +#error INT_MAX and LONG_MAX must be defined. Usually defined in limits.h +#endif + +#if defined(MAX_PATH) +#define S_MAX_PATH MAX_PATH +#elif defined(PATH_MAX) /* POSIX should have it defined in limits.h */ +#define S_MAX_PATH PATH_MAX +#else +#define S_MAX_PATH 1024 /* default */ +#endif + + /*----------------------------------------------*/ + /* printf, sprintf, sscanf helper macros */ + /*----------------------------------------------*/ + +/* helper macro for 32-bit and 64-bit pointers support */ +/* If pointer "0x%p" format is not supported then something like "0x%x",*/ +/* "0x%lx", or "0x%llx" may be used, depending on the pointer size. */ +#if defined(_WIN32) + #define S_FMT_PTR "0x%p" +#else /* all other systems (e.g. UNIX) */ + #define S_FMT_PTR "0x%p" +#endif /* all other systems (e.g. UNIX) */ + +/* helper macro for time_t */ +#if defined(_WIN32) + #if defined(_USE_32BIT_TIME_T) + #define S_FMT_TIME_T "%d" + #else + #define S_FMT_TIME_T "%I64d" + #endif +#else /* all other systems (e.g. UNIX) */ + #define S_FMT_TIME_T "%d" +#endif /* all other systems (e.g. UNIX) */ + +#ifdef INT64_SUPPORT +#ifdef _WIN32 + #define S_FMT_INT64 "%I64d" + #define S_FMT_UINT64 "%I64u" +#elif defined(_AIX) || defined(__hpux) || defined(linux) || defined(sun) || defined(__LYNX) + #define S_FMT_INT64 "%lld" + #define S_FMT_UINT64 "%llu" +#elif (defined(__alpha) && !defined(__VMS)) + #define S_FMT_INT64 "%ld" + #define S_FMT_UINT64 "%lu" +#else /* all other systems */ + #error Missing S_FMT_INT64 and S_FMT_UINT64 defines for this platform. +#endif /* all other systems */ +#endif /* INT64_SUPPORT */ + +/* helper macro for HANDLE */ +#if defined(_WIN32) + #if (_MSC_VER >= 1300) + #define S_FMT_HANDLE "0x%p" + #define S_FMT_THREAD_HANDLE "0x%p" + #else + #define S_FMT_HANDLE "%d" + #define S_FMT_THREAD_HANDLE "%lu" + #endif +#else /* all other systems (e.g. UNIX) */ + #define S_FMT_THREAD_HANDLE "0x%p" +#endif /* all other systems (e.g. UNIX) */ + + +/************************************************************************/ +/************************************************************************/ +/* Assert stuff */ +/************************************************************************/ +/************************************************************************/ + +#include + +#if defined (_WIN32) && defined (_DEBUG) +#include +#endif + +#if !defined (C_ASSERT) +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#if !defined (ASSERT) +#define ASSERT _ASSERT +#endif + +#if !defined (ASSERTE) +#define ASSERTE _ASSERTE +#endif + +#if !defined (_SASSERT) +#define _SASSERT(e) \ + { \ + int assertResult = (e) ? 1 : 0; \ + if (!assertResult) {SLOGALWAYS3("Assertion failed: '%s', file %s, line %d", #e, __FILE__, __LINE__);} \ + assert (assertResult); \ + } +#endif + +#if !defined (_SASSERTE) +#define _SASSERTE(e) \ + { \ + int assertResult = (e) ? 1 : 0; \ + if (!assertResult) {SLOGALWAYS3("Assertion failed: '%s', file %s, line %d", #e, __FILE__, __LINE__);} \ + assert (assertResult); \ + } +#endif + +#if !defined (SASSERT) +#define SASSERT _SASSERT +#endif + +#if !defined (SASSERTE) +#define SASSERTE _SASSERTE +#endif + +#if !defined (VERIFY) +#if !defined (NDEBUG) +#define VERIFY(e) _SASSERTE(e) +#else +#define VERIFY(e) ((void) (e)) +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/include/inc/time_str.h b/include/inc/time_str.h new file mode 100644 index 0000000..ff9d034 --- /dev/null +++ b/include/inc/time_str.h @@ -0,0 +1,137 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2003, All Rights Reserved */ +/* */ +/* MODULE NAME : time_str.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/28/08 JRB 16 Incl "timeb.h" only in "sysincs.h" */ +/* 11/30/06 RLH 15 merge time_str and time_str2 */ +/* 07/13/06 RLH 14 tstrTimeToStringGmt and tstrStringToTimeGmt */ +/* prototypes added */ +/* 03/06/06 RLH 13 add GetTimeAndUsec, tstrTimeToStringGmt, */ +/* tstrStringToTimeGmt */ +/* 07/27/04 DWL 12 Added tstrTmToString (struct tm) */ +/* 07/16/04 DWL 11 Added tstrStringToTm (struct tm) */ +/* 10/30/03 EJV 10 Added dataLen param to UtcValueToXmlString */ +/* 10/15/03 JRB 09 Del _WIN32 ifdef. */ +/* 09/01/03 GLB 08 Added "XmlStringToUtcValue" & */ +/* "UtcValueToXmlString" */ +/* 07/12/02 NAV 07 Add UtcValsToString and UtcStringToVals */ +/* 02/02/01 EJV 06 tstrStringToTime: chg (long *) to (time_t *) */ +/* 07/13/98 NAV 05 Add _cplusplus support */ +/* 10/15/97 NAV 04 Add Btime4 Support Functions */ +/* 10/08/97 NAV 03 Add seconds to TSTR_DEF_TIME_FORMAT */ +/* 09/04/97 NAV 02 Add Btime6 Conversion routines */ +/* 11/08/94 MDE 01 New */ +/************************************************************************/ + +/************************************************************************/ +/* TIME STRING FORM FOR READ DATA */ +/* */ +/* Date{ws}Time */ +/* Time{ws}Date (? should we allow this) */ +/* Time only (uses current time) */ +/* Date only (uses current date) */ +/* */ +/* Date forms : */ +/* 12/01/56 */ +/* 12/01/1956 */ +/* 12-01-56 */ +/* 12-01-1956 */ +/* 12-1-56 */ +/* 12-1-56 */ +/* 26-Aug-1994 */ +/* 26-AUG-1994 */ +/* AUG-26-1993 */ +/* */ +/* Time forms : */ +/* 7:21:43P */ +/* 7:21:43p */ +/* 7:21:43a */ +/* 7:21:43A */ +/* 07:21:43a */ +/* 7:21:43 */ +/* 21:21:43 */ +/* */ +/************************************************************************/ +#include "sx_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* parms that control how a date is parsed in terms of field ordering */ + +#define S_DATE_ORDER_ANY 0 /* check system locale for ordering */ +#define S_DATE_ORDER_MDY 1 /* date ordering is month-day-year */ +#define S_DATE_ORDER_DMY 2 /* date ordering is day-month-year */ +#define S_DATE_ORDER_YMD 3 /* date ordering is year-month-day */ + +/* number of seconds difference between 1984-01-01 and 1970-01-01. */ +/* this amounts to 14 years including 3 leap-year days (1972, 1976 */ +/* and 1980) converted to a number of seconds. 1984 is a leap year */ +/* but the span of dates does not include 1984-02-29, so 1984's */ +/* leap-year day is not counted. */ + +/* S_SECS_DIFF_1984_1970 is used to calculate Btime6 values. */ + +#define S_SECS_DIFF_1984_1970 ((((1984-1970)*365)+3) * 86400) + +#define MAX_TIME_STRING_LEN 256 + +#define TSTR_DEF_TIME_FORMAT "%m-%d-%Y %H:%M:%S" + +extern char *tstrTimeFormat; + +ST_RET tstrTimeToStringGmt (time_t t, char *dest); +ST_RET tstrStringToTimeGmt (char *src, time_t *out); + +ST_RET tstrStringToTime (char *src, time_t *out); +ST_RET tstrStringToTm (char *src, struct tm *out); + +ST_RET tstrTimeToString (time_t t, char *dest); +ST_RET tstrTimeToStringGmt (time_t t, char *dest); + +ST_RET tstrTmToString (struct tm *t, char *dest); +ST_RET tstrTmToStringGmt (struct tm *t, char *dest); + +#define BTIME_DEF_TIME_FORMAT "%m-%d-%Y %H:%M:%S" + +ST_RET Btime6StringToVals (char *src, ST_INT32 *numDays, ST_INT32 *numMSec); +ST_RET Btime6ValsToString (char *dest, ST_INT32 numDays, ST_INT32 numMSec); + +ST_RET Btime4StringToVals (char *src, ST_INT32 *numMSec); +ST_RET Btime4ValsToString (char *dest, ST_INT32 numMSec); + +ST_RET UtcStringToVals (char *src, ST_UINT32 *pSecs, ST_UINT32 *pFraction, + ST_UINT32 *pQflags ); +ST_RET UtcValsToString (char *dest, ST_UINT32 secs, ST_UINT32 fraction, + ST_UINT32 qflags); +ST_RET UtcStringToValues (char *src, ST_UINT32 *pSecs, ST_UINT32 *pFraction); +ST_RET UtcValuesToString (char *dest, ST_UINT32 secs, ST_UINT32 fraction); +ST_RET XmlStringToUtcValue (ST_CHAR *src, SX_DATE_TIME *sxDateTime); +ST_RET UtcValueToXmlString (ST_CHAR *dest, ST_UINT destLen, SX_DATE_TIME *sxDateTime); +ST_DOUBLE CalculateTimeZoneOffset (ST_VOID); +#define UTC_DEF_TIME_FORMAT "%Y-%m-%dT%H:%M:%S" + +#define GET_TIME_AND_USEC_DEFINED 1 +time_t GetTimeAndUsec (long *usec); + +time_t usr_mkgmtime (struct tm * t); + +#ifdef __cplusplus +} /* End of 'C' functions */ + +#endif + diff --git a/include/inc/tp0_sock.h b/include/inc/tp0_sock.h new file mode 100644 index 0000000..5375d8c --- /dev/null +++ b/include/inc/tp0_sock.h @@ -0,0 +1,268 @@ +#ifndef TP0_SOCK_INCLUDED +#define TP0_SOCK_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997 - 2006 All Rights Reserved */ +/* */ +/* MODULE NAME : tp0_sock.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* TP0/RFC1006 header file for "sockets" interface. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/26/06 EJV 30 Ported MMSEASE_MOSI code to HP-UX. */ +/* 06/19/06 EJV 29 Ported MMSEASE_MOSI code to Sun. */ +/* 08/03/05 EJV 28 SOCK_INFO: added rekeyTime */ +/* 07/19/05 EJV 27 Added SOCK_STATE_CONNECT_CANCELLED. */ +/* 06/30/05 EJV 26 SOCK_INFO: added recvCnt (for flow control) */ +/* 06/06/05 EJV 25 MMSEASE_MOSE: few more chgs to RFC1006_IPC* */ +/* 05/25/05 EJV 24 Added ssec.h */ +/* 04/25/05 JRB,EJV 23 Add RFC1006_IPC_MSG, RFC1006_LISTENER_.. defs*/ +/* 05/09/05 EJV 22 SOCK_INFO: added port field. sreadd add arg6.*/ +/* 05/05/05 EJV 21 np_connect_req: added rem_port param. */ +/* 03/08/05 JRB 20 Add RFC1006.. define. */ +/* 02/22/05 JRB 19 slistend,sreadd: chg ret from void to int. */ +/* 02/21/05 JRB 18 Del ioctlsocket define. Use def in gensock2.h*/ +/* 01/14/04 EJV 17 np_data_req: added eot param. */ +/* Added np_get_tx_queue_cnt func. */ +/* 10/23/03 JRB 16 Move all system includes to sysincs.h */ +/* 10/16/03 JRB 15 SOCK_INFO: add genSock. */ +/* 09/11/03 EJV 14 Del winsock.h (windows.h gets right winsock) */ +/* Added encrypt_ctrl arg to np_connect_req(). */ +/* SOCK_INFO: Add DBL_LNK l and encrypt_ctrl. */ +/* 07/16/02 JRB 13 Add arg to sreadd proto. */ +/* 06/20/02 JRB 12 Chg np_connect_req 2nd arg to ulong ipAddr. */ +/* 05/08/02 JRB 11 Chg connect_result to int (to store errno). */ +/* 05/03/02 JRB 10 Add ip_addr to SOCK_INFO to pass to Read task.*/ +/* 02/02/01 EJV 09 _AIX: added forward references for inet.h. */ +/* 01/02/01 EJV 08 Ported to _AIX. */ +/* 08/15/00 EJV 07 WIN32: Del pipe_msg_crit_sec, pipe_msg_count.*/ +/* 05/18/00 JRB 06 Del "select.h". See "sysincs.h". */ +/* Add for VXWORKS. */ +/* Improve "ioctlsocket" macros for non-WIN32. */ +/* 08/13/98 JRB 05 Lint cleanup. */ +/* Add for default system. */ +/* 12/09/97 JRB 04 Added __OS2__ support. */ +/* 11/14/97 JRB 03 Make PIPE_MSG for VXWORKS like _WIN32. */ +/* 11/10/97 JRB 02 Add VXWORKS support. */ +/* 08/01/97 JRB 01 Created (compatible with MMS-EASE 7.0). */ +/************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +#include "gensock2.h" /* need GEN_SOCK definition */ +#include "ssec.h" /* need S_SEC_ENCRYPT_CTRL */ + +/* Include sockets defs appropriate for this platform. */ +#if !defined (_WIN32) +#define closesocket close +#define WSAEWOULDBLOCK EWOULDBLOCK +#define WSAEINPROGRESS EINPROGRESS +#if defined (__OS2__) +#define WSAGetLastError() sock_errno() +#define GetLastError() errno +#else /* !__OS2__ */ +#define WSAGetLastError() errno +#endif /* !__OS2__ */ +#define SOCKET int +#define SOCKADDR struct sockaddr +#define SOCKADDR_IN struct sockaddr_in +#define PSOCKADDR struct sockaddr * +#define HOSTENT struct hostent +#define INVALID_SOCKET (-1) + +#if defined(sun) || defined(__hpux) +#if !defined(AF_LOCAL) +#define AF_LOCAL AF_UNIX +#endif +#endif /* defined(sun) */ + +#endif /* !_WIN32 */ + +/************************************************************************/ +/* Constant definitions. */ +/************************************************************************/ +#define IPPORT_RFC1006 102 +#define RFC1006_HEAD_LEN 4 +#define RFC1006_VERSION 3 /* first byte of TPKT is version*/ +#define INVALID_CONN_ID (-1L) +#define LISTEN_TASK_NAME "slistend" /* "Listen" task exe name*/ +#define READ_TASK_NAME "sreadd" /* "Read" task exe name */ +#define PIPE_TO_MAIN_NAME "/tmp/pipetp0main" +#define PIPE_TO_LISTEN_NAME "/tmp/pipetp0list" + +/************************************************************************/ +/* Variable type definitions. */ +/************************************************************************/ + +/* Defines of possible values for "state" in SOCK_INFO struct. */ +#define SOCK_STATE_ACCEPTED 0 +#define SOCK_STATE_CONNECTING 1 +#define SOCK_STATE_CONNECTED 2 +#define SOCK_STATE_DISCONNECTING 3 +#define SOCK_STATE_CONNECT_CANCELLED 4 +typedef struct + { + DBL_LNK l; /* needed to store this struct on linked list */ + GEN_SOCK *genSock; /* Use with gensock2. Otherwise, use "hSock" */ + SOCKET hSock; + ST_INT state; + ST_LONG user_conn_id; /* Received from user on N-CONNECT.req/rsp */ + ST_UINT32 ip_addr; /* IP addr as long int in network byte order. */ + ST_UINT16 port; /* RFC1006 port, defaults to 102 */ +#if !(defined(_WIN32) || defined (__OS2__)) + pid_t pid_read; /* Save READ process PID */ +#endif + S_SEC_ENCRYPT_CTRL encrypt_ctrl; + ST_UINT recvCnt; /* num of received (queued) data msgs */ + ST_DOUBLE rekeyTime; /* next time to check rekey if we are idle */ + } SOCK_INFO; + + +/* Info to pass to spawned thread. Can only pass 1 arg to thread, so */ +/* make it a structure, and put whatever we need in it. */ +typedef struct + { + SOCK_INFO *sock_info; /* to pass back to main in PIPE_MSG. */ + SOCKET hSock; /* copied from "sock_info" */ + ST_INT state; /* copied from "sock_info" */ + ST_UINT16 max_tpkt_len; /* Max len of RFC1006 TPKT. */ + } THREAD_INFO; + +typedef struct + { + SOCK_INFO *sock_info; + ST_INT connect_result; /* errno (WSAGetLastErr() for Windows)*/ + ST_UINT16 tpkt_len; +#if (defined (_WIN32) || defined (VXWORKS) || defined (__OS2__)) + ST_UCHAR *tpkt_ptr; +#else + ST_UCHAR tpkt_buf [1]; /* Beginning of buffer attached to this struct*/ +#endif + } PIPE_MSG; + +/* Use define for Length of PIPE_MSG without tpkt_buf at end. */ +#define PIPE_MSG_HEAD_LEN (sizeof(PIPE_MSG)-1) + +/************************************************************************/ +/* Global variables. */ +/************************************************************************/ +extern ST_UCHAR *g_tpkt_enc_buf; /* Buffer for encoding TPKTs. */ +extern SOCKET hSockListen; /* listen socket handle */ + +#if defined _WIN32 +extern HANDLE hPipeMainRead; /* read handle for pipe */ +extern HANDLE hPipeMainWrite; /* write handle for pipe */ +extern HANDLE hEventListenGo; +#endif +#if defined (__OS2__) +extern HFILE hPipeMainRead; /* read handle for pipe */ +extern HFILE hPipeMainWrite; /* write handle for pipe */ +extern HEV hEventListenGo; +extern ST_INT pipe_msg_count; +#endif /* __OS2__ */ + +/************************************************************************/ +/* Function Prototypes. */ +/************************************************************************/ +ST_RET np_init (ST_INT max_num_conns); +ST_RET np_end (ST_VOID); +ST_BOOLEAN np_event (ST_VOID); + +SOCK_INFO * np_connect_req (ST_LONG user_conn_id, ST_ULONG ipAddr, ST_UINT16 rem_port, + S_SEC_ENCRYPT_CTRL *encrypt_ctrl); +ST_VOID np_connect_cnf_pos (SOCK_INFO *sock_info, ST_LONG user_conn_id); +/* NOTE: np_connect_ind & np_connect_rsp not needed because user only */ +/* cares about Transport conn. Doesn't need to know about Network conn.*/ + +ST_RET np_data_req (SOCK_INFO *sock_info, ST_INT pdu_len, ST_UCHAR *pdu_ptr, ST_BOOLEAN eot); +ST_VOID np_data_ind (SOCK_INFO *sock_info, ST_UCHAR *pdu_ptr, ST_UINT16 pdu_len); +ST_UINT np_get_tx_queue_cnt (SOCK_INFO *sock_info); + +ST_RET np_disconnect_req (SOCK_INFO *sock_info); +ST_VOID np_disconnect_ind (SOCK_INFO *sock_info); + +ST_RET sockets_init (ST_INT max_num_conns); +ST_VOID sockets_end (ST_VOID); +ST_RET spawn_listen (SOCKET hSock); +ST_RET spawn_read (SOCK_INFO *sock_info); +ST_VOID handle_accepted_conn (SOCK_INFO *sock_info); +ST_VOID handle_connect_success (SOCK_INFO *sock_info); +ST_VOID handle_connect_fail (SOCK_INFO *sock_info); +ST_VOID handle_data (SOCK_INFO *sock_info, ST_UCHAR *tpkt_ptr, ST_UINT16 tpkt_len); +ST_VOID handle_disconnect (SOCK_INFO *sock_info); +SOCK_INFO *sock_info_alloc (SOCKET hSock, ST_INT state, ST_LONG user_conn_id); +ST_VOID sock_info_free (SOCK_INFO *sock_info); + +#if defined (_WIN32) +void ThreadSockListen (void *param); +void ThreadSockRead (void *param); +#endif /* _WIN32 */ +#if defined (__OS2__) +void _Optlink ThreadSockListen (void *param); +void _Optlink ThreadSockRead (void *param); +#endif /* __OS2__ */ + +int slistend (int arg1); +int sreadd (int arg1, int arg2, int arg3, int arg4, int arg5, int arg6); + +/************************************************************************/ +/* Code used by MMSEASE_MOSI. */ +/* Defines, etc. for interfacing to "rfc1006_listener" task. */ +/* Only used on LINUX, but the code should be portable to most UNIX-like*/ +/* systems. */ +/************************************************************************/ + +#if defined(MMSEASE_MOSI) +/* use the same task name and the UNIX domain listen socket name to */ +/* easy associate each other when viewing for example network stats */ +#if defined(linux) || defined(sun) +#define RFC1006_LISTENER_EXE_PATH "/usr/sisco/bin" +#define RFC1006_LISTENER_IPC_PATH "/tmp" +#endif +#if defined(__hpux) +#define RFC1006_LISTENER_EXE_PATH "/opt/sisco/bin" +#define RFC1006_LISTENER_IPC_PATH "/tmp" +#endif +#define RFC1006_LISTENER_NAME "rfc1006listenerd" +#define RFC1006_LISTENER_DOMSOCK "rfc1006listenerd.domsock" +#define RFC1006_LISTENER_LOG "rfc1006listenerd.log" + +#define RFC1006_IPC_MAGIC_NUM 0xBADC +/* defines for "opcode" in RFC1006_IPC_MSG. */ +#define RFC1006_IPC_OP_START 1 /* start RFC1006_LISTENER daemon */ +#define RFC1006_IPC_OP_STOP 2 /* stop RFC1006_LISTENER daemon */ +#define RFC1006_IPC_OP_BIND 3 +#define RFC1006_IPC_OP_UNBIND 4 +#define RFC1006_IPC_OP_CONNECT 5 /* TP0 connect indication */ +#define RFC1006_IPC_OP_SET_LOG 6 /* change RFC1006_LISTENER log masks */ + +typedef struct rfc1006_ipc_msg_tag + { + ST_UINT16 magic; /* always == RFC1006_IPC_MAGIC_NUM */ + ST_UINT16 opcode; /* one of RFC1006_IPC_OP.. values */ + ST_UINT16 data_len; /* length of data following this msg */ + } RFC1006_IPC_MSG; + +extern ST_BOOLEAN use_rfc1006_listener_task; +extern SOCKET domsock_listener; /* domain socket connected to the */ + /* RFC1006_LISTENER task. */ +ST_INT recvwait (SOCKET hSock, ST_VOID *buf, ST_INT numBytes, int flags); +ST_INT sendwait (SOCKET hSock, ST_VOID *buf, ST_INT numBytes, int flags); + +ST_RET setListenerIPCDir (ST_CHAR *dirPath); + +#endif /* defined(MMSEASE_MOSI) */ + +#ifdef __cplusplus +} +#endif + +#endif /* !TP0_SOCK_INCLUDED */ + diff --git a/include/inc/tp4.h b/include/inc/tp4.h new file mode 100644 index 0000000..1c2b1cf --- /dev/null +++ b/include/inc/tp4.h @@ -0,0 +1,363 @@ +#ifndef TP4_INCLUDED +#define TP4_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2005 All Rights Reserved */ +/* */ +/* MODULE NAME : tp4.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* TP4 main header file. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/22/08 JRB 17 Add TPDU_ER structure. */ +/* 03/29/05 EJV 16 MMSEASE_MOSI: added tp0_check_... protos. */ +/* 01/13/04 EJV 15 Changed tp0_send_... funcs to return value. */ +/* 06/27/02 JRB 14 Add tp_dr_reason to TP_CONN. */ +/* 10/25/01 JRB 13 Move replacement func macros to tp4api.h */ +/* 05/07/01 JRB 12 Add loc_tsap, rem_tsap to TP_CONN, TP0_CONN. */ +/* 07/19/99 RKR 11 Modified a macro so this file will install */ +/* 06/08/99 JRB 10 Allow up to 1024 connections by using new */ +/* macros to compute loc_ref_offset & loc_ref. */ +/* 08/13/98 JRB 09 Lint cleanup. */ +/* 08/14/97 JRB 08 Use MAX_TSEL_LEN defined in tp4api.h */ +/* Add max_tpdu_len (negotiated) to TP_CONN. */ +/* Add TP0/RFC1006 support defines & protos. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/21/97 JRB 07 Add tp_free_spdu_all function. */ +/* 02/20/97 EJV 06 Add session_timer to TP_CONN for MOSI implem.*/ +/* 10/04/96 JRB 05 Add global variable max_tpdu_len_enc. */ +/* Chg TPDU_CX param to max_tpdu_len_enc. */ +/* 10/04/96 JRB 04 Chg send_ak_flag to ak_delay. */ +/* 09/09/96 JRB 03 Add send_ak_flag to TP_CONN. */ +/* 09/09/96 JRB 02 Add tp_send_cr, tp_setup_and_send_??, */ +/* tp_send_dt_and_ak & tp_conn_clean prototypes.*/ +/* 07/17/96 JRB 01 Created */ +/************************************************************************/ +#include "tp4api.h" /* need some TP4 user defs. */ +#include "clnp_usr.h" /* TP4 uses CLNP user interface. */ + +#if defined (TP0_ENABLED) +#include "tp0_sock.h" /* TP0/RFC1006 sockets interface defs. */ +#endif /* TP0_ENABLED */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define TP_MAX_CONN_UDATA 32 +#define TP4_EXCEPT() tp4_except (thisFileName, __LINE__) + +/************************************************************************/ +/* The following defines used in computing "loc_ref" (16-bit value): */ +/* TP_CONN_ID_BITS: number of bits to use for conn_id in loc_ref. */ +/* TP_MAX_NUM_CONNS: max number of connections allowed. */ +/* TP_CONN_ID_MASK: mask used to find conn_id in loc_ref. */ +/* TP_LOC_REF_MOD: modulus to use for loc_ref_offset wrap around. */ +/* When loc_ref_offset incremented to this value, */ +/* go back to 1 (not 0 so loc_ref can never be 0). */ +/* TP_CONN_ID_BITS, TP_CONN_ID_MASK, TP_MAX_NUM_CONNS & TP_LOC_REF_MOD */ +/* are all related. If one changes, they must all change. */ +/************************************************************************/ +#define TP_CONN_ID_BITS 10 +#define TP_CONN_ID_MASK 0x3ff /* 0000 0011 1111 1111 binary */ +#define TP_MAX_NUM_CONNS 0x400 /* conn_id = 0 thru 0x3ff */ +/* If 10 bits used for conn_id, 6 bits left for loc_ref_offset, so it */ +/* must wrap around when it reaches 0100 0000 binary (i.e. 0x40). */ +#define TP_LOC_REF_MOD 0x40 /* modulus for 6-bit value */ + +/************************************************************************/ +/* Structure typedefs. */ +/************************************************************************/ + +/* TPDU_CX - Used for CR or CC TPDU info. */ +typedef struct + { + /* NOTE: the following options not supported: */ + /* Transport Expedited Data. */ + /* Non-use of checksum. */ + /* Use of extended format. */ + /* When sending CR, don't request any. */ + /* When sending CC, don't accept any. */ + + ST_UCHAR loc_tsap [1+MAX_TSEL_LEN]; /* Local len & TSAP addr */ + ST_UCHAR rem_tsap [1+MAX_TSEL_LEN]; /* Remote len & TSAP addr */ + ST_UINT16 loc_ref; /* Local Reference for conn. */ + ST_UINT16 rem_ref; /* Remote Reference for conn. */ + ST_UCHAR max_tpdu_len_enc; /* Negotiated Max TPDU len (encoded). */ + ST_UCHAR preferred_class; /* Preferred Transport Class 0-4 */ + ST_UCHAR cdt; /* CDT */ + ST_UCHAR *rem_mac; /* Remote MAC addr */ + ST_UCHAR *rem_nsap; /* Remote len & NSAP addr */ + ST_UINT16 udata_len; /* Length of CR/CC User Data. */ + ST_CHAR udata_buf [TP_MAX_CONN_UDATA]; /* Buffer for CR/CC User Data. */ +#if defined (TP0_ENABLED) + SOCK_INFO *sock_info; /* socket info for TP0 conns only */ +#endif /* TP0_ENABLED */ + } TPDU_CX; + +typedef struct + { + ST_UINT16 loc_ref; /* Local Reference for conn. */ + ST_UINT16 rem_ref; /* Remote Reference for conn. */ + ST_UCHAR reason; /* Reason for disconnect. */ + ST_UCHAR *rem_mac; /* Remote MAC addr */ + ST_UCHAR *rem_nsap; /* Remote len & NSAP addr */ +#if defined (TP0_ENABLED) + SOCK_INFO *sock_info; /* socket info for TP0 conns only */ +#endif /* TP0_ENABLED */ + } TPDU_DR; + +typedef TPDU_DR TPDU_DC; /* Same as DR but ignore "reason". */ + +typedef struct + { + ST_UINT16 dst_ref; /* Dest Reference for conn. */ + ST_UCHAR sn; + ST_UCHAR cdt; + ST_UCHAR *rem_mac; /* Remote MAC addr */ + ST_UCHAR *rem_nsap; /* Remote len & NSAP addr */ + } TPDU_AK; + +typedef struct + { + ST_UINT16 dst_ref; /* Dest Reference for conn. */ + ST_UCHAR sn; /* Sequence #. */ + ST_BOOLEAN eot; /* DT TPDU contains or should contain EOT flag */ + ST_UCHAR *rem_mac; /* Remote MAC addr */ + ST_UCHAR *rem_nsap; /* Remote len & NSAP addr */ + ST_CHAR *udata_ptr; /* Pointer to DT User Data. */ + ST_UINT16 udata_len; /* Length of DT User Data. */ +#if defined (TP0_ENABLED) + SOCK_INFO *sock_info; /* socket info for TP0 conns only */ +#endif /* TP0_ENABLED */ + } TPDU_DT; + +typedef struct + { + ST_UINT16 dst_ref; /* Dest Reference for conn. */ + ST_UCHAR reject_cause; /* reason for error (0-3) */ + ST_UCHAR *invalid_tpdu_ptr; /* Pointer to TPDU hdr that caused reject*/ + ST_UCHAR invalid_tpdu_len; /* Length of TPDU hdr that caused reject*/ + /* NOTE: <= 255 (must fit in 1 byte). */ + ST_UCHAR *rem_mac; /* Remote MAC addr */ + ST_UCHAR *rem_nsap; /* Remote len & NSAP addr */ +#if defined (TP0_ENABLED) + SOCK_INFO *sock_info; /* socket info for TP0 conns only */ +#endif /* TP0_ENABLED */ + } TPDU_ER; + +typedef struct + { + ST_CHAR *spdu_ptr; /* Pointer to SPDU. */ + ST_UINT spdu_len; /* Length of SPDU. */ + ST_UINT offset; /* Offset into SPDU. */ + } SPDU_INFO; + +typedef struct + { + /* NOTE: "state" is first in this struct because it will be */ + /* accessed most often (every time connection made must scan array */ + /* for a TP_CONN with state == TP_STATE_CLOSED). */ + ST_UCHAR state; /* State of connection (initially CLOSED). */ + ST_UCHAR tp_dr_reason; /* reason for disconnect (0 if connected)*/ + ST_UINT16 loc_ref_offset; /* Used to compute loc_ref (see calc_loc_ref)*/ + ST_UINT16 rem_ref; /* Peer's reference # for this connection. */ + ST_UINT16 window_time; /* Window Time */ + ST_UINT16 inact_time; /* Inactivity Time */ + ST_UINT16 retrans_time; /* Retransmission Time */ + ST_UCHAR lower_tx_sn; /* Sequence # for peer's lower window edge. */ + ST_UCHAR adj_rem_cdt; /* Last CDT received from peer. */ + /* Adjusted to stay within our limits. */ + ST_UCHAR next_tx_sn; /* Sequence # for next TPDU to send to peer. */ + ST_UCHAR next_rx_sn; /* Sequence # for next TPDU to receive from peer*/ + TPDU_DT *tpdu_dt_tx; /* ptr to array of "max_rem_cdt" structs */ + /* Allocated by tp4_initialize (). */ + + ST_UCHAR num_spdu_outst; /* # of SPDUs outstanding */ + ST_UCHAR spdu_cnt_qued; /* Count of SPDUs queued. Goes to 0 on overflow */ + ST_UCHAR spdu_cnt_sent; /* Count of SPDUs sent. Goes to 0 on overflow */ + ST_UCHAR spdu_cnt_done; /* Count of SPDUs done. Goes to 0 on overflow */ + SPDU_INFO *spdu_tx; /* ptr to array of "max_spdu_outst" structs */ + SPDU_INFO spdu_rx; /* Struct for one received SPDU */ + ST_BOOLEAN spdu_rx_start; /* Next TPDU rcvd is start of SPDU. */ + /* Save rem_mac & rem_nsap received from CLNP with CR or CC. */ + ST_UCHAR rem_mac [CLNP_MAX_LEN_MAC]; /* Remote MAC addr */ + ST_UCHAR rem_nsap [1+CLNP_MAX_LEN_NSAP]; /* Remote len & NSAP addr */ + ST_UCHAR num_trans; /* (TX ONLY) # of times a TPDU transmitted */ + ST_LONG user_conn_id; /* User's ID for this conn. */ + TPDU_CX tpdu_cx; /* CR or CC Info to Send/Receive. */ + ST_UCHAR ak_delay; /* # of loops to delay sending AK. */ + + ST_UINT16 session_timer; /* Session timer for MOSI implementation */ + ST_UINT16 max_tpdu_len; /* Negotiated TPDU len on this conn. */ + ST_UCHAR loc_tsap [1+MAX_TSEL_LEN]; /* Local len & TSAP addr */ + ST_UCHAR rem_tsap [1+MAX_TSEL_LEN]; /* Remote len & TSAP addr */ + } TP_CONN; + +typedef struct + { + /* NOTE: "state" is first in this struct because it will be */ + /* accessed most often (every time connection made must scan array */ + /* for a TP_CONN with state == TP_STATE_CLOSED). */ + ST_UCHAR state; /* State of connection (initially CLOSED). */ + ST_UINT16 loc_ref_offset; /* Used to compute loc_ref (see calc_loc_ref)*/ + ST_UINT16 rem_ref; /* Peer's reference # for this connection. */ + + SPDU_INFO spdu_rx; /* Struct for one received SPDU */ + ST_BOOLEAN spdu_rx_start; /* Next TPDU rcvd is start of SPDU. */ + ST_LONG user_conn_id; /* User's ID for this conn. */ + TPDU_CX tpdu_cx; /* CR or CC Info to Send/Receive. */ + + ST_UINT16 session_timer; /* Session timer for MOSI implementation */ + ST_UINT16 max_tpdu_len; /* Negotiated TPDU len on this conn. */ +#if defined (TP0_ENABLED) + SOCK_INFO *sock_info; /* socket info for TP0 conns only */ +#endif /* TP0_ENABLED */ + ST_UCHAR loc_tsap [1+MAX_TSEL_LEN]; /* Local len & TSAP addr */ + ST_UCHAR rem_tsap [1+MAX_TSEL_LEN]; /* Remote len & TSAP addr */ + } TP0_CONN; + +/************************************************************************/ +/* Miscellaneous Defines. */ +/************************************************************************/ +#define MODULUS_SN 128 /* Sequence # Modulus (2**7) */ + +/************************************************************************/ +/* Defines for TP4 connection states. */ +/************************************************************************/ +#define TP_STATE_CLOSED 0 +#define TP_STATE_WFCC 1 +#define TP_STATE_WBCL 2 +#define TP_STATE_OPEN 3 +#define TP_STATE_WFTRESP 4 +#define TP_STATE_AKWAIT 5 +#define TP_STATE_CLOSING 6 +#define TP_STATE_WFNC 7 /* for TP0/RFC1006 only */ + +/************************************************************************/ +/* Defines for types of TPDUs. */ +/************************************************************************/ +#define TPDU_TYPE_CR 0 +#define TPDU_TYPE_CC 1 +#define TPDU_TYPE_DR 2 +#define TPDU_TYPE_DC 3 +#define TPDU_TYPE_DT 4 +#define TPDU_TYPE_AK 5 + +/************************************************************************/ +/* Miscellaneous defines. */ +/************************************************************************/ +#define MIN_TP0_CONN_ID 10000 /* min tp_conn_id for TP0 so */ + /* don't overlap with TP4 id's */ + +/* WARNING: We assume TP_MAX_NUM_CONNS <= MIN_TP0_CONN_ID so TP0 conn */ +/* id's can't overlap with TP4 conn id's. */ +/* Let's just make sure this assumption is valid. */ +#if (TP_MAX_NUM_CONNS > MIN_TP0_CONN_ID) +#error TP_MAX_NUM_CONNS > MIN_TP0_CONN_ID. Definitions incompatible. +#endif + +/************************************************************************/ +/* Global variables. */ +/************************************************************************/ +extern TP_CONN *tp_conn_arr; /* ptr to array of "max_num_conns" structs */ +extern ST_LONG only_tp4_bind_id; /* Only one tp4_bind_id. */ +extern ST_LONG only_user_bind_id; /* Only one user_bind_id. */ +extern ST_UCHAR only_loc_tsap []; /* Local len & TSAP addr */ +extern ST_UCHAR max_tpdu_len_enc; /* Binary encoded MAX TPDU len. */ + +extern TP0_CONN *tp0_conn_arr; /* ptr to array of "max_num_conns" structs */ +extern ST_LONG only_tp0_bind_id; /* Only one tp0_bind_id. */ +extern ST_LONG only_tp0_user_bind_id; /* Only one tp0_user_bind_id. */ +extern ST_UCHAR only_tp0_loc_tsap []; /* Local len & TSAP addr */ + +/************************************************************************/ +/* Prototypes */ +/************************************************************************/ +ST_VOID tp_setup_and_send_ak (TP_CONN *tp_conn); +ST_VOID tp_setup_and_send_dr (TP_CONN *tp_conn); + +ST_VOID tp_send_cr (TPDU_CX *tpdu_cr); +ST_VOID tp_send_cc (TPDU_CX *tpdu_cc); +ST_VOID tp_send_dr (TPDU_DR *tpdu_dr); +ST_VOID tp_send_dc (TPDU_DC *tpdu_dc); +ST_VOID tp_send_dt (TPDU_DT *tpdu_dt); +ST_VOID tp_send_ak (TPDU_AK *tpdu_ak); +ST_VOID tp_send_dt_and_ak (TPDU_DT *tpdu_dt, TPDU_AK *tpdu_ak); + +ST_VOID tp_process_cr (TPDU_CX *tpdu_cr_rx); +ST_VOID tp_process_cc (TPDU_CX *tpdu_cc_rx); +ST_VOID tp_process_dr (TPDU_DR *tpdu_dr_rx); +ST_VOID tp_process_dc (TPDU_DC *tpdu_dc_rx); +ST_VOID tp_process_dt (TPDU_DT *tpdu_dt_rx); +ST_VOID tp_process_ak (TPDU_AK *tpdu_ak_rx); +ST_VOID tp_conn_clean (TP_CONN *tp_conn); +ST_VOID tp_free_spdu_all (TP_CONN *tp_conn); + +ST_RET tp0_send_cr (TPDU_CX *tpdu_cr); +ST_RET tp0_send_cc (TPDU_CX *tpdu_cc); +ST_RET tp0_send_dr (TPDU_DR *tpdu_dr); +ST_RET tp0_send_dt (TPDU_DT *tpdu_dt); + +ST_VOID tp0_process_cr (TPDU_CX *tpdu_cr_rx); +ST_VOID tp0_process_cc (TPDU_CX *tpdu_cc_rx); +ST_VOID tp0_process_dr (TPDU_DR *tpdu_dr_rx); +ST_VOID tp0_process_dt (TPDU_DT *tpdu_dt_rx); + +ST_VOID tp0_conn_clean (TP0_CONN *tp_conn); + +#if defined(MMSEASE_MOSI) +ST_RET tp0_check_tsel (ST_UCHAR *tsel, ST_LONG *user_bind_id); +ST_RET tp0_check_bind_id (ST_LONG bind_id, ST_UCHAR **tsel); +#endif + +/************************************************************************/ +/* Macros. */ +/************************************************************************/ + +/*----------------------------------------------------------------------*/ +/* inc_loc_ref_offset */ +/* Increment "loc_ref_offset". When the value reaches TP_LOC_REF_MOD */ +/* (defined above), wrap around back to 1. */ +/* NOTE: We do not wrap to 0, so "loc_ref_offet" will never be 0. */ +/* "loc_ref_offset" is used to compute "loc_ref", so "loc_ref" */ +/* will also never be 0. */ +/* Arg #1: value (i.e. loc_ref_offset) to be incremented */ +/* Example of usage: */ +/* inc_loc_ref_offset (tp_conn->loc_ref_offset); */ +/*----------------------------------------------------------------------*/ +#define inc_loc_ref_offset(value) {\ + if (++(value) >= TP_LOC_REF_MOD) \ + (value) = 1; } /* comment necessary for DDB installation tool */ + +/*----------------------------------------------------------------------*/ +/* calc_loc_ref */ +/* Calculate loc_ref from conn_id and loc_ref_offset. */ +/* IMPORTANT: loc_ref_offset MUST NEVER be 0, so loc_ref will never be 0.*/ +/* This is accomplished by using ONLY the "inc_loc_ref_offset"*/ +/* macro above to change the value of "loc_ref_offset". */ +/*----------------------------------------------------------------------*/ +#define calc_loc_ref(conn_id,loc_ref_offset) \ + ((conn_id) | ((loc_ref_offset) << TP_CONN_ID_BITS)) + +/*----------------------------------------------------------------------*/ +/* calc_conn_id */ +/* Calculate conn_id from loc_ref. */ +/*----------------------------------------------------------------------*/ +#define calc_conn_id(loc_ref) \ + ((loc_ref) & TP_CONN_ID_MASK) + +#ifdef __cplusplus +} +#endif + +#endif /* !TP4_INCLUDED */ + diff --git a/include/inc/tp4_encd.h b/include/inc/tp4_encd.h new file mode 100644 index 0000000..051d46d --- /dev/null +++ b/include/inc/tp4_encd.h @@ -0,0 +1,407 @@ +#ifndef TP4_ENCD_INCLUDED +#define TP4_ENCD_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996 - 2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : tp4_encd.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file defines structures and functions for */ +/* encoding/decoding of class 4 TPDUs. */ +/* */ +/* Note: The following TP options are NOT supported: */ +/* Transport Expedited Data */ +/* Non-use of checksum */ +/* Use of extended format. */ +/* This is reflected in structures and defines below. */ +/* */ +/* For information see the: */ +/* ISO 8073 "Information processing systems - Open Systems */ +/* Interconnections - Connection oriented transport protocol */ +/* specification. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/22/08 JRB 08 tp_decode_ak(_dc,_er): change args. */ +/* Delete tp_decode_rj (not used in TP0 or TP4).*/ +/* 11/01/07 EJV 07 Added comments. */ +/* 05/25/05 EJV 06 Added include tp4.h */ +/* 01/28/99 JRB 05 Move cltp_decode_nsdu proto to ACSE file. */ +/* 12/01/97 JRB 04 CRITICAL: Don't use "sizeof" on structures. */ +/* Caused padding on VXWORKS. */ +/* 08/14/97 JRB 03 Add TP0/RFC1006 support defines & protos. */ +/* Add tp_decode_* protos (were static before). */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 11/22/96 JRB 02 Add TP_PDU_TYPE_UD & cltp_decode_nsdu for CLTP.*/ +/* 06/20/96 EJV 01 Created */ +/************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +#include "tp4.h" + + /* encoding for Transport Protocol class and options */ + +#define TP_CLASS_0 (ST_UCHAR) 0x00 +#define TP_CLASS_1 (ST_UCHAR) 0x10 +#define TP_CLASS_2 (ST_UCHAR) 0x20 +#define TP_CLASS_3 (ST_UCHAR) 0x30 +#define TP_CLASS_4 (ST_UCHAR) 0x40 + +#define TP_OPT_FORMAT_NORMAL (ST_UCHAR) 0x00 +#define TP_OPT_FORMAT_EXTENDED (ST_UCHAR) 0x02 + +#define TP_CLASS_4_NORMAL (ST_UCHAR) (TP_CLASS_4 | TP_OPT_FORMAT_NORMAL) +#define TP_CLASS_4_EXT (ST_UCHAR) (TP_CLASS_4 | TP_OPT_FORMAT_EXTENDED) + +#define TP_CLASS_MASK_OPT (ST_UCHAR) 0xF0 /* for masking opt in ASN1_CLASS_METHOD-OPT in CR */ + + /* encoding for TPDU type code */ + +#define TP_PDU_TYPE_CR (ST_UCHAR) 0xE0 /* 1110 xxxx */ +#define TP_PDU_TYPE_CC (ST_UCHAR) 0xD0 /* 1101 xxxx */ +#define TP_PDU_TYPE_DR (ST_UCHAR) 0x80 /* 1000 0000 */ +#define TP_PDU_TYPE_DC (ST_UCHAR) 0xC0 /* 1100 0000 */ +#define TP_PDU_TYPE_DT (ST_UCHAR) 0xF0 /* 1111 0000 */ +#define TP_PDU_TYPE_ED (ST_UCHAR) 0x10 /* 0001 0000 */ +#define TP_PDU_TYPE_AK (ST_UCHAR) 0x60 /* 0110 zzzz */ +#define TP_PDU_TYPE_EA (ST_UCHAR) 0x20 /* 0010 0000 */ +#define TP_PDU_TYPE_RJ (ST_UCHAR) 0x50 /* 0101 zzzz */ +#define TP_PDU_TYPE_ER (ST_UCHAR) 0x70 /* 0111 0000 */ +#define TP_PDU_TYPE_UD (ST_UCHAR) 0x40 /* 0100 0000 for CLTP */ + +#define TP_PDU_MASK_TYPE (ST_UCHAR) 0x0F /* for masking type to get CDT */ +#define TP_PDU_MASK_CDT (ST_UCHAR) 0xF0 /* for masking CTD to get type */ + +/* encoding for max size of TPDU (parameter in the CR) */ + +#define TP_PDU_MAX_SIZE_65531 (ST_UCHAR) 0x0E /* kluge for TP0/RFC1006 only*/ +#define TP_PDU_MAX_SIZE_8192 (ST_UCHAR) 0x0D +#define TP_PDU_MAX_SIZE_4096 (ST_UCHAR) 0x0C +#define TP_PDU_MAX_SIZE_2048 (ST_UCHAR) 0x0B +#define TP_PDU_MAX_SIZE_1024 (ST_UCHAR) 0x0A +#define TP_PDU_MAX_SIZE_512 (ST_UCHAR) 0x09 +#define TP_PDU_MAX_SIZE_256 (ST_UCHAR) 0x08 +#define TP_PDU_MAX_SIZE_128 (ST_UCHAR) 0x07 + +/* encoding EOT in DT TPDU - bit 8 */ + +#define TP_PDU_EOF (ST_UCHAR) 0x80 + +#define TP_PDU_MASK_EOF (ST_UCHAR) 0x7F /* for masking EOF to get SN (DT)*/ +#define TP_PDU_MASK_SN (ST_UCHAR) 0x80 /* for masking SN to get EOF (DT)*/ + +#define TP_PDU_MASK_BIT8 (ST_UCHAR) 0x7F /* for masking bit 8 to get SN (AK)*/ + +/* encoding for DR reason */ +/* for class 1 - 4 */ +#define TP_DR_NORMAL (ST_UCHAR) 0x80 +#define TP_DR_CONGESTION (ST_UCHAR) 0x81 +#define TP_DR_CLASS_UNSUPPORTED (ST_UCHAR) 0x82 +#define TP_DR_DUPLICATE_SRC_REF (ST_UCHAR) 0x83 +#define TP_DR_INVALID_REF (ST_UCHAR) 0x84 +#define TP_DR_PROT_ERROR (ST_UCHAR) 0x85 +#define TP_DR_REF_OVERFLOW (ST_UCHAR) 0x87 +#define TP_DR_CR_REFUSED (ST_UCHAR) 0x88 +#define TP_DR_HDR_INVALID (ST_UCHAR) 0x8A + +/* for all classes (TP0) */ +#define TP_DR_NO_REASON (ST_UCHAR) 0x00 +#define TP_DR_CONGESTION_AT_TSAP (ST_UCHAR) 0x01 +#define TP_DR_NO_SESSION (ST_UCHAR) 0x02 +#define TP_DR_ADDR_UNKNOWN (ST_UCHAR) 0x03 + + +/* misc defines */ + +#define TP_MAX_CDT (ST_UCHAR) 0x0F + + + + /*----------------------------------------------*/ + /* Encoding and structures for TP parameters */ + /*----------------------------------------------*/ + + /* encoding for TP version */ + +#define TP_VERSION (ST_UCHAR) 0x01 + + /* encoding for the parameter code in CR or CC TPDU variable part */ + +#define TP_PAR_CODE_TSAP_CALLING (ST_UCHAR) 0xC1 +#define TP_PAR_CODE_TSAP_CALLED (ST_UCHAR) 0xC2 +#define TP_PAR_CODE_TPDU_SIZE (ST_UCHAR) 0xC0 +#define TP_PAR_CODE_VERSION (ST_UCHAR) 0xC4 +#define TP_PAR_CODE_ADD_OPTIONS (ST_UCHAR) 0xC6 + + /* encoding for the parameter code in AK TPDU variable part */ + +#define TP_PAR_CODE_AK_SUB_SN (ST_UCHAR) 0x8A +#define TP_PAR_CODE_AK_FLOW_CTRL (ST_UCHAR) 0x8C + + /* encoding for the parameter code in ER TPDU variable part */ + +#define TP_PAR_CODE_ER_INVAL_TPDU (ST_UCHAR) 0xC1 + + /* encoding for the parameter code in variable part (common to */ + /* different TPDU types) */ + +#define TP_PAR_CODE_CHECKSUM (ST_UCHAR) 0xC3 + + + /* encoding for CR TPDU additional options */ + +#define TP_OPT_CHECKSUM_USE (ST_UCHAR) 0x00 +#define TP_OPT_CHECKSUM_NON_USE (ST_UCHAR) 0x02 + +#define TP_OPT_EXPEDITED_NON_USE (ST_UCHAR) 0x00 +#define TP_OPT_EXPEDITED_USE (ST_UCHAR) 0x01 + + +typedef struct + { + ST_UCHAR code; /* parameter code */ + ST_UCHAR len; /* Parameter length */ + ST_UCHAR value [2]; /* parameter value has variable length */ + /* (defined as 2 bytes buffer, the ptr */ + /* will allow us to access any len param*/ + }TP_PAR; + +#define TP_PAR_FIX_LEN 2 + /* define above specifies only the fixed part */ + /* of parameter (code and len) */ + + /* some parameters are fixed in size so we can define them here */ + + /* parameters length in CR or CC */ + +#define TP_PAR_LEN_TPDU_SIZE (TP_PAR_FIX_LEN + 1) +#define TP_PAR_LEN_VERSION (TP_PAR_FIX_LEN + 1) +#define TP_PAR_LEN_ADD_OPTIONS (TP_PAR_FIX_LEN + 1) + + /* parameters length in AK */ + +#define TP_PAR_LEN_AK_SUB_SN (TP_PAR_FIX_LEN + 2) +#define TP_PAR_LEN_AK_FLOW_CTRL (TP_PAR_FIX_LEN + 8) + + /* parameters length (common to different types of TPDU types) */ + +#define TP_PAR_LEN_CHECKSUM (TP_PAR_FIX_LEN + 2) + +/* ! */ +/* NOTE: ! only ST_UCHAR type should be in protocol structs to avoid */ +/* ! packing or problems with sizeof operator. */ +/* ! */ + + + /*----------------------------------------------*/ + /* Struct and defines for CR and CC TPDU */ + /*----------------------------------------------*/ + +typedef struct + { + /* fixed part of header */ + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type_cdt; /* TPDU type and CDT */ + ST_UCHAR dest_ref [2]; /* Remote connection id (set to 0) */ + ST_UCHAR src_ref [2]; /* Local connection id */ + ST_UCHAR class_opt; /* Class and options */ + }TP_FHDR_CX; + +#define TP_FHDR_CX_LEN 7 + + /* for alloc of n_unitdata purposes the max len will be used */ + /* fixed part of header */ + /* local & remote TSAP */ + /* TPDU size parameter */ + /* TP version parameter */ + /* checksum parameter */ + /* additional opt param */ + /* user data (max allowed)*/ + +#define TP_MAX_LEN_CX (TP_FHDR_CX_LEN + \ + 2*(TP_PAR_FIX_LEN + MAX_TSEL_LEN) + \ + TP_PAR_LEN_TPDU_SIZE + \ + TP_PAR_LEN_VERSION + \ + TP_PAR_LEN_CHECKSUM + \ + TP_PAR_LEN_ADD_OPTIONS + \ + TP_MAX_CONN_UDATA) + + /*--------------------------------------*/ + /* Struct and defines for DR TPDU */ + /*--------------------------------------*/ + +typedef struct + { + /* fixed part of header */ + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type; /* TPDU type */ + ST_UCHAR dest_ref [2]; /* Remote connection id (set to 0) */ + ST_UCHAR src_ref [2]; /* Local connection id */ + ST_UCHAR reason; /* Reason code for disconnect */ + }TP_FHDR_DR; + +#define TP_FHDR_DR_LEN 7 + + /* for alloc of n_unitdata the max len will be used. */ + +#define TP_MAX_LEN_DR (TP_FHDR_DR_LEN + TP_PAR_LEN_CHECKSUM) + + /* no additional info parameter or user data in DR */ + + /*--------------------------------------*/ + /* Struct and defines for DC TPDU */ + /*--------------------------------------*/ + +typedef struct + { + /* fixed part of header */ + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type; /* TPDU type */ + ST_UCHAR dest_ref [2]; /* Remote connection id (set to 0) */ + ST_UCHAR src_ref [2]; /* Local connection id */ + }TP_FHDR_DC; + +#define TP_FHDR_DC_LEN 6 + + /* for alloc of n_unitdata the max len will be used. */ + +#define TP_MAX_LEN_DC (TP_FHDR_DC_LEN + TP_PAR_LEN_CHECKSUM) + + + /*--------------------------------------*/ + /* Struct and defines for DT TPDU */ + /*--------------------------------------*/ + +typedef struct + { + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type; /* TPDU type */ + ST_UCHAR dest_ref [2]; /* Remote connection id */ + ST_UCHAR eot_sn; /* EOT flag and sequence number */ + }TP_FHDR_DT; + +#define TP_FHDR_DT_LEN 5 + + /* for alloc of n_unitdata use TP_HEAD_LEN_DT + udata_len */ + +#define TP_HEAD_LEN_DT (ST_UINT16)(TP_FHDR_DT_LEN + TP_PAR_LEN_CHECKSUM) + +/* TP0 DT same as TP4 except doesn't use DST-REF. */ +typedef struct + { + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type; /* TPDU type */ + ST_UCHAR eot_sn; /* EOT flag and sequence number */ + }TP0_FHDR_DT; + +#define TP0_FHDR_DT_LEN 3 +#define TP0_HEAD_LEN_DT (ST_UINT16)(TP0_FHDR_DT_LEN) /* no chksum*/ + + + /*--------------------------------------*/ + /* Struct and defines for AK TPDU */ + /*--------------------------------------*/ + + +typedef struct + { + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type_cdt; /* TPDU type and CDT */ + ST_UCHAR dest_ref [2]; /* Remote connection id */ + ST_UCHAR sn; /* Next expected DT TPDU sequence number*/ + }TP_FHDR_AK; + +#define TP_FHDR_AK_LEN 5 + + /* for alloc of n_unitdata the max len will be used. */ + +#define TP_MAX_LEN_AK (TP_FHDR_AK_LEN + TP_PAR_LEN_CHECKSUM) + + + /*--------------------------------------*/ + /* Struct and defines for RJ TPDU */ + /*--------------------------------------*/ + +typedef struct + { + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type_cdt; /* TPDU type and CDT */ + ST_UCHAR dest_ref [2]; /* Remote connection id */ + ST_UCHAR sn; /* Next expected DT TPDU sequence number*/ + }TP_FHDR_RJ; + +#define TP_FHDR_RJ_LEN 5 + + /* for alloc of n_unitdata the max len will be used. */ + +#define TP_MAX_LEN_RJ TP_FHDR_RJ_LEN + + /*--------------------------------------*/ + /* Struct and defines for ER TPDU */ + /*--------------------------------------*/ + +typedef struct + { + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type; /* TPDU type */ + ST_UCHAR dest_ref [2]; /* Remote connection id */ + ST_UCHAR reason; /* Code for reject couse */ + }TP_FHDR_ER; + +#define TP_FHDR_ER_LEN 5 + + /* for alloc of n_unitdata the max len will be used. */ + +#define TP_MAX_LEN_ER (TP_FHDR_ER_LEN + TP_PAR_LEN_CHECKSUM) + + + /*----------------------------------------------*/ + /* Function prototypes for encoding/decoding */ + /*----------------------------------------------*/ + +ST_UINT16 tp_encode_cx (ST_UCHAR *enc_buf, TPDU_CX *tpdu_cx, ST_UCHAR pdu_type); +ST_UINT16 tp_encode_dr (ST_UCHAR *enc_buf, TPDU_DR *tpdu_dr); +ST_UINT16 tp_encode_dc (ST_UCHAR *enc_buf, TPDU_DC *tpdu_dc); +ST_UINT16 tp_encode_dt (ST_UCHAR *enc_buf, TPDU_DT *tpdu_dt); +ST_UINT16 tp0_encode_dt (ST_UCHAR *enc_buf, TPDU_DT *tpdu_dt); +ST_UINT16 tp_encode_ak (ST_UCHAR *enc_buf, TPDU_AK *tpdu_ak); + +ST_RET tp_decode_nsdu (N_UNITDATA *n_unitdata); + +ST_UINT16 tp_decode_cx (TPDU_CX *tpdu_cx_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len, ST_UCHAR pdu_type, ST_UCHAR max_tpdu_len_enc); +ST_UINT16 tp_decode_dr (TPDU_DR *tpdu_dr_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len); +ST_UINT16 tp_decode_dc (TPDU_DC *tpdu_dc_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len); +ST_UINT16 tp_decode_dt (TPDU_DT *tpdu_dt_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len); +ST_UINT16 tp0_decode_dt (TPDU_DT *tpdu_dt_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len); +ST_UINT16 tp_decode_ak (TPDU_AK *tpdu_ak_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len); +ST_UINT16 tp_decode_er (TPDU_ER *tpdu_er_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len, + ST_INT tp_class); /* must be 0 or 4 */ + +ST_VOID tp_log_tsdu (ST_VOID *tsdu, ST_UCHAR type, ST_UCHAR mask); + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + diff --git a/include/inc/tp4_log.h b/include/inc/tp4_log.h new file mode 100644 index 0000000..37694f1 --- /dev/null +++ b/include/inc/tp4_log.h @@ -0,0 +1,228 @@ +#ifndef TP4_LOG_INCLUDED +#define TP4_LOG_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996 - 2008, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : tp4_log.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file contains logging macros for TP. */ +/* Note: To compile logging functions use the DEBUG_SISCO define */ +/* in the project make file. */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/30/08 EJV 05 Converted to new SLOG macros. */ +/* 05/10/05 EJV 04 Added TP_LOG_ERR3. */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 10/08/98 MDE 02 Migrated to updated SLOG interface */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 06/24/96 EJV 01 Created */ +/************************************************************************/ +#include "slog.h" +#include "tp4api.h" /* NOTE the masks are defined in tp4api.h, */ + /* should we include it here? */ + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************/ +/* Log Control types */ +/****************************************************************/ + +/* defined for TP_LOG.._RIn macros */ +#define TP_REQ (ST_UCHAR) 0 +#define TP_IND (ST_UCHAR) 1 + +#if defined(DEBUG_SISCO) + +extern SD_CONST ST_CHAR *SD_CONST _tp4_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _tp4_flowup_logstr; +extern SD_CONST ST_CHAR *SD_CONST _tp4_flowdown_logstr; + + /*--------------------------------------------*/ + /* errors logging */ + /*--------------------------------------------*/ + + #define TP_LOG_ERR0(a) SLOG_0 (tp4_debug_sel & TP4_LOG_ERR,_tp4_err_logstr,a) + #define TP_LOG_ERR1(a,b) SLOG_1 (tp4_debug_sel & TP4_LOG_ERR,_tp4_err_logstr,a,b) + #define TP_LOG_ERR2(a,b,c) SLOG_2 (tp4_debug_sel & TP4_LOG_ERR,_tp4_err_logstr,a,b,c) + #define TP_LOG_ERR3(a,b,c,d) SLOG_3 (tp4_debug_sel & TP4_LOG_ERR,_tp4_err_logstr,a,b,c,d) + + /* continuation log */ + + #define TP_LOGC_ERR0(a) SLOGC_0 (tp4_debug_sel & TP4_LOG_ERR,a) + #define TP_LOGC_ERR1(a,b) SLOGC_1 (tp4_debug_sel & TP4_LOG_ERR,a,b) + #define TP_LOGC_ERR2(a,b,c) SLOGC_2 (tp4_debug_sel & TP4_LOG_ERR,a,b,c) + #define TP_LOGC_ERR3(a,b,c,d) SLOGC_2 (tp4_debug_sel & TP4_LOG_ERR,a,b,c) + + /* hex logging */ + + #define TP_LOGH_ERR(a,b) SLOGH (tp4_debug_sel & TP4_LOG_ERR,a,b) + + /*--------------------------------------------*/ + /* Indication logging */ + /*--------------------------------------------*/ + + #define TP_LOG_IND0(a) SLOG_0 (tp4_debug_sel & TP4_LOG_FLOWUP,_tp4_flowup_logstr,a) + #define TP_LOG_IND1(a,b) SLOG_1 (tp4_debug_sel & TP4_LOG_FLOWUP,_tp4_flowup_logstr,a,b) + #define TP_LOG_IND2(a,b,c) SLOG_2 (tp4_debug_sel & TP4_LOG_FLOWUP,_tp4_flowup_logstr,a,b,c) + #define TP_LOG_IND3(a,b,c,d) SLOG_3 (tp4_debug_sel & TP4_LOG_FLOWUP,_tp4_flowup_logstr,a,b,c,d) + #define TP_LOG_IND4(a,b,c,d,e) SLOG_4 (tp4_debug_sel & TP4_LOG_FLOWUP,_tp4_flowup_logstr,a,b,c,d,e) + #define TP_LOG_IND5(a,b,c,d,e,f) SLOG_5 (tp4_debug_sel & TP4_LOG_FLOWUP,_tp4_flowup_logstr,a,b,c,d,e,f) + #define TP_LOG_IND6(a,b,c,d,e,f,g) SLOG_6 (tp4_debug_sel & TP4_LOG_FLOWUP,_tp4_flowup_logstr,a,b,c,d,e,f,g) + + /* continuation log */ + + #define TP_LOGC_IND0(a) SLOGC_0 (tp4_debug_sel & TP4_LOG_FLOWUP,a) + #define TP_LOGC_IND1(a,b) SLOGC_1 (tp4_debug_sel & TP4_LOG_FLOWUP,a,b) + #define TP_LOGC_IND2(a,b,c) SLOGC_2 (tp4_debug_sel & TP4_LOG_FLOWUP,a,b,c) + + /* hex logging */ + + #define TP_LOGH_IND(a,b) SLOGH (tp4_debug_sel & TP4_LOG_FLOWUP,a,b) + + /* continuation hex logging */ + + #define TP_LOGHC_IND(a,b) SLOGH (tp4_debug_sel & TP4_LOG_FLOWUP,a,b) + + /*--------------------------------------------*/ + /* Request logging */ + /*--------------------------------------------*/ + + #define TP_LOG_REQ0(a) SLOG_0 (tp4_debug_sel & TP4_LOG_FLOWDOWN,_tp4_flowdown_logstr,a) + #define TP_LOG_REQ1(a,b) SLOG_1 (tp4_debug_sel & TP4_LOG_FLOWDOWN,_tp4_flowdown_logstr,a,b) + #define TP_LOG_REQ2(a,b,c) SLOG_2 (tp4_debug_sel & TP4_LOG_FLOWDOWN,_tp4_flowdown_logstr,a,b,c) + #define TP_LOG_REQ3(a,b,c,d) SLOG_3 (tp4_debug_sel & TP4_LOG_FLOWDOWN,_tp4_flowdown_logstr,a,b,c,d) + #define TP_LOG_REQ4(a,b,c,d,e) SLOG_4 (tp4_debug_sel & TP4_LOG_FLOWDOWN,_tp4_flowdown_logstr,a,b,c,d,e) + #define TP_LOG_REQ5(a,b,c,d,e,f) SLOG_5 (tp4_debug_sel & TP4_LOG_FLOWDOWN,_tp4_flowdown_logstr,a,b,c,d,e,f) + #define TP_LOG_REQ6(a,b,c,d,e,f,g) SLOG_6 (tp4_debug_sel & TP4_LOG_FLOWDOWN,_tp4_flowdown_logstr,a,b,c,d,e,f,g) + + /* continuation log */ + + #define TP_LOGC_REQ0(a) SLOGC_0 (tp4_debug_sel & TP4_LOG_FLOWDOWN,a) + #define TP_LOGC_REQ1(a,b) SLOGC_1 (tp4_debug_sel & TP4_LOG_FLOWDOWN,a,b) + #define TP_LOGC_REQ2(a,b,c) SLOGC_2 (tp4_debug_sel & TP4_LOG_FLOWDOWN,a,b,c) + + /* hex logging */ + + #define TP_LOGH_REQ(a,b) SLOGH (tp4_debug_sel & TP4_LOG_FLOWDOWN,a,b) + + /* continuation hex logging */ + + #define TP_LOGHC_REQ(a,b) SLOGH (tp4_debug_sel & TP4_LOG_FLOWDOWN,a,b) + + /*--------------------------------------------------------------------*/ + /* macros below are used to log REQ or IND by passing mask to select */ + /* the logging macro (this is handy in log function so the macros */ + /* do not have to repeated in function for REQ and then for IND) */ + /*--------------------------------------------------------------------*/ + + #define TP_LOG_RI0(m,a) {if (m == TP_REQ) {TP_LOG_REQ0(a);} else {TP_LOG_IND0(a)};} + #define TP_LOG_RI1(m,a,b) {if (m == TP_REQ) {TP_LOG_REQ1(a,b);} else {TP_LOG_IND1(a,b);}} + #define TP_LOG_RI2(m,a,b,c) {if (m == TP_REQ) {TP_LOG_REQ2(a,b,c);} else {TP_LOG_IND2(a,b,c);}} + #define TP_LOG_RI3(m,a,b,c,d) {if (m == TP_REQ) {TP_LOG_REQ3(a,b,c,d);} else {TP_LOG_IND3(a,b,c,d);}} + #define TP_LOG_RI4(m,a,b,c,d,e) {if (m == TP_REQ) {TP_LOG_REQ4(a,b,c,d,e);} else {TP_LOG_IND4(a,b,c,d,e);}} + #define TP_LOG_RI5(m,a,b,c,d,e,f) {if (m == TP_REQ) {TP_LOG_REQ5(a,b,c,d,e,f);} else {TP_LOG_IND5(a,b,c,d,e,f);}} + #define TP_LOG_RI6(m,a,b,c,d,e,f,g) {if (m == TP_REQ) {TP_LOG_REQ6(a,b,c,d,e,f,g);} else {TP_LOG_IND6(a,b,c,d,e,f,g);}} + + #define TP_LOGC_RI0(m,a) {if (m == TP_REQ) {TP_LOGC_REQ0(a);} else {TP_LOGC_IND0(a);}} + #define TP_LOGC_RI1(m,a,b) {if (m == TP_REQ) {TP_LOGC_REQ1(a,b);} else {TP_LOGC_IND1(a,b);}} + #define TP_LOGC_RI2(m,a,b,c) {if (m == TP_REQ) {TP_LOGC_REQ2(a,b,c);} else {TP_LOGC_IND2(a,b,c);}} + + #define TP_LOGH_RI(m,a,b) {if (m == TP_REQ) {TP_LOGH_REQ(a,b);} else {TP_LOGH_IND(a,b);}} + #define TP_LOGHC_RI(m,a,b) {if (m == TP_REQ) {TP_LOGHC_REQ(a,b);} else {TP_LOGHC_IND(a,b);}} + + +#else /* macros if DEBUG_SISCO not defined */ + + /*--------------------------------------------*/ + /* errors logging */ + /*--------------------------------------------*/ + + #define TP_LOG_ERR0(a) + #define TP_LOG_ERR1(a,b) + #define TP_LOG_ERR2(a,b,c) + #define TP_LOG_ERR3(a,b,c,d) + + #define TP_LOGC_ERR0(a) + #define TP_LOGC_ERR1(a,b) + #define TP_LOGC_ERR2(a,b,c) + + #define TP_LOGH_ERR(a,b) + #define TP_LOGHC_ERR(a,b) + + /*--------------------------------------------*/ + /* Indication logging */ + /*--------------------------------------------*/ + + #define TP_LOG_IND0(a) + #define TP_LOG_IND1(a,b) + #define TP_LOG_IND2(a,b,c) + #define TP_LOG_IND3(a,b,c,d) + #define TP_LOG_IND4(a,b,c,d,e) + #define TP_LOG_IND5(a,b,c,d,e,f) + #define TP_LOG_IND6(a,b,c,d,e,f,g) + + #define TP_LOGC_IND0(a) + #define TP_LOGC_IND1(a,b) + #define TP_LOGC_IND2(a,b,c) + + #define TP_LOGH_IND(a,b) + #define TP_LOGHC_IND(a,b) + + /*--------------------------------------------*/ + /* Request logging */ + /*--------------------------------------------*/ + + #define TP_LOG_REQ0(a) + #define TP_LOG_REQ1(a,b) + #define TP_LOG_REQ2(a,b,c) + #define TP_LOG_REQ3(a,b,c,d) + #define TP_LOG_REQ4(a,b,c,d,e) + #define TP_LOG_REQ5(a,b,c,d,e,f) + #define TP_LOG_REQ6(a,b,c,d,e,f,g) + + #define TP_LOGC_REQ0(a) + #define TP_LOGC_REQ1(a,b) + #define TP_LOGC_REQ2(a,b,c) + + #define TP_LOGH_REQ(a,b) + #define TP_LOGHC_REQ(a,b) + + /*--------------------------------------------------------------------*/ + /* macros below are used to log REQ or IND by passing mask */ + /*--------------------------------------------------------------------*/ + + #define TP_LOG_RI0(m,a) + #define TP_LOG_RI1(m,a,b) + #define TP_LOG_RI2(m,a,b,c) + #define TP_LOG_RI3(m,a,b,c,d) + #define TP_LOG_RI4(m,a,b,c,d,e) + #define TP_LOG_RI5(m,a,b,c,d,e,f) + #define TP_LOG_RI6(m,a,b,c,d,e,f,g) + + #define TP_LOGC_RI0(m,a) + #define TP_LOGC_RI1(m,a,b) + #define TP_LOGC_RI2(m,a,b,c) + + #define TP_LOGH_RI(m,a,b) + #define TP_LOGHC_RI(m,a,b) + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + diff --git a/include/inc/tp4api.h b/include/inc/tp4api.h new file mode 100644 index 0000000..48543f3 --- /dev/null +++ b/include/inc/tp4api.h @@ -0,0 +1,333 @@ +#ifndef TP4API_INCLUDED +#define TP4API_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2005 All Rights Reserved */ +/* */ +/* MODULE NAME : tp4api.h */ +/* PRODUCT(S) : TP4 API user include file */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/27/05 JRB 23 Del obsolete DS_INFO, tp4_ds_*, odbc_ds_*. */ +/* 05/05/05 EJV 22 TP0_CFG: added rfc1006_listen_port */ +/* TP4_ADDR added port. */ +/* 04/06/05 EJV 21 MMSEASE_MOSI: use 32 for MAX_TSEL_LEN */ +/* 09/17/04 JRB 20 Chg tp?_connect to ret ST_LONG (i.e. conn_id)*/ +/* 01/14/04 EJV 19 TP0_CFG: added max_spdu_outst. */ +/* 08/25/03 EJV 18 Added encrypt_ctrl arg to tp0_connect(). */ +/* Added param to tp4_connect macro. */ +/* 06/20/02 JRB 17 Replace net_addr with union in TP4_ADDR. */ +/* Chg addr args to tp4_connect_ind. */ +/* Add tp0_convert_ip proto. */ +/* 05/08/02 JRB 16 Add tp0_connect_outstanding_count proto. */ +/* 01/22/02 JRB 15 Add max_conns arg to tp*_initialize. */ +/* 05/10/01 JRB 14 Chg TSEL_LEN from 32 to 4. */ +/* 03/14/01 JRB 13 Add global session_cfg w/ disconnect_timeout.*/ +/* 08/05/99 JRB 12 Add hTcp... extern. */ +/* 06/08/99 JRB 11 Change max_num_conns to ST_UINT16 to allow */ +/* many more connections. */ +/* 01/28/99 JRB 10 Addec cltp_decode_nsdu_fun funct ptr. */ +/* 08/13/98 JRB 09 Lint cleanup. */ +/* 06/18/98 JRB 08 Add TP_TYPE_TPX. */ +/* 03/11/98 JRB 07 Del max_spdu_len from TP0_CFG & TP_CFG. */ +/* Add keepalive to TP0_CFG. */ +/* 09/04/07 JRB 06 Add max_spdu_len arg to tp4_initialize. */ +/* 08/14/97 JRB 05 RFC1006 changes: */ +/* - Add "tp0_*" protos. */ +/* - Add "tp_type" to TP4_ADDR. */ +/* - Add "tp0_cfg" config struct for RFC1006. */ +/* - Chg "tp4_data" arg "data_len" to ST_UINT. */ +/* - Replace tp4_reldata proto with dummy macro.*/ +/* - Chg MAX_TP4_SEL to MAX_TSEL_LEN (ACSE uses)*/ +/* - Chg MAX_NET_ADDR to MAX_IP_ADDR_LEN and */ +/* increase to allow IP hostname. */ +/* 08/04/97 JRB 04 Add max_tpdu_len_enc to TP_CFG (use instead */ +/* of global max_tpdu_len_enc). */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 05/07/97 JRB 03 Added Error codes. */ +/* 02/20/97 EJV 02 Added MOSI support: tp4_session_timer and */ +/* tp4_session_timer_expired. */ +/* 11/14/96 JRB 01 Created for LEAN_T only. */ +/************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ssec.h" /* for S_SEC_ENCRYPT_CTRL */ +#include "clnp_usr.h" /* Need CLNP_MAX_LEN_NSAP define. */ + +/* Defines for Transport type. Used to set "tp_type" in TP4_ADDR. */ +#define TP_TYPE_TCP 0 +#define TP_TYPE_TP4 1 +#define TP_TYPE_TPX 2 /* allow TP4 and TCP at same time. */ + +/****************************************************************/ +/* Structure definitions */ +/****************************************************************/ + +#if defined(MMSEASE_MOSI) +#define MAX_TSEL_LEN 32 +#else +#define MAX_TSEL_LEN 4 /* GOSIP Ver2 recommends len of 2 */ +#endif +#define MAX_IP_ADDR_LEN 80 /* Big enough for IP hostname */ + +typedef struct tagTP4_ADDR + { +#if !defined(REDUCED_STACK) + ST_INT tp_type; /* Type of transport: TP_TYPE_TP4 or TP_TYPE_TCP.*/ + ST_UINT tp4_sel_len; + char tp4_sel[MAX_TSEL_LEN]; + ST_UINT net_addr_len; + union + { /* If TP_TYPE_TP4, use "nsap". If TP_TYPE_TCP, use "ip". */ + ST_UCHAR nsap [CLNP_MAX_LEN_NSAP]; /* NSAP OR */ + ST_ULONG ip; /* IP Addr (network byte order) */ + }netAddr; + ST_UINT16 port; /* remote port, optional param, */ + /* defaults to 102 if not config*/ +#else + ST_UINT16 adlcAddr; +#endif + } TP4_ADDR; + +/****************************************************************/ +/* API prototypes */ +/****************************************************************/ + +ST_RET tp4_initialize (ST_UINT max_conns, ST_UINT max_spdu_len); +ST_RET tp4_terminate (ST_VOID); + +ST_BOOLEAN tp4_event (ST_VOID); + +ST_RET tp4_bind (ST_LONG user_bind_id, TP4_ADDR *tp4_addr, + ST_INT sharable, ST_INT max_conns); +ST_RET tp4_unbind (ST_LONG tp4_bind_id); + +ST_LONG tp4_connect (ST_LONG tp4_bind_id, ST_LONG user_conn_id, + TP4_ADDR *rem_tp4_addr, + ST_INT conndata_len, + char *conndata, + S_SEC_ENCRYPT_CTRL *encrypt_ctrl); /* connection encryption info */ + +ST_RET tp4_accept (ST_LONG tp4_conn_id, ST_LONG user_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp4_disconnect (ST_LONG tp4_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp4_data (ST_LONG tp4_conn_id, + ST_INT eot, + ST_UINT data_len, + char *data); +ST_RET tp4_expdata (ST_LONG tp4_conn_id, + ST_UINT data_len, + char *data); + +/* The "tp4_reldata" function is not needed in this TP4 implementation, */ +/* so define "tp4_reldata" macro which does nothing. */ +#define tp4_reldata(databuf) + +/* Function for MOSI implementation: */ +ST_RET tp4_session_timer (ST_LONG tp_conn_id, ST_BOOLEAN start); + +ST_RET tp0_initialize (ST_UINT max_conns, ST_UINT max_spdu_len); +ST_RET tp0_terminate (ST_VOID); + +ST_BOOLEAN tp0_event (ST_VOID); + +ST_RET tp0_bind (ST_LONG user_bind_id, TP4_ADDR *tp4_addr, + ST_INT sharable, ST_INT max_conns); +ST_RET tp0_unbind (ST_LONG tp4_bind_id); + +ST_LONG tp0_connect (ST_LONG tp4_bind_id, ST_LONG user_conn_id, + TP4_ADDR *rem_tp4_addr, + ST_INT conndata_len, + char *conndata, + S_SEC_ENCRYPT_CTRL *encrypt_ctrl); +ST_INT tp0_connect_outstanding_count (TP4_ADDR *tp4Addr); +ST_RET tp0_accept (ST_LONG tp4_conn_id, ST_LONG user_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp0_disconnect (ST_LONG tp4_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp0_data (ST_LONG tp4_conn_id, + ST_INT eot, + ST_UINT data_len, + char *data); + +/* Function for MOSI implementation: */ +ST_RET tp0_session_timer (ST_LONG tp_conn_id, ST_BOOLEAN start); + +/****************************************************************/ +/* Event callback function prototypes */ +/****************************************************************/ + +ST_VOID tp4_bind_cnf (ST_LONG user_bind_id, ST_LONG tp4_bind_id, ST_RET result); +ST_VOID tp4_unbind_cnf (ST_LONG user_bind_id); + +ST_VOID tp4_connect_ind (ST_LONG user_bind_id, ST_LONG tp4_conn_id, + ST_UCHAR *loc_tsap, ST_UCHAR *rem_tsap, + ST_UCHAR *rem_nsap, ST_ULONG rem_ip, + ST_INT conndata_len, char *conndata); +ST_VOID tp4_connect_cnf (ST_LONG user_conn_id, ST_LONG tp4_conn_id, + ST_INT conndata_len, char *conndata); +ST_VOID tp4_disconnect_ind (ST_LONG user_conn_id, ST_INT reason, + ST_INT conndata_len, char *conndata); +ST_VOID tp4_data_ind (ST_LONG user_conn_id, ST_INT eot, + ST_UINT data_len, char *data); +ST_VOID tp4_expdata_ind (ST_LONG user_conn_id, + ST_UINT data_len, char *data); + +/* Function for MOSI implementation: */ +ST_VOID tp4_session_timer_expired (ST_LONG user_conn_id); + + +/****************************************************************/ +/* Log Control */ +/****************************************************************/ + +#define TP4_LOG_ERR 0x00000001 +#define TP4_LOG_FLOWUP 0x00000002 +#define TP4_LOG_FLOWDOWN 0x00000004 + +extern ST_UINT tp4_debug_sel; + +/****************************************************************/ +/* Error Codes */ +/****************************************************************/ + +#define TP4E_SHMALLOC 0x1201 +#define TP4E_BADCONN 0x1202 +#define TP4E_QUEUE_FULL 0x1203 +#define TP4E_CONN_STATE 0x1204 +#define TP4E_INVAL_TPDU_LEN 0x1205 +#define TP4E_INVAL_REM_CDT 0x1206 +#define TP4E_INVAL_LOC_CDT 0x1207 +#define TP4E_INVAL_SPDU_OUTST 0x1208 +#define TP4E_INVAL_NUM_CONNS 0x1209 +#define TP4E_INVAL_SPDU_LEN 0x120A +#define TP4E_INVAL_WINDOW_TIME 0x120B +#define TP4E_INVAL_INACT_TIME 0x120C +#define TP4E_INVAL_RETRANS_TIME 0x120D +#define TP4E_INVAL_MAX_TRANS 0x120E +#define TP4E_MALLOC 0x120F +#define TP4E_INVAL_TSEL 0x1210 +#define TP4E_TOO_MANY_BINDS 0x1211 + + +/************************************************************************/ +/* Global Configuration Structure Typedef. */ +/************************************************************************/ +typedef struct + { + ST_UINT16 max_tpdu_len; /* max len of TPDU. Base on SNPDU size.*/ + /* Use to allocate TPDU buffers. */ + ST_UCHAR max_tpdu_len_enc; /* Binary encoded MAX TPDU len. Computed*/ + /* from max_tpdu_len by tp4_initialize. */ + ST_UCHAR max_rem_cdt; /* Max credits we can handle. */ + /* Will allocate this many TPDU_DT */ + /* structs. */ + /* CRITICAL: MUST BE POWER OF 2. */ + ST_UCHAR loc_cdt; /* CDT value we will ALWAYS send in ACK */ + /* We only accept in-sequence TPDUs so */ + /* only purpose of this is to */ + /* allow peer to send ahead. */ + ST_UCHAR max_spdu_outst; /* Max # of SPDUs outstanding per conn. */ + /* Will allocate this many SPDU_INFO */ + /* structs for transmit queue. */ + /* CRITICAL: MUST BE POWER OF 2. */ + ST_UINT16 max_num_conns; /* Max # Connections */ + ST_UINT16 window_time; /* Window Time */ + ST_UINT16 inact_time; /* Inactivity Time */ + ST_UINT16 retrans_time; /* Retransmission Time */ + ST_UCHAR max_trans; /* Max # of transmissions of a TPDU */ + ST_UCHAR ak_delay; /* # of loops to delay sending AK. */ + } TP_CFG; + +typedef struct + { + ST_UINT16 max_tpdu_len; /* max len of TPDU. Base on SNPDU size.*/ + /* Use to allocate TPDU buffers. */ + ST_UCHAR max_tpdu_len_enc; /* Binary encoded MAX TPDU len. Computed*/ + /* from max_tpdu_len by tp0_initialize. */ + ST_UINT max_spdu_outst; /* Max # of SPDUs outstanding per conn. */ + /* that can be queued on the gensock2 */ + ST_UINT16 max_num_conns; /* Max # Connections */ + ST_BOOLEAN keepalive; /* Use KEEPALIVE option on Sockets? */ + ST_UINT16 rfc1006_listen_port;/* RFC1006 listen port, optional param, */ + /* will default to 102 if not configured*/ + } TP0_CFG; /* For TP0/RFC1006 only. */ + +typedef struct + { + ST_UINT16 disconnect_timeout; /* time to wait for T-disconnect. */ + } SESSION_CFG; + +/************************************************************************/ +/* Global Configuration Structure */ +/* This structure must be filled in by user BEFORE tp4_initialize (). */ +/* It MUST NOT change after tp4_initialize (). */ +/************************************************************************/ +extern TP_CFG tp_cfg; +extern TP0_CFG tp0_cfg; /* For TP0/RFC1006 only. */ +extern SESSION_CFG session_cfg; + +/************************************************************************/ +/* Global Variables */ +/************************************************************************/ +/* CLTP decode function pointer. */ +extern ST_VOID (*cltp_decode_nsdu_fun) (N_UNITDATA *n_unitdata); + +/************************************************************************/ +/* Additional Prototypes for LEAN_T only. */ +/************************************************************************/ + +ST_VOID tp4_except (ST_CHAR *filename, ST_INT line); +ST_VOID tp4_timer_tick (ST_VOID); +ST_RET tp4_config (ST_VOID); +ST_VOID tp4_init_timer (ST_VOID); +ST_VOID tp4_check_timer (ST_VOID); +ST_INT tp4_buffers_avail (ST_LONG tp4_conn_id); + +ST_VOID tp0_timer_tick (ST_VOID); +ST_INT tp0_buffers_avail (ST_LONG tp4_conn_id); +ST_ULONG tp0_convert_ip (ST_CHAR *hostname); + +/************************************************************************/ +/* Event semaphore to indicate TCP events. */ +/************************************************************************/ +extern ST_EVENT_SEM hTcpEvent; + +/************************************************************************/ +/* Replacement function macros. If no TP4, call TP0 functions. */ +/************************************************************************/ +#if !defined (TP4_ENABLED) +#define tp4_initialize(a,b) tp0_initialize(a,b) +#define tp4_terminate() tp0_terminate() +#define tp4_event() tp0_event() +#define tp4_bind(a,b,c,d) tp0_bind(a,b,c,d) +#define tp4_unbind(a) tp0_unbind(a) +#define tp4_connect(a,b,c,d,e,f) tp0_connect(a,b,c,d,e,f) +#define tp4_accept(a,b,c,d) tp0_accept(a,b,c,d) +#define tp4_disconnect(a,b,c) tp0_disconnect(a,b,c) +#define tp4_data(a,b,c,d) tp0_data(a,b,c,d) +#define tp4_session_timer(a,b) tp0_session_timer(a,b) +#define tp4_timer_tick() tp0_timer_tick() +#define tp4_buffers_avail(a) tp0_buffers_avail(a) +#endif /* !defined (TP4_ENABLED) */ + +#ifdef __cplusplus +} +#endif +#endif /* !TP4API_INCLUDED */ diff --git a/include/inc/tp4api.h.bak b/include/inc/tp4api.h.bak new file mode 100644 index 0000000..73cf08f --- /dev/null +++ b/include/inc/tp4api.h.bak @@ -0,0 +1,333 @@ +#ifndef TP4API_INCLUDED +#define TP4API_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2005 All Rights Reserved */ +/* */ +/* MODULE NAME : tp4api.h */ +/* PRODUCT(S) : TP4 API user include file */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/27/05 JRB 23 Del obsolete DS_INFO, tp4_ds_*, odbc_ds_*. */ +/* 05/05/05 EJV 22 TP0_CFG: added rfc1006_listen_port */ +/* TP4_ADDR added port. */ +/* 04/06/05 EJV 21 MMSEASE_MOSI: use 32 for MAX_TSEL_LEN */ +/* 09/17/04 JRB 20 Chg tp?_connect to ret ST_LONG (i.e. conn_id)*/ +/* 01/14/04 EJV 19 TP0_CFG: added max_spdu_outst. */ +/* 08/25/03 EJV 18 Added encrypt_ctrl arg to tp0_connect(). */ +/* Added param to tp4_connect macro. */ +/* 06/20/02 JRB 17 Replace net_addr with union in TP4_ADDR. */ +/* Chg addr args to tp4_connect_ind. */ +/* Add tp0_convert_ip proto. */ +/* 05/08/02 JRB 16 Add tp0_connect_outstanding_count proto. */ +/* 01/22/02 JRB 15 Add max_conns arg to tp*_initialize. */ +/* 05/10/01 JRB 14 Chg TSEL_LEN from 32 to 4. */ +/* 03/14/01 JRB 13 Add global session_cfg w/ disconnect_timeout.*/ +/* 08/05/99 JRB 12 Add hTcp... extern. */ +/* 06/08/99 JRB 11 Change max_num_conns to ST_UINT16 to allow */ +/* many more connections. */ +/* 01/28/99 JRB 10 Addec cltp_decode_nsdu_fun funct ptr. */ +/* 08/13/98 JRB 09 Lint cleanup. */ +/* 06/18/98 JRB 08 Add TP_TYPE_TPX. */ +/* 03/11/98 JRB 07 Del max_spdu_len from TP0_CFG & TP_CFG. */ +/* Add keepalive to TP0_CFG. */ +/* 09/04/07 JRB 06 Add max_spdu_len arg to tp4_initialize. */ +/* 08/14/97 JRB 05 RFC1006 changes: */ +/* - Add "tp0_*" protos. */ +/* - Add "tp_type" to TP4_ADDR. */ +/* - Add "tp0_cfg" config struct for RFC1006. */ +/* - Chg "tp4_data" arg "data_len" to ST_UINT. */ +/* - Replace tp4_reldata proto with dummy macro.*/ +/* - Chg MAX_TP4_SEL to MAX_TSEL_LEN (ACSE uses)*/ +/* - Chg MAX_NET_ADDR to MAX_IP_ADDR_LEN and */ +/* increase to allow IP hostname. */ +/* 08/04/97 JRB 04 Add max_tpdu_len_enc to TP_CFG (use instead */ +/* of global max_tpdu_len_enc). */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 05/07/97 JRB 03 Added Error codes. */ +/* 02/20/97 EJV 02 Added MOSI support: tp4_session_timer and */ +/* tp4_session_timer_expired. */ +/* 11/14/96 JRB 01 Created for LEAN_T only. */ +/************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ssec.h" /* for S_SEC_ENCRYPT_CTRL */ +#include "clnp_usr.h" /* Need CLNP_MAX_LEN_NSAP define. */ + +/* Defines for Transport type. Used to set "tp_type" in TP4_ADDR. */ +#define TP_TYPE_TCP 0 +#define TP_TYPE_TP4 1 +#define TP_TYPE_TPX 2 /* allow TP4 and TCP at same time. */ + +/****************************************************************/ +/* Structure definitions */ +/****************************************************************/ + +#if defined(MMSEASE_MOSI) +#define MAX_TSEL_LEN 32 +#else +#define MAX_TSEL_LEN 4 /* GOSIP Ver2 recommends len of 2 */ +#endif +#define MAX_IP_ADDR_LEN 80 /* Big enough for IP hostname */ + +typedef struct tagTP4_ADDR + { +#if !defined(REDUCED_STACK) + ST_INT tp_type; /* Type of transport: TP_TYPE_TP4 or TP_TYPE_TCP.*/ + ST_UINT tp4_sel_len; + char tp4_sel[MAX_TSEL_LEN]; + ST_UINT net_addr_len; + union + { /* If TP_TYPE_TP4, use "nsap". If TP_TYPE_TCP, use "ip". */ + ST_UCHAR nsap [CLNP_MAX_LEN_NSAP]; /* NSAP OR */ + ST_ULONG ip; /* IP Addr (network byte order) */ + }netAddr; + ST_UINT16 port; /* remote port, optional param, */ + /* defaults to 102 if not config*/ +#else + ST_UINT16 adlcAddr; +#endif + } TP4_ADDR; + +/****************************************************************/ +/* API prototypes */ +/****************************************************************/ + +ST_RET tp4_initialize (ST_UINT max_conns, ST_UINT max_spdu_len); +ST_RET tp4_terminate (ST_VOID); + +ST_BOOLEAN tp4_event (ST_VOID); + +ST_RET tp4_bind (ST_LONG user_bind_id, TP4_ADDR *tp4_addr, + ST_INT sharable, ST_INT max_conns); +ST_RET tp4_unbind (ST_LONG tp4_bind_id); + +ST_LONG tp4_connect (ST_LONG tp4_bind_id, ST_LONG user_conn_id, + TP4_ADDR *rem_tp4_addr, + ST_INT conndata_len, + char *conndata, + S_SEC_ENCRYPT_CTRL *encrypt_ctrl); /* connection encryption info */ + +ST_RET tp4_accept (ST_LONG tp4_conn_id, ST_LONG user_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp4_disconnect (ST_LONG tp4_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp4_data (ST_LONG tp4_conn_id, + ST_INT eot, + ST_UINT data_len, + char *data); +ST_RET tp4_expdata (ST_LONG tp4_conn_id, + ST_UINT data_len, + char *data); + +/* The "tp4_reldata" function is not needed in this TP4 implementation, */ +/* so define "tp4_reldata" macro which does nothing. */ +#define tp4_reldata(databuf) + +/* Function for MOSI implementation: */ +ST_RET tp4_session_timer (ST_LONG tp_conn_id, ST_BOOLEAN start); + +ST_RET tp0_initialize (ST_UINT max_conns, ST_UINT max_spdu_len); +ST_RET tp0_terminate (ST_VOID); + +ST_BOOLEAN tp0_event (ST_VOID); + +ST_RET tp0_bind (ST_LONG user_bind_id, TP4_ADDR *tp4_addr, + ST_INT sharable, ST_INT max_conns); +ST_RET tp0_unbind (ST_LONG tp4_bind_id); + +ST_LONG tp0_connect (ST_LONG tp4_bind_id, ST_LONG user_conn_id, + TP4_ADDR *rem_tp4_addr, + ST_INT conndata_len, + char *conndata, + S_SEC_ENCRYPT_CTRL *encrypt_ctrl); +ST_INT tp0_connect_outstanding_count (TP4_ADDR *tp4Addr); +ST_RET tp0_accept (ST_LONG tp4_conn_id, ST_LONG user_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp0_disconnect (ST_LONG tp4_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp0_data (ST_LONG tp4_conn_id, + ST_INT eot, + ST_UINT data_len, + char *data); + +/* Function for MOSI implementation: */ +ST_RET tp0_session_timer (ST_LONG tp_conn_id, ST_BOOLEAN start); + +/****************************************************************/ +/* Event callback function prototypes */ +/****************************************************************/ + +ST_VOID tp4_bind_cnf (ST_LONG user_bind_id, ST_LONG tp4_bind_id, ST_RET result); +ST_VOID tp4_unbind_cnf (ST_LONG user_bind_id); + +/*ST_VOID tp4_connect_ind (ST_LONG user_bind_id, ST_LONG tp4_conn_id, + ST_UCHAR *loc_tsap, ST_UCHAR *rem_tsap, + ST_UCHAR *rem_nsap, ST_ULONG rem_ip, + ST_INT conndata_len, char *conndata);*/ +ST_VOID tp4_connect_cnf (ST_LONG user_conn_id, ST_LONG tp4_conn_id, + ST_INT conndata_len, char *conndata); +ST_VOID tp4_disconnect_ind (ST_LONG user_conn_id, ST_INT reason, + ST_INT conndata_len, char *conndata); +ST_VOID tp4_data_ind (ST_LONG user_conn_id, ST_INT eot, + ST_UINT data_len, char *data); +ST_VOID tp4_expdata_ind (ST_LONG user_conn_id, + ST_UINT data_len, char *data); + +/* Function for MOSI implementation: */ +ST_VOID tp4_session_timer_expired (ST_LONG user_conn_id); + + +/****************************************************************/ +/* Log Control */ +/****************************************************************/ + +#define TP4_LOG_ERR 0x00000001 +#define TP4_LOG_FLOWUP 0x00000002 +#define TP4_LOG_FLOWDOWN 0x00000004 + +extern ST_UINT tp4_debug_sel; + +/****************************************************************/ +/* Error Codes */ +/****************************************************************/ + +#define TP4E_SHMALLOC 0x1201 +#define TP4E_BADCONN 0x1202 +#define TP4E_QUEUE_FULL 0x1203 +#define TP4E_CONN_STATE 0x1204 +#define TP4E_INVAL_TPDU_LEN 0x1205 +#define TP4E_INVAL_REM_CDT 0x1206 +#define TP4E_INVAL_LOC_CDT 0x1207 +#define TP4E_INVAL_SPDU_OUTST 0x1208 +#define TP4E_INVAL_NUM_CONNS 0x1209 +#define TP4E_INVAL_SPDU_LEN 0x120A +#define TP4E_INVAL_WINDOW_TIME 0x120B +#define TP4E_INVAL_INACT_TIME 0x120C +#define TP4E_INVAL_RETRANS_TIME 0x120D +#define TP4E_INVAL_MAX_TRANS 0x120E +#define TP4E_MALLOC 0x120F +#define TP4E_INVAL_TSEL 0x1210 +#define TP4E_TOO_MANY_BINDS 0x1211 + + +/************************************************************************/ +/* Global Configuration Structure Typedef. */ +/************************************************************************/ +typedef struct + { + ST_UINT16 max_tpdu_len; /* max len of TPDU. Base on SNPDU size.*/ + /* Use to allocate TPDU buffers. */ + ST_UCHAR max_tpdu_len_enc; /* Binary encoded MAX TPDU len. Computed*/ + /* from max_tpdu_len by tp4_initialize. */ + ST_UCHAR max_rem_cdt; /* Max credits we can handle. */ + /* Will allocate this many TPDU_DT */ + /* structs. */ + /* CRITICAL: MUST BE POWER OF 2. */ + ST_UCHAR loc_cdt; /* CDT value we will ALWAYS send in ACK */ + /* We only accept in-sequence TPDUs so */ + /* only purpose of this is to */ + /* allow peer to send ahead. */ + ST_UCHAR max_spdu_outst; /* Max # of SPDUs outstanding per conn. */ + /* Will allocate this many SPDU_INFO */ + /* structs for transmit queue. */ + /* CRITICAL: MUST BE POWER OF 2. */ + ST_UINT16 max_num_conns; /* Max # Connections */ + ST_UINT16 window_time; /* Window Time */ + ST_UINT16 inact_time; /* Inactivity Time */ + ST_UINT16 retrans_time; /* Retransmission Time */ + ST_UCHAR max_trans; /* Max # of transmissions of a TPDU */ + ST_UCHAR ak_delay; /* # of loops to delay sending AK. */ + } TP_CFG; + +typedef struct + { + ST_UINT16 max_tpdu_len; /* max len of TPDU. Base on SNPDU size.*/ + /* Use to allocate TPDU buffers. */ + ST_UCHAR max_tpdu_len_enc; /* Binary encoded MAX TPDU len. Computed*/ + /* from max_tpdu_len by tp0_initialize. */ + ST_UINT max_spdu_outst; /* Max # of SPDUs outstanding per conn. */ + /* that can be queued on the gensock2 */ + ST_UINT16 max_num_conns; /* Max # Connections */ + ST_BOOLEAN keepalive; /* Use KEEPALIVE option on Sockets? */ + ST_UINT16 rfc1006_listen_port;/* RFC1006 listen port, optional param, */ + /* will default to 102 if not configured*/ + } TP0_CFG; /* For TP0/RFC1006 only. */ + +typedef struct + { + ST_UINT16 disconnect_timeout; /* time to wait for T-disconnect. */ + } SESSION_CFG; + +/************************************************************************/ +/* Global Configuration Structure */ +/* This structure must be filled in by user BEFORE tp4_initialize (). */ +/* It MUST NOT change after tp4_initialize (). */ +/************************************************************************/ +extern TP_CFG tp_cfg; +extern TP0_CFG tp0_cfg; /* For TP0/RFC1006 only. */ +extern SESSION_CFG session_cfg; + +/************************************************************************/ +/* Global Variables */ +/************************************************************************/ +/* CLTP decode function pointer. */ +extern ST_VOID (*cltp_decode_nsdu_fun) (N_UNITDATA *n_unitdata); + +/************************************************************************/ +/* Additional Prototypes for LEAN_T only. */ +/************************************************************************/ + +ST_VOID tp4_except (ST_CHAR *filename, ST_INT line); +ST_VOID tp4_timer_tick (ST_VOID); +ST_RET tp4_config (ST_VOID); +ST_VOID tp4_init_timer (ST_VOID); +ST_VOID tp4_check_timer (ST_VOID); +ST_INT tp4_buffers_avail (ST_LONG tp4_conn_id); + +ST_VOID tp0_timer_tick (ST_VOID); +ST_INT tp0_buffers_avail (ST_LONG tp4_conn_id); +ST_ULONG tp0_convert_ip (ST_CHAR *hostname); + +/************************************************************************/ +/* Event semaphore to indicate TCP events. */ +/************************************************************************/ +extern ST_EVENT_SEM hTcpEvent; + +/************************************************************************/ +/* Replacement function macros. If no TP4, call TP0 functions. */ +/************************************************************************/ +#if !defined (TP4_ENABLED) +#define tp4_initialize(a,b) tp0_initialize(a,b) +#define tp4_terminate() tp0_terminate() +#define tp4_event() tp0_event() +#define tp4_bind(a,b,c,d) tp0_bind(a,b,c,d) +#define tp4_unbind(a) tp0_unbind(a) +#define tp4_connect(a,b,c,d,e,f) tp0_connect(a,b,c,d,e,f) +#define tp4_accept(a,b,c,d) tp0_accept(a,b,c,d) +#define tp4_disconnect(a,b,c) tp0_disconnect(a,b,c) +#define tp4_data(a,b,c,d) tp0_data(a,b,c,d) +#define tp4_session_timer(a,b) tp0_session_timer(a,b) +#define tp4_timer_tick() tp0_timer_tick() +#define tp4_buffers_avail(a) tp0_buffers_avail(a) +#endif /* !defined (TP4_ENABLED) */ + +#ifdef __cplusplus +} +#endif +#endif /* !TP4API_INCLUDED */ diff --git a/lib/libcurl.so.4 b/lib/libcurl.so.4 new file mode 100644 index 0000000000000000000000000000000000000000..9a730185aa3da041657ef938519e86317f174591 GIT binary patch literal 1164856 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

tk5Jd#u7kDOZM4|5xKCiKB_P0cQKguq5COXOE> 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 z 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 >AU+u;4I6$;8gt67Iyzx2 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 literal 0 HcmV?d00001 diff --git a/lib/libcurl.so.4.3.0 b/lib/libcurl.so.4.3.0 new file mode 100644 index 0000000000000000000000000000000000000000..9409fe2bae2e6bd8d00a586999d47ae6c0030760 GIT binary patch literal 352958 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%0ATuW__gjP$>gwYJB%bs( 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 Iol4982fukBSpWb4 literal 0 HcmV?d00001 diff --git a/lib/libcurl.so.4.7.0 b/lib/libcurl.so.4.7.0 new file mode 100644 index 0000000000000000000000000000000000000000..9a730185aa3da041657ef938519e86317f174591 GIT binary patch literal 1164856 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

tk5Jd#u7kDOZM4|5xKCiKB_P0cQKguq5COXOE> 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 z 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 >AU+u;4I6$;8gt67Iyzx2 z&$8o|g6A-v75vqY+@irXjWuJVw}1iJalg|Hi>30#4;aG5mf&R=>otmBz>R1N?3rN! zd}Lh!f2z7U9QeN&f)xIPD){l}x;iI9r(y7$?6@{VP(2GMenf)!XbND4Aq^*>dML08 zR3?EQYA{A{A;@SIT5cBF03A7>4n7(>m|+MV0;+UWfexiZ(Fz?tto2d!qM5ZTk*N&g zoG&?1e;zB2mascIWBxbm!beJv-ujLgdBYwoJbLS=Cm$nw&nP+!fq)JfX_d8rY4I z&KFPdR?a57Gr6foIYRZSuIa&y%&6Vod5AD$QfY8oJ(`y2bEr+O%TJmuitJyPi+(GS z#p$2xS`5{8g2x~akXT|k2ATdQ)M09kU3M@I^L}@X(#=Vo+fiRfOBK3;1~~2X4+w0! zPAvT~{8HH-aYsvacr5AM)a+mSy)l}CXzpY(bPSszF|tCBNfA{Wz}VEM;)YlMQAaGP z3qwcCS_{pGZFX_Yhno>Ca9F!#yQov$hIGriDn4TmQ)+N*d_49T#r^$@Nh3$r_+U%z2cOAATK{ld+<|LU@W_|pC2=A1eFD7FQUPX zK$vdpLwaf@|AmqMsg&C$S=g`s<-BLJMF6b;V<9K9i15!N=yz@_AsGemtBe4N-AD+o zbe1m{jmI~FP@T5%OFGvM9F@xoZO`Hjj}SF2GL5?<4kl6jkXk996EjM)rsI+`7)RLw zB(DgG!2b!bV=($lJat<~;X}5ub7!ZmZb8hx3YL1L=*&{$R07bEPoH4)g(6U05j-n( z1j_aoM(5iV2baydAld=7VneWTjOC=mlgr>3+aA3qdB!~>2t-@;M^CKBT;(2(3ge-{ zhnWY`l!50sy;zPJ5#F9SLMZ1QOUs%*3&70UG=|GMs!ByLNVgq~ z?4jR7pQ3*((t4E#XM>-R4nZR!qz>Q7P9J`JI3)rmYpSI$WFsS-Z;A#(^gtcm4m=C= z#%@+!179FA3*HeX)(gb~Ug`lFhQB2aIM(hl#Qnz*2kg2$f!S7k>=-GZtFBmn)4VeSeN^B;0-noLkG{%kIJ!5#+^aLqhGa^?vc_}4m*hJ%Yy5RNs1SKi@uNhzT#-eMH-(P z4PYpmNvjB=CrZ8vOQi7Qi07sbTL;QFV@6~ILr%`1ecGNU8<;1XO9sS>qZ{RMzi)Wl zh_qd;&?v=m+3y-^pqmXNB4=FaoRXE=FS9~$qQ6Z`JKe4H+zEq0%4EZY?r_MllU73c;ZDK2TBEmP9 z|7uhtTEVoV_=0hdgJjP(KC+z%N$DO%;Y)zAPRW9H%Yr6Ubd}7N(b_YndMrpB3K1T+ zlNDjK<`T(c>~avlxLb**ILITsq&w=Mbr47d-J4pvZ-Ec7ytAb{o6FhKQFzF^S7PlH zuXLO7EM_eGEw{jCL{exKG?=tp*2zda5yU$B>&$JTzec@6-KVjRmByc2tWaOTD)x~# zfc$|2w65e3nHcGi@g0dALxI`{+{s99orRFNnEmWEZE)^J9?GMkbLqv#!S1`-bLkxY zA(9jBbXz6i1%_Oy(h8VU2K9Ub*j)m$%^hxl(9{zXjNgJ44HKmZ2RZ0OgpuD%3k43O zLh1Meq#8xM7h||QMbgbZblgvY%if^IjKVkpSE``R$M48CuZJao`1+hV^h)ThA8aE+ zwf-4a3XPv5q3Ye1M>M{JA1A`(2awrDb{ zkXkd}iOe+t##~?`q=p<0xymLBU3KfHR#Y`mL`Ms$_68@C@(6NC1E7)%Y36XSswkCo z$DRVwN)_$d=l^`gb_3*JGDtmYOil-%tm%61VqYDAWlO14X*;Mt^RVw|^5C|u0cG8|t1gU5j zRF6!(ySy!;`AR*rGw1L25zOAkuJQ!rs)Y4E6qqQyDfCCX0Ju`Krv$zm4l{}Ehrt%}?_D!6(!fU9?Z!4+3rUU^gZPB;W{q~2ZbyTiRK z7cD?JMAywU%IOIH;D)X~6kZe}Oa`gKOjLnWl%gEIe5$luSdPhLw!qof-phph;k19tNKY^+6uu?yZ>`AS$p|iN#u2&juFh>IO51D}lUm82P~vFsJB9ew z%^}2ly&yB11K?udVuJx#k(5e{6+8kw_wp4=TR3=aX<7qQ3fFzL*tGDaa%?OcUWBsz zno8YKvx4*kfdY-fM1)MvhUW|m{fnW{T>Z~7Uo5j!kY?JXowAL)2nrKy@w$U#iBkcC zgX8J@flZ6nu#vs-(c59!4o#6nb1Xy&>1-VT4r%&m7uy{d2;<{=yWJAMB3-5TwY&Be zqMZaoItxNKr;lJ9Qt9+6PnVHZN{M07>tW8^Jv-_(5NPfSinL7^g#^V z_4acvE>t2^Hv23LuBQq0hX52t$WZzA0IvH8b*n(}mP6WIB=;63U!|GHDY-PVE9d$k z&qV-ow&wf}M1bvtukD!TorBy^nA!~gJn)nCV7AobIk9M5&@)}o)e0(=xr3lMC%3}X&o!F7~XD6JF3G5J9eTS z`w^F(?#3*!cAu;^O7A|@iP3rU@ z`bmmj$iY=n*>I`ZGO>mY_)S^^ zaN*XJDA^>JL;*#TYFag!nYGMJs}SWHnT%wxE3i6e?d8jnr(xRpF&p06s{w?-3(Sf} z!e;8IB|+7wJOO8+)X@NEd$hB9_sg_BWr$!^y&>W= z?RThWyR<8_Tl+4vz*9D%V&b%kD^^L7IW#f*m3&A3bm%r&=-w86& z4L+f{W$)p)xa<*KlWJK*wemc~Sw8xE8jgVAoDs2t1C6mnb~}h!>;L_EtyJk>$GtB;s_^VwZb2jWJ7mu^#} z@ctO;MC3~56pW3qeHFy_TnL^D<;7a)Z(9Dlbxy_3+*|fSffq?rrU^ zbfQtjJb%7)%{#KWe-a8G{Uys#)5mNpX2a!8?I-j)c0bdwn9|DyZ9AxW1XCc;j_16G z?#}kehHv*UK&L2%ei04vxL{bOt?%u7Cod9Sjw*5_$2X9J9wA82c$3-Py2;ygiDcr2 zk@SV)MAG;9NGjuouf5itTL$|u5#5)gpU`$V3Cgs`q(jp3OBmtCPA|BdAlabo8V_l( zdPeA9Rcs*AV5?JXeJ-|;hb`t|3pS9!cC|GJu$7W{Xbdc-5GdP~bFD~_EyxL~6gG#? z(OtPc0X)S?$Ee?T;VKe`5)RC5wfBE_gG|W|D)F)a%8a=1(V6Wnej1|fFs(8{@hKz& zAyq>%sEJJjMMV-#>hJQYw>4@@`Dyi9%fyegCRY1mh{?$()-MoQVeBThjZyI>j6B9F+F^UlFB^aT%`S%`XXExN*-O_+IXSIAcc4@CAH6&XNVH81n$y zt#F-8iS}Gn2i#glY9$G@`KFkB+iAXhFkfEs- z7pHKNu1;oo9M5kbPQO*TQZO88*15C4T zBg1W822kvy>;^=4D6tnHuJjIj@-!y^YERG+sD-Qv z8|E!#C-5f~ZSrd875c_gol;1*7Lt!?Aw^(?T9rc1(L#^}qrw()vR4Q>?Gz%fULpDs z`51|5S+(}q8M6j>kUAg>&h#J#?EwpPs5MJz^_IgTtsE!Gm%x%3m8XS@JOu7XyVLfR zNw+y~lEs|`Ph+S&G=ydTdSbEOj$iI5{3L?eT=>e)s+ySQKrxQCr&^v2LD5r)&4!Tb zsvS;D{th}?>9aTFKU*&$dL!&O*gaQ%RK<#UZQKlI??OGNX>WtnW87ERgHta z+3-v+BP7LO&V~>7Qi)FBbv);C)JUKKuo&iMW5^a%-(U#FI^8z=sJF@1RGn5wlk+yx2wl=yF|F6RTkJ|6DG!BbtbAb=bE7%MOE>w0Mg?S`QDi#S=cCu>OmQ^?_ zy%ORM7A5-ptB`M=^)VVhPc47xL@mDE&zzIYBr4lj{$!*tRNvhhd&zcTu8U12#X;j# zlJV_W+hoh5A)Ir~hDVIF%?PTNsAy;-z}F)SIv|t^r8L3N0@ZIsf*#x(dcHH@&bHwc1BnSd!T%p-x5X+BdsaYCasf`G;Jt$ zsE3pI-mlC!t<2X^nF^gX zhKvN33c?45Y>Tlby1hi27Sbj)vB00HUP{}Fda;Wwc7raoW}jms?F{?i@(FABg=iNBGWaC!1U8CqyH%R7tO_B1!&saP#d#_!r)x=O`SCK&>ayYQ ze`;%vGSuLq3FmKV{I1Uazzz;k_#euIzv9)4v>iyXPesiNB07dFDC&L+og8y|&dGM< zK`w6HyW0mml=z}aoO*B^+?DTB_m2P0KJFT6`=wT>cZJF-R|u{}1D1}9$Z^~80L8AH z#w(>!jo<&~ufUDL-5f)Rz-oa*#I&ykh)~MLD`jgf4SU6ZYajQHciYF4y!nV9#i{ByTP*Pxe>)?}nL%gUQr9)Rzsjg*S^ zQ~CERSI>jCCsFN~~Akkge=Ua-}& z;nzO0`5;QjmxsRt)ELk5U4*_Y07<0^!`&tlQWUF6%FjDT-+v?hrUF!NSKFHjy)VQ6rn0G#od@Jv+LkXm$P+9|VhhU(Sh_T*_GV{j7{plm0 zVkCn5B>YplPegqokF*IgjNqUT3z;^AsbpZ5&#bI0fg-K#S_uRACGgGTM&*aZ;EC$$ zErcQ!Rm54c)6lGhILf>7_}$F~l=8?aTfdw|&SjFazpDc&#l#l2Bn~*n_b+6__P|zT z%=WUn%E#q^L>`zR3x(2)66f{KVT35fJ`gy&I_*2tW=%Vu#_R%Dow};DpQ=0 zq#t@Vmltk(uk>^C3+zWZ)%pY+Ke97TbFho5p+UZe&ILN$%_4B^Hs_`6x`-S6bisHpLx$w3*Tg!+Xc#mr-m5}tMCb2YN~^@ zwnJUChvGaLO)ey0T680bYNYjE_~wz=fdN%+SAYrJ`hn6xz)0I$crn0je>VgI*zqwk z5XKt);-SejO~BSO9iY%O$sGA9O5hQg$->%9yKX8Jp4*HwD3{rm-b~_=X!m_nrW1eOH*=L5@AbiiZlm9OgT@JCA8^5lxSDH1JgrI<8|Km8SO&U zo`Apwssf^!XG9(<;d^hUX?sZI*_g&1kzT_LGcw&;?>YHQ^bvgfHm7)L`dT_>q|e!< z4)zE1@wi=PreBGs2V&_L(C&lpIPHG));eSX^_1u%@uN&JslodAHmSje_)a|FGqQ33 zOIs^(CpM{k&41Za&PM0-m>X6$ghL9qLk_(KV*oZL?!Ub~#I>d#^rhA;IC0wdr_Gsm z(wxU<#nNxE@6NXqQJ6vF%NVF+R?UFt9-e!uOv!a0d@TJpRG)h93k3&iaM%D5X zc2?g@*9qxKash^tSypnrG>*^N@P7XhSy(k5U;QJ=c_36-hdvZ7ejC28jXs15&*4Xw zujl`oaL{BaltLer$wT4tq^oLjg3D*1Z8eaT0A$yp+e_RbA9D_90z#_^zUj$ zZ_e8;e%ooTcedi_-7^M-bCFm`0nul?X9YN@6v~&wyeltK8_#DEJi3v#%T=D4N?FrW zXZ5T~ESv{^^srvK2l;M#9D0XTRN=Wgw>49|m>ZqC;4D6Vq^f8}O)ALz)4P^Tr=N*W zX>m78WLelc%}1yeGi`dt(23ov<_RI)6dY0JL}5p}Oy}-w`w+_d5xJ?^$iRp)T{%ek zG%=^tiqrJy5?!&(FUF5!f$4hwV1o*S?xUyRg02^0=?{=n`Y&PSL=A{-roG43*kr(I zjnlW3*4Q2eRJfZ{BxFxKxH%$jj{P(T+pqi<|9J!du-=~d(p^u|!Sy1($qo@bH?Zz> zw_u|5j^$#}*H)j$#VbuYUxbS%wEA46k%yi%qQYypKc(^4Bh{UVbg3?t0qF1;H09q8 zgQjmG3{u4)y15f_KA(EI>i+sW#))FEyPC~t-i65#as)L3PkGudot@Pyy5V6ioTCxn zjolGT{}=XZYW3)O@-q^5&dWqeSgLF+lwMyYBb8w?$N6WNk_~V7wq zz!$cSjuV0x`CS`-ZNm!!iW{{sB{E9DwhWU zWtwU1Kmziee`pBMY)??Yj26EZZ_JTg_v)Kv4xR4G7H%_BKVWL`0W`&syv*`2S2~?aT+yj-@`K};@|KeyKYw0f;b+#lHSZQ2e$DyLKhtOBvkH%SWa~LVI4D95o*EpL;0jqsrhAYrn4S3u)&ufL zfu<~!uDcpLo@`PAoYLg0a?q{FWY=nWmyh(?Y#cO}#3+ai$^P+2{$RV4fc392H z>T+xg<>sg#T68$#!*fM2Ij4c~vA1jsf!ZbVMHxqoi+k8&GC(Kg(aLW*<+x%Nj#vH<#zUvts#Am{@C_r2}{e1b|; zHObp07vLoUVC$RkpyE|Q^U12_UbsZYZ@zAY#T3?_9J9@Q*8?tGyMaUHd_#VMv|-k` zB2b_T$d3X!kM?uw(9LLEHmBG=KBFfGa&B3jlV+>US%fS*O|<@gm)gJT2{$%{Pc3)I zqS5Sfm9!s`DABXKWMeuu1h55VW}NaoBHF6{jD+SlLX^xmVyxaM1n~>zHogtT=o2Da zXMEB)!}T*%*7+aoEUaO6s~MYOzKxAWIwfPuZ#I^c20x`iVaEF@S%sOPDIMS) zV*un!qtQ<&Z(^H;5Kc#@pc2N0k5Z`hugCzxE$@-m_oRgq;B&O&VOqy4kRapssaMEY z!4{xb1|FXY7-hOqhzco&Fe9Onwxxn4+Osyv4K6|m5t>#T{j5Z{!7Gkk;%Yx%u%E9J z%H+%Bg3l<-dMO3A;PIKna!l4b3~jjCqI`qNIStCu1ObT^p!3$RhxJZ{- zC_6~5e2Og< zqMzFDW61ldML)IAPc8YW-G1tTpBnRN;2m*>hJ}7=$fs;L2mp0d@tib|ga)UmG2|jF} z1xV+b{L~3PY|KxM`Kh!0)JcBoTt7AMtk zvUp3x&7lecOtkzGs;UzPaTk2}qT7sHXh|n8bGSL#ax;9s>qKi2CNTD1t{1p%_lmV; zfMAIm5o?6=#Tc3}x~Z_l3EU&rnCPzomH=Z*57(e+@m}FNDPWTmIWYMjlauf+Q7!qg zi#gMD-*OPrF_~4w+En<{zv}G?S$h&RnzLULwB&%3W)_js>1N;BP zCFj?lDmmcsE!yX%2;OYtMJ`whU`U4`7D{t}CY{MnIM78A1SwRO=rh5=an6(eFnt#q z#vi6dQnmh_{?!jsB?xD?B++2B#MHUOy#I*_g^O7vAo)j{VZKR5xz`ryQjbhBKNNr8 z5d8fwI!$zqkDr+x{F0IQ`A}sET&gw^6n&xeC`<-h*^#mmPI)yZ7MPf;x5_D#%iDg0 zP2G};?HWP#aR5#)0b7Q*Zv>B|KK;Reg3I0;K5XROEKCP-(|8dWIFna_Y6x$k^x^fw zRESPsdkhaWFtTPIep+7Sy1&}KcqM;}c8c>VZadW}4$vctDQ>`0w#_M)&OV6NQ>vFa z(?9Q11Vuzzz!R4C2Q5cisHb$17aNA8ow%^ko@QbeJ#3gDVl;XqRb zNKg})3d0q<7siuJuTrf5O%*4iQnKs9yJ_R2>$LWsxhWN9R;XB^I6%)Et>|)kAOApYt+Mx zkc@q(&x#`c@z$+&C<8O$3Q0Pb#B}9r#yXjR!9+lZb0-_9)-;(T3Y!z(VCBI#2^WO; zsu$8*-$QTxE_ldeVOrG%R%yf_wtR@onl^EKFCjrDj>cms9u;)p`&2wgCGIIuIcWKA zIICtVxM9+l=hoxM9XJ{60)Ki>IO*@m-*6X@l7(ef`pL{!iyv9pir0A}E?e7=M-J4~ z%nETbfm1NR#ez(Iw%>W|#eA1WdNd_L#d|&Ry7mU?D1O3j%RaX85rQJ#_-;VNvFcLq zN;OwnGQlWwCC=URaO^L7mt?5zd(`dWa`s|9#k zEx=pW0{rGc4cu5!3vjj;;JLK`?_Ue>m|B2e_;(H5xU&}E%W45Wwie)BYXKhoR}B^X zLoL8J)&hKfEx83C<)`egnK`fguot8 z_5N~w%e%PtG`B=FRZDMrpgp>#S{BWfiff}U!);4jkGELhRJ~jyRj)~f(gmN=a$&Uu zq*yr(PesgZ2Yxgbn@e%VkF!A-E}^Lnyny9p96)0FDC~xj&osN_^Pve`aPzX5G=SDB zB7iFIj$?2sG#26U5B=Ga1=E5hctl4D29I8hHuDS+NS8)kOXC9PN2)66R1R2R{%Iv2 z@hgd>LMaPl*i@1r#qw*$-jaG^s?O61vhka=pf;Pg*O%!}FodG&-;}Cz$EF9mHbif> z^SWQ~bz>=)7w+@t9c z;gKKYbENG{^qm7xCyash(k+0>kGF!lWd0-O_*mePiDw~NBrTODBot9{FM1Q2 zzCHS~Fl!>j?PZmNUEUYT-W=(B#K+;^z2dm;=jFW<y@&BXkTj1lI(*GxIr%kI&&=R+8(9*ir zCAPFBtqxi4ht^oy@#uF>< z!1rqJ3^|fZ(Q++)vIAq`yIK5OxIWS%xzGXA-v+r?lp`Gc>>~lIUJ?mZ zjnC4?@f5Ch&I=aFBkAT02mLT* zSKkJ+1s#RSH)X%Y3~6kEmGU6TK~5+FmJR$v($CgLB$vV^K(cU=2QuYFKq`L|E0;AnW22HIpad{|M z5$g#;C{5g}yZ46D#JB)iN&2!V^X2rGOrI01dCpCXVG)R~!cm5qlwa;(RCH!X!(4SH zqObXjAzKkLHhem0NQGYUo`{Tf1REC%o--wF3Cp#q{MI4+((WM&d*S>Wd*lVAhcL^_ zs6>$cl`Je6KFO=2k?On(`sok+26ZMlY~muv#ME2-T*|8FX3!0w1WA5)OCH^mSKQr_ z$#5gq6ECl@O!P4&mI^_4q<}e%b18$F2nWgRJ|p;Xb6*KyO?Ejlt`;!wNXkt(01rW} z3bRb$Ry8whf{{F=v46zjW-!B=d-TjG?16!j;lL*-Cs*dmnPhXja5-=KLK$u~`zSDF z)VwwL&DeAMc>-Bg1vX=2f&p*zE~fVlOcQj0M_I`L-f+`oz$(<{9pIO}6sc$twiA^s zU2P=9<0RX>AYYh@lR-)u1Y4e{(_9&ah1V=KHppr($nsnea>+Xvcv6c5DU}rC&Ne5w zuHDs1D647vzUw))xlYe}PM+pAVN{3dW7_!cj_~lEJaUUfp>ii_*K*43)-pzS(D*6T z9;i!)L}9XF1)^$%a(}f-lv@&!zVG#~*JISs9D0s2xnkTY(XA*%Ic%&EWtA$BiGz;# zj)-0iUu?DIp&J(CjO!yS(46oJ?-I7h5s8T*Y+{J+W2jdRYS{|JGB-dGW9P3bLQa4b zqQMM|RN!u$*&znV+vLoftf~`xN~6h^1X@F-_7&RhDP?sI%re1FEYxMRuePl|y z(dtmmCM*v$$)=8h@nV$&1BFe`w{R~#1qdDI*tOd#bit;%5c*V_E`toD4LG64^9oQr z>|QA>E`K?_`@3RII)$}o#|C3STADx;&k{akcZ4p*2s+Q2GCL;11il~la4oIiBCC29Kg z&OJ;;PP2$47R^B0vA}ZSz)-re*!I}&Gu1RRSwr<#*ZMmHcbkm8J< zpB#3ha;hs8zZ^_M5)`*pNJCc2K`mTsmx4KPUjE%mDMsmgUi+HcU8$0_wrPS~moOlY=PtVSG^+gbD?A3eS{e(9Py8 zGcRVtFLCf3)WYeZ%*9AT(hzQFpA>ASfKPqe&HZMZ`}K18MPlMeWQaKj1M7Q`f-z=oC1~#!~tE*+U)wl$jg^QR8)scbZwrrufVE;K>GO(F*a`2tr9_E3f2iX zF4>D82@AZfWjyME(GMy>lzj-iC~aPu%P?MJSKQ zQ#c`S{GIYWF~7%{+D+rh(;Sq?p;b#BTchIzsWl`z+ z=-~9TZ+(sXh+^G4Rk0`0#8#?%e)UwSx~#Io;6@7$GD3`j45#ck#R&mc_dFitdP2sC`{(0}#+Q@tcdXCDNd_G_gN|)r*z(p?51qW@WN!%7$nJ%6L%SaZ zE87@ubliStwjZ*)zN*z18&0gq>bGR=~#?Lt2_&d$}CAL011da60$%G_-I>xt``4ajzDuO!cMi;hh z9%U8b-xmH8lY@3pfy`3%PnJEXtCx?UNKk(JzabWY4c;zue$w<-w~gkuzK}5q)+xvz zuEU8QU}`@cgCXZ9Qg>EQ5R>Z7r~UHlZ!!BQ2Wz?(!EN~FSC$_!e*ZC;3)U7>R}!to z&>vKmoa#-~|A1C(p%IAhKn-h;591?}k`uR)D!#Jj<7<2T7uIu(b%AGv`W_v5W@`hP9Sv(D6{j+YxFrFm zBQcpd2Z16+V3PGF?a&aLbWswU+LvV2v(ORC8;b8Crof8Ej%kGATjjZ; z%WV#WH)q0|kTq*4gPhBZc^Ekn82vAshlN1iSH--UzOR$!pJcz>L5qWU2!M&gj+R^= zJs{^|2TU-2;bO#PdKGlg?}9eRG1kSjT%Gb!ON^XPL9K?eGOWORsP#Tryite5gx)|j z4kQb1ll6oq4x>Mz#iHS62zC?bFO>w6peUFY*zZxZL`uR8@iw?W3ynpfhY>ULhWmbpd@+) ziYF|k;$^uUU~#i8Cn+{kj4R=Yi+o~oD?m|9@MxL0(mhaxNfYr9u|?5PCAq%yI?PL8 zp64=1_Kjwe==esYkej3Z?Fs)V%e!8U$f0CgC*w4b*zqszQZA#&Ohu@q*iA%7>t{;w z(9gtp*p0$mubZ7{LXYT&BujW%nmUx>E!lo(P;7>>f5u|!w#$X2*SoucX@lP^JTQi7 zlb%Z{N(u%Ua_Q!EQ{LAhTm<5M?Hp}`Q4xAcbG+TCrz6~HY!1|O&naYaWl;cjjy&XW zN^2wM(^w_zjlT&eN8V+(v55`Hm<+O<4bzNSmh8qkT9P6iqZ3{QotRvG5vV#4A~<-l zTM1C6`PRR83;1GxSCAvB5f^N4jp@O<+7Hpp1LYSNkuq8mM!S){Z#_?oE@>}nlc9yw z`oBqY9lbxVJ~&wjRa2vImZEhErq*&|u2WkV1s^E?#NhLnPa<&RGA>nB`6 zGFZMKCq@7d&^cKV@%6P97(!&*8=MatUZ)Z5-oFt=aB-0FfO@|A`Q*3ZbAZd|w&Zgs zl6Qh9dz=XkGX`KQxrr4y&MJJIeGGN-1_;739LE4;2FrU z26PJ?cbvrUhpUA%Q?7o1has?+jFUv%#>53e(qtri&?Z{uABya>>Q-qY$yuJ!$6a|F z!5%Zs%G?M#RWXfRKutizXrP+~o|;%K!{DA1+{Gn_Wu26e8x>{^B(xkgwz&(kBsk*d zHWwz2$w_jIPm*RWS^-n0ptI=gie`%ywBy*~EeSGhqc<`TeSA1%8f)b*y8TJ{%!Cmz zw78xPBNUUKA>V{5^d52(gaoe)Vq!Kzej#o1mi^t#N2b0Y$mH$5d4>jaL{6~JVXve)skLRFtdoe!K%wnXOJQnVL5V5L{@#_R!wV0L#0;mM z|JqQ}MjNh;Mo2ItOR;^2pq<&fM7}ePH506&%$Ixr@RWE&K&q2aO_X43LPPPhO;DzD zDRdX*t$awcX))~%TMMnFcJ&u0sc14R9X35nS+gNT_7M}}J2cyEi1)rd9ZP3|MXzJIRV#*Hct~J=H}dx9SWmCYEj(VZwuvcA_{Urm_0u7{0&XG>D$Bem z9$$ti1d0xBH8O6dNL)CjJvC#Ic33ewAAlJGz&%yMviam~9kSUN_K_1UEU}zD;ikY! z)bbealbcDVHsLuE-_3ZA#GzfU09uMg)Wo!|(3 zpntKx3%0Bnfmk?9H_vd**$C743uLx80~7{^V&KPthd}0gq|u{O0ri(k*$~3`QXunI z9snBd17M^rkXe!kfD-!v(p_uF1B}cAU>iXoGdm9eMfOn$0bmp3HcO%xx_MFrl|sgO zQo!d_-zRkBaZD?D&G0I8Lc_K8Hch-u!)WHeK@oBAjF2lBCC-CnM}59R?LWCxBd=p8v1}~_AJ;?05Xs{rx-tH;>V-S zT@>Q)vJw4N#0mc9K2rpp@z33B+ozJv32Cd_9QQ)HY=f4J8pz;g2!hXihu2(GD9S$R zbK)K&TC7KFWpFn0LLM5W*N0{+IP*XrfcjD?I_jpL*(*J@+_LmjZbOefM@{Up9fy#;%c*b!_{|}h2DFM@mRK|+5I}ZUH^VtR z!}jT_yV)!@o`YIgXfyMT?1-m<`{q(n-UehlB^HQIc4<)Y4}q371VpDB3UqoANaxR- zk8ksInxwK3EE942-{TA+p6`ZJc&eEgu6=N2Eb3b7#!PkPu%<9Xs4!uU?D4Oki4w$| z2PP++iZTwPVS+r9=Q>jIeU{YiZnR~Tz!fm@D87w3ZeTuA=?m!0HW|k6Vr~6^Xo5fw zyxXmlnoOmV$Qu)JJK@_(euAdlj%}lhlpzY!FqD?#r>hu)%gacKjK}Jk1whV47`#FB z&aVJ6Gwsf}%{c?-3_S|B4;m$UZaJpDZbltY-8zhd;I1>5Vws(^Y+ph7q&Itl>C9s{ z6rX{hW)k9TGm>JJ9+EMQ+?0&Bkw6w1AZ`@zh$u(&W+6(9Vu~xcb$u~#`WkYczG#U3 z2Vs3oQMOyQh{&7aOi;ub0tDtHMAR5Z!ooG2b9kpK>XtlFyE1gg{wPsz^y3a0{qQ7U zQ<0?sp9!2{eNTMN!IwEU+bJJ#r|CRSr%{fHS6??(*-;iOL%QbLQ{)GUA#1>^W9VW% zb1n`D;2IkYqfB_SQY|ng5iup3j<}Wnd@I^yY`7$4O!l<(f$Xurda z0MZcda5zJ_W?GKx>CR^L?D5aS1aSi?NN5$=Mtakuva*GolnGpQ;BanNLPx+1TWz6Nf66R50YP`I}{>EZrhW0g>2$e1|d3fdI#O1>y zlM_|LD<15zaCMPE0^xDL@;gA|r0^2U^B);In zP-pyhplj^ND=Wk}RESy!Prlt2J!5yI%i!KcY-jPtz;J+VXq$E6>s+_m-|+? z2grf#;lu4lu-wD6S7*%H z3)4W0wLw4O)&x?Jq+nugC`WL+F3%0EJh)ZoxuKSV0$h*_h?*M?r@9WQiW$KB2&0t1 z|6tcY)`o@|99SXPs4K*QQ&H9-A`Y9hKn$iG%a(U_pbB9y%wh%?c7&SjdW&0K!PV%9 zAgo@HkIYiEy*%k{$8qa;f%Jm6_@vi;b544u?5EP5&8(xkM`9U`Ov;@Nk|vYQTpufG z7rQO8*Aya-l4iyM>ZS{+ZjVzH0vTkH=j>)jBG1iaM>NmPWXI{oO(MkhikoONaUQ>E zQL%b=S=o_nV__6luF2qdvuW^J8B0Dwh9BJI7B%rm9)tW8<6tr)RWVY;n1vF$35m5y zo@d^Gn@v%~vB%*{?EbU%vyair*$I<*yyu}75(r?y7YCj*+Zm?jKrE(GweEfMm=zt$ zaMaqAA2xh!Iz*c?li`I94W(Nv1SfzYI&$?1mwfkU(ZgUYrdm#jAm7%(TN39}TQ)%A(s=w~7&!^EDdV z1G}TrX)Mazk^`C5&6~aSEi(trdlPc+=)h{zG?raFLT!BXpz2n!z8E&Mxbe{v*KI(% z=!hG6;%Q(S(cWZ)vU7(-%<8>H8E-i3di2eZ3YJDwzu!U42OjO(a09DG2Enq6`0kR= zVI+X$nb10;d^ivN1~-?D_*oLoLgP9wr_*8pxEwItlv!!g-b4XmJ+PU;Lbu7Rr!nGq zeFYbLhid997M@&dVLX?JXVq+Qk{@cbm9j)!wiV@t__~cAa_9!SXVaLn{E)>+cx_*C zcBXNhm)^M;GmnaQEZo%B?EVr8RyLy{o9b4n978qd6y=OgvO?O^touzV!Z+;RxCgNy z&@O88wtWougE(eyuJWdgcELh8P<2)nRup=T9GBY^kQAE(W?J+1j`h?AUL)CXooiWaa%BxNub`ag z`4sX1BnlO8<-j&Mo3otEuACu-sBng9{3A%_f>reUiCL6_-Py$mP=HQ+HC@Fp7Y zd$6V(ts9SOz%?512^#Qj8t{K$&o?@O9UAam8t^3=@DUpD_8Rc#_q)>IUDI<=FZrj- zxRoN7bd6T)p%pHnFl0pesb?djfo5NC*8%0Io?2zq8B_%RazuHhw)?2E=m1#jQf`xVCDKf-ttfM5xm=LkF z#)_;$S5K05f}q*d!#&F~H=DmM;M^vu(J1^}jn>PF8_T&!1mj0s{_0*u0#h3BO&aj|8gPXMyrl;G(LD-jEYX0k z)__mbfcMpagBoz>-3nXIY4fq5NcsC9BKes9p*r5U6r2$`}0UzN9 zm-V*XRhARxuaO<{-vs){Ek5b=9uwBiwxC(hzxk0JF+i7pZr-gwPa&Mf!%A&*!6H-V=9e4wAni7kJg0++t#Yt4H%{kNjIJ1=Bn z?pl9O8b>$bIK;xpF5HM9=#}PkIL;sF=f*Na8u0r!`qKV$lox5hwHolr8t`5kaFGW5 zT7yCw_i4bFX~0u7;4%&PUpFWc*scNJr~#j+0Ux3PZ=nHyc)dazEgEoA13py)-bVxO zrvblFuaL$A8t_~VxKab&Sp)v&I$r{%qQ@qwt^$*dd9W@HW&Rnn$#~B@U35_o0zCt# zG3!~1)n>RJ1w)mo^r+i#J`kEJDK1JdYrqPv`>8)mHpT;kgP8|87%0u23Yiw=${5sU z_(-B&Odf+(5uA;rW2&M8V1rIojPc&VoVQS6b|YAGf^W=mC-6w4*iWNa!a2bw@*pLC z2p5&R(L~&LlUOj4C%#Mm;*9nN^G^zC zJfQ(!sR5s)0q>~+2Q=Wn)hVQLuLgXn20U2<9;N|*d95OW&uYL88t}Oq@WC4J<{I#t zYZTIWQUkt913pCq9_@j7s^&EGjIp9C+Kj`Wn{YN?qrXPtGF9HkE6YlNN~QbO`WMc$ z!9pWoD!ukf&Z}Wj5?Afu`yKP$;q`hC!Le#>v&-_nSI;hq@SJb{&4+)7yHc`0YC2E? zHLL=Y^(t7sg5@}JIx!d3oN|#{<8=12hQ_Y9Y-7D5$6{mMF$kFptWY=0;wg>K}GuHM9U0}VvZ^7ypt0=%{m(&xAfrRC6@$iQ;0-J+-pd5 z`s2hxpk%ZQpvFjY)Bnsux*)z8A9#Bi^QZl)t_BmaRnvT%wMQZYJGoiAFyriTzrVhM zS%XDCQN$GPSRz#{;`rhH4a8Am;uz_hSLEnPuT34uj*SJgrssFa$HI|~XOfBna=iw8 zjs`qV0}g4x?_Z@z;35sURs%j+1KvvmF4BNsODLpqp9XxH20TRrF4KVj1^c(rb71Wn z@QoVqc^dE`8t@hx@P{z-8!e3%4LGR*pQ-`xqXGBRfZu?n-Dqh%paIYI!2T`lX3-uc%SNskmJJJ6 zm}7eIzENxIy{%+nZ|Poo?Uphgcf(=@gzR^T#P49 z2n{d7lO&(OvklM35jwGmOW*PF7%++YD)aHEq1$X0W7lC1)--I@s!TdOc^F@jN%*Xo zgq>SsCSm8+=twSVaXW*oL$b z>uyFP@J6d?Uk&*6n1b^C8t~;B@X;FZP8#sne^exJwFZ2%2K;*sc!CBzL<9bKfkGNf zHDE^ro}mHnrvdlZfZv3P-RNSqPy?Q?0Ux6QkI;a-=PMHUf(Cq>27I9gJV^uI+5@v= zJjU%;p<}!nRco8SYDLGmJ^X&4J^TUAGGD_rr&->OVtR!M?D60R57~4+1=W-6I1l3m z`*`FM2fmIQUxmwg*2v{NYp{Qob+x_x072z01PikVhkwidEIM@zyHj)^wg+_nIjKK}y3&!QRHg zG(Z%a`_dnh!;cxt>~DfNAVO?Z=BRh!evb3!qW;UB7>3*`+dvmJ73N+%aGnf*W$y4u zV<-X9qkWK^`W4QAKI3`mj^o4zIk4e@Gq53x+tXwtNqS4f6bpY<6r1~1Xx>v`FKwb{}#!zdE346-M_S0PSNNu{@n!neqX4p9cOJHe+5BwEb)5PWh4wU%=8 z9S9vvo)$E_Sqy`?m!r<2UOt+tf0nPk>4O8(@3+4&33rNgcRFVRaE3t>KPDN%k0vywoDEFF^M3kRvT}nnj*xkUYgpX!diF5eJgS zhf}@-pevZH^Z}MRBqWU;?x%3P$q7z7)lDk&klW>mEgXj$d#PVnX1bzuZTn;#WHK2# z12#&erJf9z;@ODrGCUjnA{Q+})+bWw;Tv6 zi7rn0nWq_PS77whnAkxr62csO zk00C!21o?i{UMkJz?rff_0LZ={4^KBdq4O8GnSg%B{{wHIjl2^foy9q7T^h~_6ln&IB8iYdE7QZ-ok}>dP zTfStj<4%7kZsICG{}huCpI#z6z^ziu5={LZ-~lx;iuL;7`wfvDk03ZXhY@z+bSM;h zQLkNuk~7Psg`!`&qp&DL;(t8ohYfJ~S$}dFyndYNmp*kZ=6$h?h7848`S8rjDk8BX zlU_*pYZtJ9q|$Y7f>T%vM?A0xM*Jn#GwL|MEiUHVYp48z=|&6@dO7wWCfqk?i5+T) zIqvZ?K4M$-B({?!_C1-#&Q#0UL6+Dzot884$m8rehH&aT7{c`sxo;tS1+N@y#If)i z;CdIwB5u)l93P3LobR?HBQp(4}; z0HTXt&bUF+!it=f*TQ=AVj2^nh#It&p+cA3524MVdB-UNaInW?iM~90D&;2y74SOv zddhcrKT13J`GF>1hB!U*r40VNPO}w8Jwuy1Lk7GCNO&<8RNAf2H$wm0>sC%}gu9v` z%-qW;@|E|o6HN{#jhBfcm45y_L+lDeEa`|x97f>SiP$eI^uJBZ z6Z*J|dKY@|@i9hroyp#1mpy(1vcr9?)O5*dE0D6Brq8>&hn%hgN0jmz^m05+zw=xp zr&IrKh2B%s_vuM&yd}1kA=WJUno3W##5Q+{iASE$*D#^^Ik@fw!`XB6a^h~WDYnE` zy|%$(b3;#JcUfYW8)A)?v!{M%k~!NYCLVd5{i-Li<1Mkhg_t8b+*8<_i*GM>>m+)p z^{B$HN6F*!^yn*E(H@0&vLh97#Ay}TS!-phQd>DVi;O6$hL=Q~MG^I50ORc}@;UZL@ zKgf9;XoDKC<4ADWWHcTi`7Xu@T<~+AOcSb^AT?H8oSpK+aV;8spWRZL{>MY)nPXg$ z8+PphN=~rLdRWqCC0V_I5`Els$SF*r_(!m`W|HB8y!hTd&crv>#5WPe&+u9Pob?$i zKB1bsX{(KJLW?WM#hx#!t>lS{j1TM8*wf8iXY9F6%hi^`cUwqWPDEOEC`ijOX#BIY z(iV3CYI%*ER!hj z#u$Z>;GTI=K7Oo`;Fc0)sOC;c0$R2jViARNf@6A#Cn0Kxq9fYq_7VSvI8Y%mETX3u z`YzWTVR<9-7f3njKAn-=-L^eV1_p?WX_kG(=Bn| zA}mYXu`upDedl+~KPPx`VYC-NbM&DNLv_J`hz;|C2{R_g=ONbT zQRBm7+$b(%h5En>WrtO_irJ5zo}Ht&*p<;diw#RYZjWd$c0cp^cT{W}dBr&N^l*BW z?dS8TPoto6IHPs#y*oc_rqpe$%zSlQDb+I38e#39uoZOu82NHW2-Ezr}sFx;v^&dO4pn(nIEOI9ByQ39DF*B z9ao+62)0UHK!L=oCJ!fR+T^Q;dm-A3|f0ZCpo5w9S9 zMmT=VQEt=c4QYUy_9)Km1;Xq393v5VP1RFokX^QOhyvGjeBjV#q587aa62C98ZyBc zYvLYDXYrD8TrWpc}z{nc-n zOBucv~WE z+g`O}f5RJ7jv~RTEmU)lKk0CD%9r8VJgW1X15M2nBO;G+(+zjZpE#08Q6rS8-gz}w zBAc8hqZcBKX~CBmMytsUF2#4+&%^|RUB!D-YYf>ipVQ(QrdOCGjrE#J#3;F$*7-VZwzXgr0Nm-V) zv&j^MB|ko;JKPJ=Wg0-e$>L--&~makYx>X2Vzs!a>?YRTLc&f z`|`|DFCShkQtvQ!bJP*8$ZtPOL_U*g^fBU;KYO^*_>cQby8!i)q!m?)Ebf&L z+~<=$(hKJ21>IW_TXK;tm1GISzegn284d<`9PHrZzzNzUppJ)IMDY}y#LTeJ-8eN zAUPLi2ZaDHO*~1QwtVkz&^xRA2~scb{~wRk{{Q?bQfs~jsbH^jmG998=dQGNr{n$U zMdPF}`lGo%;_?*y;*1A5;|c1|7yN(6tN{OC+YQR%9;E@{e_s1v__>u;EhX!1w0UxdbZ>s@+`fG(W+BD$5 zXuxM_zz1r;gEioPR4SzLmljhwW@J&x()CcNbZ=Q>VB*aM&eS z{~YdITFjhr%6~J;EN<8bYJe4TWs+Rn8oQJWB;o&{k#Tx+@#jh@5&c0Xm=S$h*or-zW^L%?Z!lXvwS_CYIVT+{#j^!RwDmLb+xw4TQt6%yjKEc&ybKT%^2ivO(&i>y z*+g?97U4rppaB71x+H8oKGLTFH%|ItJ(MNem+F(uKN0OWhZN=oW@^o8W!T)=>DP3# zS9Tpz638Bic-Gn5?6D&pOXcvHoPy)raC}UlmZ@6D+ec*~2&RQ)qb@f1uH#Pmbx_&P zi(2uPH=X;&!EXLeIDW#^3CD4l<7lq1NX)H8$*YdoJLwY+FLTEF$(i!78=biERBkf# zv)n1u=CAHbVc^^yCzvv?jo9?t#Dw74Y@b$Dam)-wjPvpm*u{(;i(D#)96J#=I)USs z$jWpvPRGFne7FTqDp3>NaF7mP;UrHBx`ApKhwF6X(QHCObYYyNLy&c0 zIJmS;PDUFiC!QGI2qy8~!1o5cr)q}Rk#GFrwbr}^CM6aQuf{tM+nIxNc4qOgotZpr zX9f@3nTCy*m4xCM;d2sJ{#0Pi!x(HG84bWlAj{xZ${m^(Sj_T(&6$71W5NA2G&G{%35Z`KSG+yl;*u$fbnjzaJ$~M+k1^`mYoxM>c++ISt z=|MZfK0(~K{v~&I543QX1kM zYI!)gMwPnLf`?yIR`c4mwQ!VV$J2N##cRZgSAR(h zZy?&RF@!`SSox1vBdqy!NWAf{$b*r@zfnARbEy+Na0C@IUTR2>!9xP3;uX2qNba>P z_c}87I@*231_5xee7Z!HN{>8$15ZYt}Ok^>yey^E9o8dT>#*?J|Hg)eGzsG80 z=5(x8@|$~!`I7ndK*_X56V9lM>>rF@gL=5vAiqEmtfFg^)U}$Bjz}h1FS&}vZH64> zG$pa}h(tH}zwg=&QG5}_%_b@0%;^Uunjyp&NpfsdxcWHpZ_=6gmkrUWAswfcdJI`m zYq2W|ye#J^i6AXLp4ckHlmx=R>Rfv>iL~pd9 zzQS{7VfWZtnJ(oSa8{95rb|r4;(gl+$9}^Tbw^w%NX3I=-=1L38aFwzt=W7t6{d>m zPP8t}xuLE}I8C{4gTd);cjw#?O~<4}eWP&^&P~GIeFQc$*IfPfGsUw3rV#w|UOU2J$B==g8dmUq6lebb; zz!EFa`-AD!|+CBR3Ad{6`Mu^JzUqYV%K;Z>?rye4m@LIBb%AJhhX zG|30m03VI=K@Gr1gM2XK@ll75NoYyc;t877c<>Lco;iH7)r6+gacnwGX47esIouGf zB%WPSK@6T__yk}ykR$P3#&0}JOU<*yeizGkzv29xAk8LU3knyy-nRqx1P4r|*g{bH z-ThF#HNbiVSbi6@^6@d&s?RG?Ar7Qxj;Y z8=?p~o^f6>0xq2p3%WEnfDzOxhKDB)MBhcW^&g1!x?XU{X(MHq3c7!$WrUp`iI>y; z4&(;lG^LD_r%g;w@SCmOMa|ueC}H*}h^0u@n{<#bDa!0hNS#mfIi3e|`8gco=WwXU z;SJD1*Oc$;QhFsVTOoV$D;2Zhci_LUD0lY)p~~6S^~RE$Hje@CItIDovMFiv$0^C# zV4NkA9U`OpFE<#c5s7U(3Hb3}N}S?hGIh5lyV(VJh6MuM;g94+*oM{ky~>*;Tm zn`O_7hq_}H>D-uwS!^t2EFvq32eatlHLp(@Lv$Oxr1E$Tc$5bG!`=!uUe@fvW62K>Qp3TZ6XfD;<zDWZnAX4`kvSikXK4D{zC0(B*rfJ-&t z>`n@4EZ2blqye9)0sm419;5-kyQ4xH%^Gk_13q2@9;E^QP^L)W%Np>V8gNttj%dK! zX~3Vs!fv#YS*ZbErvaa>0Ux9RZ>j-z!LDz#G#=N0uh4)`)PVQUfY2od!H!11`~kKiEzojl~*pLIa+z0q?B=_tAj=zO6zU zO&ahYG~lB&;2kyKueMPnFr@+Cqye9=0as|iTWY``l`5pML<7EB13pay-d6(-YQUXa zE2QzD20Tv#{m<*&;0*o*_x#K7X zxVHyPxWHWv)iMAO^6b!s;S00&gcHzwD|hSyy( zpoOb9a4Z$)PHV%TSO50&B3w-MIV8ks)WPne%W>dyqub~q4fy>n6qFZfz_l9i$r|up z8gP*Y{MzOUY22p)U#0<1(SXY|;D41U643nfrvV?L0dJuJe;86oqeTNwYQU#z z!24*x{WRb=Hd9FB0S$Pr23)BD@2mlT0}H&-R`fXy_!bTL0u6Yg20T;)P7hW{<0%dJ z8V&e#4S0VIcz_1{)+P#RJfs0vYrw~9z`JO`-=Tf7(aQg#27J2)e31qm)__Yj;Osz! zG?r_?f6{=@)PR4f0T0rE-z`>1qgexvX~4&8z@s$a9|kBA__79krv@C=fFm04b{ga%)wEnA&ZxS!jfUnkoPt$<+)qsN^iKvpc~gA zRt=JY<;=a}W6ADi$<8rkap=X|mO#}ny=Yzk$1AXLcWk(&3StU3xW{fR|JV$7H{3-z z@w|(k+?+>l_BC+|i_2Y_{Y;!(SlPzQLOAT5;YLQp-X^?{GTYm6c7YtUfkPu)7i_hY z0}JYKGj(JXHogf4vVT1?s@ASCE3}-0(3s(!ZPG%~QpYBY>9*{Pcv0|fPn1_QvEw%;c z5GPZ>#i|e_#I_5>W@jP_xoG`&p6>T@VLFK9?fXh1#72)coT>ruqXGBRfZzB|!Se$e z@LUbJQUl&u1OBF4k-+CP;9E4{3pC(~8t_mJIQ^|c8c%7!*J!|}Yry+!zymbkx4uzG z;~@>WS_3{-1Kvdg{_bl<0$-IrI#ycF_+z_@0_h!)lV}0h zx#hVqwmAE#{4jXYa9;o$5J?1!88R6xG6bq{m{#!X??wcc1h7YUDXLiPaVJRx`0SIf zSa+iq2>uNSI-SfIQo%NS3d#wte3RtxZ|XX;V>}gJCtd}X{*JGHQm(-Z8H0`Ow>Gv< zk#UIa7&o>8l1Kdv$zK?fIP?eHvDz8p&XW)ELh|q`p1FWyh*qOHQdmbOgKu^lz6RlN z9wNNv$O=j+8K)a1^U9}`ZoHG9xL=sas!eew0N;KD^b*^O;aLVa0zhy{M?yRCE+HZf z%X64Z*y>LgSp{HXFwMe2%naAB2nTHu)?O22_(2iesLW6nV2<)i4lQK@+$iLnoU_(_ zwO$q!6xQGW`4Vw2SVehw4T%M7OO1HCNjtG+e$I;-x&2D;d1u zTalpKj5`3w6o5xVE|tDD0RM#cE#6CW|H*+PdY-xiI>UQ zUn0KUVA?@l{CTKZLZA>4F=aTXs02^yXC^5bQHTU>A|gpg5?b_pXz>v6#sf18nCEsjjx$1h(*P^Z_OGRCuM9Jz^U5|nu^NfO=x^6^^a~lNO z=oaVN&lTVm8t|Vr;NNP%V>IARG~o9>Q%K`c4Y)=FK0yQCO#}W9G;O1GqeBC}O9Q?{ z13p3n-d+R#9F}>brSY@|T(1Go)PTooz?*5n|I8|+@q`9^r3QSG2E3;R9MFLOhNj_0 z>&Cqr@TD5?WDR(j2K;44k-%p);06u&Tn+eO4R~`6cuiU%jVCqWt2E$KG~m%1a9<7h z^^X27I9gJV^uIS_A&%eT6hyHQ+i8_zVsB z01bGc2K>%H71DS_1OB51JXHf8sR4iArAXjQ8t@$&aFqspxCXqf2K?zi6w+wZfd8Ta zpQQmGr~wbwfdBEHLK=^0z;O+Dng+bP2K?i@iUhu*0pG0w&(?r{r2+4t0k3;UA&qA= z;OjNub2Q*_8gNJhe*bNSG!|*VwHolr8t`6za9M9>w(@XR%w60AGf+51^2J-e1WVvV zbd7(gA7{QMr>?;qQyMEPKxEcmNhE(i;=&$83Meo*1Ml1m2N(1R{4*SU_F_*CcI!c8 z100;*(NhMWzF8;(tf%PeL11c^Nrs5wMwBsp=B;wLrw5%LG>jOwhq)@uh?zYC|BM(u zexaurcJ4vs=Tq`B%12>J-tH`v$Ock!jEEtB*6p?)fqy0?JM@y06MGQpH6`YZv~AaL zDkncPO7jRL=B_PBL2T~YL7^+J#OzQqycSpI#5r3Oae^hQiUP@geIjSzy!c>Wd|*A+ z`Yyb$f4V4;JsmH>XYeu&FN64UG+u`C~=4oF2J;To*`D~xV`ow4Mt zj4LhRG#UKknJ$fdjYIDkEOg$*ZO1L+CRf3-dlJQna|a0-44W825XR_aY;#@6c+%2X=7vib~V#B zRALMD65GeG^+=nnElWgSOW^Fn#1tGHp4$fxedC7wXoV;ROnb{q2##lP3{IO5ufg3` zW5a9a?U)R&;X*l-CfVih>Ebys*znuH3bT_9FYfBfUgrDK#ZXAQGBe-&3`1CN%zA^> zVX~U54Y?8lYZhUZ&39;VbuFeDu_n$g06aQ-vIj4LR ztiOaj#4-Kdo8PZ**_ja*tWdb6`9OAp^{utOi(OwXG0pC5eSdF#8(iPr=^Jc;JYWg(W&Yr+ZZc@3 zM!HK93ls)~p+~9oT-f_qx+vCNG&=$}tX@o|GbjrYoR|q~)D@`O$Ax}LXjdNy{1=F` ztH7WQfpL&2z{Ra6q>ibuKiLDyxvl>6g^lHRqndaG? z!u0-R+AL-Oc`N*MUY>sQN6Y$rY=J{Z!X9-_xiq6xD!O7!n}yBqBvpJ zvnB(kT{wr8i<^O11R{4;{2BPz++}^DTO(ALx8mqLHo~x$HoHGOi=tSHDywX}xRlo! zI*+$fNleJimCQ{-2U<3=yGVr<^}e@4Xslf2s#R&3{bLpE9B^ z<IOv8Bh|J4_N96gwuqSOU3!t;H7IQPBH6bFOs#a zXmTRifds5b7C^qeh~zC=^L&xagqAcxOB%Vny@!e{lMG9R+vLf$)Vy#m8E*7c1#ebW zrkK=qfNRtsR#lFK#-?{h-huZ91caraGF?Zs;tlY~aydK&3i7X*7Rreh zzmLTag|FCz)zC2;S@tvpqY!Lb?& zD&$c=Mjp;+Ja8@FNO?GAbWF;Xj-}?cG=i(_%xf85i}6~Z67BKR;D{CMLWEpyg{(}( zXE0Q(mGJ~%7GkZ8DiGZ?)=Hn+Tb(c?NXwGJgsBZZ~rXYlB|c^ytvAr%CQ}8UToi!EvH^0PA(Gq zOTeJLk<*QZ5gfTvA~-U=Z)>ko-T@Z^MG`A>DivX3obs`LHlBFdW#dmKeVqh>Zz!wF z_e6hym>VFAgR1OORDa=F1ZG$y(AsjtALI{zD8j=_qCp})Lp3QXnH}PD?SyOQU0hw2 zS z6_TMiw-2RXc&b-1FJ1>^!dK+(TI^Hi<2)wI!DRXbPC0ejdewcxR)QjJM4nn}b=UIM`3}c94XS424wsF$6MZ zV;hM7ru{w^mN5D*qE8JYNG5d@WVgaZiBDbLU$@v<>i z+j{A`3muH~Us;Pgt;|i>y;<_8pTkFTQL#LP1$)`$(Wv;K#K)$$TFPKO>}1jB1(|k@ zL~ZTl?Jr9D$vlPjG>F;soAt-8$Nj8cll8((p2coPtSkhFq_1DnYy1m7D~SInfBeG` ze`Y4lQqm^TU&1bKGsJi8k%>q6iM;g!i0mvxZ0J92v4ymoy;`GATXg;tW9*->AZKi<)#&&>FFbyBCQBt+PuR$^jMO7LkZy|lsAo&=| zo7sZShV80gh9Ea?Zr;mp0WeO)SRovw(&fBJFV_OF{25&kT7}r-?!k=%o^!>Q2IHA?SsGLEMn+&V zQA|lPuaO{ZLS98*6gCpxBNy-)jRr=pk#G$~VinY*6sn1{AUWfQgO~JUi=iTkcoXFk zYvm*0ujaP{26T-TI}Z0ln;b6(;q(nsyQI>G&@3caX$TdgQV&44(@~4qlyyNNqO?Vn zQ^Gjq{}dyVO8;h&-?dsy8#J9&O@2a5{vs!YKyr~Qn?KP=CPa`PN2&BvO$l7+7kG~?P+=A(AeC_E+FZa;51D*B34)DWn@L+S8{cfsK>3|Vf zGZ~4s@{y+j+xUqb;}O}<5Rp(w=u@T*FpETzad|)uk8t0Cc#|26d&~{O4Y#wnQg_6| z2>Cs#jq8$1UrXA_xEo~M6GEuX5RwPTzXd%`#JQ6?*2>@hsHkzjBSG*T#|k%Lb`a&Z zDjkMQkn7N^2AIwm#j@H4c`iTJ=b_Klt?aP{s>%VYu&`s$cgb&Imay2nMP|omZB}Aj z5E4TK`QvPVVW(ojs&4rChT03|fbR65P_;~P97`Ambv5oMpc3!V4A z0qKlW1V z?Jan3v;DLcpo~vAVT8e*^*{uvbQm;ab6*RDu4_YYy)f-Ju=>jlq4Y9_9l;*Dic2W9 z@H(%JRtb@%v#Is#)5||%{WoX3^v)m4%NFTc^D;2~sk~e|KnkBH`}{H4tr5RB4qoCH zGp2OYC#|L`=TDh^xXcaVPBj${`6I;YWHqxh;zZwGfayApA8(l?F zI~aNrzt%^ON)JXv7z_%(6Px?a#Z~?ByNQcA03S1}hU53_s$byu%&JoSo>jF4e$T5K zjNji&fO8Q5vF8S)^A&Gf!~o&D69@&{|00P+EINLf$axT6fqIa7o4?DCO{01#aJCSk zclNNaC~WmKib6R!%KRNaZb?hJ6v>2vd=Xo!I@6rI&GOe7->V9 zJi+I5Gs2`_e;DL?wx3siKqJAvWj^;eJmlkk+DdRg5%FZX^H7Y0?J*|m*pC-k7izfh zpSO>2Lj%@khQ$sDglZN@f@Ic(Zp+yyV1ar9)mXf3-e{;<8Z$D2hx4WnF*jgEWyT}q z=X=TuG#X*B^6>92^yAkr^rdrF8`60I(`gP_jufn9cpn^ig=RG8G5kux`)}2}unsahb*9*IyHPi~C4gc#c0jFQl$T@p>%_`21)y;!jRvTqq@)AU zdn7~wi)@d0EY1LnEf|z-hAC|-WR>HU=s1HO4JQ6ql%PFc^*ektL%d_8&W5eyW!2W( znbNVejJab*x(;QbcKyKKexjQei|;d7%zXZ_C+&Bt!o3QZ(H1jWo*QC55b#%&6~9vz z7>%QP=bNIFVEw&BG9MtFXjfwDI|XS>hTq}bVgmEgG|rKgU40`?-DpV}gw5-#r*wfh zf=j#iS(KsP!_3%Vm_M=H74Wwd2{ruDv`CX9(b^ydbWt51iTbPY>t_}QCKX=@M~NE;SC^9Id&QsPbu`;jwVjl`b5JUOYZcuC2wF!h}JTh1R4{Ph0s z(IR29Cf3T|KltrfjY3QJr>9{7?NOHL|rRO8G1QPLO zz$E1t$*S6s-KPG~roq{hV%>eK_K9`(k5(E16}f$0$p@$W+&g>)fA~}ADE}oVDKtt? z^ZWOMza^8sAf3D)92)zdJ`JTcS&Ft}CsSEf=BC9MWdDfn3GboPw5eeh5~_ZesS~Y8 zylMJJH#fQcqmOg()n#W`5k`kY2$p+7k#S-t(o1sa?0)IL!mK1wW?g9954{FZqiD=1 zo21ZUQ6X~-&eo=}iG>`AdbT>*$L@!xC5SojGce2<>#D#&?HpgOP>r^LDP}(GO5q=Z zu0r(q93Lb6d_2AcmifS(=NP}|_4I^6a8q!s-}6#<))mCNn;0UaAl9}dr8E`RNjuWy zE?C79XRVN`uf&0V~b>rNCe(t#e?;tkM`jpZ7_)9Wt0bhj!Wh|_K-g!)DrhRqT zcdnDaO3$}>XL+%@ld_#KdN2Z*L&E7*ypVEo&)HcRIMXyuO0yX7RJ!X)=|E%bNY3?v zu}90+DKEdzr&3$CpeBTray4Oo3#yY0=bEoHbE{c=Fku9}LJO)w9`#u6QE2Dd<0rro zre!)FurcWQhpX{`%M5zpuRT7EZ|(6D`9NlqTCzF523{Qo+_F$EDenFyiIh!i>V=LaFx1ZGDK zizsWiVyq$7RgAK>Cps@32H3uWMm>GpJ!}tE4Kb30Wfw`ZX62Hy9GEgr?`ptX(?~%y7)>4X8TWb`AkY(A^#Y4E?<50h4*OT5>KVJ_Xs%o*f!X z7??oxQxYrf81$8x(L)Y^RVKbDTbVryk+y(Bb@WgPg@zGaKwFv-4?ZeQ@R99tN(sr} zVQNAX#q7tse8p_x6R>oFx|m3KaAeZ!Gjr}il1lStY%T-ou)n9232YcRPCP~oQziig+WIAChPeN0k$o7=iD05 zTS*8c)=FUD(w8u0%9l_r*8=2%7{wZMFH24;-7HVE9C?aasHO~1(1nGBzQAO~x(A2i zw;M$g#{jBtjGTZlMotX*Ti~5EPFR}Ouyiv{t~%vkK>bPPVTnOfi}W$kY`#u3AtGmV zy3t)PICQKGCh?Y4j%%c@s%JnOhG+U=wWN_P7sjyegH?BINa-v*32irwx)c%XB=;SB z9nYEy&$~+2uOBPya~#;!x=O>nX)h!m_va+0)+OQbhea-KlA@>|+|c{_Lm!zJI{ODV z>N)u9;gWEx>}(cd#&+@vE;9?Pp5eHL%ieCprAilD>@_2IWl z!kbWbn*x6JX8H-d*qoQ<#fHFY>Ar%8&rPk+CdJU!6z4(*SSLUrH1PB@i+jlQXJ8r= zsXh^p^GA0|esqTyL^p#q3D14xGHE~0!~8@_^NIBFOeeD?dt9M0+w5g3A3CUJSy7iA zFL(k;!^qAr(&tK}RMtD94JcJkli{N|yIo97D(lWRCNKUH%>gave3VKs3b#XPjOBb# zU#cAppu^KB*4dBb37Jb_COcE=COc@SIF8imPQ58qtS?akJE%hw*GBcn^d$GJ zpWIg9DZ6QoLbj+*)Vyl2NDqlRfD~*=*bND^X0^a*&0y9qSjAlObzrc6ArUR?g?*1c({W;49wW&Vsq#JWSFn!5!Q3SBLW zKD$e*{t)XPVq-C!l!j^+38*x5^-c0}XsBi(UdI23pHR&M_{~Ti-m1GdB1`0vi`*hHt?PMHh{Se@7c@oatB{7#>+y!{0=Wq@`W2Wp5hBPZamEwZrpg5 zFWk5xFWk8CGF`ZF<88ihd zFJxp9U&zQ3yc9CBS&oqfYn#y_NVHy!CANu0wfwEG!EYqt%)tXI{$|O;nMp^p;%^3C z{WYWvg2o%*3dtj~I02DF92O8k%p)ixa2OskZsx&8eH`PjY)WFP)eSB#n3chh7X2_s zN54?bCp5%3jL&?%BWBq^lGU^LMIC+?FEL3Dj^Q&eMWOg3a81T*5psMHDz~Z=^jqk^=saP`Q1ZUqudm(AfB#fT@F6WfJ6p$Id z?{n}y&G&sGzAJs-N8mf+`#unh(wJl?-hqcKcijix%gY#*Yp7@31$$r+5yJ{BORSXv zA*Ab|B@0@ag++J^)zsj3rFa$_OyB6RnD_^(wo1kcge5u~XZwO!6TZ+pc7km;OFH>& zz(b-KnT}H>u<0PQye$#0!#j{S7-SoA*d6`tj%M_UB)iU>XsMTyz$2?y*CD}h@_ZHb5_yQkkL5L(=U@I@WSVA<`%O`=5| zW5cU1iM6mQFKmk^&}7IPPKvFahJiJ7(a>7MG%)uaOiF|oVuY*FZ*62=F5D1_anm6kYaNa-um!uOTN)?W(V?(Mw9Iw>?9n8j6q{P z+#=&m%m2VQkt4-7Kp1G;4w8LPna}9_zf5!)d2tinXcFCp7`h_k1A!o~V3p_mL45WL zR1L`<#JBzd>@31_07mw+BPkq7=&pQ|gfht;l29hOg9()+ixBIO){b0SFSlvk{(6(v z0g_gfei3*4}b+o&ynY{^n3Ee zhP)>Nb1+ff5}1RD@@0WJm|1TNTxyq8Z^KHF-J@`W8By5@mZ+(9Y3S_SZ&AS?W@zUwlbIs+E7vBSn6}EL9M?jm}?I|#FAi2 z1d9MP^vW6xr_FsNP}RRZ{BR(9U}*8wN0M__MI7D;0n-cEgv5955^{_&qUni2X-Npi z@bFq2ez^L#4;NL>eK=5ssSlXdvEe%ITwob1{|uG2SFK-%ipUleL@onBgVDrb%((IQ zVKY;65?Pp(46nlAB~;DufR5Nh?1+UED|5V@im)hLnTEjzPDbq%=WbHwxGid01Vn4XLz&Azx&goaBiC;f$lbw!`GkZ`#;!V3(c$W#=d?9p6ht#s;+$ctUrw ze=NMJh+Eb~6xm7xMB?FxPAx-KvIcRp{#+!zXRvKzVT@0*K!MGBR-l_7ZVO#|mej5s zJsMgy*IVOSO!jPw9)e|w&0Q6k=Pi+;tP8XF+Xl(vh?m7U0$R+bY`DSDSO9fsqW%Z8 z6$>ilRD1}$M64-U0&8C@T-RirVUrTpH;HVP#wOz=*`q+av-T2{Q~3$AcrYc)YHbW< z1u^7J7)hLkro*9YkI3@tO=O^n)i+@z!IIUDh!~tyl88;!|2$5qt~p6%<1{sPeA@p> zoW(-5x&by(CdTadYP5uq&Kdugajq_iv)jZu^Zz7HE6X{ou6?rY77aHmIREGQX=Pc0 z@oB$oE0Au;b`H~tQB^zw(F^|1v}trfikp#Qw*`_g`$Ycd3Ae%?SrB!T5q52F89dDs zKtWxB* z?ago;dPC12iCXC5H=v5Ob94DBN?cucOd_59uhR_q~F3tW*l^ z@hw3BqoD3KiBx(B+r@U%NMa%?K(qdXgZOAg#W^^bWyuhcI_2w=z6R4`^ypjq0g)NL zr7&bcSwHAc9%%g*e$d-~(0K&yOiFJ7lz!w-V5;Y`$*Y#4xF$G|VIz9kPh%u$a3(Kv zy@`mq$~KB=ca*?q`HuKu&Ar)GOtm574P90J-a6$iw>c4xE+w=WBWuY+Dn0!=q2T!> z>!rlG^Gb|Ong|Jj+0rvaO_OaCnm@9;ZHg9yX(Vf0tZ20=YV}3m`d@#*0u~A)DGILvQR?qo z5OG6Li_p@du;25XnYnv+vq?LM-}h~MbMKuwb7tnunKNh3oSEAMZZqM~Sx?`Scm-vf zs*32cpV)v$u;1dChyAX=i?E;KkMU=E>g9|>h9d|k`gYTy(YoA&peXouyAaEhT= z`S1YiCZF)-i|BSfl|Z zK_s>ydrSS|C$T`H(0gd0dWv3@YCzwC-pXZYU5`JiT$H6{oLlb>xcNe)tYPsZbf#;P zCrl;xcJV2D>vXWI7Jb>h6NGou`0-7W)VuRj$LHN^DD~2r|4quQZ(3?*eJiXo+bex} zguBzxk~DWGA%6chUutICsw^@qQxqs^I9d`tD&Dk5=}lV(zuJtMbx%pnth+=q6L-h5 z{^b*Zk1bo${{=R68P@0IO;0Yu7f&vU(jpr@3#QlyN}|6hi~hDO`s;Wd#z9(%)EuJ# zteZX_=D>sG&2KItbbt2>^k%QVcz}$k&OrdHP9v*EPQ&_zJh5Ntz%Yj`kCx#eC;bT6yS=b0V9)-KQD99P1r90->|}-X z4zu*iN}Q67-|u!SE1_;>&-7N{c~n4Ec7<%HH#^ZLFcU~BFYJboOJxmh?-S(&V`2$4 zjW@m5YBuOgBf{laut!(Z;RdUo&FMFY$iTx8kX@WO<>-lH~FYfHETop#iyP0ol1jFq@`(#OXMdHY(3oWlDpSgmPd{V&wMfxhP`eSP zy42QNK~=Fb{R2Z_W(=i*LH5!r5ACfCF#Fp7j&)LRndHO?$@$FmbSu2+ex%ZELpec# zXF!4YIX8n7qCfGrCivqADkMh!&69NM1oWdkk7Vhl0`q@b~Ft! zfq=2Ozx%MKWp75C?WsooLw|>~PB#DJUZ7K1S`U|@Fz2FN_dyN`6W`R!p0+(Tn{RtD z4D@?g&uv9#`L_=boP5tK}R{|grEw>*M35rN4aszfS?@;zfJarzan_s6Qkw_Tw}Oz1_=d- zziml@K-w4nqS9V`qr^zd!ZyVL7W1U7+n7*wWmgUo9%Z$3XYbE*Sl1%4$7ZgKlr!#i0E9i0_QAPNZ_1B zhbx%k(I6Zry7zLr4RO;=`2JW`vR#E?wcNPvLu_KT+gNXh4r6q3Yk`iwn<>pm zb~&-3wMr?TQrji_LmqZ`M-=UH5rBt!!Q0yO+plaWnk`kAnQKLA)Bg3e_9@=tX`e~AnD+UAhcvOd@ACp}@0Bq}#1*)! z3%P-3r7ve*9-zgZUO(_A0S!p_Z=go;+bBeU;2ug!z5RYbw#gy(1W-0nyH(CdiZc7< zwh(<)Z?-eLX7@0{^omv@N4CFA5o?fP+XbvYrl7@f^L-dmhSz|!hUoafByeecS$c4! zFn&%bBdN#lN+b1|AM}v=E1;rUVy3(;0oH+q^xVt5UH2`Rh`_UO3aac`^NF*OqB6B9 ziOMk(%A}CC=A#V?=~Gd6)kYXgR&CY@1@%&bSUj5$5-%Yy^~<4S#*=q0*e=>zjM$#N z{0k?=ZLsipp!&BnT#@Q2&|0kt^~j+k<6uWn=c%C5l$fIR4SgNMf&w_%3jk4}0s35k zQ@sE#*@o70U>T5)TOtu;@11cJLa^U+0Ry71fDv9Q`DQYECXO$=L3pqOz=)9>&hg8k zy(ZdQmJF5C{M4FK&t8U~mEBtm3^(tk%>D?#!;{tX*`P*t?=-{>hyn=F>7@=i@I@*Q z?&3lh5MT)Su7YEmB!@@hD;@pAU;*v&so?Gn1j>93!On0=bV|v+&Fh*Q>cc@_Np!`8 zl6yA>J0$>blS}RmH@CO>*3~!TZOXtxUrVsj8D6gm8o5jn@LCWsa)~0|S`tNDuT=AR z_ildv4$LX0DM$`uqeI>RNTr}(gu@D188ct&{VLxKl}qpfheO%R_J-+Bic0f%mL~Q4 zPL|SL(NQ^=Jh6M}jkoogZsIkp&yHa>zQW%q0m!wFyx=*zEp{iRo9ZK&LMHo2+y}{w z75m;A#P{swUniWSI%rnpJdk-Cg8C);o+?TCKVa)0T=p6UVcCleO#yy>^2p7#B>)G& zMPFeri%B{9w|65D6G5_MX%wsadMZZ235b;BOtb_XvWhQ~f-2h0JDVHXJ zR}GnBb~f+e%B;r;Rpghe2UyCH5tiAoY4Qd(UVmShuv!Gy0&C7 z_x>R*tJwA{rKGVHyeU;G3j(LVm*KF%20;zR^(#P~V{GnjZ+7P+JC&m6=mgP`eobypd!=mYBi};uJ$eh{`)?p``geOAUq}rm&P8IL>cq9U zR4>z)pnz*1^_yQfDByeNp|zrS&S9HHw@<^(OL3`aFGGpA@AG864`mGnkkvqM8G?bs z8JdpQ{_T7vzu=~7_-TMcc5t7Q(szL3BsFNtP7||FO?Dq3B>|bumR43?wzxoE=&eUh zh`gs;iY#i@FX&X#f2X8T+dz_(Ad)5^0aIV>!TYQ0iI=@ovR8%lb+8$>S21rBp&P@T zCG>~Q05My?=DANeIViTBrR!JJQ@d_;^W5JqqC;gg5TA%H)*}RigO5wkd7tA}9?~uQ z<3DCUPiwB?h-ofv$DRTzLvxE0FnZ@f+`KKN4zyt?mnA{Ig{nsCro_`7)XAVzF$N+T zH`kBqBVvVCQJ|g=C5!fs2SopN{zajguOeAx8#SB>2v%Qq$9eUb5aD%bA+W^rq=|9< zZ@c6slOX~tRIy$(vk#u~;^t4vch0kd_Mj;p8Ky>QoHGU>0| zJ(d1cBYQDn>897so$P%1(2tJ8UALnjqkMgk{N@c~(V!gYbaTO5PS*zB zt+W$zCNs|j^=}vP7>g08Bqsev>k`K{ph!5vk`c5qa!;Lkr-!5NCbDq;7+H4g{&SB= z7M^p!QE`kKezr~M8UK>9o3MeBa@*}W8-Q*ELwPD7okDzOWdz%@oC&e4@P z(j<&AN<%#eHF!iNu9NPVR<>OY$1Ph#bZRI_{n+|2R@wSm6oFTbS+;j)D%(_&2#$~B zd#!)Snt+U|vAG2bvzn|P?8F&Dk1C_1BmhGdf(fI&rz3g4{Ovhc6SQFiYwsi}UxMp$PL8i$<|CI;zvX43?Rk~kYicSyW8Gar|PvAOqc@W`RliEiu; zIb8-}ez^n6<5;w8Qi$VctRJhLe~TtH?JUy74A-)u9_3cU<0IIT^KK%HO`59levQZ8 z_s3Z6(bF8gUef%PH&h-Cml!GrQGwVHeus>kaN#!6OmtOH(no@7Pw2O?SHvVU26+wP zO_Uz}F+z`Cj!spMR$Y$gc^H0wY}%M)tkR54ql3*t zqsMszjVh34$VZhhNuxVt$cC%V8#Zkdu#+N%q%_qAVePMVK$~bDQbY(kfJxJ4EP^i z#UWVEq|ke%o>l?7oydfK|D!`s@Kt8&1M$h%aV?txXn{}G)37keZBdv7-^$Qf)~#jy za2)npVb{_V>hn|Fedaj+q5d6;7EID$SMy>pw~w)f!{-QU-{75B6m=RogH1PXOng`n|>aWWA z$Oe>?*8ZWV6c9Q!o2FmD1EjUk3RH{DeTD(9|4Xx& z_1ub~GB1i=96JbC-Fx6A0a&rVO#K?|19z~Bd->PF=ObYG2b8$W+@7AzZQgA9MrL!p za08oBQBmd{5oz-6yMW(~NVAhIqHw@T0s<1#kbLv9#D$W%CiQ75b7qr4DgOtx3{TU7 z0w0%YM_SQ-yMo*}X3_pz6qe%@?Xzn=T+q=Z`7eenH7^_t2kTnvB1j6$Af zV%HsFT+$svhbwmo6^_oc#wAr162}OHkR7}!Hu?T{$tF7y09Qi%b#UliDs`inlA9py zAJH!fh8}}a$i(z>7dXD>wv1FC!Hl2!uQX;1U)sHw-OmZrfGy>T&0SLOA@vH7S_v=d zb?Yeiutq?KbT>hPH^GzZq-_*&OGM2dCud=*kT=jTxpPHPta~133-tZ?Bt!uBv6={4 z)G1zW(m_d)@TRmhwu^VGtRv?QeFHKvnKKW~V3D?dG8vrAot^`4xZ*U-=!)yy>2$+y z4Czpl_x62U_lLG+%9Sht-L>Cv0chUv6hQocy;*bXDGpH38JNZ%HA^*4ju66!(*3B% z%u+j;T}b5s?mFy3aMvLZXZJ1z7sTV$iuVzeGXCAd&gL2a_LY0s{D$BNfj&jXF*SJU z4yQ)Q>mc3Z)s$=KX{#uDQ_B%q7jMj5hRXCZG|1WGL+#r%4?C7dh^?w zz0BLz(z*JD$T%-O`7x&WU!jtL^*_$(ffgj$Tl=ZKoG?!)SvZ0xMx0x!c_MSsJj3)o z*LsHO&o>A~g-Os>-$8LvGViE;DXknj$TV_*>P468%}nYU{SZT4Bwnm^u|dRw`*;KQ zJ%h;qPpI&FEYG^i%J#J>RFL@%&X#7`QI%O#C{l@Xz9%S!C=JT9P!W(LnZ_bY$Yk_L z%EAAS$ne@K4;gN)Pa(sXWeV?-;gYo@$nXwNPzo97Jb}7z0|ozYbv_S=ukcoCU0q70 z9(}*m!nAE|3d2ukbN_Y~AaH;;TR*)D)Xi0;-oPkLUkFhkl8!LyRXf5+j&Ov*apBTk z-@Xo~;(3&=Y%lU{i2M(e#^b@8LK@eD7cG%t zzBdRD)Uox{rxgo|jL^MC>!~@=Pg19Qihv?i4d)p~7*&Zl(E($JaCr9~4AwH1>G$0- zHS6UBNNd`WRUoxYh+s{Ce~_80C@EJ$DJN-_qW)FcT(UEn+^adaF88$X`Kl2W8l{&1 z6ebd&^U?;deLx0JJ;+w4|FDdw<4N^`1CjjuQo3DlHwqvpTQl74c9E9U{Fc74 z{GbDS^20PMauzqZOPD+L!l&xNab}OdI0zea&_2L|b_4MlY)<*y4!5ttgk%~5pU+4; zmgry&S|RmVq9!!KE;PZ;XzlIM{qTR;*5}`m))xK#+eZ-3ZG@ew5eAX-&i+~ey5E(+ zH<}SRs7?xp`H+cSd{U@(vI*s0AI5&#B_ zakU=iym=MuDCdDX@&P(#Eo*fERBV3oy`&2cPTJ>$CxEW9$S?$7Fy@?=T}Wl840vvK zpY)oS-s)yY&H@S+o`()%hM}KvVCMkJlYEb4fq%7=6b?#qBgUmh?C;*P!$DIctus6x zPzU>KAEGl*^nv?eqE5uGTa52<_#f@r@~E?Udi)#E%;jJjk|c;jbif75wA8jz`wS03 zPUGY3k2;Yn1h=NX_L7~iX@KOr;oajVpULDx(Q^PXlA>SzrAyJsC4zT`Tcwl2>_CPl zr@PN5)5^MUXup>(@CDv1{vQTDduy}z{p9SeE4}aIBNvY>%pRP!XPOse-Z$Lj=9v}o z^LfAlm$5YrU&gLpge_;!Q3H&gg?{9TC`QC9B#Vk5r^2`;EGzAaKE>7%GN<>dk6t6a zD*5?sk5^l?_ECP{A+1A!Q}^{FMxXiwSChMuHya|}h|}uRGnlS2Fn(+1175HyM+T8W z8uEwze}a9Z{7-2au=vd2WMlw;xt=Z0I$_Z5S#y3!ny9$5N-AaYgs)saB*lSf$--;#{pc?Wqgsy>4n6<1cAq1uN)F9nn<)-GXJ zj*zmmpubnrjz$)>`#>D(_e(KI<`fE>mn=0gy{`k(q$$G;NjKBm`a`Bsfu4?}f0X=*9*UA3)P9dx(6~mQvd;x|G zwf91O)ez2~A9@?a-j*p??#bTzI=E`+9Y~Iog~R6$O;U(Rqygs|a@@c^O0b~-BH}NW zD|g`^BRW2Q5hc9(@YxA`f9I)yc29DieJNWxy|NlDuF=C`Wkhgxd4LCOUt_qJ_d`FGwvZ_|HX-d}$yI!35 z{K8~K^oQKAH2{a!@QCEzuagKWSoQ`i=te+x?`;wsWBZN5EYwbT(ykgl=>dEkVD=6L zJWtp6zAom1%6^6hzVs@-Qd3oz*GsMyLP(mPgwi2e9bb zBG8mP5ULv#s&lVFCs49PeKv}nJDZ*RGFm~XCJg)e5w3+eESLBqv}3b$uJhL7!`S2T zHUJLscyh#cAvU$^{|oIEfBRL*PNECf#f{_#q?lVDC(IM2N<2u@o`6Vrs1u}Ht%VrA zS|uNV&59&t0}&Y}MlYEE79|^YBN(rHZve3~%7)ElMm9)M+>RqH0WEZ?M>hPkQdnPA zdmgHxCEoCaZJ-8QA)QB8qnhARGNsF->hM@7e35ij;bH$XI5_fYC*COX5*qQ%TMi`Z zwmF;5fEVC_3(lN8`C}28Z_2~48Y@ZM zQ~AO}718~#JpaI}Cr9@`aP)%d4@L(!?0e_*2cr9X_O0#nKMjmG4rc?pXWyDW|H0w$ z%tE6)U0fyw`&rp{9o3=d^&HIRnak??3~=0mS3&X&kYn%>8ZHIZVrRd=o6%R-lnB$N zb>aesCTA&H^@xKwz*&31+fV7T-h;0xhTnm500N)K3dxR%cdGpf#qrPLU9HUOEeo@x z#DJWK5AQ`GiTnpuX9!%)_5PQ8w!F-bnxZ8+?Sf22#Zy&=&n-!+44#HFCmnmsCk_fS zk&VAx#2#RL1Wpk<{P42)0`Qs$M8v3a%x8!kPsy`M87!-?XDviL95gUfWCr{8xQc*8+QB#|3@=QX#_(8rCnR^~UF1RRYK^GE3shK!8l+8G_ zPec>6{cdBLDFYN<(`^JhM+o;+8vzC(|1Q`9QuYsH2~PquZ61#Qx{ccQp7@pRy#F}< z6}j(=Pw3$LLp;wnyYDQNk7xR3_f3?ieR$$dI-c{H-FHMz1cYJGk(CNC7#On&v zV$#)yk10D{O{V<#R-pL)sfIp>Bap6HfBBQ1m;^OVQSoI1Kei= zyxImh&j$D;8{jA3XF-kswgJA;2Dsb?*k=R$5>)OJZtjO|fIn*k++qX#J{#b-+5rD~ zfdw`8*Z}w20KeY`c$N+DcpKoSuC$=WH*A2n*Z^1A0AFMSd}O{w1s|~izTF16-3EA( z4e;4E!0`eLYTRoBe5(y`y$$dj8{kuHfPZ_11vS2H1Ke!`9Iyd?w+-;Ic@`CX)CTxV zHo%=Wz0Dr{>IAQ}_Vgr1x4e;OQSWx2u8{kjb0I#ui5~2*#IxK0Y2Xb_{CWk)Og4S_%k-Z*V_OuumPTI1N^6a3u@eD z101yhzSahKrVa2o8{l8fw4lZ=8{iMv09V)mPqhJlInSbk12({)vjJ|k0bXbW{5Bil z=W;EmakmZd$83P>Y=CFm0B6|%ADCf5jc?ij-(&-PjScX{Ho&jE*P?LhZ?*xhu>pRM4e+beEGqbz z4e(AI;E)aQVjJLdTwpF9PorNVoC5~E3x9OW`QJVwu?FCc{?g=c-@N)5v4)bHJ638ru7pY98+$a^+ zF|T;g_!i^5cNWORvBY>aCH_9h3csIE?Mq*4{rbC8iV2$g=nO!I3@^=HXN;*R&_O4R zL-V=rOTP@+UG*T)2>#)B0wAtxgRjh{tre#_TjU~(|p2#0(&|p0JV9zr=|LdT7MFPS+3-S{=1NX(p zr2yewL(xe}6{%{4D$2qYniOZiFNphHKc56yqe0eakYSv8ND$@0#fnvNIX8|bZPFn7 zH3+=oO-7^vL9kIuXwD;uiDh;YWQqm>{|m@;4U(M%@o5myTR`5TL0%9Zma9o?CRSPx9LJhLxXaAz7Fc?qDQKF+u zbo6EwO$Tt2tV2h4=;&1{njL}BRXVy#N6%N$V{+u@FESiCru31n#pW0+5lMlLru&_e zDfpyuk^u*!kM}%{4;@x@^*rOw++7>t9PD7A2losP{%i@>$7ow~nokqe?Y z&V}g(c{SWW)8J0_;`(V4?iCjfth0icARoc2a-i#{UKNij?Mt(suB1}8g=;h*I932R zqyS!(1Z>iP;9CJ)lmd8m5>R}@FN3sx-zi2~gKX84m852|q(-U;z8##=)RnS4xJ>4&Zp54 z)}Wh{MCbFMn`Y2er=UZJN}^*gV`T|z(EVBUQ&x7G2VK5FcXA54d@s6ujgGJe-KUf2 z@;&J08FW9)^3o0+HCeiO8XaK`x+O_;^E~Jl8g#)Fbm-JcbPF{)!Wwi(fkT1^7B2Ll zD>3Nao`McSAc>BWfwUv6LHG3}x)Kk%Dx$j-j509ZTiGfvx+;y1u#vY3-wj`Yw`;Nlh?wrK}(X?MKq;&7@t&umq=@PdrPaQYA&%X;x-Q;WE# z_h4Kw-6NLuKPe!lM+k^w`B>IBQ$P%t3y6kq3dkBS$QljOkpj}>1!>YCs((B_5nb=G5uMFdH#If80oX`%KGWl90$9J^~iVD!&yH-00y3{M=u~<7y3kErl7p- zI4C<6N^Eq@xUw@a!w|MP^*vv+{3|C8ZfA=n?MMuA~WPtYpmytv-(;(E)rjGnT$oNK7->I7*!rDUH_`GHIun^JaqWcOYr5_ELXlrN?9 za$W)gzx#YN`ohUQ2PZ?KOjO@WeHE35xA3TWy5C2kDl{rsY@6D46;XKhm*5P3d^Zw> z#up?@PQuA2+@-?lPZWN?I43)L^#mE7F;r)&ZOY!Tdnjz&O`l($#3@tOs&|p&)GW)5 z>y@}MN;yxBvIk3|6&ZYoqjl5Fv<^qsqK9cdL|#Z4_xoCOw0DZimzadh1?Y4 znb-T!bkC+!@GDby4mqi~v(4|%pE3Mtv@EIW%G z$3D*#QhwPb<^GIrwx$+}lv$^rD@1BS#j)oSxkjKAU<-wz622EF^d1`-NizH%lxZIh zjRr5AmwgxZtSRVW!`wE2=N;_G@O75> zNfOrIoewcL%-!ufL64oJ54@j~82Y={5I`{Wck@doYV-LveDRz=CQN#5bI1N0@M-6c z{as$K?eN8NIsn65r)}8|z6*uyn1pOa7^5`K(0f=bq}R>K=AGercbk_RSzMqj;RN{j z^Y{k@XLS)Nef|gh`&h4`9|5^au}v}rgO)V!qX1Oi><1BvOHFUGhI$k@LLg<>zhq*5 z+dZ68XKxLv*qx})7tkO*2YD(1TYwlQu*f*l!k-eIy_GHF0mTAb9#;@!tYCu&EEP`l}1BkZ{;`T3Dv)?N#}{QH2&P~0_M;6 z|2Vt%WBMJV3hT`x?MDU0^d%J7cDEQ6)-!(?_|(Kk75L`A$`>HHV`M)Q;Je)ND3f}G z5aGd+Xw@{it6^&!r~Exz`kXM1lp*!1e7N@^6pZiC{N>+AENtk7JO*n%gXAVQf|LQ9j0|ft>{H>nUOv^dIRxbbyt7--&I41~5nqa#2tscRYZ$@CRe4w^B z;Eyx$usS2P-!OMPg}D!*?6^?p`TjwCmzHlR`BR`HzU$cIkCVnQAQ&3QH+>HQDSGGs zoM}qKuWt0QO3^JlAi}nZ2psEG#nLxH1F~6B7?C|x)bl($YFF; zoU}1z_ckOeY?2A@?k4Y^3sq?NU85sWZH@M>?S{;m0zf=(CyV0Mhu8f|A^{mBQY`Da zmkbL4PIuo})}S{u*=LCsO*vU%#n+0IrE+(F?H$poIY}1xjJ9Y@`EFQ$?e6HJd?eh) zb`u6wXrdxFdYlY2 z;6DViIKx^$HJ$a4r$3|HJbM(3)8jwH{zxRcV;$P`2>9ihL#7WP>NY7ua*z@c${bMN zr_Yf3k}+hw(@-f@{laPKRn5pWD219AV_PiBbV$w$IyoZSl>4_G1tm#wSr)`;&C^_v zaT!2Fo@GA0B->k>d<AY z60^8`ExOvr|7yD0!TU%}RaW)^+Uu~=%k$ZXDH72YIo52Go~m9C;Z;v!ppkZSu0z(> zt&&>bx1U%!v(7k87%v|zb5QkZ(-^7D{O~F1^&UyT2PX=yc^=u2TBw^{Brca^vI1sp zR)|ohC&?hA@W-XVh8@lx{$K|`Frr*g9kaHbMOtf7<8Ur_GblIU=Yp*>ypZCBQ@H-x z7uX#hcm{^ML7Dvw#9PK8n~d>l>fGahfl~DlK6T-L;X`+#k#8F|jSQqo?coqc?Fr0} z(C)N5MP#gbi-*cmn>6|;LvOM|;1bSK2jZ_nr$^Q^Ro4BrICJWW`QIKDseV_j#!55#Xxyu?!; zC}aANElj0@m{5&F5cb?>RXuMgH)zVOPPl`~R=!;DypRuB>yyFMr*)T{;<0PbKzV^3 zM{LMM^gv1M^l``uxk2~h`sy#@Ly*kg0vO1X2GyKmpW=l(Qh7l{mCT0!@OR2X%vnx1k>Y{d6BG=o>p-QKuu+KTSW`P z6%XRur{u(86i$LmXe$yAoO0k6pQM~`{)@N{VA7*vfnG6%oWwx;8aUU?0RYymz)}aU z&rxC|KcmWKYJz0ig^^+>`%OC8%w$l1gawN)&d>*x2DA&SHm&1@yW=mZHrx-c+s}_j z3LHN^s)&tFHyvk3pemS`@!SmR(VXU1u}Zr%c_u=ikc97K!XEz~N`gJWKmcTRuFmWu zDl>FWx=!gd&k4)I%YgVyX6Rs9JDxM_4^(LJ>G%fm&)_0)lIg{|tLR?*MK%KsMkZr6 z+(h}zi#KFa_#(jUla3taw_!o}lh{3&3Cg=4$@<2z5){CDFlRl``3*@Skg79NR`3&b zXi3$^7nSi;kRPJd&;Qw!8gcBj1O9_3nbVKhw4N}4KI=J6gSHS+6QXSStW zsJ>kso7;_VJhFE@e&i+EDSH=)*&=JUEDCpvo&iIvK`@C3Vp-2VE49Dhha!mS0~7Ww zyV=$vY5yW~)U3bBGOWUZIV?Uh%evun(=6WIDs9x?-Ls`z4iW7h`YzMO%D3St9#G!D z`#!?3aGjN;dpC0KR5_zPcN@Cz1`v*OF-WeL%!xpM_;&8sPV$KOn(?&fyI(^qI0m86 z1B0Qm>YV1H-(%QsAF8H}GKc?U8Xe=2YV;k$8(T~qFUNIQKqJ@0=7#Oe^NNb47pav|4 zRytiV28%R&If{(~V9r+<=ktbaZ-drHq|=JCzy2l?MdO)Ut228$Wf})*kq3sA9#m3lP%XC*2@CcWkO~u*tfAF9nt_K8 zNofzD66&ZGJ=GqFhYa`(5lJ|mCA)7bA90YE<4ndOZ9G2>=`gh7G~czatFc#q&RzJ5lPL4i2dK8Nuk+B(ppJPJU_{xTVzp!idB#bY%_QAyDdL zTtFY02@8_qdI}Q#@md)#c0x*~wb}J@&gwzrvQrNo>y-IPvgeL*X>@DPmaR^B z-0(ca;B!`zAGt$5i>mVT<~2v!}rq}@t?rbYV${mujo4tNy;?>7V zyc&sRDc=WKw|!rF-sg>#Jfm~M^XN!pls0uDwATxqKe|O>k2FKt$!Oi)#6BkW>H<*i z_du#rQgBw_x~5$1P32|@O(K1+BW?{~Af|Q?a6R3dI#Zrt2qtjPCi)%3sY{L%N$`yk z2}T}+rpb|7u^YSz)7d0riuZX_NZB$>zcm?B^U4~LGM)4o7QxP`seS>$Jti$Omh!XS zR3}ug^<$+_-b=qh`5;xb0}_@>va0_n{V#*((G(Y*J4XPWGMt61P~T)wWAtl-BN z74nw7wU4M{S>It;w08m_Vp&b(*r@)ls7e;i3IXKdtgZM9rFc95*-k^JB7MKS;()%` zSzOvCzBcCAe->u+S@R{k2QdWn^`4Am8K4&m^msro%rA*;_W|m@{X`^VCCxye$6NPa zCU?U4YTwyyuYgBR!NYnycp@gP&=Hd=@PLB+iZs7MD#nCa1v)+}kMaF`rvN3iWvTdd zeCP4?vRE(kN0fv`&$_rg`T$Ngmm^lsehsG>iY&pWKf!eP`nsU*5endAp`=R+A%e23 zjH*%L|D{acw`(dFuxQiOTrle}UwZbkZE0U58HYol-XB!?8NO*Tv>HCBxni%dLu~F# z(zpZhesbqX0BtN$347uvaaGPF-J_H4WL^5RZeU(%Gpfi-h)VgAsb>51K@BX}d<5xZ zSr`5cH*D6KD5Ln$ndC4Y<|j)d=)_rtfRh>y9cClst}GBmc}bBK-qibadk z_JzwBV6(S=8XyDyXYtn=ZlRx&m-$|l1zoa}cy1ihE*qg8;v8{BI{1SIJeu|2e2isv zJ%yWg79b0%=2+U}fA*yG#Jwgl+ZSiF3LP01&03|9y*CrG^wIx}f0+JG@YxZo7Xi%Y&z>L|O$O=z_OcZGzxU$?(ielMzeA81JK>-sW*CZ~hY6?10`y`fyY@3A zOX}{Wq3;WQUnYHry78yq|8fe6ZxuY_$Egf1QyDBvhicMLw9`R=n;f72v^2zf(!sAV z;81&SgXf_l`z1a8mqGT_{Le6;Bzqmmt~JI~ooWvzGp<^YKEQ*9Df(2u4ehBg6{Duwi78~Fy8{mst<=3l`M)wheH%4RF8)_}w02kN*PqG0%_?!hbeqaOq5gXu@Ho!A%fD?bVsNfSez+bfi z?y>=1Y6E<}4e*Q4T2SL58{p5_0AFtdyub!{vJLQ`{$xRoyKI1?Ho(`~0ME1m9%lpm zt7j~zvC9Vd12(`FHo#MDfM0&vqJjf9z@M`LZnXhkXaoE<8{p>-T2SL|8{m)G0N2?7 z&$a>1vH?EuzZTT^rVa2-Ho(`|0AFka{K_9KD)=)S;4jz!ch~?I*#N)Y26*TX7S#B$ z4e-ZpfY;gp&$R)bU<3TS-&;`QJ2t>K+W^i1CZGeCMgatLeZUg*58{kSC;0tYl4?k{E!TmPCpSJ;SvjHx&0Y1wH_%DMN)VRk6 zIA#O9#s>IO8{oIt0RQF}7S#Bb4e*C-fU9kQb8LW*{*Ofke{KW(MH}E7Y=DbxfZt&Q z{QP4U)YxkSyv+und;948tX*R(B{JBL1|HlUS%QnDa z8{j22!0)sH{_D>ysIkum_>(rk>ui9pumL{Z2Kav;v7pBHZGd}ifLGW6zt;x%_5BtV zeB1{34jbT2Ho#Zg0Kdxy_|Sj_HGX0P{AnBDW*guuZGf|FfS-BTf*N<)0QU*-y6g*z z;eZ_d2fV@Whx4*C)B)DTyLp{@|4RwDG`}zbn+_)Y1OS&O|CO;Qu!M0#$eK^?YTf5oU(!7=_r~3Sj&0$}C*teN^v~Ozj zbvB1KAXlR= z-0lm7>pR0bNyb~@qM~B|;w2@eS1&Cquc)lLraDklyKMQ2m8&8y@sMr@>^A z)6z)tIYsSlZNY|cb9l%HU(5Y}WMO6Y=T3mKwa1}Mn%2E&(wMSYS+ujrQt!-|TmTGPb z2Rql*Hw1m}$qBv3DQj=2Z}FA7f#`&&QF8}-V?^r1W(RAdv0Iy4Hv4j#rAifGRKbu8 z_W`WEWusyUB2PwvY-z=i%z+7f6>4wTK)wfGX@=U=9B%RjJ3HIjK^C&GE+&~DuT2rh zS){AeBITD}fpCprhA-T?nQhS)>Azy>yMPIm?LZcOZ z98Et}ahw|m5{7(=K88F(Q3dAZXQFA3K)#tQe61lT$&Z;adVvM6w6w3SJ?smC(aFFS zmBs$D!j&r5P<clAG^VO(!6d{(Em*+U8t*ybvW(a1t_H0?-x^{{;T>!U-vPQY6 zlGD6ys?!AdI@M`z47P=v!<(Hp)j4b1I)e@E>)V=d1mB{HVMP0aZ4K>>(wETyc}D#E zB5e@pkaTU0GDf9Chalmb(0)OROe3(2^f#>C(B8hGIat@+hJi#C+7T9J>71N7`B%(c z{r>rrCN8+nw;=g;o#Rk|hjbx{!PnT?-q8_koFPNT%#G;8IX6ap@0Gu6H;02Er>-s# z#IP02#Zw8;=Q<&IcQ_ihx3z3`I_kqsPGfs(eRG>rpcq0103n6sB0X^}M12@kZmkbD zH2D;~kXp*r-sZH{cjeZv4?4lFj%Ek}=b{qiP>CGsoKu~e>RP|ExUekXcbw{AM+-zx zqZ*``BbZZ>1kJaAV~|iq<$<6XK9*4)6mqgY(|v3E%Zc%yemRkctLif^C%%L0d0cnw zcsU_Wn+vrf5De!Q3Bd~--LafJWXXT0CjYlIsu#p$&?hP&p&IJZ5ld=ns(cEaZ!rcw z=nNV43I^t?N`>A8<$`L?L}z(nbwz2#k^;j=9CPc@;dMUfPau-&VkFOqpU?cJ@n>F= z_rA%gzwz!*hZoB4qzpd=ut_i#OjE4%1$Viv9du5aPGbMfKC{NlrjkK+0Sp3QZ>A7Qxoeig3b(xMt?W_e*v zQAq*rxE7aI6c>PS?HeK;zD@0&jU3Qho1vVxt#_bl)kj*w&Q$aR`4yFw`YUQ&5qEjs zyxDpAxyAlvlO_sMaFzN$Y2r1tr8Sc#nh_xsY!ea50$}97Ap(WRnF$@Qw8D>4pa?U| zDl3=PRw=EZSUOdR2LW46#80%ZR;Tg%j;Vpjv?U$VRaG4EVLzL4wOAKWzEW}l=q^t z!a%^OXg5QKq$(|TL@f#=c?CP9Gj1cNqq=vBE8jM^8zWR=i7R`Ax8{0y;tx)7B zsPmkfnlea>2nJ~kV~runvXCKp=D!L;uP^XnaDd3npWVd^k4{lVVYy$VO`$`%p!7Q# z^-=a*tq2ML-g)N-}&2VBSn857$h&aFcr;ippW%3D$=;`_OY5F+Zzs z;p}5G^i#A91YavSx>-j$MU@p5{-Tx}q*nS+vw&;}jMZ`KxMbO3VF~wKa9+0Uc21uK;^M7(0c<#nt{mpe|5U z3HB%~s|hSC(zm*zn(8vAu&T;mQS3mPR95>J`zc2Xmjk|Z$+9`lqT0m>3Y4z$J4Fyr zi!1f5Zc$m~B0N_W)|5C!{^}YPS5jNCv~JOoin_(M6-70rm5^r=L@w5k$jcL3RvGZC znkbOudlG{pmad|qou|fLYMSV}8kDrMVp-kd>dNxE3V+S=%Ic+_eBG$pn#J?d!fPrs zC8%6l3K~FKltO%zna8UOt94*mX`n_wqDld&du7$is>(pk;!=NEaR8#dY_a^2(JF*X+1BGQ} zmCNgD0~{U7{dJ`kbwKVER|M*c3X4kob%t~dDXqXDvbeCwFY#rSMTKQ`rB!oM-Y%0j zpj(EfSI;HjgED`eW+uN1MUHh#zz0Af89Bw3C3S&7Ssl`qE?!xJs;322`N3VOP=T7l znp)sPQkL4kq*!yd%fbHY>dI=xh!_K_*l}j%=bKuQ=NA{2mQ_{=oFk3HKdiO0xI#vV zI-#n0aS6M)l9VG6gjW|Mo6_RCYCkIGEJm*>snfjWEUu~2{RB@g?eSbySzW_eRGZ^5 zAM4O3D{CtxxDFkT%~FF&G%w`*|Z^H0!vG)>Z%F@%g}NHh0M*puBfO;p4mA5DpfdUiRo@vP0<=b(s11 zmnaI9ppq-={44!v)3Siclq5z>b>)hcE(@0U3yaZ~>L%1xk1lQ1Yh_i9Qxd2_di+6^ zixsGTNdhBad39-x-;I{Hlz1hrsNm*b0kWdu{KXDmXXod`NKuGhC$G{B3}1pO@@|TX zNA^YulgiZ8LJXJ5I~%$NN(P9bX*)Q0^OP5qYX1Zz1{1r>U0uY7l z;p!%$Gx=CoR#?4+ai$l_Q<=YTnW}p7)vbGJWl>F;&_$k-;b_A^W!W-d3j}KY)s(`X zMG=)4-3_J2vT?CeJpV*MV#10%l=!(K6Le2_4 z>%J%9q^OV*;pSP>5+P-!i>13ucV*IQzjP=(p*I&TGX)jeGmsQX4TP`|<|xO5TStr= z)kTi{m5zzW#F?K=ot)Sk<4r5qRQfx4$Ozul}kACs>c-!!k9|^9RqQN zXV6Q&x@{}1Q(0Z?aD1&RgxC%^Ri)t8;;Pz3Wu+MTSK__Ozq}BXm$s6^^UtOEvk>AA zI>|?l;VEyLehj;&wz5XW3gsNImJWhC;J-$=4`Fyr77>guy$Hai%OJ~eR~6RK>cs=E z1}{{Ef<*ll29bB&N#!|Ndl5O5uo5l`t~^1W$ylet`BnvHmM9EGqKkN6R9`S5qO<51 z49V=P>dn)S(gVC0lD$Vkjc6E_8Z1`5thC5q$01qchnSX5s*>rqWTiNCGTxgPf~2h# zN_k05fY>y6Bb?k^>WWGs1FO+bA^eh|rXwdqJi~T+pbXq9u%;|9>r#zVH)b8e*pwWU z0?@QfQt z)v)W=AXrIEeXp*A_5p$m$EJmOPzP!u6GVam#ysoZQ(Y4<0}LPQ)SR%cDB!=wkpNu+ z^`dktPpnoI>o6@7XlVHU!g6RrrRrS_1dVclS59gQ8C!cjn4E*J$cRYLWgEFs@3DwkIfr^-zWBPJ21Ve({VI!JXx z-QDy^= zuUbhD)IjG0*C{3~_H*KhBBi|6flex5xxaKtNsSYzt&;XPx^$fq^#O-=_r-;n#sH1H zxXVrM8`qSQFI+g1H*KwVYW!swoJ|F5s2eXTTPk{jyi`=WLphZaC=|t|qUjrLTHmSQ z@^M*V8SKFBlkVcF0?!CASJasRX>s%7iZ^s%3@~EGft6XF-Ig`lWeqHQj8v+oJMZyK z^C4KFSk_jcAJtUDm<6p%hR)h5QSd}-MB!PF+N!e3!eV`^^UU8lyJE4RVqtFL7LX4d zJaOj$p zoZ$7EzMJ>4?t~rf8Y|tK8JC_vaog14-z|$bf8ug-a$xXUA%-=PZtf~(dq)t9w)7RC zF|3~Js}iK`TbnwY!?d=l7+RaSD9q&>8Yr1WTj|Qg_z3e?OCv0+4z99#EYy@^^=Vym zP?kPn7KHNyEoeD&a7%H7@GU8aMb<4sdPXduHuE~`-1TP|=OS3UWh6Wzuu@vz7Frji zk=<)8Y=_wsE)-!{+GwhF4!wLh@p}Al;%Qv>4;@Z)J%2c{8rS^c!--`t98N4kIANOq zdN^?o?iGJOoS1XyaN@2P4<{losW8U#8btWLNGEo?4mb|Xr0F%cu|8by76y3Y1i4ek^*1sgUnIqi@c zP!viIvZTtj(Dnwbpuu|R+tkF?-c&CQn;~IMQ?N5gdt+O0JuLlLnE{=#$`(SPaTQQF zm}#=qs$QwsGZn2`ES|7ks#^I-EQ5v42;Mr97DeIC7Kw*lG^C(MX5u1oVC*GP$fgif zGa+ilo*HVZ-@rv>i4bVR5mlW*w45QNDwL;HkVL?_65=cm!l;dPW#63HvwXRRwlK(I zJ&+KS#X;J2NbRaAWQrfa}QR1>sEHCC;CI;dd`USlgq^ic}0juyEv0^Na6VwzXp)wiELL63CH7+_COk-^qzztzKNrqL(T;-i$ zu&KNxK^nLxMiW2)j6=i>-zM-=eVb2Ma-A&aho+*Ez7OU!elREWLFD;Cm2ffoIZ6c% zRm(FpQ-Kd!TVXnvoM+@T;y=@ZIOu0-@T_GDyzWq{IaTXpO;%i;u!3AshIx;k{P=5# z68cDu4~mCs3clcy7Y?v&DC!V|^q~;^=ad)MlrzBVIuP6dpCS=HETL)vTK%OQEH}HO zSqLy|C~!}SbhNa??+Po-FufD0DT*nDMn{VsJh{Tb){gKDU$9FFY()>`=8ewt6*q_K z*S3(o#n1=!WSMagif9+1(v}u<{1)YDq5QMh@dXdM3P`m)*xcEO5>nPNW1WeL%!$lM z{jb?T(S+lR`0aFb>ak?@?8~{zA_7K01905(uHL9+^i&}+1HCOb0*QpiZ*B{PK~Bf4 z_F&mZ*05N&nYz>pJ-8xgvudvX;IgUMfENE&yi%9dlCS+k%@?VjDe#1fNA@ zF)G=>jqN^}k7eSydN^He41$h1`Ey*yKn{oIQWW#XW*9Bs$oLA^f#jO5@T#<#Zb)Yd z9dnd2(AXZt002=3ehR4}3F88&E~}$xarhl#?8UMZ2MWNEKEby3$oeMJ-ebeVugt)+ z!Re_d;*>p>;y46n3|C2^{|(&GxcCL<(LKyXSz66t_^O+f};nQ zM2*^?8{zz@d$f?K6nxtmX$Xf*t{4)*jiS+Tm~U74(Mv?h8$6JvqO7I057>_Q|mj(4JCo8i`9ZX4Ap9Ixa7iLQb>pwt?;NG)_nA+Xv1p%GyqR` z0xQvE{x*03D&HY=HE}jfVp!L_o}2fXuYT^>`LOf2L~9eIEU$XkSqw1AlyS{HGGfL_MabIUNz0VybiT+9Qcs z$GHe&;JnW!oe48A-f%vrhmRIER=C0WX5KTE>qPN0Elt|g7|D-m-6rJFd?dm|^B70X zb}%1?rOZp&pJ^xxT7;cx3{e z_`e6CPEnur#EYqrV=7%6$snFM@pd%+mXNs^Z#tb_n~o%ohK?i(!svgv>hS*f#v=)a z^P&?L@lc3(`xV1e`W1ojqkv=Ig8yclcnqt~)&xYi^*#t^sX1k2 zz2bbjMo)zYr|2>=s|?WxTrvO~Lp9yl+#U%f4GQz=^0UB^g>q5rlFBoUVVGkgXJ77B zJ}2BBMi+NFH+AKPYeE4h>G+=uJ-$5oTHsuXCBmzaZr>-4B<6kcNMh2bjwI%8KazOh z(?=3JK650|zT-&ZjL#iO+<*I##L6!oNh}7;cm6}ym;Xa}k5}GLA>UhY1&)*dnzZ;< z&-;ydehsv`_Olo-aGe60)#Lg;uKX`R?&G=_*E>MN5U%sSgfLte>^vf0!VvESS@VT{jOHj5#T(!8i z;Q9ovui|RPbvLffxW0nx=eXXr2l4{f$8dce*TcAOxjXgx6T&V;*kT=5pBA4EKid1t z$Zsps-j3_*_l&%LI7+w|_6ZHcJB4=l*1Wai4^2;QO4FI+76tY*>kb&q2M~~RAXBH z+*ue@D9ppmYytBzy5*oA*zSTc1JgI?`DQZ_(p78Agt57)eMl;EWuj3VWR8PBiC6EZ zF&WEF6i(lBxydU@0jR#%CC~}g6A66NX#9g30jnD@P1k$!By9l*f+5zWF`J9!))jN{ zZ_-Kzj8kpe_+)}Gzkm@tUhAzH3!LV*hL#A-0g<(8b4AD* zb$=y&!>PzXX>qM9X||LLCt_yT(%jk%JC=bBA#lVF3cVkbE^1?L#%v0O-;B)?WTnek zaJ|D+_Lh>qbUBkhR66wg%u7vwpmvY-0Ja(d1Jr*=12mRX#hqBWcqxP@KX!87D6@$I z-=g|ZbAyl0=uUbJws{6SRaA9w6L+dQUW#XhM@;mCdi%(mO~bSA|PWBP7#-mtj6 zvw=Dq3psOE-YhA#Y*|RP8&Q3OsW8&Xd5d_Ui{hH}J(e`Z&Fks3uPVrW3U2LEYXrj} zs_HC~YAJ9%@0I;KOsV$@va@sV9#vV@D@hu30ki!9EDOs>Yo4!E?~27lz8M>*9QVBu zCKf_thm#afHc z0r8w!dHI+y(!<|@(<`>@pqy=ypbjfAcb_*BC?`_9y88ua$i*63v&ckMOy5*r(mKbe zU}v5P!~*nFWpWbteD_Top!lxmzy(f?UYE=D>&<8dsf|Kh+@eL-e3YlO4dM`!T6cln zDP8BTBjyIs`-2RrZG$CH))sYG%6cQ1Qi+Y@FFIz>|7y|bxrNv`9hSb5^T2 zG!Flvyc{1Wp!g4BA0gZ}MRTH~=MCxx6A(u>xLu9<=KnJzE;GYd1iUQm|v4- zT};2&r+j3I5vU3vaAjW~N@)tBnk?-V6_SPAw6Pa1S4Pl`NRU5iBCw_>fXj`WLP-jf z@5p@}UAdb!ZOY|@H5Yr-)$S0|Gp7rG6ndaY%Rwqj??gA7OaMk(P@Lu&u#-dmYK;8X zp;p3*K4-oU9E6>GXfocNYT1k?7Gh`zLC&y^ z=Q#mb@LMQV>lLG4nm@-a6;~43$*P0!0|<7SJG&>EO09^yVkrGR1xiO2_%4}w30W}Y za|&@110(}1yZV6%RF78!4;oAhJ=QcmtiZQ480^R`Y=Mak7#%hAv0&t{O#c+Ul%bv$ z5!qb@>5tKr`@_~rCmmtEb7V*r$H19mEqGMI=U^RnCHf4XDM3)+gZPcWK4Ro>#%N~) z>jF8wF*vfK$#%xbo)3Ep)DEvzl*=e+Y@&cw6DX$QK#BH{K4CzLPmLgBIsp_-R>S2V z2eT=Da`34RLetKb?dQp1O!ZbM1Ic~1DFaG@vwZpTT#pWb;YzhIl?JUBAgoN=XbYSG zOn439T#>;v&F0D;W^C9laLf`bRY^V2YU`QsR$yZTwi-%50sUs^6)Z6lgX?8ayW9IX zPtbN+AxM7S6>14XOouQTZvw-*AhY21-A1cE1_A81#uMo-Pc#ST`3hyROlQRo34^gr zP8un%j9HthXtGm&81NHmhhQd zrZj>4TBmhM;S#Ms3S$ZK(cxh(=Q^JF3{jM_uoc2~cte)Ck*8)r4< z<;-ftw%kkc#|>OP`_k)ZE|s5mU#yXa;6YhgeCR=P##9AWesRj>I zl*xGyNF-;Mpsv!t*|=i+MOGGYcUta`W&XE0;o3Z5>_+|D6gsxKGesg^OirQ zJl=Bn=x00=q;SbWRngge|0{{oeXk^L!S&S#UP`~>GQ80EF z+!q>}v0qgm^P);%m>&$F_wuHIhB&XMj;Hlfs{Q5=1DSfOjj|1Tlue7Pq^Hw5pWYYi zd9>MiHT+iZq0+*gMI5~Njj6O9|Kx+8V1e6H}|0sPPO~(^s(90x@8#|S+ zQD;ysLK?cKMX%Fl?`h%=A)SnlVbi5Qn9&2{4n>YTn^_ujr9SLjhdIIwE12wK=k01_$bU3nP_K2BTQt5O^@Qt4 zs7W!olFs1>ghC6Yxk_Ymr}oK-iOCFwC9lmi!=2+%v6GK_1Xgl2DQ^@7(?iq7Q?jT0 z($qgw0u)h-tfaQj1gAMzZ-Y3Ym`%cyRL+za#WnI&49OR{PdRjqePuS4T9-(MKkg3<)^-C>;$;5K(jL%zTd1A^o4>xh3U=MY(EEh?|TNm=mNl4kb+rw66%x zMO5SJTQIK!(iy%0be~{j3A!>?7ZIpJ>S2ot%G7TKD+;d}ah!C;k5gJ+SS5b~4#vI? z2V){U3B?ir5}#~_UsPIFTC-9)8`7x{+lc)*^}-2Yi!IK;@UJK=myIMit^=Xi%v>uQ zD+9HQoZ8Z22P;%uBQC72tgOLy!OAM`vUT(J&_NCcMMJny*A3O#0 z0dPr$nVjvOBLV}xIdFvYI3%SzrmQ#nfTTzbc8W-zC0(5P)3Ua`3ll>j9}5O5`Glk_ z6*pS0&Iw(2Wlrd-%rT1mBVb2hFhx)iG!LppWn>4tpDv%;0G_FQ&+a8%L4pSua6|p6(O&uJ5woc;n@S&iKO+aXN=ZlmpzVUfs>0z#1p0GY7zS-Je%2_N6FG*Vp1_fi;P}w@mu~hydq+VoP7X-!LTojNHi-05yqKw7P@P(P6cBE?-s1ITl(Dmt3@Y2ndC9M@@!jwbk? zhkF3mMqHo8^?IFza6RAow*$Ka6%e2DLL1F1p5EKl+T!Ge zadIh74|IfJJfm1%@wcOKT?%>mp2sv^n)BWJOZKnP&)fCFr#~mtk1h$B=ABO+O-$97 z_t}J*JL61zre_m2+TGy!ckiYQ#N&PbckzyvK0S~0_Y*A#)3qHqnz-@*;q}K~C-Zku zp3%y3KFatP4SNXpQ#I_fxF0@&Yc#yJ;d?!0{GI377SD;oe?BdbJJQ~X=aCFy>G+=j z%=LhM4A-~xozEw7v0c*PNcZ%x(cUK@pVfdb#eD{@ew{DF($kQ4Z^w0&CvLoc?(&4~ z!}BkH2mZyy`@G+)```ZeXo6RZzCVdO)Vf9|kAEEJD=!^QocH|E#1CFLnrQyh(ZpoD zGmKZ|-;O4xwKca)chp}czb;-_eoc+|OBcZ|h4nv7aWRVEz(-oqu?-KNRM-}|8dHwz zU|gkLuR#IAl|sDAXl7M@adg|#7D$t#3cIAt37aD#4@wb~e+f-u`uIdFK7`d?19P6D zz+s-xq9TtDcom7sKF_zfy%UQ>G^Np@M~wDZh7P|^W|5d68tWT2V_-aG=~d-0dfjNY z8jP`d%a5Or$2TtF>8P}T1v|x$P0eL7isPJm*>??lo^eK!QZi$hNR(Nx^@eb`u95qP z3oudU8nYZo8IVUVu&84j8-1H`(BdiQ97}uv*H7MgED<>OSYiV%-gyZj^dF4b#&UcS z=Z~NPOkvXo(A|i3yvi|iR&g@W%>%@&TAL02lPeM)#4sUQqgFwc5!&l zux@UFtzI9ADJAig?=o@B zo#J4F16+*&0lE4S25MHFi2~)1a z@8GizCrp(NKgeetP8e?bKe z!wV%R$6=c;($BQ77;g9>o{M!j+tII|*>;QdGuvy4er6k$=x4S|seWc#EY;7XKiqER zNBWoRXVSkyKa*~i`kAz<($8ghzD7S!#-eC*9QPFOEZcuGBE3k2I)$=Pl>bS*u5%8I3;Yx{fPio^RXav?T-ZobtN>Z}V|6 zZ??r}aNUXPNn9`CIumrw$5nw#kLJc8Y7X5%c-q++;-TO;4G?h{4qbTJo=BZ$ZL@3% zQ)9T}#+$WTF33|+NPf>IJ!d$^(uyleml@b#cD-OXW|%>A>0D zxjYl=|L}Gv@O4ymiYaF0^5jKq*ZNg|vm{wk!tm z!O9vGG3LcDwoG2!g3w)VAJzVl@;YP}Tb{{47Xc2mh zFvl>l!c%u2s=v34<3Ch?AC@i?x{=Gqr7dk_GOzJJsj45oe-P^MlTEE`x2{V3!sFl{ z`}@237y94Lm%a3E{_}?LcO4fSt}xtTc--)&A-SXQg|Pjkg0Zo_Y}D>eF*O$cm9U#s zg4xhbji+Qr?d6Zms67io*wQ-y$!+M^+Obe?6betK zu6_%x)u;{R@wC8eos zTG|S$n#mmajRVIu&RaHasSV?)j_}dZh4(}xS2JhMn{!%d66#wecn9imJx-D*g_!UY zS}p}cyVOau=A97=q@ihkp_Cs>r-i4c6TB*xpRtB z4P%D8U<=X~>tW7?x#+$%=>fNPviB`aIY_7K)28X~S(n6&2d6(v!x?R9nyufqBgL}YmZ!TcxQqR zhvM1{FQSW^=Hp9l5H^R`emOeB-OOE*Vs`BGC>FTGZ=otNsk;u_=cA_|SFmKlB@-w- z{g5=pEjF?(t?z4YJl#zGcWrftn+}D=Sx1xKnWe3^Y4mM5ig##v6v2*?h50eLA6ZYZmHu3l?i~>ypBq`2t$1}dOAX)xoSA;Pn z)$FcGFLUAWOU4>oxWj(>oTVDB`J%AAg^7l7V}*9y+L^emLc56Ag^8meHivh0m>j@K zQVbO!&BqsZ?u2A%v+>0(+2K82SdX|xhCj~Mg%UxSKvk>^IdhI{w#HC36DJy1E0juR zg%+*hq^Idf*zFSQ++}NgVAOE`I5g-fWRJ~WzZ9Q}ikZZ4qu%D>MiOxbVW-8$xJg%i z;Tl}){!q;j-rVM9VZ0lW?%KkpN>)C`Ym`!x&Fr7ed?}kbxA1THMyK1E&=qLr;JPDc z9h#XrId&OY+Cn<>+D5DMCmWU-&NqDBaGl{M!ySfS8h&SZ((s~Tm%Uc!SM9z!|4jAj zeA%9>^QRboYxt7C!_Y8(b^b#Bf|I$}Fl*{T8N;kh{4Gwr*QQ^SP5&=lAj1L57#p;XGb$_>SQY!vlt1!>p-NR`_RD zrg@=JXo`Zc=ydLwEvlA zR`G+d3^OuXvK$y1v&0rHHT$p8mSl}Tl7=PWG!?rr+Aot$3QFNNbT)KVto7CKf0@wf zdbWQ0gu?Vo{@#DM;J8-1kFbr_E;mZ!+E1+6jzcFWp=!ey>iFELj@|#2_TD2RbUt3( z4sp{CPo<=Nb0~V2ws#7TL}(+M%f>xbIFWyJ!;wizCvv65(6~jy5gNOvv5a9;eDvSh z(M@wy;l(^{=S*#QZ%O#4G$M0V>+1Z0m#)swHC$x)fgybMDF1D!@O!o4D8n*CQf^Il z(C`DrrR_svliqCeT-8*?egV}~_sjvop#adFnXW-;wFC-h}uX^Jmv zTXPcWR;>?p<)J}){5EMsoIDm9YSSg_cz@j~X~%SxoqP)+v7$GOw#Ixz1#~jCumO|R zODh}AGg*iU*>pLR3(auRu-2#!pwr^Xq_De^HBQ>J#^*Yca%{R%$%CVzfzz2w!rG)y zAygH935QU4a7@G0U0vD5-D_JHDnY&0ES%dc-=w&{g?8g>tw&+A54UE~lzgm59U6BI zefA|4s)d&Ep)qQ5jD=18e{s4e&6^v`2+1BxFXPjqUSTWR|M3lq;ZeDy53YE-B$hI? zm-xT3eud=-WsdZ2jNM~XE>r;09wRh34K)?JV=6pY8U;)%lkNwE`Fm~$xzsnWE@)pJ) zu03(chxD6tnV1%8!jTaU3@wu97wS~@&+0uPdz`x=OI44nXxYz;AdBtw&YZI(+!&gm z(P6O&lsv1ZfEb_Tu}cfRDmFTA%hbjOv9SxB3*hq^U1w{*fG_QNvA8jk z#Nq#+?Z|)J=FO4ZacxD}k z^Un|OzjUQO98%biak-8ROCPpTF?+JE;m9q7CwCQPWePDnr&;746N=60llx5RBTAdxC}ikkbzLH>PG?h+Km9Mxcg2aM=f^$&hx21`{6a>(#)D(?!WrYk%Ms7%+0o%n zRZhR9Hc;|*)BC8xCFhFxpaa9#_ED_xHN;Jmd*Oq1(6k9>Hw zlXFto@gFgtLbog7@rJ_AE~K*T@Y&G4gNIk=em{{5e?&VQ@hwbCzE=TE=S_09dO^9Mh$I)B89)%mL5td7^oVOa`46@J;;@F~Mq zhAj=BHf&+o+z@_B?x!klcscW#V^z;7QRmcf$4ahv_jH__z{Q@-LIjKBJ zt=|}KJr{r6awz^3KP>sB_@!UM$MTz44wjJ=v!Za+$Ct4ej)FA9OS>G2Qwt3Nk_sv> zmmKGIb?kLGv`X_@`jUqOV+ST8CKk57b(lXdK8E3)x`mg%3rJrt9S-4eu@H|$rQ`*k z){a@OHJ4>JEjUR>=(=G{df=WD$7mcA?s2<=>>=*7kb;Xs+ATru3~}Us7d{A{<`jEA^cDqbDP4R2~ z+WEK^5sSvf%CdN&l{_>ZAD9apYK?iV`Mhno{ScafBxlihAFi<3lC_V0vL{Ql<`fRDJv~V&`UuJB zuCaKyB-^-n$Vx<^@8#lC9VK75Cz5m>8D29Hwn4_L_8eX5B}M4rKK-Ow&qA)v(^ZVC zlH^;l@9OzW7wP+3X(dga@}eagUKdwwxbPryIDZdoUeY#2?q0IHi#3LY?dC`9!kI(`+IvtBch*-n69)^^zNk>$ZLD0=PMQ zid3XuuGpvcoQ2wvo8-hr#pjkva^$p#9#-7tbh3bPvL(-Xr=#0{$*T&CtfBfm4avfi z&PvK(#RDib^a%^BhqAP?-V=I$566YRlf#Z)a`x%wrXD?1(-zMO$!x>*W>PmG1NiXR zwpgK!OgetLolLNBGE)ovp}^wy427Yvc!k3>WLECd$$kp;wV|Ww;j8;NUOdQ(V#1U^z%5y^3>uJYoX<%Jwm?a5@uFW&yHB~BvWIWkvN;U_F2R70V z)6&CH3l{4W$Kk3x>U@x$ztkH=Y}i<37{Abyf7;W1GPPni429-z=>*eCgJO}<-Hbww zZ9GjD9tn&u253%$lmVNU%J;$*V7MwSTljBV>uOyTH)(mIVxrP2%wpkE^A6NSLc)KFyHkA++k(lF9p-m%cq3SCoQw1nUnY{?PfJfE@mct_%Q@-z z6K7139MTg{s5iA3F`o$;iul4Er*!m?f3H=4P>e3-y|T_^v&I>ZPyf)iWK!v7N=A{L z>;7lBUyS5a>k+b#q>1vRlJyT4jNxP{-$)*QEsX!y*H`CXHN0h5?~T>@O$^%@K4;k7 zu)pCj!%>EF3?~^bFkE4{!El@5r-u6tj~X6c={^+yZg?~O`vY$H@74KF8Fn&+amI2& z`uoA0X*j`fs$rSoe8blbVchF@li`l^?_Z|=j!zn1O#cq!zUKG$3>&<;I={VP7en}b zPab5LW|*ITwuE0c{Lrw4;a19WS8+7r@wEcAPLtQi^DMN{>SbR(NcOfo)MNzTDQb-j^Ss|p^dZ)ya35CP5 zkVmZg}1Bj$wrD zx1nK6L#1JqVXR>7Ufi-IPT0#55$9$YuuO- z#*S01N<7??i`Y(b+ZnQmkly7ZJ_1phL2gMO$=Kb!lWJF#mrLp zk#6ZM2u+P+DKssng#u@xj94=M=fefj=Zjx`R7A1@!~ORpH)rE+2p9c@>?B>!8R5=d z`ktXe8GlZ^6d&$6NcCgxOb@zi6%a0>_S|ES@q47<_J6WL;#GaP+z&6OS@ZoZq12R= zf5ZHnW!dh?gkN3ohfA)Qk(&@u2mY7B-b!kOR(lw@v3_rpU0aQ>-aqBZ(to?xEen> zzB*_f-<_i$BbUExe{+xmT5PHwzsZC@RgUgi=(IR~P`INI{|Kk{aIqFvtF&G!O=tFM zvpTR-<~7H$(-aXV8_KcC6w;-Pf5df(zZEuK{39vun8%T89)g*7Uvu0!Pi=14&aks# z55q*mRKu}`d4@9#=Nc|HTxs}@;daB%4EGxzF}!ZrQeORcK5OVTj0)!|L#1Ja;T@li zPdapZxV>F`<7)Ph>Dh_l<(!%L5^A^Y>yMljUT^AU z@Y$&oXC7{B@9my8ak^ABQ3Ff=Owtk!hkBiEB>r{q!I7hq509#kf7SWWi%Y!%Hal_F zq$yJh-Ax>HtUg0@)-rQ?rgm~xb2qc|7`)fO)@mG=kkv0mc*%2k4|_JeWKuI+xU4HKL)aZ>sQ+svrutiQsY^TKb9w(ay8dJjk&SQdUsx_t;YD&plw z@j5g)wZ+@9VXJ!8^`xU}3sakQP&PB#i9l7EN1tN#O8Cl))k0UO8PiI-qYKM0Yx0ge z8$0Qf*o~DW-*9y#V06h1Iv+HK58}CLXYUMY%$*Wihh+E79y%{vCB~*ASud_P$!WEj zYSOz4$w)L1<)g{H|>VX^e!dfW;7Wse`V%W>KL zjt?EMyDEw4!!Gd_G*n=Rmsr_DRoS>R zGLMWN%Ac_FP=4kvL-`vG1BQLRFqE(J`2~EzaF6d78_qXeX}HDkS3{_P8>0p;tYNs! zTjLI8$#>!VQ1KaRfQ=qHwf7Fu_?X+M#(mRfzoW8E`tlAHoo9zV<{BvZEd=`+KEF?# zbhvyowB!q;hhFcjP9{9>mn4h*;>&4bx1#aa%t=kBh3+Pk=@behv5`o8DN!6VoPDMb zPdQTv3I(>eMb^JG+$krUWupN@G$7q^0 zVN7~|d#z330y{iW7-nU+%QLH3cEY~Cao&Y#5dq(B;h&Da~CX#2_w1o4YxBw zEwFQ|9i}CiG#b*g24jx)G;t(*DM?RhqoWuTH)>phw9t@_mInS~1Oc#|qNt4b1=9iwU>B*oapTfEt4p2hJ?IwM+F zl-Cc$9@0Z*SeQ~+iXGHAvxQyrog$HfY?U#qrnNj;88ujUoRm?$Jd`sgh&yN-8;^7pkHN z^`FUgRjB55ZI+w}_LVY+w_ivINjti<9c9QtlCYQ^#-;JR(;B;TLbjyevC_E0J()rt zli4>kD%elHp?245OSZ~rOB|dr+bJw%Ja`Hftf9tG!8ff+O?UV@pVy323zJP6wuY`T z3lDA1S{nO_3N>P(7vhDdo2|*FvmcvT=k$idZ6C$L!rz*R|1X>6X5tN$!nIDwMw53K z_+-)9$#I?Zzd!1nv+M=+A+f97unwWZPzklr-(%VVbn zC+E&)(#$%kgY@k9!g*dl?7An^LB>5CyAv<2Z*jSc#mR6nwLq5AG`vxYBT3$wkNU1S zfixY-!kqZR?T=XfnJ$n^o^Z#{A~i2?7st5a`o5Ugy0rVh_TJHSIg<7$j#!nd6Jjl? zd+46P^;lQ9PwY3j_c`;HEFPmpQh44z^u6p1b8vFsB<$vxo-Jm&$HpYjw-?@(A!7|E zvo*dHk`tFLb+{5?B!ig$* z_I%yXzyJUHe7YkvzJ^|lKYeR!b`@SD653i69%e7}aA3=Y?H$%7{H!xB6wY!sS4d%D z023Ug)6J{%=-e|=Ya8HE;3p@bWc51TM4MrLXj#io6+IZJq7-?(|Xx#Lbh zZNa!)Q}eiR56!=G#v~nakDa?DmyFQd+?0HonIsv6C7N5j_Y_ite9h@Lym+bP^Y}K- zv`LQEp-uBNnss|W9YcQ^VU7N$xa1zwT&X485Bl&FO14Kxm9qPV@jXsj_=Ojh>We>= zs+Tt97U)CwEQjb4%_Ox}iFch80Aq*ap`;QkghG4qQKy$a?=maxePgXUxZ)H;=NVoD zKPOq6aDOc6t>YudA1y$B8}DxpFIe)#O}LwsoRV{kcTD%U#Sb4BXPA_fvJ2*i*Sn^V z=oH5e(~YI+kUnDn93jigX^xb%WRwz<=Brgscj3&mWL~Ja_4DDl@U_xJxMdz*guQ0O z)WQ~(C8Rqv%rc&K;*uxZH|@|O%uEBE&;?1@)N!UU+blG2oiSy`r%Fq^k=BEW0FGzj$4uP`4mfX%*hEW%};_#$zDq zkTq=K;#E|rH7~aAb!sZy-!D|+C$)MZSBfQ0X=a=rb~B-pE_qo_cw*OtZa#`Iuuv_88vn8E!_+ zTeM6GOuAOWFp=zj`z2XhxY^LW$0?b_gz7n|3E_VB@OmecORHeRjw*S7+d9TeY8-5! zlF`;Nz3^>SVIzhe92>C}AE*oku(&z&^%&MBU7WF*q}ThT4DYGn%%a8VMwm7|-3Fn2 zR%|EW4BS{ah(m!QOxMN;du89WWnS6@qB-NVu;^?JJnXdG=?CiBKfH`&taE#KO<6b^ zq>to&P&gf>{rij>6`rUZWenw#c^=t2cv5!Hz4xjfTfFa4T8SGHx_hPJl$Jcx6)Tq0 z3R{bp9yB3!$DAkW$u=f)UDqF%NgiY>9+q<4bj)y-8`9odUxms0xOn~zZ*^&2Hn%XJ zkY&dd7#`(ITELoK@sE%W7N~hhZdQj{W3x*xq|@_cT0Rt%Ef@mO=3(-NwN>y#r4XVq*-OWL%-&kXU8-nNDC#Q)-Y`Eh2g|G zoGFDHXt8Ke*n&p01m`3*XU1P+)Zv%JhkMEHt%NDAbByEyZd!PCg07*$b<{*PxZ!5A zV!hIyQjAO>Z0)E%C1eEO?%_u7x17e>xF7P1On;l&>5|4Akno9u+WGj90ZlH+2ACD(IA zjg7AhYxKUDv6=91rm1m`55vE)6Y;U}-}pS@*yO3i&|SmW(6Pk$BnKU}RKGo+jdP2c zYd9LL=k9xir(44@dO&7^M+l zD#LAt>UrJ8_znndD!I5YAIvWsD$Ryvr+84J^Z8l zO#Ol-+d6FU=8Q7m>2||OVQ5bFM|cdfSr31iG2x}5o0ItSpOznG$sx7= zzZv3uW0J4Rgu^ZVqfvA&`NhFH-^oJLBt4QUH#RNgoTih#b|iPo!u>L5EI!=_3mfkuTqA~XK0>NOrF;g4PSJ}cD3Cf~*tUvs@>({X!+wUuqhZ5V$qu3xrvBV=ub zFwLrLvZ~>-Ctdx*d)5Er>90A3@ScKXL&eQ&y+Swcg?$+^1s@dFdcU}Jll>X<<>6*J zp@uL#Rz5m37!7Ts$L#Kww+fq+=j}W;TOVFu;vV&)`HQpD=g$vy1Ue{43!@4Xa~JDz zWNxm|L^n2k3^SOO^vx0G_#ezKE?^oyYVL?|)8#+-FXV)NEN{qxLy|34fI8hIuSy7~ z$#9|WdON+0h|6bjN6lUTKbY5lvRofAZYFHK*jznsp>&(a(uE$3GMTXNvR`n<40Qm0 ziG`tJO@0_fCsTeFRm};9)QIrCUq*xjf4}6-r&)iFh$F3IyihLMPif@C0b$PToKk#Y z#(^rp-JU!De?!e4hi}YWuq1WM)-GM#iV6E6Pb4t#h$$2wf5Tni3N7D3}v!{i( z<_!Pox01h(o;a<3wi<)lwLd$0<`lQ7hr{BC$Lz7|KC|nlPd_}|R4&e7*0HlD#oi5y zpL}uh%;~0Df8@+*CF8|O6uPDy4v!yCoHS{&+rDdmI_ubJlh*m+?8Bz($DlC7LKA80 zzFy4-`Hc(}hV2ZWGmJCrZJ1~{%rMK)U?|*?OsdF~vyxw?xFngc9dPUzRP~dzp&vbO zwVFKD-SwI7Q6G|-p|^z7Pn+Ak+iq$8J$G@Tq#4`48n^I_YDvT3s;p|ZMHV}~PZ~0h z(BL|>aEzC(uH@t6#Gze;S4u6J6J96hLMZt(oNLo^ecBpW|6FU%cjByRyZwJX<7B-x zJ(yTKd(z~Y^|L3{YZsFKsHt(m5}Sw@+ia$nRIz1nEI|)9P%K=gW=i5*IfoK^+>YsU zzF`|CrR=o-)nXM%Nt`SEP-n2l?T%25JUq8>!K#67)7fJ)TB(K0Ro4?Cw=J1Xu?2Xt zLLYARo|LO&?M1SP!_yaX(3I)37tK3!wyVe4`V`1cJF>3s!@IpWo)cEMlkt(GmF(YG z7c%4UNwap-G&Q7zc&Rcvy-anF?W9m6k=z$>8jY2l9~!-6dP&tp$r!Tl*b2MQC}&-Z zT@s(9^JIBGy#3Z0Z25+_yZq1oSg8 zt|4G}dxUhj#@gD)$;EFhFgVL(Vxzox#)@|@=g%2_o-LhDqxG=!ZPG$c6Gjh(Q?DmA zdiwOT%cSIfi}jBCag7;=9kE8b|LCR6tTA5P4Qn4CC6l(k!&^ia8aGJE_ep%AN1p%V z_6*fSC6Ogdn6AHi%aGBk*I4Qa_$7r0|7Mh=xMBvCq?}M=Q?hr~Ze2b($<<So3aQ|uzb`h64EJl|i6oo@!_gl4T?kKT zgj-Z$eyVAgEOBa4BNI16`c?7%ap}Dxp>dp8`;rElMy$&T(^uA;U6{7QUh&pa_%5`2 znmy~#BkN<$>%}GnB%>RD;DKiQUBtw~Yt+=&wAqQ*nV@W4S)-D=ivyGgG?bb+S z>Eb5U{Eme)1-XD?KXKSm1attbG`*bKy&871C#R zbh&&yALfea^?sAQ2lalYo?F*0L$gPufQv>cw86x-_=La^ozPXHN+q z7VZ)ye@vTqX5s0c`cP5m0iNMgTVd32hW5;pD_T|I>9p4PY-ZXWO(+o-f^3qc5l#3o zc?idyui}TpbIHz%tC{h@T6oIPK|1*?Z~qEUk2mWI`*hXgp^dW+Mqo94O1ihmn?rx3wnjmb!cD_{`{0XN8+@aWkef zj87MaMz$H9?Z<@M>^5V_!P8VcVZ&IF=I!6RWv0!TreY+0MYPQn?pzFi?iQ#N-Zba* zSSL~Za?4Xb$Pb+SK|Wac{VjiI{Jo(eB)xF&G^DLUN(hNJwkB$F1ri=)49$#6N)1{r zsLlwb?=&JD#&Js&?w}Mt7+?G#%x8_~7ZpL}(K1Hu_hO$jp_NVHo}7stHF@T&&??xE zze1-uX`OxH9Pbk)o3mnHntIp^8^;sa?y;(XkOe14ty5||X2bV|H7Ij6i{$lM3tu-Cl`LcP<>HK3ZA7>8bETveSr|i7E<7?iA!9}} z>x$#X)l9cX@&a`uhmLcky}3D061u%|QlWX@|Bz0yqeGRPmH;~z3U1asJ8RmMBu+D_ zrrA>B;<;YHK5zE$ZI`s%RZI2e^{&B_Zh4u&|r;rsc?eK0ZO!jY2xBnO>q49O+!56SK^op5;l~txVUKDKx7ua;u^5*=ADjs<@jEJg+2@$h6Z%=<920t+N*<(7+WUoaes*G^ zdNwm7c|0_n8-_o0rcpSGXA19Naq3Ne*BkSZ#VUd1l4$thQbpmJvnFPTrP> zgv@cFKJWNq`7`d^Q0_@r%HQD)>}jzgu3P$1vIHNVf2h8}+M}hpm)d+SMZ%gGF|^tE(DXiH#C2qvV?Q!@aqMC#Zs52bhM!Ab`?}ym4=(Sx z_EEN0JMq%vHgsANbKjDSyLgI=>sKs>7pmJD7fZqO;tD4(mX{6ddr6)ZC*(>l=Fo9B zf9QHLd|EP_bTOpHaSlcAU5bNjAS4L6=0}~^lZOxf$FsX4k(Lg#En9lZpFMTrG4iHR z;CA*2s}URitu>a#nc#(veh%^=(zNW1BM++c(6svT_+iHT9{q#|o7VnDks z@?#m%tBTUEtlYkZ-@{8MV+*K^#6CI`a>wMq;&RVENJI7T%#EKB+pfRwC+_i!PN(`_ ze=|SQ?{hx3GGE89vxz@vD_>zJx7uK3zJ~{KfQwoFvrML)Rs1dM_!gV^*^i6o40iHd z_V6|i@F|wxo5_@YLOge49Zz5rFJ&w5VJBZ=54ZTFcpkv=pL@Rrt9UKz_z;`8lC8{c zD4tWk3r&s1j@?$%iAFFl}$79*X3)saw z*~{lS$c;a{GGFnlOlAVBc{1zS#vFgmHonF#ZaY#u59J`2vf@7PB4aiGzC?&5ho2l*RT{LVYI z#*63Ctmk#i@fo)9+tuQ^ujX0jgE% z$M!iu9QzM6KW;x!9FJieuV5E@*vof0$j=>Qd4De*vYKCEJ#S}@&#;XjpCq2u?ByH| z^6RX4R61leUtvABsujh%G7w=&& zU*aIQm~Ot0OW&+!6YF^`b9{(xT*)qGXNc!i4)PpUJRyCvn!T*&h$F;vEZcY-yLb_M zc^3!yA}e~O@0sFR!+I`Yj#sgb53q}Gu$SA-63@d}@uy7Y23B*2dhxuJIj&$E-)9%^ zJJNRJzc|Egj#`9}_#L+JQMPk6yE*!3@jQ}4JfD?MWimfv4g1)@PaY$l zd$OH#+0Dz@$6s)Wud?#bPVL8vXDu6e23vRo+xZB)`40Oy>Wktzla)_rGUu^|oowLK zY~cpSiRXBB^F;RXG7j-xRz8!-yv!O_G>GR!wr~;Kc|E)NF#EWQL)__j@qbY-${Mz? zfw!`SPqLlspCF#QvX94eh?lUkFO#{OHSA{tH=iw@`?H;=v76Vhj}LN)Z?f`P`~5`m ztYZWBn5lj@A4T>)FQ~Ke<#q_hc96vX_^0kiTHXi`I|T+!#Yfo7cR0vVXNv!ubjNC*$9i@$$EVrG4bBqJ@$BV^9OPxJ=$GzT&3Dcg&vU>;&}A;#PNNOd|CPF`_5l1yT$tP5w`Iww@OdEoqc?U zL;Uz{=J$&83u`!s4g5M=_;a@N6?Sv0ABg8c9O7bD{=@l&HT*3b_!e9E*-r7C!ET<* zKHkP5KE=vcE${8(xf>gJ0$X?~+j$SW`4aoM#Sg{v09O9fd4M&%mJNJ}Ev)#Fcs6qd zZ(%>T`-$_=fa8=Sxr%k%K+ur=t zJ>octy*!(U*oIh*xtWsW~% z8~@HOZuxWZJdlH2$ci_Vi&)Lyu%3g=amQ})oW?GGiM_mqgZvXK{;i$SFT`^k>-mLW zisyT5h)3UVf4yn_9_K=k}G)Y^YS6y{x|bo zseJ#E`SLHU=Qmz4U!MC<`n z-*OytDhGHD%U3Bcu!_B`e4X z`~y3A;Rp6NS7iqCLwt6GskLvhxL4vIj&|KM{gmXN3xga zbC5q`#d;$$eXQmuw-nDknd4lx@p5+Y7wqM$9OTv&;@2OMsbw|KU_EbOj*qa7@34!b zwi3^o9OQYdC>xRKWHp~=JvaE2c#dZqPh=M_V=wRJAYW$1$3|o-wieHctmh);cs<+r zFuS;lz1->3;(0nNHW-oVXEm!oBc5}ZKYLlW z@rcZbvEn(FwLFfEyok$r7d!YOS8&sD;#tG8O-5uEa3rr{EgxVb-{5j?x2t$Q${w!f z07vgOm@nVd@x&^g&pQ5yP3&VUKe_v0zLR^hhjTf=%UQmeDym;2Km1nS% zH?W6~aDeZy+zWF@Rg33L*6}_9YCrKjmQB2Xt-O<+e4ahrcz^Mn!17Oz$ehe7 zwy}=CW)ojyE4MvBJP&0LmvVsLW%*}DWd6V^4zZ3qA1Izjv6WwCCx6TyKFa}aI8ppI zBQkrjiruW^KiI@i9VDKU*vZq`!~f<0f5-A|M`Ye+6-Q1I&m-8xFSC_DU?=~~9)7G= zJa=b#rS!upwz7^tV-x?*R&F_2JP%|K7jl5tv3xt}hgBS89d|rfJg2dhUt%Y3VGsYr z0j_t5`0b@1RqBc5<^r#dALn@Kl!XApNk4D_F;Wvx(bJ5zoWf$+OtQ z?{k2Uvpg&Pu!>cOiRZCw;stEwo$TcE?BT|Ti{}KE?g!3WsSH(2(0=Y!+L z^Dx%(Og6HE%lQ~P_yJe&3nz%@F)SNBBJ(wlFX&*^Mr3zzd&cJPb^ju+m* z0Y1X=an^%X9CfPWjWgNA^VrHxcJgWVaD&stb3Ds;wH~bEWvt`9Y~ssoWkr*CPGk=k zae&ved^hXCDz0K3cUmZ()7i=vcJfyC@JSAE{YBz;ACcLWRXm<`yo61>o2~3;CpTX# zp8Iovr?Gteh|D#t;)AT?n{46^r;BGDJ9##HcoPTs1k0;Os0b9#F|6Yk*~AOk$}V>D z1@>^0CE~d+%l8@G(!qQS$FiNrv6~mMk9Tp1FS2qU`BbZT*06yK*utyW&Ij1dH`vGRE)&ngSUEvH z#Ts_7fse6;AF!QY__}x=!#;kEL%f5P`^u+S!}4#4=RR!Ve75sj?B;#!Z7vsI zBcEaob8O&u*uqEI&eiPZ=x>VWksRXrtlUpN#TxdpfuFoWJojWf=dzoZvyZ>v5MO2G z{_?4BiDxYvcm`W|1KarsyZH|LII2xNXR`7D$2V&@$OiUaDZk*@tK=8_K3DK@_A}42 z1D)5emTq_~Yk2`1c_)|id3JE)Ys7N``*||UCOWTkB!A6XzQ#swd#!jL$__5&3VxUU z`~%Alaz5us?tGni9>qp}mCN~KcJNuQ;D*TWsNHzi+#92D^DK`*<6N_!KKAD_7hkp1ZMuC$NQ= zvYq#^n=i4CTih(32e9&Bv5K$UF27*oy~E~A>}KXE@f^b; zevy?^<^QZ<7aRBjTe!)e#dBYF^Az^+N)GXUR!+0MS;NYw#q-=g>65pygHLe<%bvBp zxf{!-OHUlhOIgc%*vOZ-oLl@=JP+UsHnE@AvTTO*#F1RdT4tXUF_bJ)R~xq`jy z=ZNRUA0a()B#&b)FJdF_;&Q&o4sQB_c-F9=3s^Q&{?CzofVKSmi{g1Dm-E1W$0ys^ z!&f=Tx|eLXS@t_?`R%_upYhLZWSP{z%smtl~V@@d`HaS8U|~JNcPc#q(eeu$kpYSzcE0_pIZ4Y~tttDW3K0 zxfU9XAfTP#0DdVbyU#+o-AZ@is3 z{_x+@E1z2_y>iDv>6O=Wh)=AtzmBy&@0c&YKO~O#yssR=9oAcw@8)yt<0I>@%9njn zI{nzHd==kfJ&)L6RlbFPVmsISxHyhu9~(Hti&=S`>si+DZ*1UZpAgUe*v?bg&8ykR z6&&KfS=pd`^hxnNoDDpSE&M*)`8d0oXCJFJ6whN>dA#!;Yj`Ic_&i&<@kZh~f!#cr zeQe_pf6dAhocCD6ZOg@T1zWhm#^O1d-MpK9?B@_S-$eXu`50?>8XI^GTlgT``6j!$ z!=~a{$0450$`j>dtl<-EU}iJ%9K&{gk=?wIeeB{8Utr}N`Pk;-xi1@d3R`$3+j&2` z`8xYpxrKO6VdY7VKi2SjY~UZ+!uQ$EUA7d@quIyh9O6${IoI*W8g5h}o_n)}^VrTS z*v((Dj{_XyXSNdGD7~_V&1~Se*}~tmo$s-mpZ}D2)^mve#mae(3)b*2Y~Uxh7SBD{ z&Xd^9Z?KQu9O6G%IbVInr^Ry;8~78p@LjgE?lY_ME1276RepezD_7+!PL_XfCyqz4 zfnQ|{f6R71%WiJCz4>x44zZDyrzrQZhQDM3|H&49dI#~G%x*4WA8+Ikdsw-^^09`W z%ZleLw(u)#=k4s~GwkEXcNEWRR-WoU1Z((pHt^?c;VW$CRy&F3LG0sV4zZn;r%898 z70;%TtMZN9a@4B)a?WK3yLMic?_uk1tMY^V87rF9zpOKfy{9s+jt$j_#5_e zkb~TDy!eIc-&oBrv7Wau$3L-+>s5>AIQFuEgS?m(i{w|V=HFP)&Grz_{n*A+*~P2b z%M~2tzge+Zezm7~9?p86#T>uSHa^ZSZnc+qevN~?gB7RCe_74)y~T4M<~W~i{1&@- zAA9*P4sx4)#Gm1Mht3dv*i<~*xtP2RL3bFJWU+8S-2|S$v4@{I~Uo` zeC~AfJI8tN4D;i^*u=$4Y-jecn}_DiheJ!v=S!yZHS^&n7n%>(yV!jAdv@~HOU#E) zw3-jMxlBILA|GK5&-l9a;;e71%D3{xE2IN%e3f*-$yeJR=h~he$)Ovi18)Bv%g3E> zvV7d-W^v5kCXRpW6!&H2*&iyW@aP|j<283kKRn`2`4!K-%l6~j?B}uvt=D^# zUd{&o{x{Z(&-}r9vFb7F#Y;HI+~d~kE6T-BSTD9dWxe>NKa1nv*})h7Vt$Ib zyaAIGzaC$g27 zv6J_*hc9!06|al`s(L+EaS`iyJ)8J2Te*sz-02PRoX!EZuzb1w%PKy}Iz3y zci2)q>)67x+0L8T%_rE$Ooe!kVdcfjX{_OeY+x5#_yXIx$yVaIFZ*~3hj=9`FOh$- zhOe`M4WAOvYuV0+*v*yfV|HutoXW~eT@SK`H?x7gY~hGci|1H&^EmeLA`bB`R<=4` zS;I{~Bc3&E;R3evDt7Y$_VEo4al38AU#32gH9V6I>|hHYV>>@!H@~p0cpk$cevOr1 zm*265&#{5O+D<%wzJqwaypwo7HBvl}|Gao+c77{A@*B>dtmXP+-^w>}SGMwacJdPT z@NN#UpXHZJALHK2S8;#V@iaE^8n*I5cJfX3aED#RvySE8ls;I+n^?yu*u>0k;yH$$ z{33gJAqUvS@++hdR&kTv#dBXa@f5c5N_O&o_V9HMuyVZkZ#loQieF_NH>iFqpW~PI zvfX$KyZI;falO55H;!Xvn{>t+Ud#smlr8)l+qv03;<+FDcq)f@H7l=FK4K03%?55i zK|BvJ&1c!i4G$2{y;ymz@;qz! zO*ZhCY~erI&QBjGo|DGtmXIE$Uky9-)9GRnJS(~v!BaZc7yXjNAj<%3b2)#{4!*|~{QL~@tY_J`T{m(hf5=+?g^m2g5#qTA zJD8j0c;k~C(?j2}B)z8?N&`45~Ya^}a4mO4K99ky`0W#-2-+0Bj5 zG(W!nW%KKlF3z)``5V^q`mZ>j@WB7Fo?OT-UdLYkhJzer#qA?9JDzX8oW^>7i8uDntGWHx#Pe|G zcoy6EeRlD2_A<{wR$UOMc>(KrCv$wBZQS@m@tnY3p3FhEvEnDvC9C-w>$&Yk z;&~|BxRhP|E_?Y04swVUcSx5Pi|0|S=U18IkJ-j&*~JYn5zoCi$VOJ&DP6LfzhpiC z$s9j@sd!Fi7niV?H*%0Ytmu-zw~FTs*7IEEcpKaJ6uVehyWFo}HSb|P zUt*41d|f;bU>BR%%WFBvhgk7b1$KpMFa` zk6}H(#vJcp8=qqr%iF|r9}aRpEACZ)!)o5gdj5+!ZgZu09>Ol>*vs#5kdLzB=jv}* z&Cyqh=aJ0ue75mN?BW(zi|0ZPa^yAQyQODVv*ud)2AkUD?|kFGl?V9U8^!UJZz~V5 z<9qUpUpTHilpnd^CiCOa&F05LZ!tgKz+OJWLB7L^U%H=ttNC#z>v|`6CW*0ZO zO+3eQkSDU@SFUSW&3jqTmziV555#jKySRwGyq<%6m=*WAu4OfM>J-oE%&~=Syp>&i zlD%C2cJbVm6~A_Uz-nH?dfv?(``N|^e<+@J{zyK{-G3sVz2Eu!4*5F2b*Jsd6(Cz?{`{u`8GjHenc-VSx=ZAR3CU57fexv?# z)3-f8ZvJfH^v&MRx3iBc_(A2{`2l`vhqpa9u0A;Xw&%uOkL~t$zJdF*g{QHd*RY!p zvX5_ah&$~5cE0kruE$uzv)RC#*up2+&dhl69K$|-kwd(YmA`X6#u~oB25wRvXA$3h_AEq5#{4O#B&N8xQs3Q9^3gxcJqDqahE;C^JrG~$oE;pN7%r3*uqhJ ziRVmq^E~#klS6!(mA`j?<=0WvW3U9otLnice9WE9OC9R;{Pa}vxWy9^me|H zPjfjpnDlnOgX6h^C$gWHvFtJH#gTlOwXCQW&xu^lMeN}9T)~Ig&s8jY+aQ%bDb658Bc$Ph3y*QG0vzGmA??3$Qd@HxEdpqCBTK4b^4)6w+|4Djb72jbUM@@Y@-^7`0<$3I6Cwurb2e`pB z@lV>Wtm28R<7I5(y=>*n>}17s@tnv3E@JspwkxanFzdLAP26dQcur?0TiC-}Ilw1b z{%70u2=UyNbv&L;yo9a1o1N@u4>zAFp8K=>Y1@@myoPmrkWGA(t=wUjc-FCpXLEoz zvHThN1FM*+7tb+l;uqP<3)#so_V5J`aFZj&|3&`5DxShRUdblj&sM(9PF5Zzo>Mr$ zWi0QLKd_4TA0xly(&HUB{2kl*HoH0U1jh}J;1Ive%4g-ztl^*8z>m!q&)wP1+3aR3 z`}i{s@$anst9jT#C7B=utY~gw*iRUA?H(tT=7nE;LvE6vw0^6N`IQ4DM zlZ$IHUp~)nUU#nJjlW^pi`Ii9x#O1|Z=A+Peu>L@3p@BHuHbs-iRU<${mpuCBrj$y zf67Mwjmx>&SHyEauHdQc=hZChS5Dwa{+qSj{=dZYa4zRr?BMsgf{(MGd6vE8I_G@x zJeIY*fQ`J9%lSMznER@D&S|sV_;r^5U41I6_zLT|)s@mK4`M49vy<)Y;cq#>w^;tN z>x-+za|Y{pE}M88Tlo|_S$4H}?#2P0!17mIU$Bbzu#PXWiCbJFo(Hg#P3+;d9N@0uJyh zmjBcB1*`Z5>$qLJcpk=9p2<#ju!oOvfFH1Y!1cv{i{~+{Uo&#;Rh|Gs!ubC7db@rHEBYW|${e1$n~b(44= z#4avoFWWiD-?HN0(jlw)*_*|426McbZT$T$j(aY+-Ek8>|Do;nrgAc?c*BouH1!Ujx!!{x8sca{>*;jr9Zcv;qPwCIq15M z)jaYSmXnS5$rrinujNmyy5I51TiDMf518L7`PYNu_{_uR$9;b*j?b}!2mVeRcmKU~ z!95-|zqiy|u!a-^-RW$X8@aty0@2J3hOoA?M@ z`3^fd>J{;v$pN0n^7oWuSjDGV#|{1=p5xid6WPhj*u#4{z?WIRS~=!b@tnvyE@Bg} zXDc6OCs(nDJN;8Ur?Y%WIfhldm34fQP5jk>bi^tDmX6rRetz;z`S$znYjPy#vX+;# zk-y+_zRC`6z0&?=E&F)}%RaE3IFgUBmhZ5UqXxxuCOdc@SFn@)e41r>+i8_}j%O`T zWFs%*a^A}hzRVS@cuPDdvdlYx7I7r6XDuIQBUf=bcY0eqr*j2c*w0&8He$WZlN`zQ z-x1GU*~sI$oR_eJcXI{%+0V`26~Eqknf*DEr?K|`A?!ZD+b9pXfh)GyB7qp+}G#n^Mm~FuRGnn_uicxVcxKI^ zoG~84BrjtdyO`zY%yaM%eQwJ#PhfZ{GKR`c{}rbgFT$aGS^&Mf9ZzM z{*3WLCRtz`KV+5*57p;p?BS6t^D2giHiVvGj9)X!=ra1;ky)O~Ja1zUUuBuUFuaWU zDXPzXm}EQKct5jzpLsSetIv&D=3xv+9XH1K0h3&FIenhOELRvd&G*UezvZX-KDqJD zDyOq)*@n3bCDIN)q9y>jYqL*xrWfyZ056UTzQ(3u4WVDz%r%*-`W(Strdi_zHm%SQdWFsWnXO!P6@Bi-PL5?aC$g6%);MTY{S_NR8?u>)vX$f6 z&PnX#7wqPc)%4lS8c$@?N)4f#*v!dnDFR(c$~ zt?gX3A#~mL*2f)pw4F@tWL$Ikooy#0N$cY{mN}c@)r`YktdE!P>bzilk7>RqZvGx= zeY}TVJao@#^%56NIWIVg(bb(Fd)cr2av$sE_4|6C+jP9NRL||?0v?}qfGFbL#&TS9_oE^m!q7&{4a}K{%FUe|IZm& zv%!A=+4^_~Q!Fyg>CADhWAu3di@b;xKE%jc&Tq!KNSi(rO!Fw_cr^=rmPLNU3YR@r ze{JVC<2;Qib~4S^nB%W3aE;^ixi2d`pOJN(-;DDErWih6pPMkpPgvl-C+PF=vmGZM zd%5wyuKNQv^MNbOd%XEdJw|hmFYjS5(^ok@>v^54t&fwKV&NLchn?3tKD_)o0!Tlo&#Ig6cK?juk(QWPc$AjG2hk2|mTxf6Y3$*eUDnI}8Q#qGpD`Agyq|4+pIJ6OrO%Do!_}VF=U9ffFdi7=3eV{C zdA4!YXPpnsu)w!iVx3i9+iiSr>ALlt@xd}%x$)nP4_?MRKVlCzecpO`JtJE+gg$-I z@#0D^IbOWuWj!ADh91l8;k9o&pZFCcTf3gU<2>X#Q;ZMp^RDB}C)vTR-gBJ!G|Sw% zq_<5&=uiK&K0f(@?c{Tx**}bb?)~vLmUz+^#vv!OXBt;fO3>ak&^>Gd+NV`O{BvuS!g!H3z(wN{>9&+-oDx%z6;>qSmt zg_YH(*P|o6&YF7MjV(NMt?Bg)-)9F`U3+@Hizl(fH(BLb>*(*$5UMf3@$2eyGBcdY z4h~;WpCeh~7*?5QbVv6gOmH?^xc>V39L)}nV;3J|iJ!8{NL+s>^8*t+jxD@_8NR>{ ze$OthxPd-*W0e_3cXphZ;9G3rOlG*whWZ@EE?&YCA7+)kj3ygGi*2OOKW%Qm^Oh~` zcfQO#``E)(wsO3fVt5zNHH`6ICix!Q7}{E&8!*p9*u%?MW*5V|8Xt^t@HYC~mTf$N zS>DJzUt$k`WSLFd>hI>dz!=YAlJ~HU?=Z_*%yYeFeICRzvkdRUVzRf&q?BTk*=<`5^_ihONnK3@XBtK>w z7vEK%TQbi!_V7BE`FDo*aX-iym)}jFyReOCGRr%dXOTUe&N3(LuD`G2xraWVV6y+; zN9yy~J*U@m{Ct1s4G%lOdBgv(%AH!AH~YEYV}hM*;cLwBS9WlXQTp7MC7#bJA7FHU z_j^n*e4suzVTOmZgIBVPPqD-=S>@1!^bhb{!UWT7;RI&*3Oo2SySVCTeeT67$1>XD zd5#H|*up^v>vKbP@KAPfJWG7!km>arpKG<>M!7y7W`5^6Ofz+a9=ATy{LVd&wZHi! z!w32t={VN~ZgRXH?_iom<~W@Nu62TWo(HhPix@e`{W|0Ph$${|qCOMM@hBE}HH&2oKhcpB5}WR9<~z+YM98Yk;>Uq%jg{21p0Oz{Jz8BXhS6Bc+li@cH* zKE=o(jvwP}K1H8LpK5>e&eNv*KDXn=Zr*pg{l@jq&^y%q8WZd})BMZ}GsZV}J=^;D zGE3a#9LJ~s-^VyUt+x9->*2f1@aI2S4~JdoeBkG-aMg>Ahr{d#COGyI>*23#=W$u* z5r4YW`(pJn-CN_-fpr!-osYD!*#w)0qa@_KgjdG@lx8dsR0f3*G1W}d}X-pO{p$xhB-H`l&ZpDnEMVm2M){+-SI zH(R;rZTj4tojjV|yoSB(W{nU3#c^$OKX|9($`kG~{`fp|eDxmZE2ri47`xYbcdX?Y zV|Jo>j<2$f2i|8KvCKSgz29--F$Kq$-#w;xoN?P_eH=Q;`Z$6)rdi+w7WoP*{F#yC zjjJb&ckaa$$1=@{%(27*2R*6J4O!u#jGSQJVVskg;ulPF$W!`kW`QTN$eUQlyUlia^C&T&lfF{b$`bBsKz&#hVHajftLMoxDB z#yG!ciYs>Ob2sLgVS#tC$hTPGOh(e~-=5RwD5iJ`(|njY_Oigm{;tn0Sm7~@oZ@+d zaX!Zszhj!ip4VrR1)jko7k|-l=aY<{>O7ikobn*HGRt;8%1(a5ZZ6Sdym2emcr2Sv za~`po&$E>kwsVD-^|>p%c@}$lCu@9@O{Y7L*vz$G(PsULyW?sWqcC($|vXjfbs?VL-%hOrot86;c^C_FT`fK{!hwW@%)Dd1U@!BmPcd$|;pfH; zXO#8E7*}8E@ylnv;%o~hzJX4&+G{0buLn``gW|1ed!kZWwYu;d-Q<>uM@AWy7IgVk0c@{Z^70zbl zPv(su^f~HB*E3!`)&AzbefAfp&d}rVnR*<_NW0f%oOz}=g=x-aj_cQ~m!nzaI9B)= zBj=ls7-wXbKDTC?$1%qnSl|mR@_Sae;%xm3%twqf!xZmgnr|`3nJjRfx;{s-!b=#r z(0s%=dzs>5p&9iww_uJNHq5AZ@pzW_OydmS=Qi&wG@~B9$ar3OhVOHG{#kT}?{gb} z%<;&@_4xG?GwQv3dGL&S_+sYz4-N&$pud&Qu z8NS5*+%hxjG49JG&u1GSV3r>+&u~2pJd#~I&@aXgcp#5NwWygqMSVTSK>CpEAqH6n$>Z9v;UsZ(#UxoTSD(8v%MA0pi#>dc zW$ymojC$k>$ANK9V~T$+&8TPi2s`*OySVs2?Kf`8D%%*n(tc!ue`gE-%M6!)U!S|M zi)XULJ6L6r(VY8ZCb-rI`aFOcUc?SQ#4dis5*PWGJ`;>y<++9lUd9glk=L;|X+3qNCqOMa=(ZP>-*Sz-sPe38-Xe9piGSNckyyEDVH z*}=Qn#kW~vja9Duwf^<)Z<*kq*}_Md;m7RY;@{}=be0(TR-d;qdV|;bPM^=PgNCX-p2sfU%M#yXl`d5E=*_m53EsvQuK1Ha z-|L&<``gA>)%nJ+S?0`NoUgZd&i~c<#z2Qv*beNWpw-Z-;f=8X%_tVeG3_eB<&S&wtIC1=)Kcqub%9<0YJ z*v08Av2&@JzMt)UVAE}0kIh_T>6yNt?Yh8rp3hD`z;1rPUWSM2a}zdox-PJpSF)8) zv7KMClS7x$=Lq&P%^D}L=`XGeZ065w<*HGA?!``yWj80XmnGIXXj%Q+T^HEQL)psl zZ096)@(Xrz>*e&>J#41$Y1{A1+i%=!g_-pfn^v^n_yRk*(@HaaKimFqnpv;#UyR=A zIbgW;aWdQZ=E^hcIo`XP{mkq-*29n1wVu1&Pp)S@{Fo`;xW41c5gR!^e2HDWa$`NN zy{X>aKL22h$%Gyk-rV-_1a@$zt-LSpvbFKRDU96Xy0ne;aUxsz!?yMZ_uGD^?_Zlg zM|fWh@1VyjBYF2BJI<^pSY`|Vv6CJ*+S&f#5lKDnvy1(~UPk}wd1E*GgIA8UKll{0 z{E~SN-BXVvSZ12xdmVqq_zIK!nQdG(rO&;X=UDb|BFii>JkjyrOP?Du$wS%3@yv1( z^ZbH69J04Qn;E{(b)GTa#3U!PjZ>NB@O|_-l06*5GV=`IZ+|n!oA!5nIGJfqWsbuS zm{~7yB#Ruw3iFISpwBpGGsX2=^f{V2j$?t3vB*zZVPus4gT^!CJdP>ez%*ZAj^DGu z6%W+sZmclFNWpyq<9v%L&SaYF9Hh@tEbtN*`7kT&W#l2xxuf-2Vv0u|Ykcyx^Nkn& z%5JW4fpN`!S>yR^`kQ%$&HR9^3}0xxaT9j(aCY-b_VOv#_$8YjHm)wx=Lohk&2~;; zCtqPVe`YUNy;z@nvFQ=xip`wJR+iY#L6_)rLw55}_HsOHoW!O_jVm^D$e;Du%yyp0 zPTs_BPG&Esvc}ad&GpCWb2Mul$EL@P3pVppwlZ?5KDTBk zk7GA)U@u=_jo-7W%ec5qpS!V@8MgB-cJeKDb0&Ma&Uk%}V$&q!g3WxGt?Xqx7rR`a zTd1dgwJ8v%wbpPGs$+I!A{=JZoa`@PGgO0Ua9}2&r8|N3)#v7+xa0o zxo}ROo3WQivc{{}^pyJ%ThIw|ghu^Zy<*wI%*5@>g@pLBn7q;ZoJ)Yz1)pSX4uBNnB`l{b0&MZ&K>$3#qjgS8)JN!N%pdh zi`}WuEtuyq?BTU6^ErlJFy0vBu)Fk`WE;<5mbWv{H`v2zEOX7f^EZF%<(Z6_$iBwJfP358F|@pWt=xK#TS_7 z_sns{2lcrdi_EaXyBK-Jab=t{nc_JG*9lhH$<-cmo^fyX@=vVsJ~sWsxMMRL{${*! zBet`ZoxGgge1g6F4{KcNVf|Nqp2B9H#8%$ScJ{E7Ke3xDKcde)S>w5Edd+hloB1wV zS!X-rkLvSacJos9@^RMq8Jk}BocEYMw_z)<^PwDfoPwVr)&lqoSc&>id zc;hZi@=Uhz4rW8$Xb2Vdph)I6LHZJmFIDE9Dbmia8hZ<_BI zddA`OT{>n1fcwYZ4*L%izK9hWaZTx^)hF{RvKbvc__nET<;m< zBqsR<+c>00pUuqkME39|mN}W>cb%tods;&tT+3*8|4+22-5I zG}nAbpZl}G3t41=6@JLbNA5qS=<^4rc>lZl>?rATpMUD}=nwR{%ZK{>_9Oj&n?HK> z+48AA-}+3SXMUy61ODr|k;$Jt*K?0wTyNM^Gw<}eKbURYak;v2#|e$KdXBHKz@J&< zs^MC_!o3*z*tlez6PaR(X%1RQpBu8kLs{f_Ryc`~PmD{(Ib>mdHZ#o=nd40?a59UW z$_j@sqW`IJ$vDR_#XQrT!W?I_!1Wi^=V(?qj*-udOUC&rQ@m{Pn%@I%f3kzyEm8A( zz>Q0m_&uvUFjDh-z&+P2S*tg*WvN=djSWj%FK=Rj>kYMD=2p;S%PO^c(-%HxTC3*! z+U_gY*5d=~)O=st=cnt|d|%srS6q)O1LkA4b3P`6Uy)pDlc!88+^$&yCr|!&u@Ktnx`l|Lb!W zCb)D`pW8FTli9&r*u|GwVjrt~a2MmP;ym2dIOTG?*>4=fEDzq>IOWp&>2VUPd|-d; z{oZ}e;d-3KR$hCo9``>T#=ct&gR#&I?XH-*$2;OB{ZI z9!E0zqwQjXdA4v0Gn~y1u79CEN3+Cntnx8Nr#g?BVB{iwZp{pjV+U_w7hhnB-?PdU zFV_Fb^@Ry$*uuM*;alwBOm=adOY}L4RbIkqpX&<~>}3lV`?Efi?BIu4eeQdyK3Be~ zRy7W9eLjDK@y&g2wBNYI1pAxo-fDdFDi*ovZN@jBW~A!x33Qsrc);z}%L#Xw z7r5A+wR$J7y{lI5=CHpxuej*L&Z}SCKQqQElU(x=>*ecDI9^OX={R$vLPu)>9& zvEEkiiEfo$WSndKwQ^JDgK@ge%$lHpmd zBaHFBrSy5;()#=_vn&qP=eALO9=)vn)}JqLzs>HyUd{4*zRhbZ&8oL@hn4ks)@rlr z1>PN-<@bC0ImDW?>NRen!p&Rv6n~zp*j2ALG1$DL%+F|HT{^IzXSBvdAM?;eT7~ z=Wt`_yixWu?_~?$V}_vv?Kf_~E*`=XFJqNmj4sp|`kV<4K1iS2GQ$(t!5i7dmssMD ztg>me{=$u+J(%D*Y~el3@Evw=7Q49K!TLOiRc0Aoq%rg;6a0iNT;dRYZp98B%PwBe z5}#+46-F0z{14UVu5961%!)w^V9(Hj$OWgKoeV)$fl8vDUnBd23;m~9BIf5Nbvx^g0 z;w!B3XGRBGZ<{{%VhhJI!-?!*iCr9YtUfnnm4`Aqq%ky}2~J`QzhH(#j?-r|yLci? zyops#W^}2>&{QTk{CItiWQJqd!92S-g(c2rmFu6NzjR}0G!vY_7EWb`|2k2h3!S9T zO9pcoIvznN{{Mx@=?UCnmV^Y5M&1^jW@# zZ5*Fre&?0!;ZrR0ONN&-PR=x6a|Dx2vyBs&k-FvcNg>$90{Jds)6#5^anhf`VR@N@K6Fisfb7$%u#8>cYK zpU$=4xbk`S8~0?D=Q6rtW9Y9;@LjgB&J5#Y?ROr`E?&wKA7_=HF}hM?Xvsh6a~rns zcxKqa4!+1P{=gDfYS-uPj5alf&SrvlvxRRn!x}rd?)myWkR|?^RX)P#aOXP{T>Juk zZpjS4x^Py#lP6v@tKQ8Dd-?UnuG4(&68mjs<2-A>@z`;$SG<`y9(uL)a?2a_c;xN& z_bRsc4%a!}cc<$d|H(8P?$YB%EU=YDUd{@iU}RO}nsF|5w?4OHnkO;Gn^|BFi~NZd zu6&RFYK|Y{JeMi{m1(}q9P2DFp4aEWtngAsR(Jdu=VwfD$-nAz8|HXC3+!N#FS5cP z7+J&dyH}sPGsUx+=H1NkZ5CK#k?T&>=YfpG96!eS2vhu+X)b=BKDT6nZ7lLSR`_>D z)^wdsQYjiEIj(&xTR@qDKF0CW6+1&05o&rMk2 z;f$yy(_zENIna3FCs*mV%FQz$`IZkAOB^Ej8QGIU6 z$okF;#yOrTPGXv0FvlT}>9d(dp2!MsVkB-JW1Lf&;_%1yIg&Y!VS#xTIfWI@W@H1` zyDoi>W{TsO=3~t9Qx+JRq|dEc;c<*?*ciHjalXJ5zh{~&KB3RuSYU=l-o*;vVq~Mn z&`id;&Xf8a#WXKrjt{fIUKY97Q~KP3k&PQe$1u)onc{Oy^E>7^>}h=_S>ze4@ODNv zX$-x=IHxhiHJ{Pv{><@07Fb}BAF{%QpVi;gJlAc$ewO$?t8AR2zeQtcV8`yV%9g zS>oV->T_F0xAq*v1aD*uUt)$ovV%?U>vIp5cn+()htX|3$1uTJY~gwz=<^_UaEpJr zPVz05Ig{aSjq?v(Cpn5qUcxp$%q)AE=VBijH{60{9>Z|6an2Z@W0K#ojl=$}&m{9a zgFU>RWxm1icE%lJT(ei7`?HM~GRp$<{E$6d_+x!;#_;yW9b>$TNj}3ie$6bSpXhT( z_V84ec^ktcj625o3zJ;^Q+@8kEZdpq{p{iUEVJ=5{T+-u#&{T$yn=0fl3A9S=hC0+ zb9cZ~66CfUa}uJVOGQ_S-`_V8Yo`5wbN8F&BD=LSsj5Vr9$X4%C&KW7gI zm-V?V!#f*yjPXV$`4ZdsBeQJ!QlERUhv%@&dl*g{cZ_islU(mBeICRtv&{2R_V5#y zxy0A{yLf(PjK?y`>)FQVnPr7}uJDaMcV(GpF}$niXU2Hix8_R@{my*J5zH~o0w=J@ zS6JcCjO^w*`Cs!b_hO1;ndU_1SYm;LD*D`z6&}jS?yi%Ja}rbhf@u!|W4F~!H2=BLatGF6{jv&iFE z;SG%J={m_czh{ao{-n>{m}7#{vudkVP*1t3Eel zWS_>+k&N>yruYog{F*sNf79oVEb>%VcpD@8nm-ulFHCXuY5LrUIkvOF`&s1stgvyq z{(j~U#(5Z1yn<;y$sEfpaOoNP+@2Ml%*g)c561a2Q|x1!tIX7AiUpp>BJX8|?=f2q5~TFf7e^G2rl64U&VIX2DK=N>Hb99DP_Bcse8 zjB^%KT(7RrTiL;-8fN>xxbuc(PGT?q&csg777iRc6JNO&B7#pI`{aED%jJCRuWP<-<3l~~SpPRCSN3e@I zmiRQQ{EE@TJeM!6&mGvpQ<&kc?BGAx#VSi&ZKyu?X7q5MKQY1k*usA@!-i$_xe>eA z$`UVUl}|8wgy(c7xKvc1+cCqF*uk6G#U7UU6RTW#S^XnDr!&EG*}}gv!*|)iI=dKO zPM-&}%1aqN%5yps{ERJJa+p51VF!&eoMvwNKzPvtnXA93}hIg}rZ?lUv zmbmT;`aF=)V?3ub!AID_kD1}(E9!GgcCn2mUdJl`&S;zGbSAj`O8VS|8J@`w-oY*w zS>kk7xmJ_@v7XbJ;6-fVL(K3ac5sp5`b@CIqgdtDj2`DXoe6%!7B0K8K6hdVPh%H5 zS>kJ~@>fQW_nf|pKKEq{&u4}Yu!A44i{VxExe2R0oY50Jr!&E)*upQF;n3CeIf7kG zv&0Fk@)br;bpOEwS6yA7hcUyu*}+fQ#n>A9Jc?D`&*(|cBPO_hOrK{l!$;V`U)aSh z*3{>0R@t@IY`+KGb!u(%4zFdJv)RG)I_6tWW0@PRYraXFj~L@U>*;ay`g)wo4jvG< zJ|4Hh?0PTH+feTm^YX^#DNf$rcCvfK?0P%5++lXTlP9v9TkmLnylbb~^~kBVV`n`M zNzSgPSY?_WyUecVxcMH|$1_>tH>~ncBfY=VT(9@Do&0r_9-ll&k2{Q>T`%yLLuc2E ze7#kVe?Ls`bno*BJ)U>89$VYIKkj>h?c~o{+sQM>+0HZE2VQDBx%hb7$zeA-4m{;1 z?~haOHGlK0`)1cGeCkl_zU_R$pXi)$UG~Y!pOPCH{)FYMSYHDn&X(`V=VAf78!X-pIb9>o^j1M zZ(xcqFwO6oAaX|DMXeeTZ!FJzGgR`?+!=euuyRiB$N z#Uq*KRm|}j7Wg%bjJ~GN9T~a6eKX^{jVZp$G=E`^tG}+#eOP2WE4-hP3*9#}&c-+N zxiQl`j5%Jx0-t1&WmdR!QU4<62je`MDc-^~UuKSdEO3=K^_gOY=P`1z`)0=Z9#ixM z_m%!=&T{B<>+Sz{X818X`Sc9i%UsR=W&5DI?~%K&Wr9Dmg_}0i zeUIGz8#{O%yZ9DM3^&$&kKFwdqgOeuOfb(De#{Jqg!Q=xyLcf>oWv@>X7p-S3@7T*>%jh%7 zrVjHvn|V81`3BoLjh$RGs?Yt|%L`d!flW7>-`UKCm(}NHZ0C{e6b6d9a1a|U9cJn3n@<-O#G+h5S=M|fI4qJH-+xZSVIg8y~Z)JTR#2T|~ z>NFp*nV+zgORS>Lt=P$9+0EoI$v4@}8SLfStLd|a zO}Crh+04JOmH%ct7hPSSo3ooovzOPf#%?y<;d2Q#bGbG2xii~&Iy?CncJp=i@;BBP zi|OC#a|t%{0=Du&w)0=?p9iv)e`Y%$VJAOkHy7VX zpIfrVHa6Yoy2fVyovr*Y+qwM4`rL)xJd?e=gEbb}bidCf*vz#y(dPkd=SA$~L+s{9 z?Bybx>NCNn2RxUvnOC!w&$6B0u#?Mfrq7+&%hOn6Cz~GhJjiDL%2uwC(C5DF>Pw!u7@KU=DUVh||CB`gzQE0@9+pf1+Z1w(T z|1wGcUvjU$`Ud@fu;bvRE^XL($%RkwLjJWsZ}a~Z1M;kV?SMQlPXy#W@*M;6vV8A= zJna1*8j#22Cj{h4`Pl(^oBWc1JS)E@AkWJ?1M(jE{Q-Gd{zO0?_Mdy19FWK4?*!yY z`NsiyoBX?gJS+b#AkWLgdoOr=^~jeF$jkDT1M;xjfb|3Nn0%{%JSpELAa9fJACPC| zM+D?~c{(8Pk)Ickm*tlRA*c{2C>ZMbsI3EY4F#^jCr^!a^a1M?&1=1KW( z@-ybk({u8eKWmfUA|GZP&VBt|{@mEOSG6PU&GmR_d`nloqX^4@;&C}Y5DR8_SIYF%lDa^=j17Q z_k8)2bMlx!E6Bf*`*oS~?VrX^=WS>IawW^%KRS4S_wS#Y zriDYHk%#ovuj!x2|2MDq@8?SvowH1Tt$%$<%RPE@Uw!RAZrAX6+tt6mwB;T-X2Iui zPX1g#UXZ^YkQe121mqQYIUtWL5(@nkkjLe-1M-x7iM9p5zqEY$fIKH(GaxU>Hx0;( z@(}@fMV<=CBaZXI0eM`0TtJ?ZpB0d&pxd{#hSkS~7xg2!J`J}e-w$YTL{WJt*GrC9Lm$K~4xuyduv9|Y@Isti3zIi}iknbelwExEYfA{03{C+Fm ze}7$+w*>Sn@}uM@4eU1@JLd)Z`;nopU-IO@{K9#!AD6!^PYui)cAMKz$!E%U9++P+ zub-B$d}3dHhk^N@=H)s0_VQN-<_#~-SzyldkGw3u_>a#SW9B_)%z6H?+;%7T)z2CD zI-WNhet#tG|I<0oEj7zsX}Pg~e7)1>yM4Eo zM+fHp&$kojf1R}D&OfcMzUaW^8XM;<)W4pb{Mgg`>SOvh@PEg*;mmpOU*0W0U|`<= zzJ7ni?Elj_@2h0FuPyiC!1eTR&)f61r+>R^mb>N5zWT<0TyCxTmy7xQ@6NOO>P!7` zxrOH~*T4NK%Z<Se~=cocUjV?scOL4W|4I$NUu^vGocYgk8@Bh=j~zH) z^v|b<&RuNIa$1M-Ue+kiZ> zVkq=$KpvMjp1>x^7R7pF8P)Lc}boO$gA@G0`ll8=7E4bAwM}F zZ;_uHkZ0uM0`d;|^#OU8{EmRUBrgQyRr%8ad306tKtP_5zZa0V$Uh6nGxF~P@(%fo zfV@k-$i)jDebH0E) zAz$K>1&_ZL`SJmIM!sf1-XY&KAn%fo2*^wFR6t&p9~_WJU2KjE$P@Cj0`eC5MFDw6 zepNu;A-^>s?~+dp$V>9BfV?VyF(8kw>F0a_c|!j0fV@Tijr^yO|NZZCkcP_K`+$u6 z=|A_?51ub?nVWaW`{WDyoUKc~a<;F2^L+j5=k`nT8|6pOmmfAaugX7=x6hZ4nUmW! zq3Bwn&}QTM>Rki#{`-sv<}A|xr*l5fX|~++mfL0Eat%AoeVtZ$S$^xly#IBso&R;R zmOJp$1%K|Cmyeat_xDE{ht7H4>%ZUWk)Lsyzo#&8Jq=gP-Hx*SGkJAj?(Z=)d_8YF z`rmhCZP(55f7oyR+dF#Ra{cQ|Sney!-9Pa48uD}3*CIdd@;?84MhpD!`1k+4iRb5k zj%~NxGFSH1ml?QR@qqbXr^j;JUiF9l{D1$_O#k~T%O}Yf z`NQip%$omwMb-(0Ic}{*xKwglK z4ake~%L4L>ydxlwtQQL16_Cf}e+$S{@@E6`wEWe8JSYEWKwgl45s(+t4~_g9}Juy@05>`V#VO@9wML^T+o&VgC2oYPl!w>8l?;aJl~Lz<%>Dm$h6a-&Y^~$L02% zw_N{r6)e|uZ(scj|2%iUHGDjGyNdEpOG5_mSE%(fQef8(&d!47|zD{&Q z)JF0(snk~22V}13f=6jvT=e|y>{7d-@3;p4B9$#qg>-6u> ztmV#ss;~a^AGiDAd7szLdH~Rr+*xD&fTmzZl9qeoxxTvpT=u-<(!amH zpMU$)mK*;_y_uLJTfc{Ly}$p=kd@c63A2M6TQ&HS7#AWz8G3CLUIn+N0>`A+h^2cEzG z_lNlX^HYcXbomhj^Zt2Y)co^6x8){UZu5c5o&NhW{qsbxyjyXiE5;L4L)+*YDqsi{{^sq~-3i+=8~FP5wl{db0Ae{OUihCp-Uo3YHuB%Kv*k zbLM~f5%QitzRolAUT4nyZ@HP4JN1vtwar_ufB!UjLp%PXuRd|$at(LSS*ZVYn&q#` z|2r`6-#?$vd!7E}+AMeFt9|wF1|A2?HGVely41hEoaOd zFMoaRe3FwN{^lR%>;8G-kbQ_=lz4QP7K2NjdHl5N}ZyGqSH4dAzvHkD2Rlec7fB5?q4M)!1 zj&}K3^2_GyUoyAfDgWrb1>f&?%hxXT)t^{l!29gK@4kP9IqT?ud;RaHY`IC_doF4m zuw4IsoiYFYd1PCE|9@&<{pI<#=Y_f36PIt%*H=HW|Apu7*WWK1{qHv=zfj&a@HwFI z_lKDN?MTa)`K7P!*F(+g_isme{_W_n+=svQ)i1Qzy!DKoyWhIxTTNT==f@@a8S*XW zdmo$3eIHf%Wz+v~y=}OB&g;)P{>{FJB5xVk@88amb6%ovzoU_sCO&eqP}7P+5L( zKpx)C_66iI`B?#ZQhrfD-X^~)AkWHg4aoEIi2-?!yel9t%U=x0!`u6LM?fBv{~yNg zJ5G&iVdMB_mlz9bqS#TdiY;Qtjvf1|QL$r3W5JFkUMw-#(O9^)V7sD5T|2R2$G&#F zHtbjuSG~IIu7&Hozr!Xl!)NEo>pyPzKAbsII5TtR%*?04Blr)(58(F- zkKm6BkK->1Pvh_5BekohJ<8+DboE=0x3`=3x7tmU>m_&Z=zi;j_FUYVtC9P4OuzMm zy*)AQ+vm>q&A&DGwa(XX-9g#Sc9>k}v}W@*-2X#vt@-<{NPBskw#xHUM1tJT3%GCR z8GK*iJ$PJrFMhJ{KKvZv-fcKf5gx>^7v7EEAv}RUEIflhE4&Bq72b<~EW8i@PPlj5 zj*foeLA=B3zW%!L1%)T@rG;nkRfYH9A>qCF*24Sn-GqB1^q&e3;ztYb#!nNTz|R++ z!KVuE!E?fU@wX`oUU}ZD?Ui^3Q{XTrXh1~1s-JUi|co4r+csKr~@C3f}!tTGH48E%H9y}zx7vEZV zAHJJ#?+$GL!h`tH!n^U)geUOxg=g@o!h7(X@Lv3G;eGg{!o54P{R^XL&AG-&sg{Erxzb5yboVaxOXR>10y_$Z!EkU-%fY}-&1%7KSX#Bo)F%PPZHjT zUntzWGtYq$9>i}I-i_ZUJb^zcJcGX?yaz7}@5R3o-iQAz+`9|?!oq|2yyM)rzixan z;R$?2;Te2w;XQa*crU(_@IHJW;ok0!jw6Hz@sosi<7W#`;Fk)|;MWQ7!Slj<@rQ)> z;m-*7?%L7uhVUT%k??N(Tj2@(H{luF65fM*7jfVIdhw-%_u;GHBVBhg#}8g0iYFb% z7biCRor3sue1gMwX?i#Qk(ho0|5kVg|4n!gZVB(jy^FdppFVsk;ojX@KEi|e`og>M zt%N7=U4>`x1BCbB6NUHUN#T9?WZ_;`>=nX;_%z|&_;le3e1`B0{(|rx{B7aActv<0 zK2x}N53cVB58_=u_wB12A1ge8FDpEQj~Cv9ZzQ}Ij|lI>_Ym&glj{%ot)2Y9=k#xP zO>1qpEhB9$$rZ`kFQn!7me}*e3ZfeTDqV2 zg4^8mC%@upcDR^af!tlo_dD;iGW{}#H)DfB z|9%)>M0gBeUU&)*3eVx22ruH>3$NgN39sXa3in4Dk19NjpCvqoUnD$*XNBkR+k_YK z`-NBVr-aw>SB3lcW<09!F#fgh82*d!6kZpe!{=MUefuloiwm#dD+#aT>j?Mn!+2ET zVSH!dF??U)DLn4t=69aMPsSgz|9;Ky{4VG3yhQF#mvT(IRK>@v=)N31`*O`wcmQ8P zcm!WdcpTqMcpBePcpl$dcnLpTcojcUxMx4^7ZV=9FA*NWuN5B0Zx^1%9~7R)pB7%i zUl(4*KNRlSpKU~V0RL5Z1pixj9A981_w6r@FDX2auPnTTuP3~UZzizNAO#P$MO4wr|~C+=kZsBm+-RiD*lyl&q4GH z2@l|Z36J3OuI#@3#qq_2r|}hq=kc|Lm+-LgD!!9&&%yKy2@l{$2#??=36JAv3s2*h z3eV%$2`}M!;Z^)0;hsb27ZM)8-w+=0O5IjqVN))6kf$A3-=sGzlZPuK23N8pDsL(&k&x*Ul5+h z-xglNE5fVzOyQox>Gu#Gz`IuMw=U@5zd8K^vj>6u`6z-Pjk}#^$MMsIr}6WJ=kck+ zOL$Ir6~9}!=LoKg2@l{e3XkCL2#@2R2~Xp*gy-=g;U(O&n)~vv;^TyS;vD}758!JE zkKh{%kK@}3Pvd(E&*O&(FX0K{ReX|g&ygJe2oK=b2#?^m3XkLW2~Xos3eV%O2ruDf z;Z^)A;hv*7{t+I){}LX-=Uv@>`-|g?2~XoI3eV$f3oqee;Z=Mm;hu>c{|FD@M+lGL zCkc<^XA4i`mkQ70*9kA-dEr(3A>p2*IsOqIz~2xa!9Nln$G;Vx#(xu@$1UL{+&kWV z`>Wzh3HKbs@sIETzP|7XzLoGezN_#wet_^iK2dlHPvR3t+4j#}hd2A(tN2rE;Ew(G zaA&#Me|wH){B5v*#OFQ)@Bsb;et^Av(=WfPb9`erxuw_Yw=Q%{XL6&n&XkkD&%+(( z`KCYb@>YMI$z{p?LeB9V3X`k1a;Dxza&NB9cu&Xlj%iM>f-kd9zqPKt-jvg|YOCHs zzUw)Td0e;OdbpE+%sIZXzX#@~#w7|fmBx6_5cxaT@3($3AI!;{`hDZ9UyR&wA@}Vv zg`X)rhhHGPh+i$dg5M&%j`s-nC%7L*co=_Kcnp7Ecnbegcn<$bcoF|ocm*G`f&22W z<38d3&)a9>X^ip2Bw&p2PPRUc?Ul5gx{`6&}NH7oNf& z6rRJM7GA_(7hb_X6kf-x!u==G?<+iv|1CU*FR-Ee_Lst!6rRIZ7GA{H6JEi$6kf-> zh5JvU-&c4TKT3EEKUH`NKTmiLzg&0`zfpJvze{)>F9`Ra%zZP$!}wdmWB8}SQ}_?U zbNGPpBHp=?`}S4A7ZzT}{lfjHaNmsZFutMi7{0CW6h1+C4nIhE5kFRV1wTW09Zw7Q zpUQnR!o&E@!ejWo!c+L;!gKgb!i)HO!YlX}!s~dSaDS5L^au~*^K9(C{l)M_g{Sa; z2+!eb3NPZD3a{Wh2(RN&;r`QjUxx57euD5A{!ig4{9@rb{9nS0_`ii$@CSs~@uG15 z={!e9co_eW@EHD$@D%=E7dPhtIsAY4tL?|{&$N!;&3QnH+)bOhZ--U<9^sxdIyxQ` z9>7b&Blx?*m0r>!0gB4 z_{aFW?fdapTKjR6%aA*N%YJK?y&Ti8_NB95tw1ia759tV%j=3a3iI>bGJg5i{nj@2 za?Tzu!%U}!KY)Ae-#63wvo#%)^PkJ_a+`kV^Lb7G;e4%no9RW!oxbhJ_f0hBAAcQR zZVcf${e`CgbljNc1RL{D?zx@mA8pTF+RB;f709iTj5#!H{k``5?;o= zd%15PHGC=IzVo>rB0PkzFFcBGB|M4mDm;rHAiRK26kf)Y!fW_s;l3%12N52^rwNbZ z(}gGT8N##p3&IQd+rrCuMR*OLDcqN4Jc#fR-W7G3| zUc>hg?z@2dV1$S8wGnxUM5Sgl~q^ebU;WcMd;zGr&ht{7U>wyPM;S z|1@{^jr)^Q^_?mXN-QQHfzY|`^`-S^2rr>?u z%MarV3XkDS3s2#z3eVvo;YECF;T3#0;dT5#;r>fF?iL=#PZJ))&ljG;rwY&EIpIb8 zZs8UDQQ>v`MdAKS8P_H}jDIFPhR+h7!iR+CaL<13+g}kMC%l3$C%lfYA>4l%^XD(@QyRrOK$Z8DQ|Rp zd9CNIn|7l{Zi_?Rm#Z(s^RI=6@co2G@gs#N@l%9n@pFY2@Qm;>euMBDey4EXwTd?De!D;PH;JcO?%Jc@51Jc(~3Jd5ux zynx4qm+@nS*YMMY`=)kuOc5T!uM{4|ZxWuw?-8EG9}`}{OZeXWmYeNH=Y+<=g=sI! z_#b$-)8?jKxzst1sZQ?5c)vw=NUI!koHF~Jl;&g8UIebBf12DM=7TxyRA;R@y$GH? zvfoO1ZEo796TQs?9#gLbxgSpEzU}sU9p0*!nO>G$FxhYY&fl%+^*5(iz&)q+JKtk( z>OK5uS@W&o`@hL;Pma?)TRFoWL8d-+d^-NJ-Ay^gX0;pRy#iNJ&gpZ{b(5=-d&AyN zo8|tzvz<LdTjRQHxh`+xA+2UPc&_GrV{*SWqkX;H>s&8Ea?7Xtt?l_vYrSmUsE?UWH@+Qy zqQj4E);ED?@t5uO-8s`W#nbiJoEkUQKe_cTac{p0_?E)Uc(?ExzQ1taHH>Q!9>Px* z9>vcSp2RN~p2cqzUcm1XUd9W;YxwiReObn}2oK?(3XkGH2v6bz!n1hirDFZ#3kxsf ze&IEIb>Y5$F|I{;2;WwC6rUhGi6109iytezfS)0}jHiXy@T-LTu4P<{@DP5li<|Z& zia(AYW^ZpyyR@(KxzH(czh3UXo^$x$!i)F%6ypCTk+m>C3_R}G-yhOE z9*E&j;U_q}H9kLu&v#|Nb#MD|&~47+pgg(ERsAErm)*2CCHy&jANzF7aa?z!D(2J1 zaaB}OBluUscsugEdq>M-SGZ{<1KH*nvU z{d}}5*f<$AUci@`HuC%!FXNlzXYqIIJoU6@J!<%M_{R2nnEr}2TKgSSU;k|!-{ktO zQ|&WlYhLhiSl`>jJfw&|JN-gC}shvzFnZuQ&S#*^6I_ng7~dG6D*mt*R6 zfU}$exdW&7ThB4M*8DxyoWC;u7v5)gvp&CWtxr?$I=N@>?zgTPWh=)_??UHt2>hGt zvG?{{94@t{XUe<6Szb4}8_6Bmp4+39GwUZw?oD!Od#>}`MyRp=@pXIL+uH)Zh43=I zi|`u0pK#yp^ot1(;im|X;^zua;u+yt{089#{7&Iz{1M?b{5j#iJnKhz2>(QQ6#rg$ z60Zr*;-l^p>mOf8co|F<`mcqD@Oy+u@yGDH9l!5<^Y@*^x4PfG{m$Zt<6GLlKm7Wu#{QvzPsUHNd*|`Z z^2_-9xZCk?4gXTO?=HqC2oK?Z3XkGr9&n$2688zu;wuO*;A;slID&_+7%2ctLm;e_nV2e@l27|5SJl|3SE~hkh~PA-wY;_w6f+FDyKX`-Nxm)rA-E z4TYESZH3qH3BrB%(Jv-EgdZzBik~4oiKm5U@vDRv@SBB~@q2~W@W+Mw?&rQ!;UWAz z;Zghxe58KA#_>PC=EMEgj*k8JwvGLFfX}k{-uPa2H|HBWH6rHIMt@$B+NyPMH(z1cq97hBUc^$(GIi(JH>8$Nw$9G^t--|#i4jzI+ceep`45UsiY&A1^$K zZzMd6M}!yfJ%pF>gN4`dC)#RvOgj-H*YQOE zi0_X#p29D}C-8TxAE$NSR1SX(-@{{b(?1hw^#_^yl*oPgbieh{n6}&-&ijV?$X)r8 z`+D~lIPVi4#P1Q_jXx$lftQ45@OOpx;GYZc#eWpuhyO0zJA;1Im))075MM-iH@>{^ z1RfNg!8Z}!gKsaq7vD>GAAYEC@1xvDEj);yCA=HINO%Iz3eVuT3Gc!07v76MCA<%R zRk-&t?xPkS#J?8ajsGG%f!Bp+@cCYG-~M{=#qn+VnK#>ubB2#iOncIcZ-Sp>_s-)Q z0por6C8B)q$lUoJd@-zdBXze{*8 zUJ%}gKQG+-6vy?#gZQVyyYU}{C-4E`8NBngk+(0ipYOpJ#(%LNcbMaWubsyoWpe*{ zz27Q2+JVO!?SLt#hM)3AzjfK-{A12|-tNo0GM*`;yUtp?ne$V?2Vd#&4W_&Zxof{> zJZ^iv4szBjLGGh(`mH}5^%`hSFM~f^?YAm+H|KrtH6rHI#(7_X+)>~5TL*dgU{3wb zdEZ{G<03y)AvbO2$jj4s9iJ}T|1`(>!o&Cr!ejW`!c%xfcn+T_yoe79ui#y?#Qfu9 zh5Mi3IA3@eA1^$HZzMd0M}+6_J%ktWgN0Y{G^Le$MaO>-Uzke!b)t zuk~B}&p98%O~3iH(SFtlJU}kkJ|8Q#mWyd0{V#AGd9dwze&;^T_BxFJjB{G)oZj8e zdd1028fv=_!z|x3ow*FT_sJd9Ufy2LT!GxYzjMFIDCcy$PH`@`3c1)H{Z^qpcaJmY zd6E70pZ(V0!nX3vb~1C}=7i094U&6w{+i`)FK-cNc~NrrEKsv*?YUXbT#DT33)ZYR z+UNKA=42b|D^G5zg=%x%FZPmqlic`D+kBYq&bGaq^;#qM_Sl-WgMGT4+cYL>+*e}1 z;^JmGgz#m@)vU4Y^EZ!k{$k`tFH*CvTTDGw;OgVABtc zmuctMu34+wb6tVv{6+Atb!*nv?dxSD=Xyzy^M`5{ry;H7X|{(4nv1isy=TeYM{aKI zQ<2<58`fOMc~$TQHmX_Yw*RhAasIA7uW&tk`V|k1r@Zf-fyRj;|^_jfaHi@vViI@ZE%0@dJf>dU?);@Bn_A@Cbgs@HjqI zcpA?M&*OIsFX4|0ui`HX_i(}Y9pM4|GvN_@mhd<}Bs`6Kj(6Yw^7uI6C44!2TYEcU z>ld!#TjM9&efGHQ#_#_v&SUY7?QXk2C4k?9@8@WT_iDDo5&Y{DYt|liH|@|4&f|>) zxdl$)IB7{HG^af??c-ugHrq#2pDel2m%1;H0=|gwGQPa<8Xgqxdz<4z;URo`;Zb}q z;Ys{Z;aU86;RXCG;br_H;Wa!f-1iRGVT6b9`-MmGr-Uc*SA}Qs4}=%+uZ5TKUxe52 zx^UmST!*>LeftaHiwlq9D+y2H>j=-{n+q@CI}0!4`wFk&apAuAcL?kh9?On3;tS$Gt`S9lVCTzD3LNq7N&Pk0&sLU;}D z6Yl$f=cfn{;qzSXzWqhF zPjftTrStqVPHyVW?%PWm&k4`tcMC7!j|#8iFADe2vHXtk0REZq2tG@A93K*%#yz*V zFP}U7YM$0KatU&mk~_`bu9^1Y=vF^zqx~cI;qC7ADd1J%W&Bs+HT-Ykz6$4Q zdH3mu@Fj&u@s))q@%4mf@hycH@NVH{e1G9J{3zkR&lu+-JcOSoJc?f~Jc-{ZJd58Y zynq*km+|L?*YLN5`#xu!i|`QsgYYOmAUuh8-r>G|W$}fD7jVDuGQPU-8or@$9~XkR z6&}JT2#?|i2~Xn33eVza2ruAi;br_P;Whkb;l3|9eit6X9~U0QUlN|g-xHq2zYt!) z`-GSAKZMutdG2)I{(N6?{4P9%|3i2bUsHGz-&A-O-$8f*j|wm2hY7FYCkXd_&GEbN z5Pq@nDE=?uN&Mf!v-ktT3wTj@8GlW94gZgD-#5Is48OXA|K{{l&VEU;pN~TL-gnhT z9G7CQ??mw@@$2p1H^&2Q&r3*=8$Z2fy*J7>9djP?YU@12l$R%0zFS|PGPz!IGw!Kb ztln0=&2&F(9fz3u*T|i4Z_Rqhp6l#sgpB*D+@FN+;P7pl9>Q1Ysaf;e>)kcFdHxl} z$KF?SzUR5~>c;m?J(KuFc+y_Jsps&cBF(46*T2ZUPi|j(u5-_3J&O4J_t&hY9QE)u z>ruhG9&rDi*YUB!{ogXqL3kJ+FFb~CBs_&jgy--*gctFHg;((7gxB#ih5Nr_{Dbf? zezouzev9xF-XlDRKOww`zbw3hzc0Lwe<|GmJ>%bmhw(p!$M7)^x^I6e+$TJTuOPgL zuO+;KZzjBs?Ld3FIl2QJ<#o1=qw~$=JnfO1^;moEzE*jroeYy(s^GqU zWB4kEBFDz>-a?B{#mru!o&Dv;W7LQ;VFEY@Ekr}coCl=yn??V zypF#u-2WqENQH;-nZjfEpzsvlHN$=T$>C##7x86-a{({eA48gop7xgvaoM zg{Sc2gy--xg%|M)gjevZUEH)Ub^I25ZugG|ej@j1&H4N_)4uHPY!AB0y+dwId%Iz~ z?>m8iCOm`B65fLk3Gc-{kGW634<9Go`!oHh!h`r4!n^T}g(vXsglF(Qh4pm~@u>axJNrj&_V+>jQv6AW&uBCPrakG# z15ebfSM6@viD#VcM3P*I+}ZZr?7{G6I$3;$Cu`Ob4nMe2i17j*$KP`JYt4F;@kO3u zys`bb$@DY-?L4onlN%`3=KlVJ-`MV-u31HUdFD9mVdrsJH@Q`xt6AUM&&SMkKXFbs zN$$Jn=`XkEOnH->xg5EzU#wXdwdc-m<;?OZk-N22v#xS1k4$rURq=5z)m-08;OS>P z4!)>|0_GfNntIREx{hboZ;;$BuhpE-Ei~(Q_Or>%yyNn zeZ6L-9DYXAv-l+Z0Eh40^aB0}K2rIno@IRXHyC$6#x{L3KOZ=s2T&*X&3hw{FE#Vw zuhCEXe$6`4QIFx5Y?$eU@qglFyPM_ldZVi5)5dXkoZPDAnsrBeZdxm6rk5d?C%2|O zXWM`F;13D!#h(%0hrc1*JHWUU;X(Xc;obOe!V|b9JcD~b5c7{OCA=43MR*^+zHsj# z=NrO<_^!gc@dJb>@QK1Rcv5%|K3RA#eueNpe423Y5a%1hgZK>L-S`W_6ZqT0Gk8UK z4?a_PFFq)|5AXVq`}XDio%0RhL3~-^-S~Ln349~r89XAq2j4?@FMhD_KKwZ0-ak0s z5FW%Y5Z;YnEj)qWB0Pil2=Bq45Z;TwEW8hYU%2;A`on|=@t=fu<9`ZI;A1{?-~KYV zPk0Z$g798^E#ZCmX2QLH(H|x}i0>`D8$Vol0zXlB22Tm^!7mZsi(f0e55HZwx6boB z@O|z3Ut52B5dU6$zZkyYZOt z1b&S041T)s9(;=MUi?boefUkny?-;#Uw9CIOn5h55}v@{6`sLA7v6*aD7+W{U3ecp z`eXO)&ueksBs_>OFT5KM3Qyph2+!c#3-7`A65fj+D!dOrUbweoRL5DugZM?lyYZ~> z1b&fGy zukZx^vG5H3o$wyKA9w2)>cuzwwB~&O!tCcY_}QoT;V0vdIri@lH~SU5o>3k1Rz|*$ ztkM60uYrGH|Gqijf1`CCZ*oy`ACX(9i+{}N|1kYKtF*>Bnp}$9mtWAI(%!#wR;z!< zZT(p$_kgoM%RhQl$C=;NtaaO` zJACUqH5=~Vh>)B7ea*_Y=PqhZ*DU`8xu1ThIp4R@bwwj&JcA!Pt7dhZg6Ax^&K;WT zrw7mA`#5~~sV9F^Zit_xQx|mA58mOb+*4{a&MD6*WMnP_V=__dt}P1lUwB%u2;0@o@wPw zyAoia*USH{SvT0H+nH^)OA&m_U)$Qru3)oWi{lf1qn)>3Kj=EQ(b$^u(|Dm)vwpMh zFS>qe>?|7XKYrowbKjrzlDpzB#{N^5#1*F$cH`3I~m?9(OUzTncP7O3|QORb6s0B*GCOM&pTl4Mw!j|oBeQg zGaa9o<8XXc`}fUsh97BTzSZd050krZ!2#<6^MP$Sb^g=2J;uq+ztDj5dI#lop3=&h z<(VOOFu9xU)17@&mhm3EvhaY_W1n8)ou+ty=5d%ukBkqDv20 z%Q~jBWOF(>eC#r9%dKtt~+3@-(KG8&hpaa>Y)K^Y5Vdr z^&8t-UZ%VrazAf4;JmNTxQ`wB8^S~QN5Z4{x5AV7Z^E;kYxpX{eZEm0 z>*Jg9TW+>Lv+s8_zwZ#ftMDj3QIwy=lftw3WZ?z;3gKmZn(!JvUAS+tQ5`dchwvAK zNAb6XC-I8#EIw0s0Us1z#=DMl-#%*iSmD0KInNdz!p94b;u{H1;t}Cld=KFT{9xf_ z{5at?{7m7#B{T8{9>s4Fp2T~EXYnV57x0&bm+|+7*YGce` z6uzwR96nxn5#LC71&;`?<9i7AFGD*cJd7VFJcgesJcVB%JcnN`yolc-yn^=#uj5Y$ z_w%6RmxYJ%_wkP%?L@hGz7WGR$pPzi`+0|HC!ThmccjU!b;f|Tx1*d1jdDyok;jj~ z-TJjl_({U6_}RieoPb{{Jb+&(Jc8$i$MJ`Rr}1Zm=kYg$m++5-SMhI!dzRyPRCoZl zghz1ineOW+jxQxVjjtj+kFPJhgl{Fhitj4ivpoA5;Q@T2@Ccq19>*sOPvchz&*RgC zm+6ye z9>F8RtM~=NJu9-G5gx#A5gx&NgvaqGgs1VBh3E12g_rOz zg;(*PgnL$^-%EG^A9I%b_7}l@!sGY~!qfO#!t?lM!b|v$!mIe+!aade9f!NP>GuoZ zC*sT7_v5DDb+}8_?6n*Hk=^8uN)1?#c=%vWzpB~a-`VPqHv97=xnIw7-`{8PRVKSH z?*hKQ@G`!Y@EX3WaNo-84}^#CiNd3JQg{-dEIf-}A-sT36JExr3$Nibg!@)ue;_=B zzb!n9SA-|=nZmR9pzs3Tb-w%dQO3s#ui?uI_i^ECyzmgdk?<%U5uU{N5T3;k7GA)Q z6JEy86kfwG5bj%z{ekchev6Bn_9BY+;E(cmvmG$kFNPm6Vm@uO7b$X^P8qQ7uwVZ& z?aDOg^|(B_$I=5MK8Mk?CnfxU!mIeU7Yw+Li}I|_xHJ42dp)|IXkLd4;QosSEH0b2 z=BI1;WhZ8SBlwt$2dt#s&3qi&nh%ppklX8$0V_AoR*q>Or;c-6Kgp7N<;DT)G-A!= z*LhO&ysBX8Gi|_mAEH^l4>pTw^uJWd-A~T#ys3^qCEP!r@sz^D_y@vc_}9Wy_%Fh9 zcwKlApD*V=e-(Uj;dOi^;r=xkPboZ%Z!SEB?<_op?<+iq$AuU1lZ99CbA;FN%Y^%b zjHeVH#_tdw!ygu&!k-nM!+V7n@sEX9@b84z@qXd{HTgl`LE)bDXs3h+@KuFJ@R0C0zP0c)zMJqoexUFYezfo^ewuL4`lC9|7aqW; z3XkA9;c@(K;c5I);d%T;;U)YX;Z^)I;hxZ_j#k}j?s>?4`-|h_gs1W4gy-=! zgqQG*g;(+IgnKp^)v>4W0Dg$@2%Zog$0yc z&U1Rm?N)GK&b|17!u#-}g?l&TcOpE9pD(-{pDH|o=Y(hQyM_1Qj|%U_UliVlza!kc z5x*1RL420*ZhT010{6^tUw;{VobVoeIpMwd8p8YVjfHzR=651Ii0>)98$U#N0#69f z;FE;+;1>$-#jg?GhuI%UVNunUgvI&^95=?R|zOS0K01vu*V; z<=yBkuR`t-a_8FXZE~~6vYC%fd7jM}ANw5Rz1wq#JIf1_+l}0|?dzxQ{<0{!W1b(d zIP7RGPct8@wbr9qt|@Y-zA)f?uV>e;jgYBV4!`5Y0c%!!IbXKQF}V`Ci7yRU6WaUd zw|8D=?;|($l>zHPzSCOI_cqs~H$19i`Bz6?kEXss{7Agu`2O(ATTMN>@jvi|+sAv4 zZjJXgnP`yMmk~{QG_wn%+yokTvUe0r^ za?JERo73O=)`0a#`*QxpxtxRK)_!NeI4_JrUr`s88&R-IL4A0xW zZTmIzmm{}+*}a@1p2UA^U++J(*1MU%D!DB_9I(3D=CAV)=W_6F!FBqN2CPhbz0Pmt zOua(n&L%g>p6g6D=P!!?2S3Q}X8zjVeWkbpu)I$d#>x^M#y*{e)tyy&iD6rUe>I)cgs;7@8Mh?YW+UU?{;ZteM02k`f|Ye z{5CUxv)`F$X4_0JMsB6A+{e+S@YC^c%ol9!c<0B?<(((D?$-m>(e_;D5zTs+@JaY4 z_W3sb%0cJy=_7Y(b--HAp6gnwxqQ4^alg`c10%k-&1^?O`~&=~_T_VubNNKct@^`& z^}WYAUtOO$_fIKu-}OLU;@h2v6bb3eVwN2ruHh2(RG#39sWv3ioe6s^b*l zVf!QNL_(j5Fcvg4{zfE`!zh8I}e@b`-e^q!L|3J9Eo9m*& z!}u@4V|ZP73ZL(H_w6r-FD|@@uOz&JuOqyUZ!X-wEB#u+!}z|!V|ZM63O`wR4nIeD z5x-1$1;1W+9lt}ke>bj+3J>GY3XkEv!c+Li!gKg{!i#vn@Cx4Xhx_(b#}^dt-<|8C z!o&Eg!ee+ycnaTIcn;r9co9EPcm+RNcpX1YxPJoIdxVGaslsD;PIwBxTX+tCRCp18 zQFsM^M|d6oOt^m!uJ;HJ<3qw@xaUvz?JtFo6Q0AD6JEsE5MIGI7GB4<6Yk%W>pjB5 z_#wh$ctUszpCmkoUnsnYUn9JN-zvP0-zVI^7uS1)hw)d0$MCZ76#kX)9R9QLBL0`~ z3O?^&16JIAp4@pz<0RRfAJ_42d>woLTh|(m&OGD(D97)0#_2nJLes%v29>aGLp2GJN zp2Lq6Uc^rkUct{5UdJ=S{rhl!ETizQXuI!ejU{!c+Ka!gKfr!i)Ge!Ylah!s~cUxPL#+&xMEa)A94|zwgeoo9#;s z|44j4g?}qNhyNzLh+D!dxVK}_wSB4MO9}Vy&wWV3!}$8bWB69WQ~0jJbNB(mi}*z0 z6+9`tj!zcuKY;s?gop8I!ejV!;VFEE@Erbv@FM=U@CsfLUdLw&_aDf0BjI7ZYn1!; z6~o60PvOf7&*9^R7x9gRSMZ4NI=+W+e~jx!_^yuM_m0iqcNo76AL%)Qjq9KI6Znpf z?{C}qzUl8z;a}lBcBj9;b9iWp`E>aDAGsqt2Q6M-)4G1p`QK(aC4AGa!MVTxlU$PA zCH8X6b=z|rMVU_<)AJofzX&-U&k4`scMC7zj|wm2FAA^W?+EuDPQQro5I#$I6dw|v#69!4Z+}^Q zobUp^obWQfhVUA`v2foJ^os}&;d=^?;)e)N;tAnde3I}2exdL(evR-Neyea_oPH7E zA^b_1Q^LHQhHb9_-Dx6ZtS)}8ip%>F*t+TWX; z=SZ%zkaL{JnB1ApT#($n^9@>8x0iQuD`$>-qU25?7q#bRzem(eFNxoYe`0qty?31D zwo^p+W0@ z^Tj#i(K_#LRLaa(5I=L_L5tT$+x)wRoBDL)+m7Wp%|5=2`gHy19EX-9H+Ip%5#MuQ z%E{tk{B8Sm%zVA%Ts}o|-;le>p6k56S>FnNsBh%;VCJWeXYsQg-ydG-rXK!@Jf{M` z((a}n7q;qQauIU-FE(gRZ_nM_%9-gU$bC$1r1zAXax(bNiw|1Mw5`vsanA8|1#+7& zF=&0&p8L?5tB@O9a?lF4ua6a5>%&afb2Q_VmL9aGv~M4iTHA-o1>q>9`{m7cFsfBQvpiDdo?BsX#BspJb9iFKL5tUR+P1e}n(McSZ?)3kh~rSr z_bd1f!t3~NIIn@XmH%zCeE%_w9}Wy!w>f;c@i5CHjBmd3pmlru^0>jdJmTaYUv<#p z^@FYHnC<9i=k}2yckyb2&hhHAUoLCrrw9KYf81V9=OfMf_TuNRK4{(N@aawO!@c82 zb~8WTV_9B!qE)Vbb5?vw&~9cH43=%kzHc@~n`1om`Kjo_96sY09bN`>Z?Yyzjx3vs0@alM5Wj{E$1H zznkr%$t7AjGhf~0-X=HF`LZb|f!A@z_GHSr&RI^D+-d9aJF`!(b9kJ7WB&2c>knFE z?DJ*H`CqFXldF)cl4G^E>TSl;#aipr4zD93%9T#(!)mcnSYr zconY+_nb&S{}%4sPXJ#?cm!WYcpP6%cpBe8cpl$IcnRNKcomNc_nbsOzwiKly6^}- zMR**)Qg|A_33uCXeA%%HWl{kWNSrEBHZakFU$!sNC( zR$TwWPrxs9OlNYVF)`Cg;bpvRchi2o-fC}5E>G^fxz99>b3pp2E)(p2IH^ zUc|G)EBI}~>-hb`{VDD*5FW-~6&}Ms5T3%n7M{a@5njaW!YlZE=euuzb$oH*{g)SPj_A_6Yv%j4EkcGzn58oa?)b3_F z`?RKGa-Q=TPeIP{zDjak+qUih$lZR)pcS^4H~c!v#{Rn-e-=--?|05>?ROgUPi~pZ z2j}|!pd7h}t{${5vQMw`{N{eHh%b2!{k!ec`*&-4W_?u2<*s$#&OMWP?gKv3bs6*h z0KV;YgVsZidh|5w5y8v&s_n-kw)dr)auVd;zkbm5ISv_onHvVJ$@b}(^)-7Ln~%-% zE09b6KXMgvZ<4#Ty}a|<*8llD*W|`QYvcC%ujM?R3XU#>f3x~6!#R-UtD&2)Rn`R*OGZZ;E`vs_JiS!a1=a+m%;a&>YYJ@j+6ulLJZ z>%Fo4r#X(fZ{*{9;}QIQJYuic>@jtw-f?^ge|0Haz0LOU)Kblgn_Pz6b+6FxW3P|N zed(-Efn4l0uG`sjUEelBrkpaq${T~$5B%*|PMYG7par^YT#x*8p>Knvg{&vvXj=!7RRp(ZXnK#~z|A_nS)9G5c zF%jbl{EP1ft$#Yce|q!#8GO_42d$kQzFpIM@VM|^{0jUC$M+9ze!mZY7a!?(&D76( zF~^%fw2hDL9A3GN`NyBb9nXiF-Iz7z9}mtPv^KL(e|Yv9$1@3h2i&dSG=oQl_uz*K z@5N6L-iQBFxc3sSzY7oI{}SGf|66zhe?WK!FADF$UlZPo|3`Qq{*7?&rQDAtJc$2K zcsD-(Ecf-Bz?Tr7!2`m3@O6dv;#&ys!*>zxy^QNC!h`sc!n^TPgeUNGg=g@L@E-gI z;l22s!u#+?gnKjmzFpk3qe1*l{FHh4$DHF2v)?&#o<RJcmyfUc|2u zUcsjcujA8&`>$Y}kMJ=5g76srw(t~Q5uU?m3NPY=!Yg=J&3*f-<70*Ur*eOe@Gw4J zcnsf2cnXgQ&*6IrFX9Iaui(cCuj6M5_g`tAv*o`0!uZv=<9c-GrOo4w7(Qyi{rf3= zA>lcE8R12IHQ^O}1L1Xi8{z(|7*`=YjK_q>@MDCh@Y99o@F~KJ_?5yd_)Ws=_&vh? zSMz)$;bFWaJchq3JcWNQJcs`%yomoUyn>G&bl?8!_#(pn*Kqwoco+`~kKvmLPvP4O z&*6IsFXD#^ui(cEuj6M4_h-5OAUup`g~#yQgs1TPh3D|6gctEwg;($ogxB$}h5P9k z`9*jbuM3ai^9{Lge<^%%;W>OI;YEBM;T3#y;dOjx;r?qm9~2(Oc1Jb~{jJcAz~ya%5sycbUj@53hx_uk0)gzz9f zO?WpxU3dbYAv}Y>AiM{ETX-*C5#EQ-6z-kI`GoKw-sN%MKDzO-!V~zi!ZY}I;XU|9 z!h7+E@IHJG;ocnQ6T*Y|al*UtGleJc3xsFztA+RAx45`zM|$xdd^LM}GkhJTIkL&* zY9=>&$Xd|eKVjOXu2#RY$@y>MzJoDC)~WXPf?VhDP#g1UqhB*Zu0n2md#-cqW;+5r?fw54<$@I1bq@DjeK z@G5?YaL+B=XC^#=PZA!%FBBffuMwWcZxx=$?-O3apA=rjUlH!PmFw5S1Nc|MBlyq4 z~~)A+oLxNjeMd@#6qT@ldN>HS>`o*T3YD^-6nrPdm%Yle>DUA?JOe zWj=dBaV$`Lt2L8o4!>9zOP%%e=egdn%#g)p17~isGZ!IO z_s@MfC&=xy?2xrW`+j!`=YBU!ZujMftbqMGIP=@JwDUT6k=!mT4$bxbK2>r*k=wF; zJ~n90huQADcko<_z{uwpW_<AYd+2LN|XEF8bj8*{M}rxoxP1p8PDVQ2ZyW|96tObFPZfU-cieYm=KDM6e0%TW`tMrQ*FGKF_3I#hJMK6h>^z}Sh*>V(_#pm`{rhG* zZSV6*l6z?FA=hzWS^N+Dv-aioervgz=@rS{zwVIp`2}WrZTF2;$#tzaWL@4~ui;aD z^J$}9@J{EsIOKk7|K0u2`rVo39U`~hhVJ|8D88leB;GANi|;SIfFC8ijGrpJhMyR|m9>vcPp2X9_v-nlQ3;4~#%lN%6ZrY6+{y5&> z-oDIqwlDr3u0L%uWX<2+9&|X{g9y1J!$Z~srXiVgoYi?xv;B_aHQep^F^#XW`H(eV z`+m-H)~AP@cgrE?^NMNjx>j-K%H(`o4OzkV`CGA-GwoQN+>%=ljW}-6xc@%R3vj=^ zoUSDrg%}Ux8*k(O{TLp@9pmLXFKI596#lx4oAs14UE#TWbY`9@W4capj^ps(KdR%I?jh?h`}~{b z{i}01M#x>Yn|pf@$8Q#%#_tuL#~&A7!e0_z#orU|d4O?w!UK4p@Cg2g@Hjrt?(WMc zjV~%ZkN-n>313rq72j02=RwBh2@l{=;Su~W;c@%~;c5Jz!t?mW!b|wSgjex@3->(4 zxIEzjyeK?^za~76|3`Ql|3-Ko|F7^8{y*VWeEtdU+n?uQ#%l==-~r(gd|lyjd<)@e zd>7$)d_UnO{7B(d{1oAyM;MnUJb-6}NAMej$MHLbr}0OG=ke!+m+&`*SMg7TdkS0^ z6CS{8!Xx;oJ>0jiIKGhZG`@`RJieOn625`(D!z?y&kXt-ga`1L@Cbg4@Hl?D@H9R} zcpksf#m#X-3BL*F@?Pus%j~D8I``9kYl4QQ=YiMd3;O9pPF0GvNh%mhdt@B)o=u_Hp0-d{6NF zS>YjkIpI-!4dF?AW8qnRJK+USp5%If_27+!_ZCS!*v$L38?_%yG+#3pXola((31JC^Hr?fqFVwED9e^ZzX8YsU{+JGW1F zE9Z2>+fxp2oiup2z!zm++2L+?Q_^Ur@N`d5$NA2k=#eNAQsFIKH*;G`^egJbs|? z5`MJsDt?-9&kGz+3J>5@g-7t5@Hl?A@HGCY@I3ya@Dl!x@GAb9aL58-iqP2p*LQ{j1h2jL|= zD!hsxCfxH1{nNq&_&B5?Sc87_mDf~{Gk!w2VuMy zzYO2YUQX9;jY5p~;m=GNvN-*3wI^KE$a=PYerGuA7kG{K?TWVXCuTk#cjmgu%_28% zTm3r!cIJ}gUZ2W1sJ7hfON*v9!_R*r_u`fAzsn;2j_?ZpneaM3OSu1a_Itv^xaTVO z`o-{Z!c+Ki!gKfq# zeZuSblfwPIj2jjn#>>KE_*cSH_|L*~_+P?{_`FxUZ+{hhG2wN5MdAK88D}ayjE9BC z@SX6Ho)>D`pA`N+zF~Vi5OlU@d2(M}Gh`iU&kf(#u>YK-DX*8@a{n5#t}_oRvmY;B zI{a=8K5ew$HFB44|GRu%x7lC#-{QK*4!^tJ4;99b5gx-&7oNhW2>-wK?gmV%`TrmP zn4Kbx+>MY$7`YosR>V>mMUC9F%FWP?>5i$WX_1v^q%;v$?iQsfWZbVpi(;f0_glzH zYAiAoR`!nhKi_j+XXc#q?L7PZe%JSVeSiP!GS^kFo!8@a-sgR8=FFM*nVTy39O5obgBoZFba&{*dT;mKb)Nw_- zgrKsy^O+>-E*RKo{+zq2n`=J)WKg#Xb#~uB=l%loBkqH5Bp!foAs&Xe5|6>#mD%?% z0q;mW1wV{<2HuUh`%8RZ1aTj{AMpTuF!3-vL_7w+j(7q-g?I`+i+Be9AaVCsxK2Xc z2Y-op0R9&7Fg!&(2LFn90$xu%1^Q}4U6cOSeH@c{e?;$e6R@fiFJ z;tBWw_(PrxrGo`Mf2o`H`i?p}}cPvSoK zOyU9fT;gH)0^%|F3&a!fH;AX;?-S3!zaZ}Z7U!Sv^G%QMe)-3@55D)MjobZRfAu;k z0Ph92J3k7;AA`SUJ@0wmeBM)uy5lZy%wl-fe17y+p-#=O26dkV8?*gQ{q2+QZyme^ z?lHC_-$$&@!&>26u4ts+m#*r(8?arkY|OSXwxiCkT5_{ebI+ZJ1yDC}NMrU*l`y{E ztTxw0P}go~;|_n1tqOIgp{|Yb{Tk{zL!)^dKZ&|dS2bqc#_@htXZie426g|08tMC6 z)$)42!?@kZM)UUwspYLOFGnfro+)KDe=dZ&dekko);()(FNV5FqZ+eUS=Mt= zew0sJ&()}VVRU2mHf!Ath5bVRy}B{`xN*H;Ig0KttUt9Mxi;ecT;ay-6l4FK zH|9E*+y3xx;T?>h8&d7K3ZECs?fBT2 z{|G+b)X%H){Y=3RjNtWxb-g@PSTCv{4XAr?lKu05XA{l?iI>1%B3=f6i+BW{B3=pq zig-1=o_H<%58@4QM>$#kG|mHwm%uv_FM}UJJOVEvUI{;gcr|}s z{5Ilc@Vkje;8nyc;ZGBo_bt2BwhmFOuP*K7x4((b-n%m zR|(&fcs2YWxZUSTYvC8er&*5!Hx`Zq>bTa5x)*L}+~N0;cz?io?TwAL-$&wyH^DzP z9+%Yf#k=O?dl+@|CO2l|*1Ctyb(N?qz6r;7Yn|nLOKMP8j=CMqH;uXjD;jtBJtOWP z@i{ltna*F-a#+4+qy%+)-`u#v?->cAZZPV0wQdK8c{@Z=*KHsQYLJU(f3K!uu0Ge>Af(d#iDK z$jN|mKYS+qRg=G*e_jf~54p23yV!Uhqn`CZ>y)IEv1D(mv!TUdTIzgE;8FlYPArPgEdX1pGNvvyRSA9Y*rX*7R7hw7K% z{Sj(@VbtAuZ)0{i{?4Bt%8&J`c4F`pe4TYa_{6*)RHJUn{f#^PzLPrCT{^dMhu?SN z`Wde)PW?df*WIYQ+1QTSeunQ6 zQSe*X!427HszRXf)2KSAADk2Tu9@4FH{3*ODR+-RrB@;Uz+)ZO>E zW%+PCaBj-20@aJ$>yk9;E}z%9JDCL|2$U#_Ytpx_at5e??b!}K9G1Td?@kaUvYhvcqx1`@gV#T;uY{p;#KhZ#B1Qs z5wC+UBi;&MMZ9NJtgl{2U0dFN<1#h>=e*dX~cO+g1Ka6-Qyc_Z2t$6)S zycFJ#co06Acm+H}yb69D@f!FP;&t#@#9QGH+PHe07ypLiFZ^BWaeA5gIPFK>nNQnq zrx5&n;!${zcpN^4coJStJPn^l-1R%&XG7czf0Vc%zL!ut?U!v_*~HQ;%GxEDT_xF0^5 zcnE$6@hH5KcpN^TcoO~`@icrHao3-C9)Jhc34=avY4|-?FWmLa_OC0cVo^_>(qHxCF&0U#D0IPhIc1k3-3j|0UjXk*@p9G z;wA8r#LM6liAUg5iC4mB6R(CpOuQEUB=H7#HF3{h`2IEGCGd}km%+a#9)bTzyb}H= z@oKp9Q~Uj+7QQ?226!=XPa{4rM7#vvgLoPIEaDOP1;i`iR}im;UroFgem(I9c$B!O z37;1tUIKrNcp3Z|;t}|(#4F+N60e4TM!XjOE%63;hPbC0<5|Q@;B7y%-~YL#3S$-#4F+V6R(CpLA)0JJn;s2 z4RKE^zR!wy34AT_GWaIq5%^Z(mGHlbSHpMx+B9N^Ir(wX26!4i%R0_?Yhj#Lorf3iW%Xcq~)2ljH8>eH% zy2dPq2@1yxb-iJ8;dr3xe5jjU*OPc7vl@byAUshp8&Ue|78$VUfW1Vws{(L409|`}|=&GIf3hk)*Wl*>KrX9bp(X*@5 zF?I)a>iAWPx(`ryj&Z)uv-154!vBB|GP>%Q_R&I>%`IOPb%&(ww^JP6m3R_z3}10{qXU`L+}dXQTR;aarj)~N%#WdY4{7oU3lZ{8^pcv_lf)AUl0$$ z)5N3j--yTI{}4~Y+kbDr|D@sj5qIH-01qebg?A_JhxZ~Lf(M94;g=GR!$%TN!Y2|> z!>1B=b-;NIaWDK~8&}5_Km1AfP3i%yUq4ZgbM37tDw}&BMi_O?s58CKSk-B7waL}x zu79BJf_nSySq;B}crE;D;tlZYiFWf1qyVANKoM z68<^yG<*Yb*8xt)FT}m@X5xPM&JFhc3&B0aqwqtB$KhRxC*h|OPs7h4?kdLk2XQZa zIB`FGJn;~`f_M}@lXx6Hmv|DsfOs1I0&&-Y82=#dg}+bS5C4LA2%aV$h5tr84*!RE z65jq#`~5Es-;cQKAdG(y_rkjq_rrS;55WV(qwq_K$KfN1C*c!`r{PnHyAHfxsSd+!~p_-=uJwLq{ zp4h1=8!^p)e186ZxWmd|^9#Zk!>1YhquMDq zFINd@tfj_`$@}a368k;Z8?S;$Cm_;bYl@MXk9@Kwa4@HNEa@QuWi@GZpC@K)lkBb<(QN80ayUU*01 ze)wU;L-20Iqwv#+$Km~mC*gyMr{N*ut|Og}>xg^dQ*2y4&i(LN@TZK&KXqJrEO!W0 zM~B?&xG?J4AKjF_R3-Aqi?aOlL=5hSUt#h~@}7X-3O8L(c3znG6nrWCGSl=I=RE`e z4L-)?p`5Gba36*7(qo#k8;!26PkosyQQ6#etP<2Upw9HZBDK7Gncr6wMBR^Fo3hVY z+lv?4%RT?0ZrpKA*-B%b^X`1V4bFo};n9p4ODT&e)!+3+b(C+p`pPH~O2hf13KeHQ(pA!QkGe0;Z8Cqp+c_gYpETUx zuW7sAE2QS*ItJr}@Ddm9=<81{?-AzbDIe;l3~0(Wnflw1n~!QI03UpQQ}$`=^JZ1y zc~jLzQ1|79P1#3`?Wq0io?KHZn|r)ep|1Z$O}4+ERs&xRUukT|xgx*Zb@1^6o3fit z{(atC;XTXjk9);FJns=Ng%2bigbyWN0Ut}e3O<>54g3z`b?{2!t?>E8i;umn8;RGzw-B#`w-RrKx4W2Z|E_r6BVGzWjCc^$F3K%I1zY?ru&;9qOu$bO;xYIG#1rs1 z@f7?;;u-jx#NEf^{cOa2@Gpr6;NKGu!+$3pgJ+2+;Op^ig*D23h^-fZQ?Qb$HWux zI^rq#Pd2WO0~z=>_-n?;w>n;E4{?>v9S1xmcwW5}uiK4v&cgRlmB2T{P2)kTo%My| zjyf+3qHghJP1#|lc7nMg)t?IZ&+v`L@d$O^wZ=Ri5l7v^VNKarjptREU(s`g^QzqV z2kK4?VVuP@KkY|rm1p3u!MAt5s`}$T5&Or8rtC-UamRQbxT1Z2!BjgXs4KayDSJEq z&eu7o=9jAs{t)~=<8rC~&NMGq1?pTkG-cm*8QRf)*Jp`-=BfG>N8Mu;P4stya?6jp z#Le4({iNE-z<+`lS^L#gIR97eczWQv-!#k*f9ID^-pi-jDS@wpce1v#hk5yes7uXk z%2rvo+r5SDrrL|5u6L{{yTw}feW6bED}lP5? zZ9Og}&Bvt%)OC8eDZ9II97G+T+nA4o#i!!^Esr;4Czyn8C|WfD{>{O)!evP z0Cj&o-L%8^T}Dv1&ofQgYfb&RCf}b*_z3tN#`zW9mhVqBJe7c3zi(%9;rn*fa@V2m znAdQ<#5A8wem<@6R`~Y5&rnTYd>Y;#^m@~FzZX(@Df}t;@y7PUx#n~0BM5&DzR;GS%KkO*{NtQw8cOK5ojs zV_L2^bMsX5tAZc=3HD3tdBIVI^8!_uMBUM!HJLxZsm>#RFz=rk)NT8`DSMc4d#JjO zh3%o*^YlXhziP@}XkE^}=JrZa*Xe7FI~vtmX^y%6ed`K~E@h6|1B>sQUUL_f>Z z)^7}T4}Ra2{SsyQI<)8fD8CtU+o2kD=hQc4hZx&a^S!vxp4xBf)Oa1YizIoT}889u{P7% z7QLhnd}{qhP`778Q+97_|J#}SUxm8XznZdF8P{*omARFx+Npu}`UlSk9n9;iXl#f4 z3R87y)ZOK7-r?^qxX-};)}cAu&$zzS`si)m?j@)@WB2ClL)N;x3w3J!2T}LZ9?iDb zH7nq65wC)$h}XcsB3=itC*BJGgLv_o*x-BG_rDar8}T5#6Y&c85yY$DCB$psXArN0 z4Imqhj_6cpJOLp3jc<9 z5Wbms1^h4KRdCl{_WNHAd{5$a@PmlA!jBGLyA&SWyV?A? zTW2bF?8!a;;k$X7xBIzWgyq0QOjjCE?hhnwqC zs9Sk>Gactv?KPloOqb^DySo{dL(TWq-AvCL#eMPlos#D4Z79ocAI#TzL%uBceC$Wv zP}G^8XH|Q96}E%g-eJ@YKCwA_ma#o;SS@!RAA?VZZ|`>v)bt7Xi}3lz^;)D|T=c%{^soS#`8Ya?e)wg?L-0|=qwomv zIQ&-PN%&pF)9^=#yZYgE3~?{~72n+lZ&(Md#b^U#|X6 z#~#GJ@B@ka;YSk>!A~L{h5L!e;TIB5!mqS(^*B$%uYt#m&lBo#evA3|(rj-@ZQhZo~udPQ=6TBZ$Y~CBzf(Gl-|)1BhqfmlJoN zkMn)vKKLZ!0r+ji!|=O_$KX}O6Y!^rr{GJ7XW;J;cVB?>ed0d&H^c+*&BVj-zlg`+ zu7URZUjn`-@f7?Z;u-ic#N8L-e4n@vem3y{{37CE_z>bTc$jzsek1V|d^+(A{66CD zi=2*m#C`B*i3i}X6A#1RBOZg-5>LRtBc6i)N<0H^A?_ZC?<*^_-~W8@eTWC(hY}CN zk0Ty~ml99F&xN0e=k)yRk!!WrBI-On1;3Jb20jsfrg8e43)8#H@OgUpDMpvy{!;Dx z;Lnrx1MnpAF#IdhehmHxnLYvETD4t|1h{fsND zzX1GJ(ta2|7jF0a^D+1W;tBW*#8dD$h-cvM6L$~7^;P0Nc$#6*2 z>n8!>tE^@Br}u{8Hj!_(LVZB%Xmg2ixyo?o07GM&dqrG5ieU<6nLgSREe& z@YCRS<2PY=1a5lYl>Atknmz_Ey~MtM3HZ6hQ}98=Gw`d3yD!80JBj;aL zzQQ=pqQ-#1pHCrDfnXI8TeA-?yKF!zz-(w4&ih1#C`Cd!~^g?#KZ7`#AEQG#1rtb#8dFe#53?a zh`UGN^Mb^E@cG08@aJq?J@1F%%izyj&kq(B&JWb%yb^V14sYJ>=P#63!xs{-h3|4z zbG8Mw`QwUnTW+92^`im43BJ+j>bkb!bIxi$#Ut@}3t8R|RdjZ)v#Om^_I`1s~*o$>u( z>N?iP=J(sxqHbV$bM`3fb?xH9b#2vNE9%N_Y0mCr?SFf7|GlGdo-h^TKE}Et?ftQ8 zJ^A5fx7t50L-1k5qwsOWycLfj9J5f8y1A|8b=A|8joOgsr+PCO0&khtp_e4dH87ybirKfHl>2)@%a`~52l z??5~bKY(}=ekAcU{6yleFrIISd*SC3_rrt4L+~-gqwsR#ariXiN%$P%Y51eWU1M?H zNZbowO56`m5)Z*YB_4&ZCmx6YOgss1B%X%1iQ4afu5mbTB<_VDOxzFm5f8z85|6_B z5RbzL5>LX15>La&5_gTqc_VQz{0`!NcqQ==d_M6g{5j%r_%h;2_$uOQ_!{D_Yw#QpGA;vsmu+wJ$iD7+)_IQ%f;Nq9HnY4~ZxUDx4#OT@kK!NmRW5b+TFI^t3I z6ykCCEaFM{gT&MDg~VMG@V+JDUie$Y{qPj=5d16RQFuM^IQ$RdNw{OW{r;7P??&7; z5#x-+z3?N5`{5cSSJHNZbp*o46ldMLYz5ns^kx zgm@hO4)G-X6XI$3H^g0&FwRKa3;&C_AMU!te*X)>_aq*LA4EJ3KZbY`elqbi{A}W` za=dSexEDTzxE~%S9)jOUJPMyqJPyB)coII3cpCmJao6>D-x6^z{5|4+crEb|{5#@N z_^-s{@D}1p_%1W-_rElJAL6bX@V+JDUifju{qR!aA^5q(qwqn*pLD*Q5QI~SPSiJ)%mtmf==%sW5c=e#vPK3NI>9A09)E;1nhInqPa zRS|Xlqy}~0&c^jt&`)jB^q9!IQ)T@K1?{;p>UV;6D>jz#ECD;BBhx_rDB$FXHZ7G0sKY2lo*V zz38&~HcG59jL>30Fu zb;&jP%YfSVU!ZQnqs`{u2UK-;73$RUc^&FDqR#I5ycNEMc=0rhYY{Jnw|mUK{UE#} z@e251#H--lh}XbRBVGsZN4yn2n0Rp%<66W^;nxul!lw|gfX^ac1%Hru4SXT-I`~V( zTj6gJFTNe)TEt7?Ul9+&>xoyu{~%rkcRX&tf7QTuBVGsZM7$M#1o7hO7}p|R3O|E* z5I%r-1^ja2Rq)ZoYv7ZJ*THWi-U`2)c<~(=*CJjDf0}p@zJz!M{2k&|@K1=>z`r40 z2j5J*75*3T;u#p%nrFZNmBRNV9)ur6yaIj<@hbSq#B1PZ6R(3`M7$L~gn02xjB61u zh2Ka#2%k>80)8LyD)>C&HSlMN*TG*W-U@$@c=4SW*CJjD|BiSN{wwhccnk3=_%8G9 z_rDtWKE&(bhZ1jvA4j}+7RI%Rm%`5_9)u4fUID*~coqCw;x+J_iPypJB;E>tfOv5X z<66W^;V%*o!rvrb0snw_75q!$HSq6=*TH`$-U`nWFP@FhV?1HM|CPe`Cmw`%AzlGL zfp`_XH}M+ydBp4Bml1D;kFs%fK3;qmK92$a7=P!->C}1lyXNz3Kk5!x(41XhtaCn= zD^lm-A^2l(yYuiU{2AhL_^ZT|@OO!);hzzA-HmZX;$C=$xF6m`JOpnWC(94tn|K`F znRpU@Eb%n_6ymNq_#JTKUU(UCKYSSR5PTf*DEubkarg}4N%;N5)9@#VyY9ibFL5ut zhPWTTns^AlmUtAtiFh2om3R{VH}N!l*M;``pX*+X`x5uUy~O?S=uKl~x$A^0NVQTWTm#Lp%-NNZj=h#({}@;jP5|@ODqx?|&h9N8(ZVVZ`I`Zp4%D(}<_x{fN6B#yBu> zFFZut55JCh2tI{)6h4c19R48jBzz(9H2fvvu17EqOxz1k5%Ks*Y+oOm2Qns^dEiFg`*8*$g87zZZq zg;x>x!=JWs^*TBPUjjG%-hp}@J+kmRI(PjGb^oBQ-1xp1)D?vbp95BP)u;<3EbpID z?a6nMsF&fn>tCo_j5@p5-L3GY#ET!p^FHxX_@~5!@b$zi;6D?uf;SScfwy_qe);O) zdl7GiA56UXaXjx6FNOCc9)$NHUI8CSyb3;)cny3k@jCcq;;ryIh!@Yp^FHxX_z|7?e7|@N{5$wSlMl#`yVb!x&u{13#R&dl9}LkGK!si+BJYARdNa zN<0Q1Njw3cNIV6fN<0IfP2Bw?z8{ac5B?r{ikkKKS*-1Mn#E zF#I0kG5BM|6YytI_WAL@a6Yx#MQ}C_CGw{EOyPw5%vZeO>pAWt-@c`UQJPbdccnp3z@dUg-@f7?L z;u-h|;_l~gos75-ehcvcJVrbWe~5StzKD1N{xb0td^zz9{6peyyuevU+z0=GcmUo& zJPhCIRr~!b2Jb*T0Y89v3VtN<4E#jm?iX;KjJOYeKJfrNNIVQ5Lp%mAC!T;$Bc6iK zA)bLhO5FV-#><)Mh5O&)|_2pbTw|8FptA}UdDcex^dRJkh!iDb!-2Fx)AD$Yj)gT z40Xf*gSu+eJ%zfMwSTu2`j;F3MVcj^@Mn$gd@5I#r{V9J z{Oz2p^;rrZ{AP3Z6{D;5`Anf7sxE}OH0mC-)>%HU5kpSrukf#pHBv! zf!}9zwcci$*PCZ4_Uo^kvn#FNGx(bMdj?BU_vd%m|6OQMAD>nIe#-niwjtErR&V)U z=%Sk3Mo`NYg&+1KexK3UFK0Br{^IZ${1xN+DS9Eda@6`u!Vk$bXV(~~SIhN*dATyE z`v`Rn);jH{q*XTe`6|z=7zg>KIeUzkPw5QhR5BujAMAcQJF1A}sc7b*K%r$SHI@Im# zY02J#Y4Y1gtrz)C6O~r$-}M@PHwAS+sf4~Ao$37g_rj0Zr^Woeokfdtomc(w!D`Yu$Jr~>v{;7*Fz=hR(o5r)Aq2mSH6d7J=CDidm`$r?OA@0 zJB_+qdSJfB{YS0;K;iMFmc#uzK2OlIB|8j%=huT;UxV|r&Fvp0sH;a^#9DWCp-!#W zAnLlG(vsa|taGl<6{-1E!2g7=HTFxbx7Fr;#ZkB5^p-4!ZwviWbq|>LvlQwMKBFaj zkac}{3hP((s{wWUoY|6n#MH03`F?qpVZVkiHM&|4&zhI76mpHBrm4DVxHF11}s3(KY2iKFh$vs=u+H(gYjTPWp8cv0UL+v~h(_#VVvHTc~e z;$HaC#QpG-h=<^Q;!*g8#N+TQi6`OL5KqHzAntm@>A0P^7k)2sKm2jxA$Wp#6#g3V zID94XB>Z#YY4`@>t~YUAjJOxxOxzFO`5gQGF9i1xkHQZj9*1`&o`j!DJPkjGxa%!k z7bEV44=3)2k0&02R}hcFXA+OY=MqoC7Z6XwUm)&Uj_YE?z3}&m`{7>@55d#KqwwE| z$Kn4FPr}=uYrp@c;rkJHt-y6L;$C=n;(mB9;vsl|cocpq@i=@W@g#gA@icrYao5{8 z|0nK+KTO;Yf0B3zUQIj-UqL($|A=@J{x$J5{72%hcW@p;+zWU1v){k`@ZE`r;KjtF z@S}*w;XQ~a;b##~!!IE2O5(a0aWDL8;(qw`#6$2X@hJQr;&J$6#FOx6h^OJN5_i3e z>te*c@Xv_*;olMu!8638@FwDMc-#K=`(F~iH}N#QGjZ2STo)tmg`Yy)5ARDn1TP~V zg%2YhhmRwkgx^Fw4WB{W^&YN^5%te*c@LdD;`=1}aFYyrEOFRlco_HL7I`JgDKk+pD65_7a7#An*g-;;vhu=ax1dkDq z!XF|Yhc6&^**kP5%Bzz$8G<+y= z*GISxLfi|VOxzE@gLnvDY2#`fFbba!|HwE_rpDWnh4D63mq1c?0~w3tF=G8pqv=X6FXo)Ob@V;l5I4OHx~VoAD0Wl-?*eD+Z)Z~+qp^WtLjGu{2RF4`?ss$dtBO*4H&0)_RTe* zrmumQ!rwCa>p54;Q3wAT{*m8B@}usGVJ+F! zrgpTQMtL2)?eLcDT_)Eq_Ne76K_4~p?zg2scsOyQkI%B_7-Dl>y8r1!Qy3eis zTW#)N8g&m|+mhYtLWBD8Ozr2J%*Qi#EuJSPwPa5*&R4FLsr|wSpA5Hqe@g)V0KAuR z`pH_K)%0Qb68QG6Yb%ezSHbN*ualZXf4=fHa!r;ik-55tGSZI>TD5pK8s6Y$w^yX8y47ZA_DUnBE( zuf_K0BXPV!JFaZjIQ>}khY8}t?J59*ZcaG>_ltb7;{|(>Sm$t8f)D! zb6p&DAE9ovwN86$h|1=+ZwhrCZfMDlG}bw_##FyD@G|&4#^-(YIEb3Bw|Tz6^Y-Kx z^Y@__U6y-Lsr|GB-g=YeI&RU0c`t)^zuA62j=*~nuY?DPSHmwQUJD;dya7IuxaUiZ z7ZWdm&n8|5f0%d#{v`2Acs22A_zL2+@Q;W$z`rK$`3mF3#7p3R5-)>0r;zOr-<^0R zyqI`3{3znJ@E*h);Aau{tiyOQ@e=qI#LM7U6OX{JCteAU60e5eL%bIL81V-9GsHb# zW4xGn3H)8+W$@34N8sNQuY_laSHqi#*TUQ0V!!`2!1pHZsl#|N@e=s4#LM8P5Rbt7 z60d}p5wC_1BVG$1N4x=k6LHTs7%wJX0>7Vl8T<+25%}}OE8#W7tKqAO*TUBlZ-8$i z?pcrVV&Wz6zloQ@cb#g#|3%>Y60d}NiC4pqCteFbop=MhKXK2u7%wJX0v|!V3_gK) z1bz$gN_dQTHT)ssweUs68{jV!_iVs;G4T@khs4X^>xf6-KM=2kHxRFe?{usE{#6U_ zK)eBd0CCTE7%wJX0zZ*>8T?G*5%~GUE8#)n)$lRIYvJX@8{pH3dp2Ucn0N{NQQ~Fr z#l$16KU0$)SC z48DII=McnfP#>@41OE&2>fp1mGCO! z)$pf@*TR<&Z-Bo;+_M?KJ3+hz{tfXm_-5h}_+P{;;jY{5_rGfRp2Tb62N7?8A4A;p zGd}M`yaawW@iO>D#3S$_#4F)p;??jQiPyrX6K{auN8FRa?@kaefj>*U4E{Rt2>d37BVGo-jCce-ig+bFLcAJ&EAd+R zUBnyUj}Z6#hR;_MFM+>8ybS&}@d*55;+60^;??kKz~{w?m%x7^UIuR_9)a&X(|-S}gnNir!w(@|3-3z20e&iR&!4!C zPrL+vv5k9heYgxh8m>ORtKU>UjQmjKch{5u#(&qqziZ&%HSq5m_;(Hby9WMU1OKjp zf7igjYvA8C@b4P{a>or>t^aMLK=17oOJ2R@Tiv3P z-$lFYP#=j$F&XNX_Bc_c1Nbzg>%)=4de#)ndPC zTAcEf7SHNtj`QTcJ{$Ku&Gq}%xDOK2J;%uXtcuS<{4e)!J-V+RtE!Kq^arP*o0s^^ z`~SM%`0^Si{criRkJgIXnan$sv_9lN?B9XX@4^4g{g?iAR{hhDozk^j=zNy8{$6`P zJHmFa)MDx`{fMhoUo%^~-*%Q3ubQjH4wBcSv2FGD+tQvjuiw90{h_ui{<+jfw%iW? zU+&*`YIo|4f9PME?ey;$>EFlWwe>OaS}p!A@w98S`}$%XgFn=E_%^F;jVnLb{27T& z5`(DejepzO<&iDi*z{`Jspo3j_n)*jpD(}H;vF{mnB@1YH`m`I`MrP8^6NHh@j=N? z%xL#VZ_#3*hy1V4&eQt$g~U3E`c&V^{qHS#-G7q&uM!(2{w;Br0b2X|{SI<}Z;1y= zJXB&giS1LcVJ+&*VU1fYK6Egz zw@$C$zg#;ZQMFP8hAC3+h0=rMnBE<`_`EIEM;$G@z1}VZ_==XXKr> z`}q9+f4P6T@2=0CTJGf7-sAIU>EHKXY3n1gPK(EUt;IQOw3z!26D;WfY=oZ?^~dL{ zcWC?XTN0BJS4mta@mq=Y5`UNYm&8_yJI&DA+ePB;5<5yfP@-4jF%r8=>?N^}#0w=} zAu%Lzg2bs3@09qU#03&xlK7g$cO|AIek!p};zo%-OKgznn5iw-?h^Nvc$mZ^B>E(F zm)JvMPl=~VJWFCV`=aUIhJV&MJvB>PugCqV^=nLn7H`?CMZNyyAGG^-Y}I17KeXun*&OwHJx;0D zT)%IPXRCyIh~QuE-s+C|wso%7KXdl~oqNmXY5iL+@m-0lC4MAvjl^#xZj|_=#9t)- zA+b^7-x7=FYxCJfqFdsg5<5yPmUx&%eNBzNYy0DhQ;*Zyef1jc`T3ybTKs5^`T2UE z+2;FtyL!CjF7A4rHC}*(dR|ihrgp}EmfP+BhyDBTZgW2_lI8fn?cXwVOr650{@r?r zrE}Z48$3!M;oJ^xC)Mke?Y~|da6Ny$5#NF9v+8`ew%w=7_MdvQcE9r!EpDg~pCS2~ zT69d+;yj5PW=UO4iyNYH|8_0*zC-d7hfde-51ppPGld{vR!Ve4RF4eVW`KU8LQgaJ3eHnV`j95iR~RMvIS1y#0CY z{&nK3oZ9_9J8Q9>#ND#m{3bcHeD9sKIP+~S&X}mhl(e(g_1b-{*Z=kZ#cycKr%P6D z%cQ-Nmuu5|-__z1a({%x8&+ufFXjG=a(~x%wEPVcf0j5Xspa34*iq{HO57yzK$-tQ ziTd*C{j^4Xd+n#5cyQD2A7;6Kg5~}hmirgU{SI0)j+t^_>ovCfvl{4YZFz$x+WDlz zu}ZF^93azcXJHOUC%ONLxca^sb<_RNf3oA%{jJh*{n7d5Q7Y?j=#R=*$|_IGtGQMWk!S^>HHtLeRA*ij{_@Z`>vH( zFL9g1w$EwZ=_s*_#2ym+NE{?_q{MQG(i7O?pl~^xvo5Z%y%lsvFk=R3G zABlq`j+9s~ak|905*JBaB5|d}wG!(kZj;#d1)0CZE)si4>?3iI#E}xqB~F((SK=ax zOC+w8xK?7l#BCDWz9{pT*hOLwiG3svk~mUgxy0!b=So~8af!s064y$sm$*%0+m~ei z61zz3A+e9dK@vwwESET4;#`S~BrcJ-QsP>P^%A#9Z2PjzUt$-DJtX##I7s41iRBWf zOPnilk;EkuS4vzfv0mafiEXQ8{t~-L>>;s_#6c2AN-UQ+UE*AcizF_QxKiR;iS-h< zNom_cJ*!ESKzr-#Qdr0gfagfB363Zn{mpE7AB8f{Ru9Ub|V!gy|65GBe z^Ox8~Vh@RZBo2}|QewHp=@REkTqJRc#FY})O01W-O=8>EW&RSoNbDi8kHkR|M@lT0 zI9=jgiHjsIk+@RgT8Z@%w@GZfOy)1Ki^Luh`$!xlaiqj@iPI&{mAFXa5{WA%u9a9X zaht@pH8OvRT_pC9*hk_Zi6bSJOPnrouEa$Wmq=VGajnF9iQ6Q$eM9Civ5UkW68lIT zByps~a*5L=&Xu@G;u47~C9aiNFL9g1wr|S(C3cb6Lt-C^gCvfWST1q8#JLg|Nn9dv zrNp%o>m_cJ*f#g2z&QR$>>{y;#6A)SNgOG$T;g0?Q&Uu ziCrZ2kl07!Ac-R-mP?#2ajwKg5|>C^DRHgDdWqX4wq4=K-8xF_BC&_WJ`x8>94WC} z;&h2~B`%VNp{zQR&1 z`C3bZ?@GS>2y^`!$vGA0+t;E&V@S@{=Adyk=699xwUpEcGW#K4EG949V9ID7@BEC1sNT3hn5x0abp8 z+sl21y$2705JXG?>S@Oq9ez+xnlH?z-%Ao*8NpMOn_njw-u zz)~NQ{A-r>!;(K5>&Mv61j(0J>ZeM6Jo3ivey8N8Sk}*jlK;oj&eM|bX6ffElJB^a z89tJH(42N`ko+%}_J5W9ua##xcKU(&a-y~n67wU0mZM*c>?@QcG^8GCN10=5> zZ}om2E_r=_)APqm{t(Oh>?!$M(Y{`*X62XsTuc20l3!rSkCyy6OFySd{!UB#cT4_S zOMP7OGcEa7B!9iMqxba<$vDTGAo*i0`_Ji;A8*-z&XfH2Xu~**!ICevJdT2rKOK4Facqp_ z&pY4zd^cJ0y)E@KB!9l8{$a@jTMOU|47B z&(9@)gr%MJl0Oo8<8j~z$)9Fv=P$`WX36i?PTRgXtuWoZk}pHnxM;^qeuk;q;pi** z{bl>=(+rS&2TT2>l3y^%{KnR+B|iY|=wr5O(um|gm-hAMrb#|+*?;Cr{yt0nJjp*{ zseexL*P&s(?`j^eO8#|Af8LS&D9icS=aTC zpfaDSlJ9KE$0Xm^(w_$FPx6~B?LQ{@ZI=4yB>#)0eyQY* z>t2=ANd7oW{R+v?M_#ReeH*Nn{K1&7v8`Ikms;A{DEX%>`@=TLpM-Xd`@h4j?GO5V z_2zb!{8&r<-jYAp@;r5rtKTneU^_J!8rMHi~@jNh~w{O{wS4jR9 zz2g!`N#28YjPo5U`SGaJ*Rh)9ddW9fmUo)ums{GoNAjo2{PggMW8AoycAMmz^c_KB`wrUrY_#M%Oa5?6`z4ZhTk`!Szndk0rR3XN@{=UL$THuV zlJ8;3&z8Io+sk--xKHvy%XWNR^7~ry3nj0gcj>cvPH*4x_+2J>xy+-NJ3f$nXG{B^ zOTLq3c{fV_YfJw(Oa2hl8=n{ck$gAH@v7tQ+VN&Y>{c3dTS{dJ|jY#SusYU$4}l8+#7d|vxQ@(V5V%}T!7GT+_z(6(25eTK3e z2S~o!vRubX{vAty&XW8Cs5drsk>uURBx;6B{v}I0lO^BRvYzjk{A$Z`&6oU_mgRa; z^6y#NUoQElE%{o>KV`}PAo-&#`7M&y&;Rws`&;rOE%oj8)YkJ=mg8qf$&azrcb5ER zmi6CV@}n&EJtc4LPanyTw$xuJ`H-bQS4h6IWjl_R{8g5AZjk)V$Q$?b+a({fY?rx` zKgF_r9^Ne`m?RBl({!`OhT(rKSJtB|q0v|GVTbwB&c%OWR((E%`kp|Dz>; zh~!VidN4j7kCeOv%WKS^B>9~z`Ew+{#nS#D$+y#YH1YA0Z?M!?NPdkaf2ZWvTJjG_ z{tHWfq2zD0&63x)LSdrcCI3hvmHX>& z$scOT@4UCx!s+Gaafy8;@3riQhfDq&%YNQN^6M@6vm{?<$(KpqhxUz+i=mP~)$+V~ zt>jO%^#5kbe{9L$E&0DJ^PMO8F_!w5B)`9LC8OqD$#=EXrzF3hrGCBS_p;1)qvQ{@ z510HgmgCY1lGn#G z^~LTb`E$`v<8};4zQxkc6_U?bmP?<1?zeLFJKKrvBzL6#e)x-a&Sg%J`}aF{*>gLS zgAp9G561UzwcRRoznTpz5^~ks&h%#le?bS zxqG+cPwdvC`w5+oJbO}j#Dwz)YWZWkpNw6h>%`F$BNHOShC8~B8y^|bb=0^?U58H^ z6Am3aCgjN78$E2|Xh+x3jpHWXI97|137V9Tm@sk7_;IE?Ltqm|gomjKEC=aRdGzi7bl7hlWLlIl7J*J!IsBVPi)O8683+`aNyZA;Tt27l>L-j$QUVlHb9y=edO`zthn%1Y^ zPfI)0bs^QZKE3|_W%59R)&8nuTQVPKU$Ca`=j;w>(lGYf2B-+CSvY(w>j$X&sNj# zihtJWM}X4g2k5PP=u<>SHe+z(W z3blWzoBnx&RX1u+C)RrXz8;^)G`r)UKE3{Vgirp%>6c+zwfy?@U&`khzTCm|m?U>w zj{l9*>)$)IL8jlTKTx!CM`ww8_z-`neMg_a{yzRs?$wsRo2)*4z3a=Z??>vogmL~3 z`Fw=qer@_6)q~D()2G*?I^Q-;KTntZt+U~8^=BRaskZd~4}DXce(0Op z^fPo&#kh6O{a^U+JN&8UZ+)EU(;r(X&Hbfn)y)_!v&i{unZI?sU!N{lg#Z3OlKW>4 literal 0 HcmV?d00001 diff --git a/lib/liblog4cplus.so.9 b/lib/liblog4cplus.so.9 new file mode 100644 index 0000000000000000000000000000000000000000..28ae191bf98b92631f129924e11aaec6c7e5f380 GIT binary patch literal 2304296 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 yOVkP`10SXVJ@%vyq>iW) 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

@0GFRr!=em!=r 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 z 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­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

_kNv)qBC|O2&@S&Dz-p-UcN4+pMQub9;Y)>|m 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 z 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

e4IGEo&K@@eZ+5nz6b*5{7`tD(t3VsU{!+z{ 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

X>(uOTB*n2~Dmc9ok7CEqv2UsnUNwqSB20p82sE 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

~hx%1V9+iKeN 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

_cie!}bi3H-C;e^tM>_ZeP!Zae<`|LAY_ zdcXWr?wk6;bHqPi;E$h2_y0e?`6c<-UjO5->9_6v?K<}QZG8O4(ecY4=<)XYo9=?V zf8L4Rzn*n(?;5}GGdtf;{)HZIufOx#`c1pO9dFM+cgKIOU)%eyy5jM8 zA9H}CpKnFK^Vffce|&yB{`_9AZ?BjCp5F>T`S|@1AH~Q2_Fw%g@@0EH`R8_KJ%`Po z{T7=eAK`7D^B3F)zyH%C`Qq>YRL_%NFaP_0;M;$m z$IDTBd-?HPU-6F}Z?C_H5B~!G+41K;)9auAto{0S{2$<0KEECRjXVAucl;lHh7Y43 zJI>zv-}r?q%#J@lK9-NpkGWg+_C9mNZ{udi+dBLSz7t>nw@&r=-#XRfGx6j1pPlEY z+3|ay>G6A?>G2=_3GX8O*m3sy$M`6|{)Zpw@gIJq$DfBo;reex9mXo`b#*T*MFM5Z^wU=z0dFRCw@&=xPJbv|E~A{Z~s6){abkZKVYKl y{(n`!w#WUQ-J*Q*-~NqCuK)D|J3$=1Dex>2~fBmh$EnoRd*#X&~d;brH9pW1R literal 0 HcmV?d00001 diff --git a/lib/libmxml.so.1 b/lib/libmxml.so.1 new file mode 100644 index 0000000000000000000000000000000000000000..a45fbf622704ab43cf849bb164ba904e5e318044 GIT binary patch literal 132088 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

mv?eZ3C1>2Q+{AE?8% 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 literal 0 HcmV?d00001 diff --git a/lib/libmxml.so.1.5 b/lib/libmxml.so.1.5 new file mode 100644 index 0000000000000000000000000000000000000000..a45fbf622704ab43cf849bb164ba904e5e318044 GIT binary patch literal 132088 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

mv?eZ3C1>2Q+{AE?8% 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 literal 0 HcmV?d00001 diff --git a/mms/mms_process.c b/mms/mms_process.c index c9e6060..c6df9dc 100644 --- a/mms/mms_process.c +++ b/mms/mms_process.c @@ -202,7 +202,7 @@ void closeChannel(chnl_usr_t *chnl_usr) mvl_free_req_ctrl(chnl_usr->m_reqCtrl); - chnl_usr->net_info->user_ext = NULL; + chnl_usr->net_info->user_info = NULL; chnl_usr->net_info = NULL; @@ -229,7 +229,7 @@ ST_VOID Callback_channel_disconnect_ind(MVL_NET_INFO * NetInfo, ST_INT discType) { chnl_usr_t *chnl_usr; - chnl_usr = (chnl_usr_t*)NetInfo->user_ext; + chnl_usr = (chnl_usr_t*)NetInfo->user_info; if ( chnl_usr ) { if(chnl_usr->m_state == CHANNEL_CONNECTING) @@ -248,7 +248,7 @@ ST_VOID Callback_channel_disconnect_ind(MVL_NET_INFO * NetInfo, ST_INT discType) chnl_usr->net_info = NULL; - NetInfo->user_ext = NULL; + NetInfo->user_info = NULL; } printf(" Callback_channel_disconnect_ind ,NetInfo = %x",NetInfo); @@ -1703,7 +1703,7 @@ void CheckNextNotConnectedChannel() chnl_usr->m_reqCtrl = NULL; chnl_usr->m_state = CHANNEL_CONNECTED; - chnl_usr->net_info->user_ext = chnl_usr; + chnl_usr->net_info->user_info = chnl_usr; all_rcb_info = (ALL_RCB_INFO *)chk_calloc(1, sizeof (ALL_RCB_INFO)); all_rcb_info->rpt_typeids = &g_rpt_typeids; @@ -1863,7 +1863,7 @@ void CheckNextNotConnectedChannel() echo_warn3( "CHANNEL_DISCONNECTING done %s:%d,NetInfo= %x ",chnl_usr->ip_str,chnl_usr->chnl->port,chnl_usr->net_info); mvl_free_req_ctrl(chnl_usr->m_reqCtrl); if(chnl_usr->net_info) - chnl_usr->net_info->user_ext = NULL; + chnl_usr->net_info->user_info = NULL; chnl_usr->m_reqCtrl = NULL; chnl_usr->net_info = NULL; @@ -1891,7 +1891,7 @@ void CheckNextNotConnectedChannel() echo_warn2( "CHANNEL_DISCONNECTING reqCtrl->done未完æˆ,but time over 180 secs, close channel IP %s,NetInfo= %x ",chnl_usr->ip_str,chnl_usr->net_info); mvl_free_req_ctrl(chnl_usr->m_reqCtrl); - chnl_usr->net_info->user_ext = NULL; + chnl_usr->net_info->user_info = NULL; mms_release_connection(chnl_usr->net_info); chnl_usr->net_info->rem_vmd = NULL; diff --git a/mms/mmscli_rpt.c b/mms/mmscli_rpt.c index 0be6095..d79ad51 100644 --- a/mms/mmscli_rpt.c +++ b/mms/mmscli_rpt.c @@ -844,7 +844,7 @@ ST_VOID u_iec_rpt_ind_data_by_devtype(MVL_VAR_ASSOC** info_va, rptinfo = find_rptinfo_from_net_rpt_info_name(net_info, rcb_info); //rptinfo->m_LastDataTime = sGetMsTime();//WW 2023-08-29 去除 LD_info = rptinfo->LD_info; - chnl_usr = net_info->user_ext; + chnl_usr = net_info->user_info; ied = chnl_usr->chnl->ied; not_set_rpt_TimeID_this = TRUE; @@ -1230,7 +1230,7 @@ ST_VOID u_iec_rpt_ind_data(MVL_VAR_ASSOC** info_va, rptinfo = find_rptinfo_from_net_rcb_info(net_info, rcb_info); //rptinfo->m_LastDataTime = sGetMsTime();//WW 2023-08-29 去除 LD_info = rptinfo->LD_info; - chnl_usr = net_info->user_ext; + chnl_usr = net_info->user_info; ied = chnl_usr->chnl->ied; not_set_rpt_TimeID_this = TRUE; diff --git a/mms/mmsop_en.c b/mms/mmsop_en.c index 3b91cfc..372dfc0 100644 --- a/mms/mmsop_en.c +++ b/mms/mmsop_en.c @@ -2451,16 +2451,16 @@ ST_INT m_cl_max_enrollment_summary; #if (MMS_LOAD_DOM_EN & RESP_EN) ST_INT m_sv_max_loadd_cap; #endif - -#if (MMS_READ_EN & RESP_EN) +//lnk编译,客户端ä¸å—å½±å“ +//#if (MMS_READ_EN & RESP_EN) ST_INT m_sv_max_read_var_spec; -#endif +//#endif -#if (MMS_WRITE_EN & RESP_EN) +//#if (MMS_WRITE_EN & RESP_EN) ST_INT m_sv_max_write_var_spec; ST_INT m_sv_max_write_data; -#endif - +//#endif +//lnk编译,客户端ä¸å—å½±å“ #if (MMS_RDDWN_EN & RESP_EN) ST_INT m_sv_max_rqdlnl_cap; #endif diff --git a/mms/rdb_ext_utils.c b/mms/rdb_ext_utils.c index 52d7e69..e2fa323 100644 --- a/mms/rdb_ext_utils.c +++ b/mms/rdb_ext_utils.c @@ -139,7 +139,7 @@ RCB_INFO* FindRcbInfo(MVL_NET_INFO *net_info,ST_CHAR *dom_name, ST_CHAR *rcb_nam int cpuno,rpt_no; char rpt_inst_name[65]; - chnl_usr = net_info->user_ext; + chnl_usr = net_info->user_info; ied = chnl_usr->chnl->ied; ied_usr = GET_IEDEXT_ADDR(ied); @@ -188,7 +188,7 @@ rptinfo_t* find_rptinfo_from_net_rpt_info_name(MVL_NET_INFO *net_info, RCB_INFO rptinfo_t *rptinfo = NULL; int cpuno,rpt_no; - chnl_usr = net_info->user_ext; + chnl_usr = net_info->user_info; ied = chnl_usr->chnl->ied; ied_usr = GET_IEDEXT_ADDR(ied); @@ -232,7 +232,7 @@ rptinfo_t* find_rptinfo_from_net_rcb_info(MVL_NET_INFO *net_info,RCB_INFO *rcb_i rptinfo_t *rptinfo = NULL; int cpuno,rpt_no; - chnl_usr = net_info->user_ext; + chnl_usr = net_info->user_info; ied = chnl_usr->chnl->ied; ied_usr = GET_IEDEXT_ADDR(ied); diff --git a/mmslib/.vscode/c_cpp_properties.json b/mmslib/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..bfa1cc6 --- /dev/null +++ b/mmslib/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "windows-gcc-x64", + "includePath": [ + "${workspaceFolder}/**" + ], + "compilerPath": "C:/Users/lnk/Downloads/mingw32/bin/gcc.exe", + "cStandard": "${default}", + "cppStandard": "${default}", + "intelliSenseMode": "windows-gcc-x64", + "compilerArgs": [ + "" + ] + } + ], + "version": 4 +} \ No newline at end of file diff --git a/mmslib/.vscode/launch.json b/mmslib/.vscode/launch.json new file mode 100644 index 0000000..e3a82da --- /dev/null +++ b/mmslib/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "C/C++ Runner: Debug Session", + "type": "cppdbg", + "request": "launch", + "args": [], + "stopAtEntry": false, + "externalConsole": true, + "cwd": "d:/canneng/自主å议库/mmslib", + "program": "d:/canneng/自主å议库/mmslib/build/Debug/outDebug", + "MIMode": "gdb", + "miDebuggerPath": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/mmslib/.vscode/settings.json b/mmslib/.vscode/settings.json new file mode 100644 index 0000000..bb879da --- /dev/null +++ b/mmslib/.vscode/settings.json @@ -0,0 +1,59 @@ +{ + "C_Cpp_Runner.cCompilerPath": "gcc", + "C_Cpp_Runner.cppCompilerPath": "g++", + "C_Cpp_Runner.debuggerPath": "gdb", + "C_Cpp_Runner.cStandard": "", + "C_Cpp_Runner.cppStandard": "", + "C_Cpp_Runner.msvcBatchPath": "C:/Program Files/Microsoft Visual Studio/VR_NR/Community/VC/Auxiliary/Build/vcvarsall.bat", + "C_Cpp_Runner.useMsvc": false, + "C_Cpp_Runner.warnings": [ + "-Wall", + "-Wextra", + "-Wpedantic", + "-Wshadow", + "-Wformat=2", + "-Wcast-align", + "-Wconversion", + "-Wsign-conversion", + "-Wnull-dereference" + ], + "C_Cpp_Runner.msvcWarnings": [ + "/W4", + "/permissive-", + "/w14242", + "/w14287", + "/w14296", + "/w14311", + "/w14826", + "/w44062", + "/w44242", + "/w14905", + "/w14906", + "/w14263", + "/w44265", + "/w14928" + ], + "C_Cpp_Runner.enableWarnings": true, + "C_Cpp_Runner.warningsAsError": false, + "C_Cpp_Runner.compilerArgs": [], + "C_Cpp_Runner.linkerArgs": [], + "C_Cpp_Runner.includePaths": [], + "C_Cpp_Runner.includeSearch": [ + "*", + "**/*" + ], + "C_Cpp_Runner.excludeSearch": [ + "**/build", + "**/build/**", + "**/.*", + "**/.*/**", + "**/.vscode", + "**/.vscode/**" + ], + "C_Cpp_Runner.useAddressSanitizer": false, + "C_Cpp_Runner.useUndefinedSanitizer": false, + "C_Cpp_Runner.useLeakSanitizer": false, + "C_Cpp_Runner.showCompilationTime": false, + "C_Cpp_Runner.useLinkTimeOptimization": false, + "C_Cpp_Runner.msvcSecureNoWarnings": false +} \ No newline at end of file diff --git a/mmslib/Makefile b/mmslib/Makefile new file mode 100644 index 0000000..833ef9e --- /dev/null +++ b/mmslib/Makefile @@ -0,0 +1,151 @@ +############################################################################# +# Makefile for building: libmmslib.a +# Generated by qmake (2.01a) (Qt 4.8.4) on: ?? 10? 12 16:45:38 2025 +# Project: mmslib.pro +# Template: lib +# Command: /qt-4.8.4/bin/qmake -o Makefile mmslib.pro +############################################################################# + +first: release +install: release-install +uninstall: release-uninstall +MAKEFILE = Makefile +QMAKE = /qt-4.8.4/bin/qmake +DEL_FILE = rm -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p +COPY = cp -f +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +INSTALL_FILE = install -m 644 -p +INSTALL_PROGRAM = install -m 755 -p +INSTALL_DIR = $(COPY_DIR) +DEL_FILE = rm -f +SYMLINK = ln -f -s +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p +SUBTARGETS = \ + release \ + debug + +release: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release +release-make_default: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release +release-make_first: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release first +release-all: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release all +release-clean: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release clean +release-distclean: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release distclean +release-install: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release install +release-uninstall: $(MAKEFILE).Release FORCE + $(MAKE) -f $(MAKEFILE).Release uninstall +debug: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug +debug-make_default: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug +debug-make_first: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug first +debug-all: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug all +debug-clean: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug clean +debug-distclean: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug distclean +debug-install: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug install +debug-uninstall: $(MAKEFILE).Debug FORCE + $(MAKE) -f $(MAKEFILE).Debug uninstall + +Makefile: mmslib.pro ../../../qt-4.8.4/mkspecs/linux-g++-64/qmake.conf ../../../qt-4.8.4/mkspecs/common/unix.conf \ + ../../../qt-4.8.4/mkspecs/common/linux.conf \ + ../../../qt-4.8.4/mkspecs/common/gcc-base.conf \ + ../../../qt-4.8.4/mkspecs/common/gcc-base-unix.conf \ + ../../../qt-4.8.4/mkspecs/common/g++-base.conf \ + ../../../qt-4.8.4/mkspecs/common/g++-unix.conf \ + ../../../qt-4.8.4/mkspecs/qconfig.pri \ + ../../../qt-4.8.4/mkspecs/features/qt_functions.prf \ + ../../../qt-4.8.4/mkspecs/features/qt_config.prf \ + ../../../qt-4.8.4/mkspecs/features/exclusive_builds.prf \ + ../../../qt-4.8.4/mkspecs/features/default_pre.prf \ + fe_common.pri \ + ../../../qt-4.8.4/mkspecs/features/release.prf \ + ../../../qt-4.8.4/mkspecs/features/debug_and_release.prf \ + ../../../qt-4.8.4/mkspecs/features/default_post.prf \ + ../../../qt-4.8.4/mkspecs/features/warn_off.prf \ + ../../../qt-4.8.4/mkspecs/features/staticlib.prf \ + ../../../qt-4.8.4/mkspecs/features/static.prf \ + ../../../qt-4.8.4/mkspecs/features/unix/gdb_dwarf_index.prf \ + ../../../qt-4.8.4/mkspecs/features/qt.prf \ + ../../../qt-4.8.4/mkspecs/features/unix/thread.prf \ + ../../../qt-4.8.4/mkspecs/features/moc.prf \ + ../../../qt-4.8.4/mkspecs/features/resources.prf \ + ../../../qt-4.8.4/mkspecs/features/uic.prf \ + ../../../qt-4.8.4/mkspecs/features/yacc.prf \ + ../../../qt-4.8.4/mkspecs/features/lex.prf \ + ../../../qt-4.8.4/mkspecs/features/include_source_dir.prf \ + /qt-4.8.4/lib/libQtCore.prl + $(QMAKE) -o Makefile mmslib.pro +../../../qt-4.8.4/mkspecs/common/unix.conf: +../../../qt-4.8.4/mkspecs/common/linux.conf: +../../../qt-4.8.4/mkspecs/common/gcc-base.conf: +../../../qt-4.8.4/mkspecs/common/gcc-base-unix.conf: +../../../qt-4.8.4/mkspecs/common/g++-base.conf: +../../../qt-4.8.4/mkspecs/common/g++-unix.conf: +../../../qt-4.8.4/mkspecs/qconfig.pri: +../../../qt-4.8.4/mkspecs/features/qt_functions.prf: +../../../qt-4.8.4/mkspecs/features/qt_config.prf: +../../../qt-4.8.4/mkspecs/features/exclusive_builds.prf: +../../../qt-4.8.4/mkspecs/features/default_pre.prf: +fe_common.pri: +../../../qt-4.8.4/mkspecs/features/release.prf: +../../../qt-4.8.4/mkspecs/features/debug_and_release.prf: +../../../qt-4.8.4/mkspecs/features/default_post.prf: +../../../qt-4.8.4/mkspecs/features/warn_off.prf: +../../../qt-4.8.4/mkspecs/features/staticlib.prf: +../../../qt-4.8.4/mkspecs/features/static.prf: +../../../qt-4.8.4/mkspecs/features/unix/gdb_dwarf_index.prf: +../../../qt-4.8.4/mkspecs/features/qt.prf: +../../../qt-4.8.4/mkspecs/features/unix/thread.prf: +../../../qt-4.8.4/mkspecs/features/moc.prf: +../../../qt-4.8.4/mkspecs/features/resources.prf: +../../../qt-4.8.4/mkspecs/features/uic.prf: +../../../qt-4.8.4/mkspecs/features/yacc.prf: +../../../qt-4.8.4/mkspecs/features/lex.prf: +../../../qt-4.8.4/mkspecs/features/include_source_dir.prf: +/qt-4.8.4/lib/libQtCore.prl: +qmake: qmake_all FORCE + @$(QMAKE) -o Makefile mmslib.pro + +qmake_all: FORCE + +make_default: release-make_default debug-make_default FORCE +make_first: release-make_first debug-make_first FORCE +all: release-all debug-all FORCE +clean: release-clean debug-clean FORCE +distclean: release-distclean debug-distclean FORCE + -$(DEL_FILE) Makefile + +check: first + +release-mocclean: $(MAKEFILE).Release + $(MAKE) -f $(MAKEFILE).Release mocclean +debug-mocclean: $(MAKEFILE).Debug + $(MAKE) -f $(MAKEFILE).Debug mocclean +mocclean: release-mocclean debug-mocclean + +release-mocables: $(MAKEFILE).Release + $(MAKE) -f $(MAKEFILE).Release mocables +debug-mocables: $(MAKEFILE).Debug + $(MAKE) -f $(MAKEFILE).Debug mocables +mocables: release-mocables debug-mocables +FORCE: + +$(MAKEFILE).Release: Makefile +$(MAKEFILE).Debug: Makefile diff --git a/mmslib/Makefile.Debug b/mmslib/Makefile.Debug new file mode 100644 index 0000000..fa53bd5 --- /dev/null +++ b/mmslib/Makefile.Debug @@ -0,0 +1,1899 @@ +############################################################################# +# Makefile for building: libmmslibd.a +# Generated by qmake (2.01a) (Qt 4.8.4) on: ?? 10? 12 16:45:38 2025 +# Project: mmslib.pro +# Template: lib +############################################################################# + +####### Compiler, tools and options + +CC = gcc +CXX = g++ +DEFINES = -DDEBUG_SISCO -DMOSI -DLEAN_T -DMVL_UCA -DMMS_LITE -DTP0_ENABLED -DSTDTIME_ANSI -DFE_VERSION_64 -DQT_CORE_LIB -DQT_SHARED +CFLAGS = -m64 -pipe -g -w -fPIC -D_REENTRANT $(DEFINES) +CXXFLAGS = -m64 -pipe -g -DDEBUG -w -fPIC -D_REENTRANT $(DEFINES) +INCPATH = -I../../../qt-4.8.4/mkspecs/linux-g++-64 -I. -I../../../qt-4.8.4/include/QtCore -I../../../qt-4.8.4/include -Iinc -Iinc/mmsop_en -Idebug +AR = ar cqs +RANLIB = +QMAKE = /qt-4.8.4/bin/qmake +TAR = tar -cf +COMPRESS = gzip -9f +COPY = cp -f +SED = sed +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +STRIP = strip +INSTALL_FILE = install -m 644 -p +INSTALL_DIR = $(COPY_DIR) +INSTALL_PROGRAM = install -m 755 -p +DEL_FILE = rm -f +SYMLINK = ln -f -s +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p + +####### Output directory + +OBJECTS_DIR = debug/ + +####### Files + +SOURCES = mmslib.cpp \ + asn1/asn1r.c \ + asn1/are_vstr.c \ + asn1/are_utc.c \ + asn1/are_time.c \ + asn1/are_ostr.c \ + asn1/are_objd.c \ + asn1/are_int.c \ + asn1/are_flt.c \ + asn1/are_delm.c \ + asn1/are_btod.c \ + asn1/are_bstr.c \ + asn1/are_bool.c \ + asn1/ard_vstr.c \ + asn1/ard_utc.c \ + asn1/ard_time.c \ + asn1/ard_strn.c \ + asn1/ard_ostr.c \ + asn1/ard_objd.c \ + asn1/ard_int.c \ + asn1/ard_idnt.c \ + asn1/ard_flt.c \ + asn1/ard_delm.c \ + asn1/ard_btod.c \ + asn1/ard_bstr.c \ + asn1/ard_bool.c \ + mem/mem_chks.c \ + mmsl/rs_write.c \ + mmsl/rs_ustat.c \ + mmsl/rs_trige.c \ + mmsl/rs_stat.c \ + mmsl/rs_repee.c \ + mmsl/rs_repec.c \ + mmsl/rs_repea.c \ + mmsl/rs_read.c \ + mmsl/rs_namel.c \ + mmsl/rs_init.c \ + mmsl/rs_info.c \ + mmsl/rs_ident.c \ + mmsl/rs_getvl.c \ + mmsl/rs_getva.c \ + mmsl/rs_getty.c \ + mmsl/rs_getpi.c \ + mmsl/rs_getee.c \ + mmsl/rs_getec.c \ + mmsl/rs_getea.c \ + mmsl/rs_getdo.c \ + mmsl/rs_getcl.c \ + mmsl/rs_evnot.c \ + mmsl/rs_defee.c \ + mmsl/rs_concl.c \ + mmsl/rs_cancl.c \ + mmsl/rs_ackev.c \ + mmsl/rq_write.c \ + mmsl/rq_ustat.c \ + mmsl/rq_trige.c \ + mmsl/rq_stat.c \ + mmsl/rq_repee.c \ + mmsl/rq_repec.c \ + mmsl/rq_repea.c \ + mmsl/rq_read.c \ + mmsl/rq_namel.c \ + mmsl/rq_init.c \ + mmsl/rq_info.c \ + mmsl/rq_ident.c \ + mmsl/rq_getvl.c \ + mmsl/rq_getva.c \ + mmsl/rq_getty.c \ + mmsl/rq_getpi.c \ + mmsl/rq_getee.c \ + mmsl/rq_getec.c \ + mmsl/rq_getea.c \ + mmsl/rq_getdo.c \ + mmsl/rq_getcl.c \ + mmsl/rq_evnot.c \ + mmsl/rq_defee.c \ + mmsl/rq_concl.c \ + mmsl/rq_cancl.c \ + mmsl/rq_ackev.c \ + mmsl/msdataas.c \ + mmsl/ms_tdef4.c \ + mmsl/ms_tdef2.c \ + mmsl/ms_tdef.c \ + mmsl/ms_size.c \ + mmsl/ms_ext.c \ + mmsl/mmsstat.c \ + mmsl/mmslvar.c \ + mmsl/mmsl_fin.c \ + mmsl/mmsinit.c \ + mmsl/mmsdtext.c \ + mmsl/mmsdec.c \ + mmsl/mmsdatat.c \ + mmsl/mmsdata.c \ + mmsl/mmsconcl.c \ + mmsl/mmscancl.c \ + mmsl/mms_tdef.c \ + mmsl/mms_rtaa.c \ + mmsl/mms_rej.c \ + mmsl/mms_err4.c \ + mmsl/mms_err3.c \ + mmsl/mms_err2.c \ + mmsl/mms_err.c \ + mmsl/mms_ced7.c \ + mmsl/mms_ced6.c \ + mmsl/mms_ced5.c \ + mmsl/mms_ced4.c \ + mmsl/mms_ced3.c \ + mmsl/mms_ced.c \ + mmsl/mms_aref.c \ + mmsl/mms_alta.c \ + mmsl/mms_adl.c \ + mmsle/rs_uploa.c \ + mmsle/rs_termu.c \ + mmsle/rs_termd.c \ + mmsle/rs_takec.c \ + mmsle/rs_store.c \ + mmsle/rs_stop.c \ + mmsle/rs_start.c \ + mmsle/rs_rssta.c \ + mmsle/rs_rspoo.c \ + mmsle/rs_rsent.c \ + mmsle/rs_resum.c \ + mmsle/rs_reset.c \ + mmsle/rs_renam.c \ + mmsle/rs_relct.c \ + mmsle/rs_rdupl.c \ + mmsle/rs_rddwn.c \ + mmsle/rs_outpu.c \ + mmsle/rs_obtfi.c \ + mmsle/rs_loadd.c \ + mmsle/rs_kill.c \ + mmsle/rs_jwrit.c \ + mmsle/rs_jstat.c \ + mmsle/rs_jread.c \ + mmsle/rs_jinit.c \ + mmsle/rs_jdele.c \ + mmsle/rs_jcrea.c \ + mmsle/rs_input.c \ + mmsle/rs_initu.c \ + mmsle/rs_initd.c \ + mmsle/rs_getsc.c \ + mmsle/rs_getas.c \ + mmsle/rs_getae.c \ + mmsle/rs_frena.c \ + mmsle/rs_fread.c \ + mmsle/rs_fopen.c \ + mmsle/rs_fdir.c \ + mmsle/rs_fdele.c \ + mmsle/rs_fclos.c \ + mmsle/rs_downl.c \ + mmsle/rs_delvl.c \ + mmsle/rs_delva.c \ + mmsle/rs_delty.c \ + mmsle/rs_delse.c \ + mmsle/rs_delpi.c \ + mmsle/rs_delee.c \ + mmsle/rs_delec.c \ + mmsle/rs_delea.c \ + mmsle/rs_deldo.c \ + mmsle/rs_defvl.c \ + mmsle/rs_defva.c \ + mmsle/rs_defty.c \ + mmsle/rs_defse.c \ + mmsle/rs_defsc.c \ + mmsle/rs_defec.c \ + mmsle/rs_defea.c \ + mmsle/rs_crepi.c \ + mmsle/rs_altee.c \ + mmsle/rs_altec.c \ + mmsle/rq_uploa.c \ + mmsle/rq_termu.c \ + mmsle/rq_termd.c \ + mmsle/rq_takec.c \ + mmsle/rq_store.c \ + mmsle/rq_stop.c \ + mmsle/rq_start.c \ + mmsle/rq_rssta.c \ + mmsle/rq_rspoo.c \ + mmsle/rq_rsent.c \ + mmsle/rq_resum.c \ + mmsle/rq_reset.c \ + mmsle/rq_renam.c \ + mmsle/rq_relct.c \ + mmsle/rq_rdupl.c \ + mmsle/rq_rddwn.c \ + mmsle/rq_outpu.c \ + mmsle/rq_obtfi.c \ + mmsle/rq_loadd.c \ + mmsle/rq_kill.c \ + mmsle/rq_jwrit.c \ + mmsle/rq_jstat.c \ + mmsle/rq_jread.c \ + mmsle/rq_jinit.c \ + mmsle/rq_jdele.c \ + mmsle/rq_jcrea.c \ + mmsle/rq_input.c \ + mmsle/rq_initu.c \ + mmsle/rq_initd.c \ + mmsle/rq_getsc.c \ + mmsle/rq_getas.c \ + mmsle/rq_getae.c \ + mmsle/rq_frena.c \ + mmsle/rq_fread.c \ + mmsle/rq_fopen.c \ + mmsle/rq_fdir.c \ + mmsle/rq_fdele.c \ + mmsle/rq_fclos.c \ + mmsle/rq_downl.c \ + mmsle/rq_delvl.c \ + mmsle/rq_delva.c \ + mmsle/rq_delty.c \ + mmsle/rq_delse.c \ + mmsle/rq_delpi.c \ + mmsle/rq_delee.c \ + mmsle/rq_delec.c \ + mmsle/rq_delea.c \ + mmsle/rq_deldo.c \ + mmsle/rq_defvl.c \ + mmsle/rq_defva.c \ + mmsle/rq_defty.c \ + mmsle/rq_defse.c \ + mmsle/rq_defsc.c \ + mmsle/rq_defec.c \ + mmsle/rq_defea.c \ + mmsle/rq_crepi.c \ + mmsle/rq_altee.c \ + mmsle/rq_altec.c \ + mmsle/mms_ced2.c \ + mmsle/mms_ced1.c \ + mvlu/sclproc.c \ + mvlu/s_write.c \ + mvlu/s_status.c \ + mvlu/s_read.c \ + mvlu/s_obtfi.c \ + mvlu/s_jstat.c \ + mvlu/s_jread.c \ + mvlu/s_jinit.c \ + mvlu/s_info.c \ + mvlu/s_ident.c \ + mvlu/s_getvla.c \ + mvlu/s_getvaa.c \ + mvlu/s_getnam.c \ + mvlu/s_getdom.c \ + mvlu/s_getcl.c \ + mvlu/s_fren.c \ + mvlu/s_fread.c \ + mvlu/s_fopen.c \ + mvlu/s_fdir.c \ + mvlu/s_fdel.c \ + mvlu/s_fclose.c \ + mvlu/s_delvl.c \ + mvlu/s_defvl.c \ + mvlu/s_concl.c \ + mvlu/s_cancel.c \ + mvlu/mvluleaf.c \ + mvlu/mvlu_sbo.c \ + mvlu/mvlu_rt.c \ + mvlu/mvlu_rpt.c \ + mvlu/mvl61850_rpt.c \ + mvlu/mvl61850_ctl.c \ + mvlu/mvl61850.c \ + mvlu/mvl_var.c \ + mvlu/mvl_uca.c \ + mvlu/mvl_type.c \ + mvlu/mvl_typ2.c \ + mvlu/mvl_serv.c \ + mvlu/mvl_send.c \ + mvlu/mvl_objb.c \ + mvlu/mvl_obj.c \ + mvlu/mvl_ijou.c \ + mvlu/mvl_dtyp.c \ + mvlu/mvl_buf.c \ + mvlu/c_write.c \ + mvlu/c_status.c \ + mvlu/c_read.c \ + mvlu/c_obtfi.c \ + mvlu/c_jstat.c \ + mvlu/c_jread.c \ + mvlu/c_jinit.c \ + mvlu/c_info.c \ + mvlu/c_ident.c \ + mvlu/c_getvla.c \ + mvlu/c_getvar.c \ + mvlu/c_getnam.c \ + mvlu/c_getdom.c \ + mvlu/c_fren.c \ + mvlu/c_fread.c \ + mvlu/c_fopen.c \ + mvlu/c_fget.c \ + mvlu/c_fdir.c \ + mvlu/c_fdel.c \ + mvlu/c_fclose.c \ + mvlu/c_delvl.c \ + mvlu/c_defvl.c \ + mvlu/c_concl.c \ + ositcps/tpx_dec.c \ + ositcps/tp4port.c \ + ositcps/tp4_enc.c \ + ositcps/tp0main.c \ + ositcps/tp0callg.c \ + ositcps/tp0calld.c \ + ositcps/tp0_socks.c \ + ositcps/tp0_dec.c \ + ositcps/osicfgx.c \ + ositcps/lean_var.c \ + ositcps/lean_cfg.c \ + ositcps/cospmain.c \ + ositcps/cosp_enc.c \ + ositcps/cosp_dec.c \ + ositcps/coppdcpr.c \ + ositcps/coppdcp.c \ + ositcps/coppdaru.c \ + ositcps/copp_enc.c \ + ositcps/copp_dec.c \ + ositcps/checksum.c \ + ositcps/acse2var.c \ + ositcps/acse2enc.c \ + ositcps/acse2dib.c \ + ositcps/acse2dec.c \ + slog/slogmem.c \ + slog/slogipcs.c \ + slog/sloghex.c \ + slog/slogfil.c \ + slog/slog.c \ + slog/qmem.c \ + ssec0/ssecusr0.c \ + util/time_str.c \ + util/sx_enc.c \ + util/sx_dec.c \ + util/sx_data.c \ + util/sx_axs4d.c \ + util/str_util.c \ + util/stime.c \ + util/stdtime_w32.c \ + util/stdtime_quadlib.c \ + util/stdtime_mms_utctime.c \ + util/stdtime_mms_btime.c \ + util/stdtime.c \ + util/sclstore.c \ + util/sclparse.c \ + util/scl_log.c \ + util/glbsem_unix.c \ + util/glbsem.c \ + util/gensock2.c \ + util/genlists.c \ + util/cfg_util.c +OBJECTS = debug/mmslib.o \ + debug/asn1r.o \ + debug/are_vstr.o \ + debug/are_utc.o \ + debug/are_time.o \ + debug/are_ostr.o \ + debug/are_objd.o \ + debug/are_int.o \ + debug/are_flt.o \ + debug/are_delm.o \ + debug/are_btod.o \ + debug/are_bstr.o \ + debug/are_bool.o \ + debug/ard_vstr.o \ + debug/ard_utc.o \ + debug/ard_time.o \ + debug/ard_strn.o \ + debug/ard_ostr.o \ + debug/ard_objd.o \ + debug/ard_int.o \ + debug/ard_idnt.o \ + debug/ard_flt.o \ + debug/ard_delm.o \ + debug/ard_btod.o \ + debug/ard_bstr.o \ + debug/ard_bool.o \ + debug/mem_chks.o \ + debug/rs_write.o \ + debug/rs_ustat.o \ + debug/rs_trige.o \ + debug/rs_stat.o \ + debug/rs_repee.o \ + debug/rs_repec.o \ + debug/rs_repea.o \ + debug/rs_read.o \ + debug/rs_namel.o \ + debug/rs_init.o \ + debug/rs_info.o \ + debug/rs_ident.o \ + debug/rs_getvl.o \ + debug/rs_getva.o \ + debug/rs_getty.o \ + debug/rs_getpi.o \ + debug/rs_getee.o \ + debug/rs_getec.o \ + debug/rs_getea.o \ + debug/rs_getdo.o \ + debug/rs_getcl.o \ + debug/rs_evnot.o \ + debug/rs_defee.o \ + debug/rs_concl.o \ + debug/rs_cancl.o \ + debug/rs_ackev.o \ + debug/rq_write.o \ + debug/rq_ustat.o \ + debug/rq_trige.o \ + debug/rq_stat.o \ + debug/rq_repee.o \ + debug/rq_repec.o \ + debug/rq_repea.o \ + debug/rq_read.o \ + debug/rq_namel.o \ + debug/rq_init.o \ + debug/rq_info.o \ + debug/rq_ident.o \ + debug/rq_getvl.o \ + debug/rq_getva.o \ + debug/rq_getty.o \ + debug/rq_getpi.o \ + debug/rq_getee.o \ + debug/rq_getec.o \ + debug/rq_getea.o \ + debug/rq_getdo.o \ + debug/rq_getcl.o \ + debug/rq_evnot.o \ + debug/rq_defee.o \ + debug/rq_concl.o \ + debug/rq_cancl.o \ + debug/rq_ackev.o \ + debug/msdataas.o \ + debug/ms_tdef4.o \ + debug/ms_tdef2.o \ + debug/ms_tdef.o \ + debug/ms_size.o \ + debug/ms_ext.o \ + debug/mmsstat.o \ + debug/mmslvar.o \ + debug/mmsl_fin.o \ + debug/mmsinit.o \ + debug/mmsdtext.o \ + debug/mmsdec.o \ + debug/mmsdatat.o \ + debug/mmsdata.o \ + debug/mmsconcl.o \ + debug/mmscancl.o \ + debug/mms_tdef.o \ + debug/mms_rtaa.o \ + debug/mms_rej.o \ + debug/mms_err4.o \ + debug/mms_err3.o \ + debug/mms_err2.o \ + debug/mms_err.o \ + debug/mms_ced7.o \ + debug/mms_ced6.o \ + debug/mms_ced5.o \ + debug/mms_ced4.o \ + debug/mms_ced3.o \ + debug/mms_ced.o \ + debug/mms_aref.o \ + debug/mms_alta.o \ + debug/mms_adl.o \ + debug/rs_uploa.o \ + debug/rs_termu.o \ + debug/rs_termd.o \ + debug/rs_takec.o \ + debug/rs_store.o \ + debug/rs_stop.o \ + debug/rs_start.o \ + debug/rs_rssta.o \ + debug/rs_rspoo.o \ + debug/rs_rsent.o \ + debug/rs_resum.o \ + debug/rs_reset.o \ + debug/rs_renam.o \ + debug/rs_relct.o \ + debug/rs_rdupl.o \ + debug/rs_rddwn.o \ + debug/rs_outpu.o \ + debug/rs_obtfi.o \ + debug/rs_loadd.o \ + debug/rs_kill.o \ + debug/rs_jwrit.o \ + debug/rs_jstat.o \ + debug/rs_jread.o \ + debug/rs_jinit.o \ + debug/rs_jdele.o \ + debug/rs_jcrea.o \ + debug/rs_input.o \ + debug/rs_initu.o \ + debug/rs_initd.o \ + debug/rs_getsc.o \ + debug/rs_getas.o \ + debug/rs_getae.o \ + debug/rs_frena.o \ + debug/rs_fread.o \ + debug/rs_fopen.o \ + debug/rs_fdir.o \ + debug/rs_fdele.o \ + debug/rs_fclos.o \ + debug/rs_downl.o \ + debug/rs_delvl.o \ + debug/rs_delva.o \ + debug/rs_delty.o \ + debug/rs_delse.o \ + debug/rs_delpi.o \ + debug/rs_delee.o \ + debug/rs_delec.o \ + debug/rs_delea.o \ + debug/rs_deldo.o \ + debug/rs_defvl.o \ + debug/rs_defva.o \ + debug/rs_defty.o \ + debug/rs_defse.o \ + debug/rs_defsc.o \ + debug/rs_defec.o \ + debug/rs_defea.o \ + debug/rs_crepi.o \ + debug/rs_altee.o \ + debug/rs_altec.o \ + debug/rq_uploa.o \ + debug/rq_termu.o \ + debug/rq_termd.o \ + debug/rq_takec.o \ + debug/rq_store.o \ + debug/rq_stop.o \ + debug/rq_start.o \ + debug/rq_rssta.o \ + debug/rq_rspoo.o \ + debug/rq_rsent.o \ + debug/rq_resum.o \ + debug/rq_reset.o \ + debug/rq_renam.o \ + debug/rq_relct.o \ + debug/rq_rdupl.o \ + debug/rq_rddwn.o \ + debug/rq_outpu.o \ + debug/rq_obtfi.o \ + debug/rq_loadd.o \ + debug/rq_kill.o \ + debug/rq_jwrit.o \ + debug/rq_jstat.o \ + debug/rq_jread.o \ + debug/rq_jinit.o \ + debug/rq_jdele.o \ + debug/rq_jcrea.o \ + debug/rq_input.o \ + debug/rq_initu.o \ + debug/rq_initd.o \ + debug/rq_getsc.o \ + debug/rq_getas.o \ + debug/rq_getae.o \ + debug/rq_frena.o \ + debug/rq_fread.o \ + debug/rq_fopen.o \ + debug/rq_fdir.o \ + debug/rq_fdele.o \ + debug/rq_fclos.o \ + debug/rq_downl.o \ + debug/rq_delvl.o \ + debug/rq_delva.o \ + debug/rq_delty.o \ + debug/rq_delse.o \ + debug/rq_delpi.o \ + debug/rq_delee.o \ + debug/rq_delec.o \ + debug/rq_delea.o \ + debug/rq_deldo.o \ + debug/rq_defvl.o \ + debug/rq_defva.o \ + debug/rq_defty.o \ + debug/rq_defse.o \ + debug/rq_defsc.o \ + debug/rq_defec.o \ + debug/rq_defea.o \ + debug/rq_crepi.o \ + debug/rq_altee.o \ + debug/rq_altec.o \ + debug/mms_ced2.o \ + debug/mms_ced1.o \ + debug/sclproc.o \ + debug/s_write.o \ + debug/s_status.o \ + debug/s_read.o \ + debug/s_obtfi.o \ + debug/s_jstat.o \ + debug/s_jread.o \ + debug/s_jinit.o \ + debug/s_info.o \ + debug/s_ident.o \ + debug/s_getvla.o \ + debug/s_getvaa.o \ + debug/s_getnam.o \ + debug/s_getdom.o \ + debug/s_getcl.o \ + debug/s_fren.o \ + debug/s_fread.o \ + debug/s_fopen.o \ + debug/s_fdir.o \ + debug/s_fdel.o \ + debug/s_fclose.o \ + debug/s_delvl.o \ + debug/s_defvl.o \ + debug/s_concl.o \ + debug/s_cancel.o \ + debug/mvluleaf.o \ + debug/mvlu_sbo.o \ + debug/mvlu_rt.o \ + debug/mvlu_rpt.o \ + debug/mvl61850_rpt.o \ + debug/mvl61850_ctl.o \ + debug/mvl61850.o \ + debug/mvl_var.o \ + debug/mvl_uca.o \ + debug/mvl_type.o \ + debug/mvl_typ2.o \ + debug/mvl_serv.o \ + debug/mvl_send.o \ + debug/mvl_objb.o \ + debug/mvl_obj.o \ + debug/mvl_ijou.o \ + debug/mvl_dtyp.o \ + debug/mvl_buf.o \ + debug/c_write.o \ + debug/c_status.o \ + debug/c_read.o \ + debug/c_obtfi.o \ + debug/c_jstat.o \ + debug/c_jread.o \ + debug/c_jinit.o \ + debug/c_info.o \ + debug/c_ident.o \ + debug/c_getvla.o \ + debug/c_getvar.o \ + debug/c_getnam.o \ + debug/c_getdom.o \ + debug/c_fren.o \ + debug/c_fread.o \ + debug/c_fopen.o \ + debug/c_fget.o \ + debug/c_fdir.o \ + debug/c_fdel.o \ + debug/c_fclose.o \ + debug/c_delvl.o \ + debug/c_defvl.o \ + debug/c_concl.o \ + debug/tpx_dec.o \ + debug/tp4port.o \ + debug/tp4_enc.o \ + debug/tp0main.o \ + debug/tp0callg.o \ + debug/tp0calld.o \ + debug/tp0_socks.o \ + debug/tp0_dec.o \ + debug/osicfgx.o \ + debug/lean_var.o \ + debug/lean_cfg.o \ + debug/cospmain.o \ + debug/cosp_enc.o \ + debug/cosp_dec.o \ + debug/coppdcpr.o \ + debug/coppdcp.o \ + debug/coppdaru.o \ + debug/copp_enc.o \ + debug/copp_dec.o \ + debug/checksum.o \ + debug/acse2var.o \ + debug/acse2enc.o \ + debug/acse2dib.o \ + debug/acse2dec.o \ + debug/slogmem.o \ + debug/slogipcs.o \ + debug/sloghex.o \ + debug/slogfil.o \ + debug/slog.o \ + debug/qmem.o \ + debug/ssecusr0.o \ + debug/time_str.o \ + debug/sx_enc.o \ + debug/sx_dec.o \ + debug/sx_data.o \ + debug/sx_axs4d.o \ + debug/str_util.o \ + debug/stime.o \ + debug/stdtime_w32.o \ + debug/stdtime_quadlib.o \ + debug/stdtime_mms_utctime.o \ + debug/stdtime_mms_btime.o \ + debug/stdtime.o \ + debug/sclstore.o \ + debug/sclparse.o \ + debug/scl_log.o \ + debug/glbsem_unix.o \ + debug/glbsem.o \ + debug/gensock2.o \ + debug/genlists.o \ + debug/cfg_util.o +DIST = ../../../qt-4.8.4/mkspecs/common/unix.conf \ + ../../../qt-4.8.4/mkspecs/common/linux.conf \ + ../../../qt-4.8.4/mkspecs/common/gcc-base.conf \ + ../../../qt-4.8.4/mkspecs/common/gcc-base-unix.conf \ + ../../../qt-4.8.4/mkspecs/common/g++-base.conf \ + ../../../qt-4.8.4/mkspecs/common/g++-unix.conf \ + ../../../qt-4.8.4/mkspecs/qconfig.pri \ + ../../../qt-4.8.4/mkspecs/features/qt_functions.prf \ + ../../../qt-4.8.4/mkspecs/features/qt_config.prf \ + ../../../qt-4.8.4/mkspecs/features/exclusive_builds.prf \ + ../../../qt-4.8.4/mkspecs/features/default_pre.prf \ + fe_common.pri \ + ../../../qt-4.8.4/mkspecs/features/debug.prf \ + ../../../qt-4.8.4/mkspecs/features/debug_and_release.prf \ + ../../../qt-4.8.4/mkspecs/features/default_post.prf \ + ../../../qt-4.8.4/mkspecs/features/build_pass.prf \ + ../../../qt-4.8.4/mkspecs/features/warn_off.prf \ + ../../../qt-4.8.4/mkspecs/features/staticlib.prf \ + ../../../qt-4.8.4/mkspecs/features/static.prf \ + ../../../qt-4.8.4/mkspecs/features/unix/gdb_dwarf_index.prf \ + ../../../qt-4.8.4/mkspecs/features/qt.prf \ + ../../../qt-4.8.4/mkspecs/features/unix/thread.prf \ + ../../../qt-4.8.4/mkspecs/features/moc.prf \ + ../../../qt-4.8.4/mkspecs/features/resources.prf \ + ../../../qt-4.8.4/mkspecs/features/uic.prf \ + ../../../qt-4.8.4/mkspecs/features/yacc.prf \ + ../../../qt-4.8.4/mkspecs/features/lex.prf \ + ../../../qt-4.8.4/mkspecs/features/include_source_dir.prf \ + mmslib.pro +QMAKE_TARGET = mmslibd +DESTDIR = +TARGET = libmmslibd.a + +first: all +####### Implicit rules + +.SUFFIXES: .o .c .cpp .cc .cxx .C + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<" + +####### Build rules + +all: Makefile.Debug $(TARGET) + +staticlib: $(TARGET) + +$(TARGET): $(OBJECTS) $(OBJCOMP) + -$(DEL_FILE) $(TARGET) + $(AR) $(TARGET) $(OBJECTS) + + +qmake: FORCE + @$(QMAKE) -o Makefile.Debug mmslib.pro + +dist: + @$(CHK_DIR_EXISTS) debug/mmslibd1.0.0 || $(MKDIR) debug/mmslibd1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) debug/mmslibd1.0.0/ && $(COPY_FILE) --parents mmslib.h inc/tp4api.h inc/tp4_log.h inc/tp4_encd.h inc/tp4.h inc/tp0_sock.h inc/time_str.h inc/sysincs.h inc/sx_log.h inc/sx_defs.h inc/sx_arb.h inc/STR_UTIL.H inc/stime.h inc/stdtime_w32.h inc/stdtime_tzrules.h inc/stdtime_timezone_csv.h inc/stdtime_stdint.h inc/stdtime_quadlib.h inc/stdtime_mms_utctime.h inc/stdtime_mms_btime.h inc/stdtime_enum_func.h inc/stdtime_enum_err.h inc/stdtime_endian.h inc/stdtime_config.h inc/stdtime.h inc/ssleLog.h inc/ssec_int.h inc/ssec.h inc/sock_log.h inc/smpval.h inc/smp_usr.h inc/smp_log.h inc/smp.h inc/Smem.h inc/slog.h inc/scrndefs.h inc/scl.h inc/rs_defs.h inc/rs_a.h inc/qmem.h inc/osillc.h inc/ntddosi.h inc/mvl_uca.h inc/mvl_log.h inc/mvl_defs.h inc/mvl_acse.h inc/mmslusec.h inc/mmslog.h inc/mmsldefs.h inc/mmsintr2.h inc/mmsefun.h inc/mmsdefs.h inc/mms_vvar.h inc/mms_pvmd.h inc/mms_pvar.h inc/mms_psem.h inc/mms_pprg.h inc/mms_pocs.h inc/mms_pjou.h inc/mms_pfil.h inc/mms_pevn.h inc/mms_perr.h inc/mms_pdom.h inc/mms_pcon.h inc/mms_mp.h inc/mms_log.h inc/mms_err.h inc/mms_dfun.h inc/mms_def2.h inc/mloguser.h inc/memlog.h inc/mem_chk.h inc/llcioctl.h inc/llcio.h inc/lean_a.h inc/gvaldefs.h inc/gse_mgmt.h inc/Goose.h inc/glbtypes.h inc/glbsem.h inc/glbopt.h inc/glberror.h inc/gensock2.h inc/gen_list.h inc/fkeydefs.h inc/ExceptionReport.h inc/ethsub.h inc/ethertyp.h inc/dibmatch.h inc/cosp_usr.h inc/cosp_log.h inc/cosp.h inc/copp_usr.h inc/copp_log.h inc/copp.h inc/conpack.h inc/clnpport.h inc/clnp_usr.h inc/clnp_tnt.h inc/clnp_sta.h inc/clnp_sne.h inc/clnp_log.h inc/clnp_llc.h inc/clnp.h inc/checksum.h inc/cfglog.h inc/cfg_util.h inc/asn1r.h inc/asn1log.h inc/asn1defs.h inc/arg.h inc/adlc_usr.h inc/adlc_sts.h inc/adlc_sm.h inc/adlc_log.h inc/adlc_dsm.h inc/adlc.h inc/acseauth.h inc/acse2usr.h inc/acse2log.h inc/acse2.h inc/mmsop_en/mmsop_en.h debug/mmslibd1.0.0/ && $(COPY_FILE) --parents mmslib.cpp asn1/asn1r.c asn1/are_vstr.c asn1/are_utc.c asn1/are_time.c asn1/are_ostr.c asn1/are_objd.c asn1/are_int.c asn1/are_flt.c asn1/are_delm.c asn1/are_btod.c asn1/are_bstr.c asn1/are_bool.c asn1/ard_vstr.c asn1/ard_utc.c asn1/ard_time.c asn1/ard_strn.c asn1/ard_ostr.c asn1/ard_objd.c asn1/ard_int.c asn1/ard_idnt.c asn1/ard_flt.c asn1/ard_delm.c asn1/ard_btod.c asn1/ard_bstr.c asn1/ard_bool.c mem/mem_chks.c mmsl/rs_write.c mmsl/rs_ustat.c mmsl/rs_trige.c mmsl/rs_stat.c mmsl/rs_repee.c mmsl/rs_repec.c mmsl/rs_repea.c mmsl/rs_read.c mmsl/rs_namel.c mmsl/rs_init.c mmsl/rs_info.c mmsl/rs_ident.c mmsl/rs_getvl.c mmsl/rs_getva.c mmsl/rs_getty.c mmsl/rs_getpi.c mmsl/rs_getee.c mmsl/rs_getec.c mmsl/rs_getea.c mmsl/rs_getdo.c mmsl/rs_getcl.c mmsl/rs_evnot.c mmsl/rs_defee.c mmsl/rs_concl.c mmsl/rs_cancl.c mmsl/rs_ackev.c mmsl/rq_write.c mmsl/rq_ustat.c mmsl/rq_trige.c mmsl/rq_stat.c mmsl/rq_repee.c mmsl/rq_repec.c mmsl/rq_repea.c mmsl/rq_read.c mmsl/rq_namel.c mmsl/rq_init.c mmsl/rq_info.c mmsl/rq_ident.c mmsl/rq_getvl.c mmsl/rq_getva.c mmsl/rq_getty.c mmsl/rq_getpi.c mmsl/rq_getee.c mmsl/rq_getec.c mmsl/rq_getea.c mmsl/rq_getdo.c mmsl/rq_getcl.c mmsl/rq_evnot.c mmsl/rq_defee.c mmsl/rq_concl.c mmsl/rq_cancl.c mmsl/rq_ackev.c mmsl/msdataas.c mmsl/ms_tdef4.c mmsl/ms_tdef2.c mmsl/ms_tdef.c mmsl/ms_size.c mmsl/ms_ext.c mmsl/mmsstat.c mmsl/mmslvar.c mmsl/mmsl_fin.c mmsl/mmsinit.c mmsl/mmsdtext.c mmsl/mmsdec.c mmsl/mmsdatat.c mmsl/mmsdata.c mmsl/mmsconcl.c mmsl/mmscancl.c mmsl/mms_tdef.c mmsl/mms_rtaa.c mmsl/mms_rej.c mmsl/mms_err4.c mmsl/mms_err3.c mmsl/mms_err2.c mmsl/mms_err.c mmsl/mms_ced7.c mmsl/mms_ced6.c mmsl/mms_ced5.c mmsl/mms_ced4.c mmsl/mms_ced3.c mmsl/mms_ced.c mmsl/mms_aref.c mmsl/mms_alta.c mmsl/mms_adl.c mmsle/rs_uploa.c mmsle/rs_termu.c mmsle/rs_termd.c mmsle/rs_takec.c mmsle/rs_store.c mmsle/rs_stop.c mmsle/rs_start.c mmsle/rs_rssta.c mmsle/rs_rspoo.c mmsle/rs_rsent.c mmsle/rs_resum.c mmsle/rs_reset.c mmsle/rs_renam.c mmsle/rs_relct.c mmsle/rs_rdupl.c mmsle/rs_rddwn.c mmsle/rs_outpu.c mmsle/rs_obtfi.c mmsle/rs_loadd.c mmsle/rs_kill.c mmsle/rs_jwrit.c mmsle/rs_jstat.c mmsle/rs_jread.c mmsle/rs_jinit.c mmsle/rs_jdele.c mmsle/rs_jcrea.c mmsle/rs_input.c mmsle/rs_initu.c mmsle/rs_initd.c mmsle/rs_getsc.c mmsle/rs_getas.c mmsle/rs_getae.c mmsle/rs_frena.c mmsle/rs_fread.c mmsle/rs_fopen.c mmsle/rs_fdir.c mmsle/rs_fdele.c mmsle/rs_fclos.c mmsle/rs_downl.c mmsle/rs_delvl.c mmsle/rs_delva.c mmsle/rs_delty.c mmsle/rs_delse.c mmsle/rs_delpi.c mmsle/rs_delee.c mmsle/rs_delec.c mmsle/rs_delea.c mmsle/rs_deldo.c mmsle/rs_defvl.c mmsle/rs_defva.c mmsle/rs_defty.c mmsle/rs_defse.c mmsle/rs_defsc.c mmsle/rs_defec.c mmsle/rs_defea.c mmsle/rs_crepi.c mmsle/rs_altee.c mmsle/rs_altec.c mmsle/rq_uploa.c mmsle/rq_termu.c mmsle/rq_termd.c mmsle/rq_takec.c mmsle/rq_store.c mmsle/rq_stop.c mmsle/rq_start.c mmsle/rq_rssta.c mmsle/rq_rspoo.c mmsle/rq_rsent.c mmsle/rq_resum.c mmsle/rq_reset.c mmsle/rq_renam.c mmsle/rq_relct.c mmsle/rq_rdupl.c mmsle/rq_rddwn.c mmsle/rq_outpu.c mmsle/rq_obtfi.c mmsle/rq_loadd.c mmsle/rq_kill.c mmsle/rq_jwrit.c mmsle/rq_jstat.c mmsle/rq_jread.c mmsle/rq_jinit.c mmsle/rq_jdele.c mmsle/rq_jcrea.c mmsle/rq_input.c mmsle/rq_initu.c mmsle/rq_initd.c mmsle/rq_getsc.c mmsle/rq_getas.c mmsle/rq_getae.c mmsle/rq_frena.c mmsle/rq_fread.c mmsle/rq_fopen.c mmsle/rq_fdir.c mmsle/rq_fdele.c mmsle/rq_fclos.c mmsle/rq_downl.c mmsle/rq_delvl.c mmsle/rq_delva.c mmsle/rq_delty.c mmsle/rq_delse.c mmsle/rq_delpi.c mmsle/rq_delee.c mmsle/rq_delec.c mmsle/rq_delea.c mmsle/rq_deldo.c mmsle/rq_defvl.c mmsle/rq_defva.c mmsle/rq_defty.c mmsle/rq_defse.c mmsle/rq_defsc.c mmsle/rq_defec.c mmsle/rq_defea.c mmsle/rq_crepi.c mmsle/rq_altee.c mmsle/rq_altec.c mmsle/mms_ced2.c mmsle/mms_ced1.c mvlu/sclproc.c mvlu/s_write.c mvlu/s_status.c mvlu/s_read.c mvlu/s_obtfi.c mvlu/s_jstat.c mvlu/s_jread.c mvlu/s_jinit.c mvlu/s_info.c mvlu/s_ident.c mvlu/s_getvla.c mvlu/s_getvaa.c mvlu/s_getnam.c mvlu/s_getdom.c mvlu/s_getcl.c mvlu/s_fren.c mvlu/s_fread.c mvlu/s_fopen.c mvlu/s_fdir.c mvlu/s_fdel.c mvlu/s_fclose.c mvlu/s_delvl.c mvlu/s_defvl.c mvlu/s_concl.c mvlu/s_cancel.c mvlu/mvluleaf.c mvlu/mvlu_sbo.c mvlu/mvlu_rt.c mvlu/mvlu_rpt.c mvlu/mvl61850_rpt.c mvlu/mvl61850_ctl.c mvlu/mvl61850.c mvlu/mvl_var.c mvlu/mvl_uca.c mvlu/mvl_type.c mvlu/mvl_typ2.c mvlu/mvl_serv.c mvlu/mvl_send.c mvlu/mvl_objb.c mvlu/mvl_obj.c mvlu/mvl_ijou.c mvlu/mvl_dtyp.c mvlu/mvl_buf.c mvlu/c_write.c mvlu/c_status.c mvlu/c_read.c mvlu/c_obtfi.c mvlu/c_jstat.c mvlu/c_jread.c mvlu/c_jinit.c mvlu/c_info.c mvlu/c_ident.c mvlu/c_getvla.c mvlu/c_getvar.c mvlu/c_getnam.c mvlu/c_getdom.c mvlu/c_fren.c mvlu/c_fread.c mvlu/c_fopen.c mvlu/c_fget.c mvlu/c_fdir.c mvlu/c_fdel.c mvlu/c_fclose.c mvlu/c_delvl.c mvlu/c_defvl.c mvlu/c_concl.c ositcps/tpx_dec.c ositcps/tp4port.c ositcps/tp4_enc.c ositcps/tp0main.c ositcps/tp0callg.c ositcps/tp0calld.c ositcps/tp0_socks.c ositcps/tp0_dec.c ositcps/osicfgx.c ositcps/lean_var.c ositcps/lean_cfg.c ositcps/cospmain.c ositcps/cosp_enc.c ositcps/cosp_dec.c ositcps/coppdcpr.c ositcps/coppdcp.c ositcps/coppdaru.c ositcps/copp_enc.c ositcps/copp_dec.c ositcps/checksum.c ositcps/acse2var.c ositcps/acse2enc.c ositcps/acse2dib.c ositcps/acse2dec.c slog/slogmem.c slog/slogipcs.c slog/sloghex.c slog/slogfil.c slog/slog.c slog/qmem.c ssec0/ssecusr0.c util/time_str.c util/sx_enc.c util/sx_dec.c util/sx_data.c util/sx_axs4d.c util/str_util.c util/stime.c util/stdtime_w32.c util/stdtime_quadlib.c util/stdtime_mms_utctime.c util/stdtime_mms_btime.c util/stdtime.c util/sclstore.c util/sclparse.c util/scl_log.c util/glbsem_unix.c util/glbsem.c util/gensock2.c util/genlists.c util/cfg_util.c debug/mmslibd1.0.0/ && (cd `dirname debug/mmslibd1.0.0` && $(TAR) mmslibd1.0.0.tar mmslibd1.0.0 && $(COMPRESS) mmslibd1.0.0.tar) && $(MOVE) `dirname debug/mmslibd1.0.0`/mmslibd1.0.0.tar.gz . && $(DEL_FILE) -r debug/mmslibd1.0.0 + + +clean:compiler_clean + -$(DEL_FILE) $(OBJECTS) + -$(DEL_FILE) *~ core *.core + + +####### Sub-libraries + +distclean: clean + -$(DEL_FILE) $(TARGET) + -$(DEL_FILE) Makefile.Debug + + +check: first + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all + +compiler_moc_header_make_all: +compiler_moc_header_clean: +compiler_rcc_make_all: +compiler_rcc_clean: +compiler_image_collection_make_all: qmake_image_collection.cpp +compiler_image_collection_clean: + -$(DEL_FILE) qmake_image_collection.cpp +compiler_moc_source_make_all: +compiler_moc_source_clean: +compiler_uic_make_all: +compiler_uic_clean: +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: + +####### Compile + +debug/mmslib.o: mmslib.cpp mmslib.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o debug/mmslib.o mmslib.cpp + +debug/asn1r.o: asn1/asn1r.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/asn1r.o asn1/asn1r.c + +debug/are_vstr.o: asn1/are_vstr.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/are_vstr.o asn1/are_vstr.c + +debug/are_utc.o: asn1/are_utc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/are_utc.o asn1/are_utc.c + +debug/are_time.o: asn1/are_time.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/are_time.o asn1/are_time.c + +debug/are_ostr.o: asn1/are_ostr.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/are_ostr.o asn1/are_ostr.c + +debug/are_objd.o: asn1/are_objd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/are_objd.o asn1/are_objd.c + +debug/are_int.o: asn1/are_int.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/are_int.o asn1/are_int.c + +debug/are_flt.o: asn1/are_flt.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/are_flt.o asn1/are_flt.c + +debug/are_delm.o: asn1/are_delm.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/are_delm.o asn1/are_delm.c + +debug/are_btod.o: asn1/are_btod.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/are_btod.o asn1/are_btod.c + +debug/are_bstr.o: asn1/are_bstr.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/are_bstr.o asn1/are_bstr.c + +debug/are_bool.o: asn1/are_bool.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/are_bool.o asn1/are_bool.c + +debug/ard_vstr.o: asn1/ard_vstr.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ard_vstr.o asn1/ard_vstr.c + +debug/ard_utc.o: asn1/ard_utc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ard_utc.o asn1/ard_utc.c + +debug/ard_time.o: asn1/ard_time.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ard_time.o asn1/ard_time.c + +debug/ard_strn.o: asn1/ard_strn.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ard_strn.o asn1/ard_strn.c + +debug/ard_ostr.o: asn1/ard_ostr.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ard_ostr.o asn1/ard_ostr.c + +debug/ard_objd.o: asn1/ard_objd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ard_objd.o asn1/ard_objd.c + +debug/ard_int.o: asn1/ard_int.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ard_int.o asn1/ard_int.c + +debug/ard_idnt.o: asn1/ard_idnt.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ard_idnt.o asn1/ard_idnt.c + +debug/ard_flt.o: asn1/ard_flt.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ard_flt.o asn1/ard_flt.c + +debug/ard_delm.o: asn1/ard_delm.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ard_delm.o asn1/ard_delm.c + +debug/ard_btod.o: asn1/ard_btod.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ard_btod.o asn1/ard_btod.c + +debug/ard_bstr.o: asn1/ard_bstr.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ard_bstr.o asn1/ard_bstr.c + +debug/ard_bool.o: asn1/ard_bool.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ard_bool.o asn1/ard_bool.c + +debug/mem_chks.o: mem/mem_chks.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mem_chks.o mem/mem_chks.c + +debug/rs_write.o: mmsl/rs_write.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_write.o mmsl/rs_write.c + +debug/rs_ustat.o: mmsl/rs_ustat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_ustat.o mmsl/rs_ustat.c + +debug/rs_trige.o: mmsl/rs_trige.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_trige.o mmsl/rs_trige.c + +debug/rs_stat.o: mmsl/rs_stat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_stat.o mmsl/rs_stat.c + +debug/rs_repee.o: mmsl/rs_repee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_repee.o mmsl/rs_repee.c + +debug/rs_repec.o: mmsl/rs_repec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_repec.o mmsl/rs_repec.c + +debug/rs_repea.o: mmsl/rs_repea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_repea.o mmsl/rs_repea.c + +debug/rs_read.o: mmsl/rs_read.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_read.o mmsl/rs_read.c + +debug/rs_namel.o: mmsl/rs_namel.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_namel.o mmsl/rs_namel.c + +debug/rs_init.o: mmsl/rs_init.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_init.o mmsl/rs_init.c + +debug/rs_info.o: mmsl/rs_info.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_info.o mmsl/rs_info.c + +debug/rs_ident.o: mmsl/rs_ident.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_ident.o mmsl/rs_ident.c + +debug/rs_getvl.o: mmsl/rs_getvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_getvl.o mmsl/rs_getvl.c + +debug/rs_getva.o: mmsl/rs_getva.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_getva.o mmsl/rs_getva.c + +debug/rs_getty.o: mmsl/rs_getty.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_getty.o mmsl/rs_getty.c + +debug/rs_getpi.o: mmsl/rs_getpi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_getpi.o mmsl/rs_getpi.c + +debug/rs_getee.o: mmsl/rs_getee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_getee.o mmsl/rs_getee.c + +debug/rs_getec.o: mmsl/rs_getec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_getec.o mmsl/rs_getec.c + +debug/rs_getea.o: mmsl/rs_getea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_getea.o mmsl/rs_getea.c + +debug/rs_getdo.o: mmsl/rs_getdo.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_getdo.o mmsl/rs_getdo.c + +debug/rs_getcl.o: mmsl/rs_getcl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_getcl.o mmsl/rs_getcl.c + +debug/rs_evnot.o: mmsl/rs_evnot.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_evnot.o mmsl/rs_evnot.c + +debug/rs_defee.o: mmsl/rs_defee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_defee.o mmsl/rs_defee.c + +debug/rs_concl.o: mmsl/rs_concl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_concl.o mmsl/rs_concl.c + +debug/rs_cancl.o: mmsl/rs_cancl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_cancl.o mmsl/rs_cancl.c + +debug/rs_ackev.o: mmsl/rs_ackev.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_ackev.o mmsl/rs_ackev.c + +debug/rq_write.o: mmsl/rq_write.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_write.o mmsl/rq_write.c + +debug/rq_ustat.o: mmsl/rq_ustat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_ustat.o mmsl/rq_ustat.c + +debug/rq_trige.o: mmsl/rq_trige.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_trige.o mmsl/rq_trige.c + +debug/rq_stat.o: mmsl/rq_stat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_stat.o mmsl/rq_stat.c + +debug/rq_repee.o: mmsl/rq_repee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_repee.o mmsl/rq_repee.c + +debug/rq_repec.o: mmsl/rq_repec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_repec.o mmsl/rq_repec.c + +debug/rq_repea.o: mmsl/rq_repea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_repea.o mmsl/rq_repea.c + +debug/rq_read.o: mmsl/rq_read.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_read.o mmsl/rq_read.c + +debug/rq_namel.o: mmsl/rq_namel.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_namel.o mmsl/rq_namel.c + +debug/rq_init.o: mmsl/rq_init.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_init.o mmsl/rq_init.c + +debug/rq_info.o: mmsl/rq_info.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_info.o mmsl/rq_info.c + +debug/rq_ident.o: mmsl/rq_ident.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_ident.o mmsl/rq_ident.c + +debug/rq_getvl.o: mmsl/rq_getvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_getvl.o mmsl/rq_getvl.c + +debug/rq_getva.o: mmsl/rq_getva.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_getva.o mmsl/rq_getva.c + +debug/rq_getty.o: mmsl/rq_getty.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_getty.o mmsl/rq_getty.c + +debug/rq_getpi.o: mmsl/rq_getpi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_getpi.o mmsl/rq_getpi.c + +debug/rq_getee.o: mmsl/rq_getee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_getee.o mmsl/rq_getee.c + +debug/rq_getec.o: mmsl/rq_getec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_getec.o mmsl/rq_getec.c + +debug/rq_getea.o: mmsl/rq_getea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_getea.o mmsl/rq_getea.c + +debug/rq_getdo.o: mmsl/rq_getdo.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_getdo.o mmsl/rq_getdo.c + +debug/rq_getcl.o: mmsl/rq_getcl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_getcl.o mmsl/rq_getcl.c + +debug/rq_evnot.o: mmsl/rq_evnot.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_evnot.o mmsl/rq_evnot.c + +debug/rq_defee.o: mmsl/rq_defee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_defee.o mmsl/rq_defee.c + +debug/rq_concl.o: mmsl/rq_concl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_concl.o mmsl/rq_concl.c + +debug/rq_cancl.o: mmsl/rq_cancl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_cancl.o mmsl/rq_cancl.c + +debug/rq_ackev.o: mmsl/rq_ackev.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_ackev.o mmsl/rq_ackev.c + +debug/msdataas.o: mmsl/msdataas.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/msdataas.o mmsl/msdataas.c + +debug/ms_tdef4.o: mmsl/ms_tdef4.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ms_tdef4.o mmsl/ms_tdef4.c + +debug/ms_tdef2.o: mmsl/ms_tdef2.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ms_tdef2.o mmsl/ms_tdef2.c + +debug/ms_tdef.o: mmsl/ms_tdef.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ms_tdef.o mmsl/ms_tdef.c + +debug/ms_size.o: mmsl/ms_size.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ms_size.o mmsl/ms_size.c + +debug/ms_ext.o: mmsl/ms_ext.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ms_ext.o mmsl/ms_ext.c + +debug/mmsstat.o: mmsl/mmsstat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mmsstat.o mmsl/mmsstat.c + +debug/mmslvar.o: mmsl/mmslvar.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mmslvar.o mmsl/mmslvar.c + +debug/mmsl_fin.o: mmsl/mmsl_fin.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mmsl_fin.o mmsl/mmsl_fin.c + +debug/mmsinit.o: mmsl/mmsinit.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mmsinit.o mmsl/mmsinit.c + +debug/mmsdtext.o: mmsl/mmsdtext.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mmsdtext.o mmsl/mmsdtext.c + +debug/mmsdec.o: mmsl/mmsdec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mmsdec.o mmsl/mmsdec.c + +debug/mmsdatat.o: mmsl/mmsdatat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mmsdatat.o mmsl/mmsdatat.c + +debug/mmsdata.o: mmsl/mmsdata.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mmsdata.o mmsl/mmsdata.c + +debug/mmsconcl.o: mmsl/mmsconcl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mmsconcl.o mmsl/mmsconcl.c + +debug/mmscancl.o: mmsl/mmscancl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mmscancl.o mmsl/mmscancl.c + +debug/mms_tdef.o: mmsl/mms_tdef.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_tdef.o mmsl/mms_tdef.c + +debug/mms_rtaa.o: mmsl/mms_rtaa.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_rtaa.o mmsl/mms_rtaa.c + +debug/mms_rej.o: mmsl/mms_rej.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_rej.o mmsl/mms_rej.c + +debug/mms_err4.o: mmsl/mms_err4.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_err4.o mmsl/mms_err4.c + +debug/mms_err3.o: mmsl/mms_err3.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_err3.o mmsl/mms_err3.c + +debug/mms_err2.o: mmsl/mms_err2.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_err2.o mmsl/mms_err2.c + +debug/mms_err.o: mmsl/mms_err.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_err.o mmsl/mms_err.c + +debug/mms_ced7.o: mmsl/mms_ced7.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_ced7.o mmsl/mms_ced7.c + +debug/mms_ced6.o: mmsl/mms_ced6.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_ced6.o mmsl/mms_ced6.c + +debug/mms_ced5.o: mmsl/mms_ced5.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_ced5.o mmsl/mms_ced5.c + +debug/mms_ced4.o: mmsl/mms_ced4.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_ced4.o mmsl/mms_ced4.c + +debug/mms_ced3.o: mmsl/mms_ced3.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_ced3.o mmsl/mms_ced3.c + +debug/mms_ced.o: mmsl/mms_ced.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_ced.o mmsl/mms_ced.c + +debug/mms_aref.o: mmsl/mms_aref.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_aref.o mmsl/mms_aref.c + +debug/mms_alta.o: mmsl/mms_alta.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_alta.o mmsl/mms_alta.c + +debug/mms_adl.o: mmsl/mms_adl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_adl.o mmsl/mms_adl.c + +debug/rs_uploa.o: mmsle/rs_uploa.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_uploa.o mmsle/rs_uploa.c + +debug/rs_termu.o: mmsle/rs_termu.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_termu.o mmsle/rs_termu.c + +debug/rs_termd.o: mmsle/rs_termd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_termd.o mmsle/rs_termd.c + +debug/rs_takec.o: mmsle/rs_takec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_takec.o mmsle/rs_takec.c + +debug/rs_store.o: mmsle/rs_store.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_store.o mmsle/rs_store.c + +debug/rs_stop.o: mmsle/rs_stop.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_stop.o mmsle/rs_stop.c + +debug/rs_start.o: mmsle/rs_start.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_start.o mmsle/rs_start.c + +debug/rs_rssta.o: mmsle/rs_rssta.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_rssta.o mmsle/rs_rssta.c + +debug/rs_rspoo.o: mmsle/rs_rspoo.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_rspoo.o mmsle/rs_rspoo.c + +debug/rs_rsent.o: mmsle/rs_rsent.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_rsent.o mmsle/rs_rsent.c + +debug/rs_resum.o: mmsle/rs_resum.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_resum.o mmsle/rs_resum.c + +debug/rs_reset.o: mmsle/rs_reset.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_reset.o mmsle/rs_reset.c + +debug/rs_renam.o: mmsle/rs_renam.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_renam.o mmsle/rs_renam.c + +debug/rs_relct.o: mmsle/rs_relct.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_relct.o mmsle/rs_relct.c + +debug/rs_rdupl.o: mmsle/rs_rdupl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_rdupl.o mmsle/rs_rdupl.c + +debug/rs_rddwn.o: mmsle/rs_rddwn.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_rddwn.o mmsle/rs_rddwn.c + +debug/rs_outpu.o: mmsle/rs_outpu.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_outpu.o mmsle/rs_outpu.c + +debug/rs_obtfi.o: mmsle/rs_obtfi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_obtfi.o mmsle/rs_obtfi.c + +debug/rs_loadd.o: mmsle/rs_loadd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_loadd.o mmsle/rs_loadd.c + +debug/rs_kill.o: mmsle/rs_kill.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_kill.o mmsle/rs_kill.c + +debug/rs_jwrit.o: mmsle/rs_jwrit.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_jwrit.o mmsle/rs_jwrit.c + +debug/rs_jstat.o: mmsle/rs_jstat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_jstat.o mmsle/rs_jstat.c + +debug/rs_jread.o: mmsle/rs_jread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_jread.o mmsle/rs_jread.c + +debug/rs_jinit.o: mmsle/rs_jinit.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_jinit.o mmsle/rs_jinit.c + +debug/rs_jdele.o: mmsle/rs_jdele.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_jdele.o mmsle/rs_jdele.c + +debug/rs_jcrea.o: mmsle/rs_jcrea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_jcrea.o mmsle/rs_jcrea.c + +debug/rs_input.o: mmsle/rs_input.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_input.o mmsle/rs_input.c + +debug/rs_initu.o: mmsle/rs_initu.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_initu.o mmsle/rs_initu.c + +debug/rs_initd.o: mmsle/rs_initd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_initd.o mmsle/rs_initd.c + +debug/rs_getsc.o: mmsle/rs_getsc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_getsc.o mmsle/rs_getsc.c + +debug/rs_getas.o: mmsle/rs_getas.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_getas.o mmsle/rs_getas.c + +debug/rs_getae.o: mmsle/rs_getae.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_getae.o mmsle/rs_getae.c + +debug/rs_frena.o: mmsle/rs_frena.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_frena.o mmsle/rs_frena.c + +debug/rs_fread.o: mmsle/rs_fread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_fread.o mmsle/rs_fread.c + +debug/rs_fopen.o: mmsle/rs_fopen.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_fopen.o mmsle/rs_fopen.c + +debug/rs_fdir.o: mmsle/rs_fdir.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_fdir.o mmsle/rs_fdir.c + +debug/rs_fdele.o: mmsle/rs_fdele.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_fdele.o mmsle/rs_fdele.c + +debug/rs_fclos.o: mmsle/rs_fclos.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_fclos.o mmsle/rs_fclos.c + +debug/rs_downl.o: mmsle/rs_downl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_downl.o mmsle/rs_downl.c + +debug/rs_delvl.o: mmsle/rs_delvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_delvl.o mmsle/rs_delvl.c + +debug/rs_delva.o: mmsle/rs_delva.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_delva.o mmsle/rs_delva.c + +debug/rs_delty.o: mmsle/rs_delty.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_delty.o mmsle/rs_delty.c + +debug/rs_delse.o: mmsle/rs_delse.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_delse.o mmsle/rs_delse.c + +debug/rs_delpi.o: mmsle/rs_delpi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_delpi.o mmsle/rs_delpi.c + +debug/rs_delee.o: mmsle/rs_delee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_delee.o mmsle/rs_delee.c + +debug/rs_delec.o: mmsle/rs_delec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_delec.o mmsle/rs_delec.c + +debug/rs_delea.o: mmsle/rs_delea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_delea.o mmsle/rs_delea.c + +debug/rs_deldo.o: mmsle/rs_deldo.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_deldo.o mmsle/rs_deldo.c + +debug/rs_defvl.o: mmsle/rs_defvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_defvl.o mmsle/rs_defvl.c + +debug/rs_defva.o: mmsle/rs_defva.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_defva.o mmsle/rs_defva.c + +debug/rs_defty.o: mmsle/rs_defty.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_defty.o mmsle/rs_defty.c + +debug/rs_defse.o: mmsle/rs_defse.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_defse.o mmsle/rs_defse.c + +debug/rs_defsc.o: mmsle/rs_defsc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_defsc.o mmsle/rs_defsc.c + +debug/rs_defec.o: mmsle/rs_defec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_defec.o mmsle/rs_defec.c + +debug/rs_defea.o: mmsle/rs_defea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_defea.o mmsle/rs_defea.c + +debug/rs_crepi.o: mmsle/rs_crepi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_crepi.o mmsle/rs_crepi.c + +debug/rs_altee.o: mmsle/rs_altee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_altee.o mmsle/rs_altee.c + +debug/rs_altec.o: mmsle/rs_altec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rs_altec.o mmsle/rs_altec.c + +debug/rq_uploa.o: mmsle/rq_uploa.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_uploa.o mmsle/rq_uploa.c + +debug/rq_termu.o: mmsle/rq_termu.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_termu.o mmsle/rq_termu.c + +debug/rq_termd.o: mmsle/rq_termd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_termd.o mmsle/rq_termd.c + +debug/rq_takec.o: mmsle/rq_takec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_takec.o mmsle/rq_takec.c + +debug/rq_store.o: mmsle/rq_store.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_store.o mmsle/rq_store.c + +debug/rq_stop.o: mmsle/rq_stop.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_stop.o mmsle/rq_stop.c + +debug/rq_start.o: mmsle/rq_start.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_start.o mmsle/rq_start.c + +debug/rq_rssta.o: mmsle/rq_rssta.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_rssta.o mmsle/rq_rssta.c + +debug/rq_rspoo.o: mmsle/rq_rspoo.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_rspoo.o mmsle/rq_rspoo.c + +debug/rq_rsent.o: mmsle/rq_rsent.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_rsent.o mmsle/rq_rsent.c + +debug/rq_resum.o: mmsle/rq_resum.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_resum.o mmsle/rq_resum.c + +debug/rq_reset.o: mmsle/rq_reset.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_reset.o mmsle/rq_reset.c + +debug/rq_renam.o: mmsle/rq_renam.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_renam.o mmsle/rq_renam.c + +debug/rq_relct.o: mmsle/rq_relct.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_relct.o mmsle/rq_relct.c + +debug/rq_rdupl.o: mmsle/rq_rdupl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_rdupl.o mmsle/rq_rdupl.c + +debug/rq_rddwn.o: mmsle/rq_rddwn.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_rddwn.o mmsle/rq_rddwn.c + +debug/rq_outpu.o: mmsle/rq_outpu.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_outpu.o mmsle/rq_outpu.c + +debug/rq_obtfi.o: mmsle/rq_obtfi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_obtfi.o mmsle/rq_obtfi.c + +debug/rq_loadd.o: mmsle/rq_loadd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_loadd.o mmsle/rq_loadd.c + +debug/rq_kill.o: mmsle/rq_kill.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_kill.o mmsle/rq_kill.c + +debug/rq_jwrit.o: mmsle/rq_jwrit.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_jwrit.o mmsle/rq_jwrit.c + +debug/rq_jstat.o: mmsle/rq_jstat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_jstat.o mmsle/rq_jstat.c + +debug/rq_jread.o: mmsle/rq_jread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_jread.o mmsle/rq_jread.c + +debug/rq_jinit.o: mmsle/rq_jinit.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_jinit.o mmsle/rq_jinit.c + +debug/rq_jdele.o: mmsle/rq_jdele.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_jdele.o mmsle/rq_jdele.c + +debug/rq_jcrea.o: mmsle/rq_jcrea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_jcrea.o mmsle/rq_jcrea.c + +debug/rq_input.o: mmsle/rq_input.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_input.o mmsle/rq_input.c + +debug/rq_initu.o: mmsle/rq_initu.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_initu.o mmsle/rq_initu.c + +debug/rq_initd.o: mmsle/rq_initd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_initd.o mmsle/rq_initd.c + +debug/rq_getsc.o: mmsle/rq_getsc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_getsc.o mmsle/rq_getsc.c + +debug/rq_getas.o: mmsle/rq_getas.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_getas.o mmsle/rq_getas.c + +debug/rq_getae.o: mmsle/rq_getae.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_getae.o mmsle/rq_getae.c + +debug/rq_frena.o: mmsle/rq_frena.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_frena.o mmsle/rq_frena.c + +debug/rq_fread.o: mmsle/rq_fread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_fread.o mmsle/rq_fread.c + +debug/rq_fopen.o: mmsle/rq_fopen.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_fopen.o mmsle/rq_fopen.c + +debug/rq_fdir.o: mmsle/rq_fdir.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_fdir.o mmsle/rq_fdir.c + +debug/rq_fdele.o: mmsle/rq_fdele.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_fdele.o mmsle/rq_fdele.c + +debug/rq_fclos.o: mmsle/rq_fclos.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_fclos.o mmsle/rq_fclos.c + +debug/rq_downl.o: mmsle/rq_downl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_downl.o mmsle/rq_downl.c + +debug/rq_delvl.o: mmsle/rq_delvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_delvl.o mmsle/rq_delvl.c + +debug/rq_delva.o: mmsle/rq_delva.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_delva.o mmsle/rq_delva.c + +debug/rq_delty.o: mmsle/rq_delty.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_delty.o mmsle/rq_delty.c + +debug/rq_delse.o: mmsle/rq_delse.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_delse.o mmsle/rq_delse.c + +debug/rq_delpi.o: mmsle/rq_delpi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_delpi.o mmsle/rq_delpi.c + +debug/rq_delee.o: mmsle/rq_delee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_delee.o mmsle/rq_delee.c + +debug/rq_delec.o: mmsle/rq_delec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_delec.o mmsle/rq_delec.c + +debug/rq_delea.o: mmsle/rq_delea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_delea.o mmsle/rq_delea.c + +debug/rq_deldo.o: mmsle/rq_deldo.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_deldo.o mmsle/rq_deldo.c + +debug/rq_defvl.o: mmsle/rq_defvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_defvl.o mmsle/rq_defvl.c + +debug/rq_defva.o: mmsle/rq_defva.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_defva.o mmsle/rq_defva.c + +debug/rq_defty.o: mmsle/rq_defty.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_defty.o mmsle/rq_defty.c + +debug/rq_defse.o: mmsle/rq_defse.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_defse.o mmsle/rq_defse.c + +debug/rq_defsc.o: mmsle/rq_defsc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_defsc.o mmsle/rq_defsc.c + +debug/rq_defec.o: mmsle/rq_defec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_defec.o mmsle/rq_defec.c + +debug/rq_defea.o: mmsle/rq_defea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_defea.o mmsle/rq_defea.c + +debug/rq_crepi.o: mmsle/rq_crepi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_crepi.o mmsle/rq_crepi.c + +debug/rq_altee.o: mmsle/rq_altee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_altee.o mmsle/rq_altee.c + +debug/rq_altec.o: mmsle/rq_altec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/rq_altec.o mmsle/rq_altec.c + +debug/mms_ced2.o: mmsle/mms_ced2.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_ced2.o mmsle/mms_ced2.c + +debug/mms_ced1.o: mmsle/mms_ced1.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mms_ced1.o mmsle/mms_ced1.c + +debug/sclproc.o: mvlu/sclproc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/sclproc.o mvlu/sclproc.c + +debug/s_write.o: mvlu/s_write.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_write.o mvlu/s_write.c + +debug/s_status.o: mvlu/s_status.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_status.o mvlu/s_status.c + +debug/s_read.o: mvlu/s_read.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_read.o mvlu/s_read.c + +debug/s_obtfi.o: mvlu/s_obtfi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_obtfi.o mvlu/s_obtfi.c + +debug/s_jstat.o: mvlu/s_jstat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_jstat.o mvlu/s_jstat.c + +debug/s_jread.o: mvlu/s_jread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_jread.o mvlu/s_jread.c + +debug/s_jinit.o: mvlu/s_jinit.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_jinit.o mvlu/s_jinit.c + +debug/s_info.o: mvlu/s_info.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_info.o mvlu/s_info.c + +debug/s_ident.o: mvlu/s_ident.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_ident.o mvlu/s_ident.c + +debug/s_getvla.o: mvlu/s_getvla.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_getvla.o mvlu/s_getvla.c + +debug/s_getvaa.o: mvlu/s_getvaa.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_getvaa.o mvlu/s_getvaa.c + +debug/s_getnam.o: mvlu/s_getnam.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_getnam.o mvlu/s_getnam.c + +debug/s_getdom.o: mvlu/s_getdom.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_getdom.o mvlu/s_getdom.c + +debug/s_getcl.o: mvlu/s_getcl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_getcl.o mvlu/s_getcl.c + +debug/s_fren.o: mvlu/s_fren.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_fren.o mvlu/s_fren.c + +debug/s_fread.o: mvlu/s_fread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_fread.o mvlu/s_fread.c + +debug/s_fopen.o: mvlu/s_fopen.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_fopen.o mvlu/s_fopen.c + +debug/s_fdir.o: mvlu/s_fdir.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_fdir.o mvlu/s_fdir.c + +debug/s_fdel.o: mvlu/s_fdel.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_fdel.o mvlu/s_fdel.c + +debug/s_fclose.o: mvlu/s_fclose.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_fclose.o mvlu/s_fclose.c + +debug/s_delvl.o: mvlu/s_delvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_delvl.o mvlu/s_delvl.c + +debug/s_defvl.o: mvlu/s_defvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_defvl.o mvlu/s_defvl.c + +debug/s_concl.o: mvlu/s_concl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_concl.o mvlu/s_concl.c + +debug/s_cancel.o: mvlu/s_cancel.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/s_cancel.o mvlu/s_cancel.c + +debug/mvluleaf.o: mvlu/mvluleaf.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvluleaf.o mvlu/mvluleaf.c + +debug/mvlu_sbo.o: mvlu/mvlu_sbo.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvlu_sbo.o mvlu/mvlu_sbo.c + +debug/mvlu_rt.o: mvlu/mvlu_rt.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvlu_rt.o mvlu/mvlu_rt.c + +debug/mvlu_rpt.o: mvlu/mvlu_rpt.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvlu_rpt.o mvlu/mvlu_rpt.c + +debug/mvl61850_rpt.o: mvlu/mvl61850_rpt.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvl61850_rpt.o mvlu/mvl61850_rpt.c + +debug/mvl61850_ctl.o: mvlu/mvl61850_ctl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvl61850_ctl.o mvlu/mvl61850_ctl.c + +debug/mvl61850.o: mvlu/mvl61850.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvl61850.o mvlu/mvl61850.c + +debug/mvl_var.o: mvlu/mvl_var.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvl_var.o mvlu/mvl_var.c + +debug/mvl_uca.o: mvlu/mvl_uca.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvl_uca.o mvlu/mvl_uca.c + +debug/mvl_type.o: mvlu/mvl_type.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvl_type.o mvlu/mvl_type.c + +debug/mvl_typ2.o: mvlu/mvl_typ2.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvl_typ2.o mvlu/mvl_typ2.c + +debug/mvl_serv.o: mvlu/mvl_serv.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvl_serv.o mvlu/mvl_serv.c + +debug/mvl_send.o: mvlu/mvl_send.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvl_send.o mvlu/mvl_send.c + +debug/mvl_objb.o: mvlu/mvl_objb.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvl_objb.o mvlu/mvl_objb.c + +debug/mvl_obj.o: mvlu/mvl_obj.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvl_obj.o mvlu/mvl_obj.c + +debug/mvl_ijou.o: mvlu/mvl_ijou.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvl_ijou.o mvlu/mvl_ijou.c + +debug/mvl_dtyp.o: mvlu/mvl_dtyp.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvl_dtyp.o mvlu/mvl_dtyp.c + +debug/mvl_buf.o: mvlu/mvl_buf.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/mvl_buf.o mvlu/mvl_buf.c + +debug/c_write.o: mvlu/c_write.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_write.o mvlu/c_write.c + +debug/c_status.o: mvlu/c_status.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_status.o mvlu/c_status.c + +debug/c_read.o: mvlu/c_read.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_read.o mvlu/c_read.c + +debug/c_obtfi.o: mvlu/c_obtfi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_obtfi.o mvlu/c_obtfi.c + +debug/c_jstat.o: mvlu/c_jstat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_jstat.o mvlu/c_jstat.c + +debug/c_jread.o: mvlu/c_jread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_jread.o mvlu/c_jread.c + +debug/c_jinit.o: mvlu/c_jinit.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_jinit.o mvlu/c_jinit.c + +debug/c_info.o: mvlu/c_info.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_info.o mvlu/c_info.c + +debug/c_ident.o: mvlu/c_ident.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_ident.o mvlu/c_ident.c + +debug/c_getvla.o: mvlu/c_getvla.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_getvla.o mvlu/c_getvla.c + +debug/c_getvar.o: mvlu/c_getvar.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_getvar.o mvlu/c_getvar.c + +debug/c_getnam.o: mvlu/c_getnam.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_getnam.o mvlu/c_getnam.c + +debug/c_getdom.o: mvlu/c_getdom.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_getdom.o mvlu/c_getdom.c + +debug/c_fren.o: mvlu/c_fren.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_fren.o mvlu/c_fren.c + +debug/c_fread.o: mvlu/c_fread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_fread.o mvlu/c_fread.c + +debug/c_fopen.o: mvlu/c_fopen.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_fopen.o mvlu/c_fopen.c + +debug/c_fget.o: mvlu/c_fget.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_fget.o mvlu/c_fget.c + +debug/c_fdir.o: mvlu/c_fdir.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_fdir.o mvlu/c_fdir.c + +debug/c_fdel.o: mvlu/c_fdel.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_fdel.o mvlu/c_fdel.c + +debug/c_fclose.o: mvlu/c_fclose.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_fclose.o mvlu/c_fclose.c + +debug/c_delvl.o: mvlu/c_delvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_delvl.o mvlu/c_delvl.c + +debug/c_defvl.o: mvlu/c_defvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_defvl.o mvlu/c_defvl.c + +debug/c_concl.o: mvlu/c_concl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/c_concl.o mvlu/c_concl.c + +debug/tpx_dec.o: ositcps/tpx_dec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/tpx_dec.o ositcps/tpx_dec.c + +debug/tp4port.o: ositcps/tp4port.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/tp4port.o ositcps/tp4port.c + +debug/tp4_enc.o: ositcps/tp4_enc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/tp4_enc.o ositcps/tp4_enc.c + +debug/tp0main.o: ositcps/tp0main.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/tp0main.o ositcps/tp0main.c + +debug/tp0callg.o: ositcps/tp0callg.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/tp0callg.o ositcps/tp0callg.c + +debug/tp0calld.o: ositcps/tp0calld.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/tp0calld.o ositcps/tp0calld.c + +debug/tp0_socks.o: ositcps/tp0_socks.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/tp0_socks.o ositcps/tp0_socks.c + +debug/tp0_dec.o: ositcps/tp0_dec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/tp0_dec.o ositcps/tp0_dec.c + +debug/osicfgx.o: ositcps/osicfgx.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/osicfgx.o ositcps/osicfgx.c + +debug/lean_var.o: ositcps/lean_var.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/lean_var.o ositcps/lean_var.c + +debug/lean_cfg.o: ositcps/lean_cfg.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/lean_cfg.o ositcps/lean_cfg.c + +debug/cospmain.o: ositcps/cospmain.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/cospmain.o ositcps/cospmain.c + +debug/cosp_enc.o: ositcps/cosp_enc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/cosp_enc.o ositcps/cosp_enc.c + +debug/cosp_dec.o: ositcps/cosp_dec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/cosp_dec.o ositcps/cosp_dec.c + +debug/coppdcpr.o: ositcps/coppdcpr.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/coppdcpr.o ositcps/coppdcpr.c + +debug/coppdcp.o: ositcps/coppdcp.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/coppdcp.o ositcps/coppdcp.c + +debug/coppdaru.o: ositcps/coppdaru.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/coppdaru.o ositcps/coppdaru.c + +debug/copp_enc.o: ositcps/copp_enc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/copp_enc.o ositcps/copp_enc.c + +debug/copp_dec.o: ositcps/copp_dec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/copp_dec.o ositcps/copp_dec.c + +debug/checksum.o: ositcps/checksum.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/checksum.o ositcps/checksum.c + +debug/acse2var.o: ositcps/acse2var.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/acse2var.o ositcps/acse2var.c + +debug/acse2enc.o: ositcps/acse2enc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/acse2enc.o ositcps/acse2enc.c + +debug/acse2dib.o: ositcps/acse2dib.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/acse2dib.o ositcps/acse2dib.c + +debug/acse2dec.o: ositcps/acse2dec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/acse2dec.o ositcps/acse2dec.c + +debug/slogmem.o: slog/slogmem.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/slogmem.o slog/slogmem.c + +debug/slogipcs.o: slog/slogipcs.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/slogipcs.o slog/slogipcs.c + +debug/sloghex.o: slog/sloghex.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/sloghex.o slog/sloghex.c + +debug/slogfil.o: slog/slogfil.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/slogfil.o slog/slogfil.c + +debug/slog.o: slog/slog.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/slog.o slog/slog.c + +debug/qmem.o: slog/qmem.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/qmem.o slog/qmem.c + +debug/ssecusr0.o: ssec0/ssecusr0.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/ssecusr0.o ssec0/ssecusr0.c + +debug/time_str.o: util/time_str.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/time_str.o util/time_str.c + +debug/sx_enc.o: util/sx_enc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/sx_enc.o util/sx_enc.c + +debug/sx_dec.o: util/sx_dec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/sx_dec.o util/sx_dec.c + +debug/sx_data.o: util/sx_data.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/sx_data.o util/sx_data.c + +debug/sx_axs4d.o: util/sx_axs4d.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/sx_axs4d.o util/sx_axs4d.c + +debug/str_util.o: util/str_util.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/str_util.o util/str_util.c + +debug/stime.o: util/stime.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/stime.o util/stime.c + +debug/stdtime_w32.o: util/stdtime_w32.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/stdtime_w32.o util/stdtime_w32.c + +debug/stdtime_quadlib.o: util/stdtime_quadlib.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/stdtime_quadlib.o util/stdtime_quadlib.c + +debug/stdtime_mms_utctime.o: util/stdtime_mms_utctime.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/stdtime_mms_utctime.o util/stdtime_mms_utctime.c + +debug/stdtime_mms_btime.o: util/stdtime_mms_btime.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/stdtime_mms_btime.o util/stdtime_mms_btime.c + +debug/stdtime.o: util/stdtime.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/stdtime.o util/stdtime.c + +debug/sclstore.o: util/sclstore.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/sclstore.o util/sclstore.c + +debug/sclparse.o: util/sclparse.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/sclparse.o util/sclparse.c + +debug/scl_log.o: util/scl_log.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/scl_log.o util/scl_log.c + +debug/glbsem_unix.o: util/glbsem_unix.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/glbsem_unix.o util/glbsem_unix.c + +debug/glbsem.o: util/glbsem.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/glbsem.o util/glbsem.c + +debug/gensock2.o: util/gensock2.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/gensock2.o util/gensock2.c + +debug/genlists.o: util/genlists.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/genlists.o util/genlists.c + +debug/cfg_util.o: util/cfg_util.c + $(CC) -c $(CFLAGS) $(INCPATH) -o debug/cfg_util.o util/cfg_util.c + +####### Install + +install_target: first FORCE + @$(CHK_DIR_EXISTS) $(INSTALL_ROOT)/usr/lib/ || $(MKDIR) $(INSTALL_ROOT)/usr/lib/ + -$(INSTALL_FILE) "$(TARGET)" "$(INSTALL_ROOT)/usr/lib/$(TARGET)" + +uninstall_target: FORCE + -$(DEL_FILE) "$(INSTALL_ROOT)/usr/lib/$(TARGET)" + -$(DEL_DIR) $(INSTALL_ROOT)/usr/lib/ + + +install: install_target FORCE + +uninstall: uninstall_target FORCE + +FORCE: + diff --git a/mmslib/Makefile.Release b/mmslib/Makefile.Release new file mode 100644 index 0000000..485230f --- /dev/null +++ b/mmslib/Makefile.Release @@ -0,0 +1,1899 @@ +############################################################################# +# Makefile for building: libmmslib.a +# Generated by qmake (2.01a) (Qt 4.8.4) on: ?? 10? 12 16:45:38 2025 +# Project: mmslib.pro +# Template: lib +############################################################################# + +####### Compiler, tools and options + +CC = gcc +CXX = g++ +DEFINES = -DDEBUG_SISCO -DMOSI -DLEAN_T -DMVL_UCA -DMMS_LITE -DTP0_ENABLED -DSTDTIME_ANSI -DFE_VERSION_64 -DQT_NO_DEBUG -DQT_CORE_LIB -DQT_SHARED +CFLAGS = -m64 -pipe -O2 -w -fPIC -D_REENTRANT $(DEFINES) +CXXFLAGS = -m64 -pipe -O2 -w -fPIC -D_REENTRANT $(DEFINES) +INCPATH = -I../../../qt-4.8.4/mkspecs/linux-g++-64 -I. -I../../../qt-4.8.4/include/QtCore -I../../../qt-4.8.4/include -Iinc -Iinc/mmsop_en -Irelease +AR = ar cqs +RANLIB = +QMAKE = /qt-4.8.4/bin/qmake +TAR = tar -cf +COMPRESS = gzip -9f +COPY = cp -f +SED = sed +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +STRIP = strip +INSTALL_FILE = install -m 644 -p +INSTALL_DIR = $(COPY_DIR) +INSTALL_PROGRAM = install -m 755 -p +DEL_FILE = rm -f +SYMLINK = ln -f -s +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p + +####### Output directory + +OBJECTS_DIR = release/ + +####### Files + +SOURCES = mmslib.cpp \ + asn1/asn1r.c \ + asn1/are_vstr.c \ + asn1/are_utc.c \ + asn1/are_time.c \ + asn1/are_ostr.c \ + asn1/are_objd.c \ + asn1/are_int.c \ + asn1/are_flt.c \ + asn1/are_delm.c \ + asn1/are_btod.c \ + asn1/are_bstr.c \ + asn1/are_bool.c \ + asn1/ard_vstr.c \ + asn1/ard_utc.c \ + asn1/ard_time.c \ + asn1/ard_strn.c \ + asn1/ard_ostr.c \ + asn1/ard_objd.c \ + asn1/ard_int.c \ + asn1/ard_idnt.c \ + asn1/ard_flt.c \ + asn1/ard_delm.c \ + asn1/ard_btod.c \ + asn1/ard_bstr.c \ + asn1/ard_bool.c \ + mem/mem_chks.c \ + mmsl/rs_write.c \ + mmsl/rs_ustat.c \ + mmsl/rs_trige.c \ + mmsl/rs_stat.c \ + mmsl/rs_repee.c \ + mmsl/rs_repec.c \ + mmsl/rs_repea.c \ + mmsl/rs_read.c \ + mmsl/rs_namel.c \ + mmsl/rs_init.c \ + mmsl/rs_info.c \ + mmsl/rs_ident.c \ + mmsl/rs_getvl.c \ + mmsl/rs_getva.c \ + mmsl/rs_getty.c \ + mmsl/rs_getpi.c \ + mmsl/rs_getee.c \ + mmsl/rs_getec.c \ + mmsl/rs_getea.c \ + mmsl/rs_getdo.c \ + mmsl/rs_getcl.c \ + mmsl/rs_evnot.c \ + mmsl/rs_defee.c \ + mmsl/rs_concl.c \ + mmsl/rs_cancl.c \ + mmsl/rs_ackev.c \ + mmsl/rq_write.c \ + mmsl/rq_ustat.c \ + mmsl/rq_trige.c \ + mmsl/rq_stat.c \ + mmsl/rq_repee.c \ + mmsl/rq_repec.c \ + mmsl/rq_repea.c \ + mmsl/rq_read.c \ + mmsl/rq_namel.c \ + mmsl/rq_init.c \ + mmsl/rq_info.c \ + mmsl/rq_ident.c \ + mmsl/rq_getvl.c \ + mmsl/rq_getva.c \ + mmsl/rq_getty.c \ + mmsl/rq_getpi.c \ + mmsl/rq_getee.c \ + mmsl/rq_getec.c \ + mmsl/rq_getea.c \ + mmsl/rq_getdo.c \ + mmsl/rq_getcl.c \ + mmsl/rq_evnot.c \ + mmsl/rq_defee.c \ + mmsl/rq_concl.c \ + mmsl/rq_cancl.c \ + mmsl/rq_ackev.c \ + mmsl/msdataas.c \ + mmsl/ms_tdef4.c \ + mmsl/ms_tdef2.c \ + mmsl/ms_tdef.c \ + mmsl/ms_size.c \ + mmsl/ms_ext.c \ + mmsl/mmsstat.c \ + mmsl/mmslvar.c \ + mmsl/mmsl_fin.c \ + mmsl/mmsinit.c \ + mmsl/mmsdtext.c \ + mmsl/mmsdec.c \ + mmsl/mmsdatat.c \ + mmsl/mmsdata.c \ + mmsl/mmsconcl.c \ + mmsl/mmscancl.c \ + mmsl/mms_tdef.c \ + mmsl/mms_rtaa.c \ + mmsl/mms_rej.c \ + mmsl/mms_err4.c \ + mmsl/mms_err3.c \ + mmsl/mms_err2.c \ + mmsl/mms_err.c \ + mmsl/mms_ced7.c \ + mmsl/mms_ced6.c \ + mmsl/mms_ced5.c \ + mmsl/mms_ced4.c \ + mmsl/mms_ced3.c \ + mmsl/mms_ced.c \ + mmsl/mms_aref.c \ + mmsl/mms_alta.c \ + mmsl/mms_adl.c \ + mmsle/rs_uploa.c \ + mmsle/rs_termu.c \ + mmsle/rs_termd.c \ + mmsle/rs_takec.c \ + mmsle/rs_store.c \ + mmsle/rs_stop.c \ + mmsle/rs_start.c \ + mmsle/rs_rssta.c \ + mmsle/rs_rspoo.c \ + mmsle/rs_rsent.c \ + mmsle/rs_resum.c \ + mmsle/rs_reset.c \ + mmsle/rs_renam.c \ + mmsle/rs_relct.c \ + mmsle/rs_rdupl.c \ + mmsle/rs_rddwn.c \ + mmsle/rs_outpu.c \ + mmsle/rs_obtfi.c \ + mmsle/rs_loadd.c \ + mmsle/rs_kill.c \ + mmsle/rs_jwrit.c \ + mmsle/rs_jstat.c \ + mmsle/rs_jread.c \ + mmsle/rs_jinit.c \ + mmsle/rs_jdele.c \ + mmsle/rs_jcrea.c \ + mmsle/rs_input.c \ + mmsle/rs_initu.c \ + mmsle/rs_initd.c \ + mmsle/rs_getsc.c \ + mmsle/rs_getas.c \ + mmsle/rs_getae.c \ + mmsle/rs_frena.c \ + mmsle/rs_fread.c \ + mmsle/rs_fopen.c \ + mmsle/rs_fdir.c \ + mmsle/rs_fdele.c \ + mmsle/rs_fclos.c \ + mmsle/rs_downl.c \ + mmsle/rs_delvl.c \ + mmsle/rs_delva.c \ + mmsle/rs_delty.c \ + mmsle/rs_delse.c \ + mmsle/rs_delpi.c \ + mmsle/rs_delee.c \ + mmsle/rs_delec.c \ + mmsle/rs_delea.c \ + mmsle/rs_deldo.c \ + mmsle/rs_defvl.c \ + mmsle/rs_defva.c \ + mmsle/rs_defty.c \ + mmsle/rs_defse.c \ + mmsle/rs_defsc.c \ + mmsle/rs_defec.c \ + mmsle/rs_defea.c \ + mmsle/rs_crepi.c \ + mmsle/rs_altee.c \ + mmsle/rs_altec.c \ + mmsle/rq_uploa.c \ + mmsle/rq_termu.c \ + mmsle/rq_termd.c \ + mmsle/rq_takec.c \ + mmsle/rq_store.c \ + mmsle/rq_stop.c \ + mmsle/rq_start.c \ + mmsle/rq_rssta.c \ + mmsle/rq_rspoo.c \ + mmsle/rq_rsent.c \ + mmsle/rq_resum.c \ + mmsle/rq_reset.c \ + mmsle/rq_renam.c \ + mmsle/rq_relct.c \ + mmsle/rq_rdupl.c \ + mmsle/rq_rddwn.c \ + mmsle/rq_outpu.c \ + mmsle/rq_obtfi.c \ + mmsle/rq_loadd.c \ + mmsle/rq_kill.c \ + mmsle/rq_jwrit.c \ + mmsle/rq_jstat.c \ + mmsle/rq_jread.c \ + mmsle/rq_jinit.c \ + mmsle/rq_jdele.c \ + mmsle/rq_jcrea.c \ + mmsle/rq_input.c \ + mmsle/rq_initu.c \ + mmsle/rq_initd.c \ + mmsle/rq_getsc.c \ + mmsle/rq_getas.c \ + mmsle/rq_getae.c \ + mmsle/rq_frena.c \ + mmsle/rq_fread.c \ + mmsle/rq_fopen.c \ + mmsle/rq_fdir.c \ + mmsle/rq_fdele.c \ + mmsle/rq_fclos.c \ + mmsle/rq_downl.c \ + mmsle/rq_delvl.c \ + mmsle/rq_delva.c \ + mmsle/rq_delty.c \ + mmsle/rq_delse.c \ + mmsle/rq_delpi.c \ + mmsle/rq_delee.c \ + mmsle/rq_delec.c \ + mmsle/rq_delea.c \ + mmsle/rq_deldo.c \ + mmsle/rq_defvl.c \ + mmsle/rq_defva.c \ + mmsle/rq_defty.c \ + mmsle/rq_defse.c \ + mmsle/rq_defsc.c \ + mmsle/rq_defec.c \ + mmsle/rq_defea.c \ + mmsle/rq_crepi.c \ + mmsle/rq_altee.c \ + mmsle/rq_altec.c \ + mmsle/mms_ced2.c \ + mmsle/mms_ced1.c \ + mvlu/sclproc.c \ + mvlu/s_write.c \ + mvlu/s_status.c \ + mvlu/s_read.c \ + mvlu/s_obtfi.c \ + mvlu/s_jstat.c \ + mvlu/s_jread.c \ + mvlu/s_jinit.c \ + mvlu/s_info.c \ + mvlu/s_ident.c \ + mvlu/s_getvla.c \ + mvlu/s_getvaa.c \ + mvlu/s_getnam.c \ + mvlu/s_getdom.c \ + mvlu/s_getcl.c \ + mvlu/s_fren.c \ + mvlu/s_fread.c \ + mvlu/s_fopen.c \ + mvlu/s_fdir.c \ + mvlu/s_fdel.c \ + mvlu/s_fclose.c \ + mvlu/s_delvl.c \ + mvlu/s_defvl.c \ + mvlu/s_concl.c \ + mvlu/s_cancel.c \ + mvlu/mvluleaf.c \ + mvlu/mvlu_sbo.c \ + mvlu/mvlu_rt.c \ + mvlu/mvlu_rpt.c \ + mvlu/mvl61850_rpt.c \ + mvlu/mvl61850_ctl.c \ + mvlu/mvl61850.c \ + mvlu/mvl_var.c \ + mvlu/mvl_uca.c \ + mvlu/mvl_type.c \ + mvlu/mvl_typ2.c \ + mvlu/mvl_serv.c \ + mvlu/mvl_send.c \ + mvlu/mvl_objb.c \ + mvlu/mvl_obj.c \ + mvlu/mvl_ijou.c \ + mvlu/mvl_dtyp.c \ + mvlu/mvl_buf.c \ + mvlu/c_write.c \ + mvlu/c_status.c \ + mvlu/c_read.c \ + mvlu/c_obtfi.c \ + mvlu/c_jstat.c \ + mvlu/c_jread.c \ + mvlu/c_jinit.c \ + mvlu/c_info.c \ + mvlu/c_ident.c \ + mvlu/c_getvla.c \ + mvlu/c_getvar.c \ + mvlu/c_getnam.c \ + mvlu/c_getdom.c \ + mvlu/c_fren.c \ + mvlu/c_fread.c \ + mvlu/c_fopen.c \ + mvlu/c_fget.c \ + mvlu/c_fdir.c \ + mvlu/c_fdel.c \ + mvlu/c_fclose.c \ + mvlu/c_delvl.c \ + mvlu/c_defvl.c \ + mvlu/c_concl.c \ + ositcps/tpx_dec.c \ + ositcps/tp4port.c \ + ositcps/tp4_enc.c \ + ositcps/tp0main.c \ + ositcps/tp0callg.c \ + ositcps/tp0calld.c \ + ositcps/tp0_socks.c \ + ositcps/tp0_dec.c \ + ositcps/osicfgx.c \ + ositcps/lean_var.c \ + ositcps/lean_cfg.c \ + ositcps/cospmain.c \ + ositcps/cosp_enc.c \ + ositcps/cosp_dec.c \ + ositcps/coppdcpr.c \ + ositcps/coppdcp.c \ + ositcps/coppdaru.c \ + ositcps/copp_enc.c \ + ositcps/copp_dec.c \ + ositcps/checksum.c \ + ositcps/acse2var.c \ + ositcps/acse2enc.c \ + ositcps/acse2dib.c \ + ositcps/acse2dec.c \ + slog/slogmem.c \ + slog/slogipcs.c \ + slog/sloghex.c \ + slog/slogfil.c \ + slog/slog.c \ + slog/qmem.c \ + ssec0/ssecusr0.c \ + util/time_str.c \ + util/sx_enc.c \ + util/sx_dec.c \ + util/sx_data.c \ + util/sx_axs4d.c \ + util/str_util.c \ + util/stime.c \ + util/stdtime_w32.c \ + util/stdtime_quadlib.c \ + util/stdtime_mms_utctime.c \ + util/stdtime_mms_btime.c \ + util/stdtime.c \ + util/sclstore.c \ + util/sclparse.c \ + util/scl_log.c \ + util/glbsem_unix.c \ + util/glbsem.c \ + util/gensock2.c \ + util/genlists.c \ + util/cfg_util.c +OBJECTS = release/mmslib.o \ + release/asn1r.o \ + release/are_vstr.o \ + release/are_utc.o \ + release/are_time.o \ + release/are_ostr.o \ + release/are_objd.o \ + release/are_int.o \ + release/are_flt.o \ + release/are_delm.o \ + release/are_btod.o \ + release/are_bstr.o \ + release/are_bool.o \ + release/ard_vstr.o \ + release/ard_utc.o \ + release/ard_time.o \ + release/ard_strn.o \ + release/ard_ostr.o \ + release/ard_objd.o \ + release/ard_int.o \ + release/ard_idnt.o \ + release/ard_flt.o \ + release/ard_delm.o \ + release/ard_btod.o \ + release/ard_bstr.o \ + release/ard_bool.o \ + release/mem_chks.o \ + release/rs_write.o \ + release/rs_ustat.o \ + release/rs_trige.o \ + release/rs_stat.o \ + release/rs_repee.o \ + release/rs_repec.o \ + release/rs_repea.o \ + release/rs_read.o \ + release/rs_namel.o \ + release/rs_init.o \ + release/rs_info.o \ + release/rs_ident.o \ + release/rs_getvl.o \ + release/rs_getva.o \ + release/rs_getty.o \ + release/rs_getpi.o \ + release/rs_getee.o \ + release/rs_getec.o \ + release/rs_getea.o \ + release/rs_getdo.o \ + release/rs_getcl.o \ + release/rs_evnot.o \ + release/rs_defee.o \ + release/rs_concl.o \ + release/rs_cancl.o \ + release/rs_ackev.o \ + release/rq_write.o \ + release/rq_ustat.o \ + release/rq_trige.o \ + release/rq_stat.o \ + release/rq_repee.o \ + release/rq_repec.o \ + release/rq_repea.o \ + release/rq_read.o \ + release/rq_namel.o \ + release/rq_init.o \ + release/rq_info.o \ + release/rq_ident.o \ + release/rq_getvl.o \ + release/rq_getva.o \ + release/rq_getty.o \ + release/rq_getpi.o \ + release/rq_getee.o \ + release/rq_getec.o \ + release/rq_getea.o \ + release/rq_getdo.o \ + release/rq_getcl.o \ + release/rq_evnot.o \ + release/rq_defee.o \ + release/rq_concl.o \ + release/rq_cancl.o \ + release/rq_ackev.o \ + release/msdataas.o \ + release/ms_tdef4.o \ + release/ms_tdef2.o \ + release/ms_tdef.o \ + release/ms_size.o \ + release/ms_ext.o \ + release/mmsstat.o \ + release/mmslvar.o \ + release/mmsl_fin.o \ + release/mmsinit.o \ + release/mmsdtext.o \ + release/mmsdec.o \ + release/mmsdatat.o \ + release/mmsdata.o \ + release/mmsconcl.o \ + release/mmscancl.o \ + release/mms_tdef.o \ + release/mms_rtaa.o \ + release/mms_rej.o \ + release/mms_err4.o \ + release/mms_err3.o \ + release/mms_err2.o \ + release/mms_err.o \ + release/mms_ced7.o \ + release/mms_ced6.o \ + release/mms_ced5.o \ + release/mms_ced4.o \ + release/mms_ced3.o \ + release/mms_ced.o \ + release/mms_aref.o \ + release/mms_alta.o \ + release/mms_adl.o \ + release/rs_uploa.o \ + release/rs_termu.o \ + release/rs_termd.o \ + release/rs_takec.o \ + release/rs_store.o \ + release/rs_stop.o \ + release/rs_start.o \ + release/rs_rssta.o \ + release/rs_rspoo.o \ + release/rs_rsent.o \ + release/rs_resum.o \ + release/rs_reset.o \ + release/rs_renam.o \ + release/rs_relct.o \ + release/rs_rdupl.o \ + release/rs_rddwn.o \ + release/rs_outpu.o \ + release/rs_obtfi.o \ + release/rs_loadd.o \ + release/rs_kill.o \ + release/rs_jwrit.o \ + release/rs_jstat.o \ + release/rs_jread.o \ + release/rs_jinit.o \ + release/rs_jdele.o \ + release/rs_jcrea.o \ + release/rs_input.o \ + release/rs_initu.o \ + release/rs_initd.o \ + release/rs_getsc.o \ + release/rs_getas.o \ + release/rs_getae.o \ + release/rs_frena.o \ + release/rs_fread.o \ + release/rs_fopen.o \ + release/rs_fdir.o \ + release/rs_fdele.o \ + release/rs_fclos.o \ + release/rs_downl.o \ + release/rs_delvl.o \ + release/rs_delva.o \ + release/rs_delty.o \ + release/rs_delse.o \ + release/rs_delpi.o \ + release/rs_delee.o \ + release/rs_delec.o \ + release/rs_delea.o \ + release/rs_deldo.o \ + release/rs_defvl.o \ + release/rs_defva.o \ + release/rs_defty.o \ + release/rs_defse.o \ + release/rs_defsc.o \ + release/rs_defec.o \ + release/rs_defea.o \ + release/rs_crepi.o \ + release/rs_altee.o \ + release/rs_altec.o \ + release/rq_uploa.o \ + release/rq_termu.o \ + release/rq_termd.o \ + release/rq_takec.o \ + release/rq_store.o \ + release/rq_stop.o \ + release/rq_start.o \ + release/rq_rssta.o \ + release/rq_rspoo.o \ + release/rq_rsent.o \ + release/rq_resum.o \ + release/rq_reset.o \ + release/rq_renam.o \ + release/rq_relct.o \ + release/rq_rdupl.o \ + release/rq_rddwn.o \ + release/rq_outpu.o \ + release/rq_obtfi.o \ + release/rq_loadd.o \ + release/rq_kill.o \ + release/rq_jwrit.o \ + release/rq_jstat.o \ + release/rq_jread.o \ + release/rq_jinit.o \ + release/rq_jdele.o \ + release/rq_jcrea.o \ + release/rq_input.o \ + release/rq_initu.o \ + release/rq_initd.o \ + release/rq_getsc.o \ + release/rq_getas.o \ + release/rq_getae.o \ + release/rq_frena.o \ + release/rq_fread.o \ + release/rq_fopen.o \ + release/rq_fdir.o \ + release/rq_fdele.o \ + release/rq_fclos.o \ + release/rq_downl.o \ + release/rq_delvl.o \ + release/rq_delva.o \ + release/rq_delty.o \ + release/rq_delse.o \ + release/rq_delpi.o \ + release/rq_delee.o \ + release/rq_delec.o \ + release/rq_delea.o \ + release/rq_deldo.o \ + release/rq_defvl.o \ + release/rq_defva.o \ + release/rq_defty.o \ + release/rq_defse.o \ + release/rq_defsc.o \ + release/rq_defec.o \ + release/rq_defea.o \ + release/rq_crepi.o \ + release/rq_altee.o \ + release/rq_altec.o \ + release/mms_ced2.o \ + release/mms_ced1.o \ + release/sclproc.o \ + release/s_write.o \ + release/s_status.o \ + release/s_read.o \ + release/s_obtfi.o \ + release/s_jstat.o \ + release/s_jread.o \ + release/s_jinit.o \ + release/s_info.o \ + release/s_ident.o \ + release/s_getvla.o \ + release/s_getvaa.o \ + release/s_getnam.o \ + release/s_getdom.o \ + release/s_getcl.o \ + release/s_fren.o \ + release/s_fread.o \ + release/s_fopen.o \ + release/s_fdir.o \ + release/s_fdel.o \ + release/s_fclose.o \ + release/s_delvl.o \ + release/s_defvl.o \ + release/s_concl.o \ + release/s_cancel.o \ + release/mvluleaf.o \ + release/mvlu_sbo.o \ + release/mvlu_rt.o \ + release/mvlu_rpt.o \ + release/mvl61850_rpt.o \ + release/mvl61850_ctl.o \ + release/mvl61850.o \ + release/mvl_var.o \ + release/mvl_uca.o \ + release/mvl_type.o \ + release/mvl_typ2.o \ + release/mvl_serv.o \ + release/mvl_send.o \ + release/mvl_objb.o \ + release/mvl_obj.o \ + release/mvl_ijou.o \ + release/mvl_dtyp.o \ + release/mvl_buf.o \ + release/c_write.o \ + release/c_status.o \ + release/c_read.o \ + release/c_obtfi.o \ + release/c_jstat.o \ + release/c_jread.o \ + release/c_jinit.o \ + release/c_info.o \ + release/c_ident.o \ + release/c_getvla.o \ + release/c_getvar.o \ + release/c_getnam.o \ + release/c_getdom.o \ + release/c_fren.o \ + release/c_fread.o \ + release/c_fopen.o \ + release/c_fget.o \ + release/c_fdir.o \ + release/c_fdel.o \ + release/c_fclose.o \ + release/c_delvl.o \ + release/c_defvl.o \ + release/c_concl.o \ + release/tpx_dec.o \ + release/tp4port.o \ + release/tp4_enc.o \ + release/tp0main.o \ + release/tp0callg.o \ + release/tp0calld.o \ + release/tp0_socks.o \ + release/tp0_dec.o \ + release/osicfgx.o \ + release/lean_var.o \ + release/lean_cfg.o \ + release/cospmain.o \ + release/cosp_enc.o \ + release/cosp_dec.o \ + release/coppdcpr.o \ + release/coppdcp.o \ + release/coppdaru.o \ + release/copp_enc.o \ + release/copp_dec.o \ + release/checksum.o \ + release/acse2var.o \ + release/acse2enc.o \ + release/acse2dib.o \ + release/acse2dec.o \ + release/slogmem.o \ + release/slogipcs.o \ + release/sloghex.o \ + release/slogfil.o \ + release/slog.o \ + release/qmem.o \ + release/ssecusr0.o \ + release/time_str.o \ + release/sx_enc.o \ + release/sx_dec.o \ + release/sx_data.o \ + release/sx_axs4d.o \ + release/str_util.o \ + release/stime.o \ + release/stdtime_w32.o \ + release/stdtime_quadlib.o \ + release/stdtime_mms_utctime.o \ + release/stdtime_mms_btime.o \ + release/stdtime.o \ + release/sclstore.o \ + release/sclparse.o \ + release/scl_log.o \ + release/glbsem_unix.o \ + release/glbsem.o \ + release/gensock2.o \ + release/genlists.o \ + release/cfg_util.o +DIST = ../../../qt-4.8.4/mkspecs/common/unix.conf \ + ../../../qt-4.8.4/mkspecs/common/linux.conf \ + ../../../qt-4.8.4/mkspecs/common/gcc-base.conf \ + ../../../qt-4.8.4/mkspecs/common/gcc-base-unix.conf \ + ../../../qt-4.8.4/mkspecs/common/g++-base.conf \ + ../../../qt-4.8.4/mkspecs/common/g++-unix.conf \ + ../../../qt-4.8.4/mkspecs/qconfig.pri \ + ../../../qt-4.8.4/mkspecs/features/qt_functions.prf \ + ../../../qt-4.8.4/mkspecs/features/qt_config.prf \ + ../../../qt-4.8.4/mkspecs/features/exclusive_builds.prf \ + ../../../qt-4.8.4/mkspecs/features/default_pre.prf \ + fe_common.pri \ + ../../../qt-4.8.4/mkspecs/features/release.prf \ + ../../../qt-4.8.4/mkspecs/features/debug_and_release.prf \ + ../../../qt-4.8.4/mkspecs/features/default_post.prf \ + ../../../qt-4.8.4/mkspecs/features/build_pass.prf \ + ../../../qt-4.8.4/mkspecs/features/warn_off.prf \ + ../../../qt-4.8.4/mkspecs/features/staticlib.prf \ + ../../../qt-4.8.4/mkspecs/features/static.prf \ + ../../../qt-4.8.4/mkspecs/features/unix/gdb_dwarf_index.prf \ + ../../../qt-4.8.4/mkspecs/features/qt.prf \ + ../../../qt-4.8.4/mkspecs/features/unix/thread.prf \ + ../../../qt-4.8.4/mkspecs/features/moc.prf \ + ../../../qt-4.8.4/mkspecs/features/resources.prf \ + ../../../qt-4.8.4/mkspecs/features/uic.prf \ + ../../../qt-4.8.4/mkspecs/features/yacc.prf \ + ../../../qt-4.8.4/mkspecs/features/lex.prf \ + ../../../qt-4.8.4/mkspecs/features/include_source_dir.prf \ + mmslib.pro +QMAKE_TARGET = mmslib +DESTDIR = +TARGET = libmmslib.a + +first: all +####### Implicit rules + +.SUFFIXES: .o .c .cpp .cc .cxx .C + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<" + +####### Build rules + +all: Makefile.Release $(TARGET) + +staticlib: $(TARGET) + +$(TARGET): $(OBJECTS) $(OBJCOMP) + -$(DEL_FILE) $(TARGET) + $(AR) $(TARGET) $(OBJECTS) + + +qmake: FORCE + @$(QMAKE) -o Makefile.Release mmslib.pro + +dist: + @$(CHK_DIR_EXISTS) release/mmslib1.0.0 || $(MKDIR) release/mmslib1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) release/mmslib1.0.0/ && $(COPY_FILE) --parents mmslib.h inc/tp4api.h inc/tp4_log.h inc/tp4_encd.h inc/tp4.h inc/tp0_sock.h inc/time_str.h inc/sysincs.h inc/sx_log.h inc/sx_defs.h inc/sx_arb.h inc/STR_UTIL.H inc/stime.h inc/stdtime_w32.h inc/stdtime_tzrules.h inc/stdtime_timezone_csv.h inc/stdtime_stdint.h inc/stdtime_quadlib.h inc/stdtime_mms_utctime.h inc/stdtime_mms_btime.h inc/stdtime_enum_func.h inc/stdtime_enum_err.h inc/stdtime_endian.h inc/stdtime_config.h inc/stdtime.h inc/ssleLog.h inc/ssec_int.h inc/ssec.h inc/sock_log.h inc/smpval.h inc/smp_usr.h inc/smp_log.h inc/smp.h inc/Smem.h inc/slog.h inc/scrndefs.h inc/scl.h inc/rs_defs.h inc/rs_a.h inc/qmem.h inc/osillc.h inc/ntddosi.h inc/mvl_uca.h inc/mvl_log.h inc/mvl_defs.h inc/mvl_acse.h inc/mmslusec.h inc/mmslog.h inc/mmsldefs.h inc/mmsintr2.h inc/mmsefun.h inc/mmsdefs.h inc/mms_vvar.h inc/mms_pvmd.h inc/mms_pvar.h inc/mms_psem.h inc/mms_pprg.h inc/mms_pocs.h inc/mms_pjou.h inc/mms_pfil.h inc/mms_pevn.h inc/mms_perr.h inc/mms_pdom.h inc/mms_pcon.h inc/mms_mp.h inc/mms_log.h inc/mms_err.h inc/mms_dfun.h inc/mms_def2.h inc/mloguser.h inc/memlog.h inc/mem_chk.h inc/llcioctl.h inc/llcio.h inc/lean_a.h inc/gvaldefs.h inc/gse_mgmt.h inc/Goose.h inc/glbtypes.h inc/glbsem.h inc/glbopt.h inc/glberror.h inc/gensock2.h inc/gen_list.h inc/fkeydefs.h inc/ExceptionReport.h inc/ethsub.h inc/ethertyp.h inc/dibmatch.h inc/cosp_usr.h inc/cosp_log.h inc/cosp.h inc/copp_usr.h inc/copp_log.h inc/copp.h inc/conpack.h inc/clnpport.h inc/clnp_usr.h inc/clnp_tnt.h inc/clnp_sta.h inc/clnp_sne.h inc/clnp_log.h inc/clnp_llc.h inc/clnp.h inc/checksum.h inc/cfglog.h inc/cfg_util.h inc/asn1r.h inc/asn1log.h inc/asn1defs.h inc/arg.h inc/adlc_usr.h inc/adlc_sts.h inc/adlc_sm.h inc/adlc_log.h inc/adlc_dsm.h inc/adlc.h inc/acseauth.h inc/acse2usr.h inc/acse2log.h inc/acse2.h inc/mmsop_en/mmsop_en.h release/mmslib1.0.0/ && $(COPY_FILE) --parents mmslib.cpp asn1/asn1r.c asn1/are_vstr.c asn1/are_utc.c asn1/are_time.c asn1/are_ostr.c asn1/are_objd.c asn1/are_int.c asn1/are_flt.c asn1/are_delm.c asn1/are_btod.c asn1/are_bstr.c asn1/are_bool.c asn1/ard_vstr.c asn1/ard_utc.c asn1/ard_time.c asn1/ard_strn.c asn1/ard_ostr.c asn1/ard_objd.c asn1/ard_int.c asn1/ard_idnt.c asn1/ard_flt.c asn1/ard_delm.c asn1/ard_btod.c asn1/ard_bstr.c asn1/ard_bool.c mem/mem_chks.c mmsl/rs_write.c mmsl/rs_ustat.c mmsl/rs_trige.c mmsl/rs_stat.c mmsl/rs_repee.c mmsl/rs_repec.c mmsl/rs_repea.c mmsl/rs_read.c mmsl/rs_namel.c mmsl/rs_init.c mmsl/rs_info.c mmsl/rs_ident.c mmsl/rs_getvl.c mmsl/rs_getva.c mmsl/rs_getty.c mmsl/rs_getpi.c mmsl/rs_getee.c mmsl/rs_getec.c mmsl/rs_getea.c mmsl/rs_getdo.c mmsl/rs_getcl.c mmsl/rs_evnot.c mmsl/rs_defee.c mmsl/rs_concl.c mmsl/rs_cancl.c mmsl/rs_ackev.c mmsl/rq_write.c mmsl/rq_ustat.c mmsl/rq_trige.c mmsl/rq_stat.c mmsl/rq_repee.c mmsl/rq_repec.c mmsl/rq_repea.c mmsl/rq_read.c mmsl/rq_namel.c mmsl/rq_init.c mmsl/rq_info.c mmsl/rq_ident.c mmsl/rq_getvl.c mmsl/rq_getva.c mmsl/rq_getty.c mmsl/rq_getpi.c mmsl/rq_getee.c mmsl/rq_getec.c mmsl/rq_getea.c mmsl/rq_getdo.c mmsl/rq_getcl.c mmsl/rq_evnot.c mmsl/rq_defee.c mmsl/rq_concl.c mmsl/rq_cancl.c mmsl/rq_ackev.c mmsl/msdataas.c mmsl/ms_tdef4.c mmsl/ms_tdef2.c mmsl/ms_tdef.c mmsl/ms_size.c mmsl/ms_ext.c mmsl/mmsstat.c mmsl/mmslvar.c mmsl/mmsl_fin.c mmsl/mmsinit.c mmsl/mmsdtext.c mmsl/mmsdec.c mmsl/mmsdatat.c mmsl/mmsdata.c mmsl/mmsconcl.c mmsl/mmscancl.c mmsl/mms_tdef.c mmsl/mms_rtaa.c mmsl/mms_rej.c mmsl/mms_err4.c mmsl/mms_err3.c mmsl/mms_err2.c mmsl/mms_err.c mmsl/mms_ced7.c mmsl/mms_ced6.c mmsl/mms_ced5.c mmsl/mms_ced4.c mmsl/mms_ced3.c mmsl/mms_ced.c mmsl/mms_aref.c mmsl/mms_alta.c mmsl/mms_adl.c mmsle/rs_uploa.c mmsle/rs_termu.c mmsle/rs_termd.c mmsle/rs_takec.c mmsle/rs_store.c mmsle/rs_stop.c mmsle/rs_start.c mmsle/rs_rssta.c mmsle/rs_rspoo.c mmsle/rs_rsent.c mmsle/rs_resum.c mmsle/rs_reset.c mmsle/rs_renam.c mmsle/rs_relct.c mmsle/rs_rdupl.c mmsle/rs_rddwn.c mmsle/rs_outpu.c mmsle/rs_obtfi.c mmsle/rs_loadd.c mmsle/rs_kill.c mmsle/rs_jwrit.c mmsle/rs_jstat.c mmsle/rs_jread.c mmsle/rs_jinit.c mmsle/rs_jdele.c mmsle/rs_jcrea.c mmsle/rs_input.c mmsle/rs_initu.c mmsle/rs_initd.c mmsle/rs_getsc.c mmsle/rs_getas.c mmsle/rs_getae.c mmsle/rs_frena.c mmsle/rs_fread.c mmsle/rs_fopen.c mmsle/rs_fdir.c mmsle/rs_fdele.c mmsle/rs_fclos.c mmsle/rs_downl.c mmsle/rs_delvl.c mmsle/rs_delva.c mmsle/rs_delty.c mmsle/rs_delse.c mmsle/rs_delpi.c mmsle/rs_delee.c mmsle/rs_delec.c mmsle/rs_delea.c mmsle/rs_deldo.c mmsle/rs_defvl.c mmsle/rs_defva.c mmsle/rs_defty.c mmsle/rs_defse.c mmsle/rs_defsc.c mmsle/rs_defec.c mmsle/rs_defea.c mmsle/rs_crepi.c mmsle/rs_altee.c mmsle/rs_altec.c mmsle/rq_uploa.c mmsle/rq_termu.c mmsle/rq_termd.c mmsle/rq_takec.c mmsle/rq_store.c mmsle/rq_stop.c mmsle/rq_start.c mmsle/rq_rssta.c mmsle/rq_rspoo.c mmsle/rq_rsent.c mmsle/rq_resum.c mmsle/rq_reset.c mmsle/rq_renam.c mmsle/rq_relct.c mmsle/rq_rdupl.c mmsle/rq_rddwn.c mmsle/rq_outpu.c mmsle/rq_obtfi.c mmsle/rq_loadd.c mmsle/rq_kill.c mmsle/rq_jwrit.c mmsle/rq_jstat.c mmsle/rq_jread.c mmsle/rq_jinit.c mmsle/rq_jdele.c mmsle/rq_jcrea.c mmsle/rq_input.c mmsle/rq_initu.c mmsle/rq_initd.c mmsle/rq_getsc.c mmsle/rq_getas.c mmsle/rq_getae.c mmsle/rq_frena.c mmsle/rq_fread.c mmsle/rq_fopen.c mmsle/rq_fdir.c mmsle/rq_fdele.c mmsle/rq_fclos.c mmsle/rq_downl.c mmsle/rq_delvl.c mmsle/rq_delva.c mmsle/rq_delty.c mmsle/rq_delse.c mmsle/rq_delpi.c mmsle/rq_delee.c mmsle/rq_delec.c mmsle/rq_delea.c mmsle/rq_deldo.c mmsle/rq_defvl.c mmsle/rq_defva.c mmsle/rq_defty.c mmsle/rq_defse.c mmsle/rq_defsc.c mmsle/rq_defec.c mmsle/rq_defea.c mmsle/rq_crepi.c mmsle/rq_altee.c mmsle/rq_altec.c mmsle/mms_ced2.c mmsle/mms_ced1.c mvlu/sclproc.c mvlu/s_write.c mvlu/s_status.c mvlu/s_read.c mvlu/s_obtfi.c mvlu/s_jstat.c mvlu/s_jread.c mvlu/s_jinit.c mvlu/s_info.c mvlu/s_ident.c mvlu/s_getvla.c mvlu/s_getvaa.c mvlu/s_getnam.c mvlu/s_getdom.c mvlu/s_getcl.c mvlu/s_fren.c mvlu/s_fread.c mvlu/s_fopen.c mvlu/s_fdir.c mvlu/s_fdel.c mvlu/s_fclose.c mvlu/s_delvl.c mvlu/s_defvl.c mvlu/s_concl.c mvlu/s_cancel.c mvlu/mvluleaf.c mvlu/mvlu_sbo.c mvlu/mvlu_rt.c mvlu/mvlu_rpt.c mvlu/mvl61850_rpt.c mvlu/mvl61850_ctl.c mvlu/mvl61850.c mvlu/mvl_var.c mvlu/mvl_uca.c mvlu/mvl_type.c mvlu/mvl_typ2.c mvlu/mvl_serv.c mvlu/mvl_send.c mvlu/mvl_objb.c mvlu/mvl_obj.c mvlu/mvl_ijou.c mvlu/mvl_dtyp.c mvlu/mvl_buf.c mvlu/c_write.c mvlu/c_status.c mvlu/c_read.c mvlu/c_obtfi.c mvlu/c_jstat.c mvlu/c_jread.c mvlu/c_jinit.c mvlu/c_info.c mvlu/c_ident.c mvlu/c_getvla.c mvlu/c_getvar.c mvlu/c_getnam.c mvlu/c_getdom.c mvlu/c_fren.c mvlu/c_fread.c mvlu/c_fopen.c mvlu/c_fget.c mvlu/c_fdir.c mvlu/c_fdel.c mvlu/c_fclose.c mvlu/c_delvl.c mvlu/c_defvl.c mvlu/c_concl.c ositcps/tpx_dec.c ositcps/tp4port.c ositcps/tp4_enc.c ositcps/tp0main.c ositcps/tp0callg.c ositcps/tp0calld.c ositcps/tp0_socks.c ositcps/tp0_dec.c ositcps/osicfgx.c ositcps/lean_var.c ositcps/lean_cfg.c ositcps/cospmain.c ositcps/cosp_enc.c ositcps/cosp_dec.c ositcps/coppdcpr.c ositcps/coppdcp.c ositcps/coppdaru.c ositcps/copp_enc.c ositcps/copp_dec.c ositcps/checksum.c ositcps/acse2var.c ositcps/acse2enc.c ositcps/acse2dib.c ositcps/acse2dec.c slog/slogmem.c slog/slogipcs.c slog/sloghex.c slog/slogfil.c slog/slog.c slog/qmem.c ssec0/ssecusr0.c util/time_str.c util/sx_enc.c util/sx_dec.c util/sx_data.c util/sx_axs4d.c util/str_util.c util/stime.c util/stdtime_w32.c util/stdtime_quadlib.c util/stdtime_mms_utctime.c util/stdtime_mms_btime.c util/stdtime.c util/sclstore.c util/sclparse.c util/scl_log.c util/glbsem_unix.c util/glbsem.c util/gensock2.c util/genlists.c util/cfg_util.c release/mmslib1.0.0/ && (cd `dirname release/mmslib1.0.0` && $(TAR) mmslib1.0.0.tar mmslib1.0.0 && $(COMPRESS) mmslib1.0.0.tar) && $(MOVE) `dirname release/mmslib1.0.0`/mmslib1.0.0.tar.gz . && $(DEL_FILE) -r release/mmslib1.0.0 + + +clean:compiler_clean + -$(DEL_FILE) $(OBJECTS) + -$(DEL_FILE) *~ core *.core + + +####### Sub-libraries + +distclean: clean + -$(DEL_FILE) $(TARGET) + -$(DEL_FILE) Makefile.Release + + +check: first + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all + +compiler_moc_header_make_all: +compiler_moc_header_clean: +compiler_rcc_make_all: +compiler_rcc_clean: +compiler_image_collection_make_all: qmake_image_collection.cpp +compiler_image_collection_clean: + -$(DEL_FILE) qmake_image_collection.cpp +compiler_moc_source_make_all: +compiler_moc_source_clean: +compiler_uic_make_all: +compiler_uic_clean: +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: + +####### Compile + +release/mmslib.o: mmslib.cpp mmslib.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o release/mmslib.o mmslib.cpp + +release/asn1r.o: asn1/asn1r.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/asn1r.o asn1/asn1r.c + +release/are_vstr.o: asn1/are_vstr.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/are_vstr.o asn1/are_vstr.c + +release/are_utc.o: asn1/are_utc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/are_utc.o asn1/are_utc.c + +release/are_time.o: asn1/are_time.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/are_time.o asn1/are_time.c + +release/are_ostr.o: asn1/are_ostr.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/are_ostr.o asn1/are_ostr.c + +release/are_objd.o: asn1/are_objd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/are_objd.o asn1/are_objd.c + +release/are_int.o: asn1/are_int.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/are_int.o asn1/are_int.c + +release/are_flt.o: asn1/are_flt.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/are_flt.o asn1/are_flt.c + +release/are_delm.o: asn1/are_delm.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/are_delm.o asn1/are_delm.c + +release/are_btod.o: asn1/are_btod.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/are_btod.o asn1/are_btod.c + +release/are_bstr.o: asn1/are_bstr.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/are_bstr.o asn1/are_bstr.c + +release/are_bool.o: asn1/are_bool.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/are_bool.o asn1/are_bool.c + +release/ard_vstr.o: asn1/ard_vstr.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ard_vstr.o asn1/ard_vstr.c + +release/ard_utc.o: asn1/ard_utc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ard_utc.o asn1/ard_utc.c + +release/ard_time.o: asn1/ard_time.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ard_time.o asn1/ard_time.c + +release/ard_strn.o: asn1/ard_strn.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ard_strn.o asn1/ard_strn.c + +release/ard_ostr.o: asn1/ard_ostr.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ard_ostr.o asn1/ard_ostr.c + +release/ard_objd.o: asn1/ard_objd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ard_objd.o asn1/ard_objd.c + +release/ard_int.o: asn1/ard_int.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ard_int.o asn1/ard_int.c + +release/ard_idnt.o: asn1/ard_idnt.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ard_idnt.o asn1/ard_idnt.c + +release/ard_flt.o: asn1/ard_flt.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ard_flt.o asn1/ard_flt.c + +release/ard_delm.o: asn1/ard_delm.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ard_delm.o asn1/ard_delm.c + +release/ard_btod.o: asn1/ard_btod.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ard_btod.o asn1/ard_btod.c + +release/ard_bstr.o: asn1/ard_bstr.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ard_bstr.o asn1/ard_bstr.c + +release/ard_bool.o: asn1/ard_bool.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ard_bool.o asn1/ard_bool.c + +release/mem_chks.o: mem/mem_chks.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mem_chks.o mem/mem_chks.c + +release/rs_write.o: mmsl/rs_write.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_write.o mmsl/rs_write.c + +release/rs_ustat.o: mmsl/rs_ustat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_ustat.o mmsl/rs_ustat.c + +release/rs_trige.o: mmsl/rs_trige.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_trige.o mmsl/rs_trige.c + +release/rs_stat.o: mmsl/rs_stat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_stat.o mmsl/rs_stat.c + +release/rs_repee.o: mmsl/rs_repee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_repee.o mmsl/rs_repee.c + +release/rs_repec.o: mmsl/rs_repec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_repec.o mmsl/rs_repec.c + +release/rs_repea.o: mmsl/rs_repea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_repea.o mmsl/rs_repea.c + +release/rs_read.o: mmsl/rs_read.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_read.o mmsl/rs_read.c + +release/rs_namel.o: mmsl/rs_namel.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_namel.o mmsl/rs_namel.c + +release/rs_init.o: mmsl/rs_init.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_init.o mmsl/rs_init.c + +release/rs_info.o: mmsl/rs_info.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_info.o mmsl/rs_info.c + +release/rs_ident.o: mmsl/rs_ident.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_ident.o mmsl/rs_ident.c + +release/rs_getvl.o: mmsl/rs_getvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_getvl.o mmsl/rs_getvl.c + +release/rs_getva.o: mmsl/rs_getva.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_getva.o mmsl/rs_getva.c + +release/rs_getty.o: mmsl/rs_getty.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_getty.o mmsl/rs_getty.c + +release/rs_getpi.o: mmsl/rs_getpi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_getpi.o mmsl/rs_getpi.c + +release/rs_getee.o: mmsl/rs_getee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_getee.o mmsl/rs_getee.c + +release/rs_getec.o: mmsl/rs_getec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_getec.o mmsl/rs_getec.c + +release/rs_getea.o: mmsl/rs_getea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_getea.o mmsl/rs_getea.c + +release/rs_getdo.o: mmsl/rs_getdo.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_getdo.o mmsl/rs_getdo.c + +release/rs_getcl.o: mmsl/rs_getcl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_getcl.o mmsl/rs_getcl.c + +release/rs_evnot.o: mmsl/rs_evnot.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_evnot.o mmsl/rs_evnot.c + +release/rs_defee.o: mmsl/rs_defee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_defee.o mmsl/rs_defee.c + +release/rs_concl.o: mmsl/rs_concl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_concl.o mmsl/rs_concl.c + +release/rs_cancl.o: mmsl/rs_cancl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_cancl.o mmsl/rs_cancl.c + +release/rs_ackev.o: mmsl/rs_ackev.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_ackev.o mmsl/rs_ackev.c + +release/rq_write.o: mmsl/rq_write.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_write.o mmsl/rq_write.c + +release/rq_ustat.o: mmsl/rq_ustat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_ustat.o mmsl/rq_ustat.c + +release/rq_trige.o: mmsl/rq_trige.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_trige.o mmsl/rq_trige.c + +release/rq_stat.o: mmsl/rq_stat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_stat.o mmsl/rq_stat.c + +release/rq_repee.o: mmsl/rq_repee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_repee.o mmsl/rq_repee.c + +release/rq_repec.o: mmsl/rq_repec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_repec.o mmsl/rq_repec.c + +release/rq_repea.o: mmsl/rq_repea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_repea.o mmsl/rq_repea.c + +release/rq_read.o: mmsl/rq_read.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_read.o mmsl/rq_read.c + +release/rq_namel.o: mmsl/rq_namel.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_namel.o mmsl/rq_namel.c + +release/rq_init.o: mmsl/rq_init.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_init.o mmsl/rq_init.c + +release/rq_info.o: mmsl/rq_info.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_info.o mmsl/rq_info.c + +release/rq_ident.o: mmsl/rq_ident.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_ident.o mmsl/rq_ident.c + +release/rq_getvl.o: mmsl/rq_getvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_getvl.o mmsl/rq_getvl.c + +release/rq_getva.o: mmsl/rq_getva.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_getva.o mmsl/rq_getva.c + +release/rq_getty.o: mmsl/rq_getty.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_getty.o mmsl/rq_getty.c + +release/rq_getpi.o: mmsl/rq_getpi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_getpi.o mmsl/rq_getpi.c + +release/rq_getee.o: mmsl/rq_getee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_getee.o mmsl/rq_getee.c + +release/rq_getec.o: mmsl/rq_getec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_getec.o mmsl/rq_getec.c + +release/rq_getea.o: mmsl/rq_getea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_getea.o mmsl/rq_getea.c + +release/rq_getdo.o: mmsl/rq_getdo.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_getdo.o mmsl/rq_getdo.c + +release/rq_getcl.o: mmsl/rq_getcl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_getcl.o mmsl/rq_getcl.c + +release/rq_evnot.o: mmsl/rq_evnot.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_evnot.o mmsl/rq_evnot.c + +release/rq_defee.o: mmsl/rq_defee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_defee.o mmsl/rq_defee.c + +release/rq_concl.o: mmsl/rq_concl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_concl.o mmsl/rq_concl.c + +release/rq_cancl.o: mmsl/rq_cancl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_cancl.o mmsl/rq_cancl.c + +release/rq_ackev.o: mmsl/rq_ackev.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_ackev.o mmsl/rq_ackev.c + +release/msdataas.o: mmsl/msdataas.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/msdataas.o mmsl/msdataas.c + +release/ms_tdef4.o: mmsl/ms_tdef4.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ms_tdef4.o mmsl/ms_tdef4.c + +release/ms_tdef2.o: mmsl/ms_tdef2.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ms_tdef2.o mmsl/ms_tdef2.c + +release/ms_tdef.o: mmsl/ms_tdef.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ms_tdef.o mmsl/ms_tdef.c + +release/ms_size.o: mmsl/ms_size.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ms_size.o mmsl/ms_size.c + +release/ms_ext.o: mmsl/ms_ext.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ms_ext.o mmsl/ms_ext.c + +release/mmsstat.o: mmsl/mmsstat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mmsstat.o mmsl/mmsstat.c + +release/mmslvar.o: mmsl/mmslvar.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mmslvar.o mmsl/mmslvar.c + +release/mmsl_fin.o: mmsl/mmsl_fin.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mmsl_fin.o mmsl/mmsl_fin.c + +release/mmsinit.o: mmsl/mmsinit.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mmsinit.o mmsl/mmsinit.c + +release/mmsdtext.o: mmsl/mmsdtext.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mmsdtext.o mmsl/mmsdtext.c + +release/mmsdec.o: mmsl/mmsdec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mmsdec.o mmsl/mmsdec.c + +release/mmsdatat.o: mmsl/mmsdatat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mmsdatat.o mmsl/mmsdatat.c + +release/mmsdata.o: mmsl/mmsdata.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mmsdata.o mmsl/mmsdata.c + +release/mmsconcl.o: mmsl/mmsconcl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mmsconcl.o mmsl/mmsconcl.c + +release/mmscancl.o: mmsl/mmscancl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mmscancl.o mmsl/mmscancl.c + +release/mms_tdef.o: mmsl/mms_tdef.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_tdef.o mmsl/mms_tdef.c + +release/mms_rtaa.o: mmsl/mms_rtaa.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_rtaa.o mmsl/mms_rtaa.c + +release/mms_rej.o: mmsl/mms_rej.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_rej.o mmsl/mms_rej.c + +release/mms_err4.o: mmsl/mms_err4.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_err4.o mmsl/mms_err4.c + +release/mms_err3.o: mmsl/mms_err3.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_err3.o mmsl/mms_err3.c + +release/mms_err2.o: mmsl/mms_err2.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_err2.o mmsl/mms_err2.c + +release/mms_err.o: mmsl/mms_err.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_err.o mmsl/mms_err.c + +release/mms_ced7.o: mmsl/mms_ced7.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_ced7.o mmsl/mms_ced7.c + +release/mms_ced6.o: mmsl/mms_ced6.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_ced6.o mmsl/mms_ced6.c + +release/mms_ced5.o: mmsl/mms_ced5.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_ced5.o mmsl/mms_ced5.c + +release/mms_ced4.o: mmsl/mms_ced4.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_ced4.o mmsl/mms_ced4.c + +release/mms_ced3.o: mmsl/mms_ced3.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_ced3.o mmsl/mms_ced3.c + +release/mms_ced.o: mmsl/mms_ced.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_ced.o mmsl/mms_ced.c + +release/mms_aref.o: mmsl/mms_aref.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_aref.o mmsl/mms_aref.c + +release/mms_alta.o: mmsl/mms_alta.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_alta.o mmsl/mms_alta.c + +release/mms_adl.o: mmsl/mms_adl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_adl.o mmsl/mms_adl.c + +release/rs_uploa.o: mmsle/rs_uploa.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_uploa.o mmsle/rs_uploa.c + +release/rs_termu.o: mmsle/rs_termu.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_termu.o mmsle/rs_termu.c + +release/rs_termd.o: mmsle/rs_termd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_termd.o mmsle/rs_termd.c + +release/rs_takec.o: mmsle/rs_takec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_takec.o mmsle/rs_takec.c + +release/rs_store.o: mmsle/rs_store.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_store.o mmsle/rs_store.c + +release/rs_stop.o: mmsle/rs_stop.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_stop.o mmsle/rs_stop.c + +release/rs_start.o: mmsle/rs_start.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_start.o mmsle/rs_start.c + +release/rs_rssta.o: mmsle/rs_rssta.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_rssta.o mmsle/rs_rssta.c + +release/rs_rspoo.o: mmsle/rs_rspoo.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_rspoo.o mmsle/rs_rspoo.c + +release/rs_rsent.o: mmsle/rs_rsent.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_rsent.o mmsle/rs_rsent.c + +release/rs_resum.o: mmsle/rs_resum.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_resum.o mmsle/rs_resum.c + +release/rs_reset.o: mmsle/rs_reset.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_reset.o mmsle/rs_reset.c + +release/rs_renam.o: mmsle/rs_renam.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_renam.o mmsle/rs_renam.c + +release/rs_relct.o: mmsle/rs_relct.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_relct.o mmsle/rs_relct.c + +release/rs_rdupl.o: mmsle/rs_rdupl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_rdupl.o mmsle/rs_rdupl.c + +release/rs_rddwn.o: mmsle/rs_rddwn.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_rddwn.o mmsle/rs_rddwn.c + +release/rs_outpu.o: mmsle/rs_outpu.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_outpu.o mmsle/rs_outpu.c + +release/rs_obtfi.o: mmsle/rs_obtfi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_obtfi.o mmsle/rs_obtfi.c + +release/rs_loadd.o: mmsle/rs_loadd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_loadd.o mmsle/rs_loadd.c + +release/rs_kill.o: mmsle/rs_kill.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_kill.o mmsle/rs_kill.c + +release/rs_jwrit.o: mmsle/rs_jwrit.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_jwrit.o mmsle/rs_jwrit.c + +release/rs_jstat.o: mmsle/rs_jstat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_jstat.o mmsle/rs_jstat.c + +release/rs_jread.o: mmsle/rs_jread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_jread.o mmsle/rs_jread.c + +release/rs_jinit.o: mmsle/rs_jinit.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_jinit.o mmsle/rs_jinit.c + +release/rs_jdele.o: mmsle/rs_jdele.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_jdele.o mmsle/rs_jdele.c + +release/rs_jcrea.o: mmsle/rs_jcrea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_jcrea.o mmsle/rs_jcrea.c + +release/rs_input.o: mmsle/rs_input.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_input.o mmsle/rs_input.c + +release/rs_initu.o: mmsle/rs_initu.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_initu.o mmsle/rs_initu.c + +release/rs_initd.o: mmsle/rs_initd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_initd.o mmsle/rs_initd.c + +release/rs_getsc.o: mmsle/rs_getsc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_getsc.o mmsle/rs_getsc.c + +release/rs_getas.o: mmsle/rs_getas.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_getas.o mmsle/rs_getas.c + +release/rs_getae.o: mmsle/rs_getae.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_getae.o mmsle/rs_getae.c + +release/rs_frena.o: mmsle/rs_frena.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_frena.o mmsle/rs_frena.c + +release/rs_fread.o: mmsle/rs_fread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_fread.o mmsle/rs_fread.c + +release/rs_fopen.o: mmsle/rs_fopen.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_fopen.o mmsle/rs_fopen.c + +release/rs_fdir.o: mmsle/rs_fdir.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_fdir.o mmsle/rs_fdir.c + +release/rs_fdele.o: mmsle/rs_fdele.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_fdele.o mmsle/rs_fdele.c + +release/rs_fclos.o: mmsle/rs_fclos.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_fclos.o mmsle/rs_fclos.c + +release/rs_downl.o: mmsle/rs_downl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_downl.o mmsle/rs_downl.c + +release/rs_delvl.o: mmsle/rs_delvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_delvl.o mmsle/rs_delvl.c + +release/rs_delva.o: mmsle/rs_delva.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_delva.o mmsle/rs_delva.c + +release/rs_delty.o: mmsle/rs_delty.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_delty.o mmsle/rs_delty.c + +release/rs_delse.o: mmsle/rs_delse.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_delse.o mmsle/rs_delse.c + +release/rs_delpi.o: mmsle/rs_delpi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_delpi.o mmsle/rs_delpi.c + +release/rs_delee.o: mmsle/rs_delee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_delee.o mmsle/rs_delee.c + +release/rs_delec.o: mmsle/rs_delec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_delec.o mmsle/rs_delec.c + +release/rs_delea.o: mmsle/rs_delea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_delea.o mmsle/rs_delea.c + +release/rs_deldo.o: mmsle/rs_deldo.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_deldo.o mmsle/rs_deldo.c + +release/rs_defvl.o: mmsle/rs_defvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_defvl.o mmsle/rs_defvl.c + +release/rs_defva.o: mmsle/rs_defva.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_defva.o mmsle/rs_defva.c + +release/rs_defty.o: mmsle/rs_defty.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_defty.o mmsle/rs_defty.c + +release/rs_defse.o: mmsle/rs_defse.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_defse.o mmsle/rs_defse.c + +release/rs_defsc.o: mmsle/rs_defsc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_defsc.o mmsle/rs_defsc.c + +release/rs_defec.o: mmsle/rs_defec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_defec.o mmsle/rs_defec.c + +release/rs_defea.o: mmsle/rs_defea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_defea.o mmsle/rs_defea.c + +release/rs_crepi.o: mmsle/rs_crepi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_crepi.o mmsle/rs_crepi.c + +release/rs_altee.o: mmsle/rs_altee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_altee.o mmsle/rs_altee.c + +release/rs_altec.o: mmsle/rs_altec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rs_altec.o mmsle/rs_altec.c + +release/rq_uploa.o: mmsle/rq_uploa.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_uploa.o mmsle/rq_uploa.c + +release/rq_termu.o: mmsle/rq_termu.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_termu.o mmsle/rq_termu.c + +release/rq_termd.o: mmsle/rq_termd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_termd.o mmsle/rq_termd.c + +release/rq_takec.o: mmsle/rq_takec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_takec.o mmsle/rq_takec.c + +release/rq_store.o: mmsle/rq_store.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_store.o mmsle/rq_store.c + +release/rq_stop.o: mmsle/rq_stop.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_stop.o mmsle/rq_stop.c + +release/rq_start.o: mmsle/rq_start.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_start.o mmsle/rq_start.c + +release/rq_rssta.o: mmsle/rq_rssta.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_rssta.o mmsle/rq_rssta.c + +release/rq_rspoo.o: mmsle/rq_rspoo.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_rspoo.o mmsle/rq_rspoo.c + +release/rq_rsent.o: mmsle/rq_rsent.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_rsent.o mmsle/rq_rsent.c + +release/rq_resum.o: mmsle/rq_resum.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_resum.o mmsle/rq_resum.c + +release/rq_reset.o: mmsle/rq_reset.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_reset.o mmsle/rq_reset.c + +release/rq_renam.o: mmsle/rq_renam.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_renam.o mmsle/rq_renam.c + +release/rq_relct.o: mmsle/rq_relct.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_relct.o mmsle/rq_relct.c + +release/rq_rdupl.o: mmsle/rq_rdupl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_rdupl.o mmsle/rq_rdupl.c + +release/rq_rddwn.o: mmsle/rq_rddwn.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_rddwn.o mmsle/rq_rddwn.c + +release/rq_outpu.o: mmsle/rq_outpu.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_outpu.o mmsle/rq_outpu.c + +release/rq_obtfi.o: mmsle/rq_obtfi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_obtfi.o mmsle/rq_obtfi.c + +release/rq_loadd.o: mmsle/rq_loadd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_loadd.o mmsle/rq_loadd.c + +release/rq_kill.o: mmsle/rq_kill.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_kill.o mmsle/rq_kill.c + +release/rq_jwrit.o: mmsle/rq_jwrit.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_jwrit.o mmsle/rq_jwrit.c + +release/rq_jstat.o: mmsle/rq_jstat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_jstat.o mmsle/rq_jstat.c + +release/rq_jread.o: mmsle/rq_jread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_jread.o mmsle/rq_jread.c + +release/rq_jinit.o: mmsle/rq_jinit.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_jinit.o mmsle/rq_jinit.c + +release/rq_jdele.o: mmsle/rq_jdele.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_jdele.o mmsle/rq_jdele.c + +release/rq_jcrea.o: mmsle/rq_jcrea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_jcrea.o mmsle/rq_jcrea.c + +release/rq_input.o: mmsle/rq_input.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_input.o mmsle/rq_input.c + +release/rq_initu.o: mmsle/rq_initu.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_initu.o mmsle/rq_initu.c + +release/rq_initd.o: mmsle/rq_initd.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_initd.o mmsle/rq_initd.c + +release/rq_getsc.o: mmsle/rq_getsc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_getsc.o mmsle/rq_getsc.c + +release/rq_getas.o: mmsle/rq_getas.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_getas.o mmsle/rq_getas.c + +release/rq_getae.o: mmsle/rq_getae.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_getae.o mmsle/rq_getae.c + +release/rq_frena.o: mmsle/rq_frena.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_frena.o mmsle/rq_frena.c + +release/rq_fread.o: mmsle/rq_fread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_fread.o mmsle/rq_fread.c + +release/rq_fopen.o: mmsle/rq_fopen.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_fopen.o mmsle/rq_fopen.c + +release/rq_fdir.o: mmsle/rq_fdir.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_fdir.o mmsle/rq_fdir.c + +release/rq_fdele.o: mmsle/rq_fdele.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_fdele.o mmsle/rq_fdele.c + +release/rq_fclos.o: mmsle/rq_fclos.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_fclos.o mmsle/rq_fclos.c + +release/rq_downl.o: mmsle/rq_downl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_downl.o mmsle/rq_downl.c + +release/rq_delvl.o: mmsle/rq_delvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_delvl.o mmsle/rq_delvl.c + +release/rq_delva.o: mmsle/rq_delva.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_delva.o mmsle/rq_delva.c + +release/rq_delty.o: mmsle/rq_delty.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_delty.o mmsle/rq_delty.c + +release/rq_delse.o: mmsle/rq_delse.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_delse.o mmsle/rq_delse.c + +release/rq_delpi.o: mmsle/rq_delpi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_delpi.o mmsle/rq_delpi.c + +release/rq_delee.o: mmsle/rq_delee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_delee.o mmsle/rq_delee.c + +release/rq_delec.o: mmsle/rq_delec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_delec.o mmsle/rq_delec.c + +release/rq_delea.o: mmsle/rq_delea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_delea.o mmsle/rq_delea.c + +release/rq_deldo.o: mmsle/rq_deldo.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_deldo.o mmsle/rq_deldo.c + +release/rq_defvl.o: mmsle/rq_defvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_defvl.o mmsle/rq_defvl.c + +release/rq_defva.o: mmsle/rq_defva.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_defva.o mmsle/rq_defva.c + +release/rq_defty.o: mmsle/rq_defty.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_defty.o mmsle/rq_defty.c + +release/rq_defse.o: mmsle/rq_defse.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_defse.o mmsle/rq_defse.c + +release/rq_defsc.o: mmsle/rq_defsc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_defsc.o mmsle/rq_defsc.c + +release/rq_defec.o: mmsle/rq_defec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_defec.o mmsle/rq_defec.c + +release/rq_defea.o: mmsle/rq_defea.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_defea.o mmsle/rq_defea.c + +release/rq_crepi.o: mmsle/rq_crepi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_crepi.o mmsle/rq_crepi.c + +release/rq_altee.o: mmsle/rq_altee.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_altee.o mmsle/rq_altee.c + +release/rq_altec.o: mmsle/rq_altec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/rq_altec.o mmsle/rq_altec.c + +release/mms_ced2.o: mmsle/mms_ced2.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_ced2.o mmsle/mms_ced2.c + +release/mms_ced1.o: mmsle/mms_ced1.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mms_ced1.o mmsle/mms_ced1.c + +release/sclproc.o: mvlu/sclproc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/sclproc.o mvlu/sclproc.c + +release/s_write.o: mvlu/s_write.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_write.o mvlu/s_write.c + +release/s_status.o: mvlu/s_status.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_status.o mvlu/s_status.c + +release/s_read.o: mvlu/s_read.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_read.o mvlu/s_read.c + +release/s_obtfi.o: mvlu/s_obtfi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_obtfi.o mvlu/s_obtfi.c + +release/s_jstat.o: mvlu/s_jstat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_jstat.o mvlu/s_jstat.c + +release/s_jread.o: mvlu/s_jread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_jread.o mvlu/s_jread.c + +release/s_jinit.o: mvlu/s_jinit.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_jinit.o mvlu/s_jinit.c + +release/s_info.o: mvlu/s_info.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_info.o mvlu/s_info.c + +release/s_ident.o: mvlu/s_ident.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_ident.o mvlu/s_ident.c + +release/s_getvla.o: mvlu/s_getvla.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_getvla.o mvlu/s_getvla.c + +release/s_getvaa.o: mvlu/s_getvaa.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_getvaa.o mvlu/s_getvaa.c + +release/s_getnam.o: mvlu/s_getnam.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_getnam.o mvlu/s_getnam.c + +release/s_getdom.o: mvlu/s_getdom.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_getdom.o mvlu/s_getdom.c + +release/s_getcl.o: mvlu/s_getcl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_getcl.o mvlu/s_getcl.c + +release/s_fren.o: mvlu/s_fren.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_fren.o mvlu/s_fren.c + +release/s_fread.o: mvlu/s_fread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_fread.o mvlu/s_fread.c + +release/s_fopen.o: mvlu/s_fopen.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_fopen.o mvlu/s_fopen.c + +release/s_fdir.o: mvlu/s_fdir.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_fdir.o mvlu/s_fdir.c + +release/s_fdel.o: mvlu/s_fdel.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_fdel.o mvlu/s_fdel.c + +release/s_fclose.o: mvlu/s_fclose.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_fclose.o mvlu/s_fclose.c + +release/s_delvl.o: mvlu/s_delvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_delvl.o mvlu/s_delvl.c + +release/s_defvl.o: mvlu/s_defvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_defvl.o mvlu/s_defvl.c + +release/s_concl.o: mvlu/s_concl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_concl.o mvlu/s_concl.c + +release/s_cancel.o: mvlu/s_cancel.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/s_cancel.o mvlu/s_cancel.c + +release/mvluleaf.o: mvlu/mvluleaf.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvluleaf.o mvlu/mvluleaf.c + +release/mvlu_sbo.o: mvlu/mvlu_sbo.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvlu_sbo.o mvlu/mvlu_sbo.c + +release/mvlu_rt.o: mvlu/mvlu_rt.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvlu_rt.o mvlu/mvlu_rt.c + +release/mvlu_rpt.o: mvlu/mvlu_rpt.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvlu_rpt.o mvlu/mvlu_rpt.c + +release/mvl61850_rpt.o: mvlu/mvl61850_rpt.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvl61850_rpt.o mvlu/mvl61850_rpt.c + +release/mvl61850_ctl.o: mvlu/mvl61850_ctl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvl61850_ctl.o mvlu/mvl61850_ctl.c + +release/mvl61850.o: mvlu/mvl61850.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvl61850.o mvlu/mvl61850.c + +release/mvl_var.o: mvlu/mvl_var.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvl_var.o mvlu/mvl_var.c + +release/mvl_uca.o: mvlu/mvl_uca.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvl_uca.o mvlu/mvl_uca.c + +release/mvl_type.o: mvlu/mvl_type.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvl_type.o mvlu/mvl_type.c + +release/mvl_typ2.o: mvlu/mvl_typ2.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvl_typ2.o mvlu/mvl_typ2.c + +release/mvl_serv.o: mvlu/mvl_serv.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvl_serv.o mvlu/mvl_serv.c + +release/mvl_send.o: mvlu/mvl_send.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvl_send.o mvlu/mvl_send.c + +release/mvl_objb.o: mvlu/mvl_objb.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvl_objb.o mvlu/mvl_objb.c + +release/mvl_obj.o: mvlu/mvl_obj.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvl_obj.o mvlu/mvl_obj.c + +release/mvl_ijou.o: mvlu/mvl_ijou.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvl_ijou.o mvlu/mvl_ijou.c + +release/mvl_dtyp.o: mvlu/mvl_dtyp.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvl_dtyp.o mvlu/mvl_dtyp.c + +release/mvl_buf.o: mvlu/mvl_buf.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/mvl_buf.o mvlu/mvl_buf.c + +release/c_write.o: mvlu/c_write.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_write.o mvlu/c_write.c + +release/c_status.o: mvlu/c_status.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_status.o mvlu/c_status.c + +release/c_read.o: mvlu/c_read.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_read.o mvlu/c_read.c + +release/c_obtfi.o: mvlu/c_obtfi.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_obtfi.o mvlu/c_obtfi.c + +release/c_jstat.o: mvlu/c_jstat.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_jstat.o mvlu/c_jstat.c + +release/c_jread.o: mvlu/c_jread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_jread.o mvlu/c_jread.c + +release/c_jinit.o: mvlu/c_jinit.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_jinit.o mvlu/c_jinit.c + +release/c_info.o: mvlu/c_info.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_info.o mvlu/c_info.c + +release/c_ident.o: mvlu/c_ident.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_ident.o mvlu/c_ident.c + +release/c_getvla.o: mvlu/c_getvla.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_getvla.o mvlu/c_getvla.c + +release/c_getvar.o: mvlu/c_getvar.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_getvar.o mvlu/c_getvar.c + +release/c_getnam.o: mvlu/c_getnam.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_getnam.o mvlu/c_getnam.c + +release/c_getdom.o: mvlu/c_getdom.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_getdom.o mvlu/c_getdom.c + +release/c_fren.o: mvlu/c_fren.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_fren.o mvlu/c_fren.c + +release/c_fread.o: mvlu/c_fread.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_fread.o mvlu/c_fread.c + +release/c_fopen.o: mvlu/c_fopen.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_fopen.o mvlu/c_fopen.c + +release/c_fget.o: mvlu/c_fget.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_fget.o mvlu/c_fget.c + +release/c_fdir.o: mvlu/c_fdir.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_fdir.o mvlu/c_fdir.c + +release/c_fdel.o: mvlu/c_fdel.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_fdel.o mvlu/c_fdel.c + +release/c_fclose.o: mvlu/c_fclose.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_fclose.o mvlu/c_fclose.c + +release/c_delvl.o: mvlu/c_delvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_delvl.o mvlu/c_delvl.c + +release/c_defvl.o: mvlu/c_defvl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_defvl.o mvlu/c_defvl.c + +release/c_concl.o: mvlu/c_concl.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/c_concl.o mvlu/c_concl.c + +release/tpx_dec.o: ositcps/tpx_dec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/tpx_dec.o ositcps/tpx_dec.c + +release/tp4port.o: ositcps/tp4port.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/tp4port.o ositcps/tp4port.c + +release/tp4_enc.o: ositcps/tp4_enc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/tp4_enc.o ositcps/tp4_enc.c + +release/tp0main.o: ositcps/tp0main.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/tp0main.o ositcps/tp0main.c + +release/tp0callg.o: ositcps/tp0callg.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/tp0callg.o ositcps/tp0callg.c + +release/tp0calld.o: ositcps/tp0calld.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/tp0calld.o ositcps/tp0calld.c + +release/tp0_socks.o: ositcps/tp0_socks.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/tp0_socks.o ositcps/tp0_socks.c + +release/tp0_dec.o: ositcps/tp0_dec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/tp0_dec.o ositcps/tp0_dec.c + +release/osicfgx.o: ositcps/osicfgx.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/osicfgx.o ositcps/osicfgx.c + +release/lean_var.o: ositcps/lean_var.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/lean_var.o ositcps/lean_var.c + +release/lean_cfg.o: ositcps/lean_cfg.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/lean_cfg.o ositcps/lean_cfg.c + +release/cospmain.o: ositcps/cospmain.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/cospmain.o ositcps/cospmain.c + +release/cosp_enc.o: ositcps/cosp_enc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/cosp_enc.o ositcps/cosp_enc.c + +release/cosp_dec.o: ositcps/cosp_dec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/cosp_dec.o ositcps/cosp_dec.c + +release/coppdcpr.o: ositcps/coppdcpr.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/coppdcpr.o ositcps/coppdcpr.c + +release/coppdcp.o: ositcps/coppdcp.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/coppdcp.o ositcps/coppdcp.c + +release/coppdaru.o: ositcps/coppdaru.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/coppdaru.o ositcps/coppdaru.c + +release/copp_enc.o: ositcps/copp_enc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/copp_enc.o ositcps/copp_enc.c + +release/copp_dec.o: ositcps/copp_dec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/copp_dec.o ositcps/copp_dec.c + +release/checksum.o: ositcps/checksum.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/checksum.o ositcps/checksum.c + +release/acse2var.o: ositcps/acse2var.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/acse2var.o ositcps/acse2var.c + +release/acse2enc.o: ositcps/acse2enc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/acse2enc.o ositcps/acse2enc.c + +release/acse2dib.o: ositcps/acse2dib.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/acse2dib.o ositcps/acse2dib.c + +release/acse2dec.o: ositcps/acse2dec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/acse2dec.o ositcps/acse2dec.c + +release/slogmem.o: slog/slogmem.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/slogmem.o slog/slogmem.c + +release/slogipcs.o: slog/slogipcs.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/slogipcs.o slog/slogipcs.c + +release/sloghex.o: slog/sloghex.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/sloghex.o slog/sloghex.c + +release/slogfil.o: slog/slogfil.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/slogfil.o slog/slogfil.c + +release/slog.o: slog/slog.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/slog.o slog/slog.c + +release/qmem.o: slog/qmem.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/qmem.o slog/qmem.c + +release/ssecusr0.o: ssec0/ssecusr0.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/ssecusr0.o ssec0/ssecusr0.c + +release/time_str.o: util/time_str.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/time_str.o util/time_str.c + +release/sx_enc.o: util/sx_enc.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/sx_enc.o util/sx_enc.c + +release/sx_dec.o: util/sx_dec.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/sx_dec.o util/sx_dec.c + +release/sx_data.o: util/sx_data.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/sx_data.o util/sx_data.c + +release/sx_axs4d.o: util/sx_axs4d.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/sx_axs4d.o util/sx_axs4d.c + +release/str_util.o: util/str_util.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/str_util.o util/str_util.c + +release/stime.o: util/stime.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/stime.o util/stime.c + +release/stdtime_w32.o: util/stdtime_w32.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/stdtime_w32.o util/stdtime_w32.c + +release/stdtime_quadlib.o: util/stdtime_quadlib.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/stdtime_quadlib.o util/stdtime_quadlib.c + +release/stdtime_mms_utctime.o: util/stdtime_mms_utctime.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/stdtime_mms_utctime.o util/stdtime_mms_utctime.c + +release/stdtime_mms_btime.o: util/stdtime_mms_btime.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/stdtime_mms_btime.o util/stdtime_mms_btime.c + +release/stdtime.o: util/stdtime.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/stdtime.o util/stdtime.c + +release/sclstore.o: util/sclstore.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/sclstore.o util/sclstore.c + +release/sclparse.o: util/sclparse.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/sclparse.o util/sclparse.c + +release/scl_log.o: util/scl_log.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/scl_log.o util/scl_log.c + +release/glbsem_unix.o: util/glbsem_unix.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/glbsem_unix.o util/glbsem_unix.c + +release/glbsem.o: util/glbsem.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/glbsem.o util/glbsem.c + +release/gensock2.o: util/gensock2.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/gensock2.o util/gensock2.c + +release/genlists.o: util/genlists.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/genlists.o util/genlists.c + +release/cfg_util.o: util/cfg_util.c + $(CC) -c $(CFLAGS) $(INCPATH) -o release/cfg_util.o util/cfg_util.c + +####### Install + +install_target: first FORCE + @$(CHK_DIR_EXISTS) $(INSTALL_ROOT)/usr/lib/ || $(MKDIR) $(INSTALL_ROOT)/usr/lib/ + -$(INSTALL_FILE) "$(TARGET)" "$(INSTALL_ROOT)/usr/lib/$(TARGET)" + +uninstall_target: FORCE + -$(DEL_FILE) "$(INSTALL_ROOT)/usr/lib/$(TARGET)" + -$(DEL_DIR) $(INSTALL_ROOT)/usr/lib/ + + +install: install_target FORCE + +uninstall: uninstall_target FORCE + +FORCE: + diff --git a/mmslib/asn1/ard_bool.c b/mmslib/asn1/ard_bool.c new file mode 100644 index 0000000..327119f --- /dev/null +++ b/mmslib/asn1/ard_bool.c @@ -0,0 +1,65 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ard_bool.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_DEC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ard_bool.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* get_bool */ +/* Function to read an ASN.1 ST_BOOLEAN from a message being decoded */ +/* Returns 0 if OK, non-zero if error. */ +/************************************************************************/ + +ST_RET asn1r_get_bool (ASN1_DEC_CTXT *ac, ST_BOOLEAN *ptr) + { +#ifdef DEBUG_ASN1_DECODE + if (!ptr) + { + slogCallStack (sLogCtrl, + "get_bool: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + + if (ac->asn1r_elmnt_len != 1) + { + ALOG_NERR0 ("ASN.1 decode: Boolean length not == 1"); + return (SD_FAILURE); + } + + *ptr = (ST_BOOLEAN) *(ac->asn1r_field_ptr++); + return (SD_SUCCESS); + } + diff --git a/mmslib/asn1/ard_bstr.c b/mmslib/asn1/ard_bstr.c new file mode 100644 index 0000000..c79d91d --- /dev/null +++ b/mmslib/asn1/ard_bstr.c @@ -0,0 +1,242 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ard_bstr.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/21/09 JRB 12 Set asn1r_bitstr_truncated flag for primitive*/ +/* OR constructed bitstring. */ +/* 07/21/09 JRB 11 Constructed bitstr code: enable it ALWAYS, */ +/* overhaul to make sure segments are multiples */ +/* of 8 bits, fix it to truncate. */ +/* 07/07/09 JRB 10 asn1r_get_bitstr: fix bitcount if truncated. */ +/* 04/21/08 JRB 09 Add cast to fix warning. */ +/* 03/17/04 RKR 08 Changed thisFileName */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 03/31/03 JRB 06 asn1r_get_bitstr: add max_bits arg & truncate*/ +/* bitstr if max_bits exceeded. */ +/* 03/05/02 JRB 05 Eliminate warnings. */ +/* 12/20/01 JRB 04 Chg ASN1_CTXT to ASN1_DEC_CTXT. */ +/* 12/12/01 JRB 03 Changes to compile MMS-EASE */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ard_bstr.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ + +static ST_VOID _dec_bitstr_cstr (ASN1_DEC_CTXT *ac, ST_UINT16 id_code); + +/************************************************************************/ +/* get_bitstr */ +/* Function to read a primitive bitstring from an ASN.1 message. */ +/* Truncate bitstring if it exceeds "max_bits". */ +/************************************************************************/ + +ST_RET asn1r_get_bitstr (ASN1_DEC_CTXT *ac, ST_UCHAR *bit_ptr, ST_INT max_bits) + { +ST_INT i; + +#ifdef DEBUG_ASN1_DECODE + if (!bit_ptr) + { + slogCallStack (sLogCtrl, + "get_: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + + ac->asn1r_bitstr_truncated = SD_FALSE; /* CRITICAL: init "truncated" flag*/ + + if (ac->asn1r_elmnt_len < 1) /* For element length of 0, return error code. */ + return (SD_FAILURE); + + i = *(ac->asn1r_field_ptr++); + if (i>7 || i<0) + return (2); /* Return error code for bad unused-bits value. */ + + if (ac->asn1r_elmnt_len == 1) /* When there is only the unused-bits octet, */ + { /* it must = 0, and there are no data bits. */ + if (i!=0) + return (2); + ac->asn1r_bitcount = 0; + } + + else /* Treat normal case where there are data bits. */ + { + ac->asn1r_bitcount = ((ac->asn1r_elmnt_len-1)*8 - i); /* Compute # data bits. */ + + /* If caller imposed a limit, truncate. */ + if (max_bits != 0 && ac->asn1r_bitcount > max_bits) + { + ac->asn1r_bitcount = max_bits; /* truncated */ + ac->asn1r_bitstr_truncated = SD_TRUE; + } + + /* Copy bitstring to user buffer */ + bstrcpy (bit_ptr, ac->asn1r_field_ptr, ac->asn1r_bitcount); + ac->asn1r_field_ptr += (ac->asn1r_elmnt_len - 1); /* point to next*/ + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/* get_bitstr_cstr */ +/* Function to setup to get a constructed bitstring. */ +/************************************************************************/ + +ST_VOID asn1r_get_bitstr_cstr (ASN1_DEC_CTXT *ac, ST_INT bits, ST_UCHAR *ptr) + { +#ifdef DEBUG_ASN1_DECODE + if (!ptr) + { + slogCallStack (sLogCtrl, + "get_bitstr_cstr: attempt to reference through a NULL pointer"); + return; + } +#endif + + ac->asn1r_max_bits = bits; /* max allowed # bits */ + ac->_ad_bitptr = ptr; /* pointer to bit storage area */ + *ac->_ad_bitptr = 0; /* zero first byte of user's storage area */ + ac->asn1r_bitcount = 0; /* running bit count */ + ac->asn1r_bitstr_truncated = SD_FALSE; /* CRITICAL: init "truncated" flag*/ + + ac->asn1r_u_id_fun = _dec_bitstr_cstr; /* universal until bitstr done */ + ac->asn1r_c_id_fun = asn1r_class_err; /* no more context */ + ac->asn1r_a_id_fun = asn1r_class_err; /* or application */ + ac->asn1r_p_id_fun = asn1r_class_err; /* or private */ + + ac->asn1r_save_method = ac->asn1r_decode_method; + ac->asn1r_decode_method = ASN1_CLASS_METHOD; + ac->_asn1r_fun_save = ac->asn1r_decode_done_fun; /* save the previous done fun */ + ac->asn1r_decode_done_fun = asn1r_done_err; /* can't be done for now */ + ac->_asn1r_cstr_done_save = ac->asn1r_c_done_fun[ac->asn1r_msg_level]; + ac->asn1r_c_done_fun[ac->asn1r_msg_level] = asn1r_chk_getcstr_done; + } + +/************************************************************************/ +/* _dec_bitstr_cstr */ +/* Function to decode asn.1 constructor bitstrings. */ +/* NOTE: last segment may be any length but other segments must be */ +/* multiple of 8 bits. We don't know which segment is last until the */ +/* decode completes. We assume any segment that is NOT a multiple of */ +/* 8 bits must be the last, so if any segment is received after that, */ +/* it is a protocol error. */ +/************************************************************************/ + +static ST_VOID _dec_bitstr_cstr (ASN1_DEC_CTXT *ac, ST_UINT16 id_code) + { +ST_INT numbytes; +ST_INT numbits; +ST_UCHAR unused_bits; /* # of unused bits in last byte */ + + ALOG_DEC0 ("_dec_bitstr_cstr"); + + if ((id_code & BITS_CODE) != BITS_CODE) + { /* Protocol error - invalid ID Code. */ + ALOG_NERR0 ("ASN.1 decode: unexpected tag"); + asn1r_set_dec_err(ac, ASN1E_UNEXPECTED_TAG); + return; + } + + if (ac->asn1r_constr_elmnt) /* Don't do anything for constructors */ + { + ac->asn1r_c_done_fun[ac->asn1r_msg_level] = NULL; + return; + } + + /* Handle primitive bitstrings */ + + if (ac->asn1r_bitstr_truncated) + { + /* Already truncated when earlier segment decoded. Just skip over this data.*/ + ac->asn1r_field_ptr += ac->asn1r_elmnt_len; + return; + } + + /* If bitcount before adding this segment is not multiple of 8, the */ + /* previous segment length was illegal. */ + if (ac->asn1r_bitcount % 8) + { /* Protocol error */ + ALOG_NERR0 ("ASN.1 decode: constructed bitstring previous segment length not multiple of 8"); + asn1r_set_dec_err(ac, ASN1E_INVALID_BITSTR); + return; + } + + /* check length. Handle most common case first. */ + if (ac->asn1r_elmnt_len > 1) + { + unused_bits = *ac->asn1r_field_ptr; /* read the unused-bits byte. */ + if (unused_bits > 7) + { /* Protocol error */ + ALOG_NERR0 ("ASN.1 decode: constructed bitstring unused bits > 7"); + asn1r_set_dec_err(ac, ASN1E_INVALID_BITSTR); + return; + } + + /* # of bytes of data does not include the "unused bits" byte. */ + numbytes = (ST_INT16) (ac->asn1r_elmnt_len - 1); + numbits = numbytes*8 - unused_bits; + if (ac->asn1r_bitcount + numbits > ac->asn1r_max_bits) + { + /* Truncate. Recalculate numbits, numbytes. */ + numbits = ac->asn1r_max_bits - ac->asn1r_bitcount; + numbytes = numbits / 8; + if (numbits % 8) + numbytes++; + ac->asn1r_bitstr_truncated = SD_TRUE; /* set "truncated" flag */ + } + /* Copy bitstring data (at ac->asn1r_field_ptr + 1) to user buffer */ + if (numbits) + bstrcpy (ac->_ad_bitptr, ac->asn1r_field_ptr + 1, numbits); + ac->_ad_bitptr += numbytes; /* adjust pointer */ + ac->asn1r_bitcount += numbits; /* adjust bit count */ + } + else if (ac->asn1r_elmnt_len == 1) /* ONLY unused-bits byte. Must be 0.*/ + { + unused_bits = *ac->asn1r_field_ptr; /* read the unused-bits byte. */ + if (unused_bits != 0) + { /* Protocol error */ + ALOG_NERR0 ("ASN.1 decode: bitstring no data. unused bits != 0"); + asn1r_set_dec_err(ac, ASN1E_INVALID_BITSTR); + return; + } + } + else /* (ac->asn1r_elmnt_len < 1) */ + { /* Protocol error */ + ALOG_NERR1 ("ASN.1 decode: bitstring element length = %d illegal", + ac->asn1r_elmnt_len); + asn1r_set_dec_err(ac, ASN1E_INVALID_BITSTR); + return; + } + /* CRITICAL: update field_ptr only here. */ + ac->asn1r_field_ptr += ac->asn1r_elmnt_len; + return; + } + diff --git a/mmslib/asn1/ard_btod.c b/mmslib/asn1/ard_btod.c new file mode 100644 index 0000000..43f4910 --- /dev/null +++ b/mmslib/asn1/ard_btod.c @@ -0,0 +1,72 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ard_btod.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 03/05/02 JRB 04 Eliminate warnings. */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_DEC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ard_btod.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/************************************************************************/ +/* get_btod */ +/************************************************************************/ + +ST_RET asn1r_get_btod (ASN1_DEC_CTXT *ac, MMS_BTOD *out) + { +ST_INT32 ms; /* ms time component */ +ST_INT32 day = 0; /* day component of TimeOfDay value */ + +#ifdef DEBUG_ASN1_DECODE + if (!out) + { + slogCallStack (sLogCtrl, + "get_btod: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + + /* Read Time Component (first 4 bytes) */ + ms = (((ST_INT32) *(ac->asn1r_field_ptr++)) << 24) & 0xFF000000L; + ms |= (((ST_INT32) *(ac->asn1r_field_ptr++)) << 16) & 0x00FF0000L; + ms |= (((ST_INT32) *(ac->asn1r_field_ptr++)) << 8) & 0x0000FF00L; + ms |= ((ST_INT32) *(ac->asn1r_field_ptr++)) & 0x000000FFL; + + /* Check to see if TimeOfDay is in long or short form */ + if (ac->asn1r_elmnt_len == 4) + { + out->form = MMS_BTOD4; + } + else + { + out->form = MMS_BTOD6; + day = (((ST_INT32) *(ac->asn1r_field_ptr++)) << 8) & 0xFF00; + day |= ((ST_INT32) *(ac->asn1r_field_ptr++)) & 0x00FF; + } + + out->ms = ms; + out->day = day; + return (SD_SUCCESS); + } + diff --git a/mmslib/asn1/ard_delm.c b/mmslib/asn1/ard_delm.c new file mode 100644 index 0000000..944bf22 --- /dev/null +++ b/mmslib/asn1/ard_delm.c @@ -0,0 +1,274 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ard_delmn.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_DEC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ad_delmn.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* Variable used in skipping over entire data elements. */ + + +static ST_VOID _get_delmnt_all (ASN1_DEC_CTXT *ac, ST_UINT16 id); +static ST_VOID _get_delmnt_done (ASN1_DEC_CTXT *ac); +static ST_VOID _get_delmnt_start (ASN1_DEC_CTXT *ac, ST_UINT16 id); +static ST_VOID _parse_next_done (ASN1_DEC_CTXT *ac); +static ST_VOID _parse_next_all (ASN1_DEC_CTXT *ac, ST_UINT16 id); +static ST_VOID _parse_next_start (ASN1_DEC_CTXT *ac, ST_UINT16 id); +static ST_VOID _parse_cstr_start(ASN1_DEC_CTXT *ac); + +/************************************************************************/ +/************************************************************************/ +/* get_delmnt submodule */ +/* The code below makes up the 'get_delmnt' and 'parse_next' functions, */ +/* which are used to simply ignore (possibly for later parsing) whatever*/ +/* data element is next. A user function is called at the end of the */ +/* data element to continue the parse as necessary. Both functions are */ +/* useful for data elements that require another 'layer' of software to */ +/* parse the data element. The difference is that get_delmnt moves */ +/* the data to a user-designated buffer, whereas parse_next leaves it */ +/* in place. */ +/************************************************************************/ + +/************************************************************************/ +/* get_delmnt */ +/* This function is used to parse the next ASN.1 data element, regard- */ +/* less of type, then call the selected done function. Inputs to */ +/* get_delmnt are the pointer to the user buffer where the data element */ +/* is to be put (as unparsed ASN.1-encoded data), the maximum length of */ +/* the buffer, and the user done function to be called when the end of */ +/* the data element is encountered. The actual length of the data ele- */ +/* ment is available to the user's done function through the global */ +/* variable asn1_octetcount. If there was not enough room in the user */ +/* buffer, a protocol error (OCTCSTR_TOO_BIG) will result. */ +/************************************************************************/ + +ST_VOID asn1r_get_delmnt (ASN1_DEC_CTXT *ac, ST_INT buflen, ST_UCHAR *bufptr, + ST_VOID (*done_fun)(ASN1_DEC_CTXT *ac)) + { + ac->_asn1_maxoctets = buflen; /* save buflen in global var. */ + ac->_asn1_octetptr = bufptr; /* initialize _asn1_octetptr */ + ac->asn1r_octetcount = 0; /* initialize asn1_octetcount */ + ac->_parse_begin_ptr = ac->asn1r_field_ptr; /* save ptr to start of element */ + + ac->_ad_parse_asn1r_fun_save = done_fun; /* save the selected done fun */ + ac->_ad_parse_method_save = ac->asn1r_decode_method; /* save method; restore later */ + ac->asn1r_decode_method = ASN1_CLASS_METHOD; + + ac->asn1r_c_id_fun = _get_delmnt_start; /* select CTX function */ + ac->asn1r_u_id_fun = _get_delmnt_start; /* select UNI function */ + ac->asn1r_p_id_fun = _get_delmnt_start; /* select PRV function */ + ac->asn1r_a_id_fun = _get_delmnt_start; /* select APP function */ + } + +/************************************************************************/ +/* _get_delmnt_start */ +/* This is the first function executed for the get_delmnt operation. */ +/************************************************************************/ + +static ST_VOID _get_delmnt_start (ASN1_DEC_CTXT *ac, ST_UINT16 id) + { + + ALOG_DEC0 ("_get_delmnt_start"); + + _get_delmnt_all (ac, id); /* move current elmnt to user buffer */ + + if (ac->asn1r_constr_elmnt) /* if this is a constructor elment - */ + { /* reset done fun for this msg level */ + ac->asn1r_c_done_fun[ac->asn1r_msg_level] = _get_delmnt_done; + ac->asn1r_c_id_fun = _get_delmnt_all; /* select CTX function */ + ac->asn1r_u_id_fun = _get_delmnt_all; /* select UNI function */ + ac->asn1r_p_id_fun = _get_delmnt_all; /* select PRV function */ + ac->asn1r_a_id_fun = _get_delmnt_all; /* select APP function */ + } + else /* if this is a primitive element - */ + _get_delmnt_done (ac); /* all done with the parse */ + } + +/************************************************************************/ +/* _get_delmnt_all */ +/* Moves the head of the current data element to the user buffer, and */ +/* moves the contents also in the case of a primitive data element. */ +/* Updates asn1_octetcount and leaves asn1_field_ptr pointing to the next elmnt. */ +/************************************************************************/ + +static ST_VOID _get_delmnt_all (ASN1_DEC_CTXT *ac, ST_UINT16 id) + { +ST_INT head_len; +ST_INT i; + + ALOG_DEC0 ("_get_delmnt_all"); + + head_len = ac->asn1r_field_ptr - ac->asn1r_field_start;/* check for room */ + ac->asn1r_octetcount += head_len; /* in the user buffer for */ + if (ac->asn1r_octetcount > ac->_asn1_maxoctets) /* the head of this data elmnt */ + { + ALOG_NERR0 ("ASN.1 decode: constructed octetstring too long"); + asn1r_set_dec_err (ac, ASN1E_OCTSTR_TOO_BIG); + return; + } + ac->asn1r_field_ptr = ac->asn1r_field_start; + for (i=0; i_asn1_octetptr++) = *(ac->asn1r_field_ptr++); /* to the user buffer */ + + if (ac->asn1r_constr_elmnt) /* if a constructor elment - */ + ac->asn1r_c_done_fun[ac->asn1r_msg_level] = NULL; + else /* if a primitive data element */ + { + ac->asn1r_octetcount += ac->asn1r_elmnt_len; /* check that the user buffer */ + if (ac->asn1r_octetcount > ac->_asn1_maxoctets) /* is big enough for the con- */ + { /* tents of this primitive elmnt*/ + ALOG_NERR0 ("ASN.1 decode: constructed octetstring too long"); + asn1r_set_dec_err (ac, ASN1E_OCTSTR_TOO_BIG); + return; + } + for (i=0; iasn1r_elmnt_len; i++) /* move the primitive contents */ + *(ac->_asn1_octetptr++) = *(ac->asn1r_field_ptr++); /* to the user buffer */ + } + } + +/************************************************************************/ +/* _get_delmnt_done */ +/* This function is called when the data element to be parsed is done. */ +/* This is either via a constructor done call or from the start fun. */ +/************************************************************************/ + +static ST_VOID _get_delmnt_done (ASN1_DEC_CTXT *ac) + { + ac->asn1r_decode_method = ac->_ad_parse_method_save; /* restore method */ + (*ac->_ad_parse_asn1r_fun_save)(ac); /* invoke the user function */ + } + + +/************************************************************************/ +/* parse_cstr_contents */ +/************************************************************************/ + +ST_VOID asn1r_parse_cstr_contents (ASN1_DEC_CTXT *ac, ST_VOID (*done_fun)(ASN1_DEC_CTXT *ac)) + { + ac->asn1r_c_done_fun[ac->asn1r_msg_level] = done_fun; + if (ac->asn1r_elmnt_len) + { + ac->_contents_done = ac->asn1r_field_ptr + ac->asn1r_elmnt_len; + _parse_cstr_start(ac); + } + } + +/************************************************************************/ +/* _parse_cstr_start */ +/* Function will indirectly call itself until the original asn1_c_done_fun */ +/* set by parse_cstr_contents expires. */ +/************************************************************************/ + +static ST_VOID _parse_cstr_start (ASN1_DEC_CTXT *ac) + { + ALOG_DEC0 ("_parse_next_start"); + if (ac->asn1r_field_ptr < ac->_contents_done) + asn1r_parse_next (ac, _parse_cstr_start); + } + +/************************************************************************/ +/* parse_next */ +/* This function is used to parse the next ASN.1 data element, regard- */ +/* less of type, then call the selected done function. In the user's */ +/* done function, the length of the data element is given in the global */ +/* variable 'asn1_octetcount', and the pointer to the beginning of the data */ +/* element is 'parse_begin_ptr'. */ +/************************************************************************/ + +ST_VOID asn1r_parse_next (ASN1_DEC_CTXT *ac, ST_VOID (*done_fun)(ASN1_DEC_CTXT *ac)) + { + + ac->_ad_parse_asn1r_fun_save = done_fun; /* save the selected done fun */ + ac->_ad_parse_method_save = ac->asn1r_decode_method; /* save method */ + ac->asn1r_decode_method = ASN1_CLASS_METHOD; + ac->_parse_begin_ptr = ac->asn1r_field_ptr; /* save ptr to start of element */ + + ac->asn1r_c_id_fun = _parse_next_start; /* select CTX function */ + ac->asn1r_u_id_fun = _parse_next_start; /* select UNI function */ + ac->asn1r_p_id_fun = _parse_next_start; /* select PRV function */ + ac->asn1r_a_id_fun = _parse_next_start; /* select APP function */ + } + +/************************************************************************/ +/* _parse_next_start */ +/* First function executed for the parse_next operation. */ +/************************************************************************/ + +static ST_VOID _parse_next_start (ASN1_DEC_CTXT *ac, ST_UINT16 id) + { + ALOG_DEC0 ("_parse_next_start"); + + if (ac->asn1r_constr_elmnt) /* if this is a constructor elment - */ + { + ac->asn1r_c_done_fun[ac->asn1r_msg_level] = _parse_next_done; + ac->asn1r_c_id_fun = _parse_next_all; /* select CTX function */ + ac->asn1r_u_id_fun = _parse_next_all; /* select UNI function */ + ac->asn1r_p_id_fun = _parse_next_all; /* select PRV function */ + ac->asn1r_a_id_fun = _parse_next_all; /* select APP function */ + } + else /* primitive element */ + { + ac->asn1r_field_ptr += ac->asn1r_elmnt_len; /* skip the contents */ + _parse_next_done (ac); /* all done with the parse */ + } + } + +/************************************************************************/ +/* _parse_next_all */ +/* This function is used as the only state function when parsing a */ +/* constructor element. It just lets the ASN.1 tools look it over. */ +/************************************************************************/ + +static ST_VOID _parse_next_all (ASN1_DEC_CTXT *ac, ST_UINT16 id) + { + ALOG_DEC0 ("_parse_next_all"); + + if (ac->asn1r_constr_elmnt) /* if this is a constructor elment - */ + ac->asn1r_c_done_fun[ac->asn1r_msg_level] = NULL; + else /* primitive element */ + ac->asn1r_field_ptr += ac->asn1r_elmnt_len; /* skip the contents */ + } + +/************************************************************************/ +/* _parse_next_done */ +/* This function is called when the data element to be parsed is done. */ +/* This is either via a constructor done call or from the start fun. */ +/************************************************************************/ + +static ST_VOID _parse_next_done (ASN1_DEC_CTXT *ac) + { + ac->asn1r_octetcount = (ST_INT16) (ac->asn1r_field_ptr - ac->_parse_begin_ptr); + ac->asn1r_decode_method = ac->_ad_parse_method_save; /* restore method */ + (*ac->_ad_parse_asn1r_fun_save)(ac); /* invoke the user function */ + } + diff --git a/mmslib/asn1/ard_flt.c b/mmslib/asn1/ard_flt.c new file mode 100644 index 0000000..d92f6e6 --- /dev/null +++ b/mmslib/asn1/ard_flt.c @@ -0,0 +1,572 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ard_float.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/03/08 JRB 08 Make sure elmnt_len is legal. */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 02/19/03 JRB 06 Use SD_BYTE_ORDER. */ +/* 02/19/03 JRB 05 Del VAX VMS support. For ALPHA VMS, assume */ +/* compiler option /FLOAT=IEEE_FLOAT is used */ +/* so it behaves like other systems. */ +/* 03/05/02 JRB 04 Eliminate warnings. */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_DEC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ad_float.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +#ifdef ASN1_ARB_FLOAT +static ST_INT16 _fp_common (ASN1_DEC_CTXT *ac, ST_INT16 *sign, ST_UINT16 *exp, ST_UCHAR *lptr, + ST_INT16 *m, ST_UCHAR *next, ST_INT16 doubl_prec); +#endif +/************************************************************************/ +/************************************************************************/ +/* get_float */ +/* Function to convert the MMS floating point type in the ASN.1 message */ +/* stream to the single precision "float" type of the C programming */ +/* language. This function will handle any size mantissa (which is */ +/* rounded to fit into the local single precision floating point format)*/ +/* and any size exponent width up to 15 bits. Exponents too large or */ +/* small for the local representation translate into + or - infinity or */ +/* zero, as the case may be. The return codes are: */ +/* */ +/* 0 - finite valid floating pt # decoded successfully */ +/* 1 - invalid floating point number */ +/* 2 - exponent length greater than 15 */ +/* -1 - floating point value = NaN */ +/* -2 - floating point value = + infinity */ +/* -3 - floating point value = - infinity */ +/* */ +/************************************************************************/ + +ST_RET asn1r_get_float (ASN1_DEC_CTXT *ac, ST_FLOAT *out) + { +ST_UCHAR n; /* length of the exponent part */ +ST_UCHAR *ptr; /* char ptr to output float variable out*/ +ST_UCHAR *next; /* points to next data element */ +ST_UCHAR *original_asn1_field_ptr; +ST_BOOLEAN float_is_zero; + +#ifdef ASN1_ARB_FLOAT +ST_UINT16 exp; /* local variable to hold exponent part */ +ST_INT i; /* utility variable */ +ST_INT16 sign; /* sign of the floating point quantity */ +ST_INT32 signexp; /* contains sign and exp parts of out */ +ST_INT16 m; /* # of fract bits in 1st 2 exp octets */ +ST_UINT32 *fract; /* contains fraction part of out */ +#endif + +#ifdef DEBUG_ASN1_DECODE + if (!out) + { + slogCallStack (sLogCtrl, + "get_float: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + +/* MMS spec says FloatingPoint must be at least 2 octets */ + if (ac->asn1r_elmnt_len < 2) + { + ALOG_ERR0 ("ASN.1 decode: length < 2 not allowed for FloatingPoint"); + return (SD_FAILURE); + } + + next = ac->asn1r_field_ptr + ac->asn1r_elmnt_len; + n = (ST_UCHAR) *(ac->asn1r_field_ptr++); /* read exponent width */ + +/* check to see if all the octets are 0 */ + + original_asn1_field_ptr = ac->asn1r_field_ptr; + float_is_zero = SD_TRUE; /* assume the float = 0 */ + while(ac->asn1r_field_ptr < next) + { + if (*(ac->asn1r_field_ptr++) != 0) + { + float_is_zero = SD_FALSE; + break; + } + } + if (float_is_zero) + { + ac->asn1r_field_ptr = next; + *out = (ST_FLOAT)0; /* this float = 0 */ + return(SD_SUCCESS); /* return success */ + } + else + ac->asn1r_field_ptr = original_asn1_field_ptr; + + ptr = (ST_UCHAR *) out; + +/* Treat case where MMS floating point format coincides with IEEE 754. */ + if (ac->asn1r_elmnt_len == 5 && n == 8) + { +#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */ + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++); +#else + ac->asn1r_field_ptr += 3; + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--); +#endif + *ptr = (ST_UCHAR) *ac->asn1r_field_ptr; + + ac->asn1r_field_ptr = next; + return (SD_SUCCESS); + } + + +#ifdef ASN1_ARB_FLOAT + +/* Otherwise, convert arbitrary MMS floating point into local single- */ +/* precision floating point. */ + +/* Get exponent and sign information, and read in the fraction part of */ +/* the floating point number. */ + m = 15 - (ST_INT16)n; + if ((i = _fp_common (ac,&sign,&exp,ptr,&m,next,SD_FALSE)) < 3) + { + *out = (ST_FLOAT)0; + return ((ST_INT16) i); + } + +/* Shift fraction part to bottom 3 bytes, add 1, and then shift one */ +/* more byte. This rounds fraction to local precision and places it */ +/* nine bits into the floating point number, where it's supposed to go. */ + fract = (ST_UINT32 *) out; + *fract = (*fract>>m) & (ST_UINT32)0x00FFFFFFL; + *fract = (*fract + (ST_UINT32)0x00000001L) >> 1; /* add 1 and then shift */ + if (*fract & (ST_UINT32)0x00800000L) + { /* rounding may cause */ + exp++; /* exponent to increment*/ + *fract &= (ST_UINT32)0x007FFFFFL; + } + +/* OR the sign, exponent and fraction parts together to make a valid */ +/* local floating point value. */ + exp <<= 7; /* ready to be ORed with other parts */ + signexp = ((ST_INT32) exp) << 16; + if (sign < 0) + signexp |= 0x80000000L; + *fract |= (ST_UINT32)signexp; + +/* Return to calling routine with success indicated. */ + return (SD_SUCCESS); + +#else /* No arbitrary float format support */ + return (SD_FAILURE); +#endif + } + + +/************************************************************************/ +/* get_double */ +/* Function to convert the MMS floating point type in the ASN.1 message */ +/* stream to the double precision "double" type of the C programming */ +/* language. This function will handle any size mantissa (which is */ +/* rounded to fit into the local double precision floating point format)*/ +/* and any size exponent width up to 15 bits. Exponents too large or */ +/* small for the local representation translate into + or - infinity or */ +/* zero, as the case may be. The return codes are: */ +/* */ +/* 0 - finite valid floating pt # decoded successfully */ +/* 1 - invalid floating point number */ +/* 2 - exponent length greater than 15 */ +/* -1 - floating point value = NaN */ +/* -2 - floating point value = + infinity */ +/* -3 - floating point value = - infinity */ +/* */ +/************************************************************************/ + +ST_RET asn1r_get_double (ASN1_DEC_CTXT *ac, ST_DOUBLE *out) + { +ST_UCHAR n; /* length of the exponent part */ +ST_UCHAR *ptr; /* char ptr to the out variable */ +ST_UCHAR *next; /* points to next data element */ +ST_UINT32 *h_ulong; +ST_UINT32 *l_ulong; +ST_UCHAR *original_asn1_field_ptr; +ST_BOOLEAN float_is_zero; + +#ifdef ASN1_ARB_FLOAT +ST_INT garbage_bits_in_mantissa; +ST_UCHAR round; /* flag indicating rounding, not trunc. */ +ST_UINT32 temp; /* utility variable */ +ST_UINT16 exp; /* value of exponent (biased) */ +ST_INT i; /* utility variable */ +ST_UINT32 signexp; /* contains sign and exp parts of out */ +ST_INT16 sign; /* sign of the floating point quantity */ +ST_INT16 m; /* # of fract bits in 1st fract octet */ +ST_INT16 local_double_exp_width; /* The local exp width of native double */ +ST_UINT32 *fract; /* points to fraction part of out */ +#endif + +#ifdef DEBUG_ASN1_DECODE + if (!out) + { + slogCallStack (sLogCtrl, + "get_double: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + + next = ac->asn1r_field_ptr + ac->asn1r_elmnt_len; + n = (ST_UCHAR) *(ac->asn1r_field_ptr++); /* read exponent width */ + +/* check to see if all the octets are 0 */ + original_asn1_field_ptr = ac->asn1r_field_ptr; + float_is_zero = SD_TRUE; /* assume the float = 0 */ + while(ac->asn1r_field_ptr < next) + { + if (*(ac->asn1r_field_ptr++) != 0) + { + float_is_zero = SD_FALSE; + break; + } + } + if (float_is_zero) + { + ac->asn1r_field_ptr = next; + *out = (ST_FLOAT)0; /* this float = 0 */ + return(SD_SUCCESS); /* return success */ + } + else + ac->asn1r_field_ptr = original_asn1_field_ptr; + + ptr = (ST_UCHAR *) out; + h_ulong = (ST_UINT32 *) out; + l_ulong = h_ulong + 1; + +/* Treat case where MMS floating point format coincides with IEEE 754 */ +/* double precision floating point format. */ + if (ac->asn1r_elmnt_len == 9 && n == 11) + { +#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */ + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++); +#else + ac->asn1r_field_ptr += 7; + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--); + *(ptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--); +#endif + *ptr = (ST_UCHAR) *ac->asn1r_field_ptr; + + ac->asn1r_field_ptr = next; + return (SD_SUCCESS); + } + +#ifdef ASN1_ARB_FLOAT + +/* Otherwise, convert arbitrary MMS floating point into local single- */ +/* precision floating point. */ +/* Get exponent and sign information, and read in the fraction part of */ +/* the floating point number. */ + m = 15 - (ST_INT16)n; + if ((i = _fp_common (ac,&sign,&exp,ptr,&m,next,SD_TRUE)) < 3) + { + *out = (ST_DOUBLE)0; + return ((ST_INT16) i); + } + +/* The number of bits used to store the exponent of a double precision */ +/* floating point number varies from machine to machine. The following */ +/* piece of code sets this local exponent width. */ + + /* Assume all systems now use IEEE 754 format */ + local_double_exp_width = 11; + +/* The following piece of code calculates the number of bit positions */ +/* to shift the fraction bits in the mantissa. */ +/* (local_exp_width + sign width) - (non_mantisa_bits) */ + + garbage_bits_in_mantissa = 8 - m; /* num of garb bits in mantissa */ + i = (local_double_exp_width + 1) - garbage_bits_in_mantissa; + /* was i = m + 4 */ + + fract = (ST_UINT32 *) out; + +#if SD_BYTE_ORDER==SD_LITTLE_ENDIAN /* little-endian (like Intel) */ + fract++; /* high half of f.p. */ +#endif + +/* save lowest i bits that will be lost when positioning the fraction */ + + temp =((0x00000001L << (local_double_exp_width + 1)) - 1L); + temp = *fract & (temp >> garbage_bits_in_mantissa); + + *fract <<= garbage_bits_in_mantissa; /* put fract at far left*/ + *fract >>= (local_double_exp_width + 1); /* shift fract in place */ + +/* grt rid of any sign and exponent */ + *fract &= 0x000fffff; /* other ports have 12 */ + + + /* pt at low half of fp */ +#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */ + fract++; +#else + fract--; +#endif + + *fract >>= (i-1); /* low half of f.p. */ + if (*fract & (ST_UINT32)0x00000001L) + round = SD_TRUE; + else + round = SD_FALSE; + temp <<= (32-i); + *fract = (*fract>>1) | temp; /* OR with bits from top half */ + +/* Round off the fraction part to fit into the local 8-byte double- */ +/* precision floating point number. */ + if (round) + { /* if low half is all 1's, then */ + if (*fract == 0xFFFFFFFF) /* rounding affects hi half too */ + { +#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */ + *(fract--) = 0; +#else + *(fract++) = 0; +#endif + *fract += 1; + if (*fract & (ST_UINT32)0xFFF00000L) /* if adding one overflows into */ + { /* exp part, increment exponent */ + exp += 1; + *fract &= (ST_UINT32)0x000FFFFFL; + } +#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */ + fract++; /* end up pointing to low half */ +#else + fract--; /* end up pointing to low half */ +#endif + } + else + *fract += 1; + } + +/* OR the sign, exponent and (high) fraction parts together to make a */ +/* valid local floating point value. */ + exp <<= 4; /* ready to be ORed with other parts */ + signexp = (ST_UINT32)exp << 16; + if (sign < 0) + signexp |= (ST_UINT32)0x80000000L; +#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */ + *(--fract) |= signexp; +#else + *(++fract) |= signexp; +#endif + +/* Return to calling routine with success indicated. */ + return (SD_SUCCESS); +#else + return (SD_FAILURE); +#endif + } + +/************************************************************************/ +/* _fp_common */ +/* Function to read the sign, exp, and fract parts of an MMS floating */ +/* point type into the designated arguments. This function represents */ +/* the common logic of the two functions: get_float and get_double. */ +/* Besides sign, exp, and fract, there are three other outputs from */ +/* this function: */ +/* asn1_field_ptr - global variable set to next data element in msg */ +/* m - modified in this function to be the number of fraction bits */ +/* in the 1st octet containing any fraction bits */ +/* return value - 0 - valid floating pt # with value of 0 */ +/* 1 - invalid floating point number */ +/* 2 - exponent length greater than 15 */ +/* 3 - valid, nonzero, finite floating pt # */ +/* -1 - floating point value = NaN */ +/* -2 - floating point value = + infinity */ +/* -3 - floating point value = - infinity */ +/************************************************************************/ + +#ifdef ASN1_ARB_FLOAT + +static ST_INT16 _fp_common ( + ASN1_DEC_CTXT *ac, /* ASN1 context pointer */ + ST_INT16 *sign, /* sign */ + ST_UINT16 *exp, /* exponent translated to local repr'n */ + ST_UCHAR *lptr, /* pointer to local f.p. # */ + ST_INT16 *m, /* begins as # of fract bits in 1st two */ + /* octets, modified in this function */ + ST_UCHAR *next, /* pointer to next data element */ + ST_INT16 doubl_prec) /* local precision - single or double */ + { +ST_INT16 lbias; /* bias of local floating point type */ +ST_UINT16 lmaxexp; /* max exponent of local f.p. type */ +ST_INT16 lfract; /* local precision length in bytes */ +ST_UINT16 bias; /* bias for MMS f.p. type being decoded */ +ST_UCHAR nonzero; /* flag indicating if fract part is !=0 */ +ST_INT i; /* utility variable */ +ST_UINT16 temp1; /* utility variable */ +ST_UCHAR temp2; /* utility variable */ + +/* Initialize variables dependent on the precision of the local f.p. */ +/* representation (either single or double). */ + if (doubl_prec) + { + lbias = 1023; + lmaxexp = 2047; + lfract = 7; + } + else + { + lbias = 127; + lmaxexp = 255; + lfract = 3; + } + +/* First, check size of exponent and fraction parts based on element */ +/* length and number of fraction bits in 1st two bytes. */ + if (ac->asn1r_elmnt_len < 3) /* must have minimum of */ + { /* 2 bytes for f.p. # */ + ac->asn1r_field_ptr = next; + return (SD_FAILURE); + } + if (*m < 0) /* exp part too big */ + { + ac->asn1r_field_ptr = next; + return (2); + } + if (*m >= 15) /* exp part too small */ + { + ac->asn1r_field_ptr = next; + return (SD_FAILURE); + } + +/* Move exponent and sign parts into *exp variable for manipulation. */ + temp1 = ((ST_UINT16) *(ac->asn1r_field_ptr++)) << 8; + *exp = temp1 | ((ST_UINT16) *(ac->asn1r_field_ptr++) & (ST_UINT16)0x00ff); + +/* Determine sign, and mask out. */ + if (*exp & (ST_UINT16)0x8000) + { + *sign = -1; + *exp = *exp & (ST_UINT16)0x7FFF; /* zero sign bit */ + } + else + *sign = 1; + +/* Reset asn1_field_ptr to point to 1st octet containing any fraction bits. */ + if (*m > 8) + ac->asn1r_field_ptr -= 2; + else if (*m > 0) + ac->asn1r_field_ptr--; + +/* Calculate bias of MMS floating point number before m is changed. */ + bias = (ST_UINT16)0x7FFF >> (*m+1); /* bias = 2**(n-1) - 1 */ + +/* Determine if exponent part is all 1's. In this case, MMS float = NaN */ +/* or infinity, so return with appropriate return code. */ + + *exp = *exp >> *m; /* get rid of fract bits on right */ + temp1 = (ST_UINT16)0x7FFF >> *m; /* prepare comparison bytes */ + *m = *m%8; + if (*m == 0) + *m = 8; /* m = # fract bits in current octet */ + if (*exp == temp1) /* check for all 1's in exponent */ + { + nonzero = SD_FALSE; /* now check for all 0's in fraction */ + temp2 = (ST_UCHAR) (*(ac->asn1r_field_ptr++) & ~(0xFF<<*m)); + while (ac->asn1r_field_ptr <= next) /* if all fract bits = */ + { /* 0, then we have a + */ + if (temp2) /* or - infinity */ + { + nonzero = SD_TRUE; + break; + } + temp2 = (ST_UCHAR) *(ac->asn1r_field_ptr++); + } + ac->asn1r_field_ptr = next; + if (nonzero) + return (-1); /* nonzero fract => NaN */ + else if (*sign > 0) + return (-2); /* case of + infinity */ + else + return (-3); /* case of - infinity */ + } + +/* Now that we know MMS float is a valid finite value, translate its */ +/* exponent part into the exponent for the local representation. */ + if ((i = (ST_INT16)*exp + lbias - (ST_INT16)bias) < 0) + return (SD_SUCCESS); /* Value too small to represent locally.*/ + + *exp = (ST_UINT16) i; + if (*exp > lmaxexp) /* biased local exp */ + { /* value too big to */ + ac->asn1r_field_ptr = next; /* represent locally - */ + if (*sign > 0) /* treat as + or - inf */ + return (-2); + else + return (-3); + } + +/* Move fraction part into local variable. */ +#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */ + for (i=0;iasn1r_field_ptr < next) + *(lptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr++); + else + { + *(lptr++) = (ST_UCHAR) 0; /* zero fill if local precision */ + } + } +#else + ac->asn1r_field_ptr += lfract; + for (i=0;iasn1r_field_ptr < next) + *(lptr++) = (ST_UCHAR) *(ac->asn1r_field_ptr--); + else + { + *(lptr++) = (ST_UCHAR) 0; /* zero fill if local precision */ + ac->asn1r_field_ptr--; /* is greater than MMS f.p. */ + } + } + *lptr = (ST_UCHAR) *ac->asn1r_field_ptr; /* we know last byte < next */ +#endif + + ac->asn1r_field_ptr = next; + return (3); /* normal case */ + } +#endif /* end of ARB FLOAT support */ diff --git a/mmslib/asn1/ard_idnt.c b/mmslib/asn1/ard_idnt.c new file mode 100644 index 0000000..98808c1 --- /dev/null +++ b/mmslib/asn1/ard_idnt.c @@ -0,0 +1,91 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ard_idnt.c */ +/* PRODUCT(S) : ASN1DE */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/24/03 JRB 04 Del MAX_IDENT_LEN define, get from mms_def2.h*/ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_DEC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ad_idnt.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include +#include "asn1r.h" +#include "asn1log.h" +#include "mms_def2.h" /* need MAX_IDENT_LEN define */ + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* get_identifier */ +/* Reads visible character data from message into selected buffer. If */ +/* character is encountered which is not valid for ASN.1 VisibleString */ +/* type, error code will be returned as function return value. Other- */ +/* wise, function return value will be zero. This function will verify */ +/* that buffer is big enough. Conversion from ASCII to local character */ +/* representation is not necessary for MS-DOS. */ +/************************************************************************/ + +ST_RET asn1r_get_identifier (ASN1_DEC_CTXT *ac, ST_CHAR *ptr) + { +ST_INT i; + +#ifdef DEBUG_ASN1_DECODE + if (!ptr) + { + slogCallStack (sLogCtrl, + "get_identifier: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + + if (ac->asn1r_elmnt_len > MAX_IDENT_LEN) + { /* if the name is to long return error */ + ALOG_NERR1 ("ASN.1 decode: Identifier too long (%u) ", + (ST_UINT) ac->asn1r_elmnt_len); + return (SD_FAILURE); + } + + if (isdigit(*ac->asn1r_field_ptr)) /* the first letter may not be a digit */ + { + ALOG_NERR0 ("ASN.1 decode: Identifier cannot start with a digit"); + return (SD_FAILURE); + } + + for (i = ac->asn1r_elmnt_len; i; --i) + { + if ((!(isalnum(*ac->asn1r_field_ptr))) && + (!(*ac->asn1r_field_ptr == '_')) && + (!(*ac->asn1r_field_ptr == '$'))) + { + ALOG_NERR1 ("ASN.1 decode: invalid character (0x%02x) in identifier", + (int) *ac->asn1r_field_ptr); + return (SD_FAILURE); + } + + *ptr = (ST_CHAR) *(ac->asn1r_field_ptr++); /* Move character to user buffer. */ + ptr++; + } + *ptr = '\x00'; /* Null terminate the visible string. */ + return(SD_SUCCESS); /* If no problelms, return success. */ + } diff --git a/mmslib/asn1/ard_int.c b/mmslib/asn1/ard_int.c new file mode 100644 index 0000000..0c10340 --- /dev/null +++ b/mmslib/asn1/ard_int.c @@ -0,0 +1,490 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ard_int.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/24/09 JRB 09 Fix signed int out of range error detection. */ +/* Use separate signed & unsigned functions. */ +/* Simplify negative value handling. */ +/* 10/03/08 JRB 08 Fix crash by testing for asn1r_elmnt_len < 1.*/ +/* 06/10/05 JRB 07 Use i64 suffix on WIN32, default to LL suffix*/ +/* 03/03/05 EJV 06 Use LL suffix also on linux. */ +/* 03/16/04 EJV 05 Added ST_(U)LONG typecast to logs,on some sys*/ +/* ST_(U)INT32 can be (unsigned) long or int. */ +/* asn1r_get_u8 (_u16): fixed potential problem.*/ +/* 01/08/04 EJV 04 asn1r_get_int64: added define for sun. */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_DEC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ad_int.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ + +static ST_RET asn1r_get_int32 (ASN1_DEC_CTXT *ac, ST_INT32 *ptr); +static ST_RET asn1r_get_uint32 (ASN1_DEC_CTXT *ac, ST_UINT32 *ptr); +#ifdef INT64_SUPPORT +static ST_RET asn1r_get_int64 (ASN1_DEC_CTXT *ac, ST_INT64 *ptr); +static ST_RET asn1r_get_uint64 (ASN1_DEC_CTXT *ac, ST_UINT64 *ptr); +#endif + +/************************************************************************/ +/* get_i8 */ +/* Function to read a short integer from a message being decoded. */ +/* Assumes asn1_field_ptr points to data (content field), and asn1_elmnt_len */ +/* equals exactly one byte. Leaves pointer set to next data element. */ +/* Returns 0 if OK, non-zero if error. */ +/************************************************************************/ + +ST_RET asn1r_get_i8 (ASN1_DEC_CTXT *ac, ST_INT8 *ptr) + { +ST_INT32 value; +ST_RET ret; + + ret = asn1r_get_int32 (ac, &value); + if (ret == SD_SUCCESS && (value > 127 || value < -128)) + { + ALOG_NERR1 ("ASN.1 decode: Signed8 out of range (%ld)", (ST_LONG) value); + return (SD_FAILURE); + } + + *ptr = (ST_CHAR) value; + return (ret); + } + +/************************************************************************/ +/* get_i16 */ +/* Function to read an integer from a message being decoded. */ +/* Assume asn1_field_ptr points to data, and asn1_elmnt_len */ +/* equals one or two bytes. Leaves pointer set to next data element. */ +/* Returns 0 if OK, non-zero if error. */ +/************************************************************************/ + +ST_RET asn1r_get_i16 (ASN1_DEC_CTXT *ac, ST_INT16 *ptr) + { +ST_INT32 value; +ST_RET ret; + + ret = asn1r_get_int32 (ac, &value); + if (ret == SD_SUCCESS && (value > 32767 || value < -32768)) + { + ALOG_NERR1 ("ASN.1 decode: Signed16 out of range (%ld)", (ST_LONG) value); + return (SD_FAILURE); + } + + *ptr = (ST_INT16) value; + return (ret); + } + +/************************************************************************/ +/* get_i32 */ +/* Function to read a long integer from a message being decoded. */ +/* Assumes asn1_field_ptr points to data, and asn1_elmnt_len */ +/* equals one to four bytes. Leaves pointer set to next data element. */ +/* Returns 0 if OK, non-zero if error. */ +/************************************************************************/ + +ST_RET asn1r_get_i32 (ASN1_DEC_CTXT *ac, ST_INT32 *ptr) + { +ST_INT32 value; +ST_RET ret; + + ret = asn1r_get_int32 (ac, &value); + *ptr = value; + return (ret); + } + +/************************************************************************/ +/* get_u8 */ +/* Function to read an ASN.1 INTEGER from a message being decoded */ +/* into a 1-byte unsigned char. Assumes asn1_field_ptr points to data */ +/* field and asn1_elmnt_len has 1 or 2 bytes. Leaves asn1_field_ptr pointing to */ +/* next data element. Returns 0 if OK, non-zero if error. */ +/************************************************************************/ + +ST_RET asn1r_get_u8 (ASN1_DEC_CTXT *ac, ST_UCHAR *ptr) + { +ST_UINT32 value; +ST_RET ret; + + ret = asn1r_get_uint32 (ac, &value); + if (ret == SD_SUCCESS && value > 0xFF) + { + ALOG_NERR1 ("ASN.1 decode: Unsigned16 out of range (%lu)", (ST_ULONG) value); + return (SD_FAILURE); + } + + *ptr = (ST_UCHAR) value; + return (ret); + } + +/************************************************************************/ +/* get_u16 */ +/* Function to read an ASN.1 INTEGER from a message being decoded */ +/* into a 2-byte unsigned integer. Assumes asn1_field_ptr points to data */ +/* field and asn1_elmnt_len has 1 to 3 bytes. Leaves asn1_field_ptr pointing to */ +/* next data element. Returns 0 if OK, non-zero if error. */ +/************************************************************************/ + +ST_RET asn1r_get_u16 (ASN1_DEC_CTXT *ac, ST_UINT16 *ptr) + { +ST_UINT32 value; +ST_RET ret; + + ret = asn1r_get_uint32 (ac, &value); + if (ret == SD_SUCCESS && value > 0xFFFF) + { + ALOG_NERR1 ("ASN.1 decode: Unsigned16 out of range (%lu)", (ST_ULONG) value); + return (SD_FAILURE); + } + + *ptr = (ST_UINT16) value; + return (ret); + } + +/************************************************************************/ +/* get_u32 */ +/* Function to read an ASN.1 INTEGER from a message being decoded */ +/* into a 4-byte unsigned ST_INT32. Assumes asn1_field_ptr points to data */ +/* field and asn1_elmnt_len has 1 to 5 bytes. Leaves asn1_field_ptr pointing */ +/* to next data element. Returns 0 if OK, non-zero if error. */ +/************************************************************************/ + +ST_RET asn1r_get_u32 (ASN1_DEC_CTXT *ac, ST_UINT32 *ptr) + { +ST_UINT32 value; +ST_RET ret; + + ret = asn1r_get_uint32 (ac, &value); + *ptr = value; + return (ret); + } + +/************************************************************************/ +/* Use this function ONLY for "signed" integers. */ +/************************************************************************/ +static ST_RET asn1r_get_int32 (ASN1_DEC_CTXT *ac, ST_INT32 *ptr) + { +/* NOTE: Use all "unsigned" variables so shifting & casting does not */ +/* cause sign extension, then cast final result to ST_INT32. */ +ST_UINT32 value; /* decoded value */ +ST_UINT32 tmp; +ST_BOOLEAN positive; +ST_INT i; + +#ifdef DEBUG_ASN1_DECODE + if (!ptr) + { + slogCallStack (sLogCtrl, + "get_i32: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + +/* ASN.1 spec says 'integer' must be at least 1 octet */ + if (ac->asn1r_elmnt_len < 1) + { + ALOG_ERR0 ("ASN.1 decode: length < 1 not allowed for integer"); + return (SD_FAILURE); + } + +/* Check to see if the ASN.1 data value is positive or negative */ + if (*ac->asn1r_field_ptr & 0x80) + positive = SD_FALSE; + else + positive = SD_TRUE; + + +/* Large 'unsigned' values may be 5 bytes, with a leading 0. */ +/* This value is 'signed', so it should NEVER be more than 4 bytes. */ + i = ac->asn1r_elmnt_len; + if (i > 4) + { + ALOG_NERR0 ("ASN.1 decode: invalid 'signed' integer encoding (more than 4 bytes)"); + return (SD_FAILURE); + } + +/* Read the value into a ST_UINT32, shifting as we go */ + if (!positive) + value = 0xFFFFFF00; /* negative value, start with high bits set */ + else + value = 0; /* positive value, start with 0 */ + while (SD_TRUE) + { + /* asn1r_field_ptr is (ST_UCHAR *), so this cast should NEVER sign extend.*/ + tmp = (ST_UINT32) *(ac->asn1r_field_ptr++); + value |= tmp; + if (--i == 0) + break; + + value <<= 8; /* more bytes to decode. Make room for next byte.*/ + } + +/* Finally, after all shifting & masking, cast it to 'signed' value. */ + *ptr = (ST_INT32) value; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* Use this function ONLY for "unsigned" integers. */ +/************************************************************************/ +static ST_RET asn1r_get_uint32 (ASN1_DEC_CTXT *ac, ST_UINT32 *ptr) + { +ST_UINT32 value; /* decoded value */ +ST_UINT32 tmp; +ST_INT i; + +#ifdef DEBUG_ASN1_DECODE + if (!ptr) + { + slogCallStack (sLogCtrl, + "get_u32: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + +/* ASN.1 spec says 'integer' must be at least 1 octet */ + if (ac->asn1r_elmnt_len < 1) + { + ALOG_ERR0 ("ASN.1 decode: length < 1 not allowed for integer"); + return (SD_FAILURE); + } + +/* ASN.1 data value MUST BE positive. */ + if (*ac->asn1r_field_ptr & 0x80) + { + ALOG_NERR0 ("ASN.1 decode: Negative number received for unsigned integer"); + return (SD_FAILURE); + } + +/* Large 'unsigned' values may be 5 bytes, with a leading 0. */ +/* If so, we strip the leading 0. */ + i = ac->asn1r_elmnt_len; + if (i > 5) + { + ALOG_NERR0 ("ASN.1 decode: invalid UINT32 encoding (more than 5 bytes)"); + return (SD_FAILURE); + } + if (i == 5) /* Large positive number, first byte must be 0. */ + { + if (*ac->asn1r_field_ptr != 0) + { + ALOG_NERR0 ("ASN.1 decode: invalid UINT32 encoding (5 bytes but first byte != 0)"); + return (SD_FAILURE); + } + ++ac->asn1r_field_ptr; /* skip the leading 0 */ + --i; + } + +/* Read the value into a ST_UINT32, shifting as we go */ + value = 0; + while (SD_TRUE) + { + /* asn1r_field_ptr is (ST_UCHAR *), so this cast should NEVER sign extend.*/ + tmp = (ST_UINT32) *(ac->asn1r_field_ptr++); + value |= tmp; + if (--i == 0) + break; + + value <<= 8; /* more bytes to decode. Make room for next byte.*/ + } + + *ptr = value; + return (SD_SUCCESS); + } + +/************************************************************************/ +#ifdef INT64_SUPPORT +/************************************************************************/ +/************************************************************************/ + +ST_RET asn1r_get_u64 (ASN1_DEC_CTXT *ac, ST_UINT64 *ptr) + { +ST_UINT64 value; +ST_RET ret; + + ret = asn1r_get_uint64 (ac, &value); + *ptr = value; + return (ret); + } + +/************************************************************************/ + +ST_RET asn1r_get_i64 (ASN1_DEC_CTXT *ac, ST_INT64 *ptr) + { +ST_INT64 value; +ST_RET ret; + + ret = asn1r_get_int64 (ac, &value); + *ptr = value; + return (ret); + } + +/************************************************************************/ +/* Use this function ONLY for "signed" integers. */ +/************************************************************************/ +static ST_RET asn1r_get_int64 (ASN1_DEC_CTXT *ac, ST_INT64 *ptr) + { +/* NOTE: Use all "unsigned" variables so shifting & casting does not */ +/* cause sign extension, then cast final result to ST_INT64. */ +ST_UINT64 value; /* decoded value */ +ST_UINT64 tmp; +ST_BOOLEAN positive; +ST_INT i; + +#ifdef DEBUG_ASN1_DECODE + if (!ptr) + { + slogCallStack (sLogCtrl, + "get_i64: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + +/* ASN.1 spec says 'integer' must be at least 1 octet */ + if (ac->asn1r_elmnt_len < 1) + { + ALOG_ERR0 ("ASN.1 decode: length < 1 not allowed for integer"); + return (SD_FAILURE); + } + +/* Check to see if the ASN.1 data value is positive or negative */ + if (*ac->asn1r_field_ptr & 0x80) + positive = SD_FALSE; + else + positive = SD_TRUE; + + +/* Large 'unsigned' values may be 9 bytes, with a leading 0. */ +/* This value is 'signed', so it should NEVER be more than 8 bytes. */ + i = ac->asn1r_elmnt_len; + if (i > 8) + { + ALOG_NERR0 ("ASN.1 decode: invalid 'signed' integer encoding (more than 8 bytes)"); + return (SD_FAILURE); + } + +/* Read the value into a ST_UINT64, shifting as we go */ + if (!positive) + { +#if defined(_WIN32) + value = 0xffffffffffffff00i64; /* negative value, start with high bits set*/ +#else + value = 0xffffffffffffff00LL; /* negative value, start with high bits set*/ +#endif + } + else + value = 0; /* positive value, start with 0 */ + while (SD_TRUE) + { + /* asn1r_field_ptr is (ST_UCHAR *), so this cast should NEVER sign extend.*/ + tmp = (ST_UINT64) *(ac->asn1r_field_ptr++); + value |= tmp; + if (--i == 0) + break; + + value <<= 8; /* more bytes to decode. Make room for next byte.*/ + } + +/* Finally, after all shifting & masking, cast it to 'signed' value. */ + *ptr = (ST_INT64) value; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* Use this function ONLY for "unsigned" integers. */ +/************************************************************************/ +static ST_RET asn1r_get_uint64 (ASN1_DEC_CTXT *ac, ST_UINT64 *ptr) + { +ST_UINT64 value; /* decoded value */ +ST_UINT64 tmp; +ST_INT i; + +#ifdef DEBUG_ASN1_DECODE + if (!ptr) + { + slogCallStack (sLogCtrl, + "get_u64: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + +/* ASN.1 spec says 'integer' must be at least 1 octet */ + if (ac->asn1r_elmnt_len < 1) + { + ALOG_ERR0 ("ASN.1 decode: length < 1 not allowed for integer"); + return (SD_FAILURE); + } + +/* ASN.1 data value MUST BE positive. */ + if (*ac->asn1r_field_ptr & 0x80) + { + ALOG_NERR0 ("ASN.1 decode: Negative number received for unsigned integer"); + return (SD_FAILURE); + } + +/* Large 'unsigned' values may be 9 bytes, with a leading 0. */ +/* If so, we strip the leading 0. */ + i = ac->asn1r_elmnt_len; + if (i > 9) + { + ALOG_NERR0 ("ASN.1 decode: invalid UINT64 encoding (more than 9 bytes)"); + return (SD_FAILURE); + } + if (i == 9) /* Large positive number, first byte must be 0. */ + { + if (*ac->asn1r_field_ptr != 0) + { + ALOG_NERR0 ("ASN.1 decode: invalid UINT64 encoding (9 bytes but first byte != 0)"); + return (SD_FAILURE); + } + ++ac->asn1r_field_ptr; /* skip the leading 0 */ + --i; + } + +/* Read the value into a ST_UINT64, shifting as we go */ + value = 0; + while (SD_TRUE) + { + /* asn1r_field_ptr is (ST_UCHAR *), so this cast should NEVER sign extend.*/ + tmp = (ST_UINT64) *(ac->asn1r_field_ptr++); + value |= tmp; + if (--i == 0) + break; + + value <<= 8; /* more bytes to decode. Make room for next byte.*/ + } + + *ptr = value; + return (SD_SUCCESS); + } + +/************************************************************************/ +#endif /* #ifdef INT64_SUPPORT */ +/************************************************************************/ diff --git a/mmslib/asn1/ard_objd.c b/mmslib/asn1/ard_objd.c new file mode 100644 index 0000000..c0a75a6 --- /dev/null +++ b/mmslib/asn1/ard_objd.c @@ -0,0 +1,113 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ard_objid.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_DEC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ard_objid.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/* get_objid */ +/* Function to read an object identifier data element from an ASN.1 msg */ +/* and put sub-identifiers into integer array. */ +/************************************************************************/ + +#define MAX_OBJ_ID_COMPONENTS 16 + +ST_RET asn1r_get_objid (ASN1_DEC_CTXT *ac, ST_INT16 component_list[], ST_INT *num_components) + { +ST_UCHAR c; /* Temporary storage for octets. */ +ST_UCHAR *last_pos; /* One past last position of this data element. */ +ST_UINT16 j; /* Temporarily holds value encoded in 2 octets. */ +ST_INT i; /* Counter for looping through sub-identifiers. */ + +#ifdef DEBUG_ASN1_DECODE + if (!num_components || !component_list) + { + slogCallStack (sLogCtrl, + "get_objid: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + + last_pos = ac->asn1r_field_ptr + ac->asn1r_elmnt_len; + c = *(ac->asn1r_field_ptr++); /* First 2 subIDs reside in 1st octet. */ + + if (c & 0x80) + { + ALOG_NERR0 ("ASN.1 decode: Object ID first octet error"); + return (SD_FAILURE); + } + + if ((component_list[0] = c/40) > 2) + { + ALOG_NERR0 ("ASN.1 decode: Object ID component 0 too big"); + return (SD_FAILURE); + } + + if ((component_list[1] = c%40) > 39) + { + ALOG_NERR0 ("ASN.1 decode: Object ID component 1 too big"); + return (SD_FAILURE); + } + + *num_components = 2; + +/* Decode remaining subIDs in contents of object identifier data el't. */ + + for (i=2; ac->asn1r_field_ptr < last_pos; i++,(*num_components)++) + { + if (i >= MAX_OBJ_ID_COMPONENTS) /* avoid overwrite */ + { + ALOG_NERR0 ("ASN.1 decode: Object ID too many components"); + return (SD_FAILURE); + } + + if ((c = *(ac->asn1r_field_ptr++)) & 0x80) /* if next octet is not last - */ + { + if (*ac->asn1r_field_ptr & 0x80) /* reject if more than 2 octets */ + { + ALOG_NERR0 ("ASN.1 decode: Object ID more than 2 octets for value"); + return (SD_FAILURE); + } + + j = (ST_UINT16) (c & 0x7F) << 7; /* support two octets per subID */ + j |= (*(ac->asn1r_field_ptr++) & 0x7F); /* merge the 14 ID bits */ + component_list[i] = j; + } + else /* only one octet */ + component_list[i] = (ST_UINT16) c; /* write masked ID code */ + } + + return(SD_SUCCESS); + } + diff --git a/mmslib/asn1/ard_ostr.c b/mmslib/asn1/ard_ostr.c new file mode 100644 index 0000000..38f8395 --- /dev/null +++ b/mmslib/asn1/ard_ostr.c @@ -0,0 +1,188 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2006, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ard_ostr.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/20/09 JRB 10 Enable constructed octetstring code ALWAYS. */ +/* 07/02/07 JRB 09 Chg ..fixlen, ..varlen arg to (ST_UCHAR *). */ +/* 07/10/06 EJV 08 Add casting to elim warnings on Sun. */ +/* 12/05/05 JRB 07 Add asn1r_get_octstr_fixlen,asn1r_get_octstr_varlen*/ +/* 03/17/04 RKR 06 Changed thisFileName */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 03/05/02 JRB 04 Eliminate warnings. */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_DEC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ard_ostr.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +static ST_VOID _dec_octstr_cstr (ASN1_DEC_CTXT *ac, ST_UINT16 id_code); + +/************************************************************************/ +/* asn1r_get_octstr_fixlen */ +/* Just like asn1r_get_octstr but checks the length for a */ +/* "fixed length" octet string (len must exactly match expected len). */ +/************************************************************************/ +ST_RET asn1r_get_octstr_fixlen (ASN1_DEC_CTXT *aCtx, ST_UCHAR *ptr, ST_INT len) + { +ST_RET retcode; + if (aCtx->asn1r_elmnt_len != len) + { + ALOG_ERR2("ASN.1 decode: octet string len = %d does not match expected len = %d", + aCtx->asn1r_elmnt_len, len); + retcode = SD_FAILURE; + } + else + retcode = asn1r_get_octstr (aCtx, (ST_UCHAR *) ptr); + return (retcode); + } + +/************************************************************************/ +/* asn1r_get_octstr_varlen */ +/* Just like asn1r_get_octstr but checks the length for a */ +/* "variable length" octet string (len must be "<=" max len). */ +/************************************************************************/ +ST_RET asn1r_get_octstr_varlen (ASN1_DEC_CTXT *aCtx, ST_UCHAR *ptr, ST_INT maxlen, ST_INT *lenout) + { +ST_RET retcode; + if (aCtx->asn1r_elmnt_len > maxlen) + { + ALOG_ERR2("ASN.1 decode: octet string len = %d exceeds max len = %d", + aCtx->asn1r_elmnt_len, maxlen); + retcode = SD_FAILURE; + } + else + { + *lenout = aCtx->asn1r_elmnt_len; + retcode = asn1r_get_octstr (aCtx, (ST_UCHAR *) ptr); + } + return (retcode); + } + +/************************************************************************/ +/* get_octstr */ +/* Function to read a primitive octet string from an ASN.1 message. */ +/************************************************************************/ + +ST_RET asn1r_get_octstr (ASN1_DEC_CTXT *ac, ST_UCHAR *octptr) + { +ST_INT i; + +#ifdef DEBUG_ASN1_DECODE + if (!octptr) + { + slogCallStack (sLogCtrl, + "get_octstr: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + + + if (ac->asn1r_elmnt_len) /* Treat normal case where there are data octets. */ + { + for (i = ac->asn1r_elmnt_len; i; --i) /* Move octets to user storage area. */ + *(octptr++) = *(ac->asn1r_field_ptr++); + } + ac->asn1r_octetcount = ac->asn1r_elmnt_len; /* Compute number of data octets. */ + return (SD_SUCCESS); + } + +/************************************************************************/ +/* get_octstr_cstr */ +/* Function to setup to get a constructed octet string. */ +/************************************************************************/ + +ST_VOID asn1r_get_octstr_cstr (ASN1_DEC_CTXT *ac, ST_INT numoctets, ST_UCHAR *octptr) + { +#ifdef DEBUG_ASN1_DECODE + if (!octptr) + { + slogCallStack (sLogCtrl, + "get_octstr_cstr: attempt to reference through a NULL pointer"); + return; + } +#endif + + + ac->_asn1_maxoctets = numoctets; /* max allowed # octets */ + ac->_asn1_octetptr = octptr; /* pointer to user's storage area */ + ac->asn1r_octetcount = 0; /* running octet count */ + + ac->asn1r_u_id_fun = _dec_octstr_cstr; /* universal until octstr done */ + ac->asn1r_c_id_fun = asn1r_class_err; /* no more context */ + ac->asn1r_a_id_fun = asn1r_class_err; /* or application */ + ac->asn1r_p_id_fun = asn1r_class_err; /* or private */ + + ac->asn1r_save_method = ac->asn1r_decode_method; + ac->asn1r_decode_method = ASN1_CLASS_METHOD; + ac->_asn1r_fun_save = ac->asn1r_decode_done_fun; /* save the previous done fun */ + ac->asn1r_decode_done_fun = asn1r_done_err; /* can't be done for now */ + ac->_asn1r_cstr_done_save = ac->asn1r_c_done_fun[ac->asn1r_msg_level]; + ac->asn1r_c_done_fun[ac->asn1r_msg_level] = asn1r_chk_getcstr_done; + } + +/************************************************************************/ +/* _dec_octstr_cstr */ +/* Function to decode asn.1 constructor octet strings */ +/************************************************************************/ + +static ST_VOID _dec_octstr_cstr (ASN1_DEC_CTXT *ac, ST_UINT16 id_code) + { +ST_INT i; + + ALOG_DEC0 ("_dec_octstr_cstr"); + + if ((id_code & OCT_CODE) != OCT_CODE) + { /* Protocol error - invalid ID Code. */ + ALOG_NERR0 ("ASN.1 decode: constructed octetstring, invalid tag"); + asn1r_set_dec_err(ac, ASN1E_UNEXPECTED_TAG); + return; + } + + if (ac->asn1r_constr_elmnt) /* Don't do anything for constructors. */ + { + ac->asn1r_c_done_fun[ac->asn1r_msg_level] = NULL; + return; + } + + ac->asn1r_octetcount += ac->asn1r_elmnt_len; + if (ac->asn1r_octetcount > ac->_asn1_maxoctets) + { /* User error - overflowed user storage area. */ + ALOG_NERR0 ("ASN.1 decode: constructed octetstring too long"); + asn1r_set_dec_err(ac, ASN1E_OCTSTR_TOO_BIG); + return; + } + + if (ac->asn1r_elmnt_len) /* Treat normal case where there are data octets. */ + { + for (i = ac->asn1r_elmnt_len; i; --i) /* Move octets to user storage area. */ + *(ac->_asn1_octetptr++) = *(ac->asn1r_field_ptr++); + } + return; + } + diff --git a/mmslib/asn1/ard_strn.c b/mmslib/asn1/ard_strn.c new file mode 100644 index 0000000..052638d --- /dev/null +++ b/mmslib/asn1/ard_strn.c @@ -0,0 +1,54 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ard_strn.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 04 Remove "thisFileName" */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_DEC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ad_strn.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* get_strn */ +/* Reads character data from message into selected buffer. No error */ +/* checking is done. The calling routine must verify that the buffer */ +/* is big enough. Conversion from ASCII to local character represen- */ +/* tation is not necessary for MS-DOS. */ +/************************************************************************/ + +ST_VOID asn1r_get_strn (ASN1_DEC_CTXT *ac, ST_CHAR *ptr) + { +ST_INT i; + +#ifdef DEBUG_ASN1_DECODE + if (!ptr) + { + slogCallStack (sLogCtrl, + "get_strn: attempt to reference through a NULL pointer"); + return; + } +#endif + + for (i = ac->asn1r_elmnt_len; i; --i) + *(ptr++) = (ST_CHAR) *(ac->asn1r_field_ptr++); + } + diff --git a/mmslib/asn1/ard_time.c b/mmslib/asn1/ard_time.c new file mode 100644 index 0000000..46843a6 --- /dev/null +++ b/mmslib/asn1/ard_time.c @@ -0,0 +1,284 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2006, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ard_time.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/16/07 JRB 07 Fix err decoding time near "19700101000000Z" */ +/* in timezone east of GMT by using usr_mkgmtime.*/ +/* 03/23/06 EJV 06 Cast time_t var to (ST_ULONG) and use '%lu'. */ +/* 07/26/02 EJV 05 Added code to skip fraction of a second. */ +/* 12/20/01 JRB 04 Chg ASN1_CTXT to ASN1_DEC_CTXT. */ +/* 11/19/01 EJV 03 Made asn1dec_figureDelta func static */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ad_time.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" +#include "time_str.h" /* for usr_mkgmtime */ + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* get_time */ +/* Function to decode Generalized Time into MS-DOS time (= number of */ +/* seconds since 00:00 Jan 1, 1970, GMT). */ +/************************************************************************/ + +ST_RET asn1r_get_time (ASN1_DEC_CTXT *ac, time_t *decTimeTValue) + { +struct tm breakDown; +struct tm gStruTime; +ST_UCHAR *last_pos; +ST_CHAR time_comp[6]; +ST_BOOLEAN adjustmetPos; +ST_INT adjust; +time_t resultantTimeT; + + /* check to see if the pointer for returning is valid */ + if (!decTimeTValue) + { + ALOG_ERR0 ("Required pointer passed to function is NULL, expecting non NULL time_t pointer"); + return(SD_FAILURE); + } + + ALOG_DEC0("Decode ASN1 generalized time string "); + last_pos = ac->asn1r_field_ptr + ac->asn1r_elmnt_len; /* 1 + last pos'n in data el't */ + + /* Determine the Year in this generalized time string */ + time_comp[0] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[1] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[2] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[3] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[4] = 0; + /* Convert the year to a integer string */ + breakDown.tm_year = (ST_INT16) atoi(time_comp); + breakDown.tm_year = breakDown.tm_year - 1900; + + /* Determine the month in this generalized time string */ + time_comp[0] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[1] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[2] = 0; + /* Convert the month to a integer string */ + breakDown.tm_mon = (ST_INT16) atoi(time_comp); + breakDown.tm_mon = breakDown.tm_mon - 1; + + /* Determine the day of the month in this generalized time string */ + time_comp[0] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[1] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[2] = 0; + /* Convert the day of the month to a integer string */ + breakDown.tm_mday = (ST_INT16) atoi(time_comp); + + /* Determine the hour in this generalized time string */ + time_comp[0] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[1] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[2] = 0; + /* Convert the hour to a integer string */ + breakDown.tm_hour = (ST_INT16) atoi(time_comp); + + /* Determine the min in this generalized time string */ + time_comp[0] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[1] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[2] = 0; + /* Convert the min to a integer string */ + breakDown.tm_min = (ST_INT16) atoi(time_comp); + + /* Determine the sec in this generalized time string */ + time_comp[0] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[1] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[2] = 0; + /* Convert the sec to a integer string */ + breakDown.tm_sec = (ST_INT16) atoi(time_comp); + + /* Check to see if we have overrun */ + if (ac->asn1r_field_ptr > last_pos) + return(SD_FAILURE); + + /* Broken Down Time component's */ + + ALOG_CDEC0(" Broken Down Component's so far"); + ALOG_CDEC1(" tm_sec %d",breakDown.tm_sec); + ALOG_CDEC1(" tm_min %d",breakDown.tm_min); + ALOG_CDEC1(" tm_hour %d",breakDown.tm_hour); + ALOG_CDEC1(" tm_mon %d",breakDown.tm_mon); + ALOG_CDEC1(" tm_year %d",breakDown.tm_year); + ALOG_CDEC1(" tm_mday %d",breakDown.tm_mday); + + /* There maybe be a fraction of a second in the generalized time. */ + /* Ignore the fraction value since we can not pass it currently up. */ + if (*ac->asn1r_field_ptr == '.') + { + ac->asn1r_field_ptr++; + /* skip all digits after the period */ + while (isdigit((ST_INT)(*ac->asn1r_field_ptr)) && ac->asn1r_field_ptr <= last_pos) + ac->asn1r_field_ptr++; + } + + /* Actually break down the date and time as a local time*/ + if (ac->asn1r_field_ptr == last_pos) + { + /* Place the known data into the fields */ + gStruTime.tm_sec = breakDown.tm_sec; + gStruTime.tm_min = breakDown.tm_min; + gStruTime.tm_hour = breakDown.tm_hour; + gStruTime.tm_mon = breakDown.tm_mon; + gStruTime.tm_year = breakDown.tm_year; + gStruTime.tm_mday = breakDown.tm_mday; + + gStruTime.tm_yday = 0; + gStruTime.tm_wday = 0; + gStruTime.tm_isdst = 0; + + /* Ask for a make time */ + resultantTimeT = mktime(&gStruTime); + + if (resultantTimeT == (time_t)-1) + { + ALOG_ERR0 ("mktime function returned -1 for time"); + return(SD_FAILURE); + } + + ALOG_CDEC1("Local time Decode : First Pass %lu ", (ST_ULONG) resultantTimeT); + + /* if the DST flag came up set, re run it with the DST flag */ + if (gStruTime.tm_isdst == 1) + { + gStruTime.tm_sec = breakDown.tm_sec; + gStruTime.tm_min = breakDown.tm_min; + gStruTime.tm_hour = breakDown.tm_hour; + gStruTime.tm_mon = breakDown.tm_mon; + gStruTime.tm_year = breakDown.tm_year; + gStruTime.tm_mday = breakDown.tm_mday; + + gStruTime.tm_yday = 0; + gStruTime.tm_wday = 0; + gStruTime.tm_isdst = 1; + + resultantTimeT = mktime(&gStruTime); + + if (resultantTimeT == (time_t)-1) + { + ALOG_ERR0 ("mktime function returned -1 for time"); + return(SD_FAILURE); + } + + ALOG_CDEC1("Local time Decode : Second Pass %lu ", (ST_ULONG) resultantTimeT); + } + + ALOG_CDEC1("Local time Decode : Result %lu ", (ST_ULONG) resultantTimeT); + + /* Now factor the Difference between GMT and local */ + *decTimeTValue = resultantTimeT; + + return (SD_SUCCESS); + } + + /* Actually break down the date and time as a GMT based time with possible offset */ + if ((*ac->asn1r_field_ptr == 'Z')||(*ac->asn1r_field_ptr == '+')||(*ac->asn1r_field_ptr == '-')) + { + /* Place the known data into the fields */ + gStruTime.tm_sec = breakDown.tm_sec; + gStruTime.tm_min = breakDown.tm_min; + gStruTime.tm_hour = breakDown.tm_hour; + gStruTime.tm_mon = breakDown.tm_mon; + gStruTime.tm_year = breakDown.tm_year; + gStruTime.tm_mday = breakDown.tm_mday; + + gStruTime.tm_yday = 0; + gStruTime.tm_wday = 0; + gStruTime.tm_isdst = 0; + + /* Ask for a make time */ + /* Convert "tm" struct to "time_t" assuming struct represents GMT time.*/ + resultantTimeT = usr_mkgmtime(&gStruTime); + if (resultantTimeT == (time_t)-1) + { + ALOG_ERR0 ("usr_mkgmtime function returned -1 for time"); + return(SD_FAILURE); + } + + ALOG_CDEC1("GMT time Decode : Result %lu ", (ST_ULONG) resultantTimeT); + + /* Now factor the Difference between GMT and local */ + *decTimeTValue = resultantTimeT; + + /* now if there are adjustment's to GMT */ + if ((*ac->asn1r_field_ptr == '+')||(*ac->asn1r_field_ptr == '-')) + { + if (*ac->asn1r_field_ptr == '+') + { + ALOG_CDEC0("Doing a GMT based adjustment of (+) "); + adjustmetPos = SD_TRUE; + } + else + { + ALOG_CDEC0("Doing a GMT based adjustment of (-) "); + adjustmetPos = SD_FALSE; + } + + ac->asn1r_field_ptr++; + time_comp[0] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[1] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[2] = 0; + adjust = atoi(time_comp); + + ALOG_CDEC1("Adjust by Hours %d ",adjust); + + if (adjustmetPos == SD_TRUE) + *decTimeTValue += (time_t) (adjust*(60 * 60)); /* adjust hrs */ + else + *decTimeTValue -= (time_t) (adjust*(60 * 60)); /* adjust hrs */ + + time_comp[0] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[1] = (ST_CHAR)*ac->asn1r_field_ptr++; + time_comp[2] = 0; + adjust = atoi(time_comp); + + ALOG_CDEC1("Adjust by Minutes %d ",adjust); + + if (adjustmetPos == SD_TRUE) + *decTimeTValue += (time_t) (adjust*(60)); /* adjust min */ + else + *decTimeTValue -= (time_t) (adjust*(60)); /* adjust min */ + + ALOG_CDEC1("GMT time Decode with offset : Result %lu ", (ST_ULONG) (*decTimeTValue)); + + return (SD_SUCCESS); + } + else + { + ac->asn1r_field_ptr++; /* Skip the 'Z' */ + return (SD_SUCCESS); + } + } /* end of GMT based Time */ + + /* if the string to decode does not end in nothing, "Z", "+", "-" */ + /* then return failure and dump the string */ + + ALOG_ERR0 ("Time string cannot be decoded by this ASN1 function"); + return(SD_FAILURE); + } + + diff --git a/mmslib/asn1/ard_utc.c b/mmslib/asn1/ard_utc.c new file mode 100644 index 0000000..5778f32 --- /dev/null +++ b/mmslib/asn1/ard_utc.c @@ -0,0 +1,80 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2004, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ard_utc.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : Decode MMS UtcTime */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/16/04 EJV 05 Added ST_(U)LONG typecast to logs,on some sys*/ +/* ST_(U)INT32 can be (unsigned) long or int. */ +/* 07/26/02 EJV 04 Time Quality byte chg position to lowest. */ +/* Added logging. */ +/* 07/03/02 EJV 03 MMS_UTC_TIME: chg name usec to fraction. */ +/* 12/20/01 JRB 02 Chg ASN1_CTXT to ASN1_DEC_CTXT. */ +/* 11/09/01 EJV 01 New module, derived from ard_btod.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* asn1r_get_utc_time */ +/************************************************************************/ + +ST_RET asn1r_get_utc_time (ASN1_DEC_CTXT *ac, MMS_UTC_TIME *dest) + { +#ifdef DEBUG_ASN1_DECODE + if (!dest) + { + slogCallStack (sLogCtrl, + "asn1r_get_utc_time: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + + ALOG_DEC0("Decoding UtcTime"); + + /* Read the number of seconds since January 1, 1970 (4 bytes) */ + dest->secs = (((ST_UINT32) *(ac->asn1r_field_ptr++)) << 24) & 0xFF000000L; + dest->secs |= (((ST_UINT32) *(ac->asn1r_field_ptr++)) << 16) & 0x00FF0000L; + dest->secs |= (((ST_UINT32) *(ac->asn1r_field_ptr++)) << 8) & 0x0000FF00L; + dest->secs |= ((ST_UINT32) *(ac->asn1r_field_ptr++)) & 0x000000FFL; + + /* read fraction of a second (3 bytes) */ + dest->fraction = (((ST_UINT32) *(ac->asn1r_field_ptr++)) << 16) & 0x00FF0000L; + dest->fraction |= (((ST_UINT32) *(ac->asn1r_field_ptr++)) << 8) & 0x0000FF00L; + dest->fraction |= ((ST_UINT32) *(ac->asn1r_field_ptr++)) & 0x000000FFL; + + /* read the quality flags (1 byte) */ + dest->qflags = ((ST_UINT32) *(ac->asn1r_field_ptr++)); + + ALOG_CDEC1("seconds: %lu", (ST_ULONG) dest->secs); + ALOG_CDEC1("fraction: %lu", (ST_ULONG) dest->fraction); + ALOG_CDEC1("quality: 0x%lX", (ST_ULONG) dest->qflags); + + return (SD_SUCCESS); + } + + + diff --git a/mmslib/asn1/ard_vstr.c b/mmslib/asn1/ard_vstr.c new file mode 100644 index 0000000..7cffb91 --- /dev/null +++ b/mmslib/asn1/ard_vstr.c @@ -0,0 +1,214 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2004, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ard_vstr.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/05/05 JRB 09 Add asn1r_get_vstr_maxlen. */ +/* 03/22/05 JRB 08 Fix cast in log macro. */ +/* 01/16/04 EJV 07 Added typecast to elim warning on AIX. */ +/* 09/24/03 JRB 06 Fix to properly decode 0-length UTF8string. */ +/* 04/22/03 JRB 05 Allow fixed len UTF8 only if local fmt=UTF16.*/ +/* 04/02/03 JRB 04 Add UTF8string support (asn1r_get_utf8) */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_DEC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ad_vstr.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* asn1r_get_vstr_maxlen */ +/* Just like asn1r_get_vstr but checks the string length. */ +/* NOTE: caller's buffer must be 1 byte bigger than max_len to allow */ +/* room for NULL terminator. */ +/************************************************************************/ +ST_RET asn1r_get_vstr_maxlen (ASN1_DEC_CTXT *aCtx, ST_CHAR *ptr, ST_INT max_len) + { + if (aCtx->asn1r_elmnt_len > max_len) + { + ALOG_ERR0("ASN.1 decode: visible string too long"); + return (SD_FAILURE); + } + else + return (asn1r_get_vstr (aCtx, ptr)); + } + +/************************************************************************/ +/* get_vstr */ +/* Reads visible character data from message into selected buffer. If */ +/* character is encountered which is not valid for ASN.1 VisibleString */ +/* type, error code will be returned as function return value. Other- */ +/* wise, function return value will be zero. The calling function must */ +/* verify that buffer is big enough. Conversion from ASCII to local */ +/* character representation is not necessary for MS-DOS. */ +/************************************************************************/ + +ST_RET asn1r_get_vstr (ASN1_DEC_CTXT *ac, ST_CHAR *ptr) + { +ST_INT i; + +#ifdef DEBUG_ASN1_DECODE + if (!ptr) + { + slogCallStack (sLogCtrl, + "get_vstr: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + + for (i = ac->asn1r_elmnt_len; i; --i) + { + *ptr = (ST_CHAR) *(ac->asn1r_field_ptr++); /* Move character to user buffer. */ + + if (*ptr < ' ') /* Check that character is not a control char. */ + { + ALOG_NERR1 ("ASN.1 decode: invalid character (0x%02x) in visible string", + (ST_UINT)(ST_UCHAR) *ptr); /* 2 casts to avoid sign extension*/ + return (SD_FAILURE); + } + ptr++; + } + *ptr = '\x00'; /* Null terminate the visible string. */ + return(SD_SUCCESS); /* If no problelms, return success. */ + } + +/************************************************************************/ +/* asn1r_get_utf8 */ +/* Reads Unicode UTF8 string data from message into selected buffer. If */ +/* character is encountered which is not valid for ASN.1 UTF8string */ +/* type, error code will be returned as function return value. Other- */ +/* wise, function return value will be zero. The calling function must */ +/* verify that buffer is big enough. */ +/************************************************************************/ + +ST_RET asn1r_get_utf8 (ASN1_DEC_CTXT *aCtx, ST_CHAR *ptr, ST_INT el_len) + { +ST_INT dst_len, local_len; + +#ifdef DEBUG_ASN1_DECODE + if (!ptr) + { + slogCallStack (sLogCtrl, + "get_utf8: attempt to reference through a NULL pointer"); + return(SD_FAILURE); + } +#endif + +/* Convert from UTF8 to local format. Input is NOT NULL terminated. + * abs (el_len) = maximum number of Unicode "characters". + * Multiply by the maximum size of each Unicode "character". + */ +#if (UNICODE_LOCAL_FORMAT==UNICODE_UTF16) + dst_len = abs(el_len)*2; +#else /* default is UTF8 */ + dst_len = abs(el_len)*4; +#endif + local_len = asn1r_utf8_to_local (ptr, dst_len, (ST_CHAR *) aCtx->asn1r_field_ptr, aCtx->asn1r_elmnt_len); + if (local_len < 0) + { + ALOG_NERR0 ("ASN.1 decode: UTF8 to local conversion failed"); + return(SD_FAILURE); + } + /* If this is "fixed length" (el_len>0), length must match. */ +#if (UNICODE_LOCAL_FORMAT==UNICODE_UTF16) + if (el_len > 0 && el_len*2 != local_len) /* Fixed len string */ + { + ALOG_NERR2 ("ASN.1 decode: expected UTF8string%d, received UTF8string%d", + el_len, local_len/2); + return (SD_FAILURE); + } + *(ST_UINT16*)(ptr+local_len) = 0; /* add "2 byte" NULL */ +#else /* default is UTF8 */ + if (el_len > 0) /* Fixed len string */ + { + /* This error should never occur because no way to define fixed len UTF8.*/ + ALOG_ERR0 ("ASN.1 decode: 'FIXED LENGTH' UTF8string not supported on this platform"); + return (SD_FAILURE); + } + ptr[local_len] = '\0'; /* add NULL */ +#endif + + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; /* Update decode ptr*/ + return(SD_SUCCESS); + } + +#if (UNICODE_LOCAL_FORMAT==UNICODE_UTF16) +#if defined(_WIN32) +#include +/************************************************************************/ +/* On Windows, the local format is UTF16, so this function converts */ +/* from UTF8 string to UTF16 string. */ +/* CRITICAL: "dst" is NOT automatically NULL terminated, so calling */ +/* function must do so if necessary. */ +/* dst_len = num bytes in dst "UTF16" string. */ +/* src_len = num bytes in src "UTF8" string. */ +/************************************************************************/ +ST_INT asn1r_utf8_to_local (ST_CHAR *dst, ST_INT dst_len, ST_CHAR *src, ST_INT src_len) + { +int ret; +ST_UINT16 *dst_utf16 = (ST_UINT16 *) dst; + + /* This function expects the max number of UTF16 chars (2 bytes per char) + * in the last arg, so divide "dst_len" by 2. + * It does NOT automatically NULL terminate, so neither does this function. + * It returns the number of UTF16 chars converted, so we multiply the + * return value by 2 to return the number of bytes. + */ +/*renxiaobao UTF8ÖÐÎıàÂëÐÞ¸Ä*/ +#ifdef WIN32 + memcpy(dst,src,src_len); return src_len; +#else + + ret = MultiByteToWideChar (CP_UTF8, 0, + src, src_len, dst_utf16, dst_len/2); + if (ret >= 0) + return (ret*2); /* success */ + return (-1); /* error */ +#endif + } +#else /* All other systems */ +#error Unicode UTF16 currently only supported on Windows +#endif +#else /* UNICODE_LOCAL_FORMAT==UNICODE_UTF8 */ +/************************************************************************/ +/* This function should work on any system where the local Unicode */ +/* format is UTF8. The ASN.1 format is also UTF8, so this function */ +/* basically just copies the string. */ +/* CRITICAL: dst_len must be >= src_len */ +/************************************************************************/ +ST_INT asn1r_utf8_to_local (ST_CHAR *dst, ST_INT dst_len, ST_CHAR *src, ST_INT src_len) + { + if (dst_len >= src_len) /* make sure dst has room */ + { + if (src_len > 0) + memcpy (dst, src, src_len); + return (src_len); /* success */ + } + return (-1); /* error */ + } +#endif /* UNICODE_LOCAL_FORMAT==UNICODE_UTF8 */ diff --git a/mmslib/asn1/are_bool.c b/mmslib/asn1/are_bool.c new file mode 100644 index 0000000..73153f3 --- /dev/null +++ b/mmslib/asn1/are_bool.c @@ -0,0 +1,48 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : are_bool.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 01/14/03 JRB 05 Avoid redundant logging of encode overrun. */ +/* 01/22/02 JRB 04 Chg asn1r_end_of_buffer to asn1r_buf_start. */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_ENC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ae_bool.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + + +/************************************************************************/ +/************************************************************************/ +/* wr_bool */ +/************************************************************************/ + +ST_VOID asn1r_wr_bool (ASN1_ENC_CTXT *ac, ST_BOOLEAN data) + { + if (ac->asn1r_field_ptr - 1 < ac->asn1r_buf_start) + { + ac->asn1r_encode_overrun = SD_TRUE; + return; + } + *(ac->asn1r_field_ptr--) = (ST_UCHAR) data; + } + + diff --git a/mmslib/asn1/are_bstr.c b/mmslib/asn1/are_bstr.c new file mode 100644 index 0000000..aa5011c --- /dev/null +++ b/mmslib/asn1/are_bstr.c @@ -0,0 +1,74 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : are_bstr.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/08 JRB 08 Fail encode if Bstring len < 0. */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 01/14/03 JRB 06 Avoid redundant logging of encode overrun. */ +/* 03/05/02 JRB 05 Eliminate warnings. */ +/* 01/22/02 JRB 04 Chg asn1r_end_of_buffer to asn1r_buf_start. */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_ENC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ae_bstr.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/************************************************************************/ +/* wr_bitstr */ +/************************************************************************/ + +ST_VOID asn1r_wr_bitstr (ASN1_ENC_CTXT *ac, ST_UCHAR *bitPtr, ST_INT numBits) + { +ST_INT bitsLeft; +ST_INT numBytes; + + if (numBits < 0) + { + ALOG_ERR0 ("ASN.1 Bitstring encode: Length < 0 not allowed"); + /* This is not really an overrun, but the overrun flag is the only */ + /* thing checked by the caller to detect an encoding error. */ + ac->asn1r_encode_overrun = SD_TRUE; + return; + } + + numBytes = numBits/8; /* calculate the total # bytes req'd */ + if ((bitsLeft = numBits % 8)!=0) /* get remainder */ + numBytes++; + + if (ac->asn1r_field_ptr - numBytes < ac->asn1r_buf_start) + { + ac->asn1r_encode_overrun = SD_TRUE; + return; + } + + ac->asn1r_field_ptr -= numBytes; + memcpy (ac->asn1r_field_ptr+1, bitPtr, numBytes); + + if (bitsLeft) /* write the unused-bits octet */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR) (8 - bitsLeft); + else + *(ac->asn1r_field_ptr--) = 0; + } + diff --git a/mmslib/asn1/are_btod.c b/mmslib/asn1/are_btod.c new file mode 100644 index 0000000..8707de6 --- /dev/null +++ b/mmslib/asn1/are_btod.c @@ -0,0 +1,58 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : are_btod.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 01/14/03 JRB 05 Avoid redundant logging of encode overrun. */ +/* 01/22/02 JRB 04 Chg asn1r_end_of_buffer to asn1r_buf_start. */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_ENC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ae_btod.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* wr_btod */ +/************************************************************************/ + +ST_VOID asn1r_wr_btod (ASN1_ENC_CTXT *ac, MMS_BTOD *data) + { + /* check for overun of buffer */ + if (ac->asn1r_field_ptr - 6 < ac->asn1r_buf_start) + { + ac->asn1r_encode_overrun = SD_TRUE; + return; + } + + if (data->form == MMS_BTOD6) + { + *(ac->asn1r_field_ptr--) = (ST_UCHAR) (data->day & 0xFF); /* low byte */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR) ((data->day >> 8) & 0xFF);/* high byte */ + } + + /* In any case, calculate and write the time component of the TimeOfDay */ + /* value. */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR) (data->ms & 0xFF); + *(ac->asn1r_field_ptr--) = (ST_UCHAR) ((data->ms >> 8) & 0xFF); + *(ac->asn1r_field_ptr--) = (ST_UCHAR) ((data->ms >> 16) & 0xFF); + *(ac->asn1r_field_ptr--) = (ST_UCHAR) ((data->ms >> 24) & 0xFF); + } + diff --git a/mmslib/asn1/are_delm.c b/mmslib/asn1/are_delm.c new file mode 100644 index 0000000..020494c --- /dev/null +++ b/mmslib/asn1/are_delm.c @@ -0,0 +1,43 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : are_delmn.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 01/22/02 JRB 04 Chg asn1r_field_start to asn1r_field_end. */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_ENC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ae_delmn.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + + +/************************************************************************/ +/* wr_delmnt */ +/* Function to write an entire data element to a message being built. */ +/* Useful when another layer of software encodes a data element to be */ +/* inserted into the current message. */ +/************************************************************************/ + +ST_VOID asn1r_wr_delmnt (ASN1_ENC_CTXT *ac, ST_UCHAR *bufPtr, ST_INT bufLen) + { + asn1r_wr_octstr (ac, bufPtr, bufLen); + ac->asn1r_field_end = ac->asn1r_field_ptr; + } diff --git a/mmslib/asn1/are_flt.c b/mmslib/asn1/are_flt.c new file mode 100644 index 0000000..964e45c --- /dev/null +++ b/mmslib/asn1/are_flt.c @@ -0,0 +1,122 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : are_float.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 08 Remove "thisFileName" */ +/* 01/14/03 JRB 07 Avoid redundant logging of encode overrun. */ +/* 02/19/03 JRB 06 Use SD_BYTE_ORDER. */ +/* 02/19/03 JRB 05 Del VAX VMS support. For ALPHA VMS, assume */ +/* compiler option /FLOAT=IEEE_FLOAT is used */ +/* so it behaves like other systems. */ +/* 01/22/02 JRB 04 Chg asn1r_end_of_buffer to asn1r_buf_start. */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_ENC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ae_float.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + + +/************************************************************************/ +/* wr_float */ +/* Function to convert a value of the single precision "float" type to */ +/* the MMS floating point type (of length 5 octets) and write it to the */ +/* message being constructed. The encoded floating point value is in */ +/* the standard IEEE 754 single precision floating point format with */ +/* the additional exponent width octet. */ +/************************************************************************/ + +ST_VOID asn1r_wr_float (ASN1_ENC_CTXT *ac, ST_FLOAT in) + { +ST_UCHAR *ptr; +ST_FLOAT f; + + if (ac->asn1r_field_ptr - 5 < ac->asn1r_buf_start) + { + ac->asn1r_encode_overrun = SD_TRUE; + return; + } + +#if defined(__OS2__) + ptr = (ST_UCHAR *) ∈ +#else + f = (ST_FLOAT) in; + ptr = (ST_UCHAR *) &f; +#endif + +#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */ + f = (ST_FLOAT) in; + ptr = (ST_UCHAR *) &f; + ptr += 3; + *(ac->asn1r_field_ptr--) = *(ptr--); + *(ac->asn1r_field_ptr--) = *(ptr--); + *(ac->asn1r_field_ptr--) = *(ptr--); +#else + *(ac->asn1r_field_ptr--) = *(ptr++); + *(ac->asn1r_field_ptr--) = *(ptr++); + *(ac->asn1r_field_ptr--) = *(ptr++); +#endif + *(ac->asn1r_field_ptr--) = *ptr; + *(ac->asn1r_field_ptr--) = (ST_UCHAR)'\x08'; + } + +/************************************************************************/ +/* wr_double */ +/* Function to convert a value of the double precision "double" type to */ +/* the MMS floating point type (of length 9 octets) and write it to the */ +/* message being constructed. The encoded floating point value is in */ +/* the standard IEEE 754 double precision floating point format with */ +/* the additional exponent width octet. */ +/************************************************************************/ + +ST_VOID asn1r_wr_double (ASN1_ENC_CTXT *ac, ST_DOUBLE in) + { +ST_UCHAR *ptr; + + if (ac->asn1r_field_ptr - 9 < ac->asn1r_buf_start) + { + ac->asn1r_encode_overrun = SD_TRUE; + return; + } + +#if SD_BYTE_ORDER==SD_BIG_ENDIAN /* big-endian (like Motorola) */ + ptr = (ST_UCHAR *) &in + 7; + *(ac->asn1r_field_ptr--) = *(ptr--); + *(ac->asn1r_field_ptr--) = *(ptr--); + *(ac->asn1r_field_ptr--) = *(ptr--); + *(ac->asn1r_field_ptr--) = *(ptr--); + *(ac->asn1r_field_ptr--) = *(ptr--); + *(ac->asn1r_field_ptr--) = *(ptr--); + *(ac->asn1r_field_ptr--) = *(ptr--); +#else + ptr = (ST_UCHAR *) ∈ + *(ac->asn1r_field_ptr--) = *(ptr++); + *(ac->asn1r_field_ptr--) = *(ptr++); + *(ac->asn1r_field_ptr--) = *(ptr++); + *(ac->asn1r_field_ptr--) = *(ptr++); + *(ac->asn1r_field_ptr--) = *(ptr++); + *(ac->asn1r_field_ptr--) = *(ptr++); + *(ac->asn1r_field_ptr--) = *(ptr++); +#endif + *(ac->asn1r_field_ptr--) = *ptr; + *(ac->asn1r_field_ptr--) = (ST_UCHAR)'\x0B'; + } + + diff --git a/mmslib/asn1/are_int.c b/mmslib/asn1/are_int.c new file mode 100644 index 0000000..506f2a4 --- /dev/null +++ b/mmslib/asn1/are_int.c @@ -0,0 +1,241 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : are_int.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 08 Remove "thisFileName" */ +/* 01/14/03 JRB 07 Avoid redundant logging of encode overrun. */ +/* 01/22/02 JRB 06 Chg asn1r_end_of_buffer to asn1r_buf_start. */ +/* 12/20/01 JRB 05 Chg ASN1_CTXT to ASN1_ENC_CTXT. */ +/* 11/12/01 EJV 04 Fixed function name asn1r_wr_i64 */ +/* 09/26/00 JRB 03 Add another #ifdef INT64_SUPPORT */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ae_int.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + + +/************************************************************************/ +/* Local functions in this module */ +/* These are not static because we may want to use them in macro's */ +/* to speed things up some time in the future. */ + +ST_VOID asn1r_wr_int32 (ASN1_ENC_CTXT *ac, ST_INT32 data, ST_BOOLEAN positive); +#ifdef INT64_SUPPORT +ST_VOID asn1r_wr_int64 (ASN1_ENC_CTXT *ac, ST_INT64 data, ST_BOOLEAN positive); +#endif + +/************************************************************************/ +/* wr_i8 */ +/************************************************************************/ + +ST_VOID asn1r_wr_i8 (ASN1_ENC_CTXT *ac, ST_INT8 data) + { + asn1r_wr_int32 (ac, (ST_INT32) data, (ST_BOOLEAN) (data >= 0 ? SD_TRUE : SD_FALSE)); + } + +/************************************************************************/ +/* wr_i16 */ +/* Function to write a 16-bit integer into message being constructed. */ +/* Can handle values to 16 bits. Sets asn1_field_ptr to next position. */ +/************************************************************************/ + +ST_VOID asn1r_wr_i16 (ASN1_ENC_CTXT *ac, ST_INT16 data) + { + asn1r_wr_int32 (ac, (ST_INT32) data, (ST_BOOLEAN) (data >= 0 ? SD_TRUE : SD_FALSE)); + } + +/************************************************************************/ +/* wr_i32 */ +/************************************************************************/ + +ST_VOID asn1r_wr_i32 (ASN1_ENC_CTXT *ac, ST_INT32 data) + { + asn1r_wr_int32 (ac, data, (ST_BOOLEAN) (data >= 0 ? SD_TRUE : SD_FALSE)); + } + +/************************************************************************/ +/* wr_u8 */ +/************************************************************************/ + +ST_VOID asn1r_wr_u8 (ASN1_ENC_CTXT *ac, ST_UINT8 data) + { + asn1r_wr_int32 (ac, (ST_INT32) data, SD_TRUE); + } + +/************************************************************************/ +/* wr_u16 */ +/************************************************************************/ + +ST_VOID asn1r_wr_u16 (ASN1_ENC_CTXT *ac, ST_UINT16 data) + { + asn1r_wr_int32 (ac, (ST_INT32) data, SD_TRUE); + } + +/************************************************************************/ +/* wr_u32 */ +/************************************************************************/ + +ST_VOID asn1r_wr_u32 (ASN1_ENC_CTXT *ac, ST_UINT32 data) + { + asn1r_wr_int32 (ac, (ST_INT32) data, SD_TRUE); + } + +/************************************************************************/ +/* _wr_int32 */ +/************************************************************************/ + +ST_VOID asn1r_wr_int32 (ASN1_ENC_CTXT *ac, ST_INT32 data, ST_BOOLEAN positive) + { +ST_INT i; + + if (ac->asn1r_field_ptr - 5 < ac->asn1r_buf_start) + { + ac->asn1r_encode_overrun = SD_TRUE; + return; + } + +/* First just write all 32 bits into the message */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR) data; + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(data >> 8); + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(data >> 16); + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(data >> 24); + + + if (positive) + { + /* ASN.1 requires us to eliminate redundant leading zero's, and */ + /* we need to make sure the MSB is not set in the high order byte */ + + if (*(ac->asn1r_field_ptr + 1) & 0x80) + *(ac->asn1r_field_ptr--) = 0x00; + else + { + for (i = 0; i < 3; ++i) + { + if ((*(ac->asn1r_field_ptr + 1) == 0x00) && + (!(*(ac->asn1r_field_ptr + 2) & 0x80))) + { + ++ac->asn1r_field_ptr; + } + else + break; + } + } + } + else /* The data value is negative */ + { + /* ASN.1 requires us to eliminate redundant leading 0xFF's, and */ + /* we need to make sure that the MSB is set in the high order byte */ + for (i = 0; i < 3; ++i) + { + if ((*(ac->asn1r_field_ptr + 1) == 0xFF) && + (*(ac->asn1r_field_ptr + 2) & 0x80)) + { + ++ac->asn1r_field_ptr; + } + else + break; + } + } + } + +/************************************************************************/ +/************************************************************************/ +#ifdef INT64_SUPPORT +/************************************************************************/ +/* wr_i64 */ +/************************************************************************/ + +ST_VOID asn1r_wr_i64 (ASN1_ENC_CTXT *ac, ST_INT64 data) + { + asn1r_wr_int64 (ac, (ST_INT64) data, (ST_BOOLEAN) (data >= 0 ? SD_TRUE : SD_FALSE)); + } + +ST_VOID asn1r_wr_u64 (ASN1_ENC_CTXT *ac, ST_UINT64 data) + { + asn1r_wr_int64 (ac, (ST_INT64) data, SD_TRUE); + } + +/************************************************************************/ +/* _wr_int64 */ +/************************************************************************/ + +ST_VOID asn1r_wr_int64 (ASN1_ENC_CTXT *ac, ST_INT64 data, ST_BOOLEAN positive) + { +ST_INT i; + + if (ac->asn1r_field_ptr - 9 < ac->asn1r_buf_start) + { + ac->asn1r_encode_overrun = SD_TRUE; + return; + } + + *(ac->asn1r_field_ptr--) = (ST_UCHAR) data; + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(data >> 8); + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(data >> 16); + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(data >> 24); + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(data >> 32); + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(data >> 40); + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(data >> 48); + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(data >> 56); + + if (positive) + { + /* ASN.1 requires us to eliminate redundant leading zero's, and */ + /* we need to make sure the MSB is not set in the high order byte */ + + if (*(ac->asn1r_field_ptr + 1) & 0x80) + *(ac->asn1r_field_ptr--) = 0x00; + else + { + for (i = 0; i < 7; ++i) + { + if ((*(ac->asn1r_field_ptr + 1) == 0x00) && + (!(*(ac->asn1r_field_ptr + 2) & 0x80))) + { + ++ac->asn1r_field_ptr; + } + else + break; + } + } + } + else /* The data value is negative */ + { + /* ASN.1 requires us to eliminate redundant leading 0xFF's, and */ + /* we need to make sure that the MSB is set in the high order byte */ + for (i = 0; i < 7; ++i) + { + if ((*(ac->asn1r_field_ptr + 1) == 0xFF) && + (*(ac->asn1r_field_ptr + 2) & 0x80)) + { + ++ac->asn1r_field_ptr; + } + else + break; + } + } + } + +/************************************************************************/ +#endif /* #ifdef INT64_SUPPORT */ +/************************************************************************/ + diff --git a/mmslib/asn1/are_objd.c b/mmslib/asn1/are_objd.c new file mode 100644 index 0000000..8ae6252 --- /dev/null +++ b/mmslib/asn1/are_objd.c @@ -0,0 +1,80 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : are_objid.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 01/14/03 JRB 06 Avoid redundant logging of encode overrun. */ +/* 03/05/02 JRB 05 Eliminate warnings. */ +/* 01/22/02 JRB 04 Chg asn1r_end_of_buffer to asn1r_buf_start. */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_ENC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ae_objid.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* Static functions in this module */ + +static ST_VOID _wr_component (ASN1_ENC_CTXT *ac, ST_INT16); + +/************************************************************************/ +/* wr_objid */ +/* Function to write an object identifier data element to a message */ +/* being built. */ +/************************************************************************/ + +ST_VOID asn1r_wr_objid (ASN1_ENC_CTXT *ac, ST_INT16 component_list[], ST_INT num_components) + { +ST_INT i; +ST_INT16 icomp; + + for (i = num_components - 1; i > 1; i--) + _wr_component(ac, component_list[i]); + + icomp = component_list[1] + component_list[0]*40; + _wr_component(ac, icomp); + } + +/************************************************************************/ +/* _wr_component */ +/* Function to write an integer to a field of octets in the following */ +/* format: [1xxxxxxx] ... 0xxxxxxx , where all but the last */ +/* octet starts with a 1 bit, and where the x's are the bits of the */ +/* binary integer input to the function (distributed 7 bits per octet).*/ +/************************************************************************/ + +static ST_VOID _wr_component (ASN1_ENC_CTXT *ac, ST_INT16 icomp) + { + if (ac->asn1r_field_ptr -2 < ac->asn1r_buf_start) + { + ac->asn1r_encode_overrun = SD_TRUE; + return; + } + + if (icomp < 0x80) + *(ac->asn1r_field_ptr--) = (ST_UCHAR) icomp; + else + { + *(ac->asn1r_field_ptr--) = (ST_UCHAR) (icomp & 0x7F); + *(ac->asn1r_field_ptr--) = (ST_UCHAR) (((icomp >> 7) & 0x7F) | 0x80); + } + } + diff --git a/mmslib/asn1/are_ostr.c b/mmslib/asn1/are_ostr.c new file mode 100644 index 0000000..1fc28cc --- /dev/null +++ b/mmslib/asn1/are_ostr.c @@ -0,0 +1,61 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : are_ostr.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/08 JRB 08 Fail encode if Ostring len < 0. */ +/* 08/01/05 JRB 07 Add const on asn1_wr_octstr args. */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 01/14/03 JRB 05 Avoid redundant logging of encode overrun. */ +/* 01/22/02 JRB 04 Chg asn1r_end_of_buffer to asn1r_buf_start. */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_ENC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ae_ostr.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* wr_octstr */ +/* Function to write a primitive octet string to a message being built. */ +/************************************************************************/ + +ST_VOID asn1r_wr_octstr (ASN1_ENC_CTXT *ac, const ST_UCHAR *octPtr, ST_INT numOctets) + { + if (numOctets < 0) + { + ALOG_ERR0 ("ASN.1 Octetstring encode: Length < 0 not allowed"); + /* This is not really an overrun, but the overrun flag is the only */ + /* thing checked by the caller to detect an encoding error. */ + ac->asn1r_encode_overrun = SD_TRUE; + return; + } + if (ac->asn1r_field_ptr - numOctets < ac->asn1r_buf_start) + { + ac->asn1r_encode_overrun = SD_TRUE; + return; + } + + ac->asn1r_field_ptr -= numOctets; + memcpy (ac->asn1r_field_ptr+1, octPtr, numOctets); + } + diff --git a/mmslib/asn1/are_time.c b/mmslib/asn1/are_time.c new file mode 100644 index 0000000..3500212 --- /dev/null +++ b/mmslib/asn1/are_time.c @@ -0,0 +1,88 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2006, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : are_time.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/23/06 EJV 07 Cast time_t var to (ST_ULONG) and use '%lu'. */ +/* 01/14/03 JRB 06 Avoid redundant logging of encode overrun. */ +/* 07/29/02 EJV 05 Log tmp_buf instead of ac->asn1r_field_ptr. */ +/* 01/22/02 JRB 04 Chg asn1r_end_of_buffer to asn1r_buf_start. */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_ENC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ae_time.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/* for wr_time the length of the string */ +#define ASN1_WR_TIME_ENC_L 15 + +/************************************************************************/ +/* wr_time */ +/* Function to encode date and time from MS-DOS time (= number of */ +/* seconds from 00:00 Jan 1, 1970, GMT) to the ASN.1 Generalized time */ +/************************************************************************/ +ST_VOID asn1r_wr_time (ASN1_ENC_CTXT *ac, time_t toEncodeTime) + { +struct tm *gmtTime; +ST_UCHAR tmp_buf [ASN1_WR_TIME_ENC_L + 1]; + + ALOG_ENC0("Encoding a GMT Zulu based time string"); + + /* check to see if the ASN1 field pointer will overflow the buffer */ + if (ac->asn1r_field_ptr - ASN1_WR_TIME_ENC_L < ac->asn1r_buf_start) + { + ac->asn1r_encode_overrun = SD_TRUE; + return; + } + + /* move the asn1 field ptr backward in the buffer */ + ac->asn1r_field_ptr = ac->asn1r_field_ptr - (ASN1_WR_TIME_ENC_L-1); + + ALOG_CENC1("Passed Unix epoche based GMT time is (in) = %lu", (ST_ULONG) toEncodeTime); + /*renxiaobao Îļþ²Ù×÷*/ + if(toEncodeTime<0x12cea600) toEncodeTime = 0x12cea600; /*1980*/ + gmtTime = gmtime(&toEncodeTime); + if(gmtTime) + { + /* encode a local time string */ + strftime ((ST_CHAR *)tmp_buf,ASN1_WR_TIME_ENC_L + 1,"%Y%m%d%H%M%SZ",gmtTime); + } + else + { + sprintf(tmp_buf,"19800001000000Z"); + printf("gmtime fail toEncodeTime=%lx\n",toEncodeTime); + } + /* encode a local time string */ + /*strftime ((ST_CHAR *)tmp_buf,ASN1_WR_TIME_ENC_L + 1,"%Y%m%d%H%M%SZ",gmtTime);*/ + memcpy (ac->asn1r_field_ptr, tmp_buf, ASN1_WR_TIME_ENC_L); /* no 0x00 copied */ + + ALOG_CENC1("ASN1 encoded String %s", tmp_buf); + + /* move the field pointer 1 more position back in the encode buffer */ + ac->asn1r_field_ptr = ac->asn1r_field_ptr -1; + } diff --git a/mmslib/asn1/are_utc.c b/mmslib/asn1/are_utc.c new file mode 100644 index 0000000..09f2afc --- /dev/null +++ b/mmslib/asn1/are_utc.c @@ -0,0 +1,82 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2004, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : are_utc.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : Encode MMS UtcTime */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/16/04 EJV 07 Added ST_(U)LONG typecast to logs,on some sys*/ +/* ST_(U)INT32 can be (unsigned) long or int. */ +/* 01/14/03 JRB 06 Avoid redundant logging of encode overrun. */ +/* 07/26/02 EJV 05 Time Quality byte chg position to lowest. */ +/* Added logging. */ +/* 07/03/02 EJV 04 MMS_UTC_TIME: chg name usec to fraction. */ +/* 01/22/02 JRB 03 Chg asn1r_end_of_buffer to asn1r_buf_start. */ +/* 12/20/01 JRB 02 Chg ASN1_CTXT to ASN1_ENC_CTXT. */ +/* 11/08/01 EJV 01 New module, derived from are_btod.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* asn1r_wr_utc_time */ +/************************************************************************/ + +ST_VOID asn1r_wr_utc_time (ASN1_ENC_CTXT *ac, MMS_UTC_TIME *data) + { +#define _ASN1R_UTCTIME_LEN 8 + + ALOG_ENC0("Encoding UtcTime"); + + /* check for overun of buffer (UtcTime is encoded on 8 bytes) */ + if (ac->asn1r_field_ptr - _ASN1R_UTCTIME_LEN < ac->asn1r_buf_start) + { + ac->asn1r_encode_overrun = SD_TRUE; + return; + } + + ALOG_CENC1("seconds: %lu", (ST_ULONG) data->secs); + ALOG_CENC1("fraction: %lu", (ST_ULONG) data->fraction); + ALOG_CENC1("quality: 0x%lX", (ST_ULONG) data->qflags); + + /* write the quality flags */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR) data->qflags; + + /* write fraction of a second (3 bytes) */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR) (data->fraction & 0xFF); + *(ac->asn1r_field_ptr--) = (ST_UCHAR) ((data->fraction >> 8) & 0xFF); + *(ac->asn1r_field_ptr--) = (ST_UCHAR) ((data->fraction >> 16) & 0xFF); + + /* write the number of seconds since January 1, 1970 */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR) (data->secs & 0xFF); + *(ac->asn1r_field_ptr--) = (ST_UCHAR) ((data->secs >> 8) & 0xFF); + *(ac->asn1r_field_ptr--) = (ST_UCHAR) ((data->secs >> 16) & 0xFF); + *(ac->asn1r_field_ptr--) = (ST_UCHAR) ((data->secs >> 24) & 0xFF); + + ALOG_CENC1("Encoded %d bytes:", _ASN1R_UTCTIME_LEN); + ALOG_ENCH(_ASN1R_UTCTIME_LEN, ac->asn1r_field_ptr + 1); + } + + diff --git a/mmslib/asn1/are_vstr.c b/mmslib/asn1/are_vstr.c new file mode 100644 index 0000000..6e0435e --- /dev/null +++ b/mmslib/asn1/are_vstr.c @@ -0,0 +1,162 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2004, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : are_vstr.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/01/05 JRB 09 Add const on asn1_wr_vstr args. */ +/* 03/11/04 GLB 08 Added "ifdef DEBUG_SISCO" to "thisFileName" */ +/* 01/16/04 EJV 07 Added typecast to elim warning on AIX. */ +/* 01/14/03 JRB 06 Avoid redundant logging of encode overrun. */ +/* 09/24/03 JRB 05 Fix to properly encode 0-length UTF8string. */ +/* 04/02/03 JRB 04 Add UTF8string support (asn1r_wr_utf8) */ +/* 12/20/01 JRB 03 Chg ASN1_CTXT to ASN1_ENC_CTXT. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/26/99 MDE 01 New module, derived from ae_vstr.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1r.h" +#include "asn1log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* wr_vstr */ +/************************************************************************/ + +ST_VOID asn1r_wr_vstr (ASN1_ENC_CTXT *ac, const ST_CHAR *ptr) + { + asn1r_wr_octstr (ac, (ST_UCHAR*)ptr,strlen (ptr)); + } + +/************************************************************************/ +/* asn1r_wr_utf8 */ +/************************************************************************/ + +ST_RET asn1r_wr_utf8 (ASN1_ENC_CTXT *aCtx, ST_CHAR *ptr, ST_INT el_len) + { +ST_CHAR *utf8_ptr; /* temporary place to encode UTF8string. */ +ST_INT utf8_len; + +/* This code is a little tricky. Since we encode backwards, the data must + * be written before the current "ASN1_ENC_PTR". Since we don't know + * the len of the data until after the conversion (asn1r_local_to_utf8), + * we allow for the maximum converted size, then after the conversion, we move + * the data forward to just before "ASN1_ENC_PTR". + */ + + /* Compute maximum converted size. + * abs (el_len) = maximum number of Unicode "characters". + * Multiply by the maximum size of each Unicode "character" (4). + */ + utf8_len = (abs(el_len)*4); /* 4 bytes per char */ + + /* Point to safe spot in ASN.1 encode buffer where maximum size + * UTF8string can be encoded (including NULL terminator). + */ + utf8_ptr = (ST_CHAR *) ASN1_ENC_PTR(aCtx) - utf8_len; + if (utf8_ptr < (ST_CHAR *) aCtx->asn1r_buf_start) + { + aCtx->asn1r_encode_overrun = SD_TRUE; + return (SD_FAILURE); + } + + /* Convert data to UTF8string (NOT NULL terminated). + * NOTE: utf8_len is overwritten with the actual number of encoded bytes. + */ + utf8_len = asn1r_local_to_utf8 (utf8_ptr, utf8_len, ptr); + if (utf8_len < 0) /* 0 len is OK. */ + { + ALOG_NERR0 ("wr_utf8: conversion from local to UTF8 failed"); + return (SD_FAILURE); + } + /* Move data forward in ASN.1 encode buffer. */ + if (utf8_len > 0) + { + memmove (ASN1_ENC_PTR(aCtx)-utf8_len, (ST_UCHAR*)utf8_ptr, utf8_len); + aCtx->asn1r_field_ptr -= utf8_len; /* update ASN.1 encode ptr */ + } + return (SD_SUCCESS); + } +/*renxioabao utf8 UTF8±àÂëÐÞ¸Ä*/ +/*#if (UNICODE_LOCAL_FORMAT==UNICODE_UTF16)*/ +#if 0 +#if defined(_WIN32) +#include +/************************************************************************/ +/* On Windows, the local format is UTF16, so this function converts */ +/* from UTF16 string to UTF8 string. */ +/* The source string (at src_ptr) must be NULL terminated. */ +/* dst_len = num bytes available in dst "UTF8" string. */ +/* RETURN: num bytes in dst (not including NULL). */ +/************************************************************************/ +ST_INT asn1r_local_to_utf8 (ST_CHAR *dst_ptr, ST_INT dst_len, ST_CHAR *src_ptr) + { +ST_INT count; + +/* NOTE: pass (src_len==-1) to WideCharToMultiByte. + * "src_ptr" must be NULL terminated, and chars converted + * up to and including the NULL. + * Return value is len of dst, possibly including NULL terminator. + */ + count = WideCharToMultiByte (CP_UTF8, 0, + (ST_UINT16 *) src_ptr, -1, dst_ptr, dst_len, NULL, NULL); + if (count > 0) + { + /* "count" MAY include the NULL terminator. If so, return 1 less. */ + if (dst_ptr[count-1]=='\0') + return (count-1); /* if count includes NULL, subtract 1 */ + else + return (count); /* if count does not include NULL, return count */ + } + return (-1); /* error */ + } +#else /* All other systems */ +#error Unicode UTF16 currently only supported on Windows +#endif +#else /* UNICODE_LOCAL_FORMAT==UNICODE_UTF8 */ +/************************************************************************/ +/* This function should work on any system where the local Unicode */ +/* format is UTF8. The ASN.1 format is also UTF8, so this function */ +/* basically just copies the string. */ +/* The source string (at src_ptr) must be NULL terminated. */ +/* This function just copies up to (not including the NULL terminator). */ +/* dst_len = num bytes available in dst "UTF8" string. */ +/* CRITICAL: dst_len must be >= src_len */ +/* RETURN: num bytes in dst (not including NULL). */ +/************************************************************************/ +ST_INT asn1r_local_to_utf8 (ST_CHAR *dst_ptr, ST_INT dst_len, ST_CHAR *src_ptr) + { +ST_INT ret = -1; /* assume error */ +ST_INT src_len; + + src_len = strlen(src_ptr); /* compute src_len */ + if (src_len <= dst_len) + { + if (src_len > 0) + strncpy (dst_ptr, src_ptr, src_len); /* not including NULL terminator*/ + ret = src_len; /* success */ + } + return (ret); + } +#endif /* UNICODE_LOCAL_FORMAT==UNICODE_UTF8 */ diff --git a/mmslib/asn1/asn1r.c b/mmslib/asn1/asn1r.c new file mode 100644 index 0000000..33571af --- /dev/null +++ b/mmslib/asn1/asn1r.c @@ -0,0 +1,1693 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2009, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : asn1r.c */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the main ASN.1 decode and encode tools. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/21/09 JRB 32 Cleanup new asn1r_get_tag. */ +/* 05/29/09 JRB 31 Add asn1r_decode_init, asn1r_get_tag functs. */ +/* For indefinite len constr, increase initial */ +/* byte_count (couldn't handle big constr). */ +/* Add asn1r_strt_constr_indef (FOR TESTING). */ +/* 05/28/09 JRB 30 On decode, don't log constr content(redundant)*/ +/* 01/15/09 MDE 29 Added asn1_peek,made asn1r_head_decode static*/ +/* 11/12/08 MDE 28 Added overreach checks to asn1r_head_decode */ +/* 11/12/08 MDE 27 Removed assert to improve robustness */ +/* 10/03/08 JRB 28 Prevent crashes while decoding by improving */ +/* len checks & doing it BEFORE logging. */ +/* 10/04/07 MDE 27 Tweaked LOGCFG_VALUE_GROUP/LOGCFGX_VALUE_MAP */ +/* 12/20/06 JRB 26 Add bstrcmp. */ +/* 03/17/06 JRB 25 Add asn1r_anytag_fun, ASN1_ANYTAG_METHOD. */ +/* 03/15/06 JRB 24 Add asn1r_skip_elmnt. */ +/* 02/28/06 EJV 23 asn1_convert_...: added typecast from time_t */ +/* 12/19/05 JRB 22 Chg cr to cr_asn1, del static to fix warning.*/ +/* 05/23/05 EJV 21 Add asn1LogMaskMapCtrl for parsing logcfg.xml*/ +/* 07/08/04 JRB 20 Use define TIME_T_1984_JAN_1 instead of mktime*/ +/* Use define SECONDS_PER_DAY from asn1r.h */ +/* Add asn1_convert_timet_to_btime6. */ +/* Use 0x01000000 (2**24) in fraction computations*/ +/* 01/14/03 JRB 19 Avoid redundant logging of encode overrun. */ +/* fin_constr decrement msg_level on encode overrun*/ +/* 11/05/03 EJV 18 Fixed logging. */ +/* 10/13/03 JRB 17 asn1r_decode_asn1: Chg assert to err return. */ +/* 04/28/03 JRB 16 Add assert to asn1r_decode_asn1. */ +/* 04/02/03 JRB 15 On unexpected tag error, log the tag. */ +/* 02/07/03 JRB 14 Add bstrcpy, bvstrcpy. */ +/* 10/29/02 JRB 13 Use new asn1r_magic in ASN1_ENC_CTXT. */ +/* 07/03/02 EJV 12 MMS_UTC_TIME: chg name usec to fraction. */ +/* 03/05/02 JRB 11 Eliminate compiler warnings. */ +/* 01/25/02 JRB 10 Move INT_MAX chk to #if, avoids unreachable */ +/* code. Make SD_CONST match header on *logstr. */ +/* 01/22/02 JRB 09 asn1r_strt_asn1_bld set new "asn1r_buf_end". */ +/* Chg asn1r_end_of_buffer to asn1r_buf_start */ +/* & asn1r_field_start to asn1r_field_end */ +/* & _asn1_constr_start to asn1r_constr_end */ +/* in ENC_CTX (start means start, end means end)*/ +/* 01/07/02 EJV 08 Added asn1_ prefix to convert_... functions. */ +/* 01/04/02 EJV 07 Add convert_btod_to_utc, convert_utc_to_btod */ +/* Cleanup few function header comments. */ +/* Updated cr[] to 2002. */ +/* 12/20/01 JRB 06 Chg ASN1_CTXT to ASN1_DEC_CTXT, ASN1_ENC_CTXT*/ +/* Delete #define USE_WITH_ASN1. */ +/* Del asn1_old_err_fun & *_old_id_fun. */ +/* asn1r_objidcmp chged to asn1_objidcmp (same */ +/* as function in asn1.c). */ +/* Del unused strt_asn1r, asn1r_end_asn_bld. */ +/* 11/28/01 EJV 05 fin_prim: corrected len for logging. */ +/* 11/12/01 EJV 04 asn1r_decode_asn1: removed static variables */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 07/29/99 MDE 02 Added TABLE method */ +/* 07/26/99 MDE 01 New module, derived from asn1.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include +#include "asn1r.h" +#include "asn1log.h" +#include "mem_chk.h" + +/************************************************************************/ + +const ST_CHAR cr_asn1[] = + "(c) COPYRIGHT SYSTEMS INTEGRATION SPECIALISTS COMPANY INC., 1986 - 2005. All Rights Reserved."; + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +#if !defined(NO_GLB_VAR_INIT) +ST_UINT asn1_debug_sel = ASN1_LOG_ERR; +#else +ST_UINT asn1_debug_sel; +#endif + +#ifdef DEBUG_SISCO +SD_CONST ST_CHAR *SD_CONST _asn1_log_dec_logstr = "ASN1_LOG_DEC"; +SD_CONST ST_CHAR *SD_CONST _asn1_log_enc_logstr = "ASN1_LOG_ENC"; +SD_CONST ST_CHAR *SD_CONST _asn1_log_err_logstr = "ASN1_LOG_ERR"; +SD_CONST ST_CHAR *SD_CONST _asn1_log_nerr_logstr = "ASN1_LOG_NERR"; + +LOGCFGX_VALUE_MAP asn1LogMaskMaps[] = + { + {"ASN1_LOG_ERR", ASN1_LOG_ERR, &asn1_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Error"}, + {"ASN1_LOG_NERR", ASN1_LOG_NERR, &asn1_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Notice"}, + {"ASN1_LOG_DEC", ASN1_LOG_DEC, &asn1_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Decode"}, + {"ASN1_LOG_ENC", ASN1_LOG_ENC, &asn1_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Encode"} + }; + +LOGCFG_VALUE_GROUP asn1LogMaskMapCtrl = + { + {NULL,NULL}, + "Asn1LogMasks", /* Parent Tag */ + sizeof(asn1LogMaskMaps)/sizeof(LOGCFGX_VALUE_MAP), + asn1LogMaskMaps + }; +#endif /* DEBUG_SISCO */ + +/************************************************************************/ +/* General variables and pointers used by the ASN1 system. */ +/************************************************************************/ +/************************************************************************/ +/* VMS Float Format select */ + +/* VMS has different forms of float format; select the default here */ +#if !defined(NO_GLB_VAR_INIT) && defined(VAXC) +ST_INT asn1_vax_double_type = A_D_FLOAT; +#endif +#if !defined(NO_GLB_VAR_INIT) && defined( __ALPHA ) +ST_INT asn1_vax_double_type = A_G_FLOAT; +#endif +#if defined(NO_GLB_VAR_INIT) && (defined( VAXC ) || defined( __ALPHA )) +ST_INT asn1_vax_double_type; +#endif + +/************************************************************************/ +/* Static functions in this module */ + +static ST_RET _asn1r_head_decode (ASN1_DEC_CTXT *ac); +static ST_VOID _do_decode_asn1 (ASN1_DEC_CTXT *ac, ST_UCHAR *ptr, ST_INT len); +static ST_BOOLEAN _indef_eoc (ASN1_DEC_CTXT *ac); +static ST_VOID _check_level_done (ASN1_DEC_CTXT *ac); +static ST_VOID _call_user (ASN1_DEC_CTXT *ac); +static ST_VOID _wr_asn1_len (ASN1_ENC_CTXT *ac, ST_INT len); +static ST_VOID _wr_ident (ASN1_ENC_CTXT *ac, ST_UINT16 id_code, ST_UINT16 tag); +#ifdef DEBUG_SISCO +static ST_VOID _list_elmnt (ASN1_DEC_CTXT *ac); +#endif + +/************************************************************************/ +/************************************************************************/ +/* ASN.1 MESSAGE DECODE */ +/************************************************************************/ +/* asn1r_decode_asn1_seq */ +/* This function is used to decode a ASN.1 data element when the outer */ +/* constructor has been stripped. */ +/************************************************************************/ + +ST_VOID asn1r_decode_asn1_seq (ASN1_DEC_CTXT *ac, ST_UCHAR *ptr, ST_INT len) + { + ac->_asn1_indef_track[0] = SD_FALSE; /* level 0 is always definite */ + ac->_asn1_indef_track[1] = SD_FALSE; /* so is level 1 in this case */ + + ac->_asn1_byte_count[0] = 0; /* assumes definite */ + ac->_asn1_byte_count[1] = len; /* contents of missing outer cstr */ + + ac->asn1r_field_ptr = ptr; /* point to first element */ + ac->asn1r_msg_level = 1; /* start at message level 1 */ + ac->asn1r_c_done_fun[ac->asn1r_msg_level] = NULL; + + _do_decode_asn1 (ac, ptr,len); + } + +/************************************************************************/ +/* asn1r_decode_asn1 */ +/* Function to drive the decoding of an ASN.1 encoded message. */ +/* The user must set up the class or tag function ptrs, and the error */ +/* and done function ptrs before calling this function. Pass the length */ +/* and location of the message as inputs. */ +/************************************************************************/ + +ST_VOID asn1r_decode_asn1 (ASN1_DEC_CTXT *ac, ST_UCHAR *ptr, ST_INT len) + { +#if !defined (MMS_LITE) +ST_UCHAR *save_asn1r_ptr = NULL; +#endif + +/* The caller MUST clear ASN1_DEC_CTXT struct before calling this funct.*/ +/* After clearing, caller may set a few params, so chk a param that */ +/* caller would NEVER set. */ + if (ac->asn1r_msg_level != 0) + { + ALOG_ERR0 ("ASN.1 decode context not initialized"); + ac->asn1r_pdu_dec_err = ASN1E_DECODE_OTHER; /* set error code */ + return; + } + +/* initialize flags, counters, pointers for decode */ + + ac->asn1r_indef_flag = SD_FALSE; /* clear flag */ + ac->_asn1_indef_track[0] = SD_FALSE; /* level 0 is always definite */ + ac->_asn1_byte_count[0] = len; /* set # bytes left in level 0 */ + ac->asn1r_msg_level = 0; /* start at message level 0 */ + ac->asn1r_c_done_fun[0] = NULL; + +#if !defined (MMS_LITE) + /* save the data in case we need to log it if decode fails */ + if ( (asn1_debug_sel & ASN1_LOG_NERR) && + !(asn1_debug_sel & ASN1_LOG_DEC)) + { + save_asn1r_ptr = chk_malloc (len); + memcpy (save_asn1r_ptr, ptr, len); + } +#endif + + _do_decode_asn1 (ac, ptr,len); + +#if !defined (MMS_LITE) + if (ac->asn1r_pdu_dec_err != NO_DECODE_ERR) /* if an error was present */ + { + if (save_asn1r_ptr) + { + ALOG_NERR0 ("ASN.1 decode: badly formed PDU:"); + ALOG_NERRH (len, save_asn1r_ptr); + } + } + if (save_asn1r_ptr) + chk_free (save_asn1r_ptr); +#endif + } + +/************************************************************************/ +/* _do_decode_asn1 */ +/************************************************************************/ + +static ST_VOID _do_decode_asn1 (ASN1_DEC_CTXT *ac, ST_UCHAR *ptr, ST_INT len) + { +ST_INT log_len; +ST_INT gone_len; +ST_INT i; +ST_RET rc; + + ac->asn1r_pdu_dec_err = NO_DECODE_ERR; /* reset error flag */ + ac->asn1r_decode_done = SD_FALSE; /* initialize flag */ + ac->asn1r_field_ptr = ptr; /* initialize asn1_field_ptr */ + ac->asn1r_done_ptr = ac->asn1r_field_ptr + len; + +/* Validate length to avoid possible problems */ + if (len <= 0) + { + ALOG_NERR0 ("ASN.1 decode: Length zero or negative"); + asn1r_set_dec_err(ac, ASN1E_END_O_BUFFER); + if (ac->asn1r_err_fun != NULL) + (*ac->asn1r_err_fun)(ac, ac->asn1r_pdu_dec_err); /* call error function */ + ac->_asn1r_ntag = 0; /* set # tags = 0 for next time */ + return; + } + + ALOG_DECLF (); + ALOG_DEC1 ("ASN.1 MESSAGE TO DECODE : len = %d",len); + ALOG_DECH (len,ptr); + +/* Enter the message parse loop. */ +/* Parse the message until all done or asn1_decode_done flag is set. */ +/* asn1_field_ptr points to the start of the data element to be decoded. */ + + while (ac->asn1r_field_ptr < ac->asn1r_done_ptr && !ac->asn1r_decode_done) + { + ALOG_DEC1 ("Current decode offset: 0x%05x", ac->asn1r_field_ptr - ptr); + ac->asn1r_field_start = ac->asn1r_field_ptr; /* save field start address */ + rc = _asn1r_head_decode (ac); /* decodes the data element header */ + if (rc != SD_SUCCESS) + { + ALOG_NERR0 ("ASN.1 decode: header decode error"); + asn1r_set_dec_err(ac, rc); + break; + } + + /* OK, the header looks good and has been validated */ + log_len = ac->asn1r_field_ptr - ac->asn1r_field_start; + /* For primitive, log the whole element */ + if (!ac->asn1r_constr_elmnt) + log_len += ac->asn1r_elmnt_len; + + ALOG_DECH (log_len, ac->asn1r_field_start); + ALOG_PAUSEDEC (""); + +#ifdef DEBUG_SISCO + _list_elmnt (ac); /* print element attributes */ +#endif + + if (_indef_eoc (ac)) /* check for indefinite level EOC elmnt */ + { /* EOC is a primitive */ + _check_level_done (ac); /* primitive complete */ + continue; /* service next field if not done */ + } + /* not indefinite length EOC */ + if (ac->asn1r_decode_done) /* if errors detected in decode */ + break; + + if (ac->asn1r_constr_elmnt) /* if constructor, bump asn1_msg_level */ + { + if (++ac->asn1r_msg_level >= ASN1_MAX_LEVEL) + { + ALOG_ERR0 ("Error : ASN.1 decode exceeded nesting level"); + asn1r_set_dec_err(ac, ASN1E_NEST_TOO_DEEP); + break; + } + ac->asn1r_c_done_fun[ac->asn1r_msg_level] = asn1r_cstr_done_err; + } + +/* Call the user function specified for the given class or tag. The */ +/* user function is expected to parse the contents of this data element */ +/* (when it's primitive) and move asn1_field_ptr to the start of the next */ +/* data element. */ + _call_user (ac); + +/* The user function has been invoked, must set the asn1_decode_done flag */ +/* if the message is complete or in error. The user function must move */ +/* asn1_field_ptr to the start of the next data element. */ + + gone_len = ac->asn1r_field_ptr - ac->asn1r_field_start;/* number of bytes gone */ + /* adjust count */ + +/* For primitive data elements, decrement _asn1_byte_count for current */ +/* message level and jump directly down to _check_level_done at the end */ +/* of the while loop. */ + if (!ac->asn1r_constr_elmnt) + { + if (ac->_asn1_byte_count[ac->asn1r_msg_level] < gone_len) + { + ALOG_NERR0 ("ASN.1 decode: invalid constructor length"); + asn1r_set_dec_err (ac, ASN1E_CSTR_INVALID_LEN); /* call error function */ + break; /* exit parse loop */ + } + ac->_asn1_byte_count[ac->asn1r_msg_level] -= gone_len; + } + +/* Constructors are much more involved. First decrement the _asn1_byte_count */ +/* for the previous message level (the one containing the new constr.), */ +/* then set _asn1_byte_count for this message level. */ + else + { + if (ac->_asn1_byte_count[ac->asn1r_msg_level-1] < gone_len) + { + ALOG_NERR0 ("ASN.1 decode: invalid constructor length"); + asn1r_set_dec_err (ac, ASN1E_CSTR_INVALID_LEN); /* call error function */ + break; /* exit parse loop */ + } + ac->_asn1_byte_count[ac->asn1r_msg_level-1] -= gone_len; + + /* save length type */ + if ((ac->_asn1_indef_track[ac->asn1r_msg_level] = ac->asn1r_indef_flag) + != SD_FALSE) /* if indefinite */ + { /* (INDEF = 0xFF) */ + ac->_asn1_constr_start[ac->asn1r_msg_level] = ac->asn1r_field_ptr; /* save start pointer */ + ac->_asn1_byte_count[ac->asn1r_msg_level] = INT_MAX; + ac->asn1r_indef_flag = SD_FALSE; /* clear flag */ + } + else /* definite length constructor */ + { /* byte count in element known */ + ac->_asn1_byte_count[ac->asn1r_msg_level] = ac->asn1r_elmnt_len; + if (ac->_asn1_byte_count[ac->asn1r_msg_level-1] < (ST_INT) ac->asn1r_elmnt_len) + { + ALOG_NERR0 ("ASN.1 decode: invalid constructor length"); + asn1r_set_dec_err (ac, ASN1E_CSTR_INVALID_LEN); /* call error function */ + break; /* exit parse loop */ + } + ac->_asn1_byte_count[ac->asn1r_msg_level-1] -= ac->asn1r_elmnt_len; + } + } + +/* After decrementing _asn1_byte_count, check to see if this message level is */ +/* done (and if so, check the next msg level, etc...). */ + _check_level_done (ac); + } /* Now return to top of parse loop. */ + +/* End of outer while loop. Message parse is complete. */ +/* At this point the asn1_field_ptr should match the done_ptr, and the */ +/* asn1_pdu_dec_err variable should be = NO_DECODE_ERR, and asn1_msg_level == -1.*/ +/* If any of these conditions are not true, the user error function */ +/* will be executed (typically will return error message). If no */ +/* decode error, the user function pointed to by (*asn1_decode_done_fun) */ +/* is executed. */ + + ALOG_CDEC0 ("Message parse complete"); + ALOG_PAUSEDEC (""); + /* don't overwrite previous err */ + if (ac->asn1r_pdu_dec_err == NO_DECODE_ERR && + (ac->asn1r_field_ptr != ac->asn1r_done_ptr || ac->asn1r_msg_level != -1)) + { /* Check for indef cstr done */ + for (i = ac->asn1r_msg_level; i >= 0; --i) + { + if (ac->_asn1_indef_track[i] == SD_TRUE) /* if indef length cstr */ + { /* check for cstr done (00 00) */ + if ((ac->asn1r_field_ptr+2 > ac->asn1r_done_ptr) || + *(ac->asn1r_field_ptr++) || *(ac->asn1r_field_ptr++)) + { + ALOG_NERR0 ("ASN.1 decode: indefinite length constructor not terminated"); + asn1r_set_dec_err (ac, ASN1E_END_O_BUFFER); /* call error function */ + break; + } + } + } + if (ac->asn1r_field_ptr != ac->asn1r_done_ptr) + { + ALOG_NERR0 ("ASN.1 decode: PDU decode terminated before complete"); + asn1r_set_dec_err (ac, ASN1E_END_O_BUFFER); /* call error function */ + } + } + + if (ac->asn1r_pdu_dec_err != NO_DECODE_ERR) /* if an error was present */ + { + if (ac->asn1r_err_fun != NULL) + (*ac->asn1r_err_fun)(ac, ac->asn1r_pdu_dec_err); /* call error function */ + } + else /* if not - */ + { + if (ac->asn1r_decode_done_fun != NULL) + (*ac->asn1r_decode_done_fun)(ac); /* invoke the done function */ + } + + ac->_asn1r_ntag = 0; /* set # tags = 0 for next time */ + } + + +/************************************************************************/ +/* _check_level_done */ +/* primitive field service complete, check to see if this level is */ +/* complete, and if so, what the next level to service is. */ +/************************************************************************/ + +static ST_VOID _check_level_done (ASN1_DEC_CTXT *ac) + { +ST_INT i; + + while (ac->asn1r_msg_level >= 0 && !ac->_asn1_byte_count[ac->asn1r_msg_level]) + { /* Search for first lower level with bytes left - */ + ALOG_CDEC1 ("Level %d parse complete",ac->asn1r_msg_level); + if (!ac->asn1r_decode_done) /* if user has not terminated */ + { + ac->_asn1r_ntag = 0; /* clear tags, and call user */ + i = ac->asn1r_msg_level--; + if (ac->asn1r_c_done_fun[i] != NULL) + (*ac->asn1r_c_done_fun[i])(ac); /* done fcn for this asn1_msg_level */ + } + else /* decode terminated, just dec. */ + ac->asn1r_msg_level--; + } + + if (ac->asn1r_msg_level < 0) /* if no bytes left at any lvl, */ + ac->asn1r_decode_done = SD_TRUE; /* stop decode */ + } + + +/************************************************************************/ +/* _indef_eoc */ +/* Function to check for universal EOC type, and perform level fixup if */ +/* so. The fix consists of determining the number of bytes that were in */ +/* the element and subtracting this number from the previous level byte */ +/* count. */ +/* Returns 0 if NOT EOC, else != 0 */ +/************************************************************************/ + +static ST_BOOLEAN _indef_eoc (ASN1_DEC_CTXT *ac) + { +ST_INT len; + + if (ac->asn1r_constr_elmnt) /* can only be a primitive */ + return (SD_FALSE); + + if (ac->asn1r_elmnt_class != UNI) /* must be universal */ + return (SD_FALSE); + + if (ac->asn1r_elmnt_id != 0) /* EOC is id_code 0 */ + return (SD_FALSE); + +/* This looks like the EOC from a indefinite length constructor */ + if (ac->_asn1_indef_track[ac->asn1r_msg_level] == SD_TRUE) /* if indef len */ + { + ALOG_CDEC1 ("EOC detected for level %d",ac->asn1r_msg_level); + len = ac->asn1r_field_ptr - ac->_asn1_constr_start[ac->asn1r_msg_level]; + if (ac->_asn1_byte_count[ac->asn1r_msg_level - 1] < len) + { + ALOG_NERR0 ("ASN.1 decode: misplaced end of indefinite length constructor"); + asn1r_set_dec_err(ac, ASN1E_CSTR_INVALID_LEN); /* call error function */ + } + ac->_asn1_byte_count[ac->asn1r_msg_level-1] -= len; + ac->_asn1_byte_count[ac->asn1r_msg_level] = 0; /* set this level count = 0 */ + return (SD_TRUE); /* indicate EOC found */ + } + else + { + ALOG_NERR0 ("ASN.1 decode: unexpected end of indefinite length constructor"); + asn1r_set_dec_err(ac, ASN1E_UNEXPECTED_TAG); /* EOC not allowed here */ + } + return (SD_FALSE); + } + + +/************************************************************************/ +/* asn1r_head_decode */ +/* function to decode the ASN.1 data element identified and length */ +/* components and put the result into the component variables. */ +/* The character ptr asn1r_field_ptr points to the data element start, */ +/* and is left pointing to the start of the contents. */ +/************************************************************************/ + +#define _CHECK_ASN1_LEFT(x) {if((ac->asn1r_field_ptr+x) > ac->asn1r_done_ptr)return(ASN1E_END_O_BUFFER);} + +static ST_RET _asn1r_head_decode (ASN1_DEC_CTXT *ac) + { +ST_UCHAR c; +ST_UINT16 ui16; +ST_INT i, i2, i3; + +/* We don't want to read past end of buffer */ + _CHECK_ASN1_LEFT(1); + c = *(ac->asn1r_field_ptr++); /* read the first byte of the element */ + /* pointer points to next byte */ + + ac->asn1r_constr_elmnt = (ST_UCHAR) (c & CONSTR);/* isolate the constr bit */ + ac->asn1r_elmnt_class = (ST_UCHAR) (c & 0xC0); /* get the class bits */ + + if ((c &= 0x1F) == 0x1F) /* if ID extender - */ + { + _CHECK_ASN1_LEFT(1); + if ((c = *(ac->asn1r_field_ptr++)) & 0x80) /* if next byte is not last - */ + { + _CHECK_ASN1_LEFT(1); + if (*ac->asn1r_field_ptr & 0x80) /* if more than two extention */ + { /* ID octets, reject */ + ALOG_NERR0 ("ASN.1 decode: element id too long"); + return (ASN1E_ID_TOO_BIG); + } + ui16 = (ST_UINT16) (c & 0x7F) << 7; /* support 2 extention bytes */ + + _CHECK_ASN1_LEFT(1); + ui16 |= (*(ac->asn1r_field_ptr++) & 0x7F);/* merge the 14 ID bits (only*/ + ac->asn1r_elmnt_id = ui16; /* 13 usable in this impl'n).*/ + } + else /* one octet extended */ + ac->asn1r_elmnt_id = (ST_UINT16) c; /* write masked ID code */ + } + else /* not extended ID code */ + ac->asn1r_elmnt_id = (ST_UINT16) c; /* write masked ID code */ + +/* asn1_field_ptr points to contents length field start. */ +/* Support all length forms : short, long, and indefinite. */ + + _CHECK_ASN1_LEFT(1); + if ((c = *(ac->asn1r_field_ptr++)) & 0x80) /* check for long,indef forms */ + { + if (c &= 0x7F) /* if long form */ + { + _CHECK_ASN1_LEFT((int) c); + switch (c) /* switch on # bytes in length */ + { + case 1 : /* one byte length */ + ac->asn1r_elmnt_len = *(ac->asn1r_field_ptr++) & 0xFF; + break; + + case 2 : /* two byte length */ + i = (ST_INT) ((ST_UINT) *(ac->asn1r_field_ptr++) << 8); + ac->asn1r_elmnt_len = (ST_INT) + (((ST_UINT) *(ac->asn1r_field_ptr++) & 0xFF) | i); + break; + + case 3 : /* three byte length */ + i = (ST_INT) ((ST_UINT) *(ac->asn1r_field_ptr++) << 16); +#if (INT_MAX <= 0x7FFF) + if (i != 0) + { + ALOG_NERR0 ("ASN.1 decode: element length too long"); + return(ASN1E_INVALID_LENGTH); /* other lengths not supported */ + } +#endif + i2 = (ST_INT) (((ST_UINT) *(ac->asn1r_field_ptr++) << 8) | i); + + ac->asn1r_elmnt_len = (ST_INT) + (((ST_UINT) *(ac->asn1r_field_ptr++) & 0xFF) | i2); + break; + + case 4 : /* four byte length */ + i = (ST_INT) ((ST_UINT) *(ac->asn1r_field_ptr++) << 24); + i2 = (ST_INT) (((ST_UINT) *(ac->asn1r_field_ptr++) << 16) | i); +#if (INT_MAX <= 0x7FFF) + if (i != 0 || i2 != 0) + { + ALOG_NERR0 ("ASN.1 decode: element length too long"); + return (ASN1E_INVALID_LENGTH); /* other lengths not supported */ + } +#endif + i3 = (ST_INT) (((ST_UINT) *(ac->asn1r_field_ptr++) << 8) | i2); + ac->asn1r_elmnt_len = (ST_INT) + (((ST_UINT) *(ac->asn1r_field_ptr++) & 0xFF) | i3); + break; + + default : + ALOG_NERR0 ("ASN.1 decode: length length > 4"); + return (ASN1E_INVALID_LENGTH); /* others not supported */ + break; + } + } + else /* indefinite length */ + { + if (ac->asn1r_constr_elmnt) /* valid only for constructors */ + ac->asn1r_indef_flag = SD_TRUE; /* set 'indefinite len' flag */ + else + { + ALOG_NERR0 ("ASN.1 decode: indefinite length primitive"); + return (ASN1E_INVALID_LENGTH); /* Bad PDU structure */ + } + } + } + else /* short form length */ + ac->asn1r_elmnt_len = (ST_INT) c; /* write length */ + + /* If NOT indefinite length, make sure length is legal. */ + if (!ac->asn1r_indef_flag) + { + if ((ac->asn1r_elmnt_len < 0) || ((ac->asn1r_field_ptr+ac->asn1r_elmnt_len) > ac->asn1r_done_ptr)) + { + ALOG_NERR2 ("ASN.1 decode element length error: ASN.1 length=%d, remaining ASN.1 buffer %d ", + ac->asn1r_elmnt_len, ac->asn1r_done_ptr - ac->asn1r_field_ptr); + return (ASN1E_INVALID_LENGTH); + } + } + + return (SD_SUCCESS); + } /* data element decode complete */ + +/************************************************************************/ +/* _call_user */ +/* Function to call the user function for the particular ID class. */ +/* Passes the id code for the data element to the selected function */ +/* For Universal class, also checks for EOC. */ +/* */ +/* The user functions are responsible for ensuring that the asn1_field_ptr */ +/* is left pointing to the start of the next field. */ +/************************************************************************/ + +static ST_VOID _call_user (ASN1_DEC_CTXT *ac) + { +ST_UINT16 curtag; +ST_INT i; +ST_INT num_tags; +ASN1R_TAG_CTRL_1 *tag_ctrl; +ASN1R_TAG_PAIR *tags; + +/* When parsing is being done on the basis of tag, compare the current */ +/* tag with the list of allowable tags and call the corresponding fcn */ +/* pointer. Error checking was done previously when tag_add was called. */ + + if (ac->asn1r_decode_method == ASN1_TABLE_METHOD) + { + curtag = (ST_UINT16) (ac->asn1r_elmnt_class | ac->asn1r_constr_elmnt) << 8; + curtag |= ac->asn1r_elmnt_id; + + tag_ctrl = (ASN1R_TAG_CTRL_1 *) ac->asn1r_tag_table; + tags = tag_ctrl->tags; + num_tags = tag_ctrl->num_tags; + for (i = 0; i < num_tags; ++i, ++tags) + { + if (curtag == tags->_asn1r_tag) + { + (*tags->_asn1r_tag_fun)(ac); /* Call user-defined function. */ + return; + } + } + ALOG_NERR1 ("ASN.1 decode: unexpected tag 0x%X", (ST_UINT) curtag); + asn1r_set_dec_err(ac, ASN1E_UNEXPECTED_TAG); + return; + } + + if (ac->asn1r_decode_method == ASN1_TAG_METHOD) + { + curtag = (ST_UINT16) (ac->asn1r_elmnt_class | ac->asn1r_constr_elmnt) << 8; + curtag |= ac->asn1r_elmnt_id; + for (i = 0; i < ac->_asn1r_ntag; i++) + { + if (curtag == ac->_asn1r_valid_tags[i]) + { + ac->_asn1r_old_ntag = ac->_asn1r_ntag; /* Tags are deleted once used, */ + ac->_asn1r_ntag = 0; /* but are recoverable. */ + (*ac->_asn1r_tag_fun[i])(ac); /* Call user-defined function. */ + return; + } + } + ALOG_NERR1 ("ASN.1 decode: unexpected tag 0x%X", (ST_UINT) curtag); + asn1r_set_dec_err(ac, ASN1E_UNEXPECTED_TAG); + return; + } + + if (ac->asn1r_decode_method == ASN1_ANYTAG_METHOD) + { + curtag = (ST_UINT16) (ac->asn1r_elmnt_class | ac->asn1r_constr_elmnt) << 8; + curtag |= ac->asn1r_elmnt_id; + (*ac->asn1r_anytag_fun)(ac, curtag); + return; + } + + ac->_asn1r_ntag = 0; /* class method, no valid tags */ + +/* When parsing is being done on the basis of class, switch on the */ +/* class of the current data element and call the corresponding fcn */ +/* pointer. Do error checking where possible. */ + switch (ac->asn1r_elmnt_class) + { + case CTX : /* class = context specific */ + (*ac->asn1r_c_id_fun)(ac, ac->asn1r_elmnt_id); + break; + + case UNI : /* class = universal */ /* Perform additional checks */ + switch (ac->asn1r_elmnt_id) /* for constr/prim allowed */ + { /* check selected types */ + case INT_CODE : /* integer must be primitive */ + if (ac->asn1r_constr_elmnt) + { + ALOG_NERR0 ("ASN.1 decode: invalid INTEGER element"); + asn1r_set_dec_err (ac, ASN1E_UNEXPECTED_FORM); + } + else + { + (*ac->asn1r_u_id_fun)(ac, ac->asn1r_elmnt_id); + } + break; + + case SEQ_CODE : /* sequence valid in constr */ + if (!ac->asn1r_constr_elmnt) + { + ALOG_NERR0 ("ASN.1 decode: invalid SEQ element"); + asn1r_set_dec_err (ac, ASN1E_UNEXPECTED_FORM); + } + else + { + (*ac->asn1r_u_id_fun)(ac, ac->asn1r_elmnt_id); + } + break; + + case SET_CODE : /* set valid in constructor */ + if (!ac->asn1r_constr_elmnt) + { + ALOG_NERR0 ("ASN.1 decode: invalid SET element"); + asn1r_set_dec_err (ac, ASN1E_UNEXPECTED_FORM); + } + else + { + (*ac->asn1r_u_id_fun)(ac, ac->asn1r_elmnt_id); + } + break; + + case BOOL_CODE : /* boolean must be primitive, */ + if (ac->asn1r_constr_elmnt || ac->asn1r_elmnt_len != 1) /* 1 octet */ + { + ALOG_NERR0 ("ASN.1 decode: invalid BOOL element"); + asn1r_set_dec_err (ac, ASN1E_INVALID_BOOLEAN); + } + else + { + (*ac->asn1r_u_id_fun)(ac, ac->asn1r_elmnt_id); + } + break; + + case NULL_CODE : /* null must be primitive */ + if (ac->asn1r_constr_elmnt || ac->asn1r_elmnt_len) + { + ALOG_NERR0 ("ASN.1 decode: invalid NULL element"); + asn1r_set_dec_err (ac, ASN1E_UNEXPECTED_TAG); + } + else + { + (*ac->asn1r_u_id_fun)(ac, ac->asn1r_elmnt_id); + } + break; + + default : /* all others can be either */ + { + (*ac->asn1r_u_id_fun)(ac, ac->asn1r_elmnt_id); + } + break; + } + break; /* end of universal */ + + case APP : /* class = application wide */ + (*ac->asn1r_a_id_fun)(ac, ac->asn1r_elmnt_id); + break; + + case PRV : /* class = private use */ + (*ac->asn1r_p_id_fun)(ac, ac->asn1r_elmnt_id); + break; + } + } + +/************************************************************************/ +/* asn1r_set_all_cstr_done */ +/************************************************************************/ + +ST_VOID asn1r_set_all_cstr_done (ASN1_DEC_CTXT *ac) + { +ST_INT i; + + for (i = 0; i < ASN1_MAX_LEVEL; ++i) + ac->asn1r_c_done_fun[i] = NULL; + } + +/************************************************************************/ +/* asn1r_tag_add */ +/************************************************************************/ + +ST_VOID asn1r_tag_add (ASN1_DEC_CTXT *ac, ST_UINT16 tag, + ST_VOID (*fcn_ptr)(ASN1_DEC_CTXT *ac)) + { +#ifdef DEBUG_SISCO + if (ac->_asn1r_ntag >= MAX_TAG_FUN) /* Array is MAX_TAG_FUN deep */ + { + ALOG_ERR0 ("ASN.1 Decode Internal Error : Tag Table Buffer Overflow"); + return; + } +#endif + + ac->_asn1r_valid_tags[ac->_asn1r_ntag] = tag; + ac->_asn1r_tag_fun[ac->_asn1r_ntag] = (ST_VOID (*)(ASN1_DEC_CTXT *)) fcn_ptr; + ac->_asn1r_ntag++; + return; + } + +/************************************************************************/ +/* asn1r_tag_restore */ +/* This fun restores the el'ts of the tag[] and _asn1_tag_fun[] arrays. */ +/************************************************************************/ + +ST_VOID asn1r_tag_restore (ASN1_DEC_CTXT *ac) + { + ac->_asn1r_ntag = ac->_asn1r_old_ntag; + } + +/************************************************************************/ +/************************************************************************/ +/* asn1_peek */ +/************************************************************************/ + +ST_RET asn1_peek (ASN1_DEC_CTXT *ac, ST_UCHAR *ptr, ST_INT len) + { +ST_RET rc; + + ac->asn1r_pdu_dec_err = NO_DECODE_ERR; /* reset error flag */ + ac->asn1r_field_ptr = ptr; /* initialize asn1_field_ptr */ + ac->asn1r_done_ptr = ac->asn1r_field_ptr + len; + +/* Validate length to avoid possible problems */ + if (len <= 0) + { + ALOG_NERR0 ("ASN.1 peek: Length zero or negative"); + asn1r_set_dec_err(ac, ASN1E_END_O_BUFFER); + return (SD_FAILURE); + } + + rc = _asn1r_head_decode (ac); /* decodes the data element header */ + if (rc != SD_SUCCESS) + { + ALOG_NERR0 ("ASN.1 decode: header decode error"); + return (rc); + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* ASN.1 message construct tools. */ +/************************************************************************/ +/************************************************************************/ +/* asn1r_strt_asn1_bld */ +/* Function to initialize the ASN.1 build parameters. Should be called */ +/* before starting construction of each message. */ +/************************************************************************/ + +ST_VOID asn1r_strt_asn1_bld (ASN1_ENC_CTXT *ac, ST_UCHAR *bufptr, ST_INT buflen) + { + ALOG_ENC0 ("Starting ASN.1 message construct"); + +/* Initialize variables in the encode context structure. */ + + ac->asn1r_encode_overrun = SD_FALSE; + ac->asn1r_buf_start = bufptr; + + /* Initialize a bunch of variables to the "end" of buffer. */ + ac->asn1r_constr_end[0] = ac->asn1r_field_ptr = ac->asn1r_field_end = + ac->asn1r_buf_end = bufptr + buflen - 1; + + ac->asn1r_msg_level = 0; /* init current level */ +/* Chk this later to verify that "asn1r_strt_asn1_bld" was called. */ + ac->asn1r_magic = ASN1_ENC_MAGIC_NUMBER; + } + +/************************************************************************/ +/* asn1r_strt_constr */ +/* Function to start a constructor build (from back). */ +/* Simply increments the message level (if notmax) sets the start */ +/* pointer for the level at the current position */ +/************************************************************************/ + +ST_VOID asn1r_strt_constr (ASN1_ENC_CTXT *ac) + { + if (++ac->asn1r_msg_level >= ASN1_MAX_LEVEL) /* increment the level */ + { + ALOG_ERR0 ("Error : ASN.1 encode exceeded nesting level"); + --ac->asn1r_msg_level; /* if at top level */ + } + + ALOG_CENC1 ("Starting constructor @ level %d",ac->asn1r_msg_level); + ac->asn1r_constr_end[ac->asn1r_msg_level] = ac->asn1r_field_ptr; /* save msg ptr */ + } + +/************************************************************************/ +/* asn1r_strt_constr_indef */ +/* FOR TEST APPLICATIONS ONLY. */ +/* SISCO applications never encode Indefinite Length constructors (slow)*/ +/* but this function may be needed by test applications to generate */ +/* ASN.1 messages with Indefinite Length constructors. */ +/************************************************************************/ + +ST_VOID asn1r_strt_constr_indef (ASN1_ENC_CTXT *ac) + { + if (++ac->asn1r_msg_level >= ASN1_MAX_LEVEL) /* increment the level */ + { + ALOG_ERR0 ("Error : ASN.1 encode exceeded nesting level"); + --ac->asn1r_msg_level; /* if at top level */ + } + + ALOG_CENC1 ("Starting 'indefinite length' constructor @ level %d",ac->asn1r_msg_level); + *ac->asn1r_field_ptr-- = 0; /* write 2 zeros for 'end of constructor'*/ + *ac->asn1r_field_ptr-- = 0; + ac->asn1r_constr_end[ac->asn1r_msg_level] = ac->asn1r_field_ptr; + /* CRITICAL: set ..field_end so length of last prim can be computed later.*/ + ac->asn1r_field_end = ac->asn1r_field_ptr; + } + +/************************************************************************/ +/* asn1r_fin_constr */ +/* Function to finish a constructor. */ +/* Writes the constructor length, then the identifier as requested. */ +/* */ +/* Pass the required id_code, the tag bits (upper 3 bits), and flag to */ +/* indicate when the indefinite length is required (indef != 0) */ +/************************************************************************/ + +ST_VOID asn1r_fin_constr (ASN1_ENC_CTXT *ac, ST_UINT16 id_code, ST_UINT16 el_tag, ST_BOOLEAN indef) + { +ST_INT len; + + if (ac->asn1r_field_ptr - ASN1_MAX_ELEMENT_OVERHEAD < ac->asn1r_buf_start) + { + /* Do NOT encode anything, but decrement msg_level to avoid nesting */ + /* errors if user continues trying to encode. */ + --ac->asn1r_msg_level; + ac->asn1r_encode_overrun = SD_TRUE; /* May already be SD_TRUE. */ + return; + } + + + if (!indef) /* write the length field (moves ptr) */ + { + len = ac->asn1r_constr_end[ac->asn1r_msg_level] - ac->asn1r_field_ptr; + _wr_asn1_len (ac, len); + } + else /* if not indefinite length - */ + *(ac->asn1r_field_ptr--) = 0x80; + + /* write identifier (moves ptr) */ + _wr_ident (ac, id_code, (ST_UINT16) (el_tag | CONSTR)); + +#ifdef DEBUG_SISCO + ALOG_CENC1 ("Finish level %d constructor",ac->asn1r_msg_level); + if (indef) + { + ALOG_CENC0 ("Indefinite length"); + } + else + { + ALOG_CENC1 ("Length = %d",ac->asn1r_constr_end[ac->asn1r_msg_level] - ac->asn1r_field_ptr); + } + ALOG_ENCH (ac->asn1r_constr_end[ac->asn1r_msg_level] - ac->asn1r_field_ptr, ac->asn1r_field_ptr + 1); +#endif + + if (--ac->asn1r_msg_level < 0) /* if was level 0 already */ + ac->asn1r_msg_level = 0; /* set = 0 */ + + ac->asn1r_field_end = ac->asn1r_field_ptr; /* reset the field end pointer*/ + } + +/************************************************************************/ +/* asn1r_fin_prim */ +/* Function to finish writing a primitive data element. */ +/* Pass the constructor type (set,sequence) and data element type. */ +/************************************************************************/ + +ST_VOID asn1r_fin_prim (ASN1_ENC_CTXT *ac, ST_UINT16 id_code, ST_UINT16 el_tag) + { +ST_INT len; + + if (ac->asn1r_field_ptr - ASN1_MAX_ELEMENT_OVERHEAD < ac->asn1r_buf_start) + { + ac->asn1r_encode_overrun = SD_TRUE; /* May already be SD_TRUE. */ + return; + } + + len = ac->asn1r_field_end - ac->asn1r_field_ptr; + + /* write the length field (moves ptr) */ + _wr_asn1_len (ac, len); + _wr_ident (ac, id_code, el_tag); /* write the identifier (moves ptr) */ + + len = ac->asn1r_field_end - ac->asn1r_field_ptr; + + ALOG_CENC0 ("Finish primitive"); + ALOG_ENCH (len, ac->asn1r_field_ptr + 1); + + ac->asn1r_field_end = ac->asn1r_field_ptr; /* reset the field end pointer*/ + } + +/************************************************************************/ +/* _wr_ident */ +/* Function to write an ASN.1 identifier field. */ +/* Pass the id code (0 to 0x3FFF), and the tag (class and constr bits) */ +/************************************************************************/ + +static ST_VOID _wr_ident (ASN1_ENC_CTXT *ac, ST_UINT16 id_code, ST_UINT16 el_tag) + { + if (id_code < 0x1F) /* if no extension octets required */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(id_code | el_tag); /* one byte identifier */ + else + { + if (id_code < 0x80) /* if just one extension byte - */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR)id_code; /* write id_code */ + else + { /* need two extension bytes */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(id_code & 0x7F); /* write low 7 bits */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(((id_code >> 7) & 0x7F) | 0x80); + } + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(el_tag | 0x1F); /* indicte extnd'r */ + } + } + +/************************************************************************/ +/* _wr_asn1_len */ +/* Function to write an ASN.1 length field */ +/* Lengths from 0 to INT_MAX are supported. */ +/************************************************************************/ + +static ST_VOID _wr_asn1_len (ASN1_ENC_CTXT *ac, ST_INT len) + { + if (len <= 0x7F) /* see if short form will do */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR)len; + else + { /* need long form */ + if (len <= 0xFF) /* if one byte will do */ + { + *(ac->asn1r_field_ptr--) = (ST_UCHAR)len; /* write length */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR) 0x81; /* write # bytes in len */ + } + else if (len <= 0xFFFF) + { + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(len & 0xFF); /* low byte */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR)((len >> 8) & 0xFF); /* high byte */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR) 0x82; /* #len bytes*/ + } + else if (len <= (ST_INT) 0xFFFFFF) + { + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(len & 0xFF); /* low byte */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR)((len >> 8) & 0xFF); /* mid byte */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR)((len >> 16) & 0xFF); /* high byte */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR) 0x83; /* #len bytes*/ + } + else + { + *(ac->asn1r_field_ptr--) = (ST_UCHAR)(len & 0xFF); /* low byte */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR)((len >> 8) & 0xFF); /* mid log byte */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR)((len >> 16) & 0xFF); /* mid high byte */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR)((len >> 24) & 0xFF); /* high byte */ + *(ac->asn1r_field_ptr--) = (ST_UCHAR) 0x84; /* #len bytes*/ + } + } + } + + + +/************************************************************************/ +/* asn1r_set_dec_err */ +/* Function called from anywhere when an error is detected. Sets the */ +/* passed error code = asn1_pdu_dec_err, and sets asn1_decode_done. */ +/************************************************************************/ + +ST_VOID asn1r_set_dec_err (ASN1_DEC_CTXT *ac, ST_RET err_code) + { + ALOG_NERR1 ("ASN.1 decode error : 0x%X", err_code); + ac->asn1r_pdu_dec_err = err_code; /* set the problem type */ + ac->asn1r_decode_done = SD_TRUE; /* quit parse */ + } + +/************************************************************************/ +/* asn1r_done_err */ +/* function to eliminate premature decode complete, allow release of */ +/* allocated resources by invoking the error function. */ +/* Use as a asn1_decode_done_fun. */ +/************************************************************************/ + +ST_VOID asn1r_done_err (ASN1_DEC_CTXT *ac) + { + ALOG_NERR0 ("ASN1 decode: PDU ended before valid"); + asn1r_set_dec_err (ac, ASN1E_END_OF_MESSAGE); /* set the error */ + if (ac->asn1r_err_fun != NULL) + (*ac->asn1r_err_fun)(ac, ASN1E_END_OF_MESSAGE); /* call the error function */ + } + + +/************************************************************************/ +/* asn1r_class_err */ +/* This function is a nominal function to be invoked when a undesired */ +/* class data element is found during the message parse. */ +/* Just set an error code, stop parse. */ +/************************************************************************/ + +ST_VOID asn1r_class_err (ASN1_DEC_CTXT *ac, ST_UINT16 id_code) + { + ALOG_NERR0 ("CLASS ERROR"); + asn1r_set_dec_err (ac, ASN1E_UNEXPECTED_CLASS); /* just set the error flag */ + } + +/************************************************************************/ +/* asn1_cstr_done_err */ +/* Function to prevent premature constructor completion. */ +/************************************************************************/ + +ST_VOID asn1r_cstr_done_err (ASN1_DEC_CTXT *ac) + { + ALOG_NERR0 ("CONSTRUCTOR DONE ERROR"); + asn1r_set_dec_err(ac, ASN1E_END_OF_CSTR); + } + +/************************************************************************/ +/* asn1r_chk_getcstr_done */ +/* General constructor done function to be used with various pieces */ +/* of code to get information from a constructor inside a message. */ +/* To use, the variables _asn1_save_method and _asn1r_fun_save MUST be */ +/* setup and the ASN.1 function pointer cstr_done_fun must point */ +/* to this function. */ +/************************************************************************/ + +ST_VOID asn1r_chk_getcstr_done (ASN1_DEC_CTXT *ac) + { + ac->asn1r_decode_method = ac->asn1r_save_method; /* restore the decode method */ + ac->asn1r_decode_done_fun = ac->_asn1r_fun_save; /* restore the decode done fun*/ + (*ac->_asn1r_cstr_done_save)(ac); /* call the user selected fun */ + } + +/************************************************************************/ +/* asn1_objidcmp */ +/* Function to compare to OBJECT IDENTIFIERs */ +/* RETURN: 0 if same */ +/* 1 if different */ +/************************************************************************/ + +ST_BOOLEAN asn1_objidcmp (MMS_OBJ_ID *obj1, MMS_OBJ_ID *obj2) + { +ST_INT i; + + if (obj1->num_comps != obj2->num_comps) + return (1); + + for (i = 0; i < obj1->num_comps; i++) + { + if (obj1->comps[i] != obj2->comps[i]) + return (SD_TRUE); + } + + return (SD_FALSE); + } + +/************************************************************************/ +/* asn1r_init_glb_vars */ +/************************************************************************/ + +#if defined(NO_GLB_VAR_INIT) + +ST_VOID asn1r_init_glb_vars (ST_VOID) + { + asn1_debug_sel = ASN1_LOG_ERR; +#if defined( __ALPHA ) + asn1_vax_double_type = A_G_FLOAT; +#endif +#if defined( VAXC ) + asn1_vax_double_type = A_D_FLOAT; +#endif + } + +#endif +/************************************************************************/ +#ifdef DEBUG_SISCO +/************************************************************************/ +/************************************************************************/ +/* _list_elmnt */ +/* Function to print the attributes of a data element */ +/************************************************************************/ + +static ST_VOID _list_elmnt (ASN1_DEC_CTXT *ac) + { +ST_CHAR *ctxt; +ST_CHAR *pc; +ST_CHAR len[50]; + + ctxt ="Bogus"; + if ((asn1_debug_sel & ASN1_LOG_DEC) == 0) + return; + + switch (ac->asn1r_elmnt_class) + { + case (0x00) : + ctxt = "Univ"; + break; + case (0x40) : + ctxt = "App "; + break; + case (0x80) : + ctxt = "Ctxt"; + break; + case (0xC0) : + ctxt = "Priv"; + break; + } + + if (ac->asn1r_constr_elmnt) + pc = "Cstr"; + else + pc = "Prim"; + + if (!ac->asn1r_indef_flag) + sprintf (len,"%u", (unsigned int) ac->asn1r_elmnt_len); + else + strcpy (len,"Indef"); + + ALOG_DECLF (); + ALOG_CDEC4 ("Element : %s, %s, ID = %d, Len = %s", + ctxt, pc, (int) ac->asn1r_elmnt_id, len); + } + +/************************************************************************/ +#endif /* end ifdef DEBUG_SISCO */ +/************************************************************************/ + + + /*------------------------------------------------------*/ + /* MMS_BTOD to/from MMS_UTC_TIME conversion functions */ + /*------------------------------------------------------*/ + +/************************************************************************/ +/* asn1_convert_btod_to_utc */ +/* This function converts MMS_BTOD (time relative to 1/1/1984) to the */ +/* MMS_UTC_TIME (time relative to 1/1/1970). */ +/* The qflags field in the MMS_UTC_TIME need to be set by the calling */ +/* function. */ +/* Only the MMS_BTOD6 form of the MMS_BTOD struct can be converted to */ +/* the MMS_UTC_TIME. */ +/* Parameters: */ +/* btod pointer to MMS_BTOD struct that should be converted to */ +/* the MMS_UTC_TIME */ +/* utc pointer to MMS_UTC_TIME struct where the result of the */ +/* conversion will be placed */ +/* Return: */ +/* SD_SUCCESS if function successful */ +/* SD_FAILURE otherwise */ +/************************************************************************/ +ST_RET asn1_convert_btod_to_utc (MMS_BTOD *btod, MMS_UTC_TIME *utc) + { +time_t tJan84 = TIME_T_1984_JAN_1; + + if (btod->form != MMS_BTOD6) + { + ALOG_NERR0 ("convert_btod_to_utc: MMS_BTOD4 can't be converted to UTC time"); + return (SD_FAILURE); + } + + /* Now compute the MMS_UTC_TIME */ + utc->secs = (ST_UINT32) (tJan84 + + (time_t) (btod->day * SECONDS_PER_DAY) + (time_t) (btod->ms / 1000)); + /* num of seconds since Jan 1, 1970 */ + /* NOTE: use 0x01000000 (2**24) in fraction computations. */ + utc->fraction = (ST_UINT32) ((ST_DOUBLE)(btod->ms % 1000) / 1000.0 * (ST_DOUBLE)0x01000000); + /* fraction of a second on 24-bits */ + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* asn1_convert_utc_to_btod */ +/* This function converts MMS_UTC_TIME (time relative to 1/1/1970) to */ +/* the MMS_BTOD (time relative to 1/1/1984). */ +/* The form field in the MMS_BTOD is set to MMS_BTOD6 by this function. */ +/* Parameters: */ +/* utc pointer to MMS_UTC_TIME struct that should be converted */ +/* to the MMS_BTOD */ +/* btod pointer to MMS_BTOD struct where the result of the */ +/* conversion will be placed */ +/* Return: */ +/* SD_SUCCESS if function successful */ +/* SD_FAILURE otherwise */ +/************************************************************************/ +ST_RET asn1_convert_utc_to_btod (MMS_UTC_TIME *utc, MMS_BTOD *btod) + { +time_t tJan84 = TIME_T_1984_JAN_1; + + /* Now compute the MMS_BTOD time */ + btod->day = (ST_INT32) (utc->secs - tJan84) / SECONDS_PER_DAY; /* num of days since 1/1/1984 */ + btod->ms = (ST_INT32) ((utc->secs - tJan84) % SECONDS_PER_DAY) * 1000; /* num milliseconds since midnight */ + /* NOTE: use 0x01000000 (2**24) in fraction computations. */ + btod->ms += (ST_INT32) ((ST_DOUBLE) utc->fraction * 1000.0/(ST_DOUBLE)0x01000000); + /* add the milliseconds left in a sec */ + btod->form = MMS_BTOD6; + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* asn1_convert_timet_to_btime6 */ +/* Convert time_t value to MMS_BTIME6. */ +/* Input "time_t" value is always based on UTC (GMT). It is compared */ +/* to the define TIME_T_1984_JAN_1 which is also based on UTC (GMT). */ +/* The difference is used to compute the number of seconds elapsed */ +/* since 1984. Then seconds is converted to days & milliseconds. */ +/************************************************************************/ +ST_RET asn1_convert_timet_to_btime6 (time_t tThis, MMS_BTIME6 *btime6) + { +time_t tJan84 = TIME_T_1984_JAN_1; +long elapsed; /* elapsed time since 1984-Jan-1 (in seconds) */ +ldiv_t divResult; +ST_RET retcode; + + /* Find the number of seconds since "1984-Jan-1" and convert to days & msec.*/ + /* NOTE: difftime returns "double" (don't know why), but ldiv needs "long".*/ + elapsed = (long) difftime (tThis, tJan84); + + if (elapsed < 0) + { /* "negative" elapsed time NOT ALLOWED */ + btime6->day = 0; /* days since 1984-Jan-1 */ + btime6->ms = 0; /* milliseconds this day */ + retcode = SD_FAILURE; + } + else + { + divResult = ldiv (elapsed, SECONDS_PER_DAY); + + btime6->day = divResult.quot; /* days since 1984 */ + btime6->ms = (divResult.rem * 1000); /* milliseconds this day */ + retcode = SD_SUCCESS; + } + + return (retcode); + } + +/************************************************************************/ +/* bstrcpy */ +/************************************************************************/ +ST_VOID bstrcpy (ST_UCHAR *dstptr, ST_UCHAR *srcptr, ST_INT numbits) + { +ST_INT num_bytes = numbits/8; /* Number of complete bytes */ +ST_INT extra_bits = numbits%8; /* Number of extra bits */ +ST_UCHAR src_mask; +ST_UCHAR dst_mask; + + if (num_bytes) + memcpy (dstptr, srcptr, num_bytes); + + if (extra_bits) + { + src_mask = 0xFF << (8-extra_bits); /* Use high bits from src */ + dst_mask = 0xFF >> extra_bits; /* Use low bits from dst */ + + dstptr[num_bytes] &= dst_mask; + dstptr[num_bytes] |= (srcptr[num_bytes] & src_mask); + } + } + +/************************************************************************/ +/* bvstrcpy */ +/* Copy one "variable length bitstring" to another. */ +/************************************************************************/ +ST_VOID bvstrcpy (MMS_BVSTRING *dstptr, MMS_BVSTRING *srcptr) + { + dstptr->len = srcptr->len; + bstrcpy (dstptr->data, srcptr->data, srcptr->len); + } + +/************************************************************************/ +/* bstrcmp */ +/* Compare bitstrings. */ +/* RETURNS: 0 if bitstrings identical, 1 if different. */ +/************************************************************************/ +ST_INT bstrcmp (ST_UCHAR *dstptr, ST_UCHAR *srcptr, ST_INT numbits) + { +ST_INT num_bytes = numbits/8; /* Number of complete bytes */ +ST_INT extra_bits = numbits%8; /* Number of extra bits */ +ST_UCHAR mask; + + if (num_bytes) + { + if (memcmp (dstptr, srcptr, num_bytes)) + return (1); /* different */ + } + + if (extra_bits) + { + /* Mask off extra (low order) bits in last byte. */ + mask = 0xFF << (8-extra_bits); /* Use high order bits */ + if ((dstptr[num_bytes] & mask) != (srcptr[num_bytes] & mask)) + return (1); /* different */ + } + return (0); /* same */ + } + +/************************************************************************/ +/* asn1r_skip_elmnt */ +/* Skip over current ASN.1 element without decoding. */ +/* Does not work for indefinite length encoding (returns SD_FAILURE). */ +/* DEBUG: If indefinite len support needed, try using asn1r_parse_next. */ +/************************************************************************/ +ST_RET asn1r_skip_elmnt (ASN1_DEC_CTXT *aCtx) + { +ST_RET retcode = SD_SUCCESS; + + if (aCtx->asn1r_constr_elmnt) + { + if (aCtx->asn1r_indef_flag) + { + ALOG_ERR0 ("asn1r_skip_elmnt: indefinite length encoding not supported"); + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); + retcode = SD_FAILURE; + } + else + { + aCtx->asn1r_constr_elmnt = 0; /* Make ASN.1 treat it like primitive. */ + --aCtx->asn1r_msg_level; /* Already incremented for constructor */ + /* so decrement to act like primitive. */ + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; + } + } + else + { /* primitive: just update field_ptr */ + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; + } + return (retcode); + } + +/*======================================================================*/ +/*======================================================================*/ +/* The following functions are for a new decode method that does */ +/* NOT use any function pointers: */ +/* asn1r_decode_init */ +/* asn1r_byte_count_decrement (static) */ +/* asn1r_get_tag */ +/*======================================================================*/ +/*======================================================================*/ + +/************************************************************************/ +/* asn1r_decode_init */ +/* Initialize the ASN.1 decode context. */ +/* IMPORTANT: Use ONLY with "asn1r_get_tag". */ +/* NOTE: This function does NOT use any of the function pointers in */ +/* ASN1_DEC_CTXT (_asn1r_tag_fun, asn1r_c_done_fun, etc.). */ +/* Also, several other parameters in ASN1_DEC_CTXT are NOT used. */ +/* NOTE: To avoid a slow "memset" call, this function only sets the */ +/* necessary parameters in ASN1_DEC_CTXT (other parameters contain */ +/* random data). */ +/************************************************************************/ +ST_RET asn1r_decode_init (ASN1_DEC_CTXT *ac, + ST_UCHAR *ptr, /* ASN.1 message to decode */ + ST_INT len) /* length of ASN.1 message */ + { + /* Validate length to avoid possible problems */ + if (len <= 0) + { + ALOG_NERR0 ("ASN.1 decode: Length zero or negative"); + return (ASN1E_END_O_BUFFER); + } + +/* initialize flags, counters, pointers for decode */ + + ac->asn1r_indef_flag = SD_FALSE; /* clear flag */ + ac->_asn1_indef_track[0] = SD_FALSE; /* level 0 is always definite */ + ac->_asn1_byte_count[0] = len; /* set # bytes left in level 0 */ + ac->asn1r_msg_level = 0; /* start at message level 0 */ + + ac->asn1r_field_ptr = ptr; + ac->asn1r_done_ptr = ptr + len; + ac->asn1r_msg_start = ptr; /* save start ptr to compute */ + /* offset for logging. */ + + ALOG_DEC1 ("ASN.1 MESSAGE TO DECODE : len = %d",len); + ALOG_DECH (len,ptr); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* asn1r_byte_count_decrement */ +/* If this is a "definite length" constructor, decrement its byte count.*/ +/* NOTE: For "indefinite length" constructor, DO NOTHING. */ +/************************************************************************/ +static ST_RET asn1r_byte_count_decrement (ASN1_DEC_CTXT *ac, + ST_INT msg_level, /* constructor nesting level */ + ST_INT byte_count) /* number of bytes processed */ + { + if ( ! ac->_asn1_indef_track[msg_level]) + { + /* This is "definite length" constructor. Decrement its byte count. */ + if (ac->_asn1_byte_count[msg_level] < byte_count) + { + if (msg_level == 0) + ALOG_ERR0 ("ASN.1 decode: data exceeds message size"); + else + ALOG_ERR1 ("ASN.1 decode: data exceeds constructor length at message level %d", msg_level); + return (ASN1E_CSTR_INVALID_LEN); + } + ac->_asn1_byte_count[msg_level] -= byte_count; + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/* asn1r_get_tag */ +/* Decode the next ASN.1 tag. */ +/* IMPORTANT: Use ONLY with "asn1r_decode_init". */ +/* Must call 'asn1r_decode_init' once before any calls to this function.*/ +/* NOTE: This function does NOT use any of the function pointers in */ +/* ASN1_DEC_CTXT (_asn1r_tag_fun, asn1r_c_done_fun, etc.). */ +/* Also does NOT use several other parameters in ASN1_DEC_CTXT. */ +/************************************************************************/ +ST_RET asn1r_get_tag (ASN1_DEC_CTXT *ac, + ST_UINT16 *tag_out) /* out: decoded tag */ + { +ST_INT head_len; /* num bytes processed by asn1r_head_decode */ +ST_RET rc; + + /* Before decoding the next tag, if current constructor is */ + /* "definite length", check if it is finished. */ + /* NOTE: end of "indefinite length" constructor is a real tag, so */ + /* it is processed AFTER the tag is decoded. */ + if ( ac->asn1r_msg_level > 0 + && ac->_asn1_indef_track[ac->asn1r_msg_level] == SD_FALSE /* definite length*/ + && ac->_asn1_byte_count[ac->asn1r_msg_level] == 0) /* constr done */ + { + /* 0 bytes left at this constructor level (i.e. this constr done). */ + ALOG_CDEC1 ("Level %d parse complete",ac->asn1r_msg_level); + ac->asn1r_msg_level--; + *tag_out = 0; /* 0 always indicates constructor done */ + return (SD_SUCCESS); + } + + if (ac->asn1r_field_ptr >= ac->asn1r_done_ptr) + { + ALOG_ERR0 ("ASN.1 decode: past end of buffer"); + return (ASN1E_END_O_BUFFER); + } + + ALOG_DEC1 ("Current decode offset: 0x%X", + ac->asn1r_field_ptr - ac->asn1r_msg_start); + ac->asn1r_field_start = ac->asn1r_field_ptr; /* save field start address*/ + + /* Clear old asn1r_indef_flag. May be set again by _asn1r_head_decode.*/ + ac->asn1r_indef_flag = SD_FALSE; /* clear flag */ + + /* Decode the ASN.1 element header. */ + rc = _asn1r_head_decode (ac); + if (rc != SD_SUCCESS) + { + ALOG_NERR0 ("ASN.1 decode: header decode error"); + return(rc); + } + + /* Log this element (if enabled). */ +#ifdef DEBUG_SISCO + if (asn1_debug_sel & ASN1_LOG_DEC) + { + ST_INT log_len; + log_len = ac->asn1r_field_ptr - ac->asn1r_field_start; + /* For primitive, log the whole element */ + if (!ac->asn1r_constr_elmnt) + log_len += ac->asn1r_elmnt_len; + + ALOG_DECH (log_len, ac->asn1r_field_start); /* log bytes just processed*/ + + _list_elmnt (ac); /* log element attributes */ + } +#endif + + /* Generate tag to return to caller (*tag_out). */ + /* Our storage of tags in ST_UINT16 can only handle elmnt_id of */ + /* 13 bits (high 3 bits indicate Class and Constructor). */ + /* This should be good enough for anything we need to parse. */ + if (ac->asn1r_elmnt_id > 0x1fff) + { + ALOG_ERR1 ("ASN.1 element id = %u unsupported", ac->asn1r_elmnt_id); + return (SD_FAILURE); /* should NEVER get here */ + } + *tag_out = ((ST_UINT16) (ac->asn1r_elmnt_class | ac->asn1r_constr_elmnt) << 8) + | ac->asn1r_elmnt_id; + + /* Check for Indefinite Length End of Constructor (EOC)(i.e. tag==0) */ + if (*tag_out == 0) + { + /* EOC found. Was constr at this level "indefinite length"? */ + if (ac->_asn1_indef_track[ac->asn1r_msg_level]) + { + ST_INT indef_len; /* Length of this indefinite length constructor */ + ALOG_CDEC1 ("EOC detected for level %d",ac->asn1r_msg_level); + indef_len = ac->asn1r_field_ptr - ac->_asn1_constr_start[ac->asn1r_msg_level]; + + /* Decrement the byte count of the "higher level" constr. */ + rc = asn1r_byte_count_decrement (ac, ac->asn1r_msg_level - 1, indef_len); + if (rc) + return (rc); + + ALOG_CDEC1 ("Level %d parse complete",ac->asn1r_msg_level); + ac->asn1r_msg_level--; + } + else + { + ALOG_NERR0 ("ASN.1 decode: unexpected end of indefinite length constructor"); + return (ASN1E_UNEXPECTED_TAG); /* EOC not allowed here */ + } + /* ALWAYS return when EOC found. */ + /* NOTE: "*tag_out" already set to 0 to indicate constructor done. */ + return (SD_SUCCESS); + } /* end "if (*tag_out == 0)" */ + + /* Compute number of bytes processed by asn1r_head_decode. */ + /* Need this to decrement constructor byte counts below. */ + head_len = ac->asn1r_field_ptr - ac->asn1r_field_start; + + if (ac->asn1r_constr_elmnt) + { + /* Process constructor. */ + if (++ac->asn1r_msg_level >= ASN1_MAX_LEVEL) + { + ALOG_ERR0 ("Error : ASN.1 decode exceeded nesting level"); + return (ASN1E_NEST_TOO_DEEP); + } + + /* Save "indefinite length" flag for this constructor level. */ + ac->_asn1_indef_track[ac->asn1r_msg_level] = ac->asn1r_indef_flag; + + if (ac->asn1r_indef_flag) + { + /* Save start ptr for this constructor. Use to compute len later. */ + ac->_asn1_constr_start[ac->asn1r_msg_level] = ac->asn1r_field_ptr; + /* _asn1_byte_count NOT USED for indef len constructor. Set to 0, */ + /* just so it's easier to see in the debugger. */ + ac->_asn1_byte_count[ac->asn1r_msg_level] = 0; /* NOT USED for indef*/ + + /* Decrement the byte count of the "higher level" constr. */ + /* Use "head_len". Adjust for "data len" later when EOC is found. */ + rc = asn1r_byte_count_decrement (ac, ac->asn1r_msg_level - 1, head_len); + if (rc) + return (rc); + } + else + { + /* definite length constructor. Initialize byte count for it. */ + ac->_asn1_byte_count[ac->asn1r_msg_level] = ac->asn1r_elmnt_len; + /* Decrement the byte count of the "higher level" constr. */ + rc = asn1r_byte_count_decrement (ac, ac->asn1r_msg_level - 1, + head_len+ac->asn1r_elmnt_len); + if (rc) + return (rc); + } + } /* end constructor processing */ + else + { + /* This is a primitive. */ + /* Decrement the byte count of the "current" constr. */ + rc = asn1r_byte_count_decrement (ac, ac->asn1r_msg_level, + head_len+ac->asn1r_elmnt_len); + if (rc) + return (rc); + } + + return (SD_SUCCESS); + } + diff --git a/mmslib/build-ubuntu.sh b/mmslib/build-ubuntu.sh new file mode 100644 index 0000000..7accf0a --- /dev/null +++ b/mmslib/build-ubuntu.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +DEBUG='-f Makefile.Debug' +RELEASE='-f Makefile.Release' + +make_function() +{ + qmake mmslib.pro + make $1 distclean + qmake mmslib.pro + make $1 clean + make $1 -j 2 + make $1 install +} + +echo Usage: "build-xxx.sh release/debug/all/clean/\"\" " +echo " release|\"\" : Make version release " +echo " debug : Make version debug " +echo " all : Make version debug and release" +echo " clean : Make clean " + +if [ "$1" = "" ]; then + make_function "$RELEASE" +fi +if [ "$1" = "release" ]; then + make_function "$RELEASE" +fi +if [ "$1" = "debug" ]; then + make_function "$DEBUG" +fi +if [ "$1" = "all" ]; then + make_function "$RELEASE" + make_function "$DEBUG" +fi +if [ "$1" = "clean" ]; then + qmake + make distclean +fi + diff --git a/mmslib/fe_common.pri b/mmslib/fe_common.pri new file mode 100644 index 0000000..bef10bc --- /dev/null +++ b/mmslib/fe_common.pri @@ -0,0 +1,47 @@ +###################################################################### +# common config for project +###################################################################### + +DEPENDPATH += . + +CONFIG += debug_and_release +CONFIG += warn_off +CONFIG -= warn_on + +CONFIG(debug, debug|release) { + TARGET = $$join(TARGET,,,d) + QMAKE_CXXFLAGS_DEBUG += -DDEBUG +} + +unix { + QMAKE_CXXFLAGS_WARN_ON = -Wall + QMAKE_CXXFLAGS_WARN_OFF = -w + LIBS += -lrt -ldl + OS_VERSION = $$system(uname -a) + contains(OS_VERSION, SunOS) { + #QMAKE_CXXFLAGS +=-D_POSIX_PTHREAD_SEMANTICS + LIBS += -lsocket -lnsl + } + contains(QMAKE_CXXFLAGS, -m64) { + DEFINES +=FE_VERSION_64 + } +} + +win32 { + DEFINES -= UNICODE + QMAKE_INCDIR = $(QTDIR)/include + QMAKE_INCDIR_QT = $(QTDIR)/include + QMAKE_LIBDIR_QT = $(QTDIR)/lib + QMAKE_LFLAGS_RELEASE = /INCREMENTAL:no + QMAKE_LFLAGS_DEBUG += /INCREMENTAL:no + QMAKE_LFLAGS += /MACHINE:X86 + QMAKE_MOC = $$(QTDIR)/bin/moc.exe + QMAKE_RCC = $$(QTDIR)/bin/rcc.exe + QMAKE_UIC = $$(QTDIR)/bin/uic.exe + QMAKE_IDC = $$(QTDIR)/bin/idc.exe + CONFIG -= warn_on + INCLUDEPATH +=$(QTDIR)/mkspecs/win32-msvc2010 + QMAKE_CXXFLAGS +=-DWIN32_LEAN_AND_MEAN + #for remove ACE warning + DEFINES += _CRT_SECURE_NO_DEPRECATE _M_IX86 WIN32 +} diff --git a/mmslib/inc/ExceptionReport.h b/mmslib/inc/ExceptionReport.h new file mode 100644 index 0000000..996f8d4 --- /dev/null +++ b/mmslib/inc/ExceptionReport.h @@ -0,0 +1,135 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003-2204, All Rights Reserved */ +/* */ +/* MODULE NAME : ExceptionReport.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : Unhandled Exception Handler */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/13/06 DSF 03 Migrate to VS.NET 2005 */ +/* 06/30/05 DSF 02 Generate a mini dump */ +/* 12/20/04 DSF 01 Minor usability changes */ +/* Stack State recorder */ +/************************************************************************/ + +#pragma once + +#include "glbtypes.h" +#include "sysincs.h" +#include "slog.h" +#include "mem_chk.h" +#include +#include +#include +#include +#include +#include +using namespace std; + +enum BasicType // Stolen from CVCONST.H in the DIA 2.0 SDK +{ + btNoType = 0, + btVoid = 1, + btChar = 2, + btWChar = 3, + btInt = 6, + btUInt = 7, + btFloat = 8, + btBCD = 9, + btBool = 10, + btLong = 13, + btULong = 14, + btCurrency = 25, + btDate = 26, + btVariant = 27, + btComplex = 28, + btBit = 29, + btBSTR = 30, + btHresult = 31 +}; + +class WheatyExceptionReport +{ + public: + + WheatyExceptionReport( ); + WheatyExceptionReport( bool terminate ); + ~WheatyExceptionReport( ); + + void SetLogFileName( PTSTR pszLogFileName ); + + + // entry point where control comes on an unhandled exception + static LONG WINAPI WheatyUnhandledExceptionFilter( + PEXCEPTION_POINTERS pExceptionInfo ); + + static BOOL GetLogicalAddress( PVOID addr, PTSTR szModule, DWORD len, + DWORD& section, DWORD& offset ); + + private: + + // where report info is extracted and generated + static void GenerateExceptionReport( PEXCEPTION_POINTERS pExceptionInfo ); + + // where mini dump is generated + static void GenerateDumpFile( PEXCEPTION_POINTERS pExceptionInfo ); + + // Helper functions + static LPTSTR GetExceptionString( DWORD dwCode ); + static void WriteStackDetails( PCONTEXT pContext, bool bWriteVariables ); + + static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO,ULONG, PVOID); + + static bool FormatSymbolValue( PSYMBOL_INFO, STACKFRAME *, char * pszBuffer, unsigned cbBuffer ); + + static char * DumpTypeIndex( char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool & ); + + static char * FormatOutputValue( char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress ); + + static BasicType GetBasicType( DWORD typeIndex, DWORD64 modBase ); + + static int __cdecl _tprintf(const TCHAR * format, ...); + + // Variables used by the class + static TCHAR m_szLogFileName[MAX_PATH]; + static TCHAR m_szDumpFileName[MAX_PATH]; + static LOG_CTRL m_logCtrl; + static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter; + static HANDLE m_hReportFile; + static HANDLE m_hProcess; + static bool m_bTerminate; +}; + + +extern WheatyExceptionReport g_WheatyExceptionReport; // global instance of class + +struct SourceInfo + { + string filename; + long linenum; + }; + +struct StackInfo + { + DWORD threadID; + SYSTEMTIME timestamp; + vector stack; + + void Log (); + }; + +void GetStackInfo (StackInfo& stackInfo); + +extern "C" void ExpInit (); +extern "C" void ExpRaiseDebugException (); +extern "C" void ExpSetLogCtrl (LOG_CTRL *pLogCtrl); + + diff --git a/mmslib/inc/Goose.h b/mmslib/inc/Goose.h new file mode 100644 index 0000000..88af00b --- /dev/null +++ b/mmslib/inc/Goose.h @@ -0,0 +1,223 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999-2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : goose.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/23/08 JRB 10 Fix len of gcRef, dataSetRef, appID. */ +/* 09/11/07 JRB 09 Add gse_iec_enc_part1, gse_iec_enc_part2. */ +/* Chg gcRef, dataSetRef, appID data type from */ +/* char ptr to char array (reduces allocation). */ +/* Fix type of numDataEntries, confRev. */ +/* 01/08/03 JRB 08 Del obsolete dataRef, elementId from structs */ +/* & from gse_iec_data_init args. */ +/* 12/03/02 ASK 07 Chg Goose structs for new ASN.1 encoding. Chg*/ +/* gse_iec_encode and gse_iec_hdr_decode protos */ +/* for Ethertype. include "ethertyp.h" */ +/* 09/30/02 NAV 06 Add ifdef __cplusplus */ +/* 02/26/02 JRB 05 Chg IEC GOOSE asn1Data args to UCHAR. */ +/* Chg some IEC GOOSE decode params to INT32. */ +/* 01/02/02 JRB 04 Add IEC GOOSE definitions. */ +/* 07/25/00 RKR 03 changed VisibleString SendingIED to ST_CHAR */ +/* 09/10/99 JRB 02 Chg SqNum, StNum, HoldTim, & BackTim */ +/* to UINT32 to match GOMSFE 0.9. */ +/* 06/25/99 MDE 01 Created */ +/************************************************************************/ +#ifndef GOOSE_HDR_INCLUDED +#define GOOSE_HDR_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "asn1r.h" /* need MMS_UTC_TIME */ +#include "clnp_usr.h" +#include "clnp_sne.h" +#include "acse2usr.h" +#include "ethertyp.h" +#include "mvl_defs.h" /* need MVL61850_MAX_* defines. */ +/* NOTE: need runtime_type from "mms_vvar.h" but requires bunch of */ +/* other includes, so just use forward declaration. */ +struct runtime_type; /* forward declaration */ + +/************************************************************************/ + + +#define GOOSE_NAME_MISMATCH 0x112 +#define GOOSE_DONE_TOO_SOON 0x113 + +/************************************************************************/ +#define GOOSE_MAX_NUM_DNA_BITS 128 +#define GOOSE_MAX_NUM_USR_BITS 512 + +#define GOOSE_DEF_NUM_DNA_BITS 64 +#define GOOSE_DEF_NUM_USR_BITS 128 + +typedef struct + { +/* GOOSE Stack addressing information */ + AUDT_APDU audtApdu; + +/* GOOSE MMS values */ + ST_CHAR SendingIED[66]; + MMS_BTOD t; + ST_UINT32 SqNum; + ST_UINT32 StNum; + ST_UINT32 HoldTim; + ST_UINT32 BackTim; + ST_UINT16 PhsID; + + ST_INT num_dna_bits; + ST_UCHAR DNA[GOOSE_MAX_NUM_DNA_BITS/8]; + + ST_INT num_usr_bits; + ST_UCHAR UserSt[GOOSE_MAX_NUM_USR_BITS/8]; + } GOOSE_INFO; + +/************************************************************************/ +/* The user makes use of these functions to send and receive GOOSE */ +/* messages. */ + +ST_RET mmsl_send_goose (GOOSE_INFO *gi); +ST_VOID u_mmsl_goose_received (GOOSE_INFO *goose_info); + +/************************************************************************/ +/* Internal */ + +#define GOOSE_MAX_PDU_SIZE 200 + +/* Define macro so new function just calls old function. */ +#define gse_uca_write(gi) mmsl_send_goose (gi) + +ST_RET gse_uca_decode (SN_UNITDATA *sn_udt, /* input subnet packet */ + GOOSE_INFO *goose_info); /* output GOOSE data */ + +/************************************************************************/ +/* BEGIN IEC GOOSE DEFINITIONS */ +/************************************************************************/ +typedef struct + { + struct runtime_type *runtimeTypeHead; /* Array of Runtime Types */ + ST_INT numRuntimeTypes; /* # of Runtime Types in array */ + ST_CHAR *dataBuf; /* ptr to local data */ + ST_VOID *userInfo; /* To store anything user wants.*/ + /* GSE code does not use it. */ + } GSE_IEC_DATA_ENTRY; + +typedef struct + { + ST_UINT8 *asn1Ptr; + ST_INT asn1Len; + } GSE_IEC_DATA_ENTRY_RX; + +typedef struct + { + ST_CHAR gcRef [MVL61850_MAX_OBJREF_LEN+1]; /* GoCBRef in IEC 61850 */ + ST_UINT32 timeToLive; + ST_CHAR dataSetRef [MVL61850_MAX_OBJREF_LEN+1];/* DatSet in IEC 61850 */ + ST_BOOLEAN appID_pres; + ST_CHAR appID [MVL61850_MAX_RPTID_LEN+1]; /* GoID in IEC 61850 */ + /* (was AppID in Ed 1) */ + MMS_UTC_TIME utcTime; + ST_UINT32 stNum; + ST_UINT32 sqNum; + ST_BOOLEAN test; + ST_UINT32 confRev; + ST_BOOLEAN needsCommissioning; + ST_INT32 numDataEntries; + GSE_IEC_DATA_ENTRY *dataEntries; /* array of data entry structs */ + }GSE_IEC_CTRL; + +typedef struct + { + ST_CHAR *gcRef; + ST_UINT32 timeToLive; + ST_CHAR *dataSetRef; + ST_BOOLEAN appID_pres; + ST_CHAR *appID; + MMS_UTC_TIME utcTime; + ST_UINT32 stNum; + ST_UINT32 sqNum; + ST_BOOLEAN test; + ST_UINT32 confRev; + ST_BOOLEAN needsCommissioning; + ST_INT32 numDataEntries; + ST_INT tmpIndex; /* index to current entry in "dataEntries" array.*/ + /* Used during decode when filling in "dataEntries".*/ + GSE_IEC_DATA_ENTRY_RX *dataEntries; /* array of data entry structs */ + }GSE_IEC_HDR; + +/* Subnet functions (clnp_snet_*) must be used to set multicast filters.*/ +/* The following "gse_*" macros may be used to access these functions. */ +#define gse_set_multicast_filter clnp_snet_set_multicast_filter +#define gse_discovery_start clnp_snet_rx_all_multicast_start +#define gse_discovery_stop clnp_snet_rx_all_multicast_stop + +GSE_IEC_HDR *gse_iec_hdr_decode (ST_UCHAR *apdu, ST_INT apdu_len); +/* After calling "gse_iec_hdr_decode", user can examine "dataEntries" */ +/* array in GSE_IEC_HDR, and call "ms_asn1_to_local" to decode any or */ +/* all dataEntries. */ + +/* User must call this function when they are done with the decoded */ +/* GOOSE info to free up the resources. */ +ST_RET gse_iec_decode_done (GSE_IEC_HDR *hdr); + + +GSE_IEC_CTRL *gse_iec_control_create (ST_CHAR *gcRef, ST_CHAR *dataSetRefRef, ST_CHAR *appId, + ST_INT numDataEntry); +ST_RET gse_iec_control_destroy (GSE_IEC_CTRL *ctrl); + +ST_RET gse_iec_data_init (GSE_IEC_CTRL *ctrl, + ST_INT index, + struct runtime_type *runtimeTypeHead, + ST_INT numRuntimeTypes + ); + +ST_RET gse_iec_data_update (GSE_IEC_CTRL *ctrl, + ST_INT index, + ST_VOID *dataPtr); + +ST_UCHAR *gse_iec_encode (GSE_IEC_CTRL *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info);/* ptr to Ethertype info*/ + +ST_RET gse_iec_send (GSE_IEC_CTRL *ctrl, + ST_UCHAR *dstMac, /* Destination MAC addr */ + ST_UCHAR *asn1Data, /* ptr to ASN.1 encoded data*/ + ST_INT asn1DataLen); /* len of ASN.1 encoded data*/ + +/* Functions to use for 2-part encode. Reduces re-encoding of data. */ +ST_UCHAR *gse_iec_enc_part1 (GSE_IEC_CTRL *ctrl, + ST_UCHAR *buf_ptr, /* buffer in which to encode */ + ST_INT buf_len, /* buffer len */ + ST_INT *asn1_len_out); /* len of ASN.1 encoded data */ +ST_UCHAR *gse_iec_enc_part2 (GSE_IEC_CTRL *ctrl, + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UCHAR *buf_ptr, /* buffer in which to encode */ + ST_INT buf_len, /* buffer len */ + ST_INT enc_part1_len, /* len of data encoded by */ + /* gse_iec_enc_part1 */ + /* CRITICAL: must be < buf_len. */ + ST_INT *asn1_len_out); /* len of ASN.1 encoded data */ + +/************************************************************************/ +/* END IEC GOOSE DEFINITIONS */ +/************************************************************************/ +#ifdef __cplusplus +} +#endif +#endif /* included */ diff --git a/mmslib/inc/STR_UTIL.H b/mmslib/inc/STR_UTIL.H new file mode 100644 index 0000000..a9609b0 --- /dev/null +++ b/mmslib/inc/STR_UTIL.H @@ -0,0 +1,158 @@ +#ifndef STR_UTIL_INCLUDED +#define STR_UTIL_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2000 - 2004 All Rights Reserved */ +/* */ +/* MODULE NAME : str_util.h */ +/* PRODUCT(S) : General Use */ +/* */ +/* MODULE DESCRIPTION : */ +/* General purpose string manipulation functions. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/29/07 JRB 23 Add strncat_maxstrlen. Del strncat_safe (len */ +/* was wrong), use strncat or strncat_maxstrlen.*/ +/* 10/11/07 JRB 22 Add asciiToSint32, asciiToUint32 */ +/* 07/28/05 DWL 21 Use const ST_CHAR* in asciiTo* functions. */ +/* 03/14/05 JRB 20 Add get_next_string. */ +/* 12/03/04 JRB 19 Use strcasecmp, strncasecmp if supported. */ +/* 07/09/04 JRB 18 Add strncat_safe, strncpy_safe. */ +/* 03/08/04 EJV 17 Added getKeywordFromFile function. */ +/* 12/12/03 JRB 16 Add LYNX support. */ +/* 12/10/03 MDE 15 Added itoa/ltoa/utoa/ultoa replacements */ +/* 04/10/03 DSF 14 Added strnstr */ +/* 02/20/03 JRB 13 Del PSOS code. */ +/* 12/20/02 CRM 12 Added "defined(linux)" for strcmpi, etc. */ +/* 02/28/02 EJV 11 Added asciiToFloat, asciiToDouble. */ +/* 02/25/02 EJV 10 Replaced ascii_to_ macros with asciiToxxx fun*/ +/* Added asciiToUlong, asciiToUint16, */ +/* asciiToUint8, asciiToSint, asciiToUint */ +/* hex_to_ascii_str: added param hex_no_spaces. */ +/* 12/09/01 GLB 05 Added asciiToSlong, asciiToSint16, */ +/* asciiToSint8, asciiToUchar */ +/* 09/10/01 GLB 08 Added ascii_to_uint & ascii_to_slongint */ +/* 08/06/01 GLB 07 Added ascii_to_sint */ +/* 06/06/01 GLB 06 Added ascii_to_double & ascii_to_float */ +/* 05/21/01 MDE 05 Added bitstring_to_ascii_str */ +/* 01/19/01 EJV 04 UNIX: added strcmpi, stricmp, strnicmp protos*/ +/* 01/05/01 EJV 03 Corrected ascii_to_ushortint, AIX returned 0.*/ +/* ascii_to_ulongint: changed "%ul" to "%lu". */ +/* 11/02/00 MDE 02 Added _hex_no_spaces */ +/* 02/03/00 JRB 01 Created */ +/************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +ST_VOID hex_to_ascii_str ( + ST_CHAR *astr, /* ascii string */ + ST_UCHAR *hstr, /* hex string */ + ST_UINT hlen, /* len of hex string */ + ST_BOOLEAN hex_no_spaces); + +ST_RET ascii_to_hex_str ( + ST_UCHAR *hstr, /* hex string */ + ST_UINT *hlen_out, /* ptr to hex len to be set */ + ST_UINT hlen_max, /* maximum hex len to allow. */ + ST_CHAR *astr); /* ascii string */ + +ST_VOID bitstring_to_ascii_str (ST_CHAR *astr, ST_UCHAR *bstr, + ST_UINT numBits); + + +ST_RET asciiToSlong (const ST_CHAR *astr, + ST_LONG *sLong); +ST_RET asciiToUlong (const ST_CHAR *astr, + ST_ULONG *uLong); + +ST_RET asciiToSint (const ST_CHAR *astr, + ST_INT *sInt); +ST_RET asciiToUint (const ST_CHAR *astr, + ST_UINT *uInt); + +ST_RET asciiToSint32 (const ST_CHAR *astr, /* ascii string */ + ST_INT32 *value); /* ptr to converted value*/ +ST_RET asciiToUint32 (const ST_CHAR *astr, /* ascii string */ + ST_UINT32 *value); /* ptr to converted value*/ + +ST_RET asciiToSint16 (const ST_CHAR *astr, + ST_INT16 *sInt16); +ST_RET asciiToUint16 (const ST_CHAR *astr, + ST_UINT16 *uInt16); + +ST_RET asciiToSint8 (const ST_CHAR *astr, + ST_INT8 *sInt8); +ST_RET asciiToUint8 (const ST_CHAR *astr, + ST_UINT8 *uInt8); + +ST_RET asciiToUchar (const ST_CHAR *astr, + ST_UCHAR *uChar); + +ST_RET asciiToFloat (const ST_CHAR *astr, + ST_FLOAT *floatNum); +ST_RET asciiToDouble (const ST_CHAR *astr, + ST_DOUBLE *doubleNum); + + +char *strnstr (char *str1, char *str2, int len); + +/* SISCO code calls strcmpi, stricmp, strnicmp (Windows functions). */ +/* On systems that support strcasecmp, strncasecmp, remap to use them. */ +#if defined(_AIX) || defined(sun) || defined(__alpha) || defined(__hpux) || \ + defined(linux) +#ifndef strcmpi +#define strcmpi strcasecmp +#endif +#ifndef stricmp +#define stricmp strcasecmp +#endif +#ifndef strnicmp +#define strnicmp strncasecmp +#endif +#endif /* UNIX-like systems that support strcasecmp, strncasecmp. */ + +/* On systems that DON'T support strcasecmp, strncasecmp, use SISCO functions. */ +#if defined(VXWORKS) || defined(__LYNX) +ST_INT strcmpi (ST_CHAR *,ST_CHAR *); +ST_INT stricmp (ST_CHAR *,ST_CHAR *); +ST_INT strnicmp (ST_CHAR *,ST_CHAR *,ST_INT n); +#endif + +/* "strncat_maxstrlen" is like "strncat" but the third arg is the */ +/* maximum length of the destination string. */ +ST_RET strncat_maxstrlen (char *dest, char *src, size_t maxstrlen); + +/* "strncpy_safe" makes sure that the "dest" string is NULL-terminated. */ +/* The standard "strncpy" does NOT always NULL-terminate "dest". */ +ST_VOID strncpy_safe (char *dest, char *src, int max_len); + +ST_CHAR *sInt8ToAscii (ST_INT8 v, ST_CHAR *p); +ST_CHAR *uInt8ToAscii (ST_UINT8 v, ST_CHAR *p); +ST_CHAR *sInt16ToAscii (ST_INT16 v, ST_CHAR *p); +ST_CHAR *uInt16ToAscii (ST_UINT16 v, ST_CHAR *p); +ST_CHAR *sInt32ToAscii (ST_INT32 v, ST_CHAR *p); +ST_CHAR *uInt32ToAscii (ST_UINT32 v, ST_CHAR *p); +ST_CHAR *sIntToAscii (ST_INT v, ST_CHAR *p); +ST_CHAR *uIntToAscii (ST_UINT v, ST_CHAR *p); +ST_CHAR *sLongToAscii (ST_LONG v, ST_CHAR *p); +ST_CHAR *uLongToAscii (ST_ULONG v, ST_CHAR *p); + +/* misc functions */ +ST_BOOLEAN getKeywordFromFile (ST_CHAR *fileStr, ST_CHAR *keywordStr, + ST_CHAR *valBuf, ST_UINT valBufLen); + +ST_CHAR *get_next_string (ST_CHAR **ptrptr, ST_CHAR *delimiters); + +#ifdef __cplusplus +} +#endif + +#endif /* !STR_UTIL_INCLUDED */ + diff --git a/mmslib/inc/Smem.h b/mmslib/inc/Smem.h new file mode 100644 index 0000000..85d1971 --- /dev/null +++ b/mmslib/inc/Smem.h @@ -0,0 +1,467 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999, All Rights Reserved */ +/* */ +/* MODULE NAME : smem.h */ +/* PRODUCT(S) : Utilities */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/14/03 JRB 10 Eliminate compiler warnings. */ +/* 10/09/01 JRB 09 Add non-debug log macros. */ +/* 10/02/01 JRB 08 Del DBL_LNK from SMEM_CONTEXT (never used). */ +/* Add forward declarations to reduce warnings. */ +/* 09/21/01 JRB 07 Add args to smem_add_pool. */ +/* Chg args to u_smem_*. */ +/* Del unused prototypes. */ +/* Add u_smem_get_buf_detail. */ +/* Pass old & new size to smem_realloc. */ +/* Add m_add_pool proto. */ +/* Del #ifdef ACSE && LEANT. */ +/* Del smemInitialized,smemDefCtxt (not needed).*/ +/* Add more SLOG macros. */ +/* Chg poolName, contextName to (ST_CHAR *). */ +/* 05/21/01 MDE 06 Mode SMEM context management work */ +/* 03/19/01 JEB 05 Moved all SMEM context defs to this file. */ +/* 03/10/01 GLB 04 Added u_smem_get_pool_params */ +/* 03/10/01 GLB 03 Added smemcfgx for parsing memory cfg. file */ +/* 02/26/01 MDE 02 Added clone control to SMEM_POOL_CTRL */ +/* 12/09/99 MDE 01 New */ +/************************************************************************/ +/************************************************************************/ + +#ifndef SMEM_INCLUDED +#define SMEM_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "gen_list.h" + +/************************************************************************/ + +#define SMEM_MAX_RANGE_TRACK 10 + +typedef struct _smem_range_track + { + ST_UINT lowLimit; + ST_UINT highLimit; + ST_LONG currNum; + ST_LONG maxNum; + } SMEM_RANGE_TRACK; + +typedef struct _smem_rt_ctrl + { + ST_INT numRanges; + SMEM_RANGE_TRACK rt[SMEM_MAX_RANGE_TRACK]; + } SMEM_RT_CTRL; + +/************************************************************************/ +struct _smem_pool_ctrl; /* forward declaration */ +struct _smem_context; /* forward declaration */ + +typedef struct _smem_pool_ctrl + { + struct _smem_pool_ctrl *next; + ST_CHAR *poolName; + ST_UINT bufSize; + ST_UINT8 numBuf; + ST_UINT8 nextAvailBuf; + ST_UINT8 *availIndexStack; /* Index table, size [numBuf] */ + ST_CHAR *firstBuf; + ST_CHAR *lastBuf; + struct _smem_context *smemContext; + + ST_BOOLEAN autoClone; + ST_INT maxClones; + ST_INT cloneCount; + +#ifdef DEBUG_SISCO + ST_UINT8 maxNumUsed; + ST_UINT16 *usedSize; /* usedSize [numBuf] */ +#endif + + ST_VOID *usr; /* SMEM user can use this ... */ + } SMEM_POOL_CTRL; + + +typedef struct _smem_context + { + ST_CHAR *contextName; + ST_INT usrId; /* User */ + ST_VOID *usr; /* User */ + +/* Must be arranged from smallest to largest buffer size */ + SMEM_POOL_CTRL *smemPoolCtrlList; + +/* Optional range tracking */ + SMEM_RT_CTRL *smemRangeTrack; + } SMEM_CONTEXT; + +/************************************************************************/ +/************************************************************************/ + +ST_RET smemcfgx (ST_CHAR *xml_filename); + +ST_VOID u_smem_get_pool_params ( SMEM_CONTEXT *contextName, + ST_UINT8 *numBuf, ST_UINT *bufSize, + ST_BOOLEAN *autoClone, + ST_INT *maxClones, + ST_CHAR **poolName); + +SMEM_POOL_CTRL *u_smem_need_buffers (SMEM_CONTEXT *smemContext, + ST_UINT8 numBuf, ST_UINT bufSize); +ST_CHAR *u_smem_get_buf_detail (ST_VOID *bufptr, ST_INT bufSize); + +SMEM_POOL_CTRL *smem_add_pool (SMEM_CONTEXT *smemContext, + ST_UINT8 numBuf, ST_UINT bufSize, + ST_BOOLEAN autoClone, + ST_INT maxClones, + ST_CHAR *poolName); + +ST_VOID *smem_malloc (SMEM_CONTEXT *smemContext, ST_UINT size); +ST_VOID *smem_calloc (SMEM_CONTEXT *smemContext, ST_UINT num, ST_UINT size); +ST_VOID *smem_realloc (SMEM_CONTEXT *smemContext, ST_VOID *oldptr, + ST_UINT oldsize, ST_UINT newsize); +ST_VOID smem_free (SMEM_CONTEXT *smemContext, ST_VOID *ptr); +ST_VOID smem_log_state (SMEM_CONTEXT *smemContext); + +ST_VOID smem_range_check (SMEM_CONTEXT *smemContext, + ST_UINT size, ST_BOOLEAN add); + + +/************************************************************************/ +/* mem_smem.c function prototypes */ +/************************************************************************/ +SMEM_POOL_CTRL *m_add_pool (SMEM_CONTEXT *smemContext, + ST_UINT8 numBuf, ST_UINT bufSize, + ST_BOOLEAN autoClone, + ST_INT maxClones, + ST_CHAR *poolName); + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +#define SMEM_LOG_ERR 0x0001 +#define SMEM_LOG_NERR 0x0002 +#define SMEM_LOG_FLOW 0x0004 +#define SMEM_LOG_DEBUG 0x0008 + +extern ST_UINT smem_debug_sel; + +/************************************************************************/ +/************************************************************************/ + +extern SD_CONST ST_CHAR *SD_CONST _smem_log_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smem_log_flow_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smem_log_nerr_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smem_log_debug_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smem_log_dump_logstr; + +#ifdef DEBUG_SISCO + +#define SMEMLOG_ERR0(a) {\ + _slog (sLogCtrl,_smem_log_err_logstr,\ + thisFileName,__LINE__,a);\ + } +#define SMEMLOG_ERR1(a,b) {\ + _slog (sLogCtrl,_smem_log_err_logstr,\ + thisFileName,__LINE__,a,b);\ + } + +#define SMEMLOG_ERR2(a,b,c) {\ + _slog (sLogCtrl,_smem_log_err_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } + +#define SMEMLOG_CERR0(a) {\ + _slogc (sLogCtrl,a);\ + } +#define SMEMLOG_CERR1(a,b) {\ + _slogc (sLogCtrl,a,b);\ + } + +#define SMEMLOG_CERR2(a,b,c) {\ + _slogc (sLogCtrl,a,b,c);\ + } + +#define SMEMLOG_NERR0(a) {\ + if (smem_debug_sel & SMEM_LOG_NERR)\ + _slog (sLogCtrl,_smem_log_nerr_logstr,\ + thisFileName,__LINE__,a);\ + } +#define SMEMLOG_NERR1(a,b) {\ + if (smem_debug_sel & SMEM_LOG_NERR)\ + _slog (sLogCtrl,_smem_log_nerr_logstr,\ + thisFileName,__LINE__,a,b);\ + } + +#define SMEMLOG_FLOW1(a,b) {\ + if (smem_debug_sel & SMEM_LOG_FLOW)\ + _slog (sLogCtrl,_smem_log_flow_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define SMEMLOG_CFLOW1(a,b) {\ + if (smem_debug_sel & SMEM_LOG_FLOW)\ + _slogc (sLogCtrl,a,b);\ + } +#define SMEMLOG_CFLOW2(a,b,c) {\ + if (smem_debug_sel & SMEM_LOG_FLOW)\ + _slogc (sLogCtrl,a,b,c);\ + } + +#define SMEMLOG_DUMP0(a) {\ + _slog (sLogCtrl,_smem_log_dump_logstr,\ + thisFileName,__LINE__,a);\ + } +#define SMEMLOG_DUMP1(a,b) {\ + _slog (sLogCtrl,_smem_log_dump_logstr,\ + thisFileName,__LINE__,a,b);\ + } + +#define SMEMLOG_CDUMP0(a) {\ + _slogc (sLogCtrl,a);\ + } + +#define SMEMLOG_CDUMP1(a,b) {\ + _slogc (sLogCtrl,a,b);\ + } + +#define SMEMLOG_CDUMP2(a,b,c) {\ + _slogc (sLogCtrl,a,b,c);\ + } + +#define SMEMLOG_CDUMP3(a,b,c,d) {\ + _slogc (sLogCtrl,a,b,c,d);\ + } + +#define SMEMLOG_CDUMP4(a,b,c,d,e) {\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define SMEMLOG_CDUMP5(a,b,c,d,e,f) {\ + _slogc (sLogCtrl,a,b,c,d,e,f);\ + } + +#define SMEMLOG_DEBUG0(a) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slog (sLogCtrl,_smem_log_debug_logstr,\ + thisFileName,__LINE__,a);\ + } + +#define SMEMLOG_DEBUG1(a,b) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slog (sLogCtrl,_smem_log_debug_logstr,\ + thisFileName,__LINE__,a,b);\ + } + +#define SMEMLOG_DEBUG2(a,b,c) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slog (sLogCtrl,_smem_log_debug_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define SMEMLOG_DEBUG3(a,b,c,d) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slog (sLogCtrl,_smem_log_debug_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define SMEMLOG_DEBUG4(a,b,c,d,e) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slog (sLogCtrl,_smem_log_debug_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define SMEMLOG_CDEBUG0(a) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slogc (sLogCtrl,a);\ + } + +#define SMEMLOG_CDEBUG1(a,b) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slogc (sLogCtrl,a,b);\ + } + +#define SMEMLOG_CDEBUG2(a,b,c) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define SMEMLOG_CDEBUG3(a,b,c,d) {\ + if (smem_debug_sel & SMEM_LOG_DEBUG)\ + _slogc (sLogCtrl,a,b,c,d);\ + } + +#else /* #ifdef DEBUG_SISCO */ + +#define SMEMLOG_ERR0(a) +#define SMEMLOG_ERR1(a,b) +#define SMEMLOG_ERR2(a,b,c) +#define SMEMLOG_CERR0(a) +#define SMEMLOG_CERR1(a,b) +#define SMEMLOG_CERR2(a,b,c) +#define SMEMLOG_NERR0(a) +#define SMEMLOG_NERR1(a,b) +#define SMEMLOG_FLOW1(a,b) +#define SMEMLOG_CFLOW1(a,b) +#define SMEMLOG_CFLOW2(a,b,c) +#define SMEMLOG_DUMP0(a) +#define SMEMLOG_DUMP1(a,b) +#define SMEMLOG_CDUMP0(a,b) +#define SMEMLOG_CDUMP1(a,b) +#define SMEMLOG_CDUMP2(a,b,c) +#define SMEMLOG_CDUMP3(a,b,c,d) +#define SMEMLOG_CDUMP4(a,b,c,d,e) +#define SMEMLOG_CDUMP5(a,b,c,d,e,f) +#define SMEMLOG_DEBUG0(a,b,c) +#define SMEMLOG_DEBUG2(a,b,c) +#define SMEMLOG_DEBUG3(a,b,c,d) +#define SMEMLOG_DEBUG4(a,b,c,d,e) +#define SMEMLOG_CDEBUG0(a) +#define SMEMLOG_CDEBUG1(a,b) +#define SMEMLOG_CDEBUG2(a,b,c) +#define SMEMLOG_CDEBUG3(a,b,c,d) + +#endif /* #ifdef DEBUG_SISCO */ + +/************************************************************************/ +/* Here we define a context control table and the associated indices */ + +#define M_SMEM_MAX_CONTEXT 30 /* number of specific context array elements */ + /* + extra context array elements for user applications */ + /* = MAX context array size */ +extern SMEM_CONTEXT m_smem_ctxt[M_SMEM_MAX_CONTEXT]; + +/* All users of SMEM that want a a context are to specify it here as an */ +/* index into the m_smem_ctxt table. */ + +/* Valid context indices */ +#define MSMEM_GEN_IDX 0 /* chk_* macros use this ctxt*/ + +/* MMS-EASE Lite indices */ +#define MSMEM_DEC_OS_INFO_IDX 1 +#define MSMEM_ENC_OS_INFO_IDX 2 +#define MSMEM_WR_DATA_DEC_BUF_IDX 3 +#define MSMEM_ASN1_DATA_ENC_IDX 4 +#define MSMEM_PDU_ENC_IDX 5 +#define MSMEM_COM_EVENT_IDX 6 +#define MSMEM_RXPDU_IDX 7 +#define MSMEM_NETINFO_IDX 8 +#define MSMEM_DYN_RT_IDX 9 +#define MSMEM_AA_ENCODE_IDX 10 +#define MSMEM_REQ_CTRL_IDX 11 +#define MSMEM_IND_CTRL_IDX 12 +#define MSMEM_MVLU_VA_IDX 13 +#define MSMEM_MVLU_VA_CTRL_IDX 14 +#define MSMEM_MVLU_VA_DATA_IDX 15 +#define MSMEM_MVLU_GNL_IDX 16 +#define MSMEM_MVLU_AA_IDX 17 + +/* For STACK (ACSE and LEANT) */ +#define MSMEM_ACSE_CONN_IDX 18 +#define MSMEM_ACSE_DATA_IDX 19 +#define MSMEM_COSP_CN_IDX 20 +#define MSMEM_N_UNITDATA_IDX 21 +#define MSMEM_SOCK_INFO_IDX 22 +#define MSMEM_SPDU_TX_IDX 23 +#define MSMEM_STARTUP_IDX 24 +#define MSMEM_TPKT_IDX 25 + +/* The following are valid Contexts */ +#define MSMEM_GEN &m_smem_ctxt[MSMEM_GEN_IDX] + +/* MMS-EASE Lite indices */ +#define MSMEM_DEC_OS_INFO &m_smem_ctxt[MSMEM_DEC_OS_INFO_IDX] +#define MSMEM_ENC_OS_INFO &m_smem_ctxt[MSMEM_ENC_OS_INFO_IDX] +#define MSMEM_WR_DATA_DEC_BUF &m_smem_ctxt[MSMEM_WR_DATA_DEC_BUF_IDX] +#define MSMEM_ASN1_DATA_ENC &m_smem_ctxt[MSMEM_ASN1_DATA_ENC_IDX] +#define MSMEM_PDU_ENC &m_smem_ctxt[MSMEM_PDU_ENC_IDX] +#define MSMEM_COM_EVENT &m_smem_ctxt[MSMEM_COM_EVENT_IDX] +#define MSMEM_RXPDU &m_smem_ctxt[MSMEM_RXPDU_IDX] +#define MSMEM_NETINFO &m_smem_ctxt[MSMEM_NETINFO_IDX] +#define MSMEM_REQ_CTRL &m_smem_ctxt[MSMEM_REQ_CTRL_IDX] +#define MSMEM_IND_CTRL &m_smem_ctxt[MSMEM_IND_CTRL_IDX] +#define MSMEM_MVLU_VA &m_smem_ctxt[MSMEM_MVLU_VA_IDX] +#define MSMEM_MVLU_VA_CTRL &m_smem_ctxt[MSMEM_MVLU_VA_CTRL_IDX] +#define MSMEM_MVLU_VA_DATA &m_smem_ctxt[MSMEM_MVLU_VA_DATA_IDX] +#define MSMEM_MVLU_AA &m_smem_ctxt[MSMEM_MVLU_AA_IDX] +#define MSMEM_MVLU_GNL &m_smem_ctxt[MSMEM_MVLU_GNL_IDX] +#define MSMEM_DYN_RT &m_smem_ctxt[MSMEM_DYN_RT_IDX] +#define MSMEM_AA_ENCODE &m_smem_ctxt[MSMEM_AA_ENCODE_IDX] + +/* For STACK (ACSE and LEANT) */ +#define MSMEM_ACSE_CONN &m_smem_ctxt[MSMEM_ACSE_CONN_IDX] +#define MSMEM_ACSE_DATA &m_smem_ctxt[MSMEM_ACSE_DATA_IDX] +#define MSMEM_COSP_CN &m_smem_ctxt[MSMEM_COSP_CN_IDX] +#define MSMEM_N_UNITDATA &m_smem_ctxt[MSMEM_N_UNITDATA_IDX] +#define MSMEM_SOCK_INFO &m_smem_ctxt[MSMEM_SOCK_INFO_IDX] +#define MSMEM_SPDU_TX &m_smem_ctxt[MSMEM_SPDU_TX_IDX] +#define MSMEM_STARTUP &m_smem_ctxt[MSMEM_STARTUP_IDX] +#define MSMEM_TPKT &m_smem_ctxt[MSMEM_TPKT_IDX] + +#ifdef SMEMCFGX +/************************************************************************/ +/* This list is used to log error messages when an invalid context name */ +/* is entered. The error message for an invalid context name will list */ +/* all valid context names, as listed below. */ +/* Note: these names should match those listed above and those in */ +/* 'smemcfg.xml' */ + +typedef struct + { + ST_INT idx; + ST_CHAR *name; + } SMEM_CTXT_NAME; + +static SMEM_CTXT_NAME smemCtxtNames[] = + { + {MSMEM_GEN_IDX, "MSMEM_GEN"}, + {MSMEM_DEC_OS_INFO_IDX, "MSMEM_DEC_OS_INFO"}, + {MSMEM_ENC_OS_INFO_IDX, "MSMEM_ENC_OS_INFO"}, + {MSMEM_WR_DATA_DEC_BUF_IDX, "MSMEM_WR_DATA_DEC_BUF"}, + {MSMEM_ASN1_DATA_ENC_IDX, "MSMEM_ASN1_DATA_ENC"}, + {MSMEM_PDU_ENC_IDX, "MSMEM_PDU_ENC"}, + {MSMEM_COM_EVENT_IDX, "MSMEM_COM_EVENT"}, + {MSMEM_RXPDU_IDX, "MSMEM_RXPDU"}, + {MSMEM_NETINFO_IDX, "MSMEM_NETINFO"}, + {MSMEM_REQ_CTRL_IDX, "MSMEM_REQ_CTRL"}, + {MSMEM_IND_CTRL_IDX, "MSMEM_IND_CTRL"}, + {MSMEM_MVLU_VA_IDX, "MSMEM_MVLU_VA"}, + {MSMEM_MVLU_VA_CTRL_IDX, "MSMEM_MVLU_VA_CTRL"}, + {MSMEM_MVLU_VA_DATA_IDX, "MSMEM_MVLU_VA_DATA"}, + {MSMEM_MVLU_AA_IDX, "MSMEM_MVLU_AA"}, + {MSMEM_MVLU_GNL_IDX, "MSMEM_MVLU_GNL"}, + {MSMEM_DYN_RT_IDX, "MSMEM_DYN_RT"}, + {MSMEM_AA_ENCODE_IDX, "MSMEM_AA_ENCODE"}, + {MSMEM_ACSE_CONN_IDX, "MSMEM_ACSE_CONN"}, + {MSMEM_ACSE_DATA_IDX, "MSMEM_ACSE_DATA"}, + {MSMEM_COSP_CN_IDX, "MSMEM_COSP_CN"}, + {MSMEM_N_UNITDATA_IDX, "MSMEM_N_UNITDATA"}, + {MSMEM_SOCK_INFO_IDX, "MSMEM_SOCK_INFO"}, + {MSMEM_SPDU_TX_IDX, "MSMEM_SPDU_TX"}, + {MSMEM_STARTUP_IDX, "MSMEM_STARTUP"}, + {MSMEM_TPKT_IDX, "MSMEM_TPKT"} + }; + +static ST_INT smem_num_ctxt_names = sizeof(smemCtxtNames)/sizeof(SMEM_CTXT_NAME); + +#endif + +/************************************************************************/ +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* smem.h already included */ + diff --git a/mmslib/inc/acse2.h b/mmslib/inc/acse2.h new file mode 100644 index 0000000..aa88728 --- /dev/null +++ b/mmslib/inc/acse2.h @@ -0,0 +1,310 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995 - 2004, All Rights Reserved */ +/* */ +/* MODULE NAME : acse2.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* ACSE main header file. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/27/04 EJV 16 ACSE_CONN (MAP30_ACSE): added initiator. */ +/* 08/25/03 EJV 15 Del old password auth (OBSOLETE_ACSE_AUTH) */ +/* ACSE_CONN: added part_auth_info, encrypt_ctrl*/ +/* Added security functions protos. */ +/* 08/01/03 JRB 14 Add lean_a.h for DIB_ENTRY. */ +/* 06/17/03 EJV 13 Moved DIB_MATCH... from m_match.h. */ +/* 10/14/02 ASK 12 Added abort diagnostic tag */ +/* 09/27/02 ASK 11 Added ASN.1 security tags to AARE APDU, moved*/ +/* bitstring defines from acse2dec.c */ +/* 06/20/02 JRB 10 Add TSELs & remote NSAP/IP to ACSE_CONN. */ +/* 12/11/01 JRB 09 Convert to use ASN1R. */ +/* 09/10/01 JRB 08 Put back cosp_cn_ptr, cosp_cn_len. */ +/* 08/01/01 JRB 07 Del cosp_cn_ptr, cosp_cn_len from ACSE_CONN. */ +/* 04/03/01 JRB 06 Add PSELs & SSELs to ACSE_CONN. */ +/* 01/05/01 EJV 05 Changes for use over Marben */ +/* 07/14/99 JRB 04 Add ACSE Password Authentication stuff. */ +/* 08/13/98 JRB 03 Lint cleanup. */ +/* 07/23/98 JRB 02 Delete Marben support. */ +/* 11/10/97 JRB 01 Chg cosp_buf to (ST_UCHAR *). */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/19/97 JRB 08 MOSI cleanup. */ +/* 03/07/97 JRB 07 Added MOSI support. */ +/* 01/02/97 EJV 06 Added ACSE2_INCLUDED and __cplusplus. */ +/* 06/25/96 JRB 05 Added 'LEAN_T' support. */ +/* 05/02/96 JRB 04 Add STATE_TP4CONN_WAIT. */ +/* 04/18/96 JRB 03 Add STATE_AARE_ABANDON. */ +/* 03/26/96 MDE 02 Added 'REDUCED_STACK' support */ +/* 10/30/95 JRB 01 Created */ +/************************************************************************/ + +#ifndef ACSE2_INCLUDED +#define ACSE2_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gen_list.h" +#include "acse2log.h" /* slog macros for ACSE */ +#include "acse2usr.h" +#if !defined(MAP30_ACSE) +#include "lean_a.h" /* need DIB_ENTRY */ +#endif +#include "dibmatch.h" + +/* Defines for bits in bitstring encoded values. */ +#define BIT_VERSION1 0x80 /* AARQ, AARE protocol_version */ +#define BIT_AUTHENTICATION 0x80 /* AARQ, AARE acse_requirements */ + +/* ACPM states. */ +#define STATE_INVALID -1 /* So user cannot use freed struct*/ +#define STATE_IDLE 0 +#define STATE_AARE_WAIT 1 +#define STATE_AASCRSP_WAIT 2 +#define STATE_RLRE_WAIT 3 +#define STATE_ARLSRSP_WAIT 4 +#define STATE_ASSOCIATED 5 +#define STATE_INIT_COLL 6 +#define STATE_RESP_COLL 7 +#define STATE_AARE_ABANDON 8 +#define STATE_TP4CONN_WAIT 9 + +/* ASN.1 tags for ACSE APDUs */ +#define TAG_AARQ 0 +#define TAG_AARE 1 +#define TAG_RLRQ 2 +#define TAG_RLRE 3 +#define TAG_ABRT 4 +#define TAG_ADT 5 +/* ASN.1 tags for CONNECTIONLESS ACSE APDUs */ +#define TAG_AUDT 0 + +/* ASN.1 tags for elements of AARQ APDU */ +#define AARQ_protocol_version 0 +#define AARQ_ASO_context_name 1 +#define AARQ_CALLED_AP_title 2 +#define AARQ_CALLED_AE_qual 3 +#define AARQ_CALLED_AP_inv_id 4 +#define AARQ_CALLED_AE_inv_id 5 +#define AARQ_CALLING_AP_title 6 +#define AARQ_CALLING_AE_qual 7 +#define AARQ_CALLING_AP_inv_id 8 +#define AARQ_CALLING_AE_inv_id 9 +#define AARQ_acse_requirements 10 +#define AARQ_mechanism_name 11 +#define AARQ_CALLING_auth_value 12 +#define AARQ_user_info 30 + +/* ASN.1 tags for elements of AUDT APDU (same as AARQ) */ +#define AUDT_protocol_version AARQ_protocol_version +#define AUDT_ASO_context_name AARQ_ASO_context_name +#define AUDT_CALLED_AP_title AARQ_CALLED_AP_title +#define AUDT_CALLED_AE_qual AARQ_CALLED_AE_qual +#define AUDT_CALLED_AP_inv_id AARQ_CALLED_AP_inv_id +#define AUDT_CALLED_AE_inv_id AARQ_CALLED_AE_inv_id +#define AUDT_CALLING_AP_title AARQ_CALLING_AP_title +#define AUDT_CALLING_AE_qual AARQ_CALLING_AE_qual +#define AUDT_CALLING_AP_inv_id AARQ_CALLING_AP_inv_id +#define AUDT_CALLING_AE_inv_id AARQ_CALLING_AE_inv_id +#define AUDT_user_info AARQ_user_info + +/* ASN.1 tags for elements of AARE APDU */ +#define AARE_protocol_version 0 +#define AARE_ASO_context_name 1 +#define AARE_result 2 +#define AARE_result_source_diagnostic 3 +#define AARE_RESPONDING_AP_title 4 +#define AARE_RESPONDING_AE_qual 5 +#define AARE_RESPONDING_AP_inv_id 6 +#define AARE_RESPONDING_AE_inv_id 7 +#define AARE_RESPONDER_acse_requirements 8 /* See the ACSE Spec for the strange name */ +#define AARE_mechanism_name 9 +#define AARE_RESPONDING_auth_value 10 +#define AARE_user_info 30 + +/* ASN.1 tags for elements of RLRQ APDU */ +#define RLRQ_reason 0 +#define RLRQ_user_info 30 + +/* ASN.1 tags for elements of RLRE APDU */ +#define RLRE_reason 0 +#define RLRE_user_info 30 + +/* ASN.1 tags for elements of ABRT APDU */ +#define ABRT_source 0 +#define ABRT_diagnostic 1 +#define ABRT_user_info 30 + +/* ASN.1 tags for elements of ADT APDU */ +#define ADT_user_info 30 + +#define ACSE_SERVICE_USER 0 +#define ACSE_SERVICE_PROVIDER 1 + +/************************************************************************/ +/* ACSE_CONN structure */ +/************************************************************************/ +#if defined (MOSI) +#define MAX_COSP_COPP_HEADER (((MAX_PSEL_LEN+MAX_SSEL_LEN)*2)+200) +typedef struct tagACSE_CONN + { + /* common part */ + ST_UINT apdu_len; /* len of a APDU (also PS-user data len)*/ + ST_UCHAR *apdu_ptr; /* pointer to start of APDU encoding */ + ST_UINT ppdu_len; /* len of a PPDU (also SS-user data len)*/ + ST_UCHAR *ppdu_ptr; /* pointer to start of PPDU encoding */ + ST_CHAR pcimms; + ST_CHAR pciacse; + /* ACSE part */ + ST_LONG user_conn_id; /* ACSE-user's connection ID. */ + ST_INT state; /* See "STATE_*" defines */ + ST_BOOLEAN initiator; /* Flag: did we initiate this connection? */ + /* COPP part */ + ST_INT num_ctxt; + ST_INT copp_state; /* See "COPP_STATE_*" defines */ + /* cosp part */ + ST_INT cosp_state; /* See "COSP_CSTATE_*" defines */ + ST_UINT cosp_cn_len; + char *cosp_cn_ptr; /* CONNECT SPDU saved until TCONN.cnf */ + ST_LONG cosp_bind_id; /* COSP bind id saved until CN arrive */ + ST_BOOLEAN cosp_vtca; /* SD_TRUE if transport connection acceptor*/ + ST_BOOLEAN cosp_vcoll; /* SD_TRUE if collision of FINISH SPDUs */ + ST_BOOLEAN cosp_vdnr; /* SD_TRUE if DISCONNECT SPDU has been */ + /* received in STA 09 (following */ + /* collision of FINISH SPDUs). */ + /* TP4 part */ + ST_LONG tp4_conn_id; /* TP4 connect id */ + ST_BOOLEAN cr; /* "collision of release" flag */ + ST_BOOLEAN rl; /* "release started" flag */ + BUFFER save_buf; /* buffer to save AARQ or RLRE to send later */ + ST_UCHAR loc_psel [MAX_PSEL_LEN+1]; /* Local PSEL (1st byte = len) */ + ST_UCHAR rem_psel [MAX_PSEL_LEN+1]; /* Remote PSEL (1st byte = len) */ + ST_UCHAR loc_ssel [MAX_SSEL_LEN+1]; /* Local SSEL (1st byte = len) */ + ST_UCHAR rem_ssel [MAX_SSEL_LEN+1]; /* Remote SSEL (1st byte = len) */ + ST_UCHAR loc_tsel [MAX_TSEL_LEN+1]; /* Local TSEL (1st byte = len) */ + ST_UCHAR rem_tsel [MAX_TSEL_LEN+1]; /* Remote TSEL (1st byte = len) */ + union + { + ST_UCHAR nsap [CLNP_MAX_LEN_NSAP+1];/* Remote NSAP (1st byte = len) */ + ST_ULONG ip; /* OR IP Addr (network byte order)*/ + }remNetAddr; + /* authentication and security */ + ACSE_AUTH_INFO part_auth_info; /* partner authentication info */ + S_SEC_ENCRYPT_CTRL encrypt_ctrl; /* connection encryption info */ + } ACSE_CONN; +#elif defined (MAP30_ACSE) +typedef struct acse_bind_info_tag + { + ST_CHAR ar_name[MAX_NAME_LEN+1]; /* local AR Name to be bind */ + ST_LONG user_bind_id; /* Save User's bind ID */ + ST_INT suic_chan_base; /* start chan where we register AR Name */ + ST_INT num_calling; /* num of calling channels */ + ST_INT num_called; /* num of called channels */ + } ACSE_BIND_INFO; + +typedef struct tagACSE_CONN + { + /* fields below are changed during binding */ + ACSE_BIND_INFO *bind_info; /* pointer to ACSE bind info */ + ST_LONG user_bind_id; /* user's bind ID */ + ST_INT chan; /* SUIC channel */ + /* fields below are changed during connection/disconnection */ + ST_INT state; /* See "STATE_*" defines */ + ST_LONG user_conn_id; /* user's connect ID */ + ST_BOOLEAN initiator; /* Flag: did we initiate this connection? */ + ST_UINT ap_context; /* SUIC AP context from associate ind */ + ST_INT num_pc_defs; /* pres context deflist count from aind */ + PC_DEF *pc_deflist; /* pres context deflist ptr from aind */ + } ACSE_CONN; +#else /* !MOSI and !MAP30_ACSE */ +typedef struct tagACSE_CONN + { + ST_LONG user_bind_id; /* tp4_connect_ind saves for u_a_associate_ind */ + ST_LONG tp4_conn_id; + ST_LONG user_conn_id; + ST_INT state; /* See "STATE_*" defines */ + ST_BOOLEAN initiator; /* Flag: did we initiate this connection? */ + ST_UCHAR *rcv_data; /* buffer to reassembling TPDUs */ + ST_UINT rcv_data_len; /* Length of data in rcv_data. */ + BUFFER save_buf; /* buffer to save AARQ or RLRE to send later */ + } ACSE_CONN; +#endif /* !MOSI */ + +/************************************************************************/ +/* PBIND structure */ +/************************************************************************/ +typedef struct tagPBIND + { + DBL_LNK link; + ST_LONG user_bind_id; /* User-supplied Bind ID */ + ST_LONG clnp_bind_id; /* Register ID returned by OSIAM */ + ST_LONG real_clpp_bind_id; /* Used in real bind/unbind to Marben */ + ST_INT sap; /* SAP number this register is bound to */ + PRES_ADDR loc_addr; + } PBIND; + +/************************************************************************/ +/* General address matching defines, control, functions */ +/* */ + +#if !defined(MAP30_ACSE) +/* Lean-T specific functions */ +ST_RET dib_match_remote_ar (DIB_MATCH_CTRL *matchCtrl, AARQ_APDU *aarq, + DIB_ENTRY **dib_entry_out); +ST_RET dib_match_local_ar (DIB_MATCH_CTRL *matchCtrl, AARQ_APDU *aarq, + DIB_ENTRY **dib_entry_out); +ST_INT dib_cmp_local_addr (DIB_MATCH_CTRL *matchCtrl, AARQ_APDU *aarq, + DIB_ENTRY *dib_entry); +ST_INT dib_cmp_remote_addr (DIB_MATCH_CTRL *matchCtrl, AARQ_APDU *aarq, + DIB_ENTRY *dib_entry); +#endif /* !defined(MAP30_ACSE) */ + + +/************************************************************************/ +/* Security functions */ +ST_RET a_get_security_info (ST_LONG acse_conn_id, S_SEC_SPARAMS *secParams); +ST_RET a_free_security_info (ACSE_AUTH_INFO *authInfo); +ST_RET a_free_part_security_info (ST_LONG acse_conn_id); + + +/************************************************************************/ +/* Global variables. */ +/************************************************************************/ +extern ST_INT num_pbinds; /* Number of P-Address bindings.*/ +extern PBIND *pbind_list; /* Linked list of PBIND structs */ +extern ST_BOOLEAN nsap_bind_done; /* Don't allow 2nd bind until 1st done */ +extern MMS_OBJ_ID mms_obj_id; /* ISO MMS Object ID */ +extern MMS_OBJ_ID acse_obj_id; /* ACSE Object ID */ +extern MMS_OBJ_ID asn1_obj_id; /* ASN.1 Object ID */ +extern MMS_OBJ_ID a_auth_password_obj_id; /* Obj ID for ACSE Password*/ + /* Authentication mech. */ + +extern ST_UINT acse_msgsize; +#ifdef MOSI +extern ST_UINT cosp_msgsize; +extern ST_UCHAR *cosp_buf; +extern ACSE_CONN *decode_acse_conn; /* connection we're doing decode for. */ +#endif + +/************************************************************************/ +/* Prototypes */ +/************************************************************************/ +ST_VOID clnp_unbind_cnf (PBIND *pbind); +ST_VOID asn1_skip_elmnt (ASN1_DEC_CTXT *aCtx); +ST_VOID acse_free_con (ACSE_CONN *con); + + +#ifdef __cplusplus +} +#endif + +#endif /* ACSE2_INCLUDED */ + diff --git a/mmslib/inc/acse2log.h b/mmslib/inc/acse2log.h new file mode 100644 index 0000000..a2cd434 --- /dev/null +++ b/mmslib/inc/acse2log.h @@ -0,0 +1,144 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-2003, All Rights Reserved */ +/* */ +/* MODULE NAME : acse2log.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* ACSE logging header file. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/02/05 JRB 07 Added acse2usr.h */ +/* 06/17/03 EJV 06 Converted to new log macros. */ +/* Deleted _audt_*_logstr. Added DIB logging. */ +/* 12/11/00 EJV 05 Added more log macros */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 12/16/96 JRB 04 Del "AUDTLOG_*" macros. Use "ACSELOG_*" for */ +/* CL ACSE as well as CO ACSE. */ +/* 10/08/98 MDE 08 Migrated to updated SLOG interface */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/20/97 JRB 07 Stop checking for sLogCtrl==NULL. */ +/* 02/20/97 JRB 06 Move *_debug_sel & logmasks from acse2log.h */ +/* to acse2usr.h. */ +/* 01/02/97 EJV 05 Added ACSE2LOG_INCLUDED */ +/* 12/16/96 JRB 04 Add "AUDTLOG_*" macros for CLACSE. */ +/* 07/19/96 JRB 03 Change DEBUG_MMS to DEBUG_SISCO. */ +/* 04/17/96 JRB 02 Del acse_sLogCtrl, use sLogCtrl (slog.c) now */ +/* 10/30/95 JRB 01 Created */ +/************************************************************************/ +#ifndef ACSE2LOG_INCLUDED +#define ACSE2LOG_INCLUDED + +#include "acse2usr.h" /* need acse_debug_sel & log mask defines */ + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef DEBUG_SISCO +/****************************************************************/ +/* Log Control macros */ +/****************************************************************/ + +extern SD_CONST ST_CHAR *SD_CONST _acse_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _acse_enc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _acse_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _acse_dib_logstr; +#endif /* DEBUG_SISCO */ + +/*--------------------------------------*/ +/* ACSELOG_DEC macros */ +/*--------------------------------------*/ +#define ACSELOG_DEC0(a) \ + SLOG_0 (acse_debug_sel & ACSE_LOG_DEC,_acse_dec_logstr,a) +#define ACSELOG_DEC1(a,b) \ + SLOG_1 (acse_debug_sel & ACSE_LOG_DEC,_acse_dec_logstr,a,b) +#define ACSELOG_DEC2(a,b,c) \ + SLOG_2 (acse_debug_sel & ACSE_LOG_DEC,_acse_dec_logstr,a,b,c) +#define ACSELOG_DEC3(a,b,c,d) \ + SLOG_3 (acse_debug_sel & ACSE_LOG_DEC,_acse_dec_logstr,a,b,c,d) + +#define ACSELOG_DEC0C(a) SLOGC_0 (acse_debug_sel & ACSE_LOG_DEC,a) +#define ACSELOG_DEC1C(a,b) SLOGC_1 (acse_debug_sel & ACSE_LOG_DEC,a,b) +#define ACSELOG_DEC2C(a,b,c) SLOGC_2 (acse_debug_sel & ACSE_LOG_DEC,a,b,c) +#define ACSELOG_DEC3C(a,b,c,d) SLOGC_3 (acse_debug_sel & ACSE_LOG_DEC,a,b,c,d) + +#define ACSELOG_DECH(a,b) SLOGH (acse_debug_sel & ACSE_LOG_DEC,a,b) + +/*--------------------------------------*/ +/* ACSELOG_ENC macros */ +/*--------------------------------------*/ +#define ACSELOG_ENC0(a) \ + SLOG_0 (acse_debug_sel & ACSE_LOG_ENC,_acse_enc_logstr,a) +#define ACSELOG_ENC1(a,b) \ + SLOG_1 (acse_debug_sel & ACSE_LOG_ENC,_acse_enc_logstr,a,b) +#define ACSELOG_ENC2(a,b,c) \ + SLOG_2 (acse_debug_sel & ACSE_LOG_ENC,_acse_enc_logstr,a,b,c) +#define ACSELOG_ENC3(a,b,c,d) \ + SLOG_3 (acse_debug_sel & ACSE_LOG_ENC,_acse_enc_logstr,a,b,c,d) + +#define ACSELOG_ENC0C(a) SLOGC_0 (acse_debug_sel & ACSE_LOG_ENC,a) +#define ACSELOG_ENC1C(a,b) SLOGC_1 (acse_debug_sel & ACSE_LOG_ENC,a,b) +#define ACSELOG_ENC2C(a,b,c) SLOGC_2 (acse_debug_sel & ACSE_LOG_ENC,a,b,c) +#define ACSELOG_ENC3C(a,b,c,d) SLOGC_3 (acse_debug_sel & ACSE_LOG_ENC,a,b,c,d) + +#define ACSELOG_ENCH(a,b) SLOGH (acse_debug_sel & ACSE_LOG_ENC,a,b) + +/*--------------------------------------*/ +/* ACSELOG_ERR macros */ +/*--------------------------------------*/ +#define ACSELOG_ERR0(a) \ + SLOG_0 (acse_debug_sel & ACSE_LOG_ERR,_acse_err_logstr,a) +#define ACSELOG_ERR1(a,b) \ + SLOG_1 (acse_debug_sel & ACSE_LOG_ERR,_acse_err_logstr,a,b) +#define ACSELOG_ERR2(a,b,c) \ + SLOG_2 (acse_debug_sel & ACSE_LOG_ERR,_acse_err_logstr,a,b,c) +#define ACSELOG_ERR3(a,b,c,d) \ + SLOG_3 (acse_debug_sel & ACSE_LOG_ERR,_acse_err_logstr,a,b,c,d) + +#define ACSELOG_ERR0C(a) SLOGC_0 (acse_debug_sel & ACSE_LOG_ERR,a) +#define ACSELOG_ERR1C(a,b) SLOGC_1 (acse_debug_sel & ACSE_LOG_ERR,a,b) +#define ACSELOG_ERR2C(a,b,c) SLOGC_2 (acse_debug_sel & ACSE_LOG_ERR,a,b,c) +#define ACSELOG_ERR3C(a,b,c,d) SLOGC_3 (acse_debug_sel & ACSE_LOG_ERR,a,b,c,d) + +#define ACSELOG_ERRH(a,b) SLOGH (acse_debug_sel & ACSE_LOG_ERR,a,b) + +/*--------------------------------------*/ +/* ACSELOG_DIB macros */ +/*--------------------------------------*/ +#define ACSELOG_DIB0(a) \ + SLOG_0 (acse_debug_sel & ACSE_LOG_DIB,_acse_dib_logstr,a) +#define ACSELOG_DIB1(a,b) \ + SLOG_1 (acse_debug_sel & ACSE_LOG_DIB,_acse_dib_logstr,a,b) +#define ACSELOG_DIB2(a,b,c) \ + SLOG_2 (acse_debug_sel & ACSE_LOG_DIB,_acse_dib_logstr,a,b,c) +#define ACSELOG_DIB3(a,b,c,d) \ + SLOG_3 (acse_debug_sel & ACSE_LOG_DIB,_acse_dib_logstr,a,b,c,d) + +#define ACSELOG_DIB0C(a) SLOGC_0 (acse_debug_sel & ACSE_LOG_DIB,a) +#define ACSELOG_DIB1C(a,b) SLOGC_1 (acse_debug_sel & ACSE_LOG_DIB,a,b) +#define ACSELOG_DIB2C(a,b,c) SLOGC_2 (acse_debug_sel & ACSE_LOG_DIB,a,b,c) +#define ACSELOG_DIB3C(a,b,c,d) SLOGC_3 (acse_debug_sel & ACSE_LOG_DIB,a,b,c,d) + +#define ACSELOG_DIBH(a,b) SLOGH (acse_debug_sel & ACSE_LOG_DIB,a,b) + + +/****************************************************************/ +/* Log Control prototypes. */ +/****************************************************************/ +ST_VOID acse_default_log (ST_VOID); /* Set default log configuration */ + +#ifdef __cplusplus +} +#endif + +#endif /* ACSE2LOG_INCLUDED */ + diff --git a/mmslib/inc/acse2usr.h b/mmslib/inc/acse2usr.h new file mode 100644 index 0000000..4030758 --- /dev/null +++ b/mmslib/inc/acse2usr.h @@ -0,0 +1,406 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-2005, All Rights Reserved */ +/* */ +/* MODULE NAME : acse2usr.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* ACSE main header file. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/05/05 EJV 33 PRES_ADDR added port. */ +/* 03/28/05 EJV 32 MMSEASE_MOSE: add MAX_PSEL_LEN, MAX_SSEL_LEN */ +/* 10/21/03 JRB 31 Add a_get_event_handles_unix. */ +/* 08/25/03 EJV 30 Del old password auth (OBSOLETE_ACSE_AUTH) */ +/* Added a_get_chan. */ +/* Renamed encrypt_info to encrypt_ctrl */ +/* 07/23/03 MDE 29 Removed ACSE_AUTH_ENABLED, S_SEC_ENABLED */ +/* 06/17/03 EJV 28 Added ACSE_LOG_DIB mask. */ +/* 06/13/03 MDE 27 Added Security */ +/* 10/14/02 ASK 26 Added abort diagnostic to ABRT_APDU. */ +/* 09/30/02 ASK 25 Moved authentication defines / protos into */ +/* acseauth.h */ +/* 09/27/02 ASK 24 Add authentication stuff to AARE_APDU */ +/* 06/20/02 JRB 23 Add calling_paddr to AARQ_APDU. */ +/* Replace "nsap" in PRES_ADDR with union. */ +/* 05/02/02 MDE 22 Added _copp_bind */ +/* 02/14/02 ASK 21 Add a_associate_reqm */ +/* 01/22/02 JRB 20 Add args to copp_initialize (same as MAP30..)*/ +/* Del a_set_msgsize (no longer needed). */ +/* 01/10/02 JRB 19 Add cltp_decode_nsdu_2 proto. */ +/* 12/20/01 JRB 18 Del clpp_bind functions and bind id args to */ +/* a_unit_data_req & u_a_unit_data_ind. */ +/* 05/10/01 JRB 17 Chg SSEL_LEN from 16 to 4. */ +/* 12/18/00 EJV 16 Added remAr param to a_associate_req for */ +/* Lite over Marben stack (MAP30_ACSE). */ +/* 08/05/99 JRB 15 Add a_get_ev... prototype. */ +/* 07/14/99 JRB 14 Add ACSE Password Authentication stuff. */ +/* 01/28/99 JRB 13 Move cltp_decode_nsdu proto from TP4 to here.*/ +/* 12/04/98 JRB 12 Del "audt_debug_sel". */ +/* Add "loc_mac" to AUDT_APDU. */ +/* 08/13/98 JRB 11 Lint cleanup. */ +/* 08/14/97 JRB 10 Added "tp_type" to PRES_ADDR. */ +/* Del MAX_TSEL_LEN & MAX_NSAP_LEN defines (use */ +/* MAX_TSEL_LEN & MAX_IP_ADDR_LEN in tp4api.h). */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 04/10/97 JRB 09 Chg error defs to use base from "glberror.h".*/ +/* 03/07/97 JRB 08 Add COPP & COSP logmasks for MOSI. */ +/* 02/20/97 JRB 07 Move *_debug_sel & logmasks from acse2log.h */ +/* to acse2usr.h. */ +/* 01/09/97 MDE 06 Allow user to specify destination MAC */ +/* 01/01/97 RKR 05 Added ACSE2USR_INCLUDED and __cplusplus */ +/* 10/04/96 JRB 04 Add adlcAddr to PRES_ADDR for MCGW. */ +/* 08/15/96 JRB 03 Add a_buffers_avail prototype for LEAN_T. */ +/* 04/18/96 JRB 02 Chg a_associate_req return to ST_LONG. */ +/* 03/26/96 MDE 01 Added header, 'REDUCED_STACK' support */ +/************************************************************************/ + +#ifndef ACSE2USR_INCLUDED +#define ACSE2USR_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "asn1defs.h" +#include "acseauth.h" +#include "ssec.h" +#include "clnp_usr.h" +#include "tp4api.h" /* Need TP_TYPE_* defines for "tp_type" values. */ + /* Need MAX_TSEL_LEN & MAX_IP_ADDR_LEN defines. */ + + +/****************************************************************/ +/* Log Control */ +/****************************************************************/ +#define ACSE_LOG_ERR 0x00000001 +#define ACSE_LOG_ENC 0x00000002 +#define ACSE_LOG_DEC 0x00000004 +#define ACSE_LOG_DIB 0x00000008 + +#define COPP_LOG_ERR 0x00000100L +#define COPP_LOG_DEC 0x00001000L +#define COPP_LOG_DEC_HEX 0x00002000L +#define COPP_LOG_ENC 0x00004000L +#define COPP_LOG_ENC_HEX 0x00008000L + +#define COSP_LOG_ERR 0x00010000L +#define COSP_LOG_DEC 0x00100000L +#define COSP_LOG_DEC_HEX 0x00200000L +#define COSP_LOG_ENC 0x00400000L +#define COSP_LOG_ENC_HEX 0x00800000L + + +extern ST_UINT acse_debug_sel; + +/************************************************************************/ +/* Error codes (returned from a_* functions). */ +/* NOTE: Values begin from E_ACSE2 (found in glberror.h). */ +/* NOTE: The exception codes (EX_ACSE_*) do not have separate range. */ +/************************************************************************/ +#define E_ACSE_ENC_ERR 0x3001 +#define E_ACSE_SEND_ERR 0x3002 +#define E_ACSE_INVALID_CONN_ID 0x3003 +#define E_ACSE_INVALID_STATE 0x3004 +#define E_ACSE_INVALID_PARAM 0x3005 +#define E_ACSE_BUFFER_OVERFLOW 0x3006 +#define E_ACSE_MEMORY_ALLOC 0x3007 + +/************************************************************************/ +/* Exception codes (passed to u_a_except or u_cla_except). */ +/* Caused by decode or state problems. */ +/************************************************************************/ +#define EX_ACSE_DECODE 0x3081 +#define EX_ACSE_INVALID_STATE 0x3082 + +/************************************************************************/ +/* Structure definitions. */ +/************************************************************************/ +/* This structure represents the entire Presentation address */ +/* NOTE: Using Fastbyte Presentation and Session, there are no P-Sels */ +/* and S-Sels, so the P-Address is equivalent to the T-Address */ + +#if defined(MMSEASE_MOSI) +#define MAX_PSEL_LEN 16 +#define MAX_SSEL_LEN 16 +#else +#define MAX_PSEL_LEN 4 /* International Std Profile recommends 4*/ +#define MAX_SSEL_LEN 4 /* GOSIP Ver2 recommends len of 2 */ +#endif +/* MAX_TSEL_LEN defined in "tp4api.h" */ +/* MAX_IP_ADDR_LEN defined in "tp4api.h" */ +typedef struct tagPRES_ADDR + { +#if !defined(REDUCED_STACK) + ST_UINT psel_len; + ST_UCHAR psel [MAX_PSEL_LEN]; + ST_UINT ssel_len; + ST_UCHAR ssel [MAX_SSEL_LEN]; + ST_INT tp_type; /* Type of transport: TP_TYPE_TP4 or TP_TYPE_TCP.*/ + ST_UINT tsel_len; + ST_UCHAR tsel [MAX_TSEL_LEN]; + ST_UINT nsap_len; + union + { /* If TP_TYPE_TP4, use "nsap". If TP_TYPE_TCP, use "ip". */ + ST_UCHAR nsap [CLNP_MAX_LEN_NSAP]; /* NSAP OR */ + ST_ULONG ip; /* IP Addr (network byte order) */ + }netAddr; + ST_UINT16 port; +#if defined (MCGW) + ST_UINT16 adlcAddr; +#endif /* defined (MCGW) */ +#else + ST_UINT16 adlcAddr; +#endif + } PRES_ADDR; + +/* This structure is used for any data that must be encoded/decoded */ +/* by the user instead of the ACSE. */ +/* If len == 0, or ptr == NULL, it is assumed there is no data. */ +typedef struct tagBUFFER + { + ST_INT len; /* Length of encoded data. */ + ST_UCHAR *ptr; /* Pointer to encoded data. */ + } BUFFER; + +/* This structure contains AE_TITLE info. */ +typedef struct tagAE_TITLE + { + ST_BOOLEAN AP_title_pres; /* present flag */ + MMS_OBJ_ID AP_title; /* AP title */ + ST_BOOLEAN AE_qual_pres; /* present flag */ + ST_INT32 AE_qual; /* AE qualifier */ + ST_BOOLEAN AP_inv_id_pres; /* present flag */ + ST_INT32 AP_inv_id; /* AP invocation ID */ + ST_BOOLEAN AE_inv_id_pres; /* present flag */ + ST_INT32 AE_inv_id; /* AE invocation ID */ + } AE_TITLE; + +/* This structure is used for the AARQ_APDU. */ +typedef struct tagAARQ_APDU + { + /* The following entries passed to peer in AARQ-apdu.*/ + /* ACSE sets and checks "protocol-version". Must be "version1". */ + ST_BOOLEAN ASO_context_name_pres; + MMS_OBJ_ID ASO_context_name; + AE_TITLE called_ae_title; + AE_TITLE calling_ae_title; + + /* authentication and security */ + ACSE_AUTH_INFO auth_info; + S_SEC_ENCRYPT_CTRL encrypt_ctrl; + + BUFFER user_info; /* User must encode/decode */ + + /* The following entries passed to presentation. */ + /* NOTE: "calling_paddr" ignored by "a_associate_req" function. */ + /* Contains remote addr when "u_a_associate_ind" called. */ + PRES_ADDR calling_paddr; + PRES_ADDR called_paddr; + } AARQ_APDU; + +/* This structure is used for the AUDT_APDU */ +/* NOTE: same as AARQ_APDU except add calling_paddr. */ +typedef struct tagAUDT_APDU + { + /* The following entries passed to peer in AUDT-apdu.*/ + /* ACSE sets and checks "protocol-version". Must be "version1". */ + ST_BOOLEAN ASO_context_name_pres; + MMS_OBJ_ID ASO_context_name; + AE_TITLE called_ae_title; + AE_TITLE calling_ae_title; + BUFFER user_info; /* User must encode/decode */ + + /* The following entries passed to or received from presentation. */ + PRES_ADDR calling_paddr; + PRES_ADDR called_paddr; + + /* User doesn't need to set loc_mac before calling a_unit_data_req. */ + /* Decode process fills in loc_mac before calling u_a_unit_data_ind. */ + ST_UCHAR loc_mac [CLNP_MAX_LEN_MAC]; /* Local MAC addr */ + ST_BOOLEAN rem_mac_valid; /* SD_TRUE if MAC addr valid */ + ST_UCHAR rem_mac [CLNP_MAX_LEN_MAC]; /* Remote MAC addr */ + } AUDT_APDU; + + +/* This structure is used for the AARE_APDU. */ +typedef struct tagAARE_APDU + { + /* ACSE sets and checks "protocol-version". Must be "version1". */ + ST_BOOLEAN ASO_context_name_pres; + MMS_OBJ_ID ASO_context_name; + AE_TITLE responding_ae_title; + ST_INT16 result; + ST_BOOLEAN result_source_diag_pres; + ST_UINT16 result_source; /* Passed as asn1_tag to ASN1 functs */ + ST_INT16 result_diag; + + /* authentication and security */ + ACSE_AUTH_INFO auth_info; + S_SEC_ENCRYPT_CTRL encrypt_ctrl; + + BUFFER user_info; /* User must encode/decode */ + } AARE_APDU; + +/* This structure is used for the RLRQ_APDU. */ +typedef struct tagRLRQ_APDU + { + ST_BOOLEAN reason_pres; + ST_INT16 reason; + BUFFER user_info; /* User must encode/decode */ + } RLRQ_APDU; + +/* This structure is used for the RLRE_APDU. */ +typedef struct tagRLRE_APDU + { + ST_BOOLEAN reason_pres; + ST_INT16 reason; + BUFFER user_info; /* User must encode/decode */ + /* NOTE: With Fastbyte presentation and session, there is no way to */ + /* refuse a release, so the "Result" parameter is assumed to be */ + /* "affirmative", and is therefore not needed in this structure.*/ + } RLRE_APDU; + +/* This structure is used for the ABRT_APDU. */ +typedef struct tagABRT_APDU + { + ST_INT16 source; /* Abort source (0=user, 1=provider) */ + ST_BOOLEAN diagnostic_pres; + ST_ACSE_AUTH diagnostic; /* Abort diagnostic; codes in acseauth.h */ + BUFFER user_info; /* User must encode/decode */ + } ABRT_APDU; + +/* NOTE: the ASO-association-identifier in the ACSE specification is not*/ +/* supported in this implementation. It will not be sent in outgoing */ +/* APDUs and will be ignored in incoming APDUs. */ + +/************************************************************************/ +/* Prototypes */ +/************************************************************************/ +ST_RET copp_initialize (ST_INT max_conns, ST_UINT msg_size); +ST_RET copp_terminate (ST_VOID); +ST_BOOLEAN copp_event (ST_VOID); +#if defined(MAP30_ACSE) +ST_RET copp_bind (ST_LONG user_bind_id, ST_CHAR *loc_ar_name, + ST_INT num_calling, ST_INT num_called); +ST_RET _copp_bind (ST_LONG user_bind_id, ST_CHAR *loc_ar_name, + ST_INT num_calling, ST_INT num_called, + ST_BOOLEAN activate); +#else +ST_RET copp_bind (ST_LONG user_bind_id, PRES_ADDR *pres_addr, + ST_INT sharable, ST_INT max_conns); +#endif /* !defined(MAP30_ACSE) */ +ST_VOID u_copp_bind_cnf (ST_LONG user_bind_id, ST_LONG copp_bind_id, ST_RET result); +ST_RET copp_unbind (ST_LONG copp_bind_id); +ST_VOID u_copp_unbind_cnf (ST_LONG user_bind_id); +ST_RET audt_set_msgsize (ST_UINT len); +#if defined(MAP30_ACSE) +ST_LONG a_associate_req ( + ST_LONG copp_bind_id, /* ACSE's bind ID received in u_copp_bind_cnf*/ + ST_LONG user_conn_id, /* USER's ID for this connection */ + AARQ_APDU *info, /* AARQ_APDU info */ + ST_CHAR *remAr); /* remote AR Name. */ + +ST_LONG a_associate_reqm ( + ST_LONG copp_bind_id, /* ACSE's bind ID received in u_copp_bind_cnf*/ + ST_LONG user_conn_id, /* USER's ID for this connection */ + AARQ_APDU *aarq_apdu, /* AARQ_APDU info */ + ST_CHAR *locAr, /* local AR Name. */ + ST_CHAR *remAr); /* remote AR Name. */ +#else +ST_LONG a_associate_req ( + ST_LONG copp_bind_id, /* ACSE's bind ID received in u_copp_bind_cnf*/ + ST_LONG user_conn_id, /* USER's ID for this connection */ + AARQ_APDU *info); /* AARQ_APDU info. */ +#endif /* !defined(MAP30_ACSE) */ +ST_VOID u_a_associate_ind ( + ST_LONG user_bind_id, /* USER's Bind ID passed to copp_bind */ + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + AARQ_APDU *info); /* AARQ_APDU info. */ +ST_RET a_associate_rsp ( + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + ST_LONG user_conn_id, /* USER's ID for this connection */ + AARE_APDU *info); /* AARE_APDU info. */ +ST_VOID u_a_associate_cnf ( + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + ST_LONG user_conn_id, /* USER's ID for this connection */ + AARE_APDU *info); /* AARE_APDU info. */ +ST_RET a_release_req ( + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + RLRQ_APDU *info); /* RLRQ_APDU info. */ +ST_VOID u_a_release_ind ( + ST_LONG user_conn_id, /* USER's ID for this connection */ + RLRQ_APDU *info); /* RLRQ_APDU info. */ +ST_RET a_release_rsp ( + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + RLRE_APDU *info); /* RLRE_APDU info. */ +ST_VOID u_a_release_cnf ( + ST_LONG user_conn_id, /* user's ID for this connection */ + RLRE_APDU *info); /* RLRE_APDU info. */ +ST_RET a_abort_req ( + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + ABRT_APDU *info); /* ABORT request info. */ +ST_VOID u_a_abort_ind ( + ST_LONG user_conn_id, /* USER's ID for this connection */ + ABRT_APDU *info); /* ABORT request info. */ +ST_RET a_data_req ( + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + ST_UINT data_len, + ST_UCHAR *data); +ST_VOID u_a_data_ind ( + ST_LONG user_conn_id, /* USER's ID for this connection */ + ST_UINT data_len, + ST_UCHAR *data); +ST_INT a_buffers_avail ( + ST_LONG acse_conn_id); /* ACSE's ID for this connection */ +ST_VOID u_a_except ( + ST_LONG user_conn_id, /* USER's ID for this connection */ + ST_INT code, /* See EX_ACSE_* defines */ + ST_CHAR *filename, /* Source code file name */ + ST_INT line); /* source code line number */ +ST_VOID u_cla_except ( + ST_LONG user_bind_id, /* USER's ID for this bind */ + ST_INT code, /* See EX_ACSE_* defines */ + ST_CHAR *filename, /* Source code file name */ + ST_INT line); /* source code line number */ + +ST_RET clpp_initialize (ST_VOID); +ST_RET clpp_terminate (ST_VOID); +ST_RET a_unit_data_req ( + AUDT_APDU *info); /* AUDT_APDU info. */ +ST_VOID u_a_unit_data_ind ( + AUDT_APDU *info); /* AUDT_APDU info. */ +ST_BOOLEAN clpp_event (ST_VOID); + +ST_VOID cltp_decode_nsdu (N_UNITDATA *n_unitdata); +ST_RET cltp_decode_nsdu_2 (N_UNITDATA *pNudt, AUDT_APDU *pAudt); + +/************************************************************************/ +/* Address resolution utility functions. */ +/************************************************************************/ +ST_UCHAR *a_get_rem_nsap (ST_LONG acse_conn_id); +ST_ULONG a_get_rem_ip_addr (ST_LONG acse_conn_id); + +/************************************************************************/ +/* Miscellaneous functions */ +/************************************************************************/ +ST_EVENT_SEM a_get_event_handles (ST_INT *pNumEntries); +int *a_get_event_handles_unix (ST_INT *pNumEntries); /* for UNIX-like systems*/ +ST_RET a_get_chan (ST_LONG acse_conn_id, ST_INT *chan_out); + + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* ACSE2USR_INCLUDED */ +/************************************************************************/ + diff --git a/mmslib/inc/acseauth.h b/mmslib/inc/acseauth.h new file mode 100644 index 0000000..0d600da --- /dev/null +++ b/mmslib/inc/acseauth.h @@ -0,0 +1,120 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-2004, All Rights Reserved */ +/* */ +/* MODULE NAME : acseauth.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* ACSE Authentication header file. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/05/04 EJV 07 Added MACE_MECH_ID and PASWORD_MECH_ID defs. */ +/* 02/04/04 EJV 06 Removed extern maceMechId. */ +/* 08/20/03 EJV 05 Added extern maceMechId. */ +/* 07/08/03 EJV 04 Del old password auth (OBSOLETE_ACSE_AUTH) */ +/* 03/19/03 MDE 03 Added ACSE_AUTH_MECH_MACE_CERT */ +/* 03/13/03 EJV 02 Added asn1r.h. */ +/* 09/30/02 ASK 01 Created */ +/************************************************************************/ + +#ifndef ACSEAUTH_INCLUDED +#define ACSEAUTH_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "asn1r.h" /* for MMS_OBJ_ID */ + +/************************************************************************/ +/* New Authentication stuff */ +/************************************************************************/ +/*#define ACSE_MAX_LEN_PASSWORD 16*/ +/*renxiaobao mod*/ +#define ACSE_MAX_LEN_PASSWORD 32 + +typedef ST_INT16 ST_ACSE_AUTH; + +/* Authentication mechanisms MMS_OBJ_ID */ +#define PASS_MECH_ID {4, {2 ,2 ,3 ,1 }} + +#define MACE_MECH_ID \ + { 8, /* num_comps */ \ + { /* comps */ \ + 1, /* ??? */ \ + 0, /* ??? */ \ + 840, /* iso member-body usa */ \ + 0, /* ansi-t1-259-1997 */ \ + 1, /* stase */ \ + 0, /* stase-authentication value */ \ + 1, /* abstractSyntax */ \ + 1 /* version */ \ + } \ + } + +/* The ACSE user shall return one of the falling codes once they have */ +/* taken a look at the partner's ACSE_AUTH_INFO structure. */ + +/* These return codes map to the ABRT-diagnostic of the Abort PDU. */ +/* Returning any of these will result in an abort PDU being sent with */ +/* the specified diagnostic code. */ +#define ACSE_AUTH_SUCCESS 0 +#define ACSE_DIAG_NO_REASON 1 +#define ACSE_DIAG_PROTOCOL_ERROR 2 +#define ACSE_DIAG_AUTH_MECH_NAME_NOT_RECOGNIZED 3 +#define ACSE_DIAG_AUTH_MECH_NAME_REQUIRED 4 +#define ACSE_DIAG_AUTH_FAILURE 5 +#define ACSE_DIAG_AUTH_REQUIRED 6 + +/* Mechanism types */ +#define ACSE_AUTH_MECH_PASSWORD 0 +#define ACSE_AUTH_MECH_MACE_CERT 1 +#define ACSE_AUTH_MECH_OTHER 2 + +/* This structure is used for any mechanism data that must be */ +/* encoded/decoded by the user instead of the ACSE. */ +typedef struct + { + ST_INT len; /* Length of encoded data. */ + ST_UCHAR *ptr; /* Pointer to encoded data. */ + ST_UCHAR *buf; /* User buffer (chk_free'd if != NULL) */ + } USR_AUTH_BUFFER; + + +/* User-Supplied Authentication Structure */ +typedef struct + { + ST_BOOLEAN auth_pres; /* If this structure is filled out */ + ST_INT mech_type; /* One of the mechanism types, defined above */ + + union + { + struct + { + ST_CHAR password[ACSE_MAX_LEN_PASSWORD + 1]; + } pw_auth; + struct + { + MMS_OBJ_ID mech_id; /* User must set to desired id */ + USR_AUTH_BUFFER auth_value; /* User must encode/decode ASN.1 */ + } other_auth; + } u; + + } ACSE_AUTH_INFO; + + + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* ACSEAUTH_INCLUDED */ +/************************************************************************/ diff --git a/mmslib/inc/adlc.h b/mmslib/inc/adlc.h new file mode 100644 index 0000000..98d2932 --- /dev/null +++ b/mmslib/inc/adlc.h @@ -0,0 +1,1021 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-2002, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : adlc.h */ +/* PRODUCT(S) : ADLC */ +/* */ +/* MODULE DESCRIPTION : */ +/* Function prototypes and commands definations as defined in */ +/* ISO/IEC 4335 for frame format */ +/* Note : For ADLC context packet refers to information passing with */ +/* stack while frame refers to information passing with Serial Manager */ +/* */ +/* This module can be divided into five parts */ +/* 1. First part deals with all the numeric defines and command defn */ +/* as in ISO specs */ +/* 2. This part deals with the defination of the data structures used */ +/* 3. This part has function like macros used to get and set various */ +/* fields */ +/* 4. This has the declaration of all the global variables as extern. */ +/* All the global variables are declared in adlc_var.c */ +/* 5. This part has the prototypes of global functions shared between */ +/* modules. All the functions are put separately according to the */ +/* module it belongs to */ +/* Note : For ADLC context packet refers to information passing with */ +/* stack while frame refers to information passing with Serial Manager */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/24/02 KCR 35 Added rdThreadError handling semaphore */ +/* 09/22/02 KCR 34 Added paranthesis to macros */ +/* 06/15/01 JRB 33 ipcChk* macros call chk_*, not x_chk_*. */ +/* 03/03/00 KCR 32 Exit Thread using events not TerminateThread() */ +/* 10/01/99 NAV 31 Added more SD_CONST modifiers */ +/* 09/13/99 MDE 30 Added SD_CONST modifiers */ +/* 04/20/98 IKE 29 Moved u_smp_record_time in Serial Manager */ +/* 03/05/98 IKE 28 Added Critical Sections to protect Adlc Data */ +/* Removed adlcIpcxxx functions */ +/* 02/04/98 IKE 27 Added deleteUIFramesFromTxList to fix bug */ +/* 10/20/97 IKE 26 Added addToListTime for Link Manager */ +/* 09/23/97 IKE 25 Added adlcExtWritePacket for define UCA_SMP */ +/* 09/18/97 IKE 24 Added telephone support */ +/* 07/16/97 IKE 23 Added device statistics and device filt log */ +/* 06/12/97 IKE 22 Made ADLC protocol transaction oriented */ +/* 05/12/97 IKE 21 Changed to MMSEASE 7.0 Data Types */ +/* 02/24/96 IKE 20 Removed #ifdef PLAIN_DOS and used ADLC_LM */ +/* define for ipc specific code */ +/* CFG_PORT also for DOS so multiple ports can */ +/* be initialized in dos platform */ +/* 02/03/97 IKE 19 adlcCfg per port basis */ +/* 01/23/97 IKE 18 Added txRxModeCounter for proper behaviour */ +/* of turnaround timers */ +/* 01/17/97 IKE 17 Added defn of initSiscoUtilGlbVarsForAdlc */ +/* and addToCfgPort */ +/* 12/03/96 IKE 16 WIN32 Support, header files cleanup */ +/* Added adlc_sm.h, some func prototypes for */ +/* adlc_tst.c */ +/* 11/15/96 IKE 15 Added adlcInitGlbVars */ +/* 11/06/96 IKE 14 Changed C++ style comments to C style */ +/* comments to make it more platform independent*/ +/* 10/28/96 KCR 13 Put ipcChkxxx macros to replace chk_xxx */ +/* 09/30/96 IKE 12 Moved adlc_stats from adlc.h to adlc_usr.h */ +/* so other apps could reference it */ +/* Added communicationMedia, put ifdef MASTER */ +/* in ADLC_CFG struct for members that were used*/ +/* for master only, added reconfigure option */ +/* 09/17/96 IKE 11 Added some struct members to ADLC_CFG_INFO */ +/* and ADLC_PORT_INFO structure */ +/* 08/22/96 IKE 10 Support for contention avoidance */ +/* Changed > to >= in CHECK_TIMEOUT macro */ +/* 08/16/96 IKE 09 Added rxMFramesList, vR and infoBufLen in */ +/* port struct (to make UI into INFO), added */ +/* turnaroundtime in cfg and device struct, */ +/* changed UPDATE_TIMEOUT */ +/* 08/05/96 IKE 08 Added connectAll to device struct, mode to */ +/* port struct and radioDelayTime to cfg struct */ +/* 07/17/96 IKE 07 Removed some lint and C6.00 warnings by type */ +/* casting to ST_UCHAR in some macros */ +/* 06/20/96 KCR 06 Increased MAX_ADLC_FRAME_LEN from 256 to 2048*/ +/* 06/18/96 IKE 05 Changed the type of configured timeout into */ +/* ST_DOUBLE. Added stackTaskId for DOS platform. */ +/* Changed time related macros to functions and */ +/* moved to module adlc_tm.c */ +/* 06/11/96 IKE 04 Added cnp_usr.h, frame timeout and SM_PUT */ +/* 05/22/96 IKE 03 Added defn for three types of run mode */ +/* Modified xxx_ADDR_FIELD_OFFSET. Put suffix */ +/* "ADLC_S" for link states for the ADLC */ +/* connection state machine */ +/* Added eventList and taskList */ +/* Added prototypes of added functions */ +/* 04/04/96 rkr 02 Cleanup */ +/* 07/18/95 IKE 01 Initial release. */ +/************************************************************************/ + +#ifndef _ADLC_H_ +#define _ADLC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gen_list.h" +#include "adlc_usr.h" +#if defined(ADLC_LM) +#include "adlc_ipc.h" +#endif +#include "adlc_log.h" +#include "adlc_sm.h" + +#if defined(ADLC_TESTING) +#include +#define ADLC_ASSERT(f) assert(f); +#else + #define ADLC_ASSERT(f) +#endif + +#if !defined(ADLC_LM) +/* At one time these macros called "x_chk_*" for DEBUG or */ +/* nonDEBUG, to be sure that the semaphore was locked. */ +/* Now "chk_*" always lock the sempaphore, so use them. */ +#define ipcChkCalloc(x,y) chk_calloc (x,y) +#define ipcChkMalloc(x) chk_malloc (x) +#define ipcChkFree(x) chk_free (x) +#endif + +#ifdef CNP +#include "cnp_usr.h" +#endif + +/************************************************************************/ +/* Constants related to configuration */ +/************************************************************************/ +#define MAX_ADLC_REQS 10 +#define MAX_ADLC_FRAME_LEN 2048 /* 2048 = 2035 + 11 + 2 */ + +/* Following are the run mode for ADLC Master */ +#define POLLED_MODE 0 +#define ENHANCED_POLLED_MODE 1 +#define CONTENTION_MODE 2 + +/* Following are the communication media for ADLC */ +#define CABLE_MEDIA 0 +#define RADIO_MEDIA 1 + +#define FRAME_FORMAT_TYPE3 0x9 /* used for polling */ +#define FRAME_FORMAT_TYPE4 0xA /* used for contention */ +#define MIN_ADLC_FRAME_LEN 11 /* Supervisory and Unnumbered */ +#define MIN_INFO_FRAME_LEN 13 + +#define SOF_FIELD_LEN 1 +#define SOF_FIELD_OFFSET 0 + +#define FORMAT_FIELD_LEN 2 +#define FORMAT_FIELD_OFFSET 1 + +#define DST_ADDR_FIELD_LEN 2 +#define DST_ADDR_FIELD_OFFSET 3 + +#define SRC_ADDR_FIELD_LEN 2 +#define SRC_ADDR_FIELD_OFFSET 5 + +#define CTRL_FILED_LEN 1 +#define CTRL_FIELD_OFFSET 7 + +#define CRC_FIELD_LEN 2 +#define CRC_FIELD_OFFSET 8 + +#define INFO_FIELD_OFFSET 10 + +#define EOF_FIELD_LEN 1 + + +#define PF_BIT 0x10 /* Poll / Final Bit */ +#define INFORMATION_FORMAT 0x00 /* last bit set to zero */ +#define INFO 0x00 /* Information */ + +#define SUPERVISORY_FORMAT 0x01 /* last bit = 1, 2nd last = 0 */ +#define RR 0x01 /* Receive Ready */ +#define RNR 0x05 /* Receive Not Ready */ +#define REJ 0x09 /* Reject */ + +#define UNNUMBERED_FORMAT 0x03 /* last two bits are set */ +#define UI 0x03 /* Unnumbered Information */ +#define SNRM 0x83 /* Set Normal Response */ +#define UA 0x63 /* Unnumbered Acknowledgment */ +#define DISC 0x43 /* Disconnect */ +#define RD 0x43 /* Request Disconnect */ +#define DM 0x0F /* Disconnect Mode */ +#define FRMR 0x87 /* Frame Reject */ + +/************************************************************************/ +/* flag attributes used when using function resetConnection */ +/************************************************************************/ +#define ADLC_DELETE_CON 1 +#define ADLC_RESET_ONLY 2 + +#if !defined(ADLC_LM) +/************************************************************************/ +/* used for global variable stackTaskId. We need to know in dos which */ +/* stack is linked to with ADLC to do different actions for different */ +/* stack */ +/* LM has this capability that it can run over both stacks at the same */ +/* time. and it will know by mapping the local address with task id */ +/************************************************************************/ +#define RLI_TASK_ID_RSGW 4 +#define RLI_TASK_ID_TRIM7 7 +#endif /* !ADLC_LM */ + +/************************************************************************/ +/* ADLC_CFG_INFO */ +/* */ +/************************************************************************/ +typedef struct tagAdlcCfgInfo + { + ST_INT modulus; + ST_INT frameLen; + ST_INT maxAdlcReqs; + ST_INT runMode; + ST_INT communicationMedia; + ST_INT retries; + ST_UCHAR sof; + ST_UCHAR eof; + ST_DOUBLE responseTimeout; /* refers to responseTimeout in port struct */ + ST_DOUBLE frameTimeout; /* refers to frameTimeout in port struct */ + ST_DOUBLE signalTimeout; /* refers to signalTimeout in port struct */ + ST_DOUBLE radioDekeyDelay; /* refers to signalTimeout in port struct */ + ST_DOUBLE radioStartOfTxDelay; /* refers to signalTimeout in port struct */ + ST_INT preambleLen; +#if defined(ADLC_MASTER) + ST_DOUBLE maxConnectRetryTimeout; + ST_DOUBLE deviceTurnaroundTime; /* refers to turnaround time in dev struct */ + ST_DOUBLE portTurnaroundTime; /* refers to turnaround time in port struct */ + ST_INT portUsage; +#endif /* ADLC_MASTER */ + } ADLC_CFG_INFO; + +/************************************************************************/ +/* ADLC_FRAME */ +/* */ +/* The following structure is used to read and write from the lower */ +/* layer (Serial Manager) */ +/************************************************************************/ +/* MMSOP_STATUS defines */ +#define STAT_STANDBY 0 +#define STAT_PROGRESS 1 +#define STAT_NACKED 2 +#define STAT_ACKED 3 + +typedef struct tagAdlcFrame + { + DBL_LNK p; /* required for link list operations */ + struct tagAdlcConInfo *cptr; /* Connection which it belongs to */ + ST_INT status; /* one of the above */ + ST_UCHAR cmd; + union + { + ST_UCHAR *infoBuf; + ST_UCHAR *redrBuf; + ST_UCHAR suprBuf[MIN_ADLC_FRAME_LEN]; + ST_UCHAR unumBuf[MIN_ADLC_FRAME_LEN]; + }u; + ST_INT infoLen; /* For info frame it is used for len of INFO msg */ + ST_INT frameLen; /* Total length of the frame including headers and trailers */ +#if defined(ADLC_LM) + DOUBLE addToListTime; +#endif + } ADLC_FRAME; + +/************************************************************************/ +/* ADLC_REQ */ +/* The following structure is to store one complete LSDU INFO */ +/* frame received from user application (Stack) */ +/************************************************************************/ +typedef struct tagAdlcReq + { + DBL_LNK p; /* required for link list operations */ +#if defined(ADLC_LM) + RLI_IPC_HDR hdr; /* IPC info including semaphore */ +#endif + struct tagAdlcConInfo *cptr; /* Connection which it belongs to */ + ADLC_FRAME *txIFramesList; /* Head to the segments of LSDU (small frames) */ + ST_ULONG usr1; /* user data - from original ADLC_CMD */ +#if defined(UCA_SMP) + ADLC_FRAME *txUIFramesList; /* Head to the segments of LSDU (small frames) */ + ST_LONG userId; +#endif + } ADLC_REQ; + +/************************************************************************/ +/* ADLC_CON_INFO */ +/* */ +/* ADLC connection information based on (Dn,Nn) where Dn represents */ +/* a device and Nn represents an OSI node */ +/************************************************************************/ +/* State Machine Design per connection for "state" */ +#define ADLC_S_DISCONNECT_PHASE 0 /* setting up data link */ +#define ADLC_S_LINK_DISCONNECT 1 /* setting up data link */ +#define ADLC_S_LINK_SETUP 2 /* setting up data link */ +#define ADLC_S_NORMAL 3 /* information transfer */ +#define ADLC_S_REMOTE_BUSY 4 /* information transfer */ +#define ADLC_S_SEND_REJECT 5 /* information transfer */ +#define ADLC_S_FRAME_REJECT 6 /* for slave only */ +#define ADLC_S_RESET 7 /* for slave only */ + +typedef struct tagAdlcConInfo + { + DBL_LNK p; /* required for link list operations */ + ST_UINT16 masterAddr; /* ISO node address */ + ST_INT txRxMode; /* TX_MODE or RX_MODE */ + struct tagAdlcDevInfo *dptr; /* ADLC device structure pointer */ + struct tagAdlcPortInfo *pptr; /* port which it belongs to */ + ST_INT state; /* Connection state defined above */ + ST_UCHAR vR; /* Receive State Variable */ + ST_UCHAR vS; /* Send State Variable */ + ST_UCHAR sendCount; /* How many frames we have sent */ + ST_INT infoBufLen; /* Length of info message for rxIFramesList */ + ST_INT txAdlcReqCount; /* How many write request ?? */ + ST_INT retries; /* How many retries are allowed */ + ADLC_FRAME *rxIFramesList; /* Info frames which are not complete LSDU */ +#if defined(ADLC_MASTER) + ST_DOUBLE connectRetryTimeout; /* To store the time when we will try to reconnect */ +#endif +#if defined(UCA_SMP) + ST_INT txExtAdlcReqCount; /* How many write request ?? */ + ADLC_FRAME *rxUIFramesList; /* Info frames which are not complete LSDU */ + ST_INT extInfoBufLen; /* Length of ui message for rxUIFramesList */ +#endif + } ADLC_CON_INFO; +/************************************************************************/ +/* ADLC_DEV_INFO */ +/* */ +/* Tracking structure for device. This is the main entry point to */ +/* reference to almost any device related info. This will be allocated */ +/* at the startup when reading from configuration file */ +/************************************************************************/ +#define MAX_DEV_NAME_SIZE 80 + +/* Mode could be one of the following */ +/* ADLC slave will only have two modes TX_MODE and RX_MODE */ +/* Slave will initially be at RX_MODE. It will go to TX_MODE when he */ +/* sees the P/F bit and after transmission it will go back to RX_MODE */ +/* In case of timeout it will remain in RX_MODE */ +/* ADLC master will initially be in TX_MODE. It will go in RX_MODE only */ +/* when it expects the response back from the slave. In case of timeout */ +/* it will go back to TX_MODE. */ +#define TX_MODE 0 +#define RX_MODE 1 + +typedef struct tagAdlcDevInfo + { + DBL_LNK p; /* required for link list operations */ + ST_CHAR name[MAX_DEV_NAME_SIZE+1]; /* storage for device name */ + ST_UINT16 address; /* Device's 16-bit address */ + ST_INT txRxMode; /* TX_MODE or RX_MODE */ + struct tagAdlcPortInfo *pptr; /* port which it belongs to */ + ADLC_CON_INFO *conList; +#if defined(ADLC_MASTER) + ST_INT pollGroup; /* 1 to MAX_POLL_GROUPS */ + ST_BOOLEAN connectAll; /* flag only used in adlcConnectAll() */ + ST_DOUBLE turnaroundTime; +#if defined(ADLC_LM) + ST_INT txRxModeCounter; /* for proper behaviour of turnaround timer */ +#endif /* ADLC_LM */ +#endif /* ADLC_MASTER */ +#if defined(ADLC_LM) + ADLC_DEV_STATS devStats; +#endif /* ADLC_LM */ + } ADLC_DEV_INFO; + +/************************************************************************/ +/* ADLC_PORT_INFO */ +/* */ +/* Tracking structure for network */ +/* will be allocated at the startup when reading from configuration file*/ +/* */ +/* txRxMode : is either TX_MODE or RX_MODE. */ +/* For master It is used in code in the following three ways */ +/* pptr->txRxMode = RX_MODE when p/f bit given to a slave */ +/* pptr->txRxMode = TX_MODE when port turnaround time or timeout has */ +/* elapsed */ +/* For slave It is used in code in the following three ways */ +/* pptr->txRxMode = TX_MODE when p/f is received from master */ +/* pptr->txRxMode = RX_MODE when p/f bit given from slave */ +/* if pptr->txRxMode == TX_MODE to see if we got p/f from master */ +/* runMode : is POLLED_MODE, ENHANCED_POLLED_MODE or CONTENTION_MODE */ +/* The idea is when runMode is configured in CONTENTION_MODE, then */ +/* pptr->runMode can change dynamically else pptr->runMode will remain */ +/* same as configured runMode (i.e. ADLC_RUN_MODE(pptr)) */ +/* For slave it is used in the following ways */ +/* pptr->runMode = POLLED_MODE when p/f is received from master */ +/* pptr->runMode = CONTENTION_MODE when p/f bit given from slave */ +/* if pptr->runMode == CONTENTION_MODE to encode the frame format */ +/* For Master it is used in the following ways */ +/* pptr->runMode = ENHANCED_POLLED_MODE when dcd is high most of times */ +/* pptr->runMode = CONTENTION_MODE when RR frames are more than INFO */ +/* if pptr->runMode == CONTENTION txStateService is called else */ +/* txService is called */ +/************************************************************************/ +/* States for getting the frame from the port used in "rxState" */ +#define STATE_WAIT_SOF 0 +#define STATE_WAIT_LEN 1 +#define STATE_WAIT_CRC 2 +#define STATE_WAIT_DATA 3 +#define STATE_WAIT_EOF 4 + +/* States for slave tranmit algorithm used in "signalState" */ +#define SL_TX_STATE_IDLE 0 +#define SL_TX_STATE_PF_RCVD 1 +#define SL_TX_STATE_WAIT_FOR_CTS_HIGH 2 +#define SL_TX_STATE_START_OF_TX_DELAY 3 +#define SL_TX_STATE_OK_TO_TX 4 +#define SL_TX_STATE_WAIT_FOR_TX_BUF_EMPTY 5 +#define SL_TX_STATE_DEKEY_DELAY 6 +#define SL_TX_STATE_WAIT_FOR_CTS_LOW 7 +#define SL_TX_STATE_UNSOL_TX 8 +#define SL_TX_STATE_WAIT_FOR_LINK 9 +#define SL_TX_STATE_START_OF_UNSOL_TX_DELAY 10 +#define SL_TX_STATE_OK_TO_UNSOL_TX 11 + +/*States for master tranmit in contention used in "signalState" */ +#define MA_TX_STATE_IDLE 0 +#define MA_TX_STATE_WAIT_FOR_CTS_HIGH 1 +#define MA_TX_STATE_WAIT_FOR_DCD_LOW 2 +#define MA_TX_STATE_OK_TO_TX 3 +#define MA_TX_STATE_WAIT_FOR_TX_BUF_EMPTY 4 +#define MA_TX_STATE_DEKEY_DELAY 5 +#define MA_TX_STATE_WAIT_FOR_CTS_LOW 6 +#define MA_TX_STATE_WAIT_FOR_CTS_HIGH_DCD_LOW 7 +typedef struct tagAdlcPortInfo + { + DBL_LNK p; /* required for link list operations */ + ST_INT port; /* digiboard port ID */ + ST_INT rxState; /* receive state */ + ST_UCHAR *rxBuf; + ST_UINT rxLen; + ADLC_CON_INFO *outstandingCptr; /* At one time only one con. have P/F set */ + ADLC_DEV_INFO *devList; /* linked list of devices associated with this port */ + ADLC_REQ *txAdlcReqList; /* linked list of write packet list from stack */ + ADLC_FRAME *txUFramesList; /* linked list of unnumbered frames */ + ADLC_FRAME *txSFramesList; /* linked list of supervisory frames */ + ADLC_FRAME *txMFramesList; /* linked list of multicast frames to tx */ + ADLC_FRAME *rxMFramesList; /* linked list of multicast frames to rx not complete LSDU */ + ST_UCHAR vR; /* receive state variable for multicast frames */ + ST_INT infoBufLen; /* Length of info message for rxMFramesList */ + ST_DOUBLE responseTimeout; /* The time request with P/F set was sent */ + ST_INT signalState; /* used for transmit algorithm */ + ST_DOUBLE signalTimeout; /* used for transmit algorithm */ + ST_INT txRxMode; /* TX_MODE or RX_MODE */ + ST_INT runMode; /* POLLED_MODE, ENHANCED_POLLED_MODE or CONTENTION_MODE */ + ADLC_CFG_INFO adlcCfg; +#if defined(ADLC_MASTER) + ADLC_FRAME *txRFramesList; /* linked list of redirect frames */ + ST_DOUBLE turnaroundTime; + ST_ULONG rxInfo; /* Received INFO frames used for switching modes*/ + ST_ULONG rxRr; /* Received RR frames used for switching modes*/ + ST_ULONG txInfo; /* Transmitted INFO frames used for transmit algorithm */ + ST_ULONG txRr; /* Transmitted RR frames used for transmit algorithm */ + ST_BOOLEAN bTxRrFlag; /* should RR have higher priority than INFO ? */ + ST_DOUBLE lastSnrmTime; /* the recorded time when last snrm was sent */ + ST_INT prQueArray[12]; /* array of int which will store priority order */ +#endif +#if defined(ADLC_LM) + HEV txDoneSem; /* sem to wait on the sm to be waited */ + HEV frameArrivalSem; /* sem to wait for frame to rx */ + HEV frameInListSem; /* sem to wait for frame to tx */ + HEV rdThreadErrSem; /* sem to clean up from read thread error */ + ST_BOOLEAN bPortBusy; /* if true - tx is pending */ +#if defined(ADLC_MASTER) + HTIMER hTxStateTimer; /* used in txStateService to drive state mach */ + ST_INT txRxModeCounter; /* for proper behaviour of turnaround timer */ +#endif /* ADLC_MASTER */ +#endif /* ADLC_LM */ +#if !defined(ADLC_LM) + ST_DOUBLE frameTimeout; +#endif +#if defined(UCA_SMP) + ADLC_REQ *txExtAdlcReqList; /* linked list of ext write packet list from stack */ + ST_CHAR recTime[SMP_SIZE_OF_REC_TIME]; /* buffer to hold time stamp */ +#endif + } ADLC_PORT_INFO; + +#if defined(ADLC_MASTER) +/************************************************************************/ +/* POLLED_DEV */ +/* */ +/* Link Manager Polling Structure */ +/************************************************************************/ + +typedef struct tagPolledDevices + { + DBL_LNK l; /* gen list link */ + ADLC_DEV_INFO *dptr; /* pointer to device structure */ + ST_BOOLEAN bSuspendPolling; /* don't poll this one for a while */ + } POLLED_DEV; + +/************************************************************************/ +/* POLL_GROUP */ +/* */ +/************************************************************************/ +#define FIRST_POLL_GROUP 1 +#define MAX_POLL_GROUPS 3 + +/* assume that pollGrpID's start at 1 and go up to MAX_POLL_GROUPS */ +/* assume that poll group 1 is polled most frequently and poll group */ +/* MAX_POLL_GROUPS is polled least frequently. */ +/* when requested to change the poll rate for a device, change the poll */ +/* group for the device - increment poll group to decrease polling or */ +/* decrement poll group to increase poll frequency */ + +typedef struct tagPollGroup + { + DBL_LNK l; /* gen list link */ + ST_INT pollGrpID; /* a unique int 1 to MAX_POLL_GROUPS */ + ST_DOUBLE pollRate; /* in m seconds from config file */ + POLLED_DEV *pollDevList; /* a linked list of devices to poll */ +#if !defined(ADLC_LM) + ST_DOUBLE pollTime; /* To store the time of last poll */ +#endif +#if defined(ADLC_LM) + HTIMER hTimer; /* used in MuxWaitSem to trigger poll */ +#endif + } POLL_GROUP; + +#endif /* ADLC_MASTER */ + +#if defined(ADLC_LM) +/************************************************************************/ +/* ADLC_TASK_INFO */ +/* */ +/************************************************************************/ +typedef struct tagAdlcTaskInfo + { + DBL_LNK l; /* gen list link */ + ST_UINT16 localAddr; + HQUEUE qHandle; + ST_INT taskId; +/* PID pid; */ + } ADLC_TASK_INFO; + +/************************************************************************/ +/* ADLC_FILTER_DEV_LOG_INFO */ +/* */ +/************************************************************************/ +typedef struct tagAdlcFilterDevLogInfo + { + ST_UINT16 address; + ST_BOOLEAN bFilter; + ST_ULONG saveIoLogMask; + } ADLC_FILTER_DEV_LOG_INFO; + +#endif /* ADLC_LM */ + +#if !defined(ADLC_LM) +/************************************************************************/ +/* ADLC_EVENT_INFO */ +/* */ +/************************************************************************/ +typedef struct tagAdlcEventInfo + { + DBL_LNK l; /* gen list link */ + ST_INT adlcEventOp; + ST_INT adlcRetCode; + ST_VOID *adlcEventCb; + } ADLC_EVENT_INFO; +#endif +/************************************************************************/ +/* Function like macros to get and set various fields */ +/************************************************************************/ +/* This macro gets the frame format from the frame */ +#define FRAME_FORMAT_GET(frame) ((frame[1] << 8) | (frame[2])) + +/* This macro gets the length of the frame from the frame */ +#define FRAME_LEN_GET(frame) (((frame[1] << 8) | (frame[2])) & 0x07FF) + +/* This macro sets the length of the frame in the frame format field */ +#define FRAME_LEN_SET(x,r) (x = ((x) & 0xF800) | ((r) & 0x07FF)) + +/* This macro gets the type of the frame from the frame */ +#define FRAME_TYPE_GET(frame) (ST_UCHAR) (frame[1] >> 4) + +/* This macro sets the type of the frame in the frame format field */ +#define FRAME_TYPE_SET(x,y) (x = ((x) & 0x0FFF) | ((y) << 12)) + +/* This macro gets the eos bit from the frame */ +#define EOS_GET(frame) (frame[1] & 0x08) + +/* This macro sets the eos in the frame format field */ +#define EOS_SET(x) (x = ((x) & 0xF7FF)) + +/* This macro gets the destination address from the frame */ +#define DST_ADDR_GET(frame) (ST_UINT16) (frame[3] << 8 | frame[4]) + +/* This macro gets the source address from the frame */ +#define SRC_ADDR_GET(frame) (ST_UINT16) (frame[5] << 8 | frame[6]) + +/* This macro gets the device address from the receing frame */ +#if defined(ADLC_MASTER) +#define DEV_ADDR_GET(frame) SRC_ADDR_GET(frame) +#endif +#if defined(ADLC_SLAVE) +#define DEV_ADDR_GET(frame) DST_ADDR_GET(frame) +#endif + +/* This macro gets the control byte from the frame */ +#define CTRL_BYTE_GET(frame) (frame[7]) + +/* This macro gets the Poll Final Bit from the control byte */ +#define PF_GET(x) ((x) & 0x10) /* Poll Final Bit get */ + +/* This macros tells to have a poll/final bit depending on frame type */ +#define PF_DECIDE(frameType) (frameType == FRAME_FORMAT_TYPE3 ? PF_BIT : 0x0) + +/* This macro sets the Poll Final Bit in the control byte */ +#define PF_SET(x) (x = (x) | (ST_UCHAR) 0x10) /* Poll Final Bit set */ + +/* These get the code from the control byte including the format type */ +#define UNUM_CODE_GET(x) (ST_UCHAR) ((x) & 0xEF) +#define SUPR_CODE_GET(x) (ST_UCHAR) ((x) & 0x0F) +#define INFO_CODE_GET(x) (ST_UCHAR) ((x) & 0x01) + + +/* These macros get the N(R) and N(S) in an info command. */ +#define INFO_NR_GET(x) (ST_UCHAR) (((x) & 0xE0) >> 5) +#define INFO_NS_GET(x) (ST_UCHAR) (((x) & 0x0E) >> 1) + +/* These macros alter the N(R) and N(S) in an info command. */ +#define INFO_NS_SET(x,r) (x = (x) | (ST_UCHAR) ((r) << 1)) +#define INFO_NR_SET(x,r) (x = (x) | (ST_UCHAR) ((r) << 5)) + +/* This macro gets the N(R) in a supervisory command. */ +#define SUPR_NR_GET(x) (ST_UCHAR) (((x) & 0xE0) >> 5) + +/* This macro alters the N(R) in a supervisory command. */ +#define SUPR_NR_SET(x,r) (x = (x) | (ST_UCHAR) ((r) << 5)) + +/* This macro gets the crc from the frame */ +#define FRAME_CRC_GET(frame,offset) ((frame[offset] << 8) | (frame[offset + 1])) + + +/* This macro rotates the bytes in unsigned int */ +#define ROTATE(x) { ST_UINT16 tmp;\ + tmp = (x) & 0xFF;\ + x = (x) >> 8;\ + x |= tmp << 8;\ + } + +/* Modulo-N increment and decrement macros */ +#define DEC_MODULO_N(x,y,z) (ST_UCHAR) (((x) >= (y)) ? ((x) - (y)) : (((x) + (z)) - (y))) +#define INC_MODULO_N(x,y,z) (ST_UCHAR) (((x) + (y)) % (z)) +#define DIFF_MODULO_N(x,y,z) (ST_UCHAR) (((x) >= (y)) ? (x) - (y) : ((x) + (z)) - (y)) + +/* if the most significant bit is set it is either broadcast or multicast */ +#define IS_MULTICAST_ADDR(x) ((x) & 0x8000) + +/* if the bit 13 is not set it is a remote address */ +#define IS_REMOTE_ADDR(x) !((x) & 0x2000) + +/* Used to change port=0 into COM1, port=1 into COM2 etc. */ +#define GET_COM_NO(x) ((x) + 1) + +/* Time Management Macros */ +#define START_TIMEOUT(x,y) (x = sGetMsTime() + (y)) +#define UPDATE_TIMEOUT(x,y) if (x) x = sGetMsTime() + (y) +#define STOP_TIMEOUT(x) (x = 0.0) +#define CHECK_TIMEOUT(x) ((x) && (sGetMsTime() >= (x))) +#define IS_TIMEOUT_ENABLED(x) (x) +#define IS_TIMEOUT_DISABLED(x) !(x) + +/* Macros to work on ADLC_CFG_INFO structure */ +#define ADLC_MODULUS(x) x->adlcCfg.modulus +#define ADLC_FRAME_LEN(x) x->adlcCfg.frameLen +#define ADLC_INFO_LEN(x) (x->adlcCfg.frameLen - MIN_INFO_FRAME_LEN) +#define ADLC_MAX_ADLC_REQS(x) x->adlcCfg.maxAdlcReqs +#define ADLC_RUN_MODE(x) x->adlcCfg.runMode +#define ADLC_COMMUNICATION_MEDIA(x) x->adlcCfg.communicationMedia +#define ADLC_RETRIES(x) x->adlcCfg.retries +#define ADLC_SOF(x) x->adlcCfg.sof +#define ADLC_EOF(x) x->adlcCfg.eof +#define ADLC_RESPONSE_TIMEOUT(x) x->adlcCfg.responseTimeout +#define ADLC_FRAME_TIMEOUT(x) x->adlcCfg.frameTimeout +#define ADLC_SIGNAL_TIMEOUT(x) x->adlcCfg.signalTimeout +#define ADLC_RADIO_DEKEY_DELAY(x) x->adlcCfg.radioDekeyDelay +#define ADLC_RADIO_START_OF_TX_DELAY(x) x->adlcCfg.radioStartOfTxDelay +#define ADLC_PREAMBLE_LEN(x) x->adlcCfg.preambleLen + +#if defined(ADLC_MASTER) +#define ADLC_MAX_CONNECT_RETRY_TIMEOUT(x) x->adlcCfg.maxConnectRetryTimeout +#define ADLC_DEVICE_TURNAROUND_TIME(x) x->adlcCfg.deviceTurnaroundTime +#define ADLC_PORT_TURNAROUND_TIME(x) x->adlcCfg.portTurnaroundTime +#define ADLC_PORT_USAGE(x) x->adlcCfg.portUsage +#endif /* ADLC_MASTER */ + +#if defined(CNP) +/* This macro checks if there is data on port and it gives the char else -1 */ +#define RX_BYTE(port) ((cnp_cnt (port)) ? cnp_getc (port) : -1 ) + +/* This macro puts the data on the port */ +#define SM_PUT(a,b,c) cnp_put(a,b,c) +#else + +#define RX_BYTE(port) ((sm_rx_cnt (port)) ? sm_getc (port) : -1 ) +#define SM_PUT(a,b,c) sm_put(a,b,c) + +#endif /* CNP */ + +#ifdef ADLC_TESTING + +/* Macro to get a random integer within a specified range */ +#define GET_RANDOM_BETWEEN( min, max ) ((rand() % (int)(((max)+1) - (min))) + (min)) + +/* Macro to get one random value out of two */ +#define GET_RANDOM_OF(val1,val2) (rand() < RAND_MAX / 2 ? val1 : val2) + +#endif +/************************************************************************/ +/* Global Variables Declarations */ +/************************************************************************/ +extern ADLC_CFG_INFO adlcCfg; +extern ADLC_PORT_INFO *portList; +extern CFG_PORT *portConfigList; +extern const ST_UINT16 adlc_crc_table[256]; +extern ADLC_STATS adlcStats; +extern ST_BOOLEAN terminateFlag; + +#if defined(ADLC_MASTER) +extern POLL_GROUP *pollGroupList; +extern ST_ULONG gRrFrames; +extern ST_ULONG gInfoFrames; +#endif + +#if defined(ADLC_ERROR) +extern ADLC_ERROR_INFO adlcError; +#endif + +#if !defined(ADLC_LM) +extern ADLC_EVENT_INFO *eventList; +extern ST_INT stackTaskId; +#endif + +#if defined(ADLC_LM) +extern ADLC_TASK_INFO *taskList; +extern ST_INT connectedTask[RLI_TASK_ID_LAST + 1]; +extern ST_INT serMgrSleep; +extern PID myPID; +extern ADLC_FILTER_DEV_LOG_INFO stFiltDevLog; +extern CRITICAL_SECTION protectAdlcData; /* to guard adlc data between threads */ +#endif +/************************************************************************/ +/* Global Functions Declarations */ +/* make the following functions static if you can */ +/************************************************************************/ +/* adlc_utl.c */ +ST_UCHAR eventTypeOf(ST_UCHAR ctrlByte); +ST_VOID timeout_error (ADLC_CON_INFO *cptr); +ST_VOID resetConnection (ADLC_CON_INFO *cptr,ST_INT attrib); +ST_VOID resetStateVarsForConnection(ADLC_CON_INFO *cptr); +ST_RET verifyCrc(ST_UCHAR *frame, ST_UINT frameLen); +ST_UINT16 calcCrc (ST_UCHAR *data, ST_UINT length); + +ADLC_PORT_INFO *getPortPtrFromPort(ST_INT port); +ADLC_DEV_INFO *getDevPtrFromAddress(ST_UINT16 addr); +ADLC_DEV_INFO *getDevPtrFromName(ST_CHAR *name); +ADLC_CON_INFO *getConPtrFromAddrPair(ST_UINT16 slaveAddr,ST_UINT16 masterAddr); +ADLC_CON_INFO *getConPtrFromDptr(ADLC_DEV_INFO *dptr,ST_UINT16 masterAddr); + +ADLC_PORT_INFO *addToPortList(ST_INT port, const ADLC_CFG_INFO *pstAdlcCfg); +CFG_PORT *addToCfgPortList(ST_INT port); +ADLC_DEV_INFO *addToDevList(ADLC_PORT_INFO *pptr, ST_CHAR *name, + ST_UINT16 address,ST_INT pollGroup,ST_BOOLEAN connectAll); +ADLC_CON_INFO *addToConList(ADLC_DEV_INFO *dptr,ST_UINT16 masterAddr); +ST_VOID addToSFramesList(ADLC_CON_INFO *cptr, ST_UCHAR cmd); +ST_VOID addToUFramesList(ADLC_CON_INFO *cptr, ST_UCHAR cmd); +ST_VOID addToRFramesList(ADLC_PORT_INFO *pptr); +ST_VOID addToMFramesInTxList(ST_UINT16 srcAddr,ST_UINT16 dstAddr, ST_VOID *data, ST_INT dataLen); +ST_VOID addToMFramesInRxList(ADLC_PORT_INFO *pptr,ST_UCHAR *data,ST_INT dataLen); +ADLC_REQ *addToReqList(ADLC_CON_INFO *cptr); +ST_VOID addToIFramesInTxList(ADLC_REQ *rptr,ST_UCHAR *data,ST_INT len); +ST_VOID addToIFramesInRxList(ADLC_CON_INFO *cptr,ST_UCHAR *data,ST_INT len); + +ST_VOID deleteAllConnections(ADLC_DEV_INFO *dptr); +ST_VOID deleteConnection(ADLC_CON_INFO *cptr); +ST_VOID deleteDevice(ADLC_DEV_INFO *dptr); +ST_VOID deletePort(ADLC_PORT_INFO *pptr); +ST_VOID deleteCfgPort(CFG_PORT *pstCfgPort); +ST_VOID deleteAllFrames(ADLC_CON_INFO *cptr); +ST_VOID deleteSFramesList(ADLC_CON_INFO *cptr); +ST_VOID deleteSFramesListWithoutPf(ADLC_CON_INFO *cptr); +ST_VOID deleteUFramesList(ADLC_CON_INFO *cptr); +ST_VOID deleteIFramesFromRxList(ADLC_CON_INFO *cptr); +ST_VOID deleteIFramesFromTxList(ADLC_CON_INFO *cptr); +ST_VOID deleteMFramesFromTxList(ADLC_PORT_INFO *pptr); +ST_VOID deleteMFramesFromRxList(ADLC_PORT_INFO *pptr); +ST_VOID deleteAckedIFramesFromTxList(ADLC_CON_INFO *cptr,ST_UCHAR nR); +ST_VOID deleteFrame(ADLC_FRAME *fptr,ADLC_FRAME **framesList); +ST_VOID deleteReqFrame (ADLC_REQ *rptr); + +ST_BOOLEAN isDevPtrValid(ADLC_DEV_INFO *rDptr); +ST_VOID nackAllIFramesFromTxList(ADLC_CON_INFO *cptr); +ST_BOOLEAN isInfoQueuedUp(ADLC_CON_INFO *cptr); +ST_BOOLEAN isPollQueuedUp(ADLC_CON_INFO *cptr); +ST_BOOLEAN isUFrameQueuedUp(ADLC_CON_INFO *cptr); +ST_BOOLEAN isOkToPoll(ADLC_CON_INFO *cptr); +ST_BOOLEAN isOkToSendUnum(ADLC_CON_INFO *cptr,ST_BOOLEAN justCheck); +ST_BOOLEAN isOkToSendSupr(ADLC_CON_INFO *cptr,ST_BOOLEAN justCheck); +ST_BOOLEAN isOkToSendInfo(ADLC_CON_INFO *cptr,ST_BOOLEAN justCheck); +ST_BOOLEAN isOkToSendMult(ADLC_PORT_INFO *pptr,ST_BOOLEAN justCheck); +ST_BOOLEAN isConStateInInfoTransfer(ADLC_CON_INFO *cptr); +ST_VOID getPfAndEosBit(ADLC_FRAME *nextFptr,ST_UCHAR sendCount, + ST_BOOLEAN *pfBit,ST_BOOLEAN *eosBit, ADLC_PORT_INFO *pptr); +ST_VOID adlc_except (SD_CONST ST_CHAR *file, ST_INT line); +ST_UINT16 getLocalAddr(ADLC_CON_INFO *cptr); +ST_UINT16 getRemoteAddr(ADLC_CON_INFO *cptr); +CFG_PORT *findCfgPort(ST_INT port); +ST_VOID adlcEndLogging (ST_VOID); + +#if defined(ADLC_MASTER) +POLL_GROUP *findPollGroup(ST_INT pollGrpID); +POLL_GROUP *addToPollGroupList(ST_INT pollGrpID,ST_DOUBLE pollRate); +ST_RET addDevToPollGrp(ADLC_DEV_INFO *dptr,ST_INT pollGroup); +POLLED_DEV *findPolledDevByName(char *devName); +POLLED_DEV *findPolledDevByAddress(ST_UINT16 addr); +#endif + +/* adlc_dec.c */ +ST_RET getFrame(ADLC_PORT_INFO *pptr); +ST_RET processAdlcFrame(ADLC_PORT_INFO *pptr); +ST_VOID giveIndicationToStack (ADLC_CON_INFO *cptr,ST_INT opcode,ST_RET retCode, ST_LONG usr1); + +/* adlc_enc.c */ +ST_RET send_info_frame(ADLC_FRAME *fptr,ST_BOOLEAN pfBit,ST_BOOLEAN eosBit); +ST_RET send_supr_frame(ADLC_FRAME *fptr); +ST_RET send_unum_frame(ADLC_FRAME *fptr); +ST_RET send_ui_frame(ADLC_FRAME *fptr); +ST_RET send_redr_frame(ADLC_FRAME *fptr,ADLC_PORT_INFO *pptr); +ST_RET send_mult_frame(ADLC_FRAME *fptr,ADLC_PORT_INFO *pptr); +ST_VOID enc_adlc_frame(ST_UCHAR *frame,ST_UINT16 srcAddr,ST_UINT16 dstAddr,ST_UCHAR ctrlByte, + ST_UINT16 frameFormat,ST_INT dataLen, ADLC_PORT_INFO *pptr); +ST_UINT16 getFrameFormat(ST_INT frameLen,ST_BOOLEAN eosBit,ST_UCHAR frameType); + +/* adlc_ssv.c adlc_msv.c */ +ST_VOID adlcService(ST_VOID); +ST_BOOLEAN checkTxService(ADLC_PORT_INFO *pptr); +ST_VOID txService(ADLC_PORT_INFO *pptr); +ST_VOID rxService(ADLC_PORT_INFO *pptr); +ST_VOID txStateService(ADLC_PORT_INFO *pptr); +ST_VOID timeoutService(ADLC_PORT_INFO *pptr); +ST_VOID stopWaitingForResp(ADLC_CON_INFO *cptr, ST_BOOLEAN bResetRetries); + +#if defined(ADLC_SLAVE) +ST_VOID startSignalTimeout(ADLC_PORT_INFO *pptr); +ST_VOID stopSignalTimeout(ADLC_PORT_INFO *pptr); +ST_BOOLEAN checkSignalTimeout(ADLC_PORT_INFO *pptr); +ST_VOID goInTxMode(ADLC_CON_INFO *cptr); +ST_VOID goInRxMode(ADLC_CON_INFO *cptr); +ST_VOID waitForResponse(ADLC_CON_INFO *cptr); +#endif /* ADLC_SLAVE */ + +#if defined(ADLC_MASTER) +ST_VOID pollDevice(ADLC_DEV_INFO *dptr); +ST_VOID pollConnection(ADLC_CON_INFO *cptr); +ST_VOID waitForResponse(ADLC_CON_INFO *cptr); +ST_VOID startConRetryTimeout(ADLC_CON_INFO *cptr); +ST_BOOLEAN checkConRetryTimeout(ADLC_CON_INFO *cptr); +ST_VOID stopConRetryTimeout(ADLC_CON_INFO *cptr); +ST_VOID startDeviceTurnaroundTimeout(ADLC_DEV_INFO *dptr); +ST_BOOLEAN checkDeviceTurnaroundTimeout(ADLC_DEV_INFO *dptr); +ST_VOID stopDeviceTurnaroundTimeout(ADLC_DEV_INFO *dptr); +ST_VOID startPortTurnaroundTimeout(ADLC_PORT_INFO *pptr); +ST_BOOLEAN checkPortTurnaroundTimeout(ADLC_PORT_INFO *pptr); +ST_VOID stopPortTurnaroundTimeout(ADLC_PORT_INFO *pptr); +ST_RET startPollTimer(POLL_GROUP *pstPollGrp); +ST_RET updatePollTimer(POLL_GROUP *pstPollGrp); +ST_RET stopPollTimer(POLL_GROUP *pstPollGrp); +ST_BOOLEAN checkPollTimer(POLL_GROUP *pstPollGrp); +ST_RET pollInit(ST_VOID); + +ST_VOID triggerLogicAnalyzer(ST_INT port); +#endif /* ADLC_MASTER */ + +/* adlc_tm.c */ +ST_VOID startRespTimeout(ADLC_PORT_INFO *pptr); +ST_VOID updateRespTimeout(ADLC_PORT_INFO *pptr); +ST_VOID stopRespTimeout(ADLC_PORT_INFO *pptr); +ST_BOOLEAN checkRespTimeout(ADLC_PORT_INFO *pptr); +ST_BOOLEAN isRespTimeoutEnabled(ADLC_PORT_INFO *pptr); +ST_BOOLEAN isRespTimeoutDisabled(ADLC_PORT_INFO *pptr); +ST_VOID startSignalTimeout(ADLC_PORT_INFO *pptr); +ST_VOID updateSignalTimeout(ADLC_PORT_INFO *pptr); +ST_VOID stopSignalTimeout(ADLC_PORT_INFO *pptr); +ST_BOOLEAN checkSignalTimeout(ADLC_PORT_INFO *pptr); +ST_VOID startRadioDelayTimeout(ADLC_PORT_INFO *pptr); +ST_VOID startFrameTimeout(ADLC_PORT_INFO *pptr); +ST_BOOLEAN checkFrameTimeout(ADLC_PORT_INFO *pptr); +ST_VOID stopFrameTimeout(ADLC_PORT_INFO *pptr); +ST_VOID time_delay (ST_DOUBLE tme); + +/* adlc_log.c */ +ST_VOID logAdlcStats(ST_VOID); + +/* adlc_get.c */ +ST_CHAR *getCommandName(ST_UCHAR ctrlByte); +ST_CHAR *getConState(ST_INT state); +ST_CHAR *getTxRxMode(ST_INT mode); +ST_CHAR *getRunMode(ST_INT mode); +ST_CHAR *getCommunicationMedia(ST_INT media); +ST_CHAR *getOpCode(ST_INT opcode); +ST_CHAR *getRetCode(ST_RET retCode); +ST_CHAR *getSignalState(ST_INT signalState); + +/* adlc_var.c */ +ST_VOID adlcInitGlbVars(ST_VOID); +ST_VOID initSiscoUtilGlbVarsForAdlc(ST_VOID); + +/* adlc_lsm.c */ +ST_VOID rdThreadErrorHandling(ADLC_PORT_INFO *pptr); + +/* adlc_cfg.c adlc_odb.c adlc_hc.c */ +ST_RET adlcConfigure (ST_VOID); +#if defined(ADLC_LM) +ST_RET adlcReConfigure (ST_VOID); +ST_RET updateAdlcLoggingParameters(ST_VOID); +ST_RET updateAdlcPollParameters(ST_UINT hi,ST_UINT med, ST_UINT low); +ST_RET adlcCloseDatabase (ST_VOID); +#endif + +/* adlc_tst.c */ +#ifdef ADLC_TESTING +ST_VOID testSetMain (ST_VOID); +ST_VOID switchMenu(ST_VOID); +ST_VOID memCheckError (ST_VOID); +ST_VOID screenLogFun (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); +ST_VOID doEnableScreenLog (ST_VOID); +ST_VOID doDisableScreenLog (ST_VOID); +#if defined(__OS2__) +extern HEV o_kbd_event_sem; +#endif +#if defined(_WIN32) +extern HEV kbdEvent; +#endif +#if defined(ADLC_LM) +ST_RET handleKeyboardEvent(ST_ULONG userId, ST_ULONG postCount); +ST_RET testStartKeyboard (ST_VOID); +ST_RET testEndKeyboard (ST_VOID); +#endif /* ADLC_LM */ +#endif + +#if !defined(ADLC_LM) +ADLC_EVENT_INFO *addToEventList(ST_INT adlcEventOp,ST_VOID *adlcEventCb,ST_INT adlcRetCode); +#endif + +#if defined(ADLC_LM) +ST_RET exitCallBack (ST_ULONG userId, ST_ULONG postCount); + +ST_RET term_init (ST_VOID); +ST_RET term_rest (ST_VOID); +ST_RET adlcQueInit (ST_VOID); +ADLC_TASK_INFO *addToTaskList(ST_UINT16 localAddr,ST_INT taskId,HQUEUE qHandle); +ADLC_TASK_INFO *getTaskPtrFromLocalAddress(ST_UINT16 addr); +ADLC_TASK_INFO *getTaskPtrFromTaskId(ST_INT taskId); +ST_VOID deleteTask(ADLC_TASK_INFO *tptr); +ST_VOID deleteTaskFromLocalAddress(ST_UINT16 localAddr); +ST_RET addTaskForLocalAddress(ST_UINT16 addr,ST_INT taskId); +ST_VOID deleteTaskFromTaskId(ST_INT taskId); +ST_INT getTaskId(ADLC_CON_INFO *cptr,ST_INT *taskId); +ST_VOID logIpcError(ST_INT retCode, ST_CHAR *str, ST_CHAR *file, ST_INT line); +ST_VOID updateStatusBar(ST_CHAR *szBuff); +ST_VOID screenLogFun (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); + +/* adlc_lm.c */ +ST_RET handleCmdQueEvent (ST_ULONG userId, ST_ULONG qMsgLen, ST_VOID *qMsg); +ST_RET handleDataQueEvent (ST_ULONG userId, ST_ULONG qMsgLen, ST_VOID *qMsg); +ST_RET sendDataMsgToStack(ADLC_CMD *srcPstCmd,ST_INT stackTaskId); +ST_RET sendDataMsgToStackNoAlloc(ADLC_CMD *dstPstCmd,ST_INT stackTaskId); +#endif /* ADLC_LM */ + +#if defined(__OS2__) +ST_VOID exitLogging (ST_ULONG ulTermCode); +ST_VOID exitCleanFun (ST_ULONG ulTermCode); +#endif + +#if defined(_WIN32) +ST_VOID exitLogging (ST_VOID); +ST_VOID exitCleanFun (ST_VOID); +#endif + +#if defined(UCA_SMP) +ADLC_REQ *addToExtReqList(ADLC_CON_INFO *cptr,ADLC_REQ **adlcReqList,ST_LONG userId); +ST_VOID deleteExtReqFrame(ADLC_REQ *rptr); +ST_VOID addToUIFramesInTxList(ADLC_REQ *rptr,ST_UCHAR *data,ST_INT dataLen); +ST_VOID addToUIFramesInRxList(ADLC_CON_INFO *cptr,ST_UCHAR *data,ST_INT dataLen); +ST_VOID deleteUIFramesFromRxList(ADLC_CON_INFO *cptr); +ST_VOID deleteUIFramesFromTxList(ADLC_CON_INFO *cptr); +ST_RET sendExtWriteDoneToStack(ADLC_CON_INFO *cptr, ST_LONG userId, + ST_CHAR *timeSync, ST_INT bufLen, + ST_RET retCode); +#endif /* UCA_SMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* _ADLC_H */ + + + diff --git a/mmslib/inc/adlc_dsm.h b/mmslib/inc/adlc_dsm.h new file mode 100644 index 0000000..319cd58 --- /dev/null +++ b/mmslib/inc/adlc_dsm.h @@ -0,0 +1,73 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-1996, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : adlc_dsm.h */ +/* PRODUCT(S) : ADLC */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains functions that provide for serial port communi- */ +/* cations for the Digiboard. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* ST_INT sm_init(port,baud,parity,data,stop) */ +/* ST_INT sm_exit(port) */ +/* ST_INT sm_put (port,len,buffer) */ +/* ST_INT sm_putc (port,ch) */ +/* ST_INT sm_rx_cnt (port) */ +/* ST_INT sm_get (port,len,buffer) */ +/* ST_INT sm_getc (port) */ +/* ST_INT sm_rx_flush(port) */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/12/97 IKE 09 Changed to MMSEASE 7.0 Data Types */ +/* 02/21/97 IKE 08 Changed COM_TEST to ESSENTIAL_COM to make */ +/* more sense */ +/* 12/03/96 IKE 07 Moved some stuff to adlc_sm.h */ +/* 09/19/96 IKE 06 Rearranged sm_get and sm_set functions */ +/* 08/22/96 IKE 05 Added sm_get_dcd for contention avoidance */ +/* 06/11/96 IKE 04 Added more functions to check RS232 signals */ +/* 05/22/96 IKE 03 Added functions to control RS232 signals */ +/* 04/04/96 rkr 02 Cleanup */ +/* 11/12/95 IKE 1 Created */ +/************************************************************************/ + +#ifndef _ADLC_DSM_H_ +#define _ADLC_DSM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(ESSENTIAL_COM) + +ST_INT xc_entr (ST_INT); +ST_INT xc_exit(ST_VOID); +ST_INT xc_init(ST_INT, ST_INT, ST_INT, ST_INT, ST_INT); +ST_INT xc_link (ST_INT, ST_INT); +ST_INT xc_unlk (ST_INT); +ST_INT xc_put (ST_INT, ST_CHAR*, ST_INT*); +ST_INT xc_putc (ST_INT, ST_CHAR); +ST_INT xc_get (ST_INT, ST_CHAR*, ST_INT*); +ST_INT xc_getc (ST_INT); +ST_INT xc_dtr (ST_INT, ST_INT); +ST_INT xc_rts (ST_INT, ST_INT); +ST_INT xc_cts(ST_INT); +ST_INT xc_dsr(ST_INT); +ST_INT xc_dcd(ST_INT); +ST_INT xc_test (ST_INT); +ST_INT xc_utest (ST_INT); +ST_INT xc_uwait(ST_INT); +#endif /* ESSENTIAL_COM */ + +#ifdef __cplusplus +} +#endif + +#endif /* adlc_dsm.h already included */ diff --git a/mmslib/inc/adlc_log.h b/mmslib/inc/adlc_log.h new file mode 100644 index 0000000..a6c50eb --- /dev/null +++ b/mmslib/inc/adlc_log.h @@ -0,0 +1,879 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-1996, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : adlc_log.h */ +/* PRODUCT(S) : ADLC */ +/* */ +/* MODULE DESCRIPTION : */ +/* All the logging macros are defined in following order for easy */ +/* editing of this file. Please keep the same order if logging macros */ +/* need to be changed */ +/* */ +/* ADLC_MASK_LOG_ERR for critical errors */ +/* ADLC_MASK_LOG_NERR for normal errors */ +/* ADLC_MASK_LOG_FLOW for program flow logging */ +/* ADLC_MASK_LOG_IO for control frames */ +/* ADLC_MASK_LOG_DEBUG for debugging purposes */ +/* ADLC_MASK_LOG_ALWAYS for always logging */ +/* ADLC_MASK_LOG_SM for serial manager logging */ +/* ADLC_MASK_LOG_INFO_FRAME for data coming to or from stack */ +/* ADLC_MASK_LOG_USER from or to user (stack) logging */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/13/99 MDE 19 Added SD_CONST modifiers */ +/* 02/01/99 JRB 18 Fix ADLC_LOG_DEV_FILT macros for new API. */ +/* Put back ADLC_MAX_LOG_MASK. ADLC_LM needs it.*/ +/* 10/08/98 MDE 17 Migrated to updated SLOG interface */ +/* 09/01/98 IKE 16 Removed the if statement for ALWAYS macros */ +/* 09/18/97 IKE 15 Added telephone support */ +/* 08/27/97 IKE 14 Fixed number of parameters in */ +/* ADLC_LOG_DEV_FILT macros for non debug ver */ +/* 07/16/97 IKE 13 Added ADLC_LOG_DEV_FILT */ +/* 06/13/97 EJV 12 Added ADLC_LOG_ERR5 */ +/* 05/12/97 IKE 11 Changed to MMSEASE 7.0 Data Types */ +/* 04/30/97 IKE 10 Updated ADLC_MAX_LOG_MASK */ +/* 02/24/97 IKE 09 Changed logMask6 to use adlc_debug_sel */ +/* moved log masks to adlc_usr.h, changed */ +/* the logging macros to use slog functions */ +/* deleted macros specific to OS2 */ +/* 12/03/96 IKE 08 WIN32 Support, header files cleanup */ +/* 11/06/96 IKE 07 Changed C++ style comments to C style */ +/* comments to make it more platform independent*/ +/* 10/28/96 KCR 06 Changed LT of HEX logging macros to _CONT */ +/* 10/22/96 IKE 05 Added LOG_ALWAYS5 */ +/* 10/04/96 IKE 04 Changed DEBUG_MMS to DEBUG_SISCO */ +/* 06/21/96 IKE 03 Added ADLC_SM, ADLC_INFO_FRAME and ADLC_USER */ +/* Changed from slog_remote to SLOG6_REM_xxx */ +/* 04/04/96 rkr 02 Cleanup, removed slog_ipc.h */ +/* 01/20/96 IKE 01 Merged NAV's OS2 code */ +/* 11/25/95 IKE 1.00 Created */ +/************************************************************************/ + +#ifndef ADLC_LOG_INCLUDED +#define ADLC_LOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "slog.h" + +/************************************************************************/ +/* The Logging Control structure */ +/* Note that more than one may be used, and there is a 1-to-1 mapping */ +/* of the control structure to associated file && memory buffer. */ +/************************************************************************/ + +#define ADLC_MAX_LOG_MASK (ADLC_MASK_LOG_ERR | ADLC_MASK_LOG_NERR | \ + ADLC_MASK_LOG_FLOW | \ + ADLC_MASK_LOG_IO | ADLC_MASK_LOG_HEXIO | \ + ADLC_MASK_LOG_DEBUG | ADLC_MASK_LOG_HEXDEBUG | \ + ADLC_MASK_LOG_SM | ADLC_MASK_LOG_HEXSM | \ + ADLC_MASK_LOG_INFO_FRAME | ADLC_MASK_LOG_HEXINFO_FRAME | \ + ADLC_MASK_LOG_USER | ADLC_MASK_LOG_HEXUSER) + +#define ADLC_LOG_CLOSE_FILE (p) {slogCloseFile (p);} + +/* Control bit set/clear macros */ + +#define ADLC_SET_CTRL(a) {sLogCtrl->logCtrl |= (a);} +#define ADLC_CLR_CTRL(a) {sLogCtrl->logCtrl &= ~(a);} + +#define ADLC_SET_FILE_CTRL(a) {sLogCtrl->fc.ctrl |= (a);} +#define ADLC_CLR_FILE_CTRL(a) {sLogCtrl->fc.ctrl &= ~(a);} + +#define ADLC_SET_LOG_MASK(a) {adlc_debug_sel |= (a);} +#define ADLC_CLR_LOG_MASK(a) {adlc_debug_sel &= ~(a);} + + +#ifdef DEBUG_SISCO /* if DEBUG_SISCO is defined, expand macros */ + +/************************************************************************/ +/* ADLC LOGGING CONTROL */ +/************************************************************************/ + +/* Log Type Strings */ +extern SD_CONST ST_CHAR *_adlc_err_logstr; +extern SD_CONST ST_CHAR *_adlc_nerr_logstr; +extern SD_CONST ST_CHAR *_adlc_flow_logstr; +extern SD_CONST ST_CHAR *_adlc_io_logstr; +extern SD_CONST ST_CHAR *_adlc_debug_logstr; +extern SD_CONST ST_CHAR *_adlc_always_logstr; +extern SD_CONST ST_CHAR *_adlc_sm_logstr; +extern SD_CONST ST_CHAR *_adlc_info_frame_logstr; +extern SD_CONST ST_CHAR *_adlc_user_logstr; + +/* --------------------------------------------------------------- */ +/* ------------------ Error Logging Macros ------------------ */ +#define ADLC_LOG_ERR0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slog (sLogCtrl, _adlc_err_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_ERR1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slog (sLogCtrl, _adlc_err_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_ERR2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slog (sLogCtrl, _adlc_err_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_ERR3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slog (sLogCtrl, _adlc_err_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_ERR4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slog (sLogCtrl, _adlc_err_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define ADLC_LOG_ERR5(a,b,c,d,e,f) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slog (sLogCtrl, _adlc_err_logstr,\ + thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CERR0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CERR1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CERR2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CERR3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CERR4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_ERR_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_ERR)\ + _slogHex (sLogCtrl,a,b);\ + } + + +/* --------------------------------------------------------------- */ +/* ------------------ Normal Error Logging Macros ------------------ */ + +#define ADLC_LOG_NERR0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slog (sLogCtrl, _adlc_nerr_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_NERR1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slog (sLogCtrl, _adlc_nerr_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_NERR2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slog (sLogCtrl, _adlc_nerr_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_NERR3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slog (sLogCtrl, _adlc_nerr_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_NERR4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slog (sLogCtrl, _adlc_nerr_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CNERR0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CNERR1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CNERR2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CNERR3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CNERR4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_NERR_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_NERR)\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ Flow Logging Macros ------------------ */ + +#define ADLC_LOG_FLOW0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slog (sLogCtrl, _adlc_flow_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_FLOW1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slog (sLogCtrl, _adlc_flow_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_FLOW2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slog (sLogCtrl, _adlc_flow_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_FLOW3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slog (sLogCtrl, _adlc_flow_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_FLOW4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slog (sLogCtrl, _adlc_flow_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CFLOW0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CFLOW1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CFLOW2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CFLOW3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CFLOW4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_FLOW_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_FLOW)\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ I/O Logging Macros ------------------ */ + +#define ADLC_LOG_IO0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_IO1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_IO2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_IO3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_IO4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CIO0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CIO1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CIO2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CIO3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CIO4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_IO)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_IO_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_HEXIO)\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ Debug Logging Macros ------------------ */ + +#define ADLC_LOG_DEBUG0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slog (sLogCtrl, _adlc_debug_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_DEBUG1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slog (sLogCtrl, _adlc_debug_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_DEBUG2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slog (sLogCtrl, _adlc_debug_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_DEBUG3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slog (sLogCtrl, _adlc_debug_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_DEBUG4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slog (sLogCtrl, _adlc_debug_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CDEBUG0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CDEBUG1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CDEBUG2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CDEBUG3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CDEBUG4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_DEBUG)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_DEBUG_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_HEXDEBUG)\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ Always Logging Macros ------------------ */ + +#define ADLC_LOG_ALWAYS0(a) {\ + _slog (sLogCtrl, _adlc_always_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_ALWAYS1(a,b) {\ + _slog (sLogCtrl, _adlc_always_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_ALWAYS2(a,b,c) {\ + _slog (sLogCtrl, _adlc_always_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_ALWAYS3(a,b,c,d) {\ + _slog (sLogCtrl, _adlc_always_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_ALWAYS4(a,b,c,d,e) {\ + _slog (sLogCtrl, _adlc_always_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define ADLC_LOG_ALWAYS5(a,b,c,d,e,f) {\ + _slog (sLogCtrl, _adlc_always_logstr,\ + thisFileName,__LINE__,a,b,c,d,e,f);\ + } +/* 'Continue' versions */ +#define ADLC_LOG_CALWAYS0(a) {\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CALWAYS1(a,b) {\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CALWAYS2(a,b,c) {\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CALWAYS3(a,b,c,d) {\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CALWAYS4(a,b,c,d,e) {\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } +#define ADLC_LOG_CALWAYS5(a,b,c,d,e,f) {\ + _slogc (sLogCtrl,a,b,c,d,e,f);\ + } + +#define ADLC_LOG_ALWAYS_HEX(a,b) {\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ SM Logging Macros ------------------ */ + +#define ADLC_LOG_SM0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slog (sLogCtrl, _adlc_sm_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_SM1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slog (sLogCtrl, _adlc_sm_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_SM2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slog (sLogCtrl, _adlc_sm_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_SM3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slog (sLogCtrl, _adlc_sm_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_SM4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slog (sLogCtrl, _adlc_sm_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CSM0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CSM1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CSM2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CSM3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CSM4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_SM)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_SM_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_HEXSM)\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ INFO_FRAME Logging Macros ------------------ */ + +#define ADLC_LOG_INFO_FRAME0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slog (sLogCtrl, _adlc_info_frame_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_INFO_FRAME1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slog (sLogCtrl, _adlc_info_frame_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_INFO_FRAME2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slog (sLogCtrl, _adlc_info_frame_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_INFO_FRAME3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slog (sLogCtrl, _adlc_info_frame_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_INFO_FRAME4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slog (sLogCtrl, _adlc_info_frame_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CINFO_FRAME0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CINFO_FRAME1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CINFO_FRAME2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CINFO_FRAME3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CINFO_FRAME4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_INFO_FRAME)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_INFO_FRAME_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_HEXINFO_FRAME)\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ USER Logging Macros ------------------ */ + +#define ADLC_LOG_USER0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slog (sLogCtrl, _adlc_user_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_USER1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slog (sLogCtrl, _adlc_user_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_USER2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slog (sLogCtrl, _adlc_user_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_USER3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slog (sLogCtrl, _adlc_user_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_USER4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slog (sLogCtrl, _adlc_user_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } +#define ADLC_LOG_USER5(a,b,c,d,e,f) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slog (sLogCtrl, _adlc_user_logstr,\ + thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CUSER0(a) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CUSER1(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CUSER2(a,b,c) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CUSER3(a,b,c,d) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CUSER4(a,b,c,d,e) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } +#define ADLC_LOG_CUSER5(a,b,c,d,e,f) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_USER)\ + _slogc (sLogCtrl,a,b,c,d,e,f);\ + } +#define ADLC_LOG_USER_HEX(a,b) {\ + if (adlc_debug_sel & ADLC_MASK_LOG_HEXUSER)\ + _slogHex (sLogCtrl,a,b);\ + } + +/* --------------------------------------------------------------- */ +/* ------------------ DEV_FILT Logging Macros ------------------ */ +#if defined(ADLC_LM) +#define ADLC_LOG_DEV_FILT0(x,a) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a);\ + } +#define ADLC_LOG_DEV_FILT1(x,a,b) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define ADLC_LOG_DEV_FILT2(x,a,b,c) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define ADLC_LOG_DEV_FILT3(x,a,b,c,d) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define ADLC_LOG_DEV_FILT4(x,a,b,c,d,e) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slog (sLogCtrl, _adlc_io_logstr,\ + thisFileName,__LINE__,a,b,c,d,e);\ + } + +/* 'Continue' versions */ +#define ADLC_LOG_CDEV_FILT0(x,a) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slogc (sLogCtrl,a);\ + } +#define ADLC_LOG_CDEV_FILT1(x,a,b) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slogc (sLogCtrl,a,b);\ + } +#define ADLC_LOG_CDEV_FILT2(x,a,b,c) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define ADLC_LOG_CDEV_FILT3(x,a,b,c,d) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define ADLC_LOG_CDEV_FILT4(x,a,b,c,d,e) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } + +#define ADLC_LOG_DEV_FILT_HEX(x,a,b) {\ + if (stFiltDevLog.bFilter && stFiltDevLog.address == x)\ + _slogHex (sLogCtrl,a,b);\ + } +#endif /* ADLC_LM */ +#else /* DEBUG_SISCO not defined */ + +/*----------------------------------------------------------------------- + * Error Logging Macros for Hard( serious ) Errors + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_ERR0(a) +#define ADLC_LOG_ERR1(a,b) +#define ADLC_LOG_ERR2(a,b,c) +#define ADLC_LOG_ERR3(a,b,c,d) +#define ADLC_LOG_ERR4(a,b,c,d,e) +#define ADLC_LOG_ERR5(a,b,c,d,e,f) + +#define ADLC_LOG_CERR0(a) +#define ADLC_LOG_CERR1(a,b) +#define ADLC_LOG_CERR2(a,b,c) +#define ADLC_LOG_CERR3(a,b,c,d) +#define ADLC_LOG_CERR4(a,b,c,d,e) + +#define ADLC_LOG_ERR_HEX(a,b) + +/*----------------------------------------------------------------------- + * Logging Macros for on Errors + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_NERR0(a) +#define ADLC_LOG_NERR1(a,b) +#define ADLC_LOG_NERR2(a,b,c) +#define ADLC_LOG_NERR3(a,b,c,d) +#define ADLC_LOG_NERR4(a,b,c,d,e) + +#define ADLC_LOG_CNERR0(a) +#define ADLC_LOG_CNERR1(a,b) +#define ADLC_LOG_CNERR2(a,b,c) +#define ADLC_LOG_CNERR3(a,b,c,d) +#define ADLC_LOG_CNERR4(a,b,c,d,e) + +#define ADLC_LOG_NERR_HEX(a,b) +/*----------------------------------------------------------------------- + * Flow Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_FLOW0(a) +#define ADLC_LOG_FLOW1(a,b) +#define ADLC_LOG_FLOW2(a,b,c) +#define ADLC_LOG_FLOW3(a,b,c,d) +#define ADLC_LOG_FLOW4(a,b,c,d,e) +#define ADLC_LOG_FLOW5(a,b,c,d,e,f) + +#define ADLC_LOG_CFLOW0(a) +#define ADLC_LOG_CFLOW1(a,b) +#define ADLC_LOG_CFLOW2(a,b,c) +#define ADLC_LOG_CFLOW3(a,b,c,d) +#define ADLC_LOG_CFLOW4(a,b,c,d,e) +#define ADLC_LOG_CFLOW5(a,b,c,d,e,f) + +#define ADLC_LOG_FLOW_HEX(a,b) +/*----------------------------------------------------------------------- + * I/O Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_IO0(a) +#define ADLC_LOG_IO1(a,b) +#define ADLC_LOG_IO2(a,b,c) +#define ADLC_LOG_IO3(a,b,c,d) +#define ADLC_LOG_IO4(a,b,c,d,e) + +#define ADLC_LOG_CIO0(a) +#define ADLC_LOG_CIO1(a,b) +#define ADLC_LOG_CIO2(a,b,c) +#define ADLC_LOG_CIO3(a,b,c,d) +#define ADLC_LOG_CIO4(a,b,c,d,e) + +#define ADLC_LOG_IO_HEX(a,b) + +/*----------------------------------------------------------------------- + * Debug Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_DEBUG0(a) +#define ADLC_LOG_DEBUG1(a,b) +#define ADLC_LOG_DEBUG2(a,b,c) +#define ADLC_LOG_DEBUG3(a,b,c,d) +#define ADLC_LOG_DEBUG4(a,b,c,d,e) + +#define ADLC_LOG_CDEBUG0(a) +#define ADLC_LOG_CDEBUG1(a,b) +#define ADLC_LOG_CDEBUG2(a,b,c) +#define ADLC_LOG_CDEBUG3(a,b,c,d) +#define ADLC_LOG_CDEBUG4(a,b,c,d,e) + +#define ADLC_LOG_DEBUG_HEX(a,b) + +/*----------------------------------------------------------------------- + * Always Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_ALWAYS0(a) +#define ADLC_LOG_ALWAYS1(a,b) +#define ADLC_LOG_ALWAYS2(a,b,c) +#define ADLC_LOG_ALWAYS3(a,b,c,d) +#define ADLC_LOG_ALWAYS4(a,b,c,d,e) +#define ADLC_LOG_ALWAYS5(a,b,c,d,e,f) + +#define ADLC_LOG_CALWAYS0(a) +#define ADLC_LOG_CALWAYS1(a,b) +#define ADLC_LOG_CALWAYS2(a,b,c) +#define ADLC_LOG_CALWAYS3(a,b,c,d) +#define ADLC_LOG_CALWAYS4(a,b,c,d,e) +#define ADLC_LOG_CALWAYS5(a,b,c,d,e,f) + +#define ADLC_LOG_ALWAYS_HEX(a,b) + +/*----------------------------------------------------------------------- + * Serial Manager Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_SM0(a) +#define ADLC_LOG_SM1(a,b) +#define ADLC_LOG_SM2(a,b,c) +#define ADLC_LOG_SM3(a,b,c,d) +#define ADLC_LOG_SM4(a,b,c,d,e) + +#define ADLC_LOG_CSM0(a) +#define ADLC_LOG_CSM1(a,b) +#define ADLC_LOG_CSM2(a,b,c) +#define ADLC_LOG_CSM3(a,b,c,d) +#define ADLC_LOG_CSM4(a,b,c,d,e) + +#define ADLC_LOG_SM_HEX(a,b) + +/*----------------------------------------------------------------------- + * INFO_FRAME Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_INFO_FRAME0(a) +#define ADLC_LOG_INFO_FRAME1(a,b) +#define ADLC_LOG_INFO_FRAME2(a,b,c) +#define ADLC_LOG_INFO_FRAME3(a,b,c,d) +#define ADLC_LOG_INFO_FRAME4(a,b,c,d,e) + +#define ADLC_LOG_CINFO_FRAME0(a) +#define ADLC_LOG_CINFO_FRAME1(a,b) +#define ADLC_LOG_CINFO_FRAME2(a,b,c) +#define ADLC_LOG_CINFO_FRAME3(a,b,c,d) +#define ADLC_LOG_CINFO_FRAME4(a,b,c,d,e) + +#define ADLC_LOG_INFO_FRAME_HEX(a,b) + +/*----------------------------------------------------------------------- + * USER Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_USER0(a) +#define ADLC_LOG_USER1(a,b) +#define ADLC_LOG_USER2(a,b,c) +#define ADLC_LOG_USER3(a,b,c,d) +#define ADLC_LOG_USER4(a,b,c,d,e) +#define ADLC_LOG_USER5(a,b,c,d,e,f) + +#define ADLC_LOG_CUSER0(a) +#define ADLC_LOG_CUSER1(a,b) +#define ADLC_LOG_CUSER2(a,b,c) +#define ADLC_LOG_CUSER3(a,b,c,d) +#define ADLC_LOG_CUSER4(a,b,c,d,e) +#define ADLC_LOG_CUSER5(a,b,c,d,e,f) + +#define ADLC_LOG_USER_HEX(a,b) + +/*----------------------------------------------------------------------- + * DEV_FILT Logging Macros + *----------------------------------------------------------------------*/ + +#define ADLC_LOG_DEV_FILT0(x,a) +#define ADLC_LOG_DEV_FILT1(x,a,b) +#define ADLC_LOG_DEV_FILT2(x,a,b,c) +#define ADLC_LOG_DEV_FILT3(x,a,b,c,d) +#define ADLC_LOG_DEV_FILT4(x,a,b,c,d,e) + +#define ADLC_LOG_CDEV_FILT0(x,a) +#define ADLC_LOG_CDEV_FILT1(x,a,b) +#define ADLC_LOG_CDEV_FILT2(x,a,b,c) +#define ADLC_LOG_CDEV_FILT3(x,a,b,c,d) +#define ADLC_LOG_CDEV_FILT4(x,a,b,c,d,e) + +#define ADLC_LOG_DEV_FILT_HEX(x,a,b) + +#endif /* for DEBUG_SISCO */ + +#ifdef __cplusplus +} +#endif + +#endif /* ADLC_LOG_INCLUDED */ + diff --git a/mmslib/inc/adlc_sm.h b/mmslib/inc/adlc_sm.h new file mode 100644 index 0000000..1eecba1 --- /dev/null +++ b/mmslib/inc/adlc_sm.h @@ -0,0 +1,317 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-2002, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : adlc_sm.h */ +/* PRODUCT(S) : ADLC */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains functions that provide for serial port communi- */ +/* cations for the Digiboard. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* ST_INT sm_init(port,baud,parity,data,stop) */ +/* ST_INT sm_exit(port) */ +/* ST_INT sm_put (port,len,buffer) */ +/* ST_INT sm_putc (port,ch) */ +/* ST_INT sm_rx_cnt (port) */ +/* ST_INT sm_get (port,packet,toRead,bytesRead) */ +/* ST_INT sm_getc (port) */ +/* ST_INT sm_rx_flush(port) */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/24/02 KCR 12 Added rdThreadError handling semaphore */ +/* 04/20/98 IKE 11 Moved u_smp_record_time in Serial Manager */ +/* 10/06/97 IKE 10 Added more baud rates */ +/* 09/18/97 IKE 09 Added telephone support */ +/* 05/12/97 IKE 08 Changed to MMSEASE 7.0 Data Types */ +/* 02/03/97 IKE 07 adlcCfg per port basis */ +/* CFG_PORT also for DOS so multiple ports can */ +/* be initialized in dos platform */ +/* 09/19/96 IKE 06 Rearranged sm_get and sm_set functions */ +/* 08/22/96 IKE 05 Added sm_get_dcd for contention avoidance */ +/* 06/11/96 IKE 04 Added more functions to check RS232 signals */ +/* 05/22/96 IKE 03 Added functions to control RS232 signals */ +/* 04/04/96 rkr 02 Cleanup */ +/* 11/12/95 IKE 1 Created */ +/************************************************************************/ + +#ifndef _ADLC_SM_H_ +#define _ADLC_SM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define COM1 0 /* Async Adapter COM1: */ +#define COM2 1 /* Async Adapter COM2: */ +#define COM3 2 /* Async Adapter COM3: */ +#define COM4 3 /* Async Adapter COM4: */ +#define COM5 4 /* Async Adapter COM5: */ +#define COM6 5 /* Async Adapter COM6: */ +#define COM7 6 /* Async Adapter COM7: */ +#define COM8 7 /* Async Adapter COM8: */ +#define COM9 8 /* Async Adapter COM9: */ +#define COM10 9 /* Async Adapter COM10: */ +#define COM11 10 /* ETC. */ +#define COM12 11 +#define COM13 12 +#define COM14 13 +#define COM15 14 +#define COM16 15 +#define COM17 16 +#define COM18 17 +#define COM19 18 +#define COM20 19 +#define COM21 20 +#define COM22 21 +#define COM23 22 +#define COM24 23 +#define COM25 24 +#define COM26 25 +#define COM27 26 +#define COM28 27 +#define COM29 28 +#define COM30 29 +#define COM31 30 +#define COM32 31 +#define COM33 32 +#define COM34 33 + +#define LOW 0 +#define HIGH 1 + +ST_RET sm_init (ST_INT,ST_INT,ST_INT,ST_INT,ST_INT); +ST_RET sm_exit (ST_INT); +ST_RET sm_put (ST_INT,ST_INT, ST_CHAR *); +ST_RET sm_putc (ST_INT, ST_CHAR); +ST_INT sm_rx_cnt (ST_INT port); +ST_INT sm_tx_cnt (ST_INT port); +ST_RET sm_get (ST_INT,ST_CHAR *,ST_INT,ST_INT *); +ST_INT sm_getc (ST_INT); +ST_VOID sm_rx_flush (ST_INT); +ST_RET sm_set_signals (ST_INT port); +ST_RET sm_clear_signals (ST_INT port); +ST_RET sm_set_rts (ST_INT port); +ST_RET sm_clear_rts (ST_INT port); +ST_RET sm_set_dtr (ST_INT port); +ST_RET sm_clear_dtr (ST_INT port); +ST_RET sm_set_rts_clear_dtr(ST_INT port); +ST_RET sm_clear_rts_set_dtr(ST_INT port); +ST_INT sm_get_rts (ST_INT port); +ST_INT sm_get_dtr (ST_INT port); +ST_INT sm_get_cts (ST_INT port); +ST_INT sm_get_dsr (ST_INT port); +ST_INT sm_get_dcd (ST_INT port); + +#if !defined(ADLC_LM) +/* The INIT (ah=00, Int 14h) communications parameters */ + +#define BAUD110 0 /* Baud rate 110 */ +#define BAUD150 1 /* Baud rate 150 */ +#define BAUD300 2 /* Baud rate 300 */ +#define BAUD600 3 /* Baud rate 600 */ +#define BAUD1200 4 /* Baud rate 1200 */ +#define BAUD2400 5 /* Baud rate 2400 */ +#define BAUD4800 6 /* Baud rate 4800 */ +#define BAUD9600 7 /* Baud rate 9600 */ +#define BAUD19200 8 /* Baud rate 19200 */ +#define BAUD38400 9 /* Baud rate 38400 */ +#define BAUD57K 10 /* Baud rate 57.4K */ +#define BAUD115K 11 /* Baud rate 115.2K */ +#define BAUD56K 12 /* Baud rate 56K */ +#define BAUD128K 13 /* Baud rate 128K */ +#define BAUD256K 14 /* Baud rate 256K */ + +#define DATA7 0 /* Data bits 7 */ +#define DATA8 1 /* Data bits 8 */ + +#define NOPAR 0 /* Parity none */ +#define ODDPAR 1 /* Parity odd */ +#define EVENPAR 2 /* Parity even */ + +#define STOP1 0 /* Stop bits 1 */ +#define STOP2 1 /* Stop bits 2 */ + +#endif /* !ADLC_LM */ + +#if defined(ADLC_LM) +/* Request OpCode Definitions */ +#define SM_INITIALIZE_PORT_REQ 0 /* open the port */ +#define SM_TERMINATE_PORT_REQ 1 /* close the port */ +#define SM_READ_REQ 2 /* read from the port */ +#define SM_WRITE_REQ 3 /* write to the port */ +#define SM_IN_BYTE_COUNT_REQ 4 /* check the input Q */ +#define SM_OUT_BYTE_COUNT_REQ 5 /* check the output Q */ +#define SM_GET_STATUS_REQ 6 /* get modem status */ +#define SM_SET_STATUS_REQ 7 /* set modem status */ +#define SM_RX_FLUSH_REQ 8 /* flush recieve buffer */ +#define SM_GET_FRAME_REQ 9 /* respond to frameArr */ + +/* Request Error Code Definitions */ +#define SM_NO_ERR 0 +#define SM_INIT_ERR 1 +#define SM_TX_ERR 2 +#define SM_RX_ERR 3 +#define SM_INVALID_REQ 4 +#define SM_PORT_ALREADY_OPEN 5 +#define SM_OPEN_ERROR 6 +#define SM_SET_BAUD_FAILURE 7 +#define SM_SET_LINE_FAILURE 8 +#define SM_SET_FLOW_FAILURE 9 +#define SM_PORT_NOT_OPEN 10 +#define SM_INVALID_PARAM 11 +#define SM_ERROR 12 +#define SM_NO_FRAMES_AVAILABLE 13 +#define SM_NO_WRITE_CONF_AVIAL 14 +#define SM_SEM_OPEN_FAILURE 15 +#define SM_TERMINATED 16 + +/* Request Status Code Definitions */ +#define SM_COMPLETED 0 +#define SM_PENDING 1 +#define SM_UNDERWAY 2 +#define SM_ABORTED 3 +#define SM_FAILED 4 +#define SM_TX_RX_IN_PROCESS 5 /* pend TX & RX on terminate*/ +#define SM_TX_IN_PROCESS 6 /* pending TX on terminate */ +#define SM_RX_IN_PROCESS 7 /* pending RX on terminate */ + +/* Request Specific Structures */ +typedef struct smRdwrReq + { + ST_INT len; /* num of bytes to read or write */ + ST_CHAR *data; /* user allocates and frees for read or */ + }SM_RDWR_REQ; /* write */ + +typedef struct smFrameReq + { + ST_INT port; /* port the frame was received from */ + ST_INT len; /* frame length */ + ST_CHAR *data; /* SM allocates - user frees!!! */ +#if defined(UCA_SMP) + ST_CHAR recTime[SMP_SIZE_OF_REC_TIME]; /* buffer to hold time stamp */ +#endif + }SM_FRAME_REQ; + +typedef struct smLineParam + { + ST_INT baudRate; /* 300, 1200, 4800, 9600, 19.2, 38.4, 57.6 */ + ST_INT dataBits; /* 5, 6, 7, 8 */ + ST_INT parity; /* 0=none, 1=odd, 2=even, 3=mark, 4=space */ + ST_INT stopBits; /* 0=>1, 1=>1.5 stop bits, 2=>2 */ + }SM_LINE_PARAM; + +typedef struct smHandShake + { + ST_BOOLEAN enableDTR; /* enable DTR input handshaking */ + ST_BOOLEAN enableCTS; /* enable CTS output handshaking */ + ST_BOOLEAN enableDSRout; /* enable DSR output handshaking */ + ST_BOOLEAN enableDCD; /* enable DCD output handshaking */ + ST_BOOLEAN enableDSRin; /* enable DSR input sensitivity */ + ST_BOOLEAN enableRTS; /* enable RTS input handshaking */ + }SM_HAND_SHAKE; + +typedef struct smFlowCtrl + { + ST_BOOLEAN enableTxFlow; /* enable auto transmit XON/XOFF */ + ST_BOOLEAN enableRxFlow; /* enable auto receive XON/XOFF */ + ST_UCHAR xonChar; /* usually 0x11 */ + ST_UCHAR xoffChar; /* usually 0x13 */ + }SM_FLOW_CTRL; + +typedef struct smInitReq + { + SM_LINE_PARAM initLineParam; + SM_HAND_SHAKE initHandShake; + SM_FLOW_CTRL initFlowCtrl; + HANDLE hCom; + ST_INT frameLen; + ST_UCHAR sof; + ST_UCHAR eof; + HEV txDoneSem; + HEV frameArrivalSem; + HEV rdThreadErrSem; + }SM_INIT_REQ; + +typedef struct smStatusReq + { + ST_BOOLEAN dtr; + ST_BOOLEAN rts; + ST_BOOLEAN dcd; + ST_BOOLEAN cts; + ST_BOOLEAN dsr; + }SM_STATUS_REQ; + +/************************************************************************/ +/* SM_REQ */ +/* Every request to serial Manager uses this data structure */ +/************************************************************************/ +typedef struct smReq + { + struct dbl_lnk l; + ST_INT opCode; /* operation requested */ + ST_INT status; + ST_INT errCode; + ST_INT port; + union + { + SM_RDWR_REQ readWriteReq; + SM_INIT_REQ initReq; + SM_STATUS_REQ setStatReq; + } i; /* input data */ + union + { + SM_RDWR_REQ readReq; + SM_STATUS_REQ getStatReq; + ST_INT byteCount; + SM_FRAME_REQ frameArrReq; + }o; /* output data */ + }SM_REQ; + +/* serial manager user access functions */ +ST_RET sm_get_status (ST_INT port,SM_REQ *pstReq); +ST_VOID sm_set_status(ST_INT port, SM_REQ *pstReq); +ST_RET _SmInitialize(ST_VOID); /* startup code */ +ST_RET _SmRequest(SM_REQ *); /* service user requests */ +ST_VOID _SmTerminate(ST_VOID); /* cleanup code */ + +#ifdef ADLC_TESTING +ST_VOID _SmShowStats(ST_INT port); +#endif + +#endif /* ADLC_LM */ + +/************************************************************************/ +/* CFG_PORT */ +/* This data structure is used only when reading the configuration File */ +/* and when opening a port, after that it is not used any more */ +/************************************************************************/ +typedef struct cfgPortStuff + { + struct dbl_lnk l; + ST_INT port; +#if !defined(ADLC_LM) + ST_INT baud; + ST_INT parity; + ST_INT data; + ST_INT stop; +#endif +#if defined(ADLC_LM) + SM_LINE_PARAM stLineParam; + SM_HAND_SHAKE stHandShake; + SM_FLOW_CTRL stFlowCtrl; +#endif + }CFG_PORT; + +#ifdef __cplusplus +} +#endif + +#endif /* adlc_sm.h already included */ diff --git a/mmslib/inc/adlc_sts.h b/mmslib/inc/adlc_sts.h new file mode 100644 index 0000000..795942e --- /dev/null +++ b/mmslib/inc/adlc_sts.h @@ -0,0 +1,82 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-1996, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : adlc_sts.h */ +/* PRODUCT(S) : ADLC */ +/* */ +/* MODULE DESCRIPTION : This header file defines data structures */ +/* and types for rli adlc link manager. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/16/97 IKE 05 Added device statistics and device filt log */ +/* 05/12/97 IKE 04 Changed to MMSEASE 7.0 Data Types */ +/* 04/10/97 EJV 03 Deletes defines ADLC_MASTER, ADLC_SLAVE */ +/* 10/23/96 IKE 02 Added statsResetTime */ +/* 09/30/96 IKE 01 Created */ +/************************************************************************/ + +#ifndef ADLC_STS_H +#define ADLC_STS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ + +/************************************************************************/ +typedef struct tagAdlcStats + { + ST_LONG statsResetTime; /* time stats last reset */ + ST_ULONG txFrames; /* Total transmitted Frames */ + ST_ULONG rxFrames; /* Total received Frames */ + ST_ULONG goodFrames; /* Total good frames received */ + ST_ULONG badFrames; /* Total bad frames when sof was ok */ + ST_ULONG discardedBytes; /* Total discarded bytes */ + ST_ULONG mCastFrames; /* Total Multicast Frames */ + ST_ULONG txPackets; /* Total Transmitted MMS LSDU */ + ST_ULONG rxPackets; /* Total Received MMS LSDU */ + ST_ULONG rxInfo; /* Total Received INFO frames */ + ST_ULONG rxRr; /* Total Received RR frames */ + ST_ULONG rxRnr; /* Total Received RNR frames */ + ST_ULONG rxRej; /* Total Received REJ frames */ + ST_ULONG rxUi; /* Total Received UI frames */ + ST_ULONG txUFrames; /* Total Transmitted Unumbered frames */ + ST_ULONG txSFrames; /* Total Transmitted Supervisory frames */ + ST_ULONG txMFrames; /* Total Transmitted Multicast frames */ + ST_ULONG txIFrames; /* Total Transmitted INFO frames */ + ST_ULONG txUiFrames; /* Total Received UI frames */ + ST_ULONG timeout; /* Total Timeouts */ + ST_ULONG retransmits; /* Total retransmit INFO frames */ + ST_ULONG rxUa; /* Total Received UA frames */ + ST_ULONG rxRd; /* Total Received RD frames */ + ST_ULONG rxDm; /* Total Received DM frames */ + ST_ULONG rxFrmr; /* Total Received FRMR frames */ + ST_ULONG txRFrames; /* Total Received Redirect frames */ + ST_ULONG rxSnrm; /* Total Received SNRM frames */ + ST_ULONG rxDisc; /* Total Received DISC frames */ + } ADLC_STATS; + +#if defined(__OS2__) || defined(_WIN32) +typedef struct tagAdlcDevStats + { + ST_ULONG txFrames; /* Total transmitted Frames */ + ST_ULONG rxFrames; /* Total received Frames */ + ST_ULONG timeout; /* Total Timeouts */ + ST_ULONG retransmits; /* Total retransmitted INFO frames */ + } ADLC_DEV_STATS; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ADLC_STS.H already included */ + diff --git a/mmslib/inc/adlc_usr.h b/mmslib/inc/adlc_usr.h new file mode 100644 index 0000000..eec47f4 --- /dev/null +++ b/mmslib/inc/adlc_usr.h @@ -0,0 +1,441 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-1997, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : adlc_usr.h */ +/* PRODUCT(S) : ADLC */ +/* */ +/* MODULE DESCRIPTION : This header file defines data structures */ +/* and types for ADLC */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/05/03 EJV 21 Chg mms_debug_sel to ST_UINT, and deleted */ +/* L suffix from MMS_LOG_... masks. */ +/* 10/17/01 JRB 20 Del #ifdef UCA_SMP */ +/* 02/04/99 JRB 19 Added adlcStartLinkMan.. */ +/* 10/08/98 MDE 18 Removed ADLC_MASK_LOG_ALWAYS */ +/* 10/21/97 IKE 17 Changed OSI_ADDR to LOCAL_ADDR in error codes*/ +/* 10/14/97 IKE 16 Split into two modules and put all the ipc */ +/* specific stuff into adlc_ipc.h */ +/* 10/1/97 IKE 15 Removed ADLC_LM define if _WIN32 or OS2 is */ +/* defined */ +/* 09/26/97 IKE 14 Added ADLC_M_LOCAL_BASE_ADDR */ +/* 09/22/97 IKE 13 Added SMP(Station Managment Protocol) support*/ +/* 09/18/97 IKE 12 Added telephone support */ +/* 07/16/97 IKE 11 Added support for new ADLC commands */ +/* adlcGetDevStats and adlcFilterDevLog. */ +/* 05/12/97 IKE 10 Changed to MMSEASE 7.0 Data Types */ +/* 04/10/97 EJV 09 Replaced error codes base 0x06xx with 0xA6xx */ +/* 03/13/97 EJV 08 Changes for BRIDGE-132-095 (COGW,RSGW,MCGW): */ +/* - added adlcLogState function; */ +/* 02/24/97 IKE 07 Moved the log masks defn from adlc_log.h */ +/* 01/22/97 IKE 06 Put prototypes for adlcOpenInterface and */ +/* adlcCloseInterface */ +/* 12/03/96 IKE 05 WIN32 Support */ +/* 09/30/96 IKE 04 Removed ifdef PLAIN_DOS for adlcRead func */ +/* so Lean-t stack can use same funct for OS2 */ +/* 05/22/96 IKE 03 Added some more error codes */ +/* 04/04/96 rkr 02 Cleanup */ +/* 01/02/96 IKE 01 Created */ +/************************************************************************/ + +#ifndef ADLC_USR_H +#define ADLC_USR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "adlc_sts.h" + +#include "smp_usr.h" + +#define ADLC_ALL_ES 0x8080 /* ES-Hello Multicast Address */ +#define ADLC_ALL_IS 0x8081 /* IS-Hello Multicast Address */ +#define ALL_STATIONS_ADDR 0xFFFF /* Broadcast Address */ +#define NO_STATION_ADDR 0x0000 /* No station address */ +#define ADLC_M_BASE_LOC_ADDR 0x2000 /* For Adlc Master local Addr */ +#define ADLC_USR_M_BASE_LOC_ADDR 0x3000 /* For user apps local adlc addr*/ + +#define CMD_BASE_ADLC_LM 600 + +/****************************************************************/ +/* Log Control */ +/****************************************************************/ +/* adlc logging mask */ +#define ADLC_MASK_LOG_ERR 0x00010000 +#define ADLC_MASK_LOG_NERR 0x00020000 +#define ADLC_MASK_LOG_FLOW 0x00040000 +#define ADLC_MASK_LOG_IO 0x00080000 +#define ADLC_MASK_LOG_HEXIO 0x00100000 +#define ADLC_MASK_LOG_DEBUG 0x00200000 +#define ADLC_MASK_LOG_HEXDEBUG 0x00400000 +#define ADLC_MASK_LOG_SM 0x01000000 +#define ADLC_MASK_LOG_HEXSM 0x02000000 +#define ADLC_MASK_LOG_INFO_FRAME 0x04000000 +#define ADLC_MASK_LOG_HEXINFO_FRAME 0x08000000 +#define ADLC_MASK_LOG_USER 0x10000000 +#define ADLC_MASK_LOG_HEXUSER 0x20000000 + +extern ST_UINT adlc_debug_sel; +/****************************************************************/ +/* ADLC Command OpCodes */ +/****************************************************************/ + +#define ADLC_CMD_CONNECT_NODE (CMD_BASE_ADLC_LM + 1) +#define ADLC_CMD_DISCONNECT_NODE (CMD_BASE_ADLC_LM + 2) +#define ADLC_CMD_CONNECT_NODE_DONE (CMD_BASE_ADLC_LM + 3) +#define ADLC_CMD_DISCONNECT_NODE_DONE (CMD_BASE_ADLC_LM + 4) +#define ADLC_CMD_CONNECT_ALL (CMD_BASE_ADLC_LM + 5) +#define ADLC_CMD_DISCONNECT_ALL (CMD_BASE_ADLC_LM + 6) +#define ADLC_CMD_WRITE_PACKET (CMD_BASE_ADLC_LM + 7) +#define ADLC_CMD_GET_CON_STATUS (CMD_BASE_ADLC_LM + 8) +#define ADLC_CMD_ADD_DEV (CMD_BASE_ADLC_LM + 9) +#define ADLC_CMD_REMOVE_DEV (CMD_BASE_ADLC_LM + 10) +#define ADLC_CMD_START_POLL_DEV (CMD_BASE_ADLC_LM + 11) +#define ADLC_CMD_STOP_POLL_DEV (CMD_BASE_ADLC_LM + 12) +#define ADLC_CMD_CHANGE_POLL_RATE (CMD_BASE_ADLC_LM + 13) +#define ADLC_CMD_QUERY_POLL_INFO (CMD_BASE_ADLC_LM + 14) + +/* #if ADLC_LM */ +#define ADLC_CMD_SET_SM_SLEEP (CMD_BASE_ADLC_LM + 15) +#define ADLC_CMD_GET_SM_SLEEP (CMD_BASE_ADLC_LM + 16) +#define ADLC_CMD_GET_DEV_STATS (CMD_BASE_ADLC_LM + 17) +#define ADLC_CMD_FILTER_DEV_LOG (CMD_BASE_ADLC_LM + 18) +#define ADLC_CMD_ADD_PORT (CMD_BASE_ADLC_LM + 19) +#define ADLC_CMD_REMOVE_PORT (CMD_BASE_ADLC_LM + 20) +#define ADLC_CMD_TEL_DIAL (CMD_BASE_ADLC_LM + 21) +#define ADLC_CMD_TEL_DIAL_DONE (CMD_BASE_ADLC_LM + 22) +#define ADLC_CMD_TEL_HANGUP (CMD_BASE_ADLC_LM + 23) +#define ADLC_CMD_TEL_HANGUP_DONE (CMD_BASE_ADLC_LM + 24) +/* #endif ADLC_LM */ + +#define ADLC_CMD_EXT_WRITE_PACKET (CMD_BASE_ADLC_LM + 25) +#define ADLC_CMD_EXT_WRITE_PACKET_DONE (CMD_BASE_ADLC_LM + 26) + +#define ADLC_CMD_WRITE_PACKET_DONE (CMD_BASE_ADLC_LM + 27) + + +#define ADLC_DEV_NAME_SIZE 80 + +/************************************************************************/ +/* ADLC_CONNECT_NODE */ +/* This is a bidirectional event */ +/* This could be an event from stack to ADLC and vice versa */ +/************************************************************************/ +typedef struct tagAdlcConnectNode + { + struct + { + ST_UINT16 localAddr; /* OSI node address */ + ST_UINT16 remoteAddr; /* ADLC device address */ + ST_ULONG usr1; /* user data */ + } i; + } ADLC_CONNECT_NODE; + +/************************************************************************/ +/* ADLC_DISCONNECT_NODE */ +/* This is a bidirectional event */ +/* This could be an event from stack to ADLC and vice versa */ +/************************************************************************/ + +typedef ADLC_CONNECT_NODE ADLC_DISCONNECT_NODE; + + +/************************************************************************/ +/* ADLC_CONNECT_NODE_DONE */ +/* This is event from ADLC to stack */ +/************************************************************************/ + +typedef ADLC_CONNECT_NODE ADLC_CONNECT_NODE_DONE; + +/************************************************************************/ +/* ADLC_DISCONNECT_NODE_DONE */ +/* This is event from ADLC to stack */ +/************************************************************************/ +typedef ADLC_CONNECT_NODE ADLC_DISCONNECT_NODE_DONE; + +/************************************************************************/ +/* ADLC_CONNECT_ALL */ +/* This is an event from stack to ADLC */ +/************************************************************************/ +typedef struct tagAdlcConnectAll + { + struct + { + ST_UINT16 localAddr; /* OSI node address */ + ST_ULONG usr1; /* user data */ + } i; + } ADLC_CONNECT_ALL; + +/************************************************************************/ +/* ADLC_DISCONNECT_ALL */ +/* This is an event from stack to ADLC */ +/************************************************************************/ +typedef ADLC_CONNECT_ALL ADLC_DISCONNECT_ALL; + +/************************************************************************/ +/* ADLC_WRITE_PACKET */ +/* This is a bidirectional event */ +/* This could be an event from stack to ADLC and vice versa */ +/************************************************************************/ +typedef struct tagAdlcWritePacket + { + struct /* input parameters */ + { + ST_UINT16 remoteAddr; /* device where data is going */ + ST_UINT16 localAddr; /* device where data comes from */ + ST_INT dataSize; + ST_VOID *data; /* allocated memory */ + ST_ULONG usr1; /* user data */ + } i; + } ADLC_WRITE_PACKET; + +/************************************************************************/ +/* ADLC_WRITE_PACKET_DONE */ +/* This is an event from ADLC to stack */ +/************************************************************************/ +typedef ADLC_WRITE_PACKET ADLC_WRITE_PACKET_DONE; + +/************************************************************************/ +/* ADLC_GET_CON_STATUS */ +/* This is an event from any task to ADLC */ +/************************************************************************/ + +#define ADLC_CON_STATUS_ONLINE 1 +#define ADLC_CON_STATUS_OFFLINE 2 +#define ADLC_CON_STATUS_UNKNOWN 3 + +typedef struct tagAdlcGetConStat + { + struct /* input parameters */ + { + ST_UINT16 remoteAddr; /* ADLC device /remote addr */ + ST_UINT16 localAddr; /* OSI node / local addr */ + } i; + struct /* output parameters */ + { + ST_INT conStatusOut; + } o; + } ADLC_GET_CON_STATUS; + +#define ADLC_NO_POLLING 0 +#define ADLC_POLL_FREQ_HI 1 +#define ADLC_POLL_FREQ_MED 2 +#define ADLC_POLL_FREQ_LOW 3 + +/************************************************************************/ +/* ADLC_ADD_DEV */ +/* This is an event from any task to ADLC */ +/************************************************************************/ +typedef struct tagAdlcAddDev + { + struct /* input parameters */ + { + ST_CHAR devName[ADLC_DEV_NAME_SIZE+1]; + ST_UINT16 address; + ST_INT pollGroup; /* defined above */ + ST_INT port; /* what port it belongs to */ + ST_BOOLEAN connectAll; /* should we try to connect it if connectAll issued */ + ST_ULONG usr1; /* user data */ + } i; + } ADLC_ADD_DEV; + +/************************************************************************/ +/* ADLC_REMOVE_DEV */ +/* This is an event from any task to ADLC */ +/************************************************************************/ +typedef struct tagAdlcRemoveDev + { + struct /* input parameters */ + { + ST_CHAR devName[ADLC_DEV_NAME_SIZE+1]; + ST_ULONG usr1; /* user data */ + } i; + } ADLC_REMOVE_DEV; + +/************************************************************************/ +/* ADLC_START_POLL_DEV */ +/* This is an event from any task to ADLC */ +/************************************************************************/ +typedef struct tagAdlcStartPollDev + { + struct /* input parameters */ + { + ST_CHAR devName[ADLC_DEV_NAME_SIZE+1]; + ST_ULONG usr1; /* user data */ + } i; + } ADLC_START_POLL_DEV; + +/************************************************************************/ +/* ADLC_STOP_POLL_DEV */ +/* This is an event from any task to ADLC */ +/************************************************************************/ +typedef struct tagAdlcStopPollDev + { + struct /* input parameters */ + { + ST_CHAR devName[ADLC_DEV_NAME_SIZE+1]; + ST_ULONG usr1; /* user data */ + } i; + } ADLC_STOP_POLL_DEV; + +/************************************************************************/ +/* ADLC_CHANGE_POLL_RATE */ +/* This is an event from any task to ADLC */ +/************************************************************************/ +/* Notes on changing the poll rate for a device: + To poll the device more frequently set + pollFreqDelta = ADLC_INC_POLL_FREQ; + The device will be moved to the poll group that polls more + frequently. + + Example: current pollGroup=3 with pollRate=n seconds + new pollGroup=2 with pollRate=n-m seconds + + Reverse the above discussion to decrease the polling frequency. */ + +#define ADLC_INC_POLL_FREQ 1 +#define ADLC_DEC_POLL_FREQ 2 + +typedef struct tagAdlcChangePollRate + { + struct /* input parameters */ + { + ST_CHAR devName[ADLC_DEV_NAME_SIZE+1]; + ST_INT pollFreqDelta; /* change to poll freq as */ + ST_ULONG usr1; /* user data */ + } i; /* defined above */ + } ADLC_CHANGE_POLL_RATE; + +/************************************************************************/ +/* ADLC_QUERY_POLL_INFO */ +/* This is an event from any task to ADLC */ +/************************************************************************/ +/* Notes on Polling: + Poll groups range from 1 to n (as of 01/17/96 n=3). All devices + associated with a poll group are polled at the pollRate set for + the poll group. The smaller the poll group the more frequently + the devices are polled. */ + +typedef struct tagQueryPollInfo + { + struct /* input parameters */ + { + ST_CHAR devName[ADLC_DEV_NAME_SIZE+1]; + ST_ULONG usr1; /* user data */ + } i; + struct + { + ST_INT pollGroup; /* current poll group for device*/ + ST_DOUBLE pollRate; /* in mili seconds */ + ST_BOOLEAN bPollingSuspended; /* polling was stopped by user */ + } o; + } ADLC_QUERY_POLL_INFO; + +/************************************************************************/ +/* ADLC_EXT_WRITE_PACKET */ +/* This is a bidirectional event */ +/* This could be an event from stack to ADLC and vice versa */ +/************************************************************************/ +typedef struct tagAdlcExtWritePacket + { + struct /* input parameters */ + { + ST_UINT16 remoteAddr; /* device where data is going */ + ST_UINT16 localAddr; /* device where data comes from */ + ST_INT dataSize; + ST_VOID *data; /* allocated memory */ + ST_LONG userId; /* user passes for done func */ + ST_CHAR recTime[SMP_SIZE_OF_REC_TIME]; /* buffer to hold time stamp */ + ST_ULONG usr1; /* user data */ + } i; + } ADLC_EXT_WRITE_PACKET; + +/************************************************************************/ +/* ADLC_EXT_WRITE_PACKET_DONE */ +/* This is event from ADLC to stack */ +/************************************************************************/ +typedef ADLC_EXT_WRITE_PACKET ADLC_EXT_WRITE_PACKET_DONE; + +/* ADLC defined error codes. The error base 0x3600 is defined in glberror.h */ + +#define E_ADLC_INVALID_DEV_NAME 0x3601 +#define E_ADLC_INVALID_DEV_ADDR 0x3602 +#define E_ADLC_DEVICE_EXISTS 0x3603 +#define E_ADLC_DEV_DOES_NOT_EXIST 0x3604 + +#define E_ADLC_INVALID_LOCAL_ADDR 0x3605 +#define E_ADLC_INVALID_CON_PAIR 0x3606 +#define E_ADLC_CON_EXISTS 0x3607 +#define E_ADLC_CON_DOES_NOT_EXIST 0x3608 +#define E_ADLC_TX_BUF_FULL 0x3609 + +#define E_ADLC_CANT_POLL_FASTER 0x360A +#define E_ADLC_CANT_POLL_SLOWER 0x360B +#define E_ADLC_INVALID_POLL_DELTA 0x360C +#define E_ADLC_INTERNAL_ERR 0x360D +#define E_ADLC_DEVICE_NOT_POLLED 0x360E +#define E_ADLC_INVALID_HQUEUE 0x360F +#define E_ADLC_INVALID_PORT 0x3610 +#define E_ADLC_INVALID_POLL_FREQ 0x3611 +#define E_ADLC_DUPLICATE_LOCAL_ADDR 0x3612 +#define E_ADLC_PACKET_LEN_NOT_VALID 0x3613 + +#define E_ADLC_RESPONSE_TIMEOUT 0x3614 +#define E_ADLC_INVALID_CMD 0x3615 +#define E_ADLC_CANT_INIT_PORT 0x3616 + +#define E_ADLC_CREATE_THREAD 0x3617 +#define E_ADLC_CANT_INIT_TAPI 0x3618 +#define E_ADLC_TEL_LINE_UNAVAIL 0x3619 +#define E_ADLC_CANT_INIT_TEL_LINE 0x361A + +#define E_ADLC_PORT_EXISTS 0x361B +#define E_ADLC_PORT_DOES_NOT_EXIST 0x361C + +#define E_ADLC_SERIAL_TX 0x361D +#define E_ADLC_SERIAL_RX 0x361E + +#define E_ADLC_CANT_OPEN_DB 0x361F +ST_RET adlcWrite(ADLC_WRITE_PACKET *adlcPacket); +ADLC_WRITE_PACKET *adlcRead(ST_VOID); +ST_VOID *adlcGetEvent(ST_INT *opcode, ST_RET *retCode); +ST_RET adlcRegisterClient (ST_UINT16 localAddr); + +/* routines to service ADLC commands */ +ST_RET adlcStartLinkManager (ST_VOID); +ST_RET adlcInit(ST_VOID); +ST_RET adlcConnectNode(ADLC_CONNECT_NODE *pstConNode); +ST_RET adlcDisconnectNode(ADLC_DISCONNECT_NODE *pstDiscNode); +ST_RET adlcConnectAll(ADLC_CONNECT_ALL *pstConAll); +ST_RET adlcDisconnectAll(ADLC_DISCONNECT_ALL *pstDiscAll); +ST_RET adlcWritePacket(ADLC_WRITE_PACKET *adlcPacket); +ST_RET adlcGetConStatus(ADLC_GET_CON_STATUS *pstGetConStatus); +ST_RET adlcAddDev(ADLC_ADD_DEV *pstAddDev); +ST_RET adlcRemoveDev(ADLC_REMOVE_DEV *pstRemoveDev); +ST_RET adlcStartPollingDev(ADLC_START_POLL_DEV *pstStartPollDev); +ST_RET adlcStopPollingDev(ADLC_STOP_POLL_DEV *pstStopPollDev); +ST_RET adlcChangePollRate(ADLC_CHANGE_POLL_RATE *pstChangePollRate); +ST_RET adlcQueryPollInfo(ADLC_QUERY_POLL_INFO *pstQueryPollInfo); +ST_VOID adlcExit (ST_VOID); + +ST_RET adlcExtWritePacket(const ADLC_EXT_WRITE_PACKET *pstExtWrite); + +#ifdef __cplusplus +} +#endif + +#endif /* end ADLC_USR */ + + + + + + diff --git a/mmslib/inc/arg.h b/mmslib/inc/arg.h new file mode 100644 index 0000000..49f8161 --- /dev/null +++ b/mmslib/inc/arg.h @@ -0,0 +1,44 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1991 All Rights Reserved */ +/* */ +/* MODULE NAME : arg.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/25/98 MDE 02 Changed numArgStrings to ST_INT */ +/* 06/23/94 MDE 01 Created */ +/************************************************************************/ +/************************************************************************/ + + +ST_INT process_args (ST_INT argc, ST_CHAR **argv); +ST_VOID listValidArgs (ST_VOID); + +/************************************************************************/ + +struct arg_ctrl + { + ST_CHAR *str; /* text to be matched */ + ST_CHAR *help; /* Help text */ + ST_VOID (*fun)(ST_INT argNum, ST_CHAR *str); /* processing function */ + }; + +extern ST_INT argRetVal; +extern ST_INT argStopProc; +extern ST_INT argCurrArg; +extern ST_CHAR **argArgv; + + +/* User must define these variables */ +extern struct arg_ctrl argCtrl[]; +extern ST_INT numArgStrings; + diff --git a/mmslib/inc/asn1defs.h b/mmslib/inc/asn1defs.h new file mode 100644 index 0000000..8c43328 --- /dev/null +++ b/mmslib/inc/asn1defs.h @@ -0,0 +1,40 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : asn1defs.h */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Contains definitions and global variables useful to the ASN1DE */ +/* user. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/19/01 JRB 14 Del everything & use "asn1r.h". */ +/* 11/14/01 EJV 13 Added MMS_UTC_TIME typedef. */ +/* Added asn1_wr_utc_time, asn1_get_utc_time */ +/* 06/22/00 DSF 12 Added asn1_max_bitcount */ +/* 06/16/00 JRB 11 Add #if INT64_SUPP... */ +/* 05/24/00 RKR 10 Deleted a an extra declaration of asn1_tzone */ +/* 09/13/99 MDE 09 Added SD_CONST modifiers */ +/* 10/08/98 MDE 08 Migrated to updated SLOG interface */ +/* 03/18/98 JRB 07 Add ASN1E_* defines. */ +/* Move ASN1 error codes from mmsintr2.h to here*/ +/* Add 0x7000 to all ASN.1 error codes. */ +/* 12/10/97 MDE 06 Changed get_i8 to take ST_INT8 */ +/* 09/29/97 MDE 05 Changed ASN1_LITE to MMS_LITE */ +/* 08/21/97 MDE 04 Added ASN1_ARB_FLOAT define */ +/* 08/13/97 MDE 03 Changed wr_i8 and wr_u8 to take sized int's */ +/* 06/17/97 MDE 02 Removed old debug defines */ +/* 05/20/97 MDE 01 Changes to time handling - renames, etc. */ +/* 04/02/97 7.00 MMSEASE 7.0 release. See ASN1ML70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "asn1r.h" /* Simply use all new defs in this file */ diff --git a/mmslib/inc/asn1log.h b/mmslib/inc/asn1log.h new file mode 100644 index 0000000..4d7676c --- /dev/null +++ b/mmslib/inc/asn1log.h @@ -0,0 +1,106 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 1994, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : asn1log.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains ASN.1 logging definitions */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/16/03 JRB 06 Add more ERR/NERR macros. */ +/* 03/31/03 JRB 05 Use new "Base" macros SLOG_*, SLOGC_*, SLOGH.*/ +/* Add more macros. */ +/* 03/13/02 JRB 04 ALOG_PAUSEDEC, ALOG_DECLF macros do nothing. */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 10/08/98 MDE 02 Migrated to updated SLOG interface */ +/* 09/11/97 DSF 01 Adde ALOG_NERRH */ +/* 04/02/97 7.00 MMSEASE 7.0 release. See ASN1ML70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef ASN1_LOG_INCLUDED +#define ASN1_LOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/* Log type strings */ +extern SD_CONST ST_CHAR *SD_CONST _asn1_log_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _asn1_log_enc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _asn1_log_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _asn1_log_nerr_logstr; + + +#define ALOG_DECLF() +#define ALOG_PAUSEDEC(msg) + +#define ALOG_DEC0(a) \ + SLOG_0 (asn1_debug_sel & ASN1_LOG_DEC,_asn1_log_dec_logstr,a) +#define ALOG_DEC1(a,b) \ + SLOG_1 (asn1_debug_sel & ASN1_LOG_DEC,_asn1_log_dec_logstr,a,b) + +#define ALOG_CDEC0(a) \ + SLOGC_0 (asn1_debug_sel & ASN1_LOG_DEC,a) +#define ALOG_CDEC1(a,b) \ + SLOGC_1 (asn1_debug_sel & ASN1_LOG_DEC,a,b) +#define ALOG_CDEC2(a,b,c) \ + SLOGC_2 (asn1_debug_sel & ASN1_LOG_DEC,a,b,c) +#define ALOG_CDEC3(a,b,c,d) \ + SLOGC_3 (asn1_debug_sel & ASN1_LOG_DEC,a,b,c,d) +#define ALOG_CDEC4(a,b,c,d,e) \ + SLOGC_4 (asn1_debug_sel & ASN1_LOG_DEC,a,b,c,d,e) + +#define ALOG_DECH(a,b) \ + SLOGH (asn1_debug_sel & ASN1_LOG_DEC,a,b) + +#define ALOG_ENC0(a) \ + SLOG_0 (asn1_debug_sel & ASN1_LOG_ENC,_asn1_log_enc_logstr,a) +#define ALOG_ENC1(a,b) \ + SLOG_1 (asn1_debug_sel & ASN1_LOG_ENC,_asn1_log_enc_logstr,a,b) + +#define ALOG_CENC0(a) \ + SLOGC_0 (asn1_debug_sel & ASN1_LOG_ENC,a) +#define ALOG_CENC1(a,b) \ + SLOGC_1 (asn1_debug_sel & ASN1_LOG_ENC,a,b) + +#define ALOG_ENCH(a,b) \ + SLOGH (asn1_debug_sel & ASN1_LOG_ENC,a,b) + +#define ALOG_ERR0(a) \ + SLOG_0 (asn1_debug_sel & ASN1_LOG_ERR,_asn1_log_err_logstr,a) +#define ALOG_ERR1(a,b) \ + SLOG_1 (asn1_debug_sel & ASN1_LOG_ERR,_asn1_log_err_logstr,a,b) +#define ALOG_ERR2(a,b,c) \ + SLOG_2 (asn1_debug_sel & ASN1_LOG_ERR,_asn1_log_err_logstr,a,b,c) +#define ALOG_ERR3(a,b,c,d) \ + SLOG_3 (asn1_debug_sel & ASN1_LOG_ERR,_asn1_log_err_logstr,a,b,c,d) + +#define ALOG_NERR0(a) \ + SLOG_0 (asn1_debug_sel & ASN1_LOG_NERR,_asn1_log_nerr_logstr,a) +#define ALOG_NERR1(a,b) \ + SLOG_1 (asn1_debug_sel & ASN1_LOG_NERR,_asn1_log_nerr_logstr,a,b) +#define ALOG_NERR2(a,b,c) \ + SLOG_2 (asn1_debug_sel & ASN1_LOG_NERR,_asn1_log_nerr_logstr,a,b,c) +#define ALOG_NERR3(a,b,c,d) \ + SLOG_3 (asn1_debug_sel & ASN1_LOG_NERR,_asn1_log_nerr_logstr,a,b,c,d) + +#define ALOG_NERRH(a,b) \ + SLOGH (asn1_debug_sel & ASN1_LOG_NERR,a,b) + +#ifdef __cplusplus +} +#endif + + +/************************************************************************/ +#endif /* End of ASN1_LOG_INCLUDED */ +/************************************************************************/ diff --git a/mmslib/inc/asn1r.h b/mmslib/inc/asn1r.h new file mode 100644 index 0000000..058f6bb --- /dev/null +++ b/mmslib/inc/asn1r.h @@ -0,0 +1,718 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2009, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : asn1r.h */ +/* PRODUCT(S) : ASN1DE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Contains definitions and global variables useful to the ASN1DE */ +/* user. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/21/09 JRB 31 Add asn1r_bitstr_truncated in ASN1_DEC_CTXT. */ +/* Del GET_CONSTRUCTED_*STRINGS defines. */ +/* 05/28/09 JRB 30 Add asn1r_decode_init, asn1r_get_tag functs. */ +/* Add asn1r_msg_start in ASN1_DEC_CTXT struct. */ +/* Add asn1r_strt_constr_indef. */ +/* 01/15/09 MDE 29 Added asn1_peek, removed asn1r_head_decode */ +/* 11/12/08 MDE 28 Added asn1r_last_byte, asn1r_head_decode rc */ +/* 07/02/07 JRB 26 Chg ..fixlen, ..varlen arg to (ST_UCHAR *). */ +/* 12/20/06 JRB 25 Add bstrcmp. */ +/* 03/17/06 JRB 24 Add asn1r_anytag_fun, ASN1_ANYTAG_METHOD, */ +/* ASN1MASK_*. */ +/* Chg BSTR_BIT_GET macro to return only 0 or 1.*/ +/* 12/05/05 JRB 23 Add asn1r_skip_elmnt & more asn1r_get* protos*/ +/* 08/01/05 JRB 22 Add const on asn1r_wr_vstr, asn1_wr_octstr args.*/ +/* 03/23/05 JRB 21 Move APP_REF from suicacse to here so almost */ +/* any SISCO app can use it. */ +/* 07/08/04 JRB 20 Add define TIME_T_1984_JAN_1 & other defines.*/ +/* Add asn1_convert_timet_to_btime6. */ +/* 10/13/03 JRB 19 Add ASN1E_DECODE_OTHER, ASN1E_ENCODE_OTHER. */ +/* 03/31/03 JRB 18 Add UTF8string support. */ +/* asn1r_get_bitstr: add max_bits arg. */ +/* 12/14/02 JRB 17 Add BSTR_*, MMS_BVSTRING, bstrcpy, bvstrcpy */ +/* 11/11/02 EJV 16 asn1r_tag_add: added type cast */ +/* 11/08/02 JRB 15 Add ASN1_DEC_PTR, ASN1_DEC_LEN macros. */ +/* 10/29/02 JRB 14 Add asn1r_magic to ASN1_ENC_CTXT. */ +/* 10/25/02 JRB 13 Add ASN1_ENC_PTR, ASN1_ENC_LEN macros. */ +/* Add MMS_BTIME6 struct. */ +/* 07/03/02 EJV 12 MMS_UTC_TIME: chg name usec to fraction. */ +/* 01/22/02 JRB 11 Add "asn1r_buf_end" to ASN1_ENC_CTXT. */ +/* Chg asn1r_end_of_buffer to asn1r_buf_start */ +/* & asn1r_field_start to asn1r_field_end */ +/* & _asn1_constr_start to asn1r_constr_end */ +/* in ENC_CTX (start means start, end means end)*/ +/* 01/07/02 EJV 09 Added asn1_ prefix to convert_... functions. */ +/* 01/04/02 EJV 08 Add convert_btod_to_utc, convert_utc_to_btod */ +/* 12/20/01 JRB 07 Split ASN1_CTXT into ASN1_DEC_CTXT, ASN1_ENC_CTXT*/ +/* Del unused calendar stuff. */ +/* Del backward compatibility defines. */ +/* Chg asn1r_objidcmp to asn1_objidcmp. */ +/* Del unused tzhour_diff, tconst, default_dcomp*/ +/* Del unused strt_asn1,asn1_tz_calc,asn1_is_dst*/ +/* 11/09/01 EJV 06 Added MMS_UTC_TIME typedef. */ +/* Added asn1r_wr_utc_time, asn1r_get_utc_time */ +/* ASN1_CTXT: del _save_asn1_len, _save_asn1_ptr*/ +/* 08/15/00 JRB 05 Add asn1_ctxt "forward reference". */ +/* 06/19/00 JRB 04 Add #if INT64_SUPP... */ +/* 05/25/00 RKR 03 Deleted a an extra declaration of asn1_tzone */ +/* 07/29/99 MDE 02 Added TABLE method */ +/* 07/26/99 MDE 01 New, derived from asn1defs.h */ +/************************************************************************/ + +#if !defined(ASN1DEFS_INCLUDED) && !defined(ASN1R_INCLUDED) +#define ASN1R_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ + +#include "slog.h" + +/* Defines for UNICODE local data format. */ +#define UNICODE_UTF8 0 +#define UNICODE_UTF16 1 +#if !defined(UNICODE_LOCAL_FORMAT) +#if defined(_WIN32) +#define UNICODE_LOCAL_FORMAT UNICODE_UTF16 +#else +#define UNICODE_LOCAL_FORMAT UNICODE_UTF8 /*default format */ +#endif +#endif /* !defined(UNICODE_LOCAL_FORMAT) */ + +/************************************************************************/ +/* asn1_debug_sel bit assignments */ + +#define ASN1_LOG_DEC 0x0001 +#define ASN1_LOG_ENC 0x0002 +#define ASN1_LOG_ERR 0x0004 +#define ASN1_LOG_NERR 0x0008 + +/************************************************************************/ +/* These are S_LOG control items for ASN1 logging */ + +extern ST_UINT asn1_debug_sel; + +/************************************************************************/ +/* Support for development time debugging can be enabled here */ +/* #define DEBUG_ASN1_DECODE */ + +/************************************************************************/ +/* Support for seldom needed decode features can be disabled here */ + +#if !defined(MMS_LITE) +#define ASN1_ARB_FLOAT +#endif + +/************************************************************************/ +/* Helpful Time-related defines */ + +#define SECONDS_PER_DAY (60*60*24) +#define MILLISECONDS_PER_DAY (1000 * SECONDS_PER_DAY) +#define DAYS_FROM_1970_TO_1984 ((11*365) + (3*366)) /*includes 3 leap years 1972, 1976, 1980*/ +#define TIME_T_1984_JAN_1 (DAYS_FROM_1970_TO_1984 * SECONDS_PER_DAY) + +/************************************************************************/ +/* Binary Time Of Day */ + +#define MMS_BTOD4 4 +#define MMS_BTOD6 6 + +typedef struct btod_data + { + ST_INT form; /* MMS_BTOD6, MMS_BTOD4 */ + ST_INT32 ms; /* Number of milliseconds since midnight */ + ST_INT32 day; /* Number of days since Jan 1, 1984 */ + } MMS_BTOD; + +/* MMS_BTIME6: this structure is the format used to pass "Btime6" data */ +/* (i.e. ISO/IEC 9506-2 TimeOfDay with size=6) between the user and */ +/* the ASN.1 encoder/decoder (i.e. ms_asn1_to_local & ms_local_to_asn1).*/ +typedef struct + { + ST_INT32 ms; /* Number of milliseconds since midnight */ + ST_INT32 day; /* Number of days since Jan 1, 1984 */ + } MMS_BTIME6; + +/************************************************************************/ +/* UTC Time */ + +typedef struct mms_utc_time_tag + { + ST_UINT32 secs; /* Number of seconds since January 1, 1970 */ + ST_UINT32 fraction; /* Fraction of a second */ + ST_UINT32 qflags; /* Quality flags, 8 least-significant bits only */ + } MMS_UTC_TIME; + +ST_RET asn1_convert_btod_to_utc (MMS_BTOD *btod, MMS_UTC_TIME *utc); +ST_RET asn1_convert_utc_to_btod (MMS_UTC_TIME *utc, MMS_BTOD *btod); +ST_RET asn1_convert_timet_to_btime6 (time_t tThis, MMS_BTIME6 *bTime6); + +/************************************************************************/ +/* Variable Length Bitstring */ +/* This structure defines the format used to pass "variable length */ +/* bitstring" data between the user and */ +/* the ASN.1 encoder/decoder (i.e. ms_asn1_to_local & ms_local_to_asn1).*/ +/* NOTE: For bitstrings longer than 8 bits, the actual data extends */ +/* beyond the end of this struct. */ + +typedef struct + { + ST_INT16 len; + ST_UCHAR data[1]; + } MMS_BVSTRING; + +/************************************************************************/ +/* VMS Float Format select */ + +#define A_D_FLOAT 1 +#define A_G_FLOAT 2 +extern ST_INT asn1_vax_double_type; + +/************************************************************************/ +/* ASN1-DE limitiations */ + +#define ASN1_MAX_PDU 0x7FFF /* maximum decodable message length */ +#define ASN1_MAX_FIELD 0x7FFF /* maximum field (data element) length */ +#define ASN1_MAX_LEVEL 50 /* maximum supported nesting level */ + +/************************************************************************/ +/* ASN.1 Definitions to support identifier construction by bit OR. */ +/* Used to make up and test 'tag' bits. */ + +/* These used in ASN1_ANYTAG_METHOD decode method. */ +#define ASN1MASK_UNI 0x0000 /* universal class */ +#define ASN1MASK_APP 0x4000 /* application wide */ +#define ASN1MASK_CTX 0x8000 /* context specific */ +#define ASN1MASK_PRV 0xC000 /* private use */ +#define ASN1MASK_CONSTR 0x2000 /* constructor */ + +/* These used in other decode methods and in encoder. */ +#define UNI 0x00 /* universal class */ +#define APP 0x40 /* application wide */ +#define CTX 0x80 /* context specific */ +#define PRV 0xC0 /* private use */ +#define CONSTR 0x20 /* constructor */ + +#define DEF 0x00 /* definite length constructor */ +#define INDEF 0xFF /* indefinite length constructor */ + +/* Universal class ASN.1 ID code definitions */ +#define EOC_CODE 0x00 +#define BOOL_CODE 0x01 +#define INT_CODE 0x02 +#define BITS_CODE 0x03 +#define OCT_CODE 0x04 +#define NULL_CODE 0x05 +#define OBJ_ID_CODE 0x06 +#define OBJDSCR_CODE 0x07 +#define EXTERN_CODE 0x08 +#define SEQ_CODE 0x10 +#define SET_CODE 0x11 +#define NUMSTR_CODE 0x12 +#define PRTSTR_CODE 0x13 +#define S61STR_CODE 0x14 +#define S100STR_CODE 0x15 +#define IA5STR_CODE 0x16 +#define UTCTIM_CODE 0x17 +#define GENTIM_CODE 0x18 +#define GRAFSTR_CODE 0x19 +#define VISTR_CODE 0x1A +#define GENSTR_CODE 0x1B + + +/************************************************************************/ +/* ASN.1 decode error definitions */ +/* Used as the argument to "asn1_set_dec_err" function which sets the */ +/* global variable "asn1_pdu_dec_err". */ +/************************************************************************/ + +#define NO_DECODE_ERR 0 /* no decode error */ +#define ASN1E_NEST_TOO_DEEP 0x7001 +#define ASN1E_UNEXPECTED_CLASS 0x7002 +#define ASN1E_UNEXPECTED_TAG 0x7003 +#define ASN1E_ID_TOO_BIG 0x7004 +#define ASN1E_CSTR_INVALID_LEN 0x7005 +#define ASN1E_INVALID_LENGTH 0x7006 +#define ASN1E_UNEXPECTED_FORM 0x7007 +#define ASN1E_PDU_TOO_BIG 0x7008 +#define ASN1E_END_O_BUFFER 0x7009 +#define ASN1E_BITCSTR_TOO_BIG 0x700a +#define ASN1E_INVALID_BITSTR 0x700b +#define ASN1E_OCTSTR_TOO_BIG 0x700c +#define ASN1E_INVALID_BOOLEAN 0x700d +#define ASN1E_END_OF_MESSAGE 0x700e +#define ASN1E_END_OF_CSTR 0x700f + +/* CRITICAL: The rest of the ASN.1 decode error definitions must not */ +/* must not be changed. The lower 2 nibbles are used to set the */ +/* REJECT class and code (mmsdec_map_err saves value to rslt.err_code */ +/* which is used in "mmspdu.c" to generate REJECT class and code). */ + +/************************************************************************/ +/* CONFIRMED REQUEST REJECT DEFINITIONS */ +/************************************************************************/ +#define REQ_UNSPECIFIED 0x7010 +#define REQ_UNREC_SERV 0x7011 +#define REQ_UNREC_MOD 0x7012 +#define REQ_INVAL_INVOKE 0x7013 +#define REQ_INVAL_ARG 0x7014 +#define REQ_INVAL_MOD 0x7015 +#define REQ_OUTSTD_EXCEED 0x7016 +#define REQ_EXCSV_LENGTH 0x7017 +#define REQ_EXCSV_NEST 0x7018 +#define REQ_BAD_VALUE 0x7019 + +/************************************************************************/ +/* CONFIRMED RESPONSE REJECT DEFINITIONS */ +/************************************************************************/ +#define RESP_UNSPECIFIED 0x7020 +#define RESP_UNREC_SERV 0x7021 +#define RESP_INVAL_INVOKE 0x7022 +#define RESP_INVAL_RSLT 0x7023 +#define RESP_EXCSV_LENGTH 0x7024 +#define RESP_EXCSV_NEST 0x7025 +#define RESP_BAD_VALUE 0x7026 + +/************************************************************************/ +/* CONFIRMED ERROR REJECT DEFINITIONS */ +/************************************************************************/ +#define ERR_UNSPECIFIED 0x7030 +#define ERR_UNREC_SERV 0x7031 +#define ERR_INVAL_INVOKE 0x7032 +#define ERR_INVAL_SERV 0x7033 +#define ERR_BAD_VALUE 0x7034 + +/************************************************************************/ +/* UNCONFIRMED PDU REJECT DEFINITIONS */ +/************************************************************************/ +#define UNCONF_UNSPECIFIED 0x7040 +#define UNCONF_UNREC_SERV 0x7041 +#define UNCONF_INVAL_ARG 0x7042 +#define UNCONF_EXCSV_NEST 0x7043 +#define UNCONF_BAD_VALUE 0x7044 + +/************************************************************************/ +/* PDU REJECT DEFINITIONS */ +/************************************************************************/ +#define PDU_UNKNOWN_TYPE 0x7050 +#define PDU_INVALID 0x7051 + +/************************************************************************/ +/* CANCEL REQUEST REJECT DEFINITIONS */ +/************************************************************************/ +#define CANREQ_UNSPECIFIED 0x7060 +#define CANREQ_INVAL_INVOKE 0x7061 + +/************************************************************************/ +/* CANCEL RESPONSE REJECT DEFINITIONS */ +/************************************************************************/ +#define CANRESP_UNSPECIFIED 0x7070 +#define CANRESP_INVAL_INVOKE 0x7071 + +/************************************************************************/ +/* CANCEL ERROR REJECT DEFINITIONS */ +/************************************************************************/ +#define CANERR_UNSPECIFIED 0x7080 +#define CANERR_INVAL_INVOKE 0x7081 +#define CANERR_INVAL_SERV 0x7082 +#define CANERR_BAD_VALUE 0x7083 + +/************************************************************************/ +/* CONCLUDE REQUEST REJECT DEFINITIONS */ +/************************************************************************/ +#define CONREQ_UNSPECIFIED 0x7090 +#define CONREQ_INVAL_ARG 0x7091 + +/************************************************************************/ +/* CONCLUDE RESPONSE REJECT DEFINITIONS */ +/************************************************************************/ +#define CONRESP_UNSPECIFIED 0x70A0 +#define CONRESP_INVAL_RSLT 0x70A1 + +/************************************************************************/ +/* CONCLUDE ERROR REJECT DEFINITIONS */ +/************************************************************************/ +#define CONERR_UNSPECIFIED 0x70B0 +#define CONERR_INVAL_SERV 0x70B1 +#define CONERR_BAD_VALUE 0x70B2 + +/************************************************************************/ +/* OTHER ASN.1 ENCODE/DECODE ERROR DEFINITIONS */ +/************************************************************************/ +#define ASN1E_DECODE_OTHER 0x70C0 +#define ASN1E_ENCODE_OTHER 0x70C1 + +/************************************************************************/ +/* General variables and pointers used by the ASN1 system. */ +/************************************************************************/ + +#define ASN1_TAG_METHOD 0 /* decode by tag method */ +#define ASN1_CLASS_METHOD 1 /* decode by class method */ +#define ASN1_TABLE_METHOD 2 /* decode by table method */ +#define ASN1_ANYTAG_METHOD 3 /* decode by "anytag" method */ + /* same callback for any tag of any class*/ +#define CSTR_DONE_FUN ac->asn1r_c_done_fun[ac->asn1r_msg_level] + +/************************************************************************/ +/* This define is the maximum tag + length for a MMS-EASE encoded data */ +/* element (actually probably is 9), and is used in fin_constr and */ +/* fin_prim to prevent encode buffer overrun */ + +#define ASN1_MAX_ELEMENT_OVERHEAD 10 + +struct asn1_dec_ctxt; /* Forward reference */ +/************************************************************************/ +/************************************************************************/ +/* TAG METHOD STRUCTURES AND DEFINES */ + +#define ASN1R_TAG_VAL(class,code) (((ST_UINT16)(class) << 8) | (code)) + +typedef struct + { + ST_UINT16 _asn1r_tag; + ST_VOID (*_asn1r_tag_fun)(struct asn1_dec_ctxt *ac); + } ASN1R_TAG_PAIR; + +/* Decode users: Select the structure that has sufficient tag capacity */ +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[1]; } ASN1R_TAG_CTRL_1; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[2]; } ASN1R_TAG_CTRL_2; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[3]; } ASN1R_TAG_CTRL_3; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[4]; } ASN1R_TAG_CTRL_4; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[5]; } ASN1R_TAG_CTRL_5; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[6]; } ASN1R_TAG_CTRL_6; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[7]; } ASN1R_TAG_CTRL_7; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[8]; } ASN1R_TAG_CTRL_8; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[9]; } ASN1R_TAG_CTRL_9; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[10];} ASN1R_TAG_CTRL_10; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[11];} ASN1R_TAG_CTRL_11; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[12];} ASN1R_TAG_CTRL_12; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[13];} ASN1R_TAG_CTRL_13; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[14];} ASN1R_TAG_CTRL_14; +typedef struct {ST_INT num_tags; ASN1R_TAG_PAIR tags[15];} ASN1R_TAG_CTRL_15; + + +/************************************************************************/ +/* ASN.1 Context */ +/* This data structure is used to store all ASN.1 encode/decode context */ +/* information. If an application provides thread safe storage for this */ +/* data structure the ASN.1 tools become thread safe. */ + +#define ASN1_MAX_USR_INFO 5 +#define MAX_TAG_FUN 16 + +typedef struct asn1_dec_ctxt + { +/****** User and Internal Use ******/ + +/* User State */ + ST_VOID *usr_info[ASN1_MAX_USR_INFO]; + +/* General variables and pointers */ + ST_BOOLEAN asn1r_decode_done; + ST_UCHAR *asn1r_field_ptr; + ST_UCHAR *asn1r_field_start; + ST_UCHAR *asn1r_done_ptr; + ST_UCHAR asn1r_constr_elmnt; + ST_UCHAR asn1r_elmnt_class; + ST_UINT16 asn1r_elmnt_id; + ST_INT asn1r_elmnt_len; + ST_INT asn1r_msg_level; + ST_BOOLEAN asn1r_indef_flag; /* flag for indef cstr */ + ST_RET asn1r_pdu_dec_err; + ST_INT asn1r_decode_method; + ST_INT asn1r_save_method; + ST_INT asn1r_max_bits; + ST_INT asn1r_bitcount; + ST_BOOLEAN asn1r_bitstr_truncated; /* SD_TRUE if bitstr truncated */ + /* while decoding. */ + ST_INT asn1r_octetcount; + +/* For ASN1 decode table mode */ + ST_VOID *asn1r_tag_table; + +/* Function pointers used by decoder users */ + ST_VOID (*asn1r_decode_done_fun)(struct asn1_dec_ctxt *ac); + ST_VOID (*asn1r_err_fun)(struct asn1_dec_ctxt *ac, ST_RET err_code); + ST_VOID (*asn1r_c_done_fun[ASN1_MAX_LEVEL])(struct asn1_dec_ctxt *ac); + ST_VOID (*asn1r_u_id_fun)(struct asn1_dec_ctxt *ac, ST_UINT16 id); + ST_VOID (*asn1r_a_id_fun)(struct asn1_dec_ctxt *ac, ST_UINT16 id); + ST_VOID (*asn1r_c_id_fun)(struct asn1_dec_ctxt *ac, ST_UINT16 id); + ST_VOID (*asn1r_p_id_fun)(struct asn1_dec_ctxt *ac, ST_UINT16 id); + /* asn1r_anytag_fun called for ANY tag of ANY class if */ + /* asn1r_decode_method==ASN1_ANYTAG_METHOD. */ + /* "id" argument has bits set to indicate class and/or constructor. */ + ST_VOID (*asn1r_anytag_fun)(struct asn1_dec_ctxt *ac, ST_UINT16 id); + +/****** Internal Use Only ******/ +/* Decode variables */ + ST_INT _asn1_maxoctets; + ST_UCHAR *_asn1_octetptr; + + ST_UCHAR *_ad_bitptr; + +/* Function pointers used internally by the ASN.1 tools */ + ST_VOID (*_asn1r_cstr_done_save)(struct asn1_dec_ctxt *ac); + ST_VOID (*_asn1r_fun_save)(struct asn1_dec_ctxt *ac); + + ST_INT _asn1r_ntag; + ST_UINT16 _asn1r_valid_tags[MAX_TAG_FUN]; + ST_VOID (*_asn1r_tag_fun[MAX_TAG_FUN])(struct asn1_dec_ctxt *ac); + ST_INT _asn1r_old_ntag; + + ST_BOOLEAN _asn1_indef_track[ASN1_MAX_LEVEL]; + ST_UCHAR *_asn1_constr_start[ASN1_MAX_LEVEL]; + ST_INT _asn1_byte_count[ASN1_MAX_LEVEL]; + + ST_INT _ad_parse_method_save; + ST_VOID (*_ad_parse_asn1r_fun_save)(struct asn1_dec_ctxt *ac); + + ST_UCHAR *_contents_done; /* will be here when done parsing cstr contents */ + ST_UCHAR *_parse_begin_ptr; /* pointer to beginning of element being skipped*/ + + ST_UCHAR *asn1r_msg_start; /* ptr to beginning of ASN.1 message */ + /* used to calc offset within message */ + /* set by asn1r_decode_init */ + /* used by asn1r_get_tag */ + } ASN1_DEC_CTXT; + +typedef struct asn1_enc_ctxt + { +/* General variables and pointers */ + ST_UCHAR *asn1r_field_ptr; + ST_UCHAR *asn1r_field_end; + ST_INT asn1r_msg_level; + ST_UCHAR *asn1r_buf_start; /* ptr to first byte of buffer */ + ST_UCHAR *asn1r_buf_end; /* ptr to last byte of buffer */ + ST_BOOLEAN asn1r_encode_overrun; + ST_UINT16 asn1r_magic; /* Use to verify asn1r_strt.. was called*/ + ST_UCHAR *asn1r_constr_end[ASN1_MAX_LEVEL]; + } ASN1_ENC_CTXT; + +/* Set "asn1r_magic" in ASN1_ENC_CTXT to this value in "asn1r_strt_asn1_bld".*/ +/* Check later to be sure asn1r_strt_asn1_bld was called. */ +#define ASN1_ENC_MAGIC_NUMBER 0xABCD +/************************************************************************/ + +ASN1_DEC_CTXT *asn1r_get_ctxt (ST_VOID); + +ST_VOID asn1r_decode_asn1 (ASN1_DEC_CTXT *ac, ST_UCHAR *ptr, ST_INT len); +ST_VOID asn1r_decode_asn1_seq (ASN1_DEC_CTXT *ac, ST_UCHAR *ptr, ST_INT len); +ST_VOID asn1r_set_dec_err (ASN1_DEC_CTXT *ac, ST_RET err_code); +ST_VOID asn1r_done_err (ASN1_DEC_CTXT *ac); +ST_VOID asn1r_cstr_done_err (ASN1_DEC_CTXT *ac); +ST_VOID asn1r_set_all_cstr_done (ASN1_DEC_CTXT *ac); + + +ST_VOID asn1r_class_err (ASN1_DEC_CTXT *ac, ST_UINT16 id); +ST_VOID asn1r_chk_getcstr_done (ASN1_DEC_CTXT *ac); + +#if !defined(ASN1R_FAST_TAG_ADD) + +#define ASN1R_TAG_ADD(ac, class, code, fcn_ptr)\ + asn1r_tag_add (ac, (ST_UINT16)(((ST_UINT16)(class) << 8) | (code)), (fcn_ptr)) + +#else + +#define ASN1R_TAG_ADD(ac, class, code, fcn_ptr)\ + {\ + ac->_asn1r_valid_tags[ac->_asn1r_ntag] = \ + (((ST_UINT16)(class) << 8) | (code));\ + ac->_asn1r_tag_fun[ac->_asn1r_ntag] = (ST_VOID (*)(ASN1_DEC_CTXT *)) fcn_ptr;\ + ac->_asn1r_ntag++;\ + } +#endif + + +#define ASN1R_TAG_DEL(ac, class, code)\ + asn1r_tag_del (ac, (((ST_UINT16)(class) << 8) | (code))) + +ST_VOID asn1r_tag_add (ASN1_DEC_CTXT *ac, ST_UINT16 tag_class, + ST_VOID (*fcn_ptr)(ASN1_DEC_CTXT *ac)); + +ST_VOID asn1r_tag_del (ASN1_DEC_CTXT *ac, ST_UINT16 tag); +ST_VOID asn1r_tag_restore (ASN1_DEC_CTXT *ac); +ST_RET asn1_peek (ASN1_DEC_CTXT *ac, ST_UCHAR *ptr, ST_INT len); + +ST_VOID asn1r_strt_asn1_bld (ASN1_ENC_CTXT *ac, ST_UCHAR *bufptr, ST_INT buflen); +ST_VOID asn1r_fin_prim (ASN1_ENC_CTXT *ac, ST_UINT16 id_code, ST_UINT16 tag); +ST_VOID asn1r_fin_constr (ASN1_ENC_CTXT *ac, ST_UINT16 id_code, ST_UINT16 el_tag, ST_BOOLEAN indef); +ST_VOID asn1r_strt_constr (ASN1_ENC_CTXT *ac); +ST_VOID asn1r_strt_constr_indef (ASN1_ENC_CTXT *ac); /* start indef len constr*/ + +ST_VOID asn1r_wr_u8 (ASN1_ENC_CTXT *ac, ST_UINT8 data); +ST_VOID asn1r_wr_u16 (ASN1_ENC_CTXT *ac, ST_UINT16 data); +ST_VOID asn1r_wr_u32 (ASN1_ENC_CTXT *ac, ST_UINT32 data); +ST_VOID asn1r_wr_i8 (ASN1_ENC_CTXT *ac, ST_INT8 data); +ST_VOID asn1r_wr_bool (ASN1_ENC_CTXT *ac, ST_BOOLEAN data); +ST_VOID asn1r_wr_i16 (ASN1_ENC_CTXT *ac, ST_INT16 data); +ST_VOID asn1r_wr_i32 (ASN1_ENC_CTXT *ac, ST_INT32 data); +ST_VOID asn1r_wr_vstr (ASN1_ENC_CTXT *ac, const ST_CHAR *data); +ST_VOID asn1r_wr_delmnt (ASN1_ENC_CTXT *ac, ST_UCHAR *bufptr, ST_INT buflen); +ST_VOID asn1r_wr_btod (ASN1_ENC_CTXT *ac, MMS_BTOD *data); +ST_VOID asn1r_wr_time (ASN1_ENC_CTXT *ac, time_t data); +ST_VOID asn1r_wr_objid (ASN1_ENC_CTXT *ac, ST_INT16 *data, ST_INT num_el); +ST_VOID asn1r_wr_bitstr (ASN1_ENC_CTXT *ac, ST_UCHAR *bitptr, ST_INT numbits); +ST_VOID asn1r_wr_octstr (ASN1_ENC_CTXT *ac, const ST_UCHAR *octptr, ST_INT numoctets); +ST_VOID asn1r_wr_float (ASN1_ENC_CTXT *ac, ST_FLOAT data); +ST_VOID asn1r_wr_double (ASN1_ENC_CTXT *ac, ST_DOUBLE data); +ST_VOID asn1r_wr_utc_time (ASN1_ENC_CTXT *ac, MMS_UTC_TIME *data); +ST_RET asn1r_wr_utf8 (ASN1_ENC_CTXT *ac, ST_CHAR *data, ST_INT el_len); + +ST_RET asn1r_get_identifier (ASN1_DEC_CTXT *ac, ST_CHAR *dest); +ST_RET asn1r_get_objid (ASN1_DEC_CTXT *ac, ST_INT16 component_list[], ST_INT *num_components); +ST_RET asn1r_get_bool (ASN1_DEC_CTXT *ac, ST_BOOLEAN *dest); +ST_VOID asn1r_get_strn (ASN1_DEC_CTXT *ac, ST_CHAR *dest); +ST_RET asn1r_get_nstr (ASN1_DEC_CTXT *ac, ST_CHAR *dest); +ST_RET asn1r_get_pstr (ASN1_DEC_CTXT *ac, ST_CHAR *dest); +ST_RET asn1r_get_vstr (ASN1_DEC_CTXT *ac, ST_CHAR *dest); +ST_RET asn1r_get_vstr_maxlen (ASN1_DEC_CTXT *aCtx, ST_CHAR *ptr, ST_INT max_len); +ST_RET asn1r_get_i8 (ASN1_DEC_CTXT *ac, ST_INT8 *dest); +ST_RET asn1r_get_i16 (ASN1_DEC_CTXT *ac, ST_INT16 *dest); +ST_RET asn1r_get_i32 (ASN1_DEC_CTXT *ac, ST_INT32 *dest); +ST_RET asn1r_get_u8 (ASN1_DEC_CTXT *ac, ST_UCHAR *dest); +ST_RET asn1r_get_u16 (ASN1_DEC_CTXT *ac, ST_UINT16 *dest); +ST_RET asn1r_get_u32 (ASN1_DEC_CTXT *ac, ST_UINT32 *dest); +ST_RET asn1r_get_btod (ASN1_DEC_CTXT *ac, MMS_BTOD *dest); +ST_RET asn1r_get_time (ASN1_DEC_CTXT *ac, time_t *dest); +ST_RET asn1r_get_bitstr (ASN1_DEC_CTXT *ac, ST_UCHAR *dest, ST_INT max_bits); +ST_VOID asn1r_get_bitstr_cstr (ASN1_DEC_CTXT *ac, ST_INT bits, ST_UCHAR *ptr); +ST_RET asn1r_get_octstr (ASN1_DEC_CTXT *ac, ST_UCHAR *dest); +ST_RET asn1r_get_octstr_fixlen (ASN1_DEC_CTXT *aCtx, ST_UCHAR *ptr, ST_INT len); +ST_RET asn1r_get_octstr_varlen (ASN1_DEC_CTXT *aCtx, ST_UCHAR *ptr, ST_INT maxlen, ST_INT *lenout); +ST_VOID asn1r_get_octstr_cstr (ASN1_DEC_CTXT *ac, ST_INT numoctets, ST_UCHAR *octptr); +ST_VOID asn1r_get_delmnt (ASN1_DEC_CTXT *ac, ST_INT buflen, ST_UCHAR *bufptr, + ST_VOID (*done_fun)(ASN1_DEC_CTXT *ac)); +ST_RET asn1r_get_float (ASN1_DEC_CTXT *ac, ST_FLOAT *dest); +ST_RET asn1r_get_double (ASN1_DEC_CTXT *ac, ST_DOUBLE *dest); +ST_RET asn1r_get_utc_time (ASN1_DEC_CTXT *ac, MMS_UTC_TIME *dest); +ST_RET asn1r_get_utf8 (ASN1_DEC_CTXT *ac, ST_CHAR *ptr, ST_INT el_len); + +#ifdef INT64_SUPPORT +ST_VOID asn1r_wr_i64 (ASN1_ENC_CTXT *ac, ST_INT64 data); +ST_VOID asn1r_wr_u64 (ASN1_ENC_CTXT *ac, ST_UINT64 data); +ST_RET asn1r_get_i64 (ASN1_DEC_CTXT *ac, ST_INT64 *dest); +ST_RET asn1r_get_u64 (ASN1_DEC_CTXT *ac, ST_UINT64 *dest); +#endif /* INT64_SUPPORT */ + +ST_VOID asn1r_parse_next (ASN1_DEC_CTXT *ac, ST_VOID (*done_fun)(ASN1_DEC_CTXT *ac)); +ST_VOID asn1r_parse_cstr_contents (ASN1_DEC_CTXT *ac, ST_VOID (*done_fun)(ASN1_DEC_CTXT *ac)); + +ST_RET asn1r_skip_elmnt (ASN1_DEC_CTXT *aCtx); + +/* Functions for simplified decode scheme (no function pointers). */ +ST_RET asn1r_decode_init (ASN1_DEC_CTXT *ac, + ST_UCHAR *ptr, /* ASN.1 message to decode */ + ST_INT len); /* length of ASN.1 message */ +ST_RET asn1r_get_tag (ASN1_DEC_CTXT *ac, + ST_UINT16 *tag_out); /* out: decoded tag */ + +/************************************************************************/ +/* These macros simplify access to members of the ASN1_ENC_CTXT struct. */ +/************************************************************************/ +/* This macro returns a pointer to the start of the ASN.1 encoded data. */ +#define ASN1_ENC_PTR(aCtx) ((aCtx)->asn1r_field_ptr+1) +/* This macro returns the length (in bytes) of the ASN.1 encoded data. */ +#define ASN1_ENC_LEN(aCtx) ((aCtx)->asn1r_buf_end - (aCtx)->asn1r_field_ptr) + +/* This macro returns a pointer to the start of the ASN.1 DECODED data. */ +#define ASN1_DEC_PTR(aCtx) ((aCtx)->asn1r_field_ptr) +/* This macro returns the length (in bytes) of the ASN.1 DECODED data. */ +#define ASN1_DEC_LEN(aCtx) ((aCtx)->asn1r_elmnt_len) + +/************************************************************************/ +/* OBJECT IDENTIFIER */ +/************************************************************************/ + +#define MAX_OBJID_COMPONENTS 16 + +struct mms_obj_id + { + ST_INT num_comps; /* number of objid components */ + ST_INT16 comps[MAX_OBJID_COMPONENTS]; /* identifier components */ + SD_END_STRUCT + }; +typedef struct mms_obj_id MMS_OBJ_ID; +ST_BOOLEAN asn1_objidcmp (MMS_OBJ_ID *obj1, MMS_OBJ_ID *obj2); + +/************************************************************************/ +/* Application Reference data structure */ +/************************************************************************/ + +#define APP_REF_FORM1 0 +#define APP_REF_FORM2 1 + +struct form1 + { + ST_UCHAR *ptr; /* ptr to something */ + ST_INT16 len; /* length of contents at ptr */ + }; +typedef struct form1 FORM1_T; + +struct app_ref + { + ST_INT16 form; /* tells if form 1 or form 2 */ + ST_BOOLEAN ap_title_pres; /* tells if AP title is there */ + union /* AP title differs in form */ + { + FORM1_T form_1; /* form 1 of AP title is ASN.1 */ + MMS_OBJ_ID form_2; /* form 2 of AP title is objectid*/ + } ap_title; + ST_BOOLEAN ap_invoke_pres; /* tells if AP invoke is there */ + ST_INT32 ap_invoke; + ST_BOOLEAN ae_qual_pres; /* tells if AE qualifier is there*/ + union /* AE qualifier differs in form */ + { + FORM1_T form_1; /* form 1 of AE qual is ASN.1 */ + ST_INT32 form_2; /* form 2 if AE qual is long word*/ + } ae_qual; + ST_BOOLEAN ae_invoke_pres; /* tells if AE invoke is there */ + ST_INT32 ae_invoke; + }; +typedef struct app_ref APP_REF; + +/************************************************************************/ +/* Miscellaneous functions/macros. */ +/************************************************************************/ +/* Functions to copy bitstrings and "variable length bitstrings". */ +ST_VOID bstrcpy (ST_UCHAR *dstptr, ST_UCHAR *srcptr, ST_INT numbits); +ST_VOID bvstrcpy (MMS_BVSTRING *dstptr, MMS_BVSTRING *srcptr); +ST_INT bstrcmp (ST_UCHAR *dstptr, ST_UCHAR *srcptr, ST_INT numbits); + +/* Macros to access each individual bit of any bitstring. */ +#define BSTR_BIT_SET_ON(ptr,bitnum) \ + ( ((ST_UINT8 *)(ptr))[(bitnum)/8] |= (0x80>>((bitnum)&7)) ) +#define BSTR_BIT_SET_OFF(ptr,bitnum) \ + ( ((ST_UINT8 *)(ptr))[(bitnum)/8] &= ~(0x80>>((bitnum)&7)) ) + +/* BSTR_BIT_GET returns 0 if bit is clear, 1 if bit is set. */ +#define BSTR_BIT_GET(ptr,bitnum) \ + (( ((ST_UINT8 *)(ptr))[(bitnum)/8] & (0x80>>((bitnum)&7)) ) ? 1:0) + +#define BSTR_BIT_SET_TRUE BSTR_BIT_SET_ON +#define BSTR_BIT_SET_FALSE BSTR_BIT_SET_OFF + +/* Calculate number of bytes needed to contain number of bits. */ +#define BSTR_NUMBITS_TO_NUMBYTES(numbits) (((numbits)+7)/8) + +/* Functions for conversion from ASN.1 UTF8string to local format. */ +/* Must be ported to each platform. */ +ST_INT asn1r_utf8_to_local (ST_CHAR *dst, ST_INT dst_len, ST_CHAR *src, ST_INT src_len); +ST_INT asn1r_local_to_utf8 (ST_CHAR *dst, ST_INT dst_len, ST_CHAR *src); +#ifdef __cplusplus +} +#endif + +/************************************************************************/ +#endif /* File not already included */ +/************************************************************************/ + diff --git a/mmslib/inc/cfg_util.h b/mmslib/inc/cfg_util.h new file mode 100644 index 0000000..fa005e8 --- /dev/null +++ b/mmslib/inc/cfg_util.h @@ -0,0 +1,112 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1991-2005 All Rights Reserved */ +/* */ +/* MODULE NAME : cfg_util.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/31/05 EJV 05 Chg MAX_NUM_KEYWORDS from 100 to 200. */ +/* 10/08/98 MDE 04 Migrated to updated SLOG interface */ +/* 08/06/98 JRB 03 Added cfg_get_octet_string function. */ +/* 12/04/97 KCR 02 Added cfg_goto_keyword function */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef CFG_UTIL_INCLUDED +#define CFG_UTIL_INCLUDED + +#include "slog.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ + +#define MAX_RVAL_LEN 256 +#define MAX_NUM_KEYWORDS 200 /* just to prevent runaway */ + +/* Keyword table element */ +struct cfg_kw_el + { + ST_CHAR *name; /* string to match on */ + ST_VOID (*extract)(ST_VOID); /* function to call to extract */ + ST_RET (*valid)(ST_VOID); /* call to check if ok to call */ + }; +typedef struct cfg_kw_el CFG_KW_EL; + +/************************************************************************/ +/* Externally visible variables */ + +extern ST_BOOLEAN config_stop; /* Set SD_TRUE to terminate */ +extern ST_RET config_err; /* Set to non-zero for error */ +extern ST_BOOLEAN config_eof; /* Set to SD_SUCCESS when eof is ok */ + +extern ST_CHAR *cfg_line_buf; /* file line read buffer */ +extern ST_INT cfg_curr_line; /* Current line number */ +extern ST_INT cfg_line_offset; /* Offset into cfg_line_buf */ +extern ST_CHAR *cfg_special_char_str; /* Special ravl chars */ +extern ST_CHAR *cfg_end_of_rval_str; /* 'End of rval' chars */ + +/************************************************************************/ +/* Internal CFG_UTIL error codes */ + +#define CFG_CONVERT_ERR 0x8000 +#define CFG_GET_RVAL_ERR 0x8001 +#define CFG_UTIL_ERR 0x8002 + +/************************************************************************/ +/* Externally visible functions */ + +ST_RET cfg_process_file (ST_CHAR *fileName, CFG_KW_EL *root_kw_tbl); +ST_RET cfg_tbl_push (CFG_KW_EL *); +ST_RET cfg_tbl_pop (ST_INT); +ST_CHAR *cfg_get_alloc_string (ST_VOID); +ST_CHAR *cfg_get_string_ptr (ST_VOID); +ST_RET cfg_get_short (ST_INT16 *int_ptr); +ST_RET cfg_get_ushort (ST_UINT16 *int_ptr); +ST_RET cfg_get_int (ST_INT *int_ptr); +ST_RET cfg_get_uint (ST_UINT *int_ptr); +ST_RET cfg_get_long (ST_LONG *int_ptr); +ST_RET cfg_get_ulong (ST_ULONG *int_ptr); +ST_RET cfg_get_hex_ushort (ST_UINT16 *int_ptr); +ST_RET cfg_get_hex_uint (ST_UINT *int_ptr); +ST_RET cfg_get_hex_ulong (ST_ULONG *out_ptr); +ST_RET cfg_get_value (ST_CHAR *format_string, ST_VOID *out_ptr); +ST_VOID cfg_set_config_err(ST_VOID); +ST_VOID cfg_set_endfile_ok(ST_VOID); +ST_RET cfg_get_double (ST_DOUBLE *out_ptr); +ST_RET cfg_goto_keyword (ST_CHAR *keyword); +ST_RET cfg_get_octet_string (ST_UCHAR *ostr, /* ptr to user's ostr */ + ST_UINT *len_out_ptr, /* addr of len var to be set */ + ST_UINT len_max); /* maximum len to allow. */ + +/************************************************************************/ +/* CFG_UTIL logging control */ + +#define CFG_LOG_ERR 0x0001 +#define CFG_LOG_FLOW 0x0002 +extern ST_UINT cfg_log_mask; + +/* For compatibility with older code only */ +#define cfg_sLogCtrl sLogCtrl + +/************************************************************************/ + +#ifdef __cplusplus +} + +#endif + +#endif diff --git a/mmslib/inc/cfglog.h b/mmslib/inc/cfglog.h new file mode 100644 index 0000000..f837414 --- /dev/null +++ b/mmslib/inc/cfglog.h @@ -0,0 +1,101 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1991-1997 All Rights Reserved */ +/* */ +/* MODULE NAME : cfglog.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 10/08/98 MDE 01 Migrated to updated SLOG interface */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef CFGLOG_INCLUDED +#define CFGLOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/************************************************************************/ + +extern SD_CONST ST_CHAR *SD_CONST _cfg_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _cfg_flow_logstr; + +/************************************************************************/ + +#ifdef DEBUG_SISCO + +#define CFG_LOG_ERR0(a) {\ + if (cfg_log_mask & CFG_LOG_ERR)\ + _slog (sLogCtrl,_cfg_err_logstr,\ + thisFileName,__LINE__,a);\ + } +#define CFG_LOG_ERR1(a,b) {\ + if (cfg_log_mask & CFG_LOG_ERR)\ + _slog (sLogCtrl,_cfg_err_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define CFG_LOG_ERR2(a,b,c) {\ + if (cfg_log_mask & CFG_LOG_ERR)\ + _slog (sLogCtrl,_cfg_err_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define CFG_LOG_ERR3(a,b,c,d) {\ + if (cfg_log_mask & CFG_LOG_ERR)\ + _slog (sLogCtrl,_cfg_err_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } + + +#define CFG_LOG_FLOW0(a) {\ + if (cfg_log_mask & CFG_LOG_FLOW)\ + _slog (sLogCtrl,_cfg_flow_logstr,\ + thisFileName,__LINE__,a);\ + } +#define CFG_LOG_FLOW1(a,b) {\ + if (cfg_log_mask & CFG_LOG_FLOW)\ + _slog (sLogCtrl,_cfg_flow_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define CFG_LOG_CFLOW0(a) {\ + if (cfg_log_mask & CFG_LOG_FLOW)\ + _slogc (sLogCtrl,a);\ + } +#define CFG_LOG_CFLOW1(a,b) {\ + if (cfg_log_mask & CFG_LOG_FLOW)\ + _slogc (sLogCtrl,a,b);\ + } + +#else /* no DEBUG */ + +#define CFG_LOG_ERR0(a) +#define CFG_LOG_ERR1(a,b) +#define CFG_LOG_ERR2(a,b,c) +#define CFG_LOG_ERR3(a,b,c,d) +#define CFG_LOG_FLOW0(a) +#define CFG_LOG_FLOW1(a,b) +#define CFG_LOG_CFLOW0(a) +#define CFG_LOG_CFLOW1(a,b) + +#endif + + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/mmslib/inc/checksum.h b/mmslib/inc/checksum.h new file mode 100644 index 0000000..b1ceeff --- /dev/null +++ b/mmslib/inc/checksum.h @@ -0,0 +1,46 @@ +#ifndef CHECKSUM_INCLUDED +#define CHECKSUM_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : checksum.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file contain functionprototypes for */ +/* implemented computation and verification of checksum */ +/* using the algorithm defined in Annex B of the ISO 8073 */ +/* or in the ISO 8473. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* checksum_insert */ +/* checksum_verified */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 06/19/96 EJV 01 Created */ +/************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + + +ST_VOID checksum_insert (ST_UCHAR *buf, ST_UINT16 buf_len, ST_UINT16 position); +ST_BOOLEAN checksum_verified (ST_UCHAR *buf, ST_UINT16 buf_len, ST_UINT16 position, ST_BOOLEAN clnp_csum); + + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ diff --git a/mmslib/inc/clnp.h b/mmslib/inc/clnp.h new file mode 100644 index 0000000..2be27e6 --- /dev/null +++ b/mmslib/inc/clnp.h @@ -0,0 +1,259 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : clnp.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file specifies internal defines and function*/ +/* prototypes for implementation of Connectionless-mode */ +/* Network Protocol (CLNP). */ +/* Note that the CLNP is implemented as non-segmenting */ +/* subset of the full protocol. */ +/* */ +/* For information see the: */ +/* ISO 8473 "Information processing systems - Data communication - */ +/* Protocol providing the connectionless-mode network service"; */ +/* ISO 8348 "Information processing systems - Data communication - */ +/* Network service definition. Addendum 1: Connectionless-mode */ +/* transmission". */ +/* ISO 9542 "Information processing systems - Telecommunications */ +/* and information exchange beetween systems - End system to */ +/* Intermediate system routing exchange protocol for use with */ +/* ISO 8473. */ +/* */ +/* GLOBAL STRUCTURES DEFINED IN THIS MODULE : */ +/* */ +/* CLNP_8473_FHDR struct */ +/* CLNP_9542_FHDR struct */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 07/19/96 EJV 02 Moved CLNP_DEF_LEN_HDR from clnp_usr.h and */ +/* deleted clnpl_all_es_mac */ +/* 05/24/96 EJV 01 Created */ +/************************************************************************/ + +#ifndef CLNP_INCLUDED +#define CLNP_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + + + +/************************************************************************/ +/* Defines and structures below are specific to the ISO 8473 standard */ +/* (DT and ER PDUs for CLNP). */ +/************************************************************************/ + + +/* ISO 8473 protocol id and version */ +#define CLNP_8473_PROT_ID (ST_UCHAR) 0x81 +#define CLNP_8473_PROT_VER (ST_UCHAR) 0x01 + +/* PDU type and flags (they are already in proper bit position) */ +#define CLNP_8473_TYPE_ER (ST_UCHAR) 0x01 +#define CLNP_8473_TYPE_DT (ST_UCHAR) 0x1C + +#define CLNP_SEG_NOT_PERMITTED (ST_UCHAR) 0x00 +#define CLNP_SEG_PERMITTED (ST_UCHAR) 0x80 + /* bit 8 ON */ + +#define CLNP_LAST_SEG (ST_UCHAR) 0x00 +#define CLNP_MORE_SEG (ST_UCHAR) 0x40 + /* bit 7 ON */ + +#define CLNP_ERR_REP_NOT_GEN (ST_UCHAR) 0x00 +#define CLNP_ERR_REP_GENERATE (ST_UCHAR) 0x20 + /* bit 6 ON */ + +#define CLNP_MASK_FLAGS (ST_UCHAR) 0x1F /* mask bit 6,7,8 */ + + + +/*----------------------------------------------------------------------*/ +/* CLNP_8473_FHDR struct */ +/*----------------------------------------------------------------------*/ +/* Structure below define the fixed part in the ISO 8473 PDU header. */ +/* The rest of the header has variable length. */ + +/* NOTE: ! only ST_UCHAR type should be in protocol structs to avoid */ +/* ! packing or problems with sizeof operator. */ + +typedef struct + { + ST_UCHAR protocol_id; /* Network Layer Protocol Identifier */ + ST_UCHAR hdr_len; /* Header length */ + ST_UCHAR protocol_ver; /* Version of the protocol */ + ST_UCHAR pdu_lifetime; /* Remaining lifetime for PDU */ + ST_UCHAR type_flags; /* PDU type & flags */ + ST_UCHAR seg_len[2]; /* Segment length (hdr+data len)swapped */ + ST_UCHAR checksum [2]; /* Checksum of the PDU header */ + }CLNP_8473_FHDR; + +#define CLNP_8473_FHDR_LEN sizeof (CLNP_8473_FHDR) + + +/* structure below defines the Segmenting part in a DT PDU header */ +typedef struct + { + ST_UCHAR pdu_id [2]; /* Data Unit Identiefier */ + ST_UCHAR pdu_offset [2]; /* Offset of the segment in original PDU*/ + ST_UCHAR pdu_total_len [2]; /* Total len of original PDU */ + }CLNP_8473_HDR_SEG; + +#define CLNP_8473_HDR_SEG_LEN sizeof (CLNP_8473_HDR_SEG) + + +#define CLNP_DEF_LEN_HDR (ST_UCHAR) (CLNP_8473_FHDR_LEN+2*(CLNP_MAX_LEN_NSAP+1)) + /* this implementaion assumes */ + /* following parts to be present*/ + /* in header: */ + /* fixedPart +destNSAP +srcNSAP */ + /* (no seg, no options parts); */ + /* 51 bytes or less */ + + +/************************************************************************/ +/* Defines and structures below are specific to the ISO 9542 standard */ +/* (ES-IS HELLOs for CLNP). */ +/************************************************************************/ + + +/* ISO 8473 protocol id and version */ +#define CLNP_9542_PROT_ID (ST_UCHAR) 0x82 +#define CLNP_9542_PROT_VER (ST_UCHAR) 0x01 + +/* PDU type */ +#define CLNP_9542_TYPE_ESH (ST_UCHAR) 0x02 +#define CLNP_9542_TYPE_ISH (ST_UCHAR) 0x04 +#define CLNP_9542_TYPE_RD (ST_UCHAR) 0x06 + + + +/*----------------------------------------------------------------------*/ +/* CLNP_9542_FHDR struct */ +/*----------------------------------------------------------------------*/ +/* Structure below defines the fixed part in the ISO 9542 PDU header. */ +/* The rest of the header has variable length. */ +/* Note that the ISO 9542 (ES HELLO and IS HELLO PDUs) do not contain */ +/* PDU data part. */ + +/* NOTE: ! only ST_UCHAR type should be in protocol structs to avoid */ +/* ! packing or problems with sizeof operator. */ + +typedef struct + { + ST_UCHAR protocol_id; /* Network Layer Protocol Identifier */ + ST_UCHAR hdr_len; /* Header length */ + ST_UCHAR protocol_ver; /* Version of the protocol */ + ST_UCHAR rfu; /* Reserved for future use */ + ST_UCHAR type; /* PDU type, bits 6,7,8 are always 0 */ + ST_UCHAR holding_time[2];/* max time to retain received info */ + ST_UCHAR checksum [2]; /* Checksum of the PDU header */ + }CLNP_9542_FHDR; + +#define CLNP_9542_FHDR_LEN sizeof (CLNP_9542_FHDR) + + + +/************************************************************************/ +/* Internal CLNP function prototypes */ +/************************************************************************/ + +/* clnp_enc.c module */ + +ST_RET clnpl_encode_dt (SN_UNITDATA *sn_req, N_UNITDATA *req); +ST_RET clnpl_encode_esh (ST_UCHAR *enc_buf, ST_UINT16 *enc_len); + + +/* clnp_dec.c module */ + +ST_RET clnpl_decode (SN_UNITDATA *sn_req, N_UNITDATA **req); +ST_VOID clnpl_log_npdu (ST_UCHAR *pdu_buf, ST_UCHAR npdu_type, ST_CHAR *enc_dec_str); + +/* clnp_esh.c module */ + +ST_RET clnpl_init_esh (ST_UINT16 delay_time); +ST_VOID clnpl_check_cfg_timer (ST_VOID); +ST_RET clnpl_send_esh (ST_UCHAR *rem_mac); + + +#if 0 +/* struct below may be needed to implement in the future the ISO 8473 */ +/* header options */ +/*----------------------------------------------------------------------*/ +/* CLNP_OPTIONS struct */ +/*----------------------------------------------------------------------*/ +/* Structure below specifies the options to be used for the PDU. */ +/* The options by default are all turned off at the start-up */ +/* time. In future some functions may be provided to set up the options */ +/* or the structure will be exposed to the CLNP-user for setting the */ +/* parameters. */ +/* NOTE: currently none of the option are implemented. */ + +/* Options for padding_flag */ +#define CLNP_OPT_PAD_NONE 0 /* no header padding */ +#define CLNP_OPT_PAD_TO_SIZE 1 /* pad header to specified size */ +#define CLNP_OPT_PAD_TO_BOUDARY 2 /* pad header so that data */ + /* starts on specified boundary */ +/* Options for security_flag */ +#define CLNP_OPT_SEC_NONE 0 /* no security level specified */ +#define CLNP_OPT_SEC_SRC 1 /* sec. Source Address specific */ +#define CLNP_OPT_SEC_DEST 2 /* sec. Dest Address specific */ +#define CLNP_OPT_SEC_UNIQUE 3 /* security Globally Unique */ + +/* Options for routeing_flag */ +#define CLNP_OPT_ROUTE_NONE 0 /* no routeing specified */ +#define CLNP_OPT_ROUTE_PART 1 /* partial routeing requested */ +#define CLNP_OPT_ROUTE_COMP 2 /* complete routeing requested */ + +/* Options for record_route_flag */ +#define CLNP_OPT_REC_ROUTE_NONE 0 /* no route recording */ +#define CLNP_OPT_REC_ROUTE_PART 1 /* partial route recording */ +#define CLNP_OPT_RCE_ROUTE_COMP 2 /* complete route recording */ + +/* Options for qos_flag (Quality of Service - QoS) */ +#define CLNP_OPT_QoS_NONE 0 /* no QoS specified */ +#define CLNP_OPT_QoS_SRC 1 /* QoS Source Address specific */ +#define CLNP_OPT_QoS_DEST 2 /* QoS Dest Address specific */ +#define CLNP_OPT_QoS_UNIQUE 3 /* QoS Globally Unique */ + +/* Options for priority_flag (use values from 1 to 14 to specified */ +/* priority parameter for the DT PDU. */ +#define CLNP_OPT_PRIORITY_DEF 0 /* default priority */ +#define CLNP_OPT_PRIORITY_MAX 14 /* max priority */ + +typedef struct + { + ST_UCHAR padding_flag; + ST_UCHAR security_flag; + ST_UCHAR routeing_flag; + ST_UCHAR record_route_flag; + ST_UCHAR qos_flag; + ST_UCHAR priority_flag; + }CLNP_OPTIONS; + +extern CLNP_OPTIONS clnpl_options; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + + + diff --git a/mmslib/inc/clnp_llc.h b/mmslib/inc/clnp_llc.h new file mode 100644 index 0000000..cecd0ee --- /dev/null +++ b/mmslib/inc/clnp_llc.h @@ -0,0 +1,66 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : clnp_llc.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file contains defines for the encoding and */ +/* decoding of Logical Link Control (LLC) which is */ +/* implemented with the CLNP layer. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/12/04 JRB 04 Del LLC_LSAP_IEC_GOOSE 0xF5 (obsolete now). */ +/* 01/10/02 JRB 03 Add LLC_LSAP_IEC_GOOSE. */ +/* 09/09/97 EJV 02 Added support for UCA SMP (Station Mgt Prot) */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 06/04/96 EJV 01 Created */ +/************************************************************************/ + +#ifndef CLNP_LLC_INCLUDED +#define CLNP_LLC_INCLUDED + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define LLC_LSAP (ST_UCHAR) 0xFE +#define LLC_CONTROL (ST_UCHAR) 0x03 + +#define LLC_LSAP_SMP (ST_UCHAR) 0xFB /* For UCA SMP (Station Mgt Prot) */ +#define LLC_CONTROL_SMP (ST_UCHAR) 0x03 /* For UCA SMP (Station Mgt Prot) */ + +typedef struct + { + ST_UCHAR dest; /* destination SAP */ + ST_UCHAR src; /* source SAP */ + ST_UCHAR control; /* control field */ + }LLC_HDR; + +#define LLC_HDR_LEN sizeof (LLC_HDR) + + +/* Function prototypes from llc.c module */ + +ST_RET clnpl_llc_encode (ST_UCHAR *enc_buf, ST_UCHAR src_lsap, ST_UCHAR dest_lsap); +ST_RET clnpl_llc_decode (ST_UCHAR *dec_buf, ST_UCHAR *dest_lsap); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + diff --git a/mmslib/inc/clnp_log.h b/mmslib/inc/clnp_log.h new file mode 100644 index 0000000..c53e1f3 --- /dev/null +++ b/mmslib/inc/clnp_log.h @@ -0,0 +1,231 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : clnp_log.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file contains logging macros for CLNP. */ +/* Note: To compile logging functions use the DEBUG_SISCO define */ +/* in the project make file. */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/09/03 JRB 07 Use new "Base" macros SLOG_*, SLOGC_*, SLOGH.*/ +/* Del unused macros. */ +/* 10/02/01 JRB 06 Fix logstr in CLSNS_LOG_* macros. */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 10/08/98 MDE 04 Migrated to updated SLOG interface */ +/* 07/28/97 JRB 03 Added CLNP_LOG_REQ2 / 3 & CLNP_LOG_IND2 / 3 */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/03/97 EJV 02 Corrected ALWAYS macros; */ +/* Removed check if sLogCtrl not NULL */ +/* 06/10/96 EJV 01 Created */ +/************************************************************************/ + +#ifndef CLNP_LOG_INCLUDED +#define CLNP_LOG_INCLUDED + +#include "slog.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* NOTE: CLNP log masks and clnp_debug_sel are defined in clnp_usr.h */ + +extern SD_CONST ST_CHAR *SD_CONST _clnp_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _clnp_nerr_logstr; +extern SD_CONST ST_CHAR *SD_CONST _clnp_req_logstr; +extern SD_CONST ST_CHAR *SD_CONST _clnp_ind_logstr; +extern SD_CONST ST_CHAR *SD_CONST _clnp_enc_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _clnp_llc_enc_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _clsns_req_logstr; +extern SD_CONST ST_CHAR *SD_CONST _clsns_ind_logstr; + +#if defined(DEBUG_SISCO) + /*--------------------------------------------------------------------*/ + /* macros below are used to log REQ or IND by passing mask to select */ + /* the logging macro (this is handy in log function so the macros */ + /* do not have to repeated in function for REQ and then for IND) */ + /*--------------------------------------------------------------------*/ + + #define CLNP_LOGC_RI0(m,a) {if (m == CLNP_LOG_REQ) {CLNP_LOGC_REQ0(a);} else {CLNP_LOGC_IND0(a);}} + #define CLNP_LOGC_RI1(m,a,b) {if (m == CLNP_LOG_REQ) {CLNP_LOGC_REQ1(a,b);} else {CLNP_LOGC_IND1(a,b);}} + + #define CLNP_LOGH_RI(m,a,b) {if (m == CLNP_LOG_REQ) {CLNP_LOGH_REQ(a,b);} else {CLNP_LOGH_IND(a,b);}} + + /*--------------------------------------------------------------------*/ + /* macros below are used to log REQ or IND by passing mask to select */ + /* the logging macro (this is handy in log function so the macros */ + /* do not have to repeated in function for REQ and then for IND) */ + /*--------------------------------------------------------------------*/ + + #define CLSNS_LOGC_RI0(m,a) {if (m == CLSNS_LOG_REQ) {CLSNS_LOGC_REQ0(a);} else {CLSNS_LOGC_IND0(a);}} + #define CLSNS_LOGC_RI1(m,a,b) {if (m == CLSNS_LOG_REQ) {CLSNS_LOGC_REQ1(a,b);} else {CLSNS_LOGC_IND1(a,b);}} + + #define CLSNS_LOGH_RI(m,a,b) {if (m == CLSNS_LOG_REQ) {CLSNS_LOGH_REQ(a,b);} else {CLSNS_LOGH_IND(a,b);}} + +#else /* !defined(DEBUG_SISCO) */ + + /*--------------------------------------------------------------------*/ + /* macros below are used to log REQ or IND by passing mask */ + /*--------------------------------------------------------------------*/ + + #define CLNP_LOGC_RI0(m,a) + #define CLNP_LOGC_RI1(m,a,b) + #define CLNP_LOGH_RI(m,a,b) + + /*--------------------------------------------------------------------*/ + /* macros below are used to log REQ or IND by passing mask */ + /*--------------------------------------------------------------------*/ + + #define CLSNS_LOGC_RI0(m,a) + #define CLSNS_LOGC_RI1(m,a,b) + + #define CLSNS_LOGH_RI(m,a,b) + +#endif /* !defined(DEBUG_SISCO) */ + + /*--------------------------------------------*/ + /* hard errors logging */ + /*--------------------------------------------*/ + +#define CLNP_LOG_ERR0(a) \ + SLOG_0 (clnp_debug_sel & CLNP_LOG_ERR,_clnp_err_logstr,a) +#define CLNP_LOG_ERR1(a,b) \ + SLOG_1 (clnp_debug_sel & CLNP_LOG_ERR,_clnp_err_logstr,a,b) +#define CLNP_LOG_ERR2(a,b,c) \ + SLOG_2 (clnp_debug_sel & CLNP_LOG_ERR,_clnp_err_logstr,a,b,c) +#define CLNP_LOG_ERR3(a,b,c,d) \ + SLOG_3 (clnp_debug_sel & CLNP_LOG_ERR,_clnp_err_logstr,a,b,c,d) + + /*--------------------------------------------*/ + /* normal errors logging */ + /*--------------------------------------------*/ + +#define CLNP_LOG_NERR0(a) \ + SLOG_0 (clnp_debug_sel & CLNP_LOG_NERR,_clnp_nerr_logstr,a) +#define CLNP_LOG_NERR1(a,b) \ + SLOG_1 (clnp_debug_sel & CLNP_LOG_NERR,_clnp_nerr_logstr,a,b) +#define CLNP_LOG_NERR2(a,b,c) \ + SLOG_2 (clnp_debug_sel & CLNP_LOG_NERR,_clnp_nerr_logstr,a,b,c) +#define CLNP_LOG_NERR3(a,b,c,d) \ + SLOG_3 (clnp_debug_sel & CLNP_LOG_NERR,_clnp_nerr_logstr,a,b,c,d) + + /*--------------------------------------------*/ + /* CLNP-user request logging */ + /*--------------------------------------------*/ + +#define CLNP_LOG_REQ0(a) \ + SLOG_0 (clnp_debug_sel & CLNP_LOG_REQ,_clnp_req_logstr,a) +#define CLNP_LOG_REQ1(a,b) \ + SLOG_1 (clnp_debug_sel & CLNP_LOG_REQ,_clnp_req_logstr,a,b) +#define CLNP_LOG_REQ2(a,b,c) \ + SLOG_2 (clnp_debug_sel & CLNP_LOG_REQ,_clnp_req_logstr,a,b,c) +#define CLNP_LOG_REQ3(a,b,c,d) \ + SLOG_3 (clnp_debug_sel & CLNP_LOG_REQ,_clnp_req_logstr,a,b,c,d) + /* continuation log */ +#define CLNP_LOGC_REQ0(a) \ + SLOGC_0 (clnp_debug_sel & CLNP_LOG_REQ,a) +#define CLNP_LOGC_REQ1(a,b) \ + SLOGC_1 (clnp_debug_sel & CLNP_LOG_REQ,a,b) + /* hex logging */ +#define CLNP_LOGH_REQ(a,b) \ + SLOGH (clnp_debug_sel & CLNP_LOG_REQ,a,b) + + /*--------------------------------------------*/ + /* CLNP_user indication logging */ + /*--------------------------------------------*/ + +#define CLNP_LOG_IND0(a) \ + SLOG_0 (clnp_debug_sel & CLNP_LOG_IND,_clnp_ind_logstr,a) +#define CLNP_LOG_IND1(a,b) \ + SLOG_1 (clnp_debug_sel & CLNP_LOG_IND,_clnp_ind_logstr,a,b) +#define CLNP_LOG_IND2(a,b,c) \ + SLOG_2 (clnp_debug_sel & CLNP_LOG_IND,_clnp_ind_logstr,a,b,c) +#define CLNP_LOG_IND3(a,b,c,d) \ + SLOG_3 (clnp_debug_sel & CLNP_LOG_IND,_clnp_ind_logstr,a,b,c,d) + /* continuation log */ +#define CLNP_LOGC_IND0(a) \ + SLOGC_0 (clnp_debug_sel & CLNP_LOG_IND,a) +#define CLNP_LOGC_IND1(a,b) \ + SLOGC_1 (clnp_debug_sel & CLNP_LOG_IND,a,b) + /* hex logging */ +#define CLNP_LOGH_IND(a,b) \ + SLOGH (clnp_debug_sel & CLNP_LOG_IND,a,b) + + /*--------------------------------------------*/ + /* CLNP encoding/decoding of NPDU */ + /*--------------------------------------------*/ + +#define CLNP_LOG_ENC_DEC0(a) \ + SLOG_0 (clnp_debug_sel & CLNP_LOG_ENC_DEC,_clnp_enc_dec_logstr,a) +#define CLNP_LOG_ENC_DEC1(a,b) \ + SLOG_1 (clnp_debug_sel & CLNP_LOG_ENC_DEC,_clnp_enc_dec_logstr,a,b) +#define CLNP_LOG_ENC_DEC2(a,b,c) \ + SLOG_2 (clnp_debug_sel & CLNP_LOG_ENC_DEC,_clnp_enc_dec_logstr,a,b,c) + /* continuation log */ +#define CLNP_LOGC_ENC_DEC0(a) \ + SLOGC_0 (clnp_debug_sel & CLNP_LOG_ENC_DEC,a) +#define CLNP_LOGC_ENC_DEC1(a,b) \ + SLOGC_1 (clnp_debug_sel & CLNP_LOG_ENC_DEC,a,b) + /* hex logging */ +#define CLNP_LOGH_ENC_DEC(a,b) \ + SLOGH (clnp_debug_sel & CLNP_LOG_ENC_DEC,a,b) + + /*--------------------------------------------*/ + /* LLC encoding/decoding of LPDU */ + /*--------------------------------------------*/ + +#define CLNP_LOG_LLC_ENC_DEC3(a,b,c,d) \ + SLOG_3 (clnp_debug_sel & CLNP_LOG_LLC_ENC_DEC,_clnp_llc_enc_dec_logstr,a,b,c,d) + + /*----------------------------------------------*/ + /* sub-network services request (write) logging */ + /*----------------------------------------------*/ + +#define CLSNS_LOG_REQ0(a) \ + SLOG_0 (clnp_debug_sel & CLSNS_LOG_REQ,_clsns_req_logstr,a) +#define CLSNS_LOG_REQ1(a,b) \ + SLOG_1 (clnp_debug_sel & CLSNS_LOG_REQ,_clsns_req_logstr,a,b) + /* continuation log */ +#define CLSNS_LOGC_REQ0(a) \ + SLOGC_0 (clnp_debug_sel & CLSNS_LOG_REQ,a) +#define CLSNS_LOGC_REQ1(a,b) \ + SLOGC_1 (clnp_debug_sel & CLSNS_LOG_REQ,a,b) + /* hex logging */ +#define CLSNS_LOGH_REQ(a,b) \ + SLOGH (clnp_debug_sel & CLSNS_LOG_REQ,a,b) + + /*------------------------------------------------*/ + /* sub-network services indication logging (read) */ + /*------------------------------------------------*/ + +#define CLSNS_LOG_IND0(a) \ + SLOG_0 (clnp_debug_sel & CLSNS_LOG_IND,_clsns_ind_logstr,a) +#define CLSNS_LOG_IND1(a,b) \ + SLOG_1 (clnp_debug_sel & CLSNS_LOG_IND,_clsns_ind_logstr,a,b) + + /* continuation log */ +#define CLSNS_LOGC_IND0(a) \ + SLOGC_0 (clnp_debug_sel & CLSNS_LOG_IND,a) +#define CLSNS_LOGC_IND1(a,b) \ + SLOGC_1 (clnp_debug_sel & CLSNS_LOG_IND,a,b) + /* hex logging */ +#define CLSNS_LOGH_IND(a,b) \ + SLOGH (clnp_debug_sel & CLSNS_LOG_IND,a,b) + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ diff --git a/mmslib/inc/clnp_sne.h b/mmslib/inc/clnp_sne.h new file mode 100644 index 0000000..be7fbee --- /dev/null +++ b/mmslib/inc/clnp_sne.h @@ -0,0 +1,227 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : clnp_sne.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file defines the interface between the */ +/* Connectionless-mode Network Protocol (CLNP) and the */ +/* underlying sub-network. */ +/* */ +/* GLOBAL STRUCTURES DEFINED IN THIS MODULE : */ +/* */ +/* SN_UNITDATA struct */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* clnp_snet_init */ +/* clnp_snet_term */ +/* clnp_snet_read */ +/* clnp_snet_write */ +/* clnp_snet_free */ +/* clnp_snet_add_multicast_mac */ +/* clnp_snet_ext_write */ +/* clnp_snet_timer_tick */ +/* clnp_snet_update_is */ +/* clnp_snet_update_es */ +/* clnp_snet_lookup_mac */ +/* clnp_snet_get_all_is_mac */ +/* clnp_snet_get_all_es_mac */ +/* clnp_snet_get_local_mac */ +/* clnp_snet_get_max_udata_len */ +/* clnp_snet_get_type */ +/* clnp_snet_create_es_table */ +/* clnp_snet_check_mac */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/12/06 JRB 15 Add hPktSock extern. */ +/* 03/20/06 JRB 14 Add clnp_snet_write_raw. */ +/* Include clnp_usr.h (need some defs from it). */ +/* 07/25/05 JRB 13 Add comment explaining "lpdu_len". */ +/* 02/08/05 JRB 12 Increase ETHE_MAX_LEN_LSDU to 1518 to allow */ +/* for 802.1Q QTag Prefix. */ +/* Del ETYPE_UNITDATA, code no longer uses it. */ +/* Add clnp_snet_frame_to_udt. */ +/* Add clnp_snet_read_hook_*. */ +/* 11/20/02 ASK 11 Added ETYPE_UNITDATA struct, clnp_etype_write*/ +/* proto */ +/* 10/24/02 NAV 10 Add clnp_snet_rx_multicast_stop proto. */ +/* 11/15/01 JRB 09 Add more "multicast" functions. */ +/* Add clnpl_log_snsdu proto. */ +/* 02/21/00 JRB 08 Del "free_lpdu" flag from SN_UNITDATA, and */ +/* use portable "clnp_snet_free" instead. */ +/* 01/28/99 MDE 07 Added size to ETHE_ALL_ES, ETHE_ALL_IS */ +/* 11/30/98 JRB 06 Added Ethernet defines. */ +/* Added clnp_snet_add_multicast_mac prototype. */ +/* Added clnp_snet_check_mac prototype. */ +/* 09/23/97 EJV 05 Added clnp_snet_ext_write for UCA_SMP. */ +/* Aligned fields in SN_UNITDATA struct. */ +/* 06/19/97 EJV 04 Added clnp_snet_create_es_table prototype. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 10/17/96 EJV 03 Added define SUBNET_PROFI. */ +/* 07/22/96 EJV 02 Added func clnp_snet_get_type () and defines */ +/* for implemented sub-networks SUBNET_ADLC and */ +/* SUBNET_ETHE. */ +/* 05/23/96 EJV 01 Created */ +/************************************************************************/ + +#ifndef CLNP_SNE_INCLUDED +#define CLNP_SNE_INCLUDED + +#include "clnp_usr.h" /* need CLNP_MAX_LEN_MAC & CLNP_PARAM */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* implemented sub-networks types */ +#define SUBNET_ADLC 1 +#define SUBNET_ETHE 2 +#define SUBNET_PROFI 3 + +/*----------------------------------------------------------------------*/ +/* Structure below is used to pass SN_UNITDATA to/from read/write */ +/* functions between the CLNP and CLNP-Subnetwork interface. */ + +typedef struct + { + ST_UCHAR loc_mac [CLNP_MAX_LEN_MAC]; /* Buffer for local MAC addr */ + ST_UCHAR rem_mac [CLNP_MAX_LEN_MAC]; /* Buffer for remote MAC addr */ + /* WARNING: The "lpdu_len" param does NOT always contain the PDU length.*/ + /* It contains the "Length/Type" field of the MAC frame as defined in */ + /* IEEE 802.3. Any value greater than or equal to 0x600 must be */ + /* interpreted as the "Type" of the MAC frame. */ + /* Renaming this parameter would clarify the code, but too much */ + /* existing code is already using it. */ + ST_UINT16 lpdu_len; /* IEEE 802.3 "Length/Type" field. */ + ST_UCHAR *lpdu; /* Pointer to LPDU buffer to send. */ + }SN_UNITDATA; + +#define SN_UNITDATA_LEN sizeof (SN_UNITDATA) + +/*----------------------------------------------------------------------*/ +/* Defines for type of MAC address in received PDU. */ +/* Returned by "clnp_snet_check_mac". */ +/*----------------------------------------------------------------------*/ +#define CLNP_MAC_INVALID 0 /* Invalid MAC address (not one */ + /* of addresses def below) */ +#define CLNP_MAC_LOCAL 1 /* Our MAC address */ +#define CLNP_MAC_ALL_ES 2 /* All-ES (End Systems) address */ +#define CLNP_MAC_ALL_IS 3 /* All-IS (Intermediate Systems)*/ +#define CLNP_MAC_GOOSE 4 /* Possible GOOSE address */ + +/*----------------------------------------------------------------------*/ +/* Defines and externs for Ethernet Subnetwork (SUBNET_ETHE) only. */ +/*----------------------------------------------------------------------*/ +#define ETHE_MAC_LEN 6 + +#define ETHE_LEN_HEAD (2*ETHE_MAC_LEN + 2) +#define ETHE_MIN_LEN_LSDU 60 +/* Max len for normal frame is 1514, but with QTag Prefix it could be 1518*/ +#define ETHE_MAX_LEN_LSDU 1518 +#define ETHE_MAX_LEN_UDATA 1500 /* max. MAC User data length */ + +#define ETHE_LEN_QTAG_PREFIX 4 /* 802.1Q (VLAN) header length */ +#define ETHE_LEN_LENTYPE 2 /* MAC Len/type field length */ + +/* Ethernet frame structure */ +/* WARNING: This structure is not convenient for representing frames */ +/* containing the IEEE 802.1Q QTag Prefix. The QTag Prefix would come */ +/* between src_addr and frame_len in this structure. */ +/* Most code using this structure was written before QTag existed. */ +/* New code should not use this structure. */ +typedef struct + { + ST_UCHAR dst_addr [ETHE_MAC_LEN]; /* destination MAC address */ + ST_UCHAR src_addr [ETHE_MAC_LEN]; /* source MAC address */ + ST_UCHAR frame_len[2]; /* total frame length */ + ST_UCHAR data_buf [ETHE_MAX_LEN_UDATA]; /* data buffer */ + } ETHE_FRAME; + +#define ETHE_FRAME_LEN sizeof (ETHE_FRAME) + +/*----------------------------------------------------------------------*/ +/* Global variables. */ +/*----------------------------------------------------------------------*/ +/* All ES and all IS addresses */ +extern ST_UCHAR ETHE_ALL_ES [ETHE_MAC_LEN]; +extern ST_UCHAR ETHE_ALL_IS [ETHE_MAC_LEN]; +extern int hPktSock; /* Packet Socket handle (for LINUX, etc.) */ + +/*----------------------------------------------------------------------*/ +/* Interface functions to underlying sub-network */ +/*----------------------------------------------------------------------*/ + +ST_RET clnp_snet_init (CLNP_PARAM *clnp_param); +ST_RET clnp_snet_term (ST_VOID); +ST_RET clnp_snet_read (SN_UNITDATA *sn_req); +ST_RET clnp_snet_write (SN_UNITDATA *sn_req); +ST_RET clnp_etype_write (SN_UNITDATA *sn_req); +/* clnp_snet_write_raw replaces OBSOLETE clnp_snet_write and clnp_etype_write.*/ +ST_RET clnp_snet_write_raw ( + ST_UCHAR *framePtr, /* Pointer to complete frame including MACs*/ + size_t frameLen); /* Length of complete frame */ +ST_VOID clnp_snet_free (SN_UNITDATA *sn_req); +ST_VOID clnpl_log_snsdu (SN_UNITDATA *sn_req, ST_ULONG log_mask); +ST_RET clnp_snet_add_multicast_mac (ST_UCHAR *mac_buf); +ST_RET clnp_snet_set_multicast_filter (ST_UCHAR *mac_list, ST_INT num_macs); +ST_RET clnp_snet_rx_all_multicast_start (ST_VOID); +ST_RET clnp_snet_rx_all_multicast_stop (ST_VOID); +ST_RET clnp_snet_rx_multicast_stop (ST_VOID); + +ST_RET clnp_snet_ext_write (SN_UNITDATA *sn_req, ST_LONG user_id); +ST_VOID clnp_snet_timer_tick (ST_VOID); + +ST_RET clnp_snet_update_is (ST_UCHAR *rem_nsap, ST_UCHAR *rem_mac, ST_UINT16 holding_time); +ST_RET clnp_snet_update_es (ST_UCHAR *rem_nsap, ST_UCHAR *rem_mac, ST_UINT16 holding_time); + +ST_RET clnp_snet_lookup_is (ST_UCHAR *rem_mac); +ST_RET clnp_snet_lookup_es (ST_UCHAR *rem_nsap, ST_UCHAR *rem_mac); + +ST_RET clnp_snet_get_all_is_mac (ST_UCHAR *mac_buf); +ST_RET clnp_snet_get_all_es_mac (ST_UCHAR *mac_buf); +ST_RET clnp_snet_get_local_mac (ST_UCHAR *mac_buf); +ST_UINT16 clnp_snet_get_max_udata_len (ST_VOID); +ST_INT clnp_snet_get_type (ST_VOID); + +ST_RET clnp_snet_create_es_table (ST_UINT max_count); +ST_INT clnp_snet_check_mac (ST_UCHAR *mac_addr); + +/* Add subnetwork read hook function to do custom processing of */ +/* received packets. */ +ST_RET clnp_snet_read_hook_add ( + ST_RET (*usr_fun)(SN_UNITDATA *sn_req)); /* hook function*/ + +/* Remove subnetwork read hook function (i.e. stop custom processing). */ +ST_RET clnp_snet_read_hook_remove ( + ST_RET (*usr_fun)(SN_UNITDATA *sn_req)); /* hook function*/ + +/* Process all subnetwork read hook functions. */ +ST_RET clnp_snet_read_hook_process (SN_UNITDATA *sn_req); + +/* Copy data from raw frame to SN_UNITDATA struct. */ +ST_RET clnp_snet_frame_to_udt (ST_UINT8 *frame_buf, /* ptr to raw frame*/ + ST_INT frame_len, /* len of raw frame*/ + SN_UNITDATA *sn_req, + ST_INT udata_max_len); /* max user data len */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + + + + + + diff --git a/mmslib/inc/clnp_sta.h b/mmslib/inc/clnp_sta.h new file mode 100644 index 0000000..87f3206 --- /dev/null +++ b/mmslib/inc/clnp_sta.h @@ -0,0 +1,125 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : clnp_sta.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file defines the statistics for the */ +/* Connectionless-mode Network Protocol (CLNP). */ +/* */ +/* Note: Compile the whole project with CLNP_STAT define to */ +/* keep statistics of CLNP operation. */ +/* */ +/* GLOBAL STRUCTURES DEFINED IN THIS MODULE : */ +/* */ +/* CLNP_STATS struct */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 05/23/96 EJV 01 Created */ +/************************************************************************/ + + +#ifndef CLNP_STA_INCLUDED +#define CLNP_STA_INCLUDED + + +#ifdef __cplusplus +extern "C" { +#endif + +/* struct below describes the statistics recorded by the CLNP */ + +/* Statistics for PDUs */ +typedef struct + { + ST_UINT cnt_sent; /* Number of sent PDUs */ + ST_UINT cnt_rcvd; /* Number of received PDUs */ + ST_UINT cnt_expired; /* Number of expired PDUs */ + ST_UINT cnt_discarded; /* Number of discarded PDUs */ + }CLNP_PDU_STAT; + +typedef struct + { + CLNP_PDU_STAT all_pdu; /* stats for all PDUs */ + CLNP_PDU_STAT dt_pdu; /* stats for DT PDUs */ + CLNP_PDU_STAT er_pdu; /* stats for ER PDUs */ + }CLNP_STATS; + +#define CLNP_STATS_LEN sizeof (CLNP_STATS) + + +ST_RET clnp_stats_reset (ST_VOID); +CLNP_STATS *clnp_stats_get (ST_VOID); + + +#if defined(CLNP_STAT) + + extern CLNP_STATS clnp_stats; + + /* macros to increment all PDUs statistics */ + + #define CLNP_STAT_INC_PDU_SENT {clnp_stats.all_pdu.cnt_sent += 1;} + #define CLNP_STAT_INC_PDU_RECEIVED {clnp_stats.all_pdu.cnt_rcvd += 1;} + #define CLNP_STAT_INC_PDU_EXPIRED {clnp_stats.all_pdu.cnt_expired += 1;} + #define CLNP_STAT_INC_PDU_DISCARDED {clnp_stats.all_pdu.cnt_discarded += 1;} + + /* macros to increment DT PDU statistics */ + + #define CLNP_STAT_INC_DT_SENT {clnp_stats.dt_pdu.cnt_sent += 1;} + #define CLNP_STAT_INC_DT_RECEIVED {clnp_stats.dt_pdu.cnt_rcvd += 1;} + #define CLNP_STAT_INC_DT_EXPIRED {clnp_stats.dt_pdu.cnt_expired += 1;} + #define CLNP_STAT_INC_DT_DISCARDED {clnp_stats.dt_pdu.cnt_discarded += 1;} + + /* macros to increment ER PDU statistics */ + + #define CLNP_STAT_INC_ER_SENT {clnp_stats.er_pdu.cnt_sent += 1;} + #define CLNP_STAT_INC_ER_RECEIVED {clnp_stats.er_pdu.cnt_rcvd += 1;} + #define CLNP_STAT_INC_ER_EXPIRED {clnp_stats.er_pdu.cnt_expired += 1;} + #define CLNP_STAT_INC_ER_DISCARDED {clnp_stats.er_pdu.cnt_discarded += 1;} + +#else + + /* macros if CLNP_STAT is not defined */ + + /* macros to increment all PDU statistics */ + + #define CLNP_STAT_INC_PDU_SENT + #define CLNP_STAT_INC_PDU_RECEIVED + #define CLNP_STAT_INC_PDU_EXPIRED + #define CLNP_STAT_INC_PDU_DISCARDED + + /* macros to increment DT PDU statistics */ + + #define CLNP_STAT_INC_DT_SENT + #define CLNP_STAT_INC_DT_RECEIVED + #define CLNP_STAT_INC_DT_EXPIRED + #define CLNP_STAT_INC_DT_DISCARDED + + /* macros to increment ER PDU statistics */ + + #define CLNP_STAT_INC_ER_SENT + #define CLNP_STAT_INC_ER_RECEIVED + #define CLNP_STAT_INC_ER_EXPIRED + #define CLNP_STAT_INC_ER_DISCARDED + +#endif /* end of CLNP_STAT defined */ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + diff --git a/mmslib/inc/clnp_tnt.h b/mmslib/inc/clnp_tnt.h new file mode 100644 index 0000000..1eea64d --- /dev/null +++ b/mmslib/inc/clnp_tnt.h @@ -0,0 +1,45 @@ +#ifndef CLNP_TNT_INCLUDED +#define CLNP_TNT_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 2000 All Rights Reserved */ +/* */ +/* MODULE NAME : clnp_tnt.h */ +/* PRODUCT(S) : Lean-T Stack (Phar Lap TNT ETS port only) */ +/* */ +/* MODULE DESCRIPTION : */ +/* Stub function prototypes for Phar Lap TNT ETS. Ethernet drivers */ +/* must be modified to call these functions instead of the normal */ +/* functions in the Phar Lap TCP/IP stack. This allows the SISCO */ +/* OSI stack to intercept these calls and and do any necessary OSI */ +/* processing before passing them on to the Phar Lap TCP/IP stack. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/05/00 JRB 03 Remove last chg. No longer needed. */ +/* 03/19/99 EJV 02 pfXmit has 4 parameters in Phar Lap ver 9.1 */ +/* (with NE2K patch) */ +/* Introduced the _PHARLAP91_PATCHED define */ +/* 10/30/98 JRB 01 Created */ +/************************************************************************/ +int __cdecl stubEtsTCPSetDeviceEthernetInfo(DEVHANDLE hDriver, + char *pEnetStationAddr); +int __cdecl stubEtsTCPRegisterDeviceFuncs(DEVHANDLE hDevice, + int (__cdecl *pfUpDown)(DEVHANDLE hDevice, + unsigned short goingUp, + char *options), + int (__cdecl *pfIoctl)(DEVHANDLE hDevice, int mode), + int (__cdecl *pfXmit)(DEVHANDLE hDevice, + long *pPacket, int packetLen), + int (__cdecl *pfSend)(void *pPacketHdr)); + +void __cdecl stubEtsTCPQueueRecvBuffer(DEVHANDLE hDriver, void *hMsg, + int pkt_len, + char *pRecvBuf); + +#endif /* !CLNP_TNT_INCLUDED */ diff --git a/mmslib/inc/clnp_usr.h b/mmslib/inc/clnp_usr.h new file mode 100644 index 0000000..2357b36 --- /dev/null +++ b/mmslib/inc/clnp_usr.h @@ -0,0 +1,462 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : clnp_usr.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file defines the interface between the */ +/* Connectionless-mode Network Protocol (CLNP) and the */ +/* CLNP-user in order to exchange Network Service Data */ +/* Units (NSDUs). */ +/* Note that the CLNP is implemented as non-segmenting */ +/* subset of the full protocol. */ +/* */ +/* For information see the: */ +/* ISO 8473 "Information processing systems - Data communication - */ +/* Protocol providing the connectionless-mode network service"; */ +/* ISO 8348 "Information processing systems - Data communication - */ +/* Network service definition. Addendum 1: Connectionless-mode */ +/* transmission". */ +/* ISO 9542 "Information processing systems - Telecommunications */ +/* and information exchange beetween systems - End system to */ +/* Intermediate system routing exchange protocol for use with */ +/* ISO 8473. */ +/* */ +/* */ +/* GLOBAL STRUCTURES DEFINED IN THIS MODULE : */ +/* */ +/* CLNP_PARAM struct */ +/* N_UNITDATA struct */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* clnp_init */ +/* clnp_end */ +/* clnp_alloc */ +/* clnp_free */ +/* clnp_read */ +/* clnp_write */ +/* clnp_timer_tick */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/10/07 JRB 09 Add network_device to CLNP_PARAM. */ +/* 10/24/03 JRB 08 Move clnp_debug_sel to slog.h. */ +/* 02/29/00 JRB 07 Add clnp_status proto. */ +/* 08/11/99 JRB 06 Add DBL_LNK to N_UNITDATA for multithreading.*/ +/* 08/05/99 JRB 05 Clean up multithreading. */ +/* 08/02/99 JRB 04 Use glbsem for multithreading. */ +/* 07/30/99 JRB 03 Add "multi-threading" support. */ +/* 12/04/98 JRB 02 Add "loc_nsap" to N_UNITDATA. */ +/* 08/13/98 JRB 01 Lint cleanup. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 04/10/97 JRB 06 Moved error defs from clnp_err.h to here */ +/* and changed to use base from "glberror.h". */ +/* 03/03/97 EJV 05 Removed CLNP_LOG_ALWAYS */ +/* 10/04/96 JRB 04 Added loc_mac to N_UNITDATA. */ +/* 07/22/96 EJV 03 Changed CLNP_DEF_ESH_DELAY from 5 to 0. */ +/* 07/19/96 EJV 02 Removed ns_userdata_len from clnp_param */ +/* Moved CLNP_DEF_LEN_HDR to clnp.h and deleted */ +/* unused defines */ +/* 05/23/96 EJV 01 Created */ +/************************************************************************/ + +#ifndef CLNP_USR_INCLUDED +#define CLNP_USR_INCLUDED + +#include "gen_list.h" /* Need DBL_LNK definition. */ +#include "glbsem.h" /* Need ST_EVENT_SEM definition. */ +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------------------*/ +/* Error codes returned from the CLNP interface funcs to the CLNP-user */ +/* NOTE: Values begin from E_CLNP (found in glberror.h). */ +/*----------------------------------------------------------------------*/ +/* CLNP general errors */ +#define CLNP_ERR_CFG_FILE 0x3400 /* Errors found in cfg file (or required*/ + /* params not configured = local MAC and*/ + /* local NSAP) */ +#define CLNP_ERR_NOT_INIT 0x3401 /* CLNP has not been initialized */ +#define CLNP_ERR_MEM_ALLOC 0x3402 /* allocating memory failed */ +#define CLNP_ERR_NULL_PTR 0x3403 /* NULL pointer passed to clnp_... func */ + +/* CLNP parsing clnp_param structure errors */ +/* -&-&- */ +/* CAN NOT recover from this parameter error !!! */ +#define CLNP_ERR_NSAP_LEN 0x3404 /* NSAP length is 0 or more then allowed*/ +/* CAN recover from parameter errors below */ +#define CLNP_ERR_LIFETIME 0x3405 /* Invalid PDU lifetime */ +#define CLNP_ERR_LIFETIME_DEC 0x3406 /* Invalid PDU lifetime decrement value */ +#define CLNP_ERR_ESH_CFG_TIMER 0x3407 /* Invalid ESH Configuration Timer value*/ +#define CLNP_ERR_ESH_DELAY 0x3408 /* Invalid delay value for first ESH */ +#define CLNP_ERR_MAC_ADDR 0x3409 /* Local MAC address not configured */ + /* (for ADLC sub-network) */ +#define CLNP_ERR_UDATA_LEN 0x3410 /* CLNP-user data length (too big) */ +/* last error code is also used for CLNP PDU encoding error */ +/* -&-&- */ + +/* CLNP PDU parsing (decoding) errors */ +#define CLNP_ERR_PDU_MAC_ADDR 0x3420 /* The NPDU MAC address is not local MAC*/ + /* or All ES MAC. */ +#define CLNP_ERR_PDU_ID 0x3421 /* invalid/not supported PDU identifier */ +#define CLNP_ERR_PDU_VER 0x3422 /* invalid/not supported PDU version */ +#define CLNP_ERR_PDU_TYPE 0x3423 /* invalid/not supported PDU type */ +#define CLNP_ERR_PDU_LEN 0x3424 /* received PDU len does not match the */ + /* len indicated by sub-network */ +#define CLNP_ERR_PDU_EXPIRED 0x3425 /* DT or ER PDU's lifetime expired */ +#define CLNP_ERR_PDU_NSAP_ADDR 0x3426 /* PDU not addressed to our local NSAP */ +#define CLNP_ERR_PDU_SEGMENTING 0x3427 /* Segmented PDUs not supported */ +#define CLNP_ERR_PDU_CHECKSUM 0x3428 /* PDU checksum verification failed */ +#define CLNP_ERR_PDU_LAST_SEG 0x3429 /* Last seg bit not set (unsegmented PDU)*/ +#define CLNP_ERR_PDU_ER_PDU 0x342A /* code turned off for ER PDU processing*/ + +/* LLC encoding/decoding errors */ +#define LLC_ERR_SRC_ADDR 0x3481 /* LLC header Source field invalid */ +#define LLC_ERR_DEST_ADDR 0x3482 /* LLC header Dest filed invalid */ +#define LLC_ERR_CONTROL 0x3483 /* LLC header Control field invalid */ + +/*----------------------------------------------------------------------*/ +/* Error codes returned from the sub-network interface functions. */ +/* NOTE: Values begin from E_SUBNET (found in glberror.h). */ +/*----------------------------------------------------------------------*/ +#define SNET_ERR_INIT 0x3501 /* Init sub-net interface failed*/ +#define SNET_ERR_WRITE 0x3502 /* sub-net write func failed */ +#define SNET_ERR_READ 0x3503 /* sub-net read func failed or no data */ +#define SNET_ERR_MAC_INVALID 0x3504 /* invalid MAC address, unable */ + /* to obtain requested ALL ES, */ + /* ALL IS, or local MAC address.*/ +#define SNET_ERR_FRAME_LEN 0x3505 /* received more data than */ + /* reserved in buffer. */ +#define SNET_ERR_UDATA_LEN 0x3506 /* invalid len of data to send (too large)*/ + +/* sub-net errors specific to the Ethernet driver */ +#define SNET_ERR_DRV_OPEN 0x3520 /* open driver failed */ +#define SNET_ERR_DRV_LOC_MAC 0x3521 /* obtain local MAC addr from driver failed*/ +#define SNET_ERR_DRV_ADD_ES_ADDR 0x3522 /* add All ES Address failed */ +#define SNET_ERR_DRV_BIND_LSAP 0x3523 /* bind to LSAP failed */ +#define SNET_ERR_DRV_POST_BUFS 0x3524 /* post buffers to driver failed*/ + +/*----------------------------------------------------------------------*/ +/* CLNP logging types */ + +#define CLNP_LOG_ERR 0x00000001L +#define CLNP_LOG_NERR 0x00000002L + +/* to log CLNP-user indication or request */ +#define CLNP_LOG_REQ 0x00000010L +#define CLNP_LOG_IND 0x00000020L + +/* to log CLNP encoding/decoding or LLC encoding/decoding */ + +#define CLNP_LOG_ENC_DEC 0x00000100L +#define CLNP_LOG_LLC_ENC_DEC 0x00000200L + +/* to log data read/written to sub-network */ +#define CLSNS_LOG_REQ 0x00001000L +#define CLSNS_LOG_IND 0x00002000L + +/* CLNP is using clnp_debug_sel variable to turn on/off different */ +/* types of logging (see slog.h). */ + +/*----------------------------------------------------------------------*/ +/* The defines with CLNP_MAX_... specify the maximum values the */ +/* ISO 8473 or this implementation allows. The CLNP_DEF_... defines */ +/* specify the default values used to initialize the CLNP_PARAM struct. */ +/* */ +/* Note: The max length of NS-USERDATA is 64512 bytes but this number */ +/* is limited by underlying sub-network to: */ +/* for ADLC -> 32676 - CLNP_DEF_LEN_HDR - LLC_HDR_LEN */ +/* for Ethernet -> 1500 - CLNP_DEF_LEN_HDR - LLC_HDR_LEN */ + + +#define CLNP_MAX_LEN_MAC 6 /* Max len of MAC addr */ +#define CLNP_MAX_LEN_NSAP 20 /* Max len of NSAP addr */ + +#define CLNP_MIN_PDU_LIFETIME (ST_UCHAR) 1 /* min PDU lifetime in 500msec units */ +#define CLNP_MAX_PDU_LIFETIME (ST_UCHAR) 255 /* max PDU lifetime in 500msec units */ +#define CLNP_DEF_PDU_LIFETIME (ST_UCHAR) 50 /* def PDU lifetime in 500msec units */ +#define CLNP_DEF_PDU_LIFETIME_DEC (ST_UCHAR) 1 /* PDU lifetime decrement (in 500msec units) */ + + +#define CLNP_MAX_ESH_CFG_TIMER (ST_UINT16) 32767 /* max value for ESH Configuration Timer, it is */ + /* related to Holding Time in ESH which is */ + /* 2*CfgTimer=2*32767=65534 (must be ST_UINT16) */ +#define CLNP_DEF_ESH_CFG_TIMER (ST_UINT16) 120 /* default ESH Configuration Timer (in seconds) */ +#define CLNP_DEF_ESH_DELAY (ST_UINT16) 0 /* default delay before first ESH will be sent */ + + + +/*----------------------------------------------------------------------*/ +/* CLNP_PARAM struct */ +/* */ +/* This struct is used to supply actual parameters needed for operation */ +/* of the CLNP. */ +/* It is set by the NS-USER during call to clnp_init() function from */ +/* configuration file or from hard coded module clnp_hc.c. */ +/* */ +/* NOTE: The NSAP address is represented as sequence of unsigned bytes. */ +/* The first byte is the length of the NSAP address. This makes */ +/* it easy to put the NSAP to PDU. */ +/* Note: The pdu_lifetime_dec specifies by how many units the lifetime */ +/* value in received DT or ER PDU should be decremented. It has */ +/* to be at least 1. In case the transit delay plus processing */ +/* time is larger then 500msec the pdu_life_time_dec should be */ +/* adjusted accordingly. */ + +typedef struct + { + ST_UCHAR pdu_lifetime; /* PDU lifetime (in 500 msec units) for */ + /* outgoing DT PDUs. */ + /* init to CLNP_DEF_PDU_LIFETIME */ + ST_UCHAR pdu_lifetime_dec; /* PDU lifetime decrement (1=500msec) */ + /* for incomming DT or ER PDUs. */ + /* init to CLNP_DEF_PDU_LIFETIME_DEC */ + ST_UINT16 esh_cfg_timer; /* How often we report our presence to */ + /* other network entities (in seconds) */ + /* init to CLNP_DEF_ESH_CFG_TIMER */ + ST_UINT16 esh_delay; /* Delay time before first ESH is sent */ + /* init to CLNP_DEF_ESH_DELAY */ + ST_UCHAR loc_mac [CLNP_MAX_LEN_MAC]; /* Local MAC address */ + /* For ADLC the NS-USER sets the loc_mac*/ + /* DEBUG: Now the loc_mac has to match */ + /* the address in adlc.cfg !!! */ + /* For the Ethernet this param will be */ + /* read from the driver during init. */ + ST_UCHAR loc_nsap [1+CLNP_MAX_LEN_NSAP];/* Local len & NSAP address */ + ST_CHAR *network_device; /* network device name. May be used to */ + /* select device on some platforms */ + }CLNP_PARAM; + +#define CLNP_PARAM_LEN sizeof (CLNP_PARAM) + + +extern CLNP_PARAM clnp_param; /* This struct holds parameters needed */ + /* for the CLNP operations. */ + /* It is set by the CLNP-user before */ + /* calling the clnp_init() function. */ + + + + +/*----------------------------------------------------------------------*/ +/* N_UNITDATA struct */ +/* */ +/* This struct is used to pass N_UNITDATA request primitive to CLNP */ +/* and to receive N_UNITDATA indication from CLNP. */ +/* This struct uses the following trick to make the size of data buffer */ +/* configurable: */ +/* The last entry in the structure is a tiny (2 bytes) buffer. */ +/* To allow for any size data_buf, we can allocate extra bytes */ +/* after this struct. */ +/* For example if we want data_buf to be 4096 bytes, we could use */ +/* the following malloc call: */ +/* N_UNITDATA *req = malloc (sizeof (N_UNITDATA) + 4096 - 2 ); */ +/* The buffer can then be filled in, for example, as follow: */ +/* memcpy (req->data_buf, raw_data, 4096); */ +/* */ +/* NOTE: The "Local NSAP" is not passed back and forth in this struct. */ +/* Only one local NSAP is allowed. */ +/* */ +/* NOTE: The NSAP address is represented as sequence of unsigned bytes. */ +/* The first byte is the length of the NSAP address. This makes */ +/* it easy to get a NSAP from a NSDU. */ + + +#define CLNP_MIN_LEN_UDATA 2 + /* min length of data_buf defined in */ + /* N_UNITDATA struct. Do not use 1 */ + /* because optimizer may NOT treat this */ + /* field as an array. */ + +typedef struct + { + DBL_LNK link; /* for multithreading, must go on linked list */ + ST_BOOLEAN rem_mac_valid; /* SD_TRUE if MAC addr valid */ + ST_UCHAR loc_mac [CLNP_MAX_LEN_MAC]; /* Local MAC addr */ + ST_UCHAR rem_mac [CLNP_MAX_LEN_MAC]; /* Remote MAC addr */ + ST_UCHAR loc_nsap [1+CLNP_MAX_LEN_NSAP]; /* Local len & NSAP addr*/ + ST_UCHAR rem_nsap [1+CLNP_MAX_LEN_NSAP]; /* Remote len & NSAP addr */ + ST_UINT16 data_len; /* Data length in bytes */ + ST_UCHAR data_buf [CLNP_MIN_LEN_UDATA]; /* Data buffer */ + }N_UNITDATA; + +#define N_UNITDATA_LEN sizeof (N_UNITDATA) + + + + + +/************************************************************************/ +/* clnp_init */ +/*----------------------------------------------------------------------*/ +/* This function will initialize the operation of CLNP and the interface*/ +/* to underlying sub-network. */ +/* The CLNP-user should set the parameters in the clnp_param structure */ +/* before calling this function. */ +/* */ +/* Parameters: */ +/* ST_UINT ns_userdata_len Max size of NS-USERDATA */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if initialization successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET clnp_init (ST_UINT ns_userdata_len); + + +/************************************************************************/ +/* clnp_end */ +/*----------------------------------------------------------------------*/ +/* This function will terminate the operation of the CLNP and cleanup */ +/* the interface to underlying subnetwork. */ +/* */ +/* Parameters: */ +/* ST_VOID none */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if termination successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET clnp_end (ST_VOID); + + +/************************************************************************/ +/* clnp_alloc */ +/*----------------------------------------------------------------------*/ +/* This function will allocate a buffer for N_UNITDATA to pass data */ +/* between the CLNP and the CLNP-user. */ +/* */ +/* Parameters: */ +/* ST_UINT data_len Length of data in bytes. The length */ +/* of CLNP-user data has to be: */ +/* 0 < data_len <= CLNP_MAX_LEN_UDATA */ +/* */ +/* Return: */ +/* N_UNITDATA * pointer to allocated memory */ +/* NULL if function fails to alloc memory */ +/************************************************************************/ +N_UNITDATA *clnp_alloc (ST_UINT data_len); + + +/************************************************************************/ +/* clnp_free */ +/*----------------------------------------------------------------------*/ +/* This function will free buffer allocated for N_UNITDATA passed */ +/* between the CLNP and the CLNP-user. */ +/* */ +/* Parameters: */ +/* N_UNITDATA * memory pointer to free */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID clnp_free (N_UNITDATA *req); + + +/************************************************************************/ +/* clnp_read */ +/*----------------------------------------------------------------------*/ +/* This function is used by the CLNP-user to read N_UNITDATA.indication */ +/* from the CLNP. */ +/* The CLNP-user should free the returned pointer after the indication */ +/* has been processed. */ +/* */ +/* Parameters: */ +/* ST_VOID none */ +/* */ +/* Return: */ +/* N_UNITDATA * ptr to received N_UNITDATA.indication */ +/* NULL if N_UNITDATA.indication not received */ +/************************************************************************/ +N_UNITDATA *clnp_read (ST_VOID); + + +/************************************************************************/ +/* clnp_write */ +/*----------------------------------------------------------------------*/ +/* This function is used by the CLNP-user to write N_UNITDATA.request */ +/* to the CLNP. */ +/* The CLNP will free the req pointer. */ +/* */ +/* Parameters: */ +/* N_UNITDATA *req ptr to N_UNITDATA.request to send */ +/* This pointer should be allocated using */ +/* the clnp_alloc function. */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if N_UNITDATA.request sent successfully */ +/* error code otherwise */ +/************************************************************************/ +ST_RET clnp_write (N_UNITDATA *req); + + +/************************************************************************/ +/* clnp_timer_tick */ +/*----------------------------------------------------------------------*/ +/* This function is called on 1 second intervals by the CLNP-user (TP4) */ +/* When this function is called, CLNP decrements the Configuration */ +/* Timer (used to trigger sending of ES-Hellos), and the Holding Timers */ +/* (used to trigger clearing the {NSAP,MAC} table entries). */ +/* */ +/* Parameters: */ +/* ST_VOID none */ +/* */ +/* Return: */ +/* ST_VOID none */ +/************************************************************************/ +ST_VOID clnp_timer_tick (ST_VOID); + + +/************************************************************************/ +/* clnp_config */ +/*----------------------------------------------------------------------*/ +/* This function will initialize the CLNP parameters. */ +/* */ +/* Parameters: */ +/* ST_VOID none */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if configuration successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET clnp_config (ST_VOID); + +/************************************************************************/ +/* clnp_status */ +/*----------------------------------------------------------------------*/ +/* This function checks to see if CLNP is running. */ +/* */ +/* Return: */ +/* SD_SUCCESS if running, else error code. */ +/************************************************************************/ +ST_RET clnp_status (ST_VOID); + +/************************************************************************/ +/* Multi-threading prototypes and externs. */ +/************************************************************************/ +ST_RET clnp_read_thread_start (ST_VOID); +N_UNITDATA *clnp_read_main (ST_VOID); +N_UNITDATA *clnp_read_goose (ST_VOID); + +extern N_UNITDATA * (*clnp_read_fun_cl) (ST_VOID); /* Function ptr.*/ +extern N_UNITDATA * (*clnp_read_fun_co) (ST_VOID); /* Function ptr.*/ +extern ST_EVENT_SEM hMMSEvent; +extern ST_EVENT_SEM hMainEvent; +extern ST_EVENT_SEM hGooseEvent; + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + diff --git a/mmslib/inc/clnpport.h b/mmslib/inc/clnpport.h new file mode 100644 index 0000000..6b83b2b --- /dev/null +++ b/mmslib/inc/clnpport.h @@ -0,0 +1,52 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : clnpport.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file specifies defines which should be */ +/* ported for use by specific system. */ +/* */ +/* For information see the: */ +/* ISO 8473 "Information processing systems - Data communication - */ +/* Protocol providing the connectionless-mode network service"; */ +/* ISO 8348 "Information processing systems - Data communication - */ +/* Network service definition. Addendum 1: Connectionless-mode */ +/* transmission". */ +/* ISO 9542 "Information processing systems - Telecommunications */ +/* and information exchange beetween systems - End system to */ +/* Intermediate system routing exchange protocol for use with */ +/* ISO 8473. */ +/* */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 05/06/97 EJV 02 Removed SWAP_SHORT macro */ +/* 05/31/96 EJV 01 Created */ +/************************************************************************/ + +#ifndef CLNPPORT_INCLUDED +#define CLNPPORT_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/* NOTE: This file currently is empty. It may be used in the future */ +/* to implement code specific to an operating system. */ + +#endif +#ifdef __cplusplus +} + +#endif /* end of 'already included' */ diff --git a/mmslib/inc/conpack.h b/mmslib/inc/conpack.h new file mode 100644 index 0000000..d237441 --- /dev/null +++ b/mmslib/inc/conpack.h @@ -0,0 +1,101 @@ +#define NDIS_PACKET_TYPE_DIRECTED 0x0001 +#define NDIS_PACKET_TYPE_MULTICAST 0x0002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004 +#define NDIS_PACKET_TYPE_BROADCAST 0x0008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020 +#define NDIS_PACKET_TYPE_SMT 0x0040 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000 +#define NDIS_PACKET_TYPE_GROUP 0x1000 + +#define OID_GEN_SUPPORTED_LIST 0x00010101 +#define OID_GEN_HARDWARE_STATUS 0x00010102 +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_MEDIA_IN_USE 0x00010104 +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +#define OID_GEN_LINK_SPEED 0x00010107 +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +#define OID_GEN_VENDOR_ID 0x0001010C +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +#define OID_GEN_DRIVER_VERSION 0x00010110 +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 +#define OID_GEN_MAC_OPTIONS 0x00010113 + +#define OID_GEN_XMIT_OK 0x00020101 +#define OID_GEN_RCV_OK 0x00020102 +#define OID_GEN_XMIT_ERROR 0x00020103 +#define OID_GEN_RCV_ERROR 0x00020104 +#define OID_GEN_RCV_NO_BUFFER 0x00020105 + +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C + +#define OID_GEN_RCV_CRC_ERROR 0x0002020D +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E + + +// +// 802.3 Objects (Ethernet) +// + +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +#define OID_802_3_MULTICAST_LIST 0x01010103 +#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 + +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 + +#define OID_802_3_XMIT_DEFERRED 0x01020201 +#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define OID_802_3_RCV_OVERRUN 0x01020203 +#define OID_802_3_XMIT_UNDERRUN 0x01020204 +#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 + +// +// WAN objects +// + +#define OID_WAN_PERMANENT_ADDRESS 0x04010101 +#define OID_WAN_CURRENT_ADDRESS 0x04010102 +#define OID_WAN_QUALITY_OF_SERVICE 0x04010103 +#define OID_WAN_PROTOCOL_TYPE 0x04010104 +#define OID_WAN_MEDIUM_SUBTYPE 0x04010105 +#define OID_WAN_HEADER_FORMAT 0x04010106 + +#define OID_WAN_GET_INFO 0x04010107 +#define OID_WAN_SET_LINK_INFO 0x04010108 +#define OID_WAN_GET_LINK_INFO 0x04010109 + +#define OID_WAN_LINE_COUNT 0x0401010A + +#define OID_WAN_GET_BRIDGE_INFO 0x0401020A +#define OID_WAN_SET_BRIDGE_INFO 0x0401020B +#define OID_WAN_GET_COMP_INFO 0x0401020C +#define OID_WAN_SET_COMP_INFO 0x0401020D +#define OID_WAN_GET_STATS_INFO 0x0401020E + + + diff --git a/mmslib/inc/copp.h b/mmslib/inc/copp.h new file mode 100644 index 0000000..d03b1b9 --- /dev/null +++ b/mmslib/inc/copp.h @@ -0,0 +1,68 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : copp.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* COPP internal header file. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/11/01 JRB 04 Convert to use ASN1R. */ +/* 02/20/98 JRB 03 Chg abort_reason to ST_INT8 too. */ +/* 12/22/97 JRB 02 Use ST_INT8. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/05/97 JRB 01 Created. */ +/************************************************************************/ + +#ifndef COPP_INCLUDED +#define COPP_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "copp_usr.h" +#include "copp_log.h" + + /*======================================================*/ + /* C O N N E C T I O N S T A T E S */ + /*======================================================*/ + +/* Valid states, the first IDLE state must be 0) */ +#define COPP_STATE_IDLE 0 +#define COPP_STATE_AWAIT_CPA 1 +#define COPP_STATE_AWAIT_CON_RSP 2 +#define COPP_STATE_CONNECTED 3 + + /*======================================================*/ + /* PRESENTATION INTERNAL FUNCTIONS */ + /*======================================================*/ + +/* Function to encode and send ARP PPDU. */ +ST_VOID copp_p_abort_req (ACSE_CONN *acse_conn, ST_INT8 abort_reason, ST_INT8 event_id); +ST_VOID START_p_user_data (ASN1_DEC_CTXT *aCtx); + + /*======================================================*/ + /* PRESENTATION INTERNAL VARIABLES */ + /*======================================================*/ + +extern ST_UCHAR only_loc_psel []; /* Local len & PSEL */ +extern ST_BOOLEAN p_user_data_is_outer; /* Is P-User-data outermost constr?*/ + /* SD_TRUE or SD_FALSE */ + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* COPP_INCLUDED */ +/************************************************************************/ + diff --git a/mmslib/inc/copp_log.h b/mmslib/inc/copp_log.h new file mode 100644 index 0000000..73b7298 --- /dev/null +++ b/mmslib/inc/copp_log.h @@ -0,0 +1,167 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997 - 2007, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : copp_log.h */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file contains logging macros for COPP. */ +/* Note: To compile logging functions use the DEBUG_SISCO define */ +/* in the project make file. */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/01/07 EJV 05 Updated COPP_LOG_* macros to use SLOG_n. */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 10/08/98 MDE 03 Migrated to updated SLOG interface */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/19/97 JRB 02 General cleanup. */ +/* 02/20/97 EJV 01 Created */ +/************************************************************************/ + +#ifndef COPP_LOG_INCLUDED +#define COPP_LOG_INCLUDED + +#include "slog.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* NOTE: COPP log masks and acse_debug_sel are defined in acse2usr.h */ + +#if defined(DEBUG_SISCO) + +extern SD_CONST ST_CHAR *SD_CONST _copp_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _copp_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _copp_dec_hex_logstr; +extern SD_CONST ST_CHAR *SD_CONST _copp_enc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _copp_enc_hex_logstr; + + /*--------------------------------------------*/ + /* hard errors logging */ + /*--------------------------------------------*/ + + #define COPP_LOG_ERR0(a) \ + SLOG_0 (acse_debug_sel & COPP_LOG_ERR,_copp_err_logstr,a) + + #define COPP_LOG_ERR1(a,b) \ + SLOG_1 (acse_debug_sel & COPP_LOG_ERR,_copp_err_logstr,a,b) + + #define COPP_LOG_ERR2(a,b,c) \ + SLOG_2 (acse_debug_sel & COPP_LOG_ERR,_copp_err_logstr,a,b, c) + + #define COPP_LOG_ERR3(a,b,c,d) \ + SLOG_3 (acse_debug_sel & COPP_LOG_ERR,_copp_err_logstr,a,b, c,d) + + /*--------------------------------------------*/ + /* PS-user req and rsp logging */ + /*--------------------------------------------*/ + + #define COPP_LOG_ENC0(a) \ + SLOG_0 (acse_debug_sel & COPP_LOG_ENC,_copp_enc_logstr,a) + + #define COPP_LOG_ENC1(a,b) \ + SLOG_1 (acse_debug_sel & COPP_LOG_ENC,_copp_enc_logstr,a,b) + + #define COPP_LOG_ENC2(a,b,c) \ + SLOG_2 (acse_debug_sel & COPP_LOG_ENC,_copp_enc_logstr,a,b,c) + + #define COPP_LOG_ENC3(a,b,c,d) \ + SLOG_3 (acse_debug_sel & COPP_LOG_ENC,_copp_enc_logstr,a,b,c,d) + + #define COPP_LOG_ENC4(a,b,c,d,e) \ + SLOG_4 (acse_debug_sel & COPP_LOG_ENC,_copp_enc_logstr,a,b,c,d,e) + + /* continuation macros */ + #define COPP_LOG_ENCC0(a) \ + SLOGC_0 (acse_debug_sel & COPP_LOG_ENC,a) + + #define COPP_LOG_ENCC1(a,b) \ + SLOGC_1 (acse_debug_sel & COPP_LOG_ENC,a,b) + + /* hex logging */ + #define COPP_LOG_ENCH(a,b) \ + SLOGH (acse_debug_sel & COPP_LOG_ENC,a,b) + + /*--------------------------------------------*/ + /* PS-user ind and cnf logging */ + /*--------------------------------------------*/ + + #define COPP_LOG_DEC0(a) \ + SLOG_0 (acse_debug_sel & COPP_LOG_DEC,_copp_dec_logstr,a) + + #define COPP_LOG_DEC1(a,b) \ + SLOG_1 (acse_debug_sel & COPP_LOG_DEC,_copp_dec_logstr,a,b) + + #define COPP_LOG_DEC2(a,b,c) \ + SLOG_2 (acse_debug_sel & COPP_LOG_DEC,_copp_dec_logstr,a,b,c) + + #define COPP_LOG_DEC3(a,b,c,d) \ + SLOG_3 (acse_debug_sel & COPP_LOG_DEC,_copp_dec_logstr,a,b,c,d) + + #define COPP_LOG_DEC4(a,b,c,d,e) \ + SLOG_4 (acse_debug_sel & COPP_LOG_DEC,_copp_dec_logstr,a,b,c,d,e) + + /* continuation macros */ + #define COPP_LOG_DECC0(a) \ + SLOGC_0 (acse_debug_sel & COPP_LOG_DEC,a) + + #define COPP_LOG_DECC1(a,b) \ + SLOGC_1 (acse_debug_sel & COPP_LOG_DEC,a,b) + + /* hex logging */ + #define COPP_LOG_DECH(a,b) \ + SLOGH (acse_debug_sel & COPP_LOG_DEC,a,b) + +#else + /*--------------------------------------------*/ + /* hard errors logging */ + /*--------------------------------------------*/ + + #define COPP_LOG_ERR0(a) + #define COPP_LOG_ERR1(a,b) + #define COPP_LOG_ERR2(a,b,c) + #define COPP_LOG_ERR3(a,b,c,d) + + /*--------------------------------------------*/ + /* PS-user req and rsp logging */ + /*--------------------------------------------*/ + + #define COPP_LOG_ENC0(a) + #define COPP_LOG_ENC1(a,b) + #define COPP_LOG_ENC2(a,b,c) + #define COPP_LOG_ENC3(a,b,c,d) + #define COPP_LOG_ENC4(a,b,c,d,e) + #define COPP_LOG_ENCC0(a) + #define COPP_LOG_ENCC1(a,b) + #define COPP_LOG_ENCH(a,b) + + /*--------------------------------------------*/ + /* PS-user ind and cnf logging */ + /*--------------------------------------------*/ + + #define COPP_LOG_DEC0(a) + #define COPP_LOG_DEC1(a,b) + #define COPP_LOG_DEC2(a,b,c) + #define COPP_LOG_DEC3(a,b,c,d) + #define COPP_LOG_DEC4(a,b,c,d,e) + #define COPP_LOG_DECC0(a) + #define COPP_LOG_DECC1(a,b) + #define COPP_LOG_DECH(a,b) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ diff --git a/mmslib/inc/copp_usr.h b/mmslib/inc/copp_usr.h new file mode 100644 index 0000000..4715da3 --- /dev/null +++ b/mmslib/inc/copp_usr.h @@ -0,0 +1,193 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2001, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : copp_usr.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* COPP user header file. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/11/01 JRB 05 Convert to use ASN1R. */ +/* 08/13/98 JRB 04 Lint cleanup. */ +/* 06/17/98 JRB 03 Add error codes. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/19/97 JRB 02 Add "CALLING" support. General cleanup. */ +/* 03/05/97 JRB 01 Created. */ +/************************************************************************/ + +#ifndef COPP_USR_INCLUDED +#define COPP_USR_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + + /*======================================================*/ + /* PRESENTATION USER DEFINES */ + /* */ + /*======================================================*/ +/* Defines used for encoded values of "Provider-reason". */ +/* Used in encode/decode of CPR (Connect Presentation Reject PPDU). */ +#define PROV_REASON_NOT_SPECIFIED 0 +#define PROV_REASON_CONGESTION 1 +#define PROV_REASON_LOCAL_LIMIT 2 +#define PROV_REASON_CALLED_PRES_ADDR 3 +#define PROV_REASON_VERSION 4 +#define PROV_REASON_DEFAULT_CONTEXT 5 +#define PROV_REASON_USER_DATA 6 +#define PROV_REASON_NO_PSAP 7 + +/* Defines for P-CONNECT.cnf result parameter */ +#define P_CON_RESULT_ACCEPT 0 +#define P_CON_RESULT_USER_REJ 1 +#define P_CON_RESULT_PROVIDER_REJ 2 + + /*======================================================*/ + /* PRESENTATION ERROR CODES */ + /* */ + /*======================================================*/ + +/* NOTE: Values begin from E_COPP (found in glberror.h). */ + +/* COPP general errors */ +#define COPP_ERR_INV_PSEL 0x3101 /* Invalid local PSEL */ +#define COPP_ERR_INV_STATE 0x3102 /* Invalid connect state */ + + /*======================================================*/ + /* PRESENTATION GLOBAL VARIABLES */ + /* */ + /*======================================================*/ +extern ST_CHAR expected_pdv_pci; +extern ST_UCHAR *pdv_data_ptr; +extern ST_INT pdv_data_len; + + /*======================================================*/ + /* PRESENTATION PROVIDER FUNCTIONS */ + /* */ + /* Called by user to encode and send */ + /* Presentation PDUs. */ + /*======================================================*/ + +/************************************************************************/ +/* copp_con_req */ +/* P-Connect Request. */ +/************************************************************************/ +ST_RET copp_con_req (ST_LONG copp_bind_id, ACSE_CONN *acse_conn, PRES_ADDR *rem_addr); + +/************************************************************************/ +/* copp_rel_req */ +/* P-Release Request. */ +/************************************************************************/ +ST_RET copp_rel_req (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* copp_con_rsp_pos */ +/* P-Connect Accept. */ +/************************************************************************/ +ST_RET copp_con_rsp_pos (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* copp_con_rsp_neg */ +/* P-Connect Reject. */ +/* If "provider_reason" < 0, this is "user-reject", else this is */ +/* "provider-reject" and the value of "provider_reason" will be */ +/* encoded in the "Provider-reason" parameter of the PPDU. */ +/************************************************************************/ +ST_RET copp_con_rsp_neg (ACSE_CONN *acse_conn, ST_INT provider_reason); + +/************************************************************************/ +/* copp_rel_rsp_pos */ +/* P-Release Positive Response. */ +/************************************************************************/ +ST_RET copp_rel_rsp_pos (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* copp_u_abort_req */ +/* P-U-Abort Request. */ +/************************************************************************/ +ST_RET copp_u_abort_req (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* copp_data_req */ +/* P-Data Request. */ +/************************************************************************/ +ST_RET copp_data_req (ACSE_CONN *acse_conn); + + + /*======================================================*/ + /* PRESENTATION USER FUNCTIONS */ + /* */ + /* Called by Presentation to pass decoded */ + /* Presentation PDUs up to user. */ + /*======================================================*/ + +/************************************************************************/ +/* u_copp_con_cnf */ +/* P-CONNECT.cnf (Connect Confirm). */ +/* Parameters: */ +/* acse_conn Pointer to connection info */ +/* result P_CON_RESULT_ACCEPT, P_CON_RESULT_USER_REJ or */ +/* P_CON_RESULT_PROVIDER_REJ */ +/* reason Provider-reason (if result=P_CON_RESULT_PROVIDER_REJ)*/ +/************************************************************************/ +ST_VOID u_copp_con_cnf (ACSE_CONN *acse_conn, ST_INT result, ST_INT reason); + +/************************************************************************/ +/* u_copp_rel_cnf_pos */ +/* P-RELEASE.cnf+ (POSITIVE Release Confirm). */ +/************************************************************************/ +ST_VOID u_copp_rel_cnf_pos (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* u_copp_con_ind */ +/* P-Connect Indication. */ +/************************************************************************/ +ST_VOID u_copp_con_ind (ST_LONG user_bind_id, ACSE_CONN *acse_conn); + +/************************************************************************/ +/* u_copp_rel_ind */ +/* P-Release Indication. */ +/************************************************************************/ +ST_VOID u_copp_rel_ind (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* u_copp_p_abort_ind */ +/* P-P-Abort Indication. */ +/************************************************************************/ +ST_VOID u_copp_p_abort_ind (ACSE_CONN *acse_conn, ST_INT reason); + +/************************************************************************/ +/* u_copp_u_abort_ind */ +/* P-U-Abort Indication. */ +/************************************************************************/ +ST_VOID u_copp_u_abort_ind (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* u_copp_data_ind */ +/* P-Data Indication. */ +/************************************************************************/ +ST_VOID u_copp_data_ind (ACSE_CONN *acse_conn); + +/************************************************************************/ +/* START_pdv_list */ +/* ASN.1 decode function that may be used by Presentation-user */ +/* (i.e. ACSE) for decoding a "PDV-list" (same encoding as "EXTERNAL"). */ +/************************************************************************/ +ST_VOID START_pdv_list (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* COPP_USR_INCLUDED */ +/************************************************************************/ + diff --git a/mmslib/inc/cosp.h b/mmslib/inc/cosp.h new file mode 100644 index 0000000..e25d01f --- /dev/null +++ b/mmslib/inc/cosp.h @@ -0,0 +1,199 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : cosp.h */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file defines variable and functions */ +/* internal to the COSP (decoding and encoding). */ +/* */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/12/01 JRB 03 Reverse cosp_enc_cn_ac change (not needed). */ +/* 08/01/01 JRB 02 Del rem_addr from cosp_enc_cn_ac proto. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 01/13/97 EJV 01 Created */ +/************************************************************************/ +#ifndef COSP_INCLUDED +#define COSP_INCLUDED + + +#ifdef __cplusplus +extern "C" { +#endif + + +extern ST_UCHAR cosp_only_ssel [1+MAX_SSEL_LEN]; + + + /*======================================================*/ + /* */ + /* C O N N E C T I O N S T A T E S */ + /* */ + /*======================================================*/ + + +/* Valid states, the first IDLE state must be 0) */ +#define COSP_CSTATE_IDLE 0 /* idle, transport not connected*/ +#define COSP_CSTATE_WAIT_TCON_CNF 1 /* wait T-CONNECT.cnf */ +#define COSP_CSTATE_IDLE_TCON 100 /* idle, transport connected */ +#define COSP_CSTATE_WAIT_AC 2 /* wait for ACCEPT SPDU */ +#define COSP_CSTATE_WAIT_DN 3 /* wait for DISCONNECT SPDU */ +#define COSP_CSTATE_WAIT_CON_RSP 8 /* wait S-CONNECT.rsp */ +#define COSP_CSTATE_WAIT_REL_RSP 9 /* wait for S-RELEASE.rsp */ +#define COSP_CSTATE_WAIT_TDISCON_IND 16 /* wait T-DISCONNECT.ind */ +#define COSP_CSTATE_DATA_XFER 713 /* Data Transfer state */ + + /*======================================================*/ + /* */ + /* C O S P P R O T O C O L D E F I N E S */ + /* */ + /* D E C O D E D S P D U S T R U C T U R E S */ + /* */ + /*======================================================*/ + + +/* Encoding for supported COSP versions codes */ +#define COSP_VER1 (ST_UCHAR) 1 +#define COSP_VER2 (ST_UCHAR) 2 + + +/* Encoding of SPDU Session Identifier (SI) codes */ +#define COSP_SI_DATA (ST_UCHAR) 1 +#define COSP_SI_GIVE_TOKEN (ST_UCHAR) 1 /* this is correct DT=GIVE-TOKEN */ +#define COSP_SI_FINISH (ST_UCHAR) 9 +#define COSP_SI_DISCON (ST_UCHAR) 10 +#define COSP_SI_REFUSE (ST_UCHAR) 12 +#define COSP_SI_CONNECT (ST_UCHAR) 13 +#define COSP_SI_ACCEPT (ST_UCHAR) 14 +#define COSP_SI_ABORT (ST_UCHAR) 25 +#define COSP_SI_AB_ACCEPT (ST_UCHAR) 26 + + +/* struct used to store decoded params from CONNECT or ACCEPT SPDU */ +typedef struct tagCOSP_CN_AC + { + ST_UCHAR prot_option; + ST_UINT16 initiator_tsdu_size; + ST_UINT16 responder_tsdu_size; + ST_UCHAR ver_num; + ST_UCHAR ses_urequir [2]; /* byte0 (bits 9-16), byte1 (bits 1-8)*/ + ST_UCHAR loc_ssel [1+MAX_SSEL_LEN]; + ST_UCHAR rem_ssel [1+MAX_SSEL_LEN]; + ST_UINT udata_len; /* SS-user data length */ + ST_UCHAR *udata_ptr; /* SS-user data pointer */ + }COSP_CN_AC; + + +/* Encoding for Reason Code PI in a REFUSE SPDU generated by SS-user */ +#define COSP_RF_REASON_U_NOT_SPECIFIED (ST_UCHAR) 0 +#define COSP_RF_REASON_U_CONGESTION (ST_UCHAR) 1 +#define COSP_RF_REASON_U_REJECT (ST_UCHAR) 2 +/* Encoding for Reason Code PI in a REFUSE SPDU generated by SS-provider */ +#define COSP_RF_REASON_S_INV_SSEL (ST_UCHAR) 128+1 +#define COSP_RF_REASON_S_NOT_ATTACHED (ST_UCHAR) 128+2 +#define COSP_RF_REASON_S_CONGESTION (ST_UCHAR) 128+3 +#define COSP_RF_REASON_S_INV_VERSION (ST_UCHAR) 128+4 +#define COSP_RF_REASON_S_NOT_SPECIFIED (ST_UCHAR) 128+5 +#define COSP_RF_REASON_S_RESTRICTIONS (ST_UCHAR) 128+6 + + +/* struct used to store decoded params from REFUSE SPDU */ +typedef struct tagCOSP_RF + { + ST_BOOLEAN disconnect; /* if SD_TRUE then disconnect transport */ + ST_UCHAR ver_num; + ST_UCHAR reason; /* reason code for refuse connection */ + ST_UCHAR ses_urequir [2]; /* byte0 (bits 9-16), byte1 (bits 1-8) */ + ST_UINT udata_len; /* SS-user data length */ + ST_UCHAR *udata_ptr; /* SS-user data pointer */ + }COSP_RF; + + +#define COSP_P_AB_SPDU_LEN 9 /* P-ABORT is fixed in size */ + +/* Encoding for Transport Disconnect PI in an ABORT (and FINISH) SPDU */ +#define COSP_TCONN_KEEP (ST_UCHAR) 0x00 +#define COSP_TCONN_RELEASE (ST_UCHAR) 0x01 +/* | with one reason code below */ +#define COSP_AB_REASON_USER_ABORT (ST_UCHAR) 0x02 +#define COSP_AB_REASON_PROT_ERROR (ST_UCHAR) 0x04 +#define COSP_AB_REASON_NO_REASON (ST_UCHAR) 0x08 +#define COSP_AB_REASON_IMPLEMENTATION (ST_UCHAR) 0x10 + + +/* struct used to store decoded params from ABORT SPDU */ +typedef struct tagCOSP_AB + { + ST_BOOLEAN disconnect; /* if SD_TRUE then disconnect transport */ + ST_UCHAR reason; /* reason code for abort connection */ + ST_UINT reflect_par_len; /* Reflect param length */ + ST_UCHAR reflect_par [9]; /* Reflect param */ + ST_UINT udata_len; /* SS-user data length */ + ST_UCHAR *udata_ptr; /* SS-user data pointer */ + }COSP_AB; + + +/* struct used to store decoded params from FINISH SPDU */ +typedef struct tagCOSP_FN_DN + { + ST_BOOLEAN disconnect; /* SD_TRUE to discon transport (FN)*/ + ST_UINT udata_len; /* SS-user data length */ + ST_UCHAR *udata_ptr; /* SS-user data pointer */ + }COSP_FN_DN; + +/* struct used to store decoded params from DATA SPDU */ +typedef struct tagCOSP_DT + { + ST_UINT udata_len; /* SS-user data length */ + ST_UCHAR *udata_ptr; /* SS-user data pointer */ + }COSP_DT; + + + + /*======================================================*/ + /* */ + /* E N C O D E / D E C O D E F U N C T I O N S */ + /* */ + /*======================================================*/ + +/* cosp_enc.c */ +ST_UINT cosp_envelope_len (ACSE_CONN *con, ST_UINT rem_ssel_len, ST_UCHAR spdu_type); + +ST_RET cosp_enc_cn_ac (ACSE_CONN *con, PRES_ADDR *rem_addr, + char **spdu_ptr, ST_UINT *spdu_len, ST_UCHAR spdu_type); +ST_RET cosp_enc_rf (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len, ST_UCHAR reason); +ST_RET cosp_enc_fn_dn (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len, ST_UCHAR spdu_type); +ST_RET cosp_enc_u_ab (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len); +ST_RET cosp_enc_p_ab (char *spdu_ptr, ST_INT err_code); +ST_RET cosp_enc_dt (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len); + +/* cosp_dec.c */ +ST_RET cosp_dec_cn_ac (COSP_CN_AC *dec_par, char *spdu_buf, ST_UINT spdu_len, ST_UCHAR spdu_type); +ST_RET cosp_dec_rf (COSP_RF *dec_par, char *spdu_buf, ST_UINT spdu_len); +ST_RET cosp_dec_fn_dn (COSP_FN_DN *dec_par, char *spdu_buf, ST_UINT spdu_len, ST_UCHAR spdu_type); +ST_RET cosp_dec_ab (COSP_AB *dec_par, char *spdu_buf, ST_UINT spdu_len); +ST_RET cosp_dec_dt (COSP_DT *dec_par, char *spdu_buf, ST_UINT spdu_len); + + + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + + diff --git a/mmslib/inc/cosp_log.h b/mmslib/inc/cosp_log.h new file mode 100644 index 0000000..20c88e6 --- /dev/null +++ b/mmslib/inc/cosp_log.h @@ -0,0 +1,214 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : cosp_log.h */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file contains logging macros for COSP. */ +/* Note: To compile logging functions use the DEBUG_SISCO define */ +/* in the project make file. */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 10/08/98 MDE 04 Migrated to updated SLOG interface */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 04/24/97 JRB 03 Added NO-DEBUG version of COSP_LOG_ERRH. */ +/* 03/20/97 EJV 02 Enhanced logging. */ +/* 02/13/97 EJV 01 Created */ +/************************************************************************/ +#ifndef COSP_LOG_INCLUDED +#define COSP_LOG_INCLUDED + +#include "slog.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* NOTE: COSP log masks and acse_debug_sel are defined in acse2usr.h */ + + +#if defined(DEBUG_SISCO) + + /* this number will identify the log entry as COSP log */ + +extern SD_CONST ST_CHAR *SD_CONST _cosp_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _cosp_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _cosp_dec_hex_logstr; +extern SD_CONST ST_CHAR *SD_CONST _cosp_enc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _cosp_enc_hex_logstr; + + /*--------------------------------------------*/ + /* hard errors logging */ + /*--------------------------------------------*/ + + #define COSP_LOG_ERR0(a) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slog (sLogCtrl,_cosp_err_logstr,thisFileName,__LINE__,a);\ + } + #define COSP_LOG_ERR1(a,b) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slog (sLogCtrl,_cosp_err_logstr,thisFileName,__LINE__,a,b);\ + } + #define COSP_LOG_ERR2(a,b,c) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slog (sLogCtrl,_cosp_err_logstr,thisFileName,__LINE__,a,b,c);\ + } + #define COSP_LOG_ERR3(a,b,c,d) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slog (sLogCtrl,_cosp_err_logstr,thisFileName,__LINE__,a,b,c,d);\ + } + /* continuation macros */ + #define COSP_LOG_ERRC0(a) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slogc (sLogCtrl,a);\ + } + #define COSP_LOG_ERRC1(a,b) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slogc (sLogCtrl,a,b);\ + } + #define COSP_LOG_ERRC2(a,b,c) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c);\ + } + /* hex logging */ + #define COSP_LOG_ERRH(a,b) {\ + if (acse_debug_sel & COSP_LOG_ERR)\ + _slogHex (sLogCtrl,a,b);\ + } + + /*--------------------------------------------*/ + /* SS-user req and rsp logging */ + /*--------------------------------------------*/ + + #define COSP_LOG_ENC0(a) {\ + if (acse_debug_sel & COSP_LOG_ENC)\ + _slog (sLogCtrl,_cosp_enc_logstr,thisFileName,__LINE__,a);\ + } + #define COSP_LOG_ENC1(a,b) {\ + if (acse_debug_sel & COSP_LOG_ENC)\ + _slog (sLogCtrl,_cosp_enc_logstr,thisFileName,__LINE__,a,b);\ + } + #define COSP_LOG_ENC2(a,b,c) {\ + if (acse_debug_sel & COSP_LOG_ENC)\ + _slog (sLogCtrl,_cosp_enc_logstr,thisFileName,__LINE__,a,b,c);\ + } + #define COSP_LOG_ENC3(a,b,c,d) {\ + if (acse_debug_sel & COSP_LOG_ENC)\ + _slog (sLogCtrl,_cosp_enc_logstr,thisFileName,__LINE__,a,b,c,d);\ + } + #define COSP_LOG_ENC4(a,b,c,d,e) {\ + if (acse_debug_sel & COSP_LOG_ENC)\ + _slog (sLogCtrl,_cosp_enc_logstr,thisFileName,__LINE__,a,b,c,d,e);\ + } + /* continuation macros */ + #define COSP_LOG_ENCC0(a) {\ + if (acse_debug_sel & COSP_LOG_ENC)\ + _slogc (sLogCtrl,a);\ + } + #define COSP_LOG_ENCC1(a,b) {\ + if (acse_debug_sel & COSP_LOG_ENC)\ + _slogc (sLogCtrl,a,b);\ + } + /* hex logging */ + #define COSP_LOG_ENCH(a,b) {\ + if (acse_debug_sel & COSP_LOG_ENC_HEX)\ + _slogHex (sLogCtrl,a,b);\ + } + + /*--------------------------------------------*/ + /* SS-user ind and cnf logging */ + /*--------------------------------------------*/ + + #define COSP_LOG_DEC0(a) {\ + if (acse_debug_sel & COSP_LOG_DEC)\ + _slog (sLogCtrl,_cosp_dec_logstr,thisFileName,__LINE__,a);\ + } + #define COSP_LOG_DEC1(a,b) {\ + if (acse_debug_sel & COSP_LOG_DEC)\ + _slog (sLogCtrl,_cosp_dec_logstr,thisFileName,__LINE__,a,b);\ + } + #define COSP_LOG_DEC2(a,b,c) {\ + if (acse_debug_sel & COSP_LOG_DEC)\ + _slog (sLogCtrl,_cosp_dec_logstr,thisFileName,__LINE__,a,b,c);\ + } + #define COSP_LOG_DEC3(a,b,c,d) {\ + if (acse_debug_sel & COSP_LOG_DEC)\ + _slog (sLogCtrl,_cosp_dec_logstr,thisFileName,__LINE__,a,b,c,d);\ + } + #define COSP_LOG_DEC4(a,b,c,d,e) {\ + if (acse_debug_sel & COSP_LOG_DEC)\ + _slog (sLogCtrl,_cosp_dec_logstr,thisFileName,__LINE__,a,b,c,d,e);\ + } + /* continuation macros */ + #define COSP_LOG_DECC0(a) {\ + if (acse_debug_sel & COSP_LOG_DEC)\ + _slogc (sLogCtrl,a);\ + } + #define COSP_LOG_DECC1(a,b) {\ + if (acse_debug_sel & COSP_LOG_DEC)\ + _slogc (sLogCtrl,a,b);\ + } + /* hex logging */ + #define COSP_LOG_DECH(a,b) {\ + if (acse_debug_sel & COSP_LOG_DEC_HEX)\ + _slogHex (sLogCtrl,a,b);\ + } +#else + /*--------------------------------------------*/ + /* hard errors logging */ + /*--------------------------------------------*/ + + #define COSP_LOG_ERR0(a) + #define COSP_LOG_ERR1(a,b) + #define COSP_LOG_ERR2(a,b,c) + #define COSP_LOG_ERR3(a,b,c,d) + #define COSP_LOG_ERRC0(a) + #define COSP_LOG_ERRC1(a,b) + #define COSP_LOG_ERRC2(a,b,c) + #define COSP_LOG_ERRH(a,b) + + /*--------------------------------------------*/ + /* SS-user req and rsp logging */ + /*--------------------------------------------*/ + + #define COSP_LOG_ENC0(a) + #define COSP_LOG_ENC1(a,b) + #define COSP_LOG_ENC2(a,b,c) + #define COSP_LOG_ENC3(a,b,c,d) + #define COSP_LOG_ENC4(a,b,c,d,e) + #define COSP_LOG_ENCC0(a) + #define COSP_LOG_ENCC1(a,b) + #define COSP_LOG_ENCH(a,b) + + /*--------------------------------------------*/ + /* SS-user ind and cnf logging */ + /*--------------------------------------------*/ + + #define COSP_LOG_DEC0(a) + #define COSP_LOG_DEC1(a,b) + #define COSP_LOG_DEC2(a,b,c) + #define COSP_LOG_DEC3(a,b,c,d) + #define COSP_LOG_DEC4(a,b,c,d,e) + #define COSP_LOG_DECC0(a) + #define COSP_LOG_DECC1(a,b) + #define COSP_LOG_DECH(a,b) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ diff --git a/mmslib/inc/cosp_usr.h b/mmslib/inc/cosp_usr.h new file mode 100644 index 0000000..98e603e --- /dev/null +++ b/mmslib/inc/cosp_usr.h @@ -0,0 +1,531 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : cosp_usr.h */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file defines the interface between the */ +/* Connection-oriented Session Protocol (COSP) and the */ +/* Connection-oriented Presentation Layer (COPP) in order */ +/* to exchange Session Service Data Units (SSDU). */ +/* */ +/* For information see the: */ +/* ISO 8326 "Information processing systems - Open Systems */ +/* Interconnection - Basic connection oriented session service */ +/* definition. */ +/* ISO 8327 "Information processing systems - Open Systems */ +/* Interconnection - Basic connection oriented session protocol */ +/* specification. */ +/* ISO 8327/ADD.2 (Draft for Version2). */ +/* */ +/* */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* cosp_bind */ +/* u_cosp_bind_cnf */ +/* cosp_unbind */ +/* u_cosp_unbind_cnf */ +/* */ +/* cosp_con_req */ +/* u_cosp_con_cnf_pos */ +/* u_cosp_con_cnf_neg */ +/* */ +/* u_cosp_con_ind */ +/* cosp_con_rsp_pos */ +/* cosp_con_rsp_neg */ +/* */ +/* cosp_rel_req */ +/* u_cosp_rel_cnf_pos */ +/* */ +/* u_cosp_rel_ind */ +/* cosp_rel_rsp_pos */ +/* */ +/* cosp_u_abort_req */ +/* u_cosp_abort_ind */ +/* */ +/* cosp_data_req */ +/* u_cosp_data_ind */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 04/10/97 JRB 02 Chg error defs to use base from "glberror.h".*/ +/* 01/10/97 EJV 01 Created */ +/************************************************************************/ +#ifndef COSP_USR_INCLUDED +#define COSP_USR_INCLUDED + + +#ifdef __cplusplus +extern "C" { +#endif + + + /*======================================================*/ + /* */ + /* C O S P S P E C I F I C D E F I N E S */ + /* */ + /*======================================================*/ + +/* Defines below specify limits on certain parameters for the COSP MOSI */ +/* Version2 implementation: */ + +#define COSP_MAX_UDATA_CON (ST_UINT) 10240 +#define COSP_MAX_ENVELOPE (ST_UINT) 56 +#define COSP_MAX_UDATA ((ST_UINT) 65535 - COSP_MAX_ENVELOPE) + + /*======================================================*/ + /* */ + /* Result and Reason Codes in S-CONNECT.cnf- */ + /* */ + /*======================================================*/ + +/* Result codes */ +#define COSP_CON_CNF_U_REJECT 1 +#define COSP_CON_CNF_P_REJECT 2 + +/* Reason codes in S-CONNECT.cnf- when result=COSP_CON_CNF_U_REJECT */ +#define COSP_CON_CNF_U_NOT_SPECIFIED 0 +#define COSP_CON_CNF_U_CONGESTION 1 +#define COSP_CON_CNF_U_IN_UDATA 2 /* udata = PPDU */ + +/* Valid reason codes in S-CONNECT.cnf- when result=COSP_CON_CNF_P_REJECT */ +#define COSP_CON_CNF_P_NOT_SPECIFIED 3 /* or version not supported, */ + /* or implementation restrictions */ +#define COSP_CON_CNF_P_CONGESTION 4 +#define COSP_CON_CNF_P_INV_SSEL 5 /* called Session Address unknown */ +#define COSP_CON_CNF_P_NOT_ATTACHED 6 /* called SS-user not attached to SSAP */ + + + /*======================================================*/ + /* */ + /* Reason Codes in S-CONNECT.rsp- */ + /* */ + /*======================================================*/ + +/* Reason codes in S-CONNECT.rsp- (if connection rejected) */ +#define COSP_CON_RSP_U_NOT_SPECIFIED 0 +#define COSP_CON_RSP_U_CONGESTION 1 +#define COSP_CON_RSP_U_IN_UDATA 2 /* udata = PPDU */ + + + /*======================================================*/ + /* */ + /* Reason Codes in S-P-ABORT.ind */ + /* */ + /*======================================================*/ + +#define COSP_P_AB_IND_TP_DISCON 0 +#define COSP_P_AB_IND_PROT_ERR 1 +#define COSP_P_AB_IND_UNDEFINED 2 + + + /*======================================================*/ + /* */ + /* C O S P E R R O R C O D E S */ + /* */ + /*======================================================*/ + +/* NOTE: Values begin from E_COSP (found in glberror.h). */ + +/* COSP general errors */ +#define COSP_ERR_BIND_STATE 0x3201 /* Invalid Bind state->already called*/ +#define COSP_ERR_TP4_RET 0x3202 /* Transport layer returned error */ +#define COSP_ERR_INV_TP4_ADDR 0x3203 /* Transport address invalid */ +#define COSP_ERR_INV_CON_STATE 0x3204 /* Invalid connect state */ +#define COSP_ERR_INV_SSEL 0x3205 /* Invalid local SSEL length */ +#define COSP_ERR_INV_UDATA_LEN 0x3206 /* Invalid User Data length */ +#define COSP_ERR_INV_POINTER 0x3207 /* Invalid pointer to encode buffer */ + +/* COSP PDU decoding errors */ +#define COSP_ERR_DEC_INV_SPDU 0x3210 /* Invalid/not-supp. SPDU SI rcvd */ +#define COSP_ERR_DEC_INV_LEN 0x3211 /* Invalid SPDU len (dec vs fun len) */ +#define COSP_ERR_DEC_INV_PI_CODE 0x3212 /* Invalid/out-of-place PGI/PI code */ +#define COSP_ERR_DEC_INV_LOC_SSEL 0x3213 /* SPDU not addressed to local SSEL */ +#define COSP_ERR_DEC_INV_PROT_OPT 0x3214 /* Extended SPDU concat not supp. */ +#define COSP_ERR_DEC_INV_SEG 0x3215 /* Invalid/not-supp. SSDU Segmenting */ +#define COSP_ERR_DEC_INV_PROT_VER 0x3216 /* Invalid/not-supp. prot version */ +#define COSP_ERR_DEC_INV_FUN_UNITS 0x3217 /* Invalid/not-supp. FU in Ses Req. */ +#define COSP_ERR_DEC_INV_RF_UDATA 0x3218 /* Invalid udata len,len>0 reason!=2 */ +#define COSP_ERR_DEC_INV_AB_RP 0x3219 /* Inv len of Reflect Par in AB SPDU */ + + + /*======================================================*/ + /* */ + /* B I N D I N G F U N C T I O N S */ + /* */ + /*======================================================*/ + +/************************************************************************/ +/* cosp_bind */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to bind to local Session Address. */ +/* The SS-user should implement the u_cosp_bind_cnf function. */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_user_bind_id COSP User's id for this binding.*/ +/* PRES_ADDR *loc_addr Local Address to bind to */ +/* ST_INT sharable Ignored, (for compatibility with*/ +/* ST_INT max_conns Ignored, previous versions) */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if bind successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_bind (ST_LONG cosp_user_bind_id, PRES_ADDR *loc_addr, + ST_INT sharable, ST_INT max_conns); + + +/************************************************************************/ +/* u_cosp_bind_cnf */ +/*----------------------------------------------------------------------*/ +/* This function is called by the SS-provider to indicate the result of */ +/* the bind operation (see cosp_bind func). */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_user_bind_id COSP User's id for this binding. */ +/* ST_LONG cosp_bind_id COSP id for this binding. */ +/* ST_RET result Indicates if the bind was successful: */ +/* = 0 Success */ +/* <> 0 Error code */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_bind_cnf (ST_LONG cosp_user_bind_id, ST_LONG cosp_bind_id, + ST_RET result); + + +/************************************************************************/ +/* cosp_unbind */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to unbind from local Session Address. */ +/* The SS-user should implement the u_cosp_unbind_cnf function. */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_bind_id COSP's id to unbind. */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if unbind successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_unbind (ST_LONG cosp_bind_id); + + +/************************************************************************/ +/* u_cosp_unbind_cnf */ +/*----------------------------------------------------------------------*/ +/* This function is called by the SS-provider to indicate that the */ +/* unbind operation finished (see cosp_unbind func). */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_user_bind_id COSP User's id for this binding.*/ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_unbind_cnf (ST_LONG cosp_user_bind_id); + + + /*======================================================*/ + /* */ + /* C O N N E C T F U N C T I O N S (CALLED SIDE) */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* u_cosp_con_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* remote node wishes to establish a connection. */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_user_bind_id COSP user id bind */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_con_ind (ST_LONG cosp_user_bind_id, ACSE_CONN *con); + + +/************************************************************************/ +/* cosp_con_rsp_pos */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to Accept an incomming connection. */ +/* If SS-user data are sent make sure the reason=COSP_CON_RSP_U_IN_UDATA*/ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to con info struct */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_con_rsp_pos (ACSE_CONN *con); + + +/************************************************************************/ +/* cosp_con_rsp_neg */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to Reject an incomming connection. */ +/* If SS-user data are sent make sure the reason=COSP_CON_RSP_U_IN_UDATA*/ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to con info struct */ +/* ST_INT reason Reason for reject COSP_CON_RSP_U_... */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_con_rsp_neg (ACSE_CONN *con, ST_INT reason); + + + /*======================================================*/ + /* */ + /* C O N N E C T F U N C T I O N S (CALLING SIDE) */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* cosp_con_req */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to establish a Session connection. */ +/* SS-user should implement following functions to confirm to this */ +/* request: u_cosp_con_cnf_pos and u_cosp_con_cnf_neg. */ +/* If this function returns value other then SD_SUCCESS then the function */ +/* u_cosp_con_cnf_xxx will not be called. */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_bind_id COSP bind id (also= TP4 bind id)*/ +/* PRES_ADDR *rem_addr Remote Address */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_con_req (ST_LONG cosp_bind_id, PRES_ADDR *rem_addr, ACSE_CONN *con); + + +/************************************************************************/ +/* u_cosp_con_cnf_pos */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that */ +/* the connection has been established. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_con_cnf_pos (ACSE_CONN *con); + + +/************************************************************************/ +/* u_cosp_con_cnf_neg */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate the */ +/* connection has been rejected by remote. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* ST_INT result see def results COSP_CON_CNF_... above */ +/* ST_INT reason see def reasons COSP_CON_CNF_... above */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_con_cnf_neg (ACSE_CONN *con, ST_INT result, ST_INT reason); + + + /*======================================================*/ + /* */ + /* C O N N E C T I O N R E L E A S E (CALLED SIDE) */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* u_cosp_rel_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* remote node wishes to release a connection. The SS-user should call */ +/* cosp_rel_rsp_pos to release the connection. Negative cnf not allowed.*/ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_rel_ind (ACSE_CONN *con); + + +/************************************************************************/ +/* cosp_rel_rsp_pos */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to respond positively to release of */ +/* connection. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_rel_rsp_pos (ACSE_CONN *con); + + + /*======================================================*/ + /* */ + /* C O N N E C T I O N R E L E A S E (CALLING SIDE)*/ + /* */ + /*======================================================*/ + +/************************************************************************/ +/* cosp_rel_req */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to release a Session connection. */ +/* SS-user should implement the u_cosp_rel_cnf_pos function to receive */ +/* confirm for this request. Negative confirm is not implemented. */ +/* If this function returns value other then SD_SUCCESS then the function */ +/* u_cosp_rel_cnf_pos will not be called. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_rel_req (ACSE_CONN *con); + + +/************************************************************************/ +/* u_cosp_rel_cnf_pos */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate positive */ +/* result of the release operation. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_rel_cnf_pos (ACSE_CONN *con); + + + /*======================================================*/ + /* */ + /* A B O R T F U N C T I O N S */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* cosp_u_abort_req */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to Abort a connection (S-U-ABORT) */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_u_abort_req (ACSE_CONN *con); + + +/************************************************************************/ +/* u_cosp_p_abort_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* connection has been aborted by SS-provider (local or remote). */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* ST_INT reason see def reasons COSP_P_AB_IND_... above */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_p_abort_ind (ACSE_CONN *con, ST_INT reason); + + +/************************************************************************/ +/* u_cosp_u_abort_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* connection has been aborted by remote SS-user. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_u_abort_ind (ACSE_CONN *con); + + + /*======================================================*/ + /* */ + /* D A T A T R A N S F E R F U N C T I O N S */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* cosp_data_req */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to transfer normal data on a previously */ +/* established connection. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_data_req (ACSE_CONN *con); + + +/************************************************************************/ +/* u_cosp_data_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* data have been received. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_data_ind (ACSE_CONN *con); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + diff --git a/mmslib/inc/dibmatch.h b/mmslib/inc/dibmatch.h new file mode 100644 index 0000000..b38b488 --- /dev/null +++ b/mmslib/inc/dibmatch.h @@ -0,0 +1,64 @@ +#ifndef DIBMATCH_H + +#define DIBMATCH_H + +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003 - 2005, All Rights Reserved */ +/* */ +/* MODULE NAME : dibmatch.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/04/06 EJV 04 Added DLLs incompatibility comments. */ +/* 07/19/05 EJV 03 Added gensock2.h include. */ +/* 07/12/05 EJV 02 DIB_MATCH_CTRL: added use_gethostbyname. */ +/* 06/11/03 MDE 01 New */ +/************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gensock2.h" + +/************************************************************************/ +/* General address matching defines, control, functions */ + +/* Compare Results */ +#define DIB_MATCH_NOT 0 +#define DIB_MATCH_CLOSE 1 +#define DIB_MATCH_EXACT 2 + +typedef struct dib_match_ctrl_tag + { + /* Note: adding/removing fields to/from this struct will make older */ + /* !!! applications incompatible with new security DLLs. */ + ST_BOOLEAN match_allow_missing_ae_elements; + ST_BOOLEAN match_allow_extra_ae_elements; + + ST_BOOLEAN match_ap_title; + ST_BOOLEAN match_ae_qualifier; + ST_BOOLEAN match_ap_invoke; + ST_BOOLEAN match_ae_invoke; + ST_BOOLEAN match_psel; + ST_BOOLEAN match_ssel; + ST_BOOLEAN match_tsel; + ST_BOOLEAN match_net_addr; + ST_BOOLEAN use_gethostbyname; /* gethostbyname() call may take LONG */ + /* time when the DNS is not available. */ + } DIB_MATCH_CTRL; + + + +#ifdef __cplusplus +} +#endif + +#endif /* DIBMATCH_H */ diff --git a/mmslib/inc/ethertyp.h b/mmslib/inc/ethertyp.h new file mode 100644 index 0000000..16f6f59 --- /dev/null +++ b/mmslib/inc/ethertyp.h @@ -0,0 +1,72 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2002-2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ethertyp.h */ +/* PRODUCT(S) : MMS-EASE Lite */ +/* */ +/* MODULE DESCRIPTION : Ethertype frame encode functions and constants.*/ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/08/05 JRB 03 Chg first arg to etype_hdr_decode. */ +/* 03/24/03 ASK 02 Updated ETYPE_TYPE_* constant values */ +/* 11/20/02 ASK 01 Created */ +/************************************************************************/ + +#if !defined(ETHERTYP_H_INCLUDED) +#define ETHERTYP_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "clnp_usr.h" +#include "clnp_sne.h" + + +#define ETYPE_VLAN_TYPE_ID 0x8100 +#define ETYPE_TYPE_GOOSE 0x88B8 +#define ETYPE_TYPE_GSE 0x88B9 +#define ETYPE_TYPE_SV 0x88BA +#define ETYPE_TCI_GOOSE 0x8000 +#define ETYPE_TCI_GSE 0x2000 +#define ETYPE_TCI_SV 0x8001 + +#define VLAN_HEAD_LEN 4 +#define ETYPE_HEAD_LEN 8 + +/* Ethertype Frame Info to be filled out by the user */ +typedef struct + { + ST_UINT16 tci; /* VLAN Tag Control Info */ + ST_UINT16 etypeID; /* Ethertype ID */ + ST_UINT16 appID; /* APP ID */ + } ETYPE_INFO; + + +ST_UCHAR *etype_hdr_encode(ST_UCHAR *bufPtr, /* buffer to encode into */ + ST_INT bufLen, /* len of buffer */ + ST_INT *asn1Len, /* ptr to len encoded */ + ETYPE_INFO *info);/* ptr etype struct */ + +ST_UCHAR *vlan_hdr_encode(ST_UCHAR *bufPtr, /* buffer to encode into */ + ST_INT *asn1Len, /* ptr to len encoded */ + ETYPE_INFO *info); /* ptr etype struct */ + +ST_UCHAR *etype_hdr_decode(SN_UNITDATA *sn_req, + ETYPE_INFO *info, /* ptr etype struct */ + ST_INT *bufLen); /* ptr to len decoded */ + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ diff --git a/mmslib/inc/ethsub.h b/mmslib/inc/ethsub.h new file mode 100644 index 0000000..b7d0a4f --- /dev/null +++ b/mmslib/inc/ethsub.h @@ -0,0 +1,132 @@ +#ifndef ETHSUB_INCLUDED +#define ETHSUB_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2000-2006 All Rights Reserved */ +/* */ +/* MODULE NAME : ethsub.h */ +/* PRODUCT(S) : Lean-T Stack for Windows 95/98/NT */ +/* */ +/* MODULE DESCRIPTION : */ +/* Definitions to allow Subnetwork interface to work with OSI LLC */ +/* Ethernet driver. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/21/06 JRB 04 Chg to use SISCO naming conventions. */ +/* 04/14/06 JRB 03 Add sysincs header. */ +/* 11/20/02 ASK 02 Add ethdown_etype proto */ +/* 04/06/00 JRB 01 Created */ +/************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************/ +/* Include files required to interface with */ +/* OSI LLC NDIS Ethernet Driver */ +/* */ +/****************************************************************/ + +#include "conpack.h" +#include "osillc.h" + +#include "glbtypes.h" +#include "sysincs.h" +#include "slog.h" +#include "stime.h" +#include "clnp_usr.h" /* clnp_sne.h needs this */ +#include "clnp_log.h" +#include "clnp_sne.h" /* for SN_UNITDATA, etc. */ + +/****************************************************************/ +/****************************************************************/ + +typedef struct +{ +/** ----- Following fields are specific to this Access Method */ + HANDLE hFile; /* LLC device driver descriptor */ + + unsigned long seq; /* sequence number to expect */ + void *readlst[10]; /* list of pointers to out of sequence packet blocks */ + + /* ----- Following fields are required for 95/98 */ + struct rd_wr_block *pWriteEvents; /* list of write event structures */ + struct rd_wr_block *pReadEvents; /* list of read event structures */ +} LLC_CONTEXT; + +/************************************************************************/ +/* OSI Event structure - Modified for MMS_LITE */ +/************************************************************************/ + +typedef struct + { + void * nxevt; + SN_UNITDATA sn_req; /* event data in format needed by LEANT CLNP. */ + } SN_EVENT; + +typedef struct rd_wr_block + { + int inuse; + HANDLE hEvent; + OVERLAPPED *ovlp; + ST_UCHAR *framep; /* pointer to raw Ethernet frame */ + void *pb; + LLC_CONTEXT *gccp; + } RD_WR_BLOCK; + +/************************************************************************/ +/* MMS_LITE function to Queue received packet for Lite CLNP. */ +/************************************************************************/ +void QueueRxPacket (ST_UCHAR *framep); + +/************************************************************************/ +/* Functions that may be called from CLNP. */ +/************************************************************************/ +void ethdown (SN_UNITDATA *sn_req); +void ethdown_etype (SN_UNITDATA *sn_req); +void ethsapoff (void); +void ethsapon (ST_CHAR *drvname); +int llcsetup (void); + +BOOL QueryOid (HANDLE hDriver, ULONG ulOid, PBYTE pBuffer, ULONG ulLength); +BOOL SetOid (HANDLE hDriver, ULONG ulOid, PBYTE pBuffer, ULONG ulLength); + +void osifreeevt (SN_EVENT *evt); +SN_EVENT *osiallocevt (); +void osiputevt (SN_EVENT *evt); +SN_EVENT *osigetevt (); + +void OsiReadThread (LPDWORD lpdwParam); +void OsiReadThreadNT (LPDWORD lpdwParam); +void CALLBACK WriteCompletion (DWORD error, DWORD length, OVERLAPPED *ovlp); +void CALLBACK ReadCompletion (DWORD error, DWORD length, OVERLAPPED *ovlp); +void ProcessReadBlock (OVERLAPPED *ovlp); + +/************************************************************************/ +/* Global variables. */ +/************************************************************************/ +extern LLC_CONTEXT GCC; /* General Current Context */ +extern LLC_CONTEXT *GCCP; /* General Current Context Pointer */ + +extern int MaxWriteOut; +extern int MaxReadOut; +extern int FramesPerBlock; +extern int ReceptionMode; +extern int DriverID; +extern int NumWriteOut; +extern CRITICAL_SECTION csOsiList; /* Critical Section object for OSI Event List */ +extern BOOL bServiceControl; +extern BOOL bNT; +extern BOOL bOsiRequired; +extern DWORD Priority; + +#ifdef __cplusplus +} +#endif + +#endif /* !ETHSUB_INCLUDED */ + diff --git a/mmslib/inc/fkeydefs.h b/mmslib/inc/fkeydefs.h new file mode 100644 index 0000000..abc6394 --- /dev/null +++ b/mmslib/inc/fkeydefs.h @@ -0,0 +1,209 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986-2001 All Rights Reserved */ +/* */ +/* MODULE NAME : fkeydefs.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains user application definitions and is not */ +/* directly a part of MMSEASE. It is only used for the sample */ +/* application. */ +/* NOTE: If the ?key.c module is compiled with define UTIL_LIB only */ +/* following functions from wkey.c are exposed: */ +/* nlfn () */ +/* log_hex_bytes () */ +/* wait_debug_log () */ +/* wait_msg () */ +/* flush_keys () */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/18/03 JRB 05 Fix QNX #ifdef. */ +/* 02/17/03 CRM 04 Added "defined(linux)" code. */ +/* 02/17/03 JRB 03 Stop using SYSTEM_SEL define. */ +/* 05/16/01 EJV 02 Added proto for term_init, term_rest. */ +/* 01/22/98 NAV 01 Added funct_menu proto. */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef FKEYDEFS_INCLUDED +#define FKEYDEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#if defined (_WIN32) +#include +#endif + +/************************************************************************/ +/* NOTE: */ +/* For QUICK WIN application the call to kbhit () or getch () functions */ +/* will install our keyboard handling hook function to intercept the */ +/* keyboard input. */ +/* It is not necessary to call strt_Hook function, because the kbhit */ +/* and getch functions are checking for the hook beeing in place. */ +/* It will be wise to call the end_Hook function to clear the Windows */ +/* from our keyboard handling if not needed anymore. */ +/************************************************************************/ +int strt_Hook(ST_VOID); +int end_Hook(ST_VOID); + +/*====================================================================== + Basic functions keyboard functions: + kbhit () checks if keyboard was pressed. It installs also our + keyboard handling hook function for the QUICK WIN apps. + fkey_kbhit () returns SD_FALSE most of the times. Only every KBHIT_PERIOD + (50-th time when called) it will return the return + from the call to the kbhit () function. + This function may be absolete. + getch () returns the ASCII value of a pressed key. The kbhit () + function should be called first to see if the keyboard + was pressed. The function will install our keyboard + handling hook function for the QUICK WIN applications, + if not already installed. + flush_keys () flushes the keyboard character buffer. + get_a_char () will wait for the keyboard hit and return the ascii + code for the character. In addition the function will + echo the character to screen. +======================================================================*/ +#if !defined (_WIN32) +#if defined(__VMS) +/* VMS uses a short return type, and is prototyped in a lot of places */ +ST_INT kbhit (ST_VOID); +ST_INT getch (ST_VOID); +#else +int kbhit (ST_VOID); +int getch (ST_VOID); +#endif +#else +int nt_kbhit (ST_VOID); +#define kbhit nt_kbhit +#endif + +ST_RET fkey_kbhit (ST_VOID); +ST_VOID flush_keys (ST_VOID); +ST_CHAR get_a_char (ST_VOID); + +#define KBHIT_PERIOD 50 +#define KBHIT() fkey_kbhit () + + +/*======================================================================= + Formatting output to stdout (or FILE *) functions: + log_hex_bytes () outputs formatted hex data to a dest (may be stdout). + It will format each line (16 hex numbers) of the output + as follow: + "\noffs hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh *tttttttttttttttt*" + list_bytes () outputs formatted bytes to stdout. It will format each + line (16 hex numbers) of the output as follow: + "\n hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh hh " + list_ascii () outputs the ascii data to stdout. The ascii data will + be split on more then one line if required. The data in + the ptr do not have to be NULL terminated. + list_words () outputs the formatted words to stdout. The format is + as follow: + "hhhh hhhh hhhh ...." +========================================================================*/ +ST_VOID log_hex_bytes (FILE *dest, ST_UCHAR *ptr, ST_INT len); +ST_VOID list_bytes (ST_UCHAR *ptr, ST_INT len); +ST_VOID list_ascii (ST_CHAR *ptr, ST_INT len); +ST_VOID list_words (ST_UINT *ptr, ST_INT len); + + +/*======================================================================= + Functions to display a message and wait for user to hit a key: + wait_debug_log () outputs the str to a fptr (which may be stdout). + If the output is stdout the function will wait for user + to hit a key. During waiting the function will call + the servefun () to execute background processing. + wait_msg () outputs the str to stdout. The function will wait for + user to hit a key. During waiting the function will call + the servefun () to execute background processing. + wait_key () waits for user to hit a key. During waiting the function + will call the servefun () to execute background processing. + err_msg () outputs the str to stdout. The function will wait for + user to hit a key. Note that this func will NOT call + the servefun () while waiting for the keyboard input. + ask () asks a yes/no question and return the answer. + SD_TRUE will be returned if the answer is 'y' or 'Y'; + SD_FALSE will be returned if the answer is 'n' or 'N'; + if user presses the ENTER key the default answer will + be returned. + key_err () displays a message and returns shortly after, used to + display error messages without waiting for user to hit + a key to continue. +========================================================================*/ +ST_VOID wait_debug_log (FILE *fptr, ST_CHAR *str); +ST_VOID wait_msg (ST_CHAR *msg); +ST_VOID wait_key (ST_VOID); +ST_VOID err_msg (ST_CHAR *str); +ST_BOOLEAN ask (ST_CHAR *question, ST_BOOLEAN default_ans); +ST_VOID key_err (ST_CHAR *msg); + +/*======================================================================== + Pointer to USER's background function called while waiting for keyboard + input in following functions: + wait_key () + wait_msg () + wait_debug_log () + do_fun () + This function is initialized to a nlfn () which returns 0 if called. +========================================================================*/ +extern ST_RET (*servefun) (ST_VOID); + +/*======================================================================== + Pointers to USER's functions handling the actions for key F1 - F10 + This pointers will be initialized at program startup to bad_key () + function, which flushes the keyboard buffer. +========================================================================*/ +extern ST_VOID (*funct_1) (ST_VOID); +extern ST_VOID (*funct_2) (ST_VOID); +extern ST_VOID (*funct_3) (ST_VOID); +extern ST_VOID (*funct_4) (ST_VOID); +extern ST_VOID (*funct_5) (ST_VOID); +extern ST_VOID (*funct_6) (ST_VOID); +extern ST_VOID (*funct_7) (ST_VOID); +extern ST_VOID (*funct_8) (ST_VOID); +extern ST_VOID (*funct_9) (ST_VOID); +extern ST_VOID (*funct_10) (ST_VOID); +extern ST_VOID (*funct_menu) (ST_VOID); /* may be used to refresh menu */ + +ST_VOID fun_null (ST_VOID); /* make all function keys F1-F10 illegal*/ +ST_VOID do_fun (ST_VOID); /* execute functions assigned to funct_n*/ + /* pointers until F10 is pressed. */ +ST_INT check_key (ST_VOID); /* Check for pressed function key and */ + /* execute an action for that key. */ + /* Returns 1 if F10 key was pressed, */ + /* 0 otherwise. */ + +/* functions implemented in ?key.c */ +#if defined(_AIX) || defined(sun) || defined(__hpux) || defined(linux) \ + || (defined(__alpha) && !defined(__VMS)) \ + || defined(VXWORKS) || defined(__QNX__) || defined(__VMS) +ST_VOID term_init (); +ST_VOID term_rest (); +#elif defined (__OS2__) +int term_init (void); +int term_rest (void); +#endif + +#if defined (_WIN32) +ST_RET term_init (ST_VOID); +ST_INT term_rest (ST_VOID); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* FKEYDEFS_INCLUDED */ diff --git a/mmslib/inc/gen_list.h b/mmslib/inc/gen_list.h new file mode 100644 index 0000000..88414a2 --- /dev/null +++ b/mmslib/inc/gen_list.h @@ -0,0 +1,117 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1988-2000, All Rights Reserved */ +/* */ +/* MODULE NAME : gen_list.h */ +/* PRODUCT(S) : General Use */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the definitions as required for */ +/* manipulation of double-linked circular lists */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/04/06 EJV 04 Added DLLs incompatibility comments. */ +/* 04/20/00 JRB 03 Del (ST_VOID **) protos. ANSI doesn't like. */ +/* 10/09/98 JRB 02 Add list_find_prev, list_find_last. */ +/* 08/25/98 EJV 01 Use non-relaxed protos for __hpux. */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef GEN_LIST_INCLUDED +#define GEN_LIST_INCLUDED + + +#ifdef __cplusplus +extern "C" { +#endif + +/*#define FASTLIST */ + +/************************************************************************/ +/* LINKED LIST MECHANISM */ +/************************************************************************/ +/* This following structure is used in all doubly linked circular lists */ +/* as the first component in the structure. This allows one set of list*/ +/* manipulation primitives to be used with any linked structure */ +/* containing it. */ + +typedef struct dbl_lnk + { + /* Note: adding/removing fields to/from this struct will make older */ + /* !!! applications incompatible with new security DLLs. */ + struct dbl_lnk *next; + struct dbl_lnk *prev; + } DBL_LNK; + + +/************************************************************************/ +/* The variable below can be used to do integrity checking of any list */ +/* manipulated in the generic queuing functions by setting it to SD_TRUE */ + +extern ST_BOOLEAN list_debug_sel; + +/* For compatibility with older code only */ +#define list_sLogCtrl sLogCtrl + +/************************************************************************/ + +#ifdef FASTLIST +#define list_get_next(h,p) (((DBL_LNK *)p)->next == (DBL_LNK *)h ? NULL : ((DBL_LNK *)p)->next) +#define list_get_first(h) *(h);list_unlink (h,*h) +#else +/* NOTE: I_AM_THE_TRUE_GEN_LIST is only defined in the module */ +/* genlists.c so it will compile. */ +#if defined(I_AM_THE_TRUE_GEN_LIST) +ST_VOID *list_get_first (DBL_LNK **); +ST_VOID *list_get_next (DBL_LNK *, DBL_LNK *); +#else +ST_VOID *list_get_first (ST_VOID *); +ST_VOID *list_get_next (ST_VOID *, ST_VOID *); +#endif +#endif /* FASTLIST */ + + +/************************************************************************/ +/* Primitive functions for generic queue handling */ + +#if defined(I_AM_THE_TRUE_GEN_LIST) +ST_RET list_unlink (DBL_LNK **, DBL_LNK *); +ST_RET list_add_first (DBL_LNK **, DBL_LNK *); +ST_RET list_add_last (DBL_LNK **, DBL_LNK *); +ST_RET list_move_to_first (DBL_LNK **, DBL_LNK **, DBL_LNK *); +ST_RET list_find_node (DBL_LNK *, DBL_LNK *); +ST_RET list_add_node_after (DBL_LNK *, DBL_LNK *); +ST_INT list_get_sizeof (DBL_LNK *); +ST_VOID *list_get_last (DBL_LNK **); +#else +/* NOTE: these prototypes provide very little argument type checking. */ +/* They allow you to pass almost any argument without casting. */ +/* ANSI compilers automatically cast the arguments to (ST_VOID *). */ +/* This is not a great loss, because if the "real" prototypes were */ +/* used, most code would have to cast arguments to (DBL_LNK *) or */ +/* (DBL_LNK **), which would disable the argument type checking anyway. */ + +ST_RET list_unlink (ST_VOID *pphol, ST_VOID *pnode); +ST_RET list_add_first (ST_VOID *pphol, ST_VOID *pnode); +ST_RET list_add_last (ST_VOID *pphol, ST_VOID *pnode); +ST_RET list_move_to_first (ST_VOID *pphol1, ST_VOID *pphol2, ST_VOID *pnode); +ST_RET list_find_node (ST_VOID *pphol, ST_VOID *pnode); +ST_RET list_add_node_after (ST_VOID *pnode1, ST_VOID *pnode2); +ST_INT list_get_sizeof (ST_VOID *phol); +ST_VOID *list_get_last (ST_VOID *pphol); +#endif + +/* New functions. Abandon the "I_AM_THE_TRUE_GEN_LIST" casting business.*/ +DBL_LNK *list_find_prev (DBL_LNK *list_head_ptr, DBL_LNK *cur_node); +DBL_LNK *list_find_last (DBL_LNK *list_head_ptr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mmslib/inc/gensock2.h b/mmslib/inc/gensock2.h new file mode 100644 index 0000000..2c2a3f1 --- /dev/null +++ b/mmslib/inc/gensock2.h @@ -0,0 +1,591 @@ +/************************************************************************/ +/* SOFTWARE MODULE HEADER ***********************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2002 - 2007, All Rights Reserved */ +/* */ +/* MODULE NAME : gensock2.h */ +/* PRODUCT(S) : General Sockets Interface */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/08/08 MDE 29 Allow variable len header, sockEventQueueFlush*/ +/* 03/17/08 EJV 28 Chg MMSEASE_MOSI to !defined(MMS_LITE). */ +/* 12/07/07 EJV 27 Impl SISCO's KeepAlive (disconnect idle cons)*/ +/* GEN_SOCK_CTRL: added lastCheckIdleTime, */ +/* GEN_SOCK_CTXT: added maxIdleTime, */ +/* GEN_SOCK_STATS: added lastActivityTime. */ +/* 11/01/07 EJV 26 Moved include winsock2.h to sysincs.h. */ +/* Added new GS_DISCONNECT_* error codes. */ +/* Added GS_DISCONNECT_REASON_STR macro & vars. */ +/* 09/10/07 MDE 25 Added log_disable, to support IPC logging */ +/* 05/18/07 RKR 24 Ported to Red Hat 5 */ +/* 02/08/07 JRB 23 Add GEN_SOCK_EVENT, sockEventPut/Get. */ +/* Repl uSockConnect with 2 separate pointers */ +/* uSockConnectInd, uSockConnectConf. */ +/* 01/30/07 JRB 22 Del obsolete params & sockServiceFreeList. */ +/* 01/15/07 JRB 21 Del gs_poll_mode flag & poll_mode arg to */ +/* sockStart (no longer supported). */ +/* 01/03/07 EJV 20 GEN_SOCK_CTXT: del gSockMutex, txMutex fields*/ +/* 11/29/06 EJV 19 HP-UX: chg to use socklen_t. */ +/* 10/25/06 EJV 18 Ported to HP-UX. */ +/* 02/17/06 EJV 17 __VMS: added SOCK_OPTLEN,SOCK_ADDRLEN. */ +/* Aligned some defines. */ +/* 12/19/05 EJV 28 sockUsrFun: chg args. */ +/* GEN_SOCK: moved sockId, sockIdStr fields down*/ +/* 09/28/05 EJV 27 Implemented GEN_SOCK_CTXT. */ +/* Moved GENSOCK_MAX_HEADER_SIZE above struct. */ +/* Moved MUTEX macros to gensock2.c and renamed */ +/* GEN_SOCK: added sockId, sockIdStr, sockCtx. */ +/* GEN_SOCK_CTRL: added sockCtx. */ +/* Added GS_DISCONNECT_XXX_ERROR defines. */ +/* _sockAddSock: chg from ST_VOID to ST_RET ret.*/ +/* sockUsrFun: new func. */ +/* 07/11/05 EJV 26 Add convertIPAddr proto. */ +/* 06/10/05 JRB 25 Obsolete "_sockClose" function replaced with */ +/* macro that calls normal "sockClose". */ +/* 05/10/05 EJV 24 Added _sockAllocSock, _sockAddSock protos. */ +/* 03/23/05 EJV 23 Added sockCreateWakeupSockets */ +/* linux MMSEASE_MOSI:add GENSOCK_THREAD_SUPPORT*/ +/* 03/16/05 JRB 22 Add GENSOCK_HUNT_DISCONNECT define. */ +/* 02/21/05 JRB 21 Fix ioctlsocket define (deleted from tp0_sock)*/ +/* 02/10/05 MDE 20 Added sockGetRemAddrInfo */ +/* 07/22/04 EJV 19 sun: added GENSOCK_THREAD_SUPPORT */ +/* 06/18/04 MDE 18 Include winsock2.h if needed */ +/* 03/11/04 EJV 17 SOCK_OPTLEN,SOCK_ADDRLEN diff for each system*/ +/* 02/25/04 EJV 16 _AIX: added GENSOCK_THREAD_SUPPORT */ +/* Added SOCK_OPTLEN and SOCK_ADDRLEN. */ +/* Chg SOCK_NOTSOCK to be EBADF (not ENOTSOCK). */ +/* 01/27/04 EJV 15 Added SOCK_NOTSOCK error. */ +/* 01/14/04 EJV 14 GEN_SOCK: added sockTxQueuedGroupCnt field. */ +/* GEN_SOCK_DATA: added eot field. */ +/* Added sockGetTxQueueGroupCnt proto. */ +/* 10/23/03 JRB 13 Move all system includes to sysincs.h */ +/* 06/25/03 JRB 12 Move log macros to "sock_log.h". */ +/* 06/23/03 EJV 11 Added 'first' param to sockTxQueueAdd. */ +/* 06/20/03 EJV 10 Rem param from gs_mutex_get. */ +/* 06/20/03 EJV 09 Added sockTxQueueDestroy.Chg gSock w/pSock. */ +/* Alligned struct fields. */ +/* 06/19/03 EJV 08 _WIN32: added GENSOCK_THREAD_SUPPORT */ +/* Added comments to struct, #else, #endif */ +/* 06/19/03 JRB 07 Make Rx/Tx names more consistent. */ +/* 06/18/03 JRB 06 Move defines to top & add SOCKADDR*, ioctlsocket*/ +/* Del GENSOCK_THREAD_SUPPORT, define in makefile*/ +/* Add forward reference. */ +/* Add sockTxPend to GEN_SOCK. */ +/* Add GSOCK_LOG_FLOWH. */ +/* Del winsock2.h (windows.h gets right winsock)*/ +/* Use "base" slog macros. */ +/* Add uSockTxBufFree to GEN_SOCK_CONFIG. */ +/* Add sockTxMsg, sockTxQueue* funcs. */ +/* 06/13/03 MDE 05 More user poll featuresAdded sockGetFds */ +/* 06/13/03 EJV 04 Added parameter to gs_mutex_get. */ +/* 05/14/03 MDE 03 Added sockGetFds */ +/* 05/09/03 JRB 02 Add SOCK_* defines for !_WIN32 */ +/* 02/17/03 MDE 01 Created */ +/************************************************************************/ + +#ifndef GENSOCK_INCLUDED +#define GENSOCK_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "gen_list.h" +#include "glbsem.h" +#include "mem_chk.h" +#include "sock_log.h" /* logging macros */ + + +/* Windows vs. the rest of the world ... */ +#ifdef _WIN32 + +#if !defined(GENSOCK_THREAD_SUPPORT) +#define GENSOCK_THREAD_SUPPORT /*RXB*/ +#endif +#define SOCKET_ERRORNO WSAGetLastError() +#define SOCK_EADDRINUSE WSAEADDRINUSE +#define SOCK_WOULDBLOCK WSAEWOULDBLOCK +#define SOCK_INTR WSAEINTR +#define SOCK_NOBUFS WSAENOBUFS +#define SOCK_INPROGRESS WSAEINPROGRESS +#define SOCK_TIMEDOUT WSAETIMEDOUT +#define SOCK_NOTSOCK WSAENOTSOCK +#define CLOSE_SOCKET(x) closesocket(x) + +#define SOCK_OPTLEN ST_INT /* in getsockopt */ +#define SOCK_ADDRLEN ST_INT /* in accept */ + +#else /* !_WIN32 */ + +/* define multithread support for GENSOCK on some platforms */ +#if defined(_AIX) || defined(sun) || defined(__hpux) || \ + (defined(linux) && !defined(MMS_LITE)) +#if !defined(GENSOCK_THREAD_SUPPORT) +#define GENSOCK_THREAD_SUPPORT +#endif +#endif /* defined(_AIX) || ... */ + +#define SOCKET_ERRORNO errno +#define SOCK_EADDRINUSE EADDRINUSE +#define SOCK_WOULDBLOCK EWOULDBLOCK +#define SOCK_INTR EINTR +#define SOCK_NOBUFS ENOBUFS +#define SOCK_INPROGRESS EINPROGRESS +#define SOCK_TIMEDOUT ETIMEDOUT +#define SOCK_NOTSOCK EBADF +#define CLOSE_SOCKET(x) close(x) + +#define SOCKET int +#define INVALID_SOCKET (-1) +#define SOCKADDR struct sockaddr +#define SOCKADDR_IN struct sockaddr_in + +#if defined (__OS2__) /* OS/2 ioctl has extra arg */ +#define ioctlsocket(hSock,opt,valptr) ioctl(hSock, opt, (ST_CHAR *)valptr, sizeof(u_long)) +#elif defined (VXWORKS) /* VXWORKS wants arg to be int */ +#define ioctlsocket(hSock,opt,valptr) ioctl(hSock, opt, (int) valptr) +#else /* all other systems (e.g. UNIX) */ +#define ioctlsocket ioctl +#endif + +#if defined(_AIX) || defined(sun) || defined(__hpux) || defined(linux) +/* Note: __hpux will need these defines when passing access rights SCM_RIGHTS */ +/* through domain socket is working properly for _XOPEN_SOURCE_EXTENDED. */ +#define SOCK_OPTLEN socklen_t /* in getsockopt */ +#define SOCK_ADDRLEN socklen_t /* in accept */ +#elif defined(__VMS) +#define SOCK_OPTLEN __size_t /* in getsockopt */ +#define SOCK_ADDRLEN __size_t /* in accept */ +#else +/* all other no-Windows platforms not defined above */ +#define SOCK_OPTLEN int /* in getsockopt */ +#define SOCK_ADDRLEN int /* in accept */ +#endif +#endif /* !_WIN32 */ + + +struct tag_GEN_SOCK; /* Forward reference */ +/************************************************************************/ +/************************************************************************/ + +typedef struct tag_GEN_SOCK_DATA + { +/* User Send/Receive Queueing */ + DBL_LNK l; + +/* For user management of send/receive buffers */ + ST_UCHAR *usrBufBase; /* Data buffer */ + ST_INT usrBufLen; /* Total send buffer size */ + + ST_VOID *usr1; /* Misc. user use */ + ST_VOID *usr2; /* Misc. user use */ + +/* Data to be sent/Received Data */ + ST_UCHAR *data; /* Recv Data, Send Data */ + ST_INT dataLen; /* Length of data recvd, or to be sent */ + + ST_INT result; /* For receive, SD_SUCCESS or error */ + ST_BOOLEAN eot; /* SD_TRUE - if last msg in a group */ + } GEN_SOCK_DATA; + + + +/************************************************************************/ + +typedef struct + { + time_t createdTime; + time_t activeTime; /* connected or listening */ + ST_LONG numSend; /* num of RFC1006 msgs sent */ + ST_LONG numRecv; /* num of RFC1006 msgs received */ + ST_DOUBLE lastActivityTime; /* for disconnecting idle connections */ + } GEN_SOCK_STATS; + +/************************************************************************/ + +typedef struct tag_GEN_SOCK_CONFIG + { +/* Config parameters */ + ST_INT hdrSize; /* Default sizeof (ST_INT) */ + ST_INT hdrAllocSize; /* Size to allocate for hdrBuf */ + /* in GEN_SOCK struct */ + /* If 0 then hdrSize is used */ + +/* setsockopt parameters */ + ST_BOOLEAN setSockOpts; + ST_INT noDelay; + ST_INT keepAlive; + ST_INT reuseAddr; + ST_INT rcvBufSize; + ST_INT sndBufSize; + +/* User can set to disable receive */ + ST_BOOLEAN pauseRecv; + +/* Listen backlog */ + ST_INT listenBacklog; + +/* User callbacks */ + ST_RET (*uSockConnectInd) (struct tag_GEN_SOCK *pSock); + ST_RET (*uSockConnectConf) (struct tag_GEN_SOCK *pSock); + ST_VOID (*uSockDisconnect) (struct tag_GEN_SOCK *pSock); + ST_VOID (*uSockHunt) (struct tag_GEN_SOCK *pSock, ST_INT *huntStateIo, + ST_CHAR *buf, ST_INT bufCount, ST_INT *lenOut); + ST_VOID (*uSockRx) (struct tag_GEN_SOCK *pSock, GEN_SOCK_DATA *sockData); + ST_VOID (*uSockRxBufAlloc) (struct tag_GEN_SOCK *pSock, ST_INT dataLen, GEN_SOCK_DATA **sockData); + ST_VOID (*uSockTxBufFree) (struct tag_GEN_SOCK *pSock, GEN_SOCK_DATA *sockData); + ST_VOID (*uSockWritable) (struct tag_GEN_SOCK *pSock); + +/* User fields */ + ST_EVENT_SEM recvEvent; + ST_VOID *usr1; + ST_VOID *usr2; + ST_VOID *usr3; + ST_VOID *usr4; + +/* Internal Security Hooks: Set to NULL unless using security plug-in */ + ST_BOOLEAN secEnable; + ST_RET (*secConnectProc) (struct tag_GEN_SOCK *pSock); + ST_VOID (*secDisconnectProc) (struct tag_GEN_SOCK *pSock); + ST_RET (*secRxProc) (struct tag_GEN_SOCK *pSock, ST_CHAR *dest, ST_INT maxRx, + ST_INT flags, ST_INT *rxCountOut, ST_BOOLEAN *secDataLeftOut); + ST_RET (*secTxProc) (struct tag_GEN_SOCK *pSock, GEN_SOCK_DATA *sockData, ST_INT *numSentOut); + ST_VOID (*secWritable) (struct tag_GEN_SOCK *pSock); + ST_VOID (*secSockFree) (struct tag_GEN_SOCK *pSock); + + ST_VOID *secCtrl; + +/* Set to enable write select */ + ST_BOOLEAN chkWritable; + } GEN_SOCK_CONFIG; + +/************************************************************************/ + +/* State defines for GEN_SOCK */ +#define GS_STATE_LISTENING 1 +#define GS_STATE_STOPPING_LISTEN 2 +#define GS_STATE_FAILED_LISTEN 3 +#define GS_STATE_CONNECTING 4 +#define GS_STATE_CONNECTED 5 +#define GS_STATE_CLOSED 6 + +/* Role defines */ +#define GS_ROLE_CALLING 1 +#define GS_ROLE_LISTENING 2 +#define GS_ROLE_CALLED 3 + +/* disconnectReason defines */ +#define GS_DISCONNECT_UNKNOWN 0 +#define GS_DISCONNECT_CONNECT_FAILED 1 +#define GS_DISCONNECT_USR_REFUSED 2 +#define GS_DISCONNECT_SEND_FAILURE 3 +#define GS_DISCONNECT_RECV_FAILED 4 +#define GS_DISCONNECT_ACCEPT_FAILED 5 +#define GS_DISCONNECT_CLOSED 6 +#define GS_DISCONNECT_TERMINATING 7 +#define GS_DISCONNECT_RESOURCES_ERROR 8 +#define GS_DISCONNECT_INTERNAL_ERROR 9 +#define GS_DISCONNECT_NORMAL_DISCONNECT 10 /* normal disconnect */ +/* disconnectReason for SSL connection */ +#define GS_DISCONNECT_SSLE_LICENSE 11 /* SSL Engine licence expired */ +#define GS_DISCONNECT_SSLE_INT_ERR 12 /* SSL Engine internal error */ +#define GS_DISCONNECT_REKEY_FAILED 13 /* failed to rekey SSL conn */ +#define GS_DISCONNECT_CERT_VERIFY_ERR 14 /* certificate not acceptable */ +#define GS_DISCONNECT_CERT_ON_CRL 15 /* certificate on CRL */ +#define GS_DISCONNECT_SEC_PARAM_ERR 16 /* cipher or cert ctrl err */ +/* update gensock2.c sockDisconnReasonStr when more codes added */ + +extern ST_CHAR *sockDisconnReasonStr[]; +extern ST_INT sockDisconnReasonStrCnt; +/* disconnectReason strings for logging */ +#define GS_DISCONNECT_REASON_STR(reason) ((reason < sockDisconnReasonStrCnt) ? sockDisconnReasonStr[reason] : "DISCONNECT REASON: UNKNOWN") + +/* Hunt state defines */ +#define GENSOCK_HUNT_UNDERWAY 1 +#define GENSOCK_HUNT_DONE 2 +#define GENSOCK_HUNT_RESET 3 +#define GENSOCK_HUNT_DISCONNECT 4 /* stop hunting and disconnect */ + +#define RECV_STATE_HUNT 1 +#define RECV_STATE_DATA 2 + +#define GEN_SOCK_CTX_NAME_MAX_STR 32 /* Socket Context max name length */ +#define GEN_SOCK_CTX_ID_MAX_STR 20 +#define GEN_SOCK_SOCK_ID_MAX_STR (GEN_SOCK_CTX_NAME_MAX_STR + GEN_SOCK_CTX_ID_MAX_STR + 20) + +struct tag_GEN_SOCK_CTXT; /* Forward reference */ + +typedef struct tag_GEN_SOCK + { + DBL_LNK l; /* internal use */ + +/* Socket state */ + ST_INT sockState; + ST_INT role; + +/* Valid in user socket disconnet call */ + ST_INT disconnectReason; + +/* Config parameters */ + GEN_SOCK_CONFIG sockCfg; + + GEN_SOCK_STATS sockStats; + +/* For Listen socket only */ + ST_UINT maxActive; + ST_UINT numActive; + +/* For called socket, reference the listen socket */ + struct tag_GEN_SOCK *listenSocket; + + ST_INT callingAddrLen; + SOCKADDR_IN callingAddr; + +/* Internal */ + SOCKET hSock; + + ST_INT recvState; + ST_CHAR *recvBuf; + ST_INT recvDoneCount; + ST_INT recvCurrCount; + ST_CHAR *hdrBuf; /* ptr to buffer allocated after this struct*/ + GEN_SOCK_DATA *sockData; + + struct sockaddr_in sockAddrIn; + ST_BOOLEAN usrCloseCalled; + ST_BOOLEAN recvUsing; + + struct tag_GEN_SOCK_CTRL *serviceCtrl; + + GEN_SOCK_DATA *sockTxPend; /* Queue of data to be sent. */ + ST_UINT sockTxQueueGroupCnt; /* num of queued msgs w/eot to tx */ + + /* Fields added since MMS-SECURE, ICCP-SECURE v1.03 release */ + ST_UINT sockId; /* different id for each socket */ + ST_CHAR sockIdStr[GEN_SOCK_SOCK_ID_MAX_STR]; /* assemble for use in log later */ + + struct tag_GEN_SOCK_CTXT *sockCtx; + } GEN_SOCK; + +/************************************************************************/ + +/* Allow one for wakeup socket */ +#define GS_MAX_SOCK_PER_SERVICE FD_SETSIZE - 1 + +typedef struct tag_GEN_SOCK_CTRL + { + DBL_LNK l; + ST_INT numSock; + GEN_SOCK *sockList; + ST_DOUBLE lastCheckIdleTime; + +#if defined(GENSOCK_THREAD_SUPPORT) + ST_EVENT_SEM serviceEvent; + ST_THREAD_HANDLE thService; + ST_THREAD_ID tIdService; + + ST_UINT16 wakeupPort; + SOCKET xCalledSock; + SOCKET xCallingSock; +#endif /* GENSOCK_THREAD_SUPPORT */ + + struct tag_GEN_SOCK_CTXT *sockCtx; + } GEN_SOCK_CTRL; + +/************************************************************************/ +/* GEN_SOCK_EVENT: Socket event structure to store incoming event. */ + +/* Values for "eventType" member of GEN_SOCK_EVENT structure. */ +#define GS_EVENT_CONNECT_IND 1 /* connect indication */ +#define GS_EVENT_CONNECT_CONF 2 /* connect confirmation */ +#define GS_EVENT_DISCONNECT 3 /* socket disconnected */ +#define GS_EVENT_DATA_IND 4 /* data indication */ + +typedef struct + { + DBL_LNK l; + ST_INT eventType; /* type of event (GS_EVENT_DATA_IND, etc.)*/ + GEN_SOCK *pSock; + GEN_SOCK_DATA *sockData; + } GEN_SOCK_EVENT; + +/************************************************************************/ +/* gensock2 context */ +/* each sockStart() call will create new context with its own lists, */ +/* threads, and events handling. Call sockEnd() to clean. */ + +/* ctxStatus states */ +#define GEN_SOCK_CTX_ACTIVE 0 +#define GEN_SOCK_CTX_TERMINATING 1 + + +typedef struct tag_GEN_SOCK_CTXT + { + DBL_LNK l; /* internal use */ + + ST_UINT ctxId; /* diff id for each context */ + ST_INT ctxStatus; /* GEN_SOCK_CTX_xxx */ + ST_CHAR ctxName[GEN_SOCK_CTX_NAME_MAX_STR + GEN_SOCK_CTX_ID_MAX_STR]; + ST_BOOLEAN log_disable; + + /* Lists */ + GEN_SOCK_CTRL *sockServiceList; + + GEN_SOCK_EVENT *sockEventList; /* socket event list */ + /* maintained by sockEventPut/Get*/ + ST_INT sockEventCount; /* num events on sockEventList */ + /* maintained by sockEventPut/Get*/ + + ST_UINT maxIdleTime; /* ms, if>0 check for idle cons, */ + /* SISCO's KeepAlive implementation */ + + #if defined(GENSOCK_THREAD_SUPPORT) + /* Port used for wakeup sockets */ + ST_UINT16 gs_wakeup_port; /* default >= 55050 */ + + /* Used by list service thread */ + ST_INT gs_select_timeout; /* default = 100000 */ + + ST_BOOLEAN gTerminateService; + + #endif /* defined(GENSOCK_THREAD_SUPPORT) */ + } GEN_SOCK_CTXT; + +extern GEN_SOCK_CTXT *sockCtxList; /* contexts list */ + + +/************************************************************************/ +/* gensock2 user functions */ + +ST_RET sockStart (ST_CHAR *ctxName, GEN_SOCK_CTXT **sockCtxOut); +ST_RET sockStartEx (ST_CHAR *ctxName, GEN_SOCK_CTXT **sockCtxOut, ST_BOOLEAN log_disable); +ST_RET sockEnd (GEN_SOCK_CTXT *sockCtx); + +ST_RET sockInitCalling (GEN_SOCK_CTXT *sockCtx, GEN_SOCK_CONFIG *sockCfg, + ST_UINT16 portNo, ST_CHAR *ipAddr, GEN_SOCK **pSockOut); + +ST_RET sockInitListen (GEN_SOCK_CTXT *sockCtx, GEN_SOCK_CONFIG *sockCfg, + ST_UINT16 portNo, ST_INT maxActive, GEN_SOCK **pListenSockOut); + +ST_RET sockTx (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData, ST_INT *numSentOut); +ST_RET sockTxMsg (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData); +ST_RET sockTxQueueAdd (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData, ST_BOOLEAN first); +ST_RET sockTxQueueDestroy (GEN_SOCK *pSock); +ST_RET sockTxQueueProc (GEN_SOCK *pSock); +ST_UINT sockTxQueueGroupCntGet (GEN_SOCK *pSock); +ST_RET sockStopRecv (GEN_SOCK *pSock); +ST_RET sockClose (GEN_SOCK *pSock); +ST_RET sockFree (GEN_SOCK *pSock); + +/* Polling support */ + +/* Get socket descriptors */ +typedef struct + { + ST_INT totalfds; + ST_UINT selectnfds; + + ST_INT numReadfds; + fd_set readfds; + + ST_INT numWritefds; + fd_set writefds; + + ST_INT numExceptfds; + fd_set exceptfds; + } GENSOCK_FD_SET; + +ST_VOID sockGetFds (GEN_SOCK_CTRL *serviceCtrl, GENSOCK_FD_SET *sockFds); + +/* Return values for sockCtrlService, sockSelectResultProcess */ +#define GS_SELECT_NO_ACTIVE_SOCK 1 +#define GS_SELECT_TIMEOUT 2 +#define GS_SELECT_ERROR 3 +#define GS_SELECT_ACTIVE 4 +#define GS_SELECT_TERMINATED 5 + +ST_VOID sockServiceAll (GEN_SOCK_CTXT *sockCtx, ST_LONG timeOut); +ST_INT sockCtrlService (GEN_SOCK_CTRL *serviceCtrl, ST_LONG timeOut); + +#if !defined(GENSOCK_THREAD_SUPPORT) +ST_VOID sockInitAllFds (GENSOCK_FD_SET *sockFds); +#endif + +ST_VOID sockInitFds (GEN_SOCK_CTRL *serviceCtrl, GENSOCK_FD_SET *sockFds); +ST_VOID sockAddReadFds (GENSOCK_FD_SET *sockFds, SOCKET hSock); +ST_VOID sockAddWriteFds (GENSOCK_FD_SET *sockFds, SOCKET hSock); +ST_VOID sockAddExceptFds (GENSOCK_FD_SET *sockFds, SOCKET hSock); +ST_INT sockSelectResultProcess (GEN_SOCK_CTRL *serviceCtrl, + int nfds, GENSOCK_FD_SET *sockFds); + +/* Thread support */ +ST_RET sockCreateWakeupSockets (GEN_SOCK_CTXT *sockCtx, + ST_UINT16 basePort, ST_UINT portRange, + ST_UINT16 *usedPort, + SOCKET *callingSock, SOCKET *calledSock); +ST_VOID sockServiceWakeAll (GEN_SOCK_CTXT *sockCtx); +ST_VOID sockServiceWake (GEN_SOCK_CTRL *serviceCtrl); + +/* Logging */ +ST_VOID sockLogState (GEN_SOCK_CTXT *sockCtx); +ST_VOID sockLogSockState (GEN_SOCK *pSock, ST_CHAR *prefix); + +/* Socket info */ +ST_RET sockGetRemAddrInfo (GEN_SOCK *pSock, SOCKADDR_IN *remSockAddrDest, + ST_CHAR **remAddrTxtOut, ST_INT *portOut); + +/* Functions to maintain list of GEN_SOCK_EVENT. */ +ST_VOID sockEventPut (GEN_SOCK_CTXT *sockCtx, GEN_SOCK_EVENT *event); /* put on list*/ +GEN_SOCK_EVENT *sockEventGet (GEN_SOCK_CTXT *sockCtx); /* get from list*/ +ST_VOID sockEventQueueFlush (GEN_SOCK_CTXT *sockCtx, GEN_SOCK *pSock); + +/************************************************************************/ +/************************************************************************/ +/* INTERNAL */ +/************************************************************************/ + +/* sockUsrFun calls usrFun for each socket in every context, if the */ +/* usrFun doesn't return SD_SUCCESS then socket will be closed; */ +/* errMsg will be logged on error. */ +ST_VOID sockUsrFun (ST_RET (*usrFun)(ST_VOID *secCtrl), ST_CHAR *errMsg); + +GEN_SOCK *_sockAllocSock (GEN_SOCK_CTXT *sockCtx, + ST_INT role, ST_INT sockState, SOCKET hSock, + GEN_SOCK_CONFIG *sockCfg); +ST_RET _sockAddSock (GEN_SOCK *pSock); + +ST_RET _sockRecv (GEN_SOCK *pSock, ST_CHAR *dest, + ST_INT maxRx, ST_INT flags, ST_INT *rxCountOut); + +ST_RET _sockTx (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData, ST_INT *numSentOut); + +/* OBSOLETE: For backward compatibility only. New code should use "sockClose".*/ +#define _sockClose sockClose + + + /* -------------------------------------------- */ + /* Misc socket related functions */ + /* -------------------------------------------- */ + +ST_ULONG convertIPAddr (ST_CHAR *ipAddrStr, ST_BOOLEAN useGetHostByName); + + +/************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* GENSOCK_INCLUDED */ + + + + + + diff --git a/mmslib/inc/glberror.h b/mmslib/inc/glberror.h new file mode 100644 index 0000000..2890660 --- /dev/null +++ b/mmslib/inc/glberror.h @@ -0,0 +1,117 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : glberror.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains defines for all the entities that may */ +/* generate error code. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/30/98 DSF 02 Added E_ACTIVEMMS */ +/* 03/18/98 JRB 01 Added E_ASN1_DEC. */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + + +/*** NOTE : These defines are for reference only, and are not used in */ +/* creating the actual error code defines. */ + +#ifndef GBLERROR_INCLUDED +#define GBLERROR_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#define E_SUBSYS 0x0 /* underlying MAP subsystem: */ + /* Board or Board Driver (non-SISCO) */ + +#define E_DRIVER 0x100 /* SISCO MAP Board Driver */ +#define E_DH 0x200 /* SISCO Data Highway Driver */ + +#define EX_DRIVER 0x500 /* SISCO MAP Board Driver Exceptions */ +#define EX_DH 0x600 /* SISCO Data Highway Driver Exceptions */ + +#define E_CASESUIC 0xA00 /* CASE SUIC */ +#define E_ACSESUIC 0xB00 /* ACSE SUIC */ + +#define EX_CASESUIC 0xE00 /* CASE SUIC Exceptions */ +#define EX_ACSESUIC 0xF00 /* ACSE SUIC Exceptions */ + +#define E_TP4 0x1200 /* TP4 errors (see tp4api.h) */ + +#define E_CASESUIC_IS 0x1400 /* CASE SUIC Implementation Specific */ +#define E_ACSESUIC_IS 0x1500 /* ACSE SUIC Implementation Specific */ + +#define EX_CASESUIC_IS 0x1900 /* CASE SUIC Implementation Specific Exceptions */ +#define EX_ACSESUIC_IS 0x1A00 /* ACSE SUIC Implementation Specific Exceptions */ + +#define E_SESSIF 0x1E00 /* Session Interface */ +#define E_CASE 0x1F00 /* SISCO CASE Layer Provider */ + +#define EX_SESSIF 0x2400 /* Session Interface Exceptions */ +#define EX_CASE 0x2500 /* SISCO CASE Layer Provider Exceptions */ + +#define E_SESSIF_IS 0x2800 /* Session IF Implementation Spec */ +#define E_CASE_IS 0x2900 /* SISCO CASE Layer Provider Imp. Spec */ + +#define EX_SESSIF_IS 0x2D00 /* Session IF Implementation Spec Exceptions */ +#define EX_CASE_IS 0x2E00 /* SISCO CASE Layer Provider Imp. Spec Exceptions */ + +#define E_ACSE2 0x3000 /* ACSE2 errors (see acse2usr.h) */ +#define E_COPP 0x3100 /* COPP errors (see copp_usr.h) */ +#define E_COSP 0x3200 /* COSP errors (see cosp_usr.h) */ +#define E_CLNP 0x3400 /* CLNP errors (see clnp_usr.h) */ +#define E_SUBNET 0x3500 /* SUBNET errors (see clnp_usr.h) */ +#define E_ADLC 0x3600 /* ADLC errors (see adlc_usr.h) */ +#define E_RLI_IPC 0x3700 /* RLI_IPC errors (see rli_ipce.h) */ + +#define E_CFG_UTIL 0x4000 /* CFG UTIL codes */ +#define E_HLM 0x4100 /* HLM codes */ +#define E_HLM_MMS 0x4200 /* HLM MMS code */ + +#define E_ACTIVEMMS 0x4A00 /* ActiveMMS codes */ + +#define E_CM 0x5100 /* CM error codes base */ +#define E_CRM 0x5200 /* CRM error codes base */ + +#define E_MMS_GEN 0x6400 /* General provider */ +#define E_MMS_PPI 0X6500 /* Paired Primitive Interface */ +#define E_MMS_RESP 0x6600 /* Request Control Block (resp_err) */ +#define E_MMS_VMI 0x6700 /* Virtual Machine Interface */ +#define E_MMS_EXCPT 0x6800 /* MMS exceptions */ +#define E_LLP_ACSE 0x6900 /* ACSE LLP codes */ +#define E_LLP_CASE 0x6A00 /* CASE LLP codes */ +#define E_LLP_LLC 0x6B00 /* LLC LLP codes */ +#define E_MMS_LITE 0x6A00 /* MMS-LITE codes */ + +#define E_MMS_DS 0x6B00 /* MMS Directory Services */ + +#define E_ASN1_DEC 0x7000 /* ASN.1 decode errors */ + +/* The following define indicates the beginning of a range for */ +/* User-Defined error codes. Users may define error codes above this */ +/* value without conflicting with SISCO defined errors. */ + +#define E_USER_APP 0x7E00 /* User Application errors */ + +/* ******** DO NOT DEFINE ANY ERROR CODES ABOVE "0x7E00" ******** */ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/mmslib/inc/glbopt.h b/mmslib/inc/glbopt.h new file mode 100644 index 0000000..5fc5f58 --- /dev/null +++ b/mmslib/inc/glbopt.h @@ -0,0 +1,43 @@ +#ifndef GLBOPT_INCLUDED +#define GLBOPT_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2002-2002 All Rights Reserved */ +/* */ +/* MODULE NAME : glbopt.h */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Global compiler options to be used by all SISCO source modules. */ +/* This file may be used to enable optional features in */ +/* MMSEASE-LITE. Usually this is easier than adding an */ +/* option to several makefiles. If this file is modified, all */ +/* source code should be recompiled. */ +/* */ +/* This file must be included by "glbtypes.h" so that all SISCO */ +/* source modules will indirectly include it. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/09/05 JRB 09 Delete all defines. This file should now be */ +/* used only for "user" customization. */ +/* 09/22/03 EJV 08 Deleted ACSE_AUTH_ENABLED, S_SEC_ENABLED */ +/* 07/16/03 MDE 07 Removed ACSE_AUTH_ENABLED */ +/* 07/15/03 EJV 06 ACSE_AUTH_ENABLED enabled (ICCP Gateway) */ +/* 04/17/03 JRB 05 Chg MVLU_LEAF_FUN_LOOKUP_ENABLE (defined). */ +/* 12/20/02 JRB 04 Add MVLU_LEAF_FUN_LOOKUP_ENABLE (!defined). */ +/* 12/18/02 JRB 03 Add USE_RT_TYPE_2 (defined by default). */ +/* 10/17/02 ASK 02 Added ACSE_AUTH_ENABLED */ +/* 02/27/02 JRB 01 Created */ +/************************************************************************/ + +/* + * NOTE: Insert "global" defines here. These will be used when compiling + * all SISCO code. + */ + +#endif /* !GLBOPT_INCLUDED */ + diff --git a/mmslib/inc/glbsem.h b/mmslib/inc/glbsem.h new file mode 100644 index 0000000..23933b9 --- /dev/null +++ b/mmslib/inc/glbsem.h @@ -0,0 +1,565 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2008, All Rights Reserved */ +/* */ +/* MODULE NAME : glbsem.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : Multi-thread support defines and prototypes. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/01/08 EJV 61 Ported to Windows Vista. */ +/* 01/15/07 EJV 60 Chg S_LOCK_RESOURCES to S_LOCK_UTIL_RESOURCES*/ +/* 12/15/06 MDE 59 Added S_UNLOCK_CR_AND_RETURN_VAL */ +/* 10/25/06 EJV 58 Ported to HP-UX. */ +/* 07/13/06 EJV 57 Sun: changed the test for POSIX define. */ +/* 03/23/06 EJV 56 Added ( ) in #if a || b || (c && d). */ +/* 01/30/06 GLB 55 Integrated porting changes for VMS */ +/* 08/04/05 EJV 54 Reworked defs for UNIX and LINUX */ +/* 04/12/05 DSF 53 Added refCount member to GS_MUTEX (Windows) */ +/* 01/10/05 DSF 52 Added event member to GS_TIMER */ +/* 01/06/05 DSF 51 Added owner member to GS_MUTEX (Windows) */ +/* 01/14/05 EJV 50 Change removed. */ +/* 06/09/04 EJV 49 Added multithread support for sun. */ +/* 08/23/04 EJV 48 GS_TIMER: rpl elapsed w/ ST_DOUBLE expiration*/ +/* 05/10/04 EJV 47 gs_timer_cleanup: added timeout parameter. */ +/* gs_timer_init: added min_workers, max_workers*/ +/* Added GS_TIMER_WORKER_... defines. */ +/* GS_TIMER: added/moved fields. */ +/* 01/21/04 JRB 46 Add LYNX support. */ +/* 01/21/04 EJV 45 Win Timers: changed to use UNIX code. */ +/* Win impl preserved with _WIN32_timers define */ +/* 12/03/03 EJV 44 Add SD_WIN_VER_2003_AND_LATER, replaced */ +/* SD_WIN_VER_NET with SD_WIN_VER_2003; */ +/* gs_is_win_ver(): chg return ST_RET to ST_INT */ +/* 12/01/03 EJV 43 Added SD_WIN_VER_2K_AND_LATER. */ +/* 11/04/03 JRB 42 Del gs_sleep (use sMsSleep). */ +/* 10/24/03 JRB 41 Move gs_debug_sel to slog.h. */ +/* 09/29/03 JRB 40 Add "linux" support. */ +/* Enable gs_timer* functions for ALL systems. */ +/* 06/20/03 EJV 39 Redesigned mutex sems implementation. */ +/* 06/11/03 EJV 38 gs_named_mutex_xxx, gs_get_named_event_sem */ +/* defined for all systems. */ +/* __alpha: removed gs_xxx_sig and related code.*/ +/* 06/10/03 EJV 37 _WIN32: added gs_named_mutex_xxx functions. */ +/* 06/06/03 JRB 36 S_LOCK_RESOURCES use new gs_util_mutex. */ +/* Use new "Base" macros SLOG_*, SLOGC_*, SLOGH.*/ +/* Del GLBSEM_LOG_ALWAYS*, use SLOGALWAYS*. */ +/* 06/03/03 EJV 35 _WIN32: changed for 64-bit compiler: */ +/* ST_THREAD_HANDLE to uintptr_t */ +/* 04/14/03 JRB 34 Chg mutex macros to use gs_mutex_get/free. */ +/* Chg gs_get/free_sem functions to macros. */ +/* 03/03/24 EJV 33 Added _glbem_err_logstr & _glbem_nerr_logstr;*/ +/* S_LOCK_RESOURCES, S_UNLOCK_RESOURCES call */ +/* now non-logging gs_get_sem & gs_free_sem. */ +/* 02/03/03 EJV 32 _WIN32: added gs_is_win_ver(), SD_WIN_.. defs*/ +/* added gs_get_named_event_sem() */ +/* 01/14/03 EJV 31 Added gs_sleep(). */ +/* 11/01/02 EJV 30 Use SISCO's link list in GS_TIMER. */ +/* 07/29/02 EJV 29 Added gs_timer_get_resolution(), */ +/* GS_TIMER: made more fields common to UNIX,Win*/ +/* Added field delay_start for WIN32. */ +/* 04/09/02 EJV 28 __alpha: moved pthread.h up (cleaner code) */ +/* 02/06/02 EJV 27 _AIX: check for _THREAD_SAFE compiler define */ +/* 10/31/01 EJV 26 _WIN32: added code to call _beginthreadex; */ +/* Added gs_close_thread, gs_pulse_event_sem; */ +/* Added _ERR, _NERR log macros */ +/* UNIX: chg predicate to ST_INT from ST_BOOLEAN*/ +/* UNIX: added manualReset to GS_EVENT_SEM. */ +/* 09/20/01 EJV 25 _WIN32: added pending field to GS_TIMER. */ +/* 08/01/01 JRB 24 Add comment explaining S_LOCK_RES.. */ +/* 07/30/01 EJV 23 Added gs_timer_set_resolution().Chg GS_TIMER.*/ +/* Added ST_THREAD_RET, ST_THREAD_RET_VAL macros*/ +/* and changed gs_start_thread arg. */ +/* 07/25/01 DSF 22 Use <> when including windows.h */ +/* 07/24/01 EJV 21 _WIN32: added gs_timer support. */ +/* 04/04/01 DSF 20 Added gs_set_thread_name for WIN32 */ +/* 03/15/01 EJV 19 UNIX: corrected spelling of REENTRANT. */ +/* 03/07/01 EJV 18 Added slog macros for !DEBUG_SISCO */ +/* 02/19/01 EJV 17 _AIX: eliminated need to call gs_timer_init. */ +/* 02/16/01 EJV 16 AIX: added timer functions gs_times_xxx. */ +/* 01/16/01 EJV 15 Moved GET_THREAD_ID define here from glbsem.c*/ +/* 12/20/00 EJV 14 Ported to AIX. Revised DEC UNIX. */ +/* 12/13/00 EJV 13 Added gs_mutex_... funs for multiple mutex */ +/* semaphores support. Added ST_MUTEX_SEM. */ +/* 12/13/00 EJV 12 Removed USE_MANUAL_RESET_SEM. */ +/* 12/06/00 EJV 11 Changed gs_get_event_sem to accept arg. */ +/* 10/25/00 JRB 10 For _WIN32, define S_MT_SUP.. if _MT defined.*/ +/* 10/06/00 EJV 09 Ported to DEC UNIX (__alpha) pthread funcs. */ +/* Added few GLBSEM_LOG_FLOWn macros. */ +/* Deleted gs_chk_thread_id(), check _REENTRANT */ +/* 01/21/00 JRB 08 Del *sem_fun & *sem_funx function pointers. */ +/* Chg macros to call functions directly. */ +/* S_GS_INSTALL, gs_install, S_GS_INIT obsolete.*/ +/* Chg macros if !S_MT_SUPPORT to call gs_chk...*/ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 08/02/99 JRB 06 Chged "gs_get_event_sem" to "auto-reset" & */ +/* #ifdef'd out "gs_reset_event_sem". */ +/* 10/08/98 MDE 05 Migrated to updated SLOG interface */ +/* 05/05/98 DSF 04 Added SD_TIMEOUT */ +/* 12/11/97 KCR 03 Added gs_wait_mult_event_sem for _WIN32 */ +/* 10/06/97 DSF 02 Modified the macros used by SLOG such that */ +/* they could be used by SLOG in DEBUG_SISCO */ +/* mode */ +/* 08/15/97 MDE 01 Changed default ST_xxx to ST_VOID * */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef GBLSEM_INCLUDED +#define GBLSEM_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "slog.h" +#include "stime.h" +#include "gen_list.h" + +/************************************************************************/ +#define SD_TIMEOUT 2 + +/************************************************************************/ +/* Logging masks and variable */ + +#define GS_LOG_FLOW 0x0001 +#define GS_LOG_ERR 0x0002 +#define GS_LOG_NERR 0x0004 + +extern SD_CONST ST_CHAR *SD_CONST _glbem_flow_logstr; +extern SD_CONST ST_CHAR *SD_CONST _glbem_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _glbem_nerr_logstr; + +/* Mutex types: unnamed (local) can be used to synchronize threads in */ +/* a process, and named (global) can be used to synchronize processes */ +/* and threads within a process. */ +#define GS_MUTEX_UNNAMED 0 +#define GS_MUTEX_NAMED 1 + +/************************************************************************/ +/* Just for convenience ... */ +#define S_UNLOCK_CR_AND_RETURN() {S_UNLOCK_COMMON_RESOURCES(); return;} +#define S_UNLOCK_CR_AND_RETURN_VAL(_rc) {S_UNLOCK_COMMON_RESOURCES(); return (_rc);} + +/************************************************************************/ +/************************************************************************/ +/* WINDOWS 95/98/NT/2000 */ +/* These typedefs, defines, and function prototypes are for use with */ +/* Windows only. */ +/************************************************************************/ + +#if defined(_WIN32) /* VC++, 32-Bit */ + +#include + +/* The VC++ compiler automatically defines (_MT) if Multithread libs */ +/* are selected. The user clearly wants multithread support, so */ +/* S_MT_SUPPORT "MUST" be enabled. */ +/* DEBUG: something similar should be done for any system that supports */ +/* multithreading (e.g. OS2). */ + +#if defined(_MT) && !defined(S_MT_SUPPORT) +#define S_MT_SUPPORT +#endif + +#define ST_THREAD_ID unsigned + +typedef struct gs_mutex_tag + { + ST_INT mutexType; /* GS_MUTEX_UNNAMED (_NAMED) */ + ST_THREAD_ID owner; + ST_THREAD_ID refCount; + union + { + HANDLE hMutex; /* for named mutex & unnamed special */ + CRITICAL_SECTION cs; /* for unnamed mutex */ + } u; + } GS_MUTEX; + +#define GET_THREAD_ID() GetCurrentThreadId() +#define ST_MUTEX_SEM GS_MUTEX +#define ST_EVENT_SEM HANDLE +#if (_MSC_VER >= 1300) +#define ST_THREAD_HANDLE uintptr_t +#else +#define ST_THREAD_HANDLE unsigned long +#endif +#define ST_THREAD_ARG void * +#define ST_THREAD_CALL_CONV __stdcall +#define ST_THREAD_RET unsigned +#define ST_THREAD_RET_VAL 0 + +/* defines to distinguish Windows versions passed to gs_is_win_ver() */ +#define SD_WIN_VER_95_98_Me 1 /* 95, 98, Me */ +#define SD_WIN_VER_NT_AND_LATER 2 /* NT 3.51, NT 4.0 and above */ +#define SD_WIN_VER_2K_AND_LATER 3 /* 2000 and above */ +#define SD_WIN_VER_XP_AND_LATER 4 /* XP and above */ +#define SD_WIN_VER_2003_AND_LATER 5 /* 2003 and above */ +#define SD_WIN_VER_VISTA_AND_LATER 6 /* Vista and above */ + +/* specific Windows version */ +#define SD_WIN_VER_95 10 +#define SD_WIN_VER_98 20 +#define SD_WIN_VER_Me 30 +#define SD_WIN_VER_NT_351 40 +#define SD_WIN_VER_NT_40 50 +#define SD_WIN_VER_2000 60 +#define SD_WIN_VER_XP 70 +#define SD_WIN_VER_2003 80 +#define SD_WIN_VER_VISTA 90 + +#endif /* defined(_WIN32) */ + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* UNIX, Linux, ... */ +/* These typedefs, defines, and function prototypes are for use with */ +/* UNIX, Linux,... only */ +/* Implemented functions are complying with the "POSIX 1003.1c" standard.*/ +/************************************************************************/ + +#if defined(_AIX) || defined(sun) || defined(__hpux) || \ + defined(linux) || defined(__LYNX) || \ + (defined(__alpha) && !defined(__VMS)) || /* Tru64 alpha */ \ + (defined(__ALPHA) && defined(__VMS)) /* OpenVMS alpha */ + +#if (defined(__alpha) && !defined(__VMS)) || /* Tru64 alpha */ \ + (defined(__ALPHA) && defined(__VMS)) /* OpenVMS alpha */ +/* If the code is compiled with -pthread switch then the _REENTRANT */ +/* symbol is defined. This means that there should be a multithread */ +/* support for the code (the S_MT_SUPPORT should be defined). */ + +#if defined(_REENTRANT) && !defined(S_MT_SUPPORT) +#define S_MT_SUPPORT +#endif + +/* According to the POSIX standard this define should be included in */ +/* every application module. The included in */ +/* defines the _POSIX_C_SOURCE to be 199506L. */ + +#define _POSIX_C_SOURCE 199506L +#endif /* defined(__alpha) && !defined(__VMS) */ + +#if defined(_AIX) +/* If the compiler defines _THREAD_SAFE we should build the code */ +/* with multithread support (the S_MT_SUPPORT should be defined). */ + +#if defined(_THREAD_SAFE) && !defined(S_MT_SUPPORT) +#define S_MT_SUPPORT +#endif +#endif /* defined(_AIX) */ + +#if defined(sun) || defined(__hpux) +/* On Solaris 9,10 an application must define _POSIX_C_SOURCE >=199506L */ +/* IN EVERY MODULE OF AN APPLICATION to get the multithread support. */ +/* There is no other compiler define that indicates if a module is */ +/* compiled for multithread support. */ + +#define _POSIX_C_SOURCE 199506L + +#if (_POSIX_C_SOURCE-0 >= 199506L) && !defined(S_MT_SUPPORT) +#define S_MT_SUPPORT +#endif +#endif /* defined(sun) || defined(__hpux) */ + +#if defined(linux) || defined(__LYNX) +/* If the compiler defines _THREAD_SAFE, we should build the code */ +/* with multithread support (the S_MT_SUPPORT should be defined). */ + +#if (defined(_THREAD_SAFE) || defined(_REENTRANT)) && !defined(S_MT_SUPPORT) +#define S_MT_SUPPORT +#endif +#endif /* defined(linux) */ + +#if defined(S_MT_SUPPORT) +#include +typedef struct gs_event_sem_tag + { + ST_INT predicate; /* predicate to change value */ + pthread_mutex_t mutex; /* mutex sem protecting the cond*/ + pthread_cond_t cond; /* condition variable */ + ST_BOOLEAN manualReset; /* type os event semaphore */ + } GS_EVENT_SEM; + +#define GET_THREAD_ID() pthread_self() +#define ST_MUTEX_SEM pthread_mutex_t +#define ST_EVENT_SEM GS_EVENT_SEM * +#define ST_THREAD_ID pthread_t +#define ST_THREAD_HANDLE pthread_t +#define ST_THREAD_ARG void * +#define ST_THREAD_CALL_CONV +#define ST_THREAD_RET void * +#define ST_THREAD_RET_VAL NULL +#endif /* defined(S_MT_SUPPORT) */ + +#endif /* defined UNIX, linux,... */ + + +/************************************************************************/ +/************************************************************************/ +/* If no system has defined the required types, do so now. This allows */ +/* the source to include variables of these types w/o errors. */ + +#if !defined (ST_EVENT_SEM) + +#define GET_THREAD_ID() (ST_THREAD_ID) 0xFFFFFFFF +#define ST_MUTEX_SEM ST_VOID * +#define ST_EVENT_SEM ST_VOID * +#define ST_THREAD_ID ST_VOID * +#define ST_THREAD_HANDLE ST_VOID * +#define ST_THREAD_ARG ST_VOID * +#define ST_THREAD_CALL_CONV +#define ST_THREAD_RET ST_VOID +#define ST_THREAD_RET_VAL + +#endif /* !defined (ST_EVENT_SEM) */ + +/************************************************************************/ +/************************************************************************/ +/* Global functions */ + +/* SISCO Single MUTEX functions */ +ST_RET gs_init (ST_VOID); +ST_VOID gs_log_sem_state (ST_VOID); +ST_VOID gs_get_semx (SD_CONST ST_CHAR *srcFile, ST_INT srcLineNum); +ST_VOID gs_free_semx (SD_CONST ST_CHAR *srcFile, ST_INT srcLineNum); + +/* User's MUTEX Semaphore functions */ +ST_RET gs_mutex_create (ST_MUTEX_SEM *ms); +ST_RET gs_named_mutex_create (ST_MUTEX_SEM *ms, ST_CHAR *name); +ST_RET gs_mutex_get_tm (ST_MUTEX_SEM *ms, ST_LONG timeout); +#define gs_mutex_get(ms) gs_mutex_get_tm(ms, -1L) +ST_RET gs_mutex_free (ST_MUTEX_SEM *ms); +ST_RET gs_mutex_destroy (ST_MUTEX_SEM *ms); + +/* Event Semaphores */ +ST_EVENT_SEM gs_get_event_sem (ST_BOOLEAN manualReset); +ST_EVENT_SEM gs_get_named_event_sem (ST_CHAR *name, ST_BOOLEAN manualReset); +ST_RET gs_wait_event_sem (ST_EVENT_SEM es, ST_LONG timeout); +ST_RET gs_wait_mult_event_sem (ST_INT numEvents, ST_EVENT_SEM *esTable, + ST_BOOLEAN *activity, ST_LONG timeout); +ST_VOID gs_signal_event_sem (ST_EVENT_SEM es); +ST_VOID gs_pulse_event_sem (ST_EVENT_SEM es); +ST_VOID gs_reset_event_sem (ST_EVENT_SEM es); +ST_VOID gs_free_event_sem (ST_EVENT_SEM es); + +/* Thread */ +ST_RET gs_start_thread (ST_THREAD_RET (ST_THREAD_CALL_CONV *threadFunc) (ST_THREAD_ARG), + ST_THREAD_ARG threadArg, + ST_THREAD_HANDLE *threadHandleOut, + ST_THREAD_ID *threadIdOut); +ST_RET gs_wait_thread (ST_THREAD_HANDLE threadHandle, + ST_THREAD_ID threadId, ST_LONG timeout); +ST_RET gs_close_thread (ST_THREAD_HANDLE threadHandle); + +#if defined (_WIN32) +ST_VOID gs_set_thread_name (ST_THREAD_ID threadId, ST_CHAR *pThreadName); +#endif + +/* Misc. functions */ +#if defined (_WIN32) +ST_INT gs_is_win_ver (ST_UINT ver); +#endif + +/************************************************************************/ +/* These are the macro's used to call the glbsem get/free functions. */ +/* Note that the behavior depends on the defines used at compile time. */ + +#if defined(S_MT_SUPPORT) /* If code is to have MT support */ + +#if defined(DEBUG_SISCO) /* MT support, debug */ + +#define S_LOCK_COMMON_RESOURCES() gs_get_semx(thisFileName, __LINE__) +#define S_UNLOCK_COMMON_RESOURCES() gs_free_semx(thisFileName, __LINE__) + +/* NOTE: because S_LOCK_UTIL_RESOURCES & S_UNLOCK_UTIL_RESOURCES are called from SLOG, */ +/* the gs_mutex_get and gs_mutex_free (code handling unnamed mutexes) */ +/* should not be logging to avoid infinite loop (i.e. lock funct calling */ +/* log funct which calls lock funct again). */ +#define S_LOCK_UTIL_RESOURCES() gs_mutex_get (&gs_util_mutex) +#define S_UNLOCK_UTIL_RESOURCES() gs_mutex_free (&gs_util_mutex) + +#else /* MT support, no debug */ + +#define S_LOCK_COMMON_RESOURCES() gs_mutex_get (&gs_glb_mutex) +#define S_UNLOCK_COMMON_RESOURCES() gs_mutex_free (&gs_glb_mutex) + +#define S_LOCK_UTIL_RESOURCES() gs_mutex_get (&gs_util_mutex) +#define S_UNLOCK_UTIL_RESOURCES() gs_mutex_free (&gs_util_mutex) + +#endif + +#else /* No MT support is compiled in */ +#define S_LOCK_COMMON_RESOURCES() +#define S_UNLOCK_COMMON_RESOURCES() +#define S_LOCK_UTIL_RESOURCES() +#define S_UNLOCK_UTIL_RESOURCES() +#endif + +/* FOR BACKWARD COMPATIBILITY ONLY. Old code may be calling gs_get_sem, */ +/* gs_free_sem directly. These calls should be replaced with S_LOCK_.. */ +#define gs_get_sem() S_LOCK_UTIL_RESOURCES() +#define gs_free_sem() S_UNLOCK_UTIL_RESOURCES() + +/************************************************************************/ + +#define MAX_SEM_NEST_TRACK 20 +extern ST_MUTEX_SEM gs_glb_mutex; /* the global mutex semaphore */ +extern ST_MUTEX_SEM gs_util_mutex;/* UTILITY MUTEX semaphore: for "low-level"*/ + /* util functs (slog,mem_chk,stime,etc.)*/ +extern ST_BOOLEAN gs_already_inited; +extern ST_UINT gs_track; /* This variable when set to value >0 */ + /* during an application startup allows */ + /* tracking of MUTEX or EVENT sem. */ +extern ST_INT gs_currSemOwnerIndex; +extern ST_CHAR gs_currSemOwnerFile[MAX_SEM_NEST_TRACK][SLOG_MAX_FNAME+1]; +extern ST_INT gs_currSemOwnerLine[MAX_SEM_NEST_TRACK]; + +extern ST_DOUBLE gs_hwMutexTime; +extern ST_DOUBLE gs_hwEventTime; + + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + /* */ + /* Timer functions */ + /* */ + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + + /* Note: On AIX the real-time support is not implemented. */ + /* Functions such as timer_create, sleep, or nanosleep are*/ + /* not available (in AIX version 4.3.2 or 4.3.3). */ + /* This implementation of timers is using the GLBSEM */ + /* gs_wait_event_sem function implemented with phtreads */ + /* to support the timer functionality. */ + +/* The timer support will be initialized automatically when the function*/ +/* gs_timer_start is called for the first time. */ + +/* If the timer is of type SD_TIMER_ONESHOT then the timer resources */ +/* will be automatically deleted after the first time the timer is */ +/* serviced. For the SD_TIMER_PERIODIC timer the user needs to call */ +/* the gs_timer_end function to stop the timer and release resources. */ + +/* Before application exits the function gs_timer_cleanup should be */ +/* called to cleanup all resources associates with timers. */ + +/* NOTE: Since Windows is limiting number of timers to 16 per process */ +/* we have to use the UNIX timer implementation on Windows. */ +/* If the _WIN32_timers is defined then the Windows implementation*/ +/* of timers will be in effect for Windows. */ +#if defined _WIN32 +/* #define _WIN32_timers */ +#endif + +#define SD_TIMER_ONESHOT 1 +#define SD_TIMER_PERIODIC 2 + +#define GS_TIMER_WORKER_MIN 4 /* def min number of timer worker threads */ +#define GS_TIMER_WORKER_MAX 10 /* def max number of timer worker threads */ + +struct gs_timer_tag; /* forward definition */ + +typedef struct gs_timer_tag + { + DBL_LNK link; /* link list */ +#if defined (_WIN32_timers) + UINT timerID; /* timer id returned from timeSetEvent */ + ST_DOUBLE delay_start; /* time when delete timer delay started */ +#endif + ST_BOOLEAN terminate; /* set if timer should be terminated */ + ST_BOOLEAN pending; /* shows if timer processing is already pending */ + ST_ULONG interval; /* milliseconds, time between servicing */ + ST_DOUBLE expiration; /* milliseconds, next expiration time */ + ST_UINT type; /* timer type: oneshot or periodic */ + ST_VOID (*callback_fun)(ST_VOID *); + ST_VOID *arg; /* argument for the callback_fun. */ + ST_EVENT_SEM event; /* user can set this if it wants to be notified */ + /* when the timer object is destroyed */ + } GS_TIMER; + +/* The timer resolution could be set to the lowest value required by an */ +/* application before calling the gs_timer_start function. */ +/* On Windows system if the timer resolution is changed while the */ +/* application is running, only timers started afterwards will be */ +/* affected. On UNIX system all timers will be affected. */ + +ST_RET gs_timer_init (ST_UINT min_workers, ST_UINT max_workers); +ST_RET gs_timer_set_resolution (ST_ULONG timer_resolution); +ST_ULONG gs_timer_get_resolution (ST_VOID); + +GS_TIMER *gs_timer_start (ST_UINT type, + ST_ULONG interval, + ST_VOID (*callback_fun)(ST_VOID *), + ST_VOID *arg); +ST_RET gs_timer_end (GS_TIMER *timer_id); +ST_RET gs_timer_cleanup (ST_LONG timeout); + + +/************************************************************************/ +/* Logging macro's used internally by glbsem.c */ + +#define GLBSEM_LOG_ERR0(a) \ + SLOG_0 (gs_debug_sel & GS_LOG_ERR,_glbem_err_logstr,a) +#define GLBSEM_LOG_ERR1(a,b) \ + SLOG_1 (gs_debug_sel & GS_LOG_ERR,_glbem_err_logstr,a,b) +#define GLBSEM_LOG_ERR2(a,b,c) \ + SLOG_2 (gs_debug_sel & GS_LOG_ERR,_glbem_err_logstr,a,b,c) +#define GLBSEM_LOG_ERR3(a,b,c,d) \ + SLOG_3 (gs_debug_sel & GS_LOG_ERR,_glbem_err_logstr,a,b,c,d) + +#define GLBSEM_LOG_CERR0(a) \ + SLOGC_0 (gs_debug_sel & GS_LOG_ERR,a) +#define GLBSEM_LOG_CERR1(a,b) \ + SLOGC_1 (gs_debug_sel & GS_LOG_ERR,a,b) +#define GLBSEM_LOG_CERR2(a,b,c) \ + SLOGC_2 (gs_debug_sel & GS_LOG_ERR,a,b,c) +#define GLBSEM_LOG_CERR3(a,b,c,d) \ + SLOGC_3 (gs_debug_sel & GS_LOG_ERR,a,b,c,d) + +#define GLBSEM_LOG_NERR0(a) \ + SLOG_0 (gs_debug_sel & GS_LOG_NERR,_glbem_nerr_logstr,a) +#define GLBSEM_LOG_NERR1(a,b) \ + SLOG_1 (gs_debug_sel & GS_LOG_NERR,_glbem_nerr_logstr,a,b) +#define GLBSEM_LOG_NERR2(a,b,c) \ + SLOG_2 (gs_debug_sel & GS_LOG_NERR,_glbem_nerr_logstr,a,b,c) +#define GLBSEM_LOG_NERR3(a,b,c,d) \ + SLOG_3 (gs_debug_sel & GS_LOG_NERR,_glbem_nerr_logstr,a,b,c,d) + +#define GLBSEM_LOG_FLOW0(a) \ + SLOG_0 (gs_debug_sel & GS_LOG_FLOW,_glbem_flow_logstr,a) +#define GLBSEM_LOG_FLOW1(a,b) \ + SLOG_1 (gs_debug_sel & GS_LOG_FLOW,_glbem_flow_logstr,a,b) +#define GLBSEM_LOG_FLOW2(a,b,c) \ + SLOG_2 (gs_debug_sel & GS_LOG_FLOW,_glbem_flow_logstr,a,b,c) +#define GLBSEM_LOG_FLOW3(a,b,c,d) \ + SLOG_3 (gs_debug_sel & GS_LOG_FLOW,_glbem_flow_logstr,a,b,c,d) + +#define GLBSEM_LOG_CFLOW0(a) \ + SLOGC_0 (gs_debug_sel & GS_LOG_FLOW,a) +#define GLBSEM_LOG_CFLOW1(a,b) \ + SLOGC_1 (gs_debug_sel & GS_LOG_FLOW,a,b) +#define GLBSEM_LOG_CFLOW2(a,b,c) \ + SLOGC_2 (gs_debug_sel & GS_LOG_FLOW,a,b,c) +#define GLBSEM_LOG_CFLOW3(a,b,c,d) \ + SLOGC_3 (gs_debug_sel & GS_LOG_FLOW,a,b,c,d) + +/************************************************************************/ +#define gs_install() /* OBSOLETE: for backward compat. only */ +#define S_GS_INSTALL() /* OBSOLETE: for backward compat. only. */ +#define S_GS_INIT() /* OBSOLETE: for backward compat. only. */ + + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef GBLSEM_INCLUDED */ + diff --git a/mmslib/inc/glbtypes.h b/mmslib/inc/glbtypes.h new file mode 100644 index 0000000..a2b751f --- /dev/null +++ b/mmslib/inc/glbtypes.h @@ -0,0 +1,688 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2006, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : glbtypes.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/18/08 JRB 30 Use endian.h to set SD_BYTE_ORDER on linux. */ +/* 01/27/06 EJV 29 _WIN32: chg ST_UINT64 to unsigned __int64. */ +/* 08/01/05 JRB 28 Disable SD_CONST for ALL platforms. */ +/* 02/12/04 JRB 27 Disable ST_CONST for LINUX. */ +/* 01/08/04 EJV 26 Checked SD_BIG_ENDIAN on sun, rem pragma msg.*/ +/* 12/09/03 JRB 25 Add LYNX, don't def ST_CONST for LYNX. */ +/* 02/19/03 JRB 24 Define SD_BYTE_ORDER for each system. */ +/* 02/19/03 JRB 23 Del VAX-VMS & PSOS code. */ +/* 02/17/03 CRM 22 Added "defined(linux)" code. */ +/* 02/17/03 JRB 21 Del unsupported __IC86__ */ +/* Del obsolete DEBUG_MMS, DEBUG_SUIC, etc. */ +/* Del NEW_SYSTEM.. defines (not very useful). */ +/* 02/27/02 JRB 20 Include compiler option file "glbopt.h". */ +/* 10/05/01 EJV 19 sun supports ST_INT64 (long long) */ +/* 01/02/01 EJV 18 disabled SD_CONST macro for _AIX */ +/* enabled SD_CONST macro for QNX */ +/* 06/16/00 JRB 17 Define "*INT64" only if INT64_SUPPORT defined*/ +/* 03/13/00 MDE 16 disabled SD_CONST macro for WIN32 */ +/* 09/24/99 JRB 15 disabled SD_CONST macro for QNX */ +/* 09/13/99 MDE 14 Added SD_CONST modifiers */ +/* 04/14/99 MDE 13 Changed SYSTEM_SEL defines */ +/* 01/19/99 EJV 12 AIX: Added 64 bit integer support */ +/* 08/26/98 EJV 11 Deleted CPU_SEL and all releated defines. */ +/* __hpux supports 64-bit integers. */ +/* Eliminated spaces at the end of lines. */ +/* 02/09/98 RKR 10 Removed PRODUCT_ONLY_VMS_ALPHA */ +/* 01/23/98 EJV 09 Digital UNIX: revised. */ +/* 12/11/97 JRB 08 Cleaned up PSOS ifdefs. Define PSOS_SYSTEM */ +/* to compile. Use new SYSTEM_SEL=SYS_PSOS. */ +/* 12/11/97 JRB 07 Deleted _MRI ifdef (for Modicon/MICROTEC) */ +/* Deleted EMBEDDED_6800 SYSTEM_SEL. */ +/* 10/27/97 EJV 06 AIX: revised types, deleted pragma message() */ +/* 09/23/97 JRB 05 QNX: pragma stops unused symbol warnings. */ +/* 08/16/97 EJV 04 For QNX corrected ST_INT16, ST_UINT16. */ +/* 08/15/97 JRB 03 Use MOTO_68000 consistently. */ +/* 08/13/97 EJV 02 Changed #if (A && B) statements to avoid */ +/* warning if A or B has not been defined. */ +/* 06/20/97 MDE 01 Added 64 bit integer support for 95/NT */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef GBLTYPES_INCLUDED +#define GBLTYPES_INCLUDED + +#include "glbopt.h" /* Global compiler options. */ + +#ifdef __cplusplus +extern "C" { +#endif +void logprint(char * fmt,...); +/* +#define VXWORKS + +#define DEBUG_SISCO +#define MOSI +#define LEAN_T +#define MVL_UCA +#define MMS_LITE +#define TP0_ENABLED*/ +#ifndef WIN32 +#define WIN32 +#endif + + + + +/**/ + + + + + + + + + + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* General purpose defines, same for all platforms */ + +#define SD_TRUE 1 +#define SD_FALSE 0 +#define SD_SUCCESS 0 +#define SD_FAILURE 1 +#define SD_BIG_ENDIAN 0 +#define SD_LITTLE_ENDIAN 1 + +/* Define used for 'const' modifier */ +/* DEBUG: someday if all code is changed to consistently use SD_CONST, */ +/* this define may be replaced with the following: */ +/* #define SD_CONST const */ +#define SD_CONST + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +/* SYSTEM_SEL defines - bit masked */ +#define SYSTEM_SEL_MSOFT 0x0001 +#define SYSTEM_SEL_OS2 0x0008 +#define SYSTEM_SEL_OPEN_VMS 0x0010 +#define SYSTEM_SEL_SYS_5 0x0020 +#define SYSTEM_SEL_SYS_BSD 0x0040 +#define SYSTEM_SEL_QNX_C86 0x0100 +#define SYSTEM_SEL_SYSVXWORKS 0x0800 +#define SYSTEM_SEL_SYS_QNX4 0x1000 + +/* For backwards compatibility only, do not use. Will be deleted soon. */ +#if !defined(MSOFT) +#define MSOFT SYSTEM_SEL_MSOFT +#endif +#if !defined(OS2) +#define OS2 SYSTEM_SEL_OS2 +#endif +#if !defined(OPEN_VMS) +#define OPEN_VMS SYSTEM_SEL_OPEN_VMS +#endif +#if !defined(SYS_5) +#define SYS_5 SYSTEM_SEL_SYS_5 +#endif +#if !defined(SYS_BSD) +#define SYS_BSD SYSTEM_SEL_SYS_BSD +#endif +#if !defined(QNX_C86) +#define QNX_C86 SYSTEM_SEL_QNX_C86 +#endif +#if !defined(SYSVXWORKS) +#define SYSVXWORKS SYSTEM_SEL_SYSVXWORKS +#endif +#if !defined(SYS_QNX4) +#define SYS_QNX4 SYSTEM_SEL_SYS_QNX4 +#endif + +/************************************************************************/ +/************************************************************************/ +/* SYSTEM and CPU select defines. These are based on built in compiler */ +/* defines which allow automatic detection of the compiler. */ +/************************************************************************/ + +/************************************************************************/ +/* MS-DOS and WINDOWS */ +/************************************************************************/ +#if defined(MSDOS) || defined(__MSDOS__) /* Microsoft or Borland */ + +#if !defined(_WINDOWS) && !defined(_Windows) +#define PLAIN_DOS /* straight and pure DOS */ +#endif + +#define SD_BYTE_ORDER SD_LITTLE_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_MSOFT +#define SD_END_STRUCT + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long + +/* SD_TRUE or SD_FALSE only */ +#define ST_BOOLEAN unsigned char + + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* WINDOWS 95/NT */ +/************************************************************************/ +#if defined(_WIN32) /* VC++, 32-Bit */ + +#define SD_BYTE_ORDER SD_LITTLE_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_MSOFT +#define SD_END_STRUCT + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_INT64 __int64 +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_UINT64 unsigned __int64 +#define ST_BOOLEAN unsigned char + +/* This define shows that we really have support for 64 bit integers */ +#define INT64_SUPPORT + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* OS/2 - IBM C/SET2 and C/SET++ */ +/************************************************************************/ +#if defined(__OS2__) /* IBM C Set/2 */ + +#pragma message("Please look over the OS/2 system detect & defines") + +#pragma data_seg(alldata) + +#define SD_BYTE_ORDER SD_LITTLE_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_OS2 +#define SD_END_STRUCT + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_BOOLEAN unsigned char + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* SUN */ +/************************************************************************/ +#if defined(sun) /* SUN */ + +#define SD_BYTE_ORDER SD_BIG_ENDIAN +#define SYSTEM_SEL SYS_5 +#define SD_END_STRUCT long end_of; /* force struct to quad word allign */ + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_INT64 signed long long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_UINT64 unsigned long long +#define ST_BOOLEAN unsigned char + +/* This define shows that we really have support for 64 bit integers */ +#define INT64_SUPPORT + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* AIX */ +/************************************************************************/ +#if defined(_AIX) /* AIX */ + +#define SD_BYTE_ORDER SD_BIG_ENDIAN +#define SYSTEM_SEL SYS_5 +#define SD_END_STRUCT long end_of; /* force struct to quad word allign */ + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_INT64 signed long long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_UINT64 unsigned long long +#define ST_BOOLEAN unsigned char + +/* This define shows that we really have support for 64 bit integers */ +#define INT64_SUPPORT + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* OpenVMS AXP */ +/************************************************************************/ +#if defined(__ALPHA) && defined(__VMS) /* OpenVMS AXP uses DECC*/ + +#define SD_BYTE_ORDER SD_LITTLE_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_OPEN_VMS +#define SD_END_STRUCT long end_of; + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_BOOLEAN unsigned char + + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* Digital UNIX */ +/************************************************************************/ + +#if defined(__alpha) && !defined(__VMS) + +#define SD_BYTE_ORDER SD_LITTLE_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_SYS_5 +#define SD_END_STRUCT long end_of; + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed int +#define ST_INT64 signed long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned int +#define ST_UINT64 unsigned long +#define ST_BOOLEAN unsigned char + +/* This define shows that we really have support for 64 bit integers */ +#define INT64_SUPPORT + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* ECOS */ +/************************************************************************/ + +#if defined(__ECOS) + +#define SD_BYTE_ORDER SD_BIG_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_SYSVXWORKS +#define SD_END_STRUCT + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed int +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned int +#define ST_BOOLEAN unsigned char + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif /* __ECOS */ + +/************************************************************************/ +/* VXWORKS - VXWORKS on Motorola 680x0 processor */ +/************************************************************************/ + +#if defined(VXWORKS) + +#define SD_BYTE_ORDER SD_BIG_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_SYSVXWORKS +#define SD_END_STRUCT + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_BOOLEAN unsigned char + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* QNX */ +/************************************************************************/ +#ifdef __QNX__ /* This should be defined automatically by compiler. */ + +#pragma off (unreferenced) /* don't warn about unused symbols. */ + +#define SD_BYTE_ORDER SD_LITTLE_ENDIAN +#define SYSTEM_SEL SYSTEM_SEL_SYS_QNX4 +#define SD_END_STRUCT + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_BOOLEAN unsigned char + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* HP-UX */ +/************************************************************************/ +#if defined(__hpux) /* HP-UX */ + +#define SD_BYTE_ORDER SD_BIG_ENDIAN +#define SYSTEM_SEL SYS_5 +#define SD_END_STRUCT long end_of; /* force struct to quad word allign */ + + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +#define ST_INT32 signed long +#define ST_INT64 signed long long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +#define ST_UINT32 unsigned long +#define ST_UINT64 unsigned long long +#define ST_BOOLEAN unsigned char + +/* This define shows that we really have support for 64 bit integers */ +#define INT64_SUPPORT + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif + +/************************************************************************/ +/* LINUX SYSTEM */ +/* OR LYNXOS SYSTEM (same types) */ +/************************************************************************/ +#if defined(linux) || defined(__LYNX) + +/* NOTE: this may also work for setting SD_BYTE_ORDER on other */ +/* platforms that use the GNU C Library */ +#include +#if (__BYTE_ORDER ==__LITTLE_ENDIAN) + #define SD_BYTE_ORDER SD_LITTLE_ENDIAN +#elif (__BYTE_ORDER ==__BIG_ENDIAN) + #define SD_BYTE_ORDER SD_BIG_ENDIAN +#else + #error unsupported byte order +#endif + +#define SD_END_STRUCT + +/* We can tolerate machine-dependent sizes for these types */ +#define ST_CHAR char +#define ST_INT signed int +#define ST_LONG signed long int +#define ST_UCHAR unsigned char +#define ST_UINT unsigned int +#define ST_ULONG unsigned long +#define ST_VOID void +#define ST_DOUBLE double +#define ST_FLOAT float + +/* General purpose return code */ +#define ST_RET signed int + +/* We need specific sizes for these types */ +#define ST_INT8 signed char +#define ST_INT16 signed short +//renxiaobao +#define ST_INT32 signed int +//#define ST_INT32 signed long +#define ST_INT64 signed long long +#define ST_UINT8 unsigned char +#define ST_UINT16 unsigned short +//renxiaobao +#define ST_UINT32 unsigned int +//#define ST_UINT32 unsigned long +#define ST_UINT64 unsigned long +//#define ST_UINT64 unsigned long long +#define ST_BOOLEAN unsigned char + +/* This define shows that we really have support for 64 bit integers */ +#define INT64_SUPPORT + +/* This define shows that we have supplied all required */ +#define _SISCOTYPES_DEFINED + +#endif /* linux */ + +/************************************************************************/ +/************************************************************************/ +/* Make sure that this module has identified the target system */ + +#if !defined(_SISCOTYPES_DEFINED) +#error Warning: System not correctly identified by glbtypes.h +#endif + +#if !defined(SD_BYTE_ORDER) +#error SD_BYTE_ORDER not defined +#endif + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + + +#endif /* #ifndef GBLTYPES_INCLUDED */ diff --git a/mmslib/inc/gse_mgmt.h b/mmslib/inc/gse_mgmt.h new file mode 100644 index 0000000..4c6c97f --- /dev/null +++ b/mmslib/inc/gse_mgmt.h @@ -0,0 +1,252 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999-2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : gse_mgmt.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/03/06 CRM 01 Created */ +/************************************************************************/ + +#ifndef GSE_MGMT_INCLUDED +#define GSE_MGMT_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "acse2usr.h" +#include "asn1r.h" +#include "ethertyp.h" + + + +#define MAX_GSE_MGMT_ENCODE_BUF 1540 +#define MAX_VSTRING_BUF 65 +#define NUM_ELEMENTS 500 + +#define GET_GO_REF_REQ_TAG 1 +#define GET_GOOSE_ELE_NUM_REQ_TAG 2 +#define GET_GS_REF_REQ_TAG 3 +#define GET_GSSE_DATA_OFF_REQ_TAG 4 + +#define GET_GO_REF_RSP_TAG 1 +#define GET_GOOSE_ELE_NUM_RSP_TAG 2 +#define GET_GS_REF_RSP_TAG 3 +#define GET_GSSE_DATA_OFF_RSP_TAG 4 + +#define RSP_OTHER 0 +#define RSP_NOT_FOUND 1 + +#define GLB_ERROR 2 +#define GLB_ERR_OTHER 0 +#define GLB_ERR_UNKNOWN_CTRL_BLK 1 +#define GLB_ERR_RSP_TOO_LARGE 2 +#define GLB_ERR_CTRL_BLK_CONFIG_ERR 3 + + +#define GSE_MSG_TYPE_GO_REF_REQ 1 +#define GSE_MSG_TYPE_GOOSE_ELE_REQ 2 +#define GSE_MSG_TYPE_GS_REF_REQ 3 +#define GSE_MSG_TYPE_GSSE_DATA_OFF_REQ 4 + +#define GSE_MSG_TYPE_GLOBAL_ERROR_RSP 10 +#define GSE_MSG_TYPE_GO_REF_RSP 11 +#define GSE_MSG_TYPE_GOOSE_ELE_RSP 12 +#define GSE_MSG_TYPE_GS_REF_RSP 13 +#define GSE_MSG_TYPE_GSSE_DATA_OFF_RSP 14 + + + +/************************************************************************/ +/* BEGIN GSE MGMT DEFINITIONS */ +/************************************************************************/ +typedef struct + { + ST_UINT32 stateID; + ST_CHAR ident[MAX_VSTRING_BUF+1]; + ST_INT numIntegers; + ST_UINT32 *offset; + } GSE_REF_REQ; + +typedef struct + { + ST_UINT32 stateID; + ST_CHAR ident[MAX_VSTRING_BUF+1]; + ST_INT numVStrings; + ST_CHAR **references; + } GSE_OFFSET_REQ; + +/* Global error response sturcture */ +typedef struct + { + ST_UINT32 stateID; + ST_CHAR ident[MAX_VSTRING_BUF+1]; + ST_UINT32 confRev; + ST_UINT32 glbError; + } GSE_GLB_ERR_RSP; + + +/* Offset response sturctures */ +typedef struct + { + ST_INT rsp_type; + ST_UINT32 offset; + ST_UINT32 error; + } OFFSET_REQ_RESULTS; + +typedef struct + { + ST_UINT32 stateID; + ST_CHAR ident[MAX_VSTRING_BUF+1]; + ST_UINT32 confRev; + ST_CHAR datSet[MAX_VSTRING_BUF+1]; + ST_INT numResults; + OFFSET_REQ_RESULTS *result; + } GSE_OFFSET_RSP; + + +/* Reference response sturctures */ +typedef struct + { + ST_INT rsp_type; + ST_CHAR reference[MAX_VSTRING_BUF+1]; + ST_UINT32 error; + } REF_REQ_RESULTS; + + +typedef struct + { + ST_UINT32 stateID; + ST_CHAR ident[MAX_VSTRING_BUF+1]; + ST_UINT32 confRev; + ST_CHAR datSet[MAX_VSTRING_BUF+1]; + ST_INT numResults; + REF_REQ_RESULTS *result; + } GSE_REF_RSP; + + + +/************************************************************************/ +/* STRUCTURE DEFINITIONS */ +/************************************************************************/ + +typedef struct + { + ST_UINT32 stateID; + ST_INT msgType; + + union GSE_MSG + { + GSE_REF_REQ refReq; + GSE_OFFSET_REQ offReq; + GSE_OFFSET_RSP offRsp; + GSE_REF_RSP refRsp; + GSE_GLB_ERR_RSP glbErrRsp; + } msg; + } GSE_MGMT_MSG; + + + + +ST_UCHAR *getGoRefReqEncode (GSE_REF_REQ *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ +ST_UCHAR *getGOOSEEleNumReqEncode (GSE_OFFSET_REQ *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ +ST_UCHAR *getGsRefReqEncode (GSE_REF_REQ *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ +ST_UCHAR *getGSSEDataOffsetReqEncode (GSE_OFFSET_REQ *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ + + + +ST_UCHAR *gse_mgmt_NotSupported (ST_VOID); +ST_UCHAR *getGlbErrorRspEncode (GSE_GLB_ERR_RSP *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ +ST_UCHAR *getGoRefRspEncode (GSE_REF_RSP *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ +ST_UCHAR *getGOOSEEleNumRspEncode (GSE_OFFSET_RSP *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ +ST_UCHAR *getGsRefRspEncode (GSE_REF_RSP *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ +ST_UCHAR *getGSSEDataOffsetRspEncode (GSE_OFFSET_RSP *ctrl, + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut, /* ptr to len encoded */ + ETYPE_INFO *etype_info, /* ptr to Ethertype info */ + ST_UINT8 *dstMac, /* destination MAC address */ + ST_UINT8 *srcMac); /* source MAC address */ + + + +/************************************************************************/ +/* Functions for receiving GSE_MGMT messages. */ +/* Decode GSE_MGMT message and fill in GSE_MGMT_MSG struct. */ +/************************************************************************/ +GSE_MGMT_MSG *gse_mgmt_msg_decode ( + SN_UNITDATA *sn_req, /* message to decode */ + ETYPE_INFO *etypeInfo); /* where to store decoded Ethertype info*/ + +/* Must be called to free structure returned from gse_mgmt_msg_decode. */ +ST_VOID gse_mgmt_msg_free (GSE_MGMT_MSG *gseMgmtMsg); + + +/************************************************************************/ +/* END GSE MGMT DEFINITIONS */ +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* GSE_MGMT_INCLUDED */ diff --git a/mmslib/inc/gvaldefs.h b/mmslib/inc/gvaldefs.h new file mode 100644 index 0000000..cc8e9cb --- /dev/null +++ b/mmslib/inc/gvaldefs.h @@ -0,0 +1,48 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986-1997 All Rights Reserved */ +/* */ +/* MODULE NAME : gvaldefs.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This include file contains common declarations used throughout */ +/* the user application code. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef GVALDEFS_INCLUDED +#define GVALDEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#define STRGETSTRINGSIZE 256 + +ST_BOOLEAN floatget (ST_FLOAT *dest); +ST_BOOLEAN doubleget( ST_DOUBLE *dest); +ST_BOOLEAN intget (ST_INT *dest); /* int get function */ +ST_BOOLEAN hexget (ST_INT *dest); /* int get function */ +ST_BOOLEAN longget (ST_LONG *dest); /* long int get function */ +ST_BOOLEAN longhexget (ST_LONG *dest); /* long int get function */ +ST_BOOLEAN strget (ST_CHAR *dest); /* string get function */ +ST_INT input_hex (ST_UCHAR *dest_str, ST_INT maxbytes); + +ST_VOID entry1 (ST_INT maxlen, ST_CHAR *str_ptr); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/mmslib/inc/lean_a.h b/mmslib/inc/lean_a.h new file mode 100644 index 0000000..d7ab0ee --- /dev/null +++ b/mmslib/inc/lean_a.h @@ -0,0 +1,145 @@ +#ifndef LEAN_A_H +#define LEAN_A_H +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996 - 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : lean_a.h */ +/* PRODUCT(S) : Lean-T Stack SUIC */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/13/05 EJV 11 MMSEASE_MOSI: added extern domsock_listener */ +/* 03/15/05 EJV 10 MMSEASE_MOSI: set MAX_SUIC_CHAN to 1000 */ +/* Added mms_event_fd. */ +/* 02/08/02 JRB 09 Move osicfgx prototype to mvl_acse.h. */ +/* 11/27/00 JRB 08 Add osicfgx proto. */ +/* 12/10/97 JRB 07 Add MMSEventName and hMMSEvent for OS2. */ +/* 08/14/97 JRB 06 #include "acse2usr.h" and use PRES_ADDR in */ +/* DIB_ENTRY. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 05/02/97 JRB 05 Del MAX_?_SEL defines. Use suicacse.h defs. */ +/* 05/01/97 JRB 04 Move MAX_SUIC_CHAN define to here. */ +/* 01/02/96 JRB 03 Add MMSEventName and hMMSEvent. */ +/* 10/04/96 JRB 02 #ifdef MCGW, add adlcAddr to DIB_ENTRY. */ +/* Add *_clt7 function prototypes. */ +/* 05/29/96 MDE 01 Changed DIB_ENTRY - name is now a pointer */ +/* 03/27/96 MDE Created */ +/************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (_WIN32) +#include +#endif /* _WIN32 */ + +#if defined (__OS2__) +#define INCL_BASE +#include +#endif /* __OS2__ */ + +#include "asn1defs.h" /* for MMS_OBJ_ID definition */ +#include "acse2usr.h" /* for PRES_ADDR definition */ + +#if defined(MMSEASE_MOSI) +#define MAX_SUIC_CHAN 1024 /* number of channels <=TP_MAX_NUM_CONNS*/ +#include "gensock2.h" /* defines SOCKET */ +extern SOCKET mms_event_fd; /* wakeup socket, indicating TCP Events */ +extern SOCKET domsock_listener; /* domain socket connected to the */ + /* RFC1006_LISTENER task. */ +#else +#define MAX_SUIC_CHAN 256 /* number of channels */ +#endif + +/************************************************************************/ +/* The structure below is used to save Directory and other information */ +/* about local and remote AE's read in from SUIC.DIB */ +/************************************************************************/ + +#define DIB_ENTRY_DEFINED + +struct dib_entry +{ + ST_LONG reserved; /* reserved field */ + ST_CHAR *name; /* user-defined ASCII character string */ + ST_CHAR local; /* local or remote name */ + ST_UCHAR AP_title_pres; /* present flag */ + MMS_OBJ_ID AP_title; /* AP title */ + ST_UCHAR AP_inv_id_pres; /* present flag */ + ST_INT32 AP_invoke_id; /* AP invocation ID */ + ST_UCHAR AE_qual_pres; /* present flag */ + ST_INT32 AE_qual; /* AE qualifier */ + ST_UCHAR AE_inv_id_pres; /* present flag */ + ST_INT32 AE_invoke_id; /* AE invocation ID */ + PRES_ADDR pres_addr; /* Presentation address. */ +} ; +typedef struct dib_entry DIB_ENTRY; + +/************************************************************************/ +/* Channel-oriented control structure used to hold connection-specific */ +/* information */ +/************************************************************************/ + +#define MAX_TX_OUT 10 /* max. outstanding TX requests allowed */ + +struct chanctrl + { + DIB_ENTRY *loc_de; /* Pointer to Local DIB Entry */ + DIB_ENTRY *rem_de; /* Pointer to Remote DIB Entry */ + } ; +extern struct chanctrl *s_chan_ctrl; + +/************************************************************************/ +/* Structure to store incoming associate indication in case no listen */ +/* channel is available */ +/************************************************************************/ + +extern ST_INT num_loc_dib_entries; +extern ST_INT num_rem_dib_entries; +extern DIB_ENTRY *loc_dib_table; +extern DIB_ENTRY *rem_dib_table; + +/************************************************************************/ +/* Event handling variables for WIN32 & OS2. */ +/************************************************************************/ +#ifdef _WIN32 +extern ST_CHAR *MMSEventName; /* Pointer to the globally unique name of Event Object */ +extern HANDLE hMMSEvent; /* Handle to Event Object to be signalled when */ + /* s_serve () needs to be called */ +#endif /* _WIN32 */ +#ifdef __OS2__ +extern ST_CHAR *MMSEventName; /* Pointer to the globally unique name of Event Object */ +extern HEV hMMSEvent; /* Handle to Event Object to be signalled when */ + /* s_serve () needs to be called */ +#endif /* __OS2__ */ + +/************************************************************************/ +/* Prototypes */ +/************************************************************************/ +ST_VOID s_reset_ctrl (ST_INT); +ST_RET init_dirser (ST_VOID); +DIB_ENTRY *find_dib_entry (ST_CHAR *); +DIB_ENTRY *find_loc_dib_entry (ST_CHAR *ar_name); +DIB_ENTRY *find_rem_dib_entry (ST_CHAR *ar_name); + +ST_RET init_dirser_clt7 (ST_VOID); +DIB_ENTRY *find_dib_entry_clt7 (ST_CHAR *); +DIB_ENTRY *find_loc_dib_entry_clt7 (ST_CHAR *ar_name); + +#ifdef __cplusplus +} +#endif + +#endif /* !LEAN_A_H */ + + diff --git a/mmslib/inc/llcio.h b/mmslib/inc/llcio.h new file mode 100644 index 0000000..284435f --- /dev/null +++ b/mmslib/inc/llcio.h @@ -0,0 +1,337 @@ +#ifndef _LLCIO_H +#define _LLCIO_H + +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994, All Rights Reserved */ +/* */ +/* MODULE NAME : llcio.h */ +/* PRODUCT(S) : osillc.sys */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/21/98 IKE 03 Converted to 7.0 Data types, removed */ +/* underscores so it can be compiled */ +/* 11/02/95 DSF 02 Enhanced to retrieve stats information */ +/* 12/08/94 DSF 01 Added SET_OFFSET */ +/* 03/10/94 DSF Initial Release */ +/************************************************************************/ + +/* +** User Functions +*/ + +int LlcOpen (char *Name); +int LlcClose (int fd); +int LlcWrite (int fd, char *buffer, int size); +int LlcRead (int fd, char *buffer, int size); +int LlcIoctl (int fd, void *pArg, int size); + + + + +/* +** IOCTL Management +*/ + +/* +** LLC Driver IOCTL requests +*/ + + +#define LLC_ADD_MULTI 1 +#define LLC_DEL_MULTI 2 +#define LLC_GET_HW_ADDR 3 +#define LLC_SET_FRAME_FILTER 4 +#define LLC_BIND_LSAP 5 +#define LLC_UNBIND_LSAP 6 +#define LLC_TRACE_ON 7 +#define LLC_TRACE_OFF 8 +#define LLC_DEBUG_ON 9 +#define LLC_DEBUG_OFF 10 +#define LLC_GET_PROTO_STATS 11 +#define LLC_GET_MAC_STATS 12 +#define LLC_ARM_SIGNAL 13 +#define LLC_ARM_POST 15 +#define LLC_GET_EMB_PHYS_ADDR 16 +#define LLC_SET_WRITE_CONFIRM_FLAG 17 +#define LLC_GET_DEBUG 18 +#define LLC_POST_BUFS 19 +#define LLC_SET_OFFSET 20 +#define LLC_GET_MAC_CHARS 21 +#define LLC_CLEAR_MAC_STATS 22 +#define LLC_CLEAR_PROTO_STATS 23 + + +/* +** LLC Driver IOCTL Errors +*/ + +#define LLCERR_NO_ERROR 0 +#define LLCERR_LSAP_BOUND 1 +#define LLCERR_LSAP_NOTBOUND 2 +#define LLCERR_ILLEGAL_OPERATION 3 +#define LLCERR_UNKNOWN_COMMAND 4 + +#define MAX_HWADDR_SIZE 12 + +typedef struct + { + int Opcode; + int Status; + } LLCGENERICIOCTL; + + +typedef struct + { + int Opcode; + int Status; + int cSize; + char Multicast[MAX_HWADDR_SIZE]; + } LLCADDMULTI; + +typedef struct + { + int Opcode; + int Status; + int cSize; + char Multicast[MAX_HWADDR_SIZE]; + } LLCDELMULTI; + +typedef struct + { + int Opcode; + int Status; + int cSize; + char HwAddr[MAX_HWADDR_SIZE]; + } LLCGETHWADDR; + +typedef struct + { + int Opcode; + int Status; + unsigned Lsap; + } LLCBINDLSAP; + +typedef struct + { + int Opcode; + int Status; + } LLCUNBINDLSAP; + +typedef struct + { + int Opcode; + int Status; + long EmbPhysAddr; + long EmbSize; + } LLCGETEMBPHYSADDR; + +typedef struct + { + int Opcode; + int Status; + char far *pfWriteConfirm; + } LLCSETWRITECONFIRMFLAG; + +typedef struct + { + int Opcode; + int Status; + int VxDID; + } LLCARMPOST; + +typedef struct + { + int Opcode; + int Status; + long offset; + } LLCSETOFFSET; + + +typedef struct tagUSERBUFDESC + { + struct tagUSERBUFDESC far *Next; + char far *pBuf; + int cBufSize; + int cDataSize; + } USERBUFDESC; + +typedef struct + { + int Opcode; + int Status; + USERBUFDESC far *pBufDesc; + } LLCPOSTBUFS; + +typedef struct + { + int Opcode; + int Status; + int MessageNum; + int Parm1; + int Parm2; + int Parm3; + } LLCGETDEBUG; + + +/* +** NDIS Protocol Driver Stats +*/ + +typedef struct + { + long nFramesReceived; + long nReceiveLookaheadReceived; + long nReceiveChainReceived; + long nFramesDiscardedNotRecognized; + long nFramesDiscardedOutOfResources; + long nTransferDataFailed; + long nTransmitChainIssued; + long nTransmitChainFailed; + long nFramesDelivered; /* DOS only */ + } LLCPROTOSTATS; + +typedef struct + { + int Opcode; + int Status; + LLCPROTOSTATS ProtoStats; + } LLCGETPROTOSTATS; + +typedef struct + { + int Opcode; + int Status; + } LLCCLEARPROTOSTATS; + +/* +** NDIS MAC Driver Characteristics +*/ + +typedef struct /* structure for MAC service specific info */ + { + int cSize; /* length of the characteristic table */ + char TypeName[16]; /* name of the MAC type (eg. 802.3...) */ + int cStationAddr; /* length of station address (MAC) */ + char PermMACAddr[16]; /* hardware default MAC address */ + char CurrMACAddr[16]; /* current MAC address in use */ + long FunctionAddr; /* current functional address of adapter */ + long reserved; /* pointer to multicast table */ + long LinkSpeed; /* link speed bits/sec */ + long fMAC; /* flags of capabilities */ + int MaxFrameSize; /* maximum MAC frame which can be sent */ + long TotalTxSpace; /* total transmit buffer space */ + int cTxBlockSize; /* size of allocated transmission blocks */ + long TotalRxSpace; /*total reception buffer space */ + int cRxBlockSize; /*reception buffer alloc blk size */ + char VendorID[3]; /*vendor IEEE ID */ + char VendorAdapterDesc; /*vendor adapter description */ + long reserved2; /*pointer to vendor serial number */ + int IRQLevel; /*interrupt level */ + int TransmitQueueDepth; + int nMaxDataBlocks; + } LLCMACCHARS; + +typedef struct + { + int Opcode; + int Status; + LLCMACCHARS MacChars; + } LLCGETMACCHARS; + +typedef struct + { + int cSize; /*size of table */ + long LastDiagTime; /*seconds since 1-1-1970 of diags */ + long MACStatus; /*mac status, this is a bit mask */ + /* Bits 0-2: 0 - Hardware Not Installed */ + /* 1 - Hardware Failed Pwrup Diags */ + /* 2 - Hardware Failed CNFG Prob */ + /* 3 - Hardware Faulted */ + /* 4 - Hardware Marginally Operat */ + /* 7 - Fully Operational */ + /* Bit 3: MAC BOUND */ + /* Bit 4: MAC OPEN */ + /* Bit 5: DIAG_IN_PROGRESS */ + int CurrPacketFilter; /* Bit 1: Directed and Multicast Group */ + /* Bit 2: Broadcast */ + /* Bit 3: Promiscuous */ + /* Bit 4: All Source Routing */ + long reserved; /*pointer to media specific stats */ + long LastClearTime; /*seconds since 1-1-1970 */ + long nOkFramesReceived; /*total frames received ok */ + long nCrcErrorFrames; /*total frames received with crc errors */ + long nBytesReceived; /*total number of bytes recieved */ + long nFramesDiscarded; /*total number of frames discarded */ + long nMulticastFramesReceived; /*total number of multicast frames rxd OK */ + long nBroadcastFramesReceived; /*total number of broadcast frames rxd OK */ + long reserved1; + long reserved2; + long reserved3; + long reserved4; + long reserved5; + long nFramesDiscardedHwError; /*total number of frames discarded due to HW err*/ + long nFramesTransmittedOk; /*total number of frames transmitted OK */ + long nBytesTransimittedOk; /*total number of bytes transmitted OK */ + long nMulticastFramesTransmitted; /*total number of multicast transmitted */ + long nBroadcastFramesTransmitted; /*total broadcast frame transmitted */ + long reserved6; + long reserved7; + long nFramesNotTransmittedTimeout; /*total frames not transmitted due to timeout */ + long nFramesNotTransmittedHwError; /*total frames not transmitted due to HW ERR */ + } LLCMACSTATS; + +typedef struct + { + int Opcode; + int Status; + LLCMACSTATS MacStats; + } LLCGETMACSTATS; + +typedef struct + { + int Opcode; + int Status; + } LLCCLEARMACSTATS; + +typedef union + { + LLCADDMULTI AddMulti; + LLCDELMULTI DelMulti; + LLCGETHWADDR GetHwAddr; + LLCBINDLSAP BindLsap; + LLCUNBINDLSAP UnBindLsap; + LLCGETEMBPHYSADDR GetEmbPhysAddr; + LLCSETWRITECONFIRMFLAG SetWriteConfirmFlag; + LLCPOSTBUFS PostBufs; + LLCARMPOST ArmPost; + LLCGETDEBUG GetDebug; + LLCSETOFFSET SetOffset; + LLCGETMACCHARS GetMacChars; + LLCGETMACSTATS GetMacStats; + LLCCLEARMACSTATS ClearMacStats; + LLCGETPROTOSTATS GetProtoStats; + LLCCLEARPROTOSTATS ClearProtoStats; + } LLCIOCTL; + + + +/* +** Function prototypes +*/ + +int llc_getstats (LLCMACCHARS *MacChars, + LLCMACSTATS *MacStats, + LLCPROTOSTATS *ProtoStats); +void llc_clearstats (); + + +#endif diff --git a/mmslib/inc/llcioctl.h b/mmslib/inc/llcioctl.h new file mode 100644 index 0000000..995fac0 --- /dev/null +++ b/mmslib/inc/llcioctl.h @@ -0,0 +1,121 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : llcioctl.c */ +/* PRODUCT(S) : OSI LLC NDIS 3.1 VxD */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/16/97 DSF 05 Added stats */ +/* 09/10/96 DSF 04 Added Length field to SET_MULTI */ +/* 09/05/96 DSF 03 Added SET_FILTER */ +/* 08/14/96 DSF 02 Added Transmit Completion object */ +/* 04/01/96 DSF 01 Initial Release */ +/* */ +/************************************************************************/ + +#define IOCTL_BASE 0x8100 +#define IOCTL_GET_PHYS_ADDR (IOCTL_BASE + 1) +#define IOCTL_SET_MULTI (IOCTL_BASE + 2) +#define IOCTL_ARM_EVENT (IOCTL_BASE + 3) +#define IOCTL_SEND (IOCTL_BASE + 4) +#define IOCTL_RECEIVE (IOCTL_BASE + 5) +#define IOCTL_ARM_COMPLETE (IOCTL_BASE + 6) +#define IOCTL_SET_FILTER (IOCTL_BASE + 7) +#define IOCTL_GET_STATS (IOCTL_BASE + 8) + + +#define PHYS_ADDR_LENGTH 6 +typedef struct _GET_PHYS_ADDR + { + UINT Status; + char PhysAddr[PHYS_ADDR_LENGTH]; + } GET_PHYS_ADDR; + + +typedef struct _SET_MULTI + { + UINT Status; + UINT Length; + char MultiAddr[2 * PHYS_ADDR_LENGTH]; + } SET_MULTI; + +typedef struct _SET_FILTER + { + UINT Status; + } SET_FILTER; + +typedef struct _ARM_EVENT + { + UINT Status; + HANDLE EventHandle; + } ARM_EVENT; + +typedef struct _ARM_COMPLETE + { + UINT Status; + HANDLE CompleteHandle; + } ARM_COMPLETE; + +#if !defined (GET_STATS_DEFINED) +typedef struct _MAC_STATS + { + ULONG HardwareStatus; + ULONG MaxLookahead; + ULONG MaxFrameSize; + ULONG LinkSpeed; + ULONG TransmitBufferSpace; + ULONG ReceiveBufferSpace; + ULONG TransmitBlockSize; + ULONG ReceiveBlockSize; + ULONG MaximumTotalSize; + ULONG MacOptions; + ULONG ConnectStatus; + ULONG XmitOk; + ULONG RcvOk; + ULONG XmitError; + ULONG RcvError; + ULONG RcvNoBuffer; + ULONG RcvCrcError; + ULONG TransmitQueueLength; + } MAC_STATS; + +typedef struct _PROTO_STATS + { + ULONG XmitOk; + ULONG RcvOk; + ULONG XmitError; + ULONG RcvError; + ULONG RcvUnknown; + ULONG XmitInd; + ULONG RcvInd; + ULONG AllocError; + } PROTO_STATS; + +typedef struct _USER_STATS + { + ULONG XmitOk; + ULONG RcvOk; + ULONG XmitError; + ULONG RcvError; + ULONG RcvUnknown; + } USER_STATS; + +typedef struct _GET_STATS + { + UINT Status; + MAC_STATS mac; + PROTO_STATS proto; + USER_STATS user; + } GET_STATS; + +#define GET_STATS_DEFINED +#endif diff --git a/mmslib/inc/mem_chk.h b/mmslib/inc/mem_chk.h new file mode 100644 index 0000000..ff264cf --- /dev/null +++ b/mmslib/inc/mem_chk.h @@ -0,0 +1,339 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986-2004 All Rights Reserved */ +/* */ +/* MODULE NAME : mem_chk.h */ +/* PRODUCT(S) : General Use */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the declarations of the dynamic memory */ +/* handling functions. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/06/04 EJV 16 Added dyn_mem_ptr_status2. */ +/* 04/14/03 DSF 15 Cleanup */ +/* 04/08/03 DSF 14 added m_mem_crt_debug */ +/* 04/04/03 DSF 13 new/delete checks for MFC */ +/* 08/20/01 JRB 12 chk_* functions chged to nd_chk_*. */ +/* chk_* names are now ALWAYS macros. */ +/* Make 4 sets of macros depending on whether */ +/* DEBUG_SISCO and/or SMEM_ENABLE defined. */ +/* Don't define SMEM_ENABLE, do from makefiles. */ +/* Remove logging backward compatibility stuff. */ +/* 08/06/01 RKR 11 S_THISFILE was removed, need a thisFileName */ +/* 03/19/01 JRB 10 Move SMEM context defs to "smem.h". */ +/* 01/25/01 DSF 09 new/delete checks */ +/* 11/01/00 MDE 08 Additional SMEM work */ +/* 01/21/00 MDE 07 Added SMEM support */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 01/26/98 MDE 05 Added 'chk_strdup' */ +/* 12/08/98 MDE 04 Added 'ST_BOOLEAN m_auto_hw_log' */ +/* 10/08/98 MDE 03 Migrated to updated SLOG interface */ +/* 10/14/97 DSF 02 m_bad_ptr_val is now a pointer */ +/* 09/16/97 DSF 01 chk_debug_en is UINT */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MEM_CHK_INCLUDED +#define MEM_CHK_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef SMEM_ENABLE +#include "smem.h" +#endif + +/************************************************************************/ +/* MEM_CHK MACROS and FUNCTION PROTOTYPES */ +/* Memory allocation macros. There are 4 sets of macros depending on */ +/* DEBUG_SISCO and SMEM_ENABLE. Each set of macros calls a unique set */ +/* of functions. */ +/* The DEBUG macros use thisFileName (instead of __FILE__) to reduce */ +/* memory usage. Any file using these macros MUST contain the following */ +/* statement: */ +/* static char *thisFileName = __FILE__; */ +/************************************************************************/ + +#if defined(SMEM_ENABLE) + #if defined(DEBUG_SISCO) + #define M_MALLOC(ctx,x) x_m_malloc (ctx,x, thisFileName,__LINE__) + #define M_CALLOC(ctx,x,y) x_m_calloc (ctx,x,y,thisFileName,__LINE__) + #define M_REALLOC(ctx,x,y) x_m_realloc (ctx,x,y,thisFileName,__LINE__) + #define M_STRDUP(ctx,x) x_m_strdup (ctx,x, thisFileName,__LINE__) + #define M_FREE(ctx,x) x_m_free (ctx,x, thisFileName,__LINE__) + + #define chk_malloc(x) x_m_malloc (MSMEM_GEN,x, thisFileName,__LINE__) + #define chk_calloc(x,y) x_m_calloc (MSMEM_GEN,x,y,thisFileName,__LINE__) + #define chk_realloc(x,y) x_m_realloc (MSMEM_GEN,x,y,thisFileName,__LINE__) + #define chk_strdup(x) x_m_strdup (MSMEM_GEN,x, thisFileName,__LINE__) + #define chk_free(x) x_m_free (MSMEM_GEN,x, thisFileName,__LINE__) + + ST_VOID *x_m_malloc (SMEM_CONTEXT *smem_ctx, ST_UINT size, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + + ST_VOID *x_m_calloc (SMEM_CONTEXT *smem_ctx, ST_UINT num, + ST_UINT size, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + + ST_VOID *x_m_realloc (SMEM_CONTEXT *smem_ctx, ST_VOID *old, + ST_UINT size, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + ST_VOID x_m_free (SMEM_CONTEXT *smem_ctx, ST_VOID *ptr, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + ST_CHAR *x_m_strdup (SMEM_CONTEXT *smem_ctx, ST_CHAR *str, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + + #else /* !DEBUG_SISCO */ + + #define M_MALLOC(ctx,x) nd_m_malloc (ctx,x) + #define M_CALLOC(ctx,x,y) nd_m_calloc (ctx,x,y) + #define M_REALLOC(ctx,x,y) nd_m_realloc (ctx,x,y) + #define M_STRDUP(ctx,x) nd_m_strdup (ctx,x) + #define M_FREE(ctx,x) nd_m_free (ctx,x) + + #define chk_malloc(x) nd_m_malloc (MSMEM_GEN,x) + #define chk_calloc(x,y) nd_m_calloc (MSMEM_GEN,x,y) + #define chk_realloc(x,y) nd_m_realloc (MSMEM_GEN,x,y) + #define chk_strdup(x) nd_m_strdup (MSMEM_GEN,x) + #define chk_free(x) nd_m_free (MSMEM_GEN,x) + + ST_VOID *nd_m_malloc (SMEM_CONTEXT *smem_ctx, ST_UINT size); + ST_VOID *nd_m_calloc (SMEM_CONTEXT *smem_ctx, ST_UINT num, ST_UINT size); + ST_VOID *nd_m_realloc (SMEM_CONTEXT *smem_ctx, ST_VOID *old, ST_UINT size); + ST_VOID nd_m_free (SMEM_CONTEXT *smem_ctx, ST_VOID *ptr); + ST_CHAR *nd_m_strdup (SMEM_CONTEXT *smem_ctx, ST_CHAR *str); + + #endif /* !DEBUG_SISCO */ +#else /* !SMEM_ENABLE */ + #if defined(DEBUG_SISCO) + + #define M_MALLOC(ctx,x) x_chk_malloc (x, thisFileName,__LINE__) + #define M_CALLOC(ctx,x,y) x_chk_calloc (x,y,thisFileName,__LINE__) + #define M_REALLOC(ctx,x,y) x_chk_realloc (x,y,thisFileName,__LINE__) + #define M_STRDUP(ctx,x) x_chk_strdup (x, thisFileName,__LINE__) + #define M_FREE(ctx,x) x_chk_free (x, thisFileName,__LINE__) + + #define chk_malloc(x) x_chk_malloc (x, thisFileName,__LINE__) + #define chk_calloc(x,y) x_chk_calloc (x,y,thisFileName,__LINE__) + #define chk_realloc(x,y) x_chk_realloc (x,y,thisFileName,__LINE__) + #define chk_strdup(x) x_chk_strdup (x, thisFileName,__LINE__) + #define chk_free(x) x_chk_free (x, thisFileName,__LINE__) + + ST_VOID *x_chk_realloc (ST_VOID *old, + ST_UINT size, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + ST_VOID *x_chk_malloc (ST_UINT size, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + ST_VOID *x_chk_calloc (ST_UINT num, + ST_UINT size, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + ST_CHAR *x_chk_strdup (ST_CHAR *str, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + ST_VOID x_chk_free (ST_VOID *old, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line); + + #else /* !DEBUG_SISCO */ + + #define M_MALLOC(ctx,x) nd_chk_malloc (x) + #define M_CALLOC(ctx,x,y) nd_chk_calloc (x,y) + #define M_REALLOC(ctx,x,y) nd_chk_realloc (x,y) + #define M_STRDUP(ctx,x) nd_chk_strdup (x) + #define M_FREE(ctx,x) nd_chk_free (x) + + #define chk_malloc(x) nd_chk_malloc (x) + #define chk_calloc(x,y) nd_chk_calloc (x,y) + #define chk_realloc(x,y) nd_chk_realloc (x,y) + #define chk_strdup(x) nd_chk_strdup (x) + #define chk_free(x) nd_chk_free (x) + + ST_VOID *nd_chk_malloc (ST_UINT size); + ST_VOID *nd_chk_calloc (ST_UINT num, ST_UINT size); + ST_VOID *nd_chk_realloc (ST_VOID *old, ST_UINT size); + ST_CHAR *nd_chk_strdup (ST_CHAR *str); + ST_VOID nd_chk_free (ST_VOID *ptr); + + #endif /* !DEBUG_SISCO */ +#endif /* !SMEM_ENABLE */ + + +/************************************************************************/ +/* chk_debug_en bit assignments */ +/* These are the defines to be used by all new applications */ +#define MEM_LOG_ERR 0x0001 +#define MEM_LOG_CALLOC 0x0002 +#define MEM_LOG_MALLOC 0x0004 +#define MEM_LOG_REALLOC 0x0008 +#define MEM_LOG_FREE 0x0010 + +extern ST_UINT chk_debug_en; + +/************************************************************************/ +/* Replacement Memory allocation functions. */ +/************************************************************************/ + +ST_VOID init_mem_chk (ST_VOID); +ST_VOID dyn_mem_ptr_status (ST_VOID); +ST_UINT dyn_mem_ptr_status2 (ST_VOID *marker_ptr); +ST_VOID dyn_mem_ptr_statistics (ST_BOOLEAN log_to_screen); +ST_VOID check_mem_list (ST_VOID); +ST_RET chk_alloc_ptr (ST_VOID *ptr); + + +/************************************************************************/ +/* fatal error service function pointers, used for unrecoverable errors */ +/************************************************************************/ +#define MEM_ERR_EXIT_CODE 2001 + +extern ST_VOID *(*m_memerr_fun)(ST_UINT size); /* for malloc */ +extern ST_VOID *(*c_memerr_fun)(ST_UINT num, ST_UINT size); /* for calloc */ +extern ST_VOID *(*r_memerr_fun)(ST_VOID *old, ST_UINT size); /* for realloc*/ + +/************************************************************************/ +/* statistics */ +/************************************************************************/ +extern ST_UINT32 chk_curr_mem_count; +extern ST_UINT32 chk_max_dyn_mem_ptrs; +extern ST_UINT32 chk_max_mem_allocated; +extern ST_UINT32 chk_curr_mem_size; + + +/************************************************************************/ +/************************************************************************/ +/* HEAP checking functions and macros */ + +/* These defines are used to control the level or print in chk_hp */ +#define DEBUG_HEAP_SUM 0x0001 +#define DEBUG_HEAP_ENTRY 0x0002 +#define DEBUG_HEAP_ALL 0x0003 + +#ifdef HEAP_CHECK_ENABLE +#define HEAP_CHECK() chk_hp (0, (ST_CHAR *) __FILE__, __LINE__) +#else +#define HEAP_CHECK() +#endif + +ST_RET msoft_heap_check (ST_INT16); +ST_RET chk_hp (ST_INT16 prt_mask,ST_CHAR *file,ST_INT line); + +/************************************************************************/ + +extern ST_VOID *m_bad_ptr_val; + +/* This variable used to enable MSOFT heap check calls on every alloc */ +/* and free call. Also sets the unused heap memory to 0x55's */ +extern ST_BOOLEAN m_heap_check_enable; + +/* This variable used to enable list validation and overwrite checking */ +/* on every alloc and free call. */ +extern ST_BOOLEAN m_check_list_enable; + +/* Set this = SD_FALSE to speed up the debug version. When SD_TRUE, it */ +/* enables searching the memory list for the element before accessing */ +/* the memory during chk_realloc and chk_free calls */ +extern ST_BOOLEAN m_find_node_enable; + +/* This variable will cause chk_realloc to not realloc when the new */ +/* size is smaller than the old size */ +extern ST_BOOLEAN m_no_realloc_smaller; + +/* Dump memory table whenever high water mark is advanced */ +extern ST_BOOLEAN m_auto_hw_log; + +extern ST_CHAR *m_pad_string; +extern ST_INT m_num_pad_bytes; + +extern ST_BOOLEAN m_fill_en; +extern ST_UCHAR m_fill_byte; + +extern ST_BOOLEAN m_mem_debug; + +extern ST_BOOLEAN m_mem_crt_debug; + +/* This function pointer can be set to select a function to be called */ +/* in case of memory error. */ + +extern ST_VOID (*mem_chk_err)(ST_VOID); + +/* Read only */ +extern ST_UINT m_mem_overhead; + + +/************************************************************************/ +/************************************************************************/ +#ifdef __cplusplus +} +#endif + + + +#ifdef __cplusplus +/************************************************************************/ +/* deal with new and delete */ +/************************************************************************/ +#if defined (DEBUG_SISCO) && defined (DEBUG_NEW_SISCO) + +#include + +void * operator new(size_t nSize) throw (std::bad_alloc); +void * operator new(size_t nSize, const char *fileName, const int lineNum) throw (std::bad_alloc); +void * operator new(size_t nSize, const std::nothrow_t&) throw (); +void * operator new[](size_t nSize) throw (std::bad_alloc); +void * operator new[](size_t nSize, const char *fileName, const int lineNum) throw (std::bad_alloc); +void * operator new[](size_t nSize, const std::nothrow_t&) throw (); +void operator delete(void *p) throw (); +void operator delete(void *p, const char *fileName, const int lineNum) throw (); +void operator delete[](void *p) throw (); +void operator delete[](void *p, const char *fileName, const int lineNum) throw (); + +#ifndef MEM_CHK +#define new new(thisFileName, __LINE__) +#endif + +#endif + +#if defined (DEBUG_SISCO) && defined (DEBUG_NEW_MFC) + +#include + +#if !defined (__AFX_H__) + +#include + +#define THIS_FILE __FILE__ + +void* __cdecl operator new(size_t nSize, LPCSTR lpszFileName, int nLine); +#define DEBUG_NEW new(THIS_FILE, __LINE__) +void __cdecl operator delete(void* p, LPCSTR lpszFileName, int nLine); + +void * __cdecl operator new[](size_t); +void* __cdecl operator new[](size_t nSize, LPCSTR lpszFileName, int nLine); +void __cdecl operator delete[](void* p, LPCSTR lpszFileName, int nLine); +void __cdecl operator delete[](void *); + +#endif /* AFX */ + +#endif /* DEBUG_NEW_MFC */ + +#endif /* __cplusplus */ + + +#endif /* mem_chk.h already included */ diff --git a/mmslib/inc/memlog.h b/mmslib/inc/memlog.h new file mode 100644 index 0000000..ecdb3a3 --- /dev/null +++ b/mmslib/inc/memlog.h @@ -0,0 +1,201 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986, 1987, 1988, 1989, 1990, All Rights Reserved */ +/* */ +/* MODULE NAME : memlog.h */ +/* PRODUCT(S) : General Use */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the declarations of the dynamic memory */ +/* handling functions. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/13/02 JRB 08 MEMLOG_PAUSE*, MEMLOG_LF macros do nothing. */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 10/08/98 MDE 06 Migrated to updated SLOG interface */ +/* 04/17/96 JRB 05 Del #define THISFILE thisFileName. */ +/* 04/17/96 JRB 04 Del mem_sLogCtrl. Use new sLogCtrl in slog.c */ +/* 04/01/94 MDE 03 Removed THISFILE defines, changed THISFILE */ +/* to thisFileName */ +/* 03/29/94 DSF 02 Corrected definition for THISFILE */ +/* 12/10/93 DSF 01 Added MEMLOG_CHERR macro */ +/************************************************************************/ + +#ifndef MEMLOG_INCLUDED +#define MEMLOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "slog.h" + +/************************************************************************/ +/************************************************************************/ + +extern SD_CONST ST_CHAR *SD_CONST _mem_log_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mem_log_calloc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mem_log_malloc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mem_log_realloc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mem_log_free_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mem_log_nerr_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mem_log_dump_logstr; + + +#define MEMLOG_LF() + +#define MEMLOG_CALLSTACK(a) slogCallStack (sLogCtrl,a); + +#define MEMLOG_PAUSE(msg) +#define MEMLOG_PAUSEERR(msg) + +#define MEMLOG_MALLOC2(a,b,c) {\ + if (chk_debug_en & MEM_LOG_MALLOC)\ + _slog (sLogCtrl,_mem_log_malloc_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define MEMLOG_CMALLOC1(a,b) {\ + if (chk_debug_en & MEM_LOG_MALLOC)\ + _slogc (sLogCtrl,a,b);\ + } +#define MEMLOG_CMALLOC2(a,b,c) {\ + if (chk_debug_en & MEM_LOG_MALLOC)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define MEMLOG_CMALLOC3(a,b,c,d) {\ + if (chk_debug_en & MEM_LOG_MALLOC)\ + _slogc (sLogCtrl,a,b,c,d);\ + } + +#define MEMLOG_CALLOC3(a,b,c,d) {\ + if (chk_debug_en & MEM_LOG_CALLOC)\ + _slog (sLogCtrl,_mem_log_calloc_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define MEMLOG_CCALLOC1(a,b) {\ + if (chk_debug_en & MEM_LOG_CALLOC)\ + _slogc (sLogCtrl,a,b);\ + } +#define MEMLOG_CCALLOC2(a,b,c) {\ + if (chk_debug_en & MEM_LOG_CALLOC)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define MEMLOG_CCALLOC3(a,b,c,d) {\ + if (chk_debug_en & MEM_LOG_CALLOC)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define MEMLOG_REALLOC3(a,b,c,d) {\ + if (chk_debug_en & MEM_LOG_REALLOC)\ + _slog (sLogCtrl,_mem_log_realloc_logstr,\ + thisFileName,__LINE__,a,b,c,d);\ + } +#define MEMLOG_CREALLOC1(a,b) {\ + if (chk_debug_en & MEM_LOG_REALLOC)\ + _slogc (sLogCtrl,a,b);\ + } +#define MEMLOG_CREALLOC2(a,b,c) {\ + if (chk_debug_en & MEM_LOG_REALLOC)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define MEMLOG_CREALLOC3(a,b,c,d) {\ + if (chk_debug_en & MEM_LOG_REALLOC)\ + _slogc (sLogCtrl,a,b,c,d);\ + } + +#define MEMLOG_FREE1(a,b) {\ + if (chk_debug_en & MEM_LOG_FREE)\ + _slog (sLogCtrl,_mem_log_free_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define MEMLOG_CFREE2(a,b,c) {\ + if (chk_debug_en & MEM_LOG_FREE)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define MEMLOG_CFREE3(a,b,c,d) {\ + if (chk_debug_en & MEM_LOG_FREE)\ + _slogc (sLogCtrl,a,b,c,d);\ + } + +#define MEMLOG_ERR0(a) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slog (sLogCtrl,_mem_log_err_logstr,\ + thisFileName,__LINE__,a);\ + } +#define MEMLOG_ERR1(a,b) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slog (sLogCtrl,_mem_log_err_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define MEMLOG_ERR2(a,b,c) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slog (sLogCtrl,_mem_log_err_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define MEMLOG_CERR0(a) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slogc (sLogCtrl,a);\ + } +#define MEMLOG_CERR1(a,b) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slogc (sLogCtrl,a,b);\ + } +#define MEMLOG_CERR2(a,b,c) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define MEMLOG_CERR3(a,b,c,d) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c,d);\ + } +#define MEMLOG_CERR5(a,b,c,d,e,f) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c,d,e,f);\ + } +#define MEMLOG_CERR6(a,b,c,d,e,f,g) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slogc (sLogCtrl,a,b,c,d,e,f,g);\ + } +#define MEMLOG_CHERR(a,b) {\ + if (chk_debug_en & MEM_LOG_ERR)\ + _slogHex (sLogCtrl,a,b);\ + } + +#define MEMLOG_DUMP0(a) {\ + _slog (sLogCtrl,_mem_log_dump_logstr,\ + thisFileName,__LINE__,a);\ + } +#define MEMLOG_DUMP1(a,b) {\ + _slog (sLogCtrl,_mem_log_dump_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define MEMLOG_CDUMP4(a,b,c,d,e) {\ + _slogc (sLogCtrl,a,b,c,d,e);\ + } +#define MEMLOG_CDUMP5(a,b,c,d,e,f) {\ + _slogc (sLogCtrl,a,b,c,d,e,f);\ + } +#define MEMLOG_CDUMP0(a) {\ + _slogc (sLogCtrl,a);\ + } +#define MEMLOG_CDUMP1(a,b) {\ + _slogc (sLogCtrl,a,b);\ + } +#define MEMLOG_CDUMP2(a,b,c) {\ + _slogc (sLogCtrl,a,b,c);\ + } +#define MEMLOG_CDUMP3(a,b,c,d) {\ + _slogc (sLogCtrl,a,b,c,d);\ + } + + +#ifdef __cplusplus +} +#endif + + +#endif /* memlog.h already included */ + diff --git a/mmslib/inc/mloguser.h b/mmslib/inc/mloguser.h new file mode 100644 index 0000000..eb55381 --- /dev/null +++ b/mmslib/inc/mloguser.h @@ -0,0 +1,297 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2008 All Rights Reserved */ +/* */ +/* MODULE NAME : mloguser.h */ +/* PRODUCT(S) : MMS-EASE 250-001 */ +/* */ +/* MODULE DESCRIPTION : */ +/* ANSI Protytped Logging Functions for MMS-EASE user code. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/01/08 JRB 16 Del commented code. */ +/* 10/30/06 JRB 15 Add mlog_arb_log_ctrl extern. */ +/* 03/23/05 JRB 14 Del unused m_log_mllp* & m_log_llp* protos. */ +/* 06/10/04 EJV 13 Removed suicacse.h - lber.h conflict on AIX. */ +/* 04/05/02 MDE 12 Cleaned up MMS Lite use of MLOG */ +/* 11/04/98 DSF 11 Added m_get_mms_rej_text () */ +/* 08/13/98 MDE 10 Added m_log_tdl */ +/* 07/16/98 MDE 09 Added ml_log_dec_rslt declaration */ +/* 06/15/98 MDE 08 Changes to allow compile under C++ */ +/* 03/20/98 JRB 07 Del mmsop_en.h. Only user code needs it now. */ +/* 09/29/97 MDE 06 Don't need mlog_en.h */ +/* 08/15/97 MDE 05 BTOD handling changes */ +/* 08/14/97 MDE 04 Removed unused 'm_log_info_print' */ +/* 08/04/97 MDE 03 Added 'no log' function declarations */ +/* 08/04/97 MDE 02 Changes towards breakup */ +/* 06/09/97 MDE 01 Removed several mmv_v???.h includes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MLOGUSER_INCLUDED +#define MLOGUSER_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mmslog.h" +#include "mms_pcon.h" +#include "mms_pdom.h" +#include "mms_pevn.h" +#include "mms_pfil.h" +#include "mms_pjou.h" +#include "mms_pocs.h" +#include "mms_pprg.h" +#include "mms_psem.h" +#include "mms_pvar.h" +#include "mms_pvmd.h" +#include "mms_vvar.h" +#if defined(MMS_LITE) +#include "mmsintr2.h" +#endif +#include "sx_arb.h" /* needed for SXD_ARB_DATA_CTRL */ + + +/************************************************************************/ +/************************************************************************/ + +extern ST_VOID (*m_req_log_fun_tbl [MAX_MMSOP_DIS+1]) (ST_VOID *v); +extern ST_VOID (*m_resp_log_fun_tbl [MAX_MMSOP_DIS+1]) (ST_VOID *v); + +/* Request / Response Data Logging Functions */ +ST_VOID m_log_ackevnot_req (ACKEVNOT_REQ_INFO *info); +ST_VOID m_log_altecm_req (ALTECM_REQ_INFO *info); +ST_VOID m_log_altee_resp (ALTEE_RESP_INFO *info); +ST_VOID m_log_altee_req (ALTEE_REQ_INFO *info); +ST_VOID m_log_crepi_req (CREPI_REQ_INFO *info); +ST_VOID m_log_cancel_req (ST_VOID); +ST_VOID m_log_cancel_resp (ST_VOID); +ST_VOID m_log_defea_req (DEFEA_REQ_INFO *info); +ST_VOID m_log_defec_req (DEFEC_REQ_INFO *info); +ST_VOID m_log_defee_req (DEFEE_REQ_INFO *info); +ST_VOID m_log_defscat_req (DEFSCAT_REQ_INFO *info); +ST_VOID m_log_defsem_req (DEFSEM_REQ_INFO *info); +ST_VOID m_log_deftype_req (DEFTYPE_REQ_INFO *info); +ST_VOID m_log_defvar_req (DEFVAR_REQ_INFO *info); +ST_VOID m_log_defvlist_req (DEFVLIST_REQ_INFO *info); +ST_VOID m_log_deldom_req (DELDOM_REQ_INFO *info); +ST_VOID m_log_delea_resp (DELEA_RESP_INFO *info); +ST_VOID m_log_delea_req (DELEA_REQ_INFO *info); +ST_VOID m_log_delec_req (DELEC_REQ_INFO *info); +ST_VOID m_log_delec_resp (DELEC_RESP_INFO *info); +ST_VOID m_log_delee_resp (DELEE_RESP_INFO *info); +ST_VOID m_log_delee_req (DELEE_REQ_INFO *info); +ST_VOID m_log_delpi_req (DELPI_REQ_INFO *info); +ST_VOID m_log_delsem_req (DELSEM_REQ_INFO *info); +ST_VOID m_log_deltype_resp (DELTYPE_RESP_INFO *info); +ST_VOID m_log_deltype_req (DELTYPE_REQ_INFO *info); +ST_VOID m_log_delvar_resp (DELVAR_RESP_INFO *info); +ST_VOID m_log_delvar_req (DELVAR_REQ_INFO *info); +ST_VOID m_log_delvlist_resp (DELVLIST_RESP_INFO *info); +ST_VOID m_log_delvlist_req (DELVLIST_REQ_INFO *info); +ST_VOID m_log_download_resp (DOWNLOAD_RESP_INFO *info); +ST_VOID m_log_download_req (DOWNLOAD_REQ_INFO *info); +ST_VOID m_log_evnot_req (EVNOT_REQ_INFO *info); +ST_VOID m_log_fclose_req (FCLOSE_REQ_INFO *info); +ST_VOID m_log_fdelete_req (FDELETE_REQ_INFO *info); +ST_VOID m_log_fdir_resp (FDIR_RESP_INFO *info); +ST_VOID m_log_fdir_req (FDIR_REQ_INFO *info); +ST_VOID m_log_fopen_resp (FOPEN_RESP_INFO *info); +ST_VOID m_log_fopen_req (FOPEN_REQ_INFO *info); +ST_VOID m_log_fread_resp (FREAD_RESP_INFO *info); +ST_VOID m_log_fread_req (FREAD_REQ_INFO *info); +ST_VOID m_log_frename_req (FRENAME_REQ_INFO *info); +ST_VOID m_log_getaes_resp (GETAES_RESP_INFO *info); +ST_VOID m_log_getaes_req (GETAES_REQ_INFO *info); +ST_VOID m_log_getas_resp (GETAS_RESP_INFO *info); +ST_VOID m_log_getas_req (GETAS_REQ_INFO *info); +ST_VOID m_log_getcl_resp (GETCL_RESP_INFO *info); +ST_VOID m_log_getcl_req (GETCL_REQ_INFO *info); +ST_VOID m_log_getdom_resp (GETDOM_RESP_INFO *info); +ST_VOID m_log_getdom_req (GETDOM_REQ_INFO *info); +ST_VOID m_log_geteaa_resp (GETEAA_RESP_INFO *info); +ST_VOID m_log_geteaa_req (GETEAA_REQ_INFO *info); +ST_VOID m_log_geteca_resp (GETECA_RESP_INFO *info); +ST_VOID m_log_geteca_req (GETECA_REQ_INFO *info); +ST_VOID m_log_geteea_resp (GETEEA_RESP_INFO *info); +ST_VOID m_log_geteea_req (GETEEA_REQ_INFO *info); +ST_VOID m_log_getpi_resp (GETPI_RESP_INFO *info); +ST_VOID m_log_getpi_req (GETPI_REQ_INFO *info); +ST_VOID m_log_getscat_resp (GETSCAT_RESP_INFO *info); +ST_VOID m_log_getscat_req (GETSCAT_REQ_INFO *info); +ST_VOID m_log_gettype_resp (GETTYPE_RESP_INFO *info); +ST_VOID m_log_gettype_req (GETTYPE_REQ_INFO *info); +ST_VOID m_log_getvar_resp (GETVAR_RESP_INFO *info); +ST_VOID m_log_getvar_req (GETVAR_REQ_INFO *info); +ST_VOID m_log_getvlist_resp (GETVLIST_RESP_INFO *info); +ST_VOID m_log_getvlist_req (GETVLIST_REQ_INFO *info); +ST_VOID m_log_ident_resp (IDENT_RESP_INFO *info); +ST_VOID m_log_info_req (INFO_REQ_INFO *info); +ST_VOID m_log_initdown_req (INITDOWN_REQ_INFO *info); +ST_VOID m_log_initupl_resp (INITUPL_RESP_INFO *info); +ST_VOID m_log_initupl_req (INITUPL_REQ_INFO *info); +ST_VOID m_log_init_info (INIT_INFO *info); +ST_VOID m_log_input_resp (INPUT_RESP_INFO *info); +ST_VOID m_log_input_req (INPUT_REQ_INFO *info); +ST_VOID m_log_jcreate_req (JCREATE_REQ_INFO *info); +ST_VOID m_log_jdelete_req (JDELETE_REQ_INFO *info); +ST_VOID m_log_jinit_resp (JINIT_RESP_INFO *info); +ST_VOID m_log_jinit_req (JINIT_REQ_INFO *info); +ST_VOID m_log_jread_resp (JREAD_RESP_INFO *info); +ST_VOID m_log_jread_req (JREAD_REQ_INFO *info); +ST_VOID m_log_jstat_resp (JSTAT_RESP_INFO *info); +ST_VOID m_log_jstat_req (JSTAT_REQ_INFO *info); +ST_VOID m_log_jwrite_req (JWRITE_REQ_INFO *info); +ST_VOID m_log_kill_req (KILL_REQ_INFO *info); +ST_VOID m_log_loaddom_req (LOADDOM_REQ_INFO *info); +ST_VOID m_log_namelist_resp (NAMELIST_RESP_INFO *info); +ST_VOID m_log_namelist_req (NAMELIST_REQ_INFO *info); +ST_VOID m_log_obtfile_req (OBTFILE_REQ_INFO *info); +ST_VOID m_log_output_req (OUTPUT_REQ_INFO *info); +ST_VOID m_log_rddwn_req (RDDWN_REQ_INFO *info); +ST_VOID m_log_rdupl_req (RDUPL_REQ_INFO *info); +ST_VOID m_log_read_resp (READ_RESP_INFO *info); +ST_VOID m_log_read_req (READ_REQ_INFO *info); +ST_VOID m_log_relctrl_req (RELCTRL_REQ_INFO *info); +ST_VOID m_log_rename_req (RENAME_REQ_INFO *info); +ST_VOID m_log_repeas_resp (REPEAS_RESP_INFO *info); +ST_VOID m_log_repeas_req (REPEAS_REQ_INFO *info); +ST_VOID m_log_repecs_resp (REPECS_RESP_INFO *info); +ST_VOID m_log_repecs_req (REPECS_REQ_INFO *info); +ST_VOID m_log_repees_resp (REPEES_RESP_INFO *info); +ST_VOID m_log_repees_req (REPEES_REQ_INFO *info); +ST_VOID m_log_reset_req (RESET_REQ_INFO *info); +ST_VOID m_log_resume_req (RESUME_REQ_INFO *info); +ST_VOID m_log_rsentry_resp (RSENTRY_RESP_INFO *info); +ST_VOID m_log_rsentry_req (RSENTRY_REQ_INFO *info); +ST_VOID m_log_rspool_resp (RSPOOL_RESP_INFO *info); +ST_VOID m_log_rspool_req (RSPOOL_REQ_INFO *info); +ST_VOID m_log_rsstat_resp (RSSTAT_RESP_INFO *info); +ST_VOID m_log_rsstat_req (RSSTAT_REQ_INFO *info); +ST_VOID m_log_start_req (START_REQ_INFO *info); +ST_VOID m_log_status_resp (STATUS_RESP_INFO *info); +ST_VOID m_log_status_req (STATUS_REQ_INFO *info); +ST_VOID m_log_stop_req (STOP_REQ_INFO *info); +ST_VOID m_log_storedom_req (STOREDOM_REQ_INFO *info); +ST_VOID m_log_takectrl_resp (TAKECTRL_RESP_INFO *info); +ST_VOID m_log_takectrl_req (TAKECTRL_REQ_INFO *info); +ST_VOID m_log_termdown_req (TERMDOWN_REQ_INFO *info); +ST_VOID m_log_termupl_req (TERMUPL_REQ_INFO *info); +ST_VOID m_log_trige_req (TRIGE_REQ_INFO *info); +ST_VOID m_log_upload_resp (UPLOAD_RESP_INFO *info); +ST_VOID m_log_upload_req (UPLOAD_REQ_INFO *info); +ST_VOID m_log_ustatus_req (USTATUS_REQ_INFO *info); +ST_VOID m_log_write_resp (WRITE_RESP_INFO *info); +ST_VOID m_log_write_req (WRITE_REQ_INFO *info); + +/* common component logging */ +ST_VOID m_log_app_ref (APP_REF *info); +ST_VOID m_log_asn1_app_ref (ST_UCHAR *buf_ptr, ST_INT buf_len); +ST_VOID m_log_modifier (MODIFIER *info); +ST_VOID m_log_tdl (ST_UCHAR *asn1, ST_INT asn1_len); + +ST_VOID m_log_error_info (ERR_INFO *err_ptr); +#if !defined(MMS_LITE) +ST_VOID m_log_err_info (MMSREQ_PEND *req_ptr); +#endif + +ST_VOID m_no_log_resp (ST_VOID *resp); +ST_VOID m_no_log_req (ST_VOID *req); + +/************************************************************************/ + +ST_VOID m_get_mms_err_text (ST_INT eclass, ST_INT code, + ST_CHAR *dest, ST_INT dest_len); + +ST_VOID m_get_mms_rej_text (ST_INT rclass, ST_INT code, + ST_CHAR *dest, ST_INT dest_len); + +ST_VOID m_log_reject_info (REJECT_RESP_INFO *rej_ptr); + +ST_VOID m_log_evtime (EVENT_TIME *info); +ST_VOID m_log_evt_tod (MMS_BTOD *info); +ST_VOID m_log_external (EXTERN_INFO *info); + +ST_VOID m_log_objname (OBJECT_NAME *info); +ST_VOID m_log_pi_state (ST_INT state); +ST_VOID m_log_address (VAR_ACC_ADDR *info); +ST_VOID m_log_var_list (VARIABLE_LIST *vl_ptr, ST_INT num_of_vars); +ST_VOID m_log_var_spec (VARIABLE_SPEC *info); +ST_VOID m_log_vaspec (VAR_ACC_SPEC *info); +ST_VOID m_log_data (ST_INT asn1_data_len, ST_UCHAR *asn1_data); + +/************************************************************************/ +/************************************************************************/ +#if defined(MMS_LITE) +/************************************************************************/ + +ST_RET ml_log_dec_rslt (MMSDEC_INFO *rslt); + +ST_VOID _ml_log_req_info (ST_INT invokeId, ST_INT op, ST_VOID *info); +ST_VOID _ml_log_ind_info (ST_INT invokeId, ST_INT op, ST_VOID *info); +ST_VOID _ml_log_resp_info (ST_INT invokeId, ST_INT op, ST_VOID *info); +ST_VOID _ml_log_conf_info (ST_INT invokeId, ST_INT op, ST_VOID *info); +ST_VOID _ml_log_unsol_req_info (ST_INT op, ST_VOID *info); +ST_VOID _ml_log_unsol_ind_info (ST_INT op, ST_VOID *info); +ST_VOID _ml_log_error_resp (ST_INT invokeId, ST_VOID *info); +ST_VOID _ml_log_error_conf (ST_INT invokeId, ST_VOID *info); +ST_VOID _ml_log_reject_send (ST_VOID *info); +ST_VOID _ml_log_reject_recv (ST_VOID *info); + + +/* MLOG integration */ +extern ST_VOID (*ml_log_req_info_fun) (ST_INT invokeId, ST_INT op, ST_VOID *info); +extern ST_VOID (*ml_log_ind_info_fun) (ST_INT invokeId, ST_INT op, ST_VOID *info); + +extern ST_VOID (*ml_log_resp_info_fun) (ST_INT invokeId, ST_INT op, ST_VOID *info); +extern ST_VOID (*ml_log_conf_info_fun) (ST_INT invokeId, ST_INT op, ST_VOID *info); + +extern ST_VOID (*ml_log_unsol_req_info_fun) (ST_INT op, ST_VOID *info); +extern ST_VOID (*ml_log_unsol_ind_info_fun) (ST_INT op, ST_VOID *info); + +extern ST_VOID (*ml_log_error_conf_fun) (ST_INT invokeId, ST_VOID *info); +extern ST_VOID (*ml_log_error_resp_fun) (ST_INT invokeId, ST_VOID *info); + +extern ST_VOID (*ml_log_reject_send_fun) (ST_VOID *info); +extern ST_VOID (*ml_log_reject_recv_fun) (ST_VOID *info); + +ST_VOID ml_mlog_install (ST_VOID); + +/************************************************************************/ +#endif /* MMS_LITE */ +/************************************************************************/ + +/************************************************************************/ +#if !defined(MMS_LITE) +/************************************************************************/ +ST_VOID m_log_ureq_info (ST_INT chan, ST_INT op, ST_VOID *info); +ST_VOID m_log_req_info (MMSREQ_PEND *req, ST_VOID *info); +ST_VOID m_log_resp_info (MMSREQ_IND *ind, ST_VOID *info); +ST_VOID m_log_ind_info (MMSREQ_IND *ind); +ST_VOID m_log_conf_info (MMSREQ_PEND *conf); +ST_VOID m_log_error_resp (MMSREQ_IND *ind, ST_INT16 eclass, ST_INT16 code); +ST_RET m_mlog_install (ST_VOID); +#endif + +/************************************************************************/ +/* Global variables. */ +/************************************************************************/ +extern SXD_ARB_DATA_CTRL mlog_arb_log_ctrl; + +/************************************************************************/ +#ifdef __cplusplus +} +#endif +/************************************************************************/ + + +#endif /* MLOGUSER_INCLUDED */ + diff --git a/mmslib/inc/mms_def2.h b/mmslib/inc/mms_def2.h new file mode 100644 index 0000000..c29ab15 --- /dev/null +++ b/mmslib/inc/mms_def2.h @@ -0,0 +1,308 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_def2.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains miscellaneous definitions and variables. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/12/07 MDE 11 Added MMSOP_RD_USR_HANDLED, etc.. */ +/* 04/24/03 JRB 10 Increase MAX_IDENT_LEN from 32 to 64. */ +/* 07/09/02 MDE 09 Fixed up opcode defines */ +/* 02/24/00 DSF 08 Bumped up MAX_FILES_OPEN to 100 */ +/* 10/06/99 GLB 07 Added file Rename and Obtain File */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 04/14/98 JRB 05 Del MPARAM* defs. Still needed in mmsop_en.h */ +/* 04/03/98 JRB 04 Add check for obsolete version of mmsop_en.h */ +/* 03/20/98 JRB 03 Move defs from "mmsop_en.h" to here. */ +/* 08/15/97 MDE 02 Added xxx_DATA_SUPPORT defines, cleanup */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_DEF2_INCLUDED +#define MMS_DEF2_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (REQ_RESP_DIS) || defined (MAX_MMS_OPCODE) +#error May have obsolete version of "mmsop_en.h". See Release Notes. +#endif + +/************************************************************************/ +/************************************************************************/ +/* define the operation enable switches used by "mmsop_en.h" */ +/************************************************************************/ +#define REQ_RESP_DIS 0x00 /* no support for req or resp */ +#define REQ_EN 0x01 /* support for request */ +#define RESP_EN 0x02 /* support for response */ +#define REQ_RESP_EN 0x03 /* support for resp and req */ + +/************************************************************************/ +/************************************************************************/ +/* The following character array is used to check if a MMS operation is */ +/* to be supported as requestor and/or responder, and whether to expect */ +/* a constructor or primitive after the invoke ID. The operation opcode */ +/* is used as an index into the table. */ +/************************************************************************/ + +#define MAX_MMS_OPCODE 77 /* highest MMS opcode */ +#define MAX_MMSOP_DIS 85 /* highest mmsop_en[] entry */ + +extern SD_CONST ST_UCHAR mmsop_en [MAX_MMSOP_DIS+1]; + +/************************************************************************/ +/************************************************************************/ +/* The following array is used to print the opcode description. The */ +/* operation opcode is used as an index into the table. */ +/************************************************************************/ + +extern ST_CHAR *mms_op_string[106]; +extern ST_INT m_num_mms_op_string; + +/************************************************************************/ +/************************************************************************/ +/* Define the MMS operation opcodes */ +/************************************************************************/ +#define MMSOP_STATUS 0 /* status */ +#define MMSOP_GET_NAMLIST 1 /* get name list */ +#define MMSOP_IDENTIFY 2 /* identify */ +#define MMSOP_RENAME 3 /* rename */ +#define MMSOP_READ 4 /* read */ +#define MMSOP_WRITE 5 /* write */ +#define MMSOP_GET_VAR 6 /* get variable name definition */ +#define MMSOP_DEF_VAR 7 /* define variable name */ +#define MMSOP_DEF_SCAT 8 /* define scattered access */ +#define MMSOP_GET_SCAT 9 /* get scattered access attributes */ +#define MMSOP_DEL_VAR 10 /* delete variable name definition */ +#define MMSOP_DEF_VLIST 11 /* define named variable list */ +#define MMSOP_GET_VLIST 12 /* get named variable list */ +#define MMSOP_DEL_VLIST 13 /* delete named variable list */ +#define MMSOP_DEF_TYPE 14 /* define type name */ +#define MMSOP_GET_TYPE 15 /* get type name definition */ +#define MMSOP_DEL_TYPE 16 /* delete type name */ + +#define MMSOP_INPUT 17 /* input */ +#define MMSOP_OUTPUT 18 /* output */ + +#define MMSOP_TAKE_CONTROL 19 /* take control */ +#define MMSOP_REL_CONTROL 20 /* relinquish control */ +#define MMSOP_DEFINE_SEM 21 /* define semaphore */ +#define MMSOP_DELETE_SEM 22 /* delete semaphore */ +#define MMSOP_REP_SEMSTAT 23 /* report semaphore status */ +#define MMSOP_REP_SEMPOOL 24 /* report semaphore pool status */ +#define MMSOP_REP_SEMENTRY 25 /* report semaphore entry status */ + +#define MMSOP_INIT_DOWNLOAD 26 /* initiate download sequence */ +#define MMSOP_DOWN_LOAD 27 /* download segment */ +#define MMSOP_TERM_DOWNLOAD 28 /* terminate download sequence */ +#define MMSOP_INIT_UPLOAD 29 /* initiate upload sequence */ +#define MMSOP_UP_LOAD 30 /* upload segment */ +#define MMSOP_TERM_UPLOAD 31 /* terminate upload sequence */ +#define MMSOP_REQ_DOM_DOWN 32 /* request domain download */ +#define MMSOP_REQ_DOM_UPL 33 /* request domain upload */ +#define MMSOP_LOAD_DOMAIN 34 /* load domain content */ +#define MMSOP_STORE_DOMAIN 35 /* store domain content */ +#define MMSOP_DELETE_DOMAIN 36 /* delete domain */ +#define MMSOP_GET_DOM_ATTR 37 /* get domain attribute */ + +#define MMSOP_CREATE_PI 38 /* create program invocation */ +#define MMSOP_DELETE_PI 39 /* delete program invocation */ +#define MMSOP_START 40 /* start */ +#define MMSOP_STOP 41 /* stop */ +#define MMSOP_RESUME 42 /* resume */ +#define MMSOP_RESET 43 /* reset */ +#define MMSOP_KILL 44 /* kill */ +#define MMSOP_GET_PI_ATTR 45 /* get program invocation attribute */ + +#define MMSOP_OBTAIN_FILE 46 /* obtain file */ + +#define MMSOP_DEF_EC 47 /* define event condition */ +#define MMSOP_DEL_EC 48 /* delete event condition */ +#define MMSOP_GET_EC_ATTR 49 /* get event condition attributes */ +#define MMSOP_REP_EC_STAT 50 /* report event condition status */ +#define MMSOP_ALT_EC_MON 51 /* alter event condition monitoring */ +#define MMSOP_TRIGGER_EV 52 /* trigger event */ +#define MMSOP_DEF_EA 53 /* define event action status */ +#define MMSOP_DEL_EA 54 /* delete event action */ +#define MMSOP_GET_EA_ATTR 55 /* get event action attributes */ +#define MMSOP_REP_EA_STAT 56 /* report event action status */ +#define MMSOP_DEF_EE 57 /* define event enrollment */ +#define MMSOP_DEL_EE 58 /* delete event enrollment */ +#define MMSOP_ALT_EE 59 /* alter event enrollment */ +#define MMSOP_REP_EE_STAT 60 /* report event enrollment status */ +#define MMSOP_GET_EE_ATTR 61 /* get event enrollment attributes */ +#define MMSOP_ACK_EVENT_NOT 62 /* acknowledge event notification */ +#define MMSOP_GET_ALARM_SUM 63 /* get alarm summary */ +#define MMSOP_GET_ALARM_ESUM 64 /* get alarm enrollment summary */ + +#define MMSOP_READ_JOURNAL 65 /* read journal */ +#define MMSOP_WRITE_JOURNAL 66 /* write journal */ +#define MMSOP_INIT_JOURNAL 67 /* initialize journal */ +#define MMSOP_STAT_JOURNAL 68 /* report journal status */ +#define MMSOP_CREATE_JOURNAL 69 /* create journal */ +#define MMSOP_DELETE_JOURNAL 70 /* delete journal */ + +#define MMSOP_GET_CAP_LIST 71 /* get capability list */ + +#define MMSOP_FILE_OPEN 72 /* file open */ +#define MMSOP_FILE_READ 73 /* file read */ +#define MMSOP_FILE_CLOSE 74 /* file close */ +#define MMSOP_FILE_RENAME 75 /* file rename */ +#define MMSOP_FILE_DELETE 76 /* file delete */ +#define MMSOP_FILE_DIR 77 /* file directory */ + + +/************************************************************************/ +/* The opcodes below are reserved for the unconfirmed services and are */ +/* NOT used on the wire. */ +/************************************************************************/ +#define MMSOP_USTATUS 78 /* unsolicited status, ucs 1 */ +#define MMSOP_INFO_RPT 79 /* information report, ucs 0 */ +#define MMSOP_EVENT_NOT 80 /* unsolicited status, ucs 2 */ + + +/************************************************************************/ +/* These are not really opcodes at all, but simply represent the bit */ +/* positions in the services supported bitstring */ + +#define _MMSOP_ATTACH_TO_EC 81 /* Attach to event condition */ +#define _MMSOP_ATTACH_TO_SEM 82 /* Attach to semaphore */ + +/************************************************************************/ +/* These opcodes are reserved for Initiate, Conclude, etc. and are */ +/* NOT used on the wire, since these operations do not take op codes. */ +/************************************************************************/ + +#define MMSOP_CONCLUDE 83 /* conclude */ +#define MMSOP_CANCEL 84 /* cancel */ + + +/************************************************************************/ +/* MVLU Internal Use */ +#define MMSOP_MVLU_RPT_VA 200 +#define MMSOP_MVLU_GOOSE_UPDATE 201 +#define MMSOP_RD_USR_HANDLED 202 + +/************************************************************************/ +/* The opcodes below are NOT used on the wire, only for completed */ +/* 'Macro' function complete flags. */ +/************************************************************************/ +#define MMSOP_INITIATE 85 /* initiate operation */ + +#define MMSOP_NAMED_READ 90 /* Named Read */ +#define MMSOP_NAMED_WRITE 91 /* Named Write */ +#define MMSOP_REM_FILE_OPEN 93 /* Remote File Open */ +#define MMSOP_REM_FILE_READ 94 /* Remote File Read */ +#define MMSOP_REM_FILE_CLOSE 95 /* Remote File Close */ +#define MMSOP_INIT_CONN 96 /* Initiate */ +#define MMSOP_REM_FILE_COPY 98 /* Remote file copy */ +#define MMSOP_MV_DOWNLOAD 99 /* VM Domain Download */ +#define MMSOP_MV_UPLOAD 100 /* VM Domain Upload */ +#define MMSOP_VM_VAR_READ 101 /* Var Read */ +#define MMSOP_VM_VAR_WRITE 102 /* Var Write */ + +/************************************************************************/ +/************************************************************************/ +/* Various MMS limitations, parameters, etc. */ +/************************************************************************/ + +#define SERVICE_RESP_SIZE 11 /* BYTE size of service resp array */ + +#define MAX_FILES_OPEN 100 /* maximum files open locally/remotely */ +#define MAX_FILE_NAME 255 /* maximum length of a file pathname */ +#define MAX_IDENT_LEN 64 /* length of an Identifier variable */ +#define MAX_AR_LEN 64 /* length of a AR name */ + +/************************************************************************/ +/************************************************************************/ +/* This structure is used to support modifier handling. */ +/************************************************************************/ + +struct list_of_mods + { + ST_BOOLEAN info_pres; /* must be set to get info encoded */ + ST_INT num_of_mods; /* tells how many mods in the list */ + struct modifier *mod_list_ptr;/* ptr to array of contiguous modifiers */ + }; +typedef struct list_of_mods LIST_OF_MODS; + +extern struct list_of_mods modifier_list; +extern ST_INT m_max_mods; + +/************************************************************************/ +/************************************************************************/ +/* COMPANION STANDARD HANDLING */ +/************************************************************************/ +/* This structure is used as a global input parameter to all MMS */ +/* requests and responses sent by the application. To send CS info, the */ +/* 'cs_pres' flag must be set SD_TRUE, the other components refer to the*/ +/* ASN.1 CS INFO to be sent. 'cs_pres' is reset after being used. */ +/************************************************************************/ + + +struct csi + { + ST_BOOLEAN cs_pres; /* SD_TRUE if CS info was received */ + ST_INT cs_len; /* length of ASN.1 */ + ST_UCHAR *cs_ptr; /* pointer to ASN.1 */ + }; +typedef struct csi CSI ; + +extern struct csi cs_send; /* SEND CS info structure */ + +/************************************************************************/ +/************************************************************************/ +/* These defines can be commented out to exclude support for some data */ +/* types if they are not required. */ + +#ifndef MMS_LITE +#define FLOAT_DATA_SUPPORT +#define TIME_DATA_SUPPORT +#define BTOD_DATA_SUPPORT +#else +#define FLOAT_DATA_SUPPORT +#define TIME_DATA_SUPPORT +#define BTOD_DATA_SUPPORT +#endif + +/************************************************************************/ +/************************************************************************/ +/* These defines are the values that the domain state attribute */ +/* named_dom_ctrl.state can take on. */ +/************************************************************************/ + +#define DOM_NON_EXISTENT 0 +#define DOM_LOADING 1 +#define DOM_READY 2 +#define DOM_IN_USE 3 +#define DOM_COMPLETE 4 +#define DOM_INCOMPLETE 5 + +#define DOM_D1 7 +#define DOM_D2 8 +#define DOM_D3 9 +#define DOM_D4 10 +#define DOM_D5 11 +#define DOM_D6 12 +#define DOM_D7 13 +#define DOM_D8 14 +#define DOM_D9 15 + +#ifdef __cplusplus +} +#endif + +#endif /* MMS_DEF2_INCLUDED */ + + diff --git a/mmslib/inc/mms_dfun.h b/mmslib/inc/mms_dfun.h new file mode 100644 index 0000000..b5c0a78 --- /dev/null +++ b/mmslib/inc/mms_dfun.h @@ -0,0 +1,212 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_dfun.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the function declarations required to interface */ +/* with the primitive level decode routines. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 01 Convert to use ASN1R. */ +/* Add mms_err_invoke_fun proto. */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_DFUN_INCLUDED +#define MMS_DFUN_INCLUDED + +#include "asn1r.h" /* need ASN1_DEC_CTXT */ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/************************************************************************/ +/* MMS service decode functions */ +/************************************************************************/ + +ST_VOID mms_reject (ASN1_DEC_CTXT *ac, ST_UINT16 id_code); +ST_VOID mms_err_invoke_fun (ASN1_DEC_CTXT *aCtx, ST_UINT16); +ST_VOID mms_status_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_status_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_status (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_ustatus_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_namelist_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_namelist_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_identify_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_identify_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rename_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_getcl_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_getcl_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_init_download_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_init_download_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_download_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_download_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_term_download_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_term_download_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_init_upload_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_init_upload_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_upload_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_upload_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_term_upload_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_term_upload_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rddwn_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rddwn_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rdupl_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rdupl_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_load_domain_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_load_domain_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_store_domain_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_store_domain_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delete_domain_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delete_domain_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_dom_attr_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_dom_attr_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_create_pi_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_create_pi_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delete_pi_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delete_pi_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_start_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_stop_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_stop_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_resume_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_resume_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_reset_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_reset_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_kill_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_kill_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_pi_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_pi_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_read_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_read_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_write_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_write_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_info_rpt_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_var_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_var_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_def_var_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_def_var_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_del_var_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_del_var_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_def_scat_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_scat_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_scat_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_def_vlist_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_vlist_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_vlist_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_del_vlist_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_del_vlist_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_type_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_get_type_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_def_type_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_def_type_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_del_type_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_del_type_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_takectrl_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_takectrl_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_relctrl_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_relctrl_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rsstat_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rsstat_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rspool_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rspool_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rsentry_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_rsentry_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_defsem_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_defsem_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delsem_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delsem_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_output_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_output_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_input_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_input_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_defec_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delec_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delec_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_geteca_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_geteca_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_repecs_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_repecs_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_altecm_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_trige_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_defea_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delea_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delea_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_geteaa_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_geteaa_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_repeas_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_repeas_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_defee_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delee_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_delee_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_altee_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_altee_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_repees_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_repees_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_geteea_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_geteea_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_evnot_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_ackevnot_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_ackevnot_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_getas_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_getas_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_getaes_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_getaes_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_jwrite_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jwrite_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jread_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jread_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jinit_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jinit_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jstat_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jstat_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jcreate_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_jdelete_req (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_obtain_file_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_obtain_file_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_open_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_open_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_read_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_read_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_close_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_close_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_rename_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_rename_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_delete_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_delete_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_dir_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_file_dir_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_conclude_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_conclude_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_cancel_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_cancel_rsp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_init_req (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_init_rsp (ASN1_DEC_CTXT *aCtx); + +ST_VOID mms_rsp_not_supp (ASN1_DEC_CTXT *aCtx); +ST_VOID mms_req_not_supp (ASN1_DEC_CTXT *aCtx); +ST_VOID _mms_null_pdu_dec (ASN1_DEC_CTXT *aCtx); + +#ifdef __cplusplus +} +#endif + +#endif /* MMS_DFUN_INCLUDED */ diff --git a/mmslib/inc/mms_err.h b/mmslib/inc/mms_err.h new file mode 100644 index 0000000..38f8bc8 --- /dev/null +++ b/mmslib/inc/mms_err.h @@ -0,0 +1,213 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_err.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains structure & function definitions used for */ +/* decoding and encoding an error response. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/03/06 CRM 03 Add MMS_ERRCLASS_* and MMS_ERRCODE_*. */ +/* 12/20/01 JRB 02 Convert to use ASN1R. */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_ERR_INCLUDED +#define MMS_ERR_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_mp.h" + +/************************************************************************/ +/* MMS Error Codes: */ +/************************************************************************/ + +#define MMS_ERRCODE_OTHER 0 /* same for all classes */ + +/* Defines for "VMD State" error class. */ +#define MMS_ERRCLASS_VMD_STATE 0 +#define MMS_ERRCODE_VMD_STATE_CONFLICT 1 +#define MMS_ERRCODE_VMD_OPERATIONAL_PROBLEM 2 +#define MMS_ERRCODE_DOMAIN_TRANSFER_PROBLEM 3 +#define MMS_ERRCODE_STATE_MACHINE_ID_INVALID 4 + +/* Defines for "Application Reference" error class.*/ +#define MMS_ERRCLASS_APP_REF 1 +#define MMS_ERRCODE_APP_UNREACHABLE 1 +#define MMS_ERRCODE_CONNECTION_LOST 2 +#define MMS_ERRCODE_APP_REF_INVALID 3 +#define MMS_ERRCODE_CONTEXT_UNSUPPORTED 4 + +/* Defines for "Definition" error class. */ +#define MMS_ERRCLASS_DEFINITION 2 +#define MMS_ERRCODE_OBJ_UNDEFINED 1 +#define MMS_ERRCODE_INVALID_ADDRESS 2 +#define MMS_ERRCODE_TYPE_UNSUPPORTED 3 +#define MMS_ERRCODE_TYPE_INCONSISTENT 4 +#define MMS_ERRCODE_OBJ_EXISTS 5 +#define MMS_ERRCODE_OBJ_ATTRIBUTE_INCONSISTENT 6 + +/* Defines for "Resource" error class. */ +#define MMS_ERRCLASS_RESOURCE 3 +#define MMS_ERRCODE_MEM_UNAVAILABLE 1 +#define MMS_ERRCODE_PROCESSOR_RESOURCE_UNAVAILABLE 2 +#define MMS_ERRCODE_MASS_STORAGE_UNAVAILABLE 3 +#define MMS_ERRCODE_CAPABILITY_UNAVAILABLE 4 +#define MMS_ERRCODE_CAPABILITY_UNKOWN 5 + +/* Defines for "Service" error class. */ +#define MMS_ERRCLASS_SERVICE 4 +#define MMS_ERRCODE_PRIMITIVES_OUT_OF_SEQ 1 +#define MMS_ERRCODE_OBJ_STATE_CONFLICT 2 +/* Value 3 reserved for further definition */ +#define MMS_ERRCODE_CONTINUATION_INVALID 4 +#define MMS_ERRCODE_OBJ_CONSTRAINT_CONFLICT 5 + +/* Defines for "Service Preempt" error class. */ +#define MMS_ERRCLASS_SERVICE_PREEMPT 5 +#define MMS_ERRCODE_TIMEOUT 1 +#define MMS_ERRCODE_DEADLOCK 2 +#define MMS_ERRCODE_CANCEL 3 + +/* Defines for "Time Resolution" error class. */ +#define MMS_ERRCLASS_TIME_RESOLUTION 6 +#define MMS_ERRCODE_UNSUPPORTABLE_TIME_RESOLUTION 1 + +/* Defines for "Access" error class. */ +#define MMS_ERRCLASS_ACCESS 7 +#define MMS_ERRCODE_OBJ_ACCESS_UNSUPPORTED 1 +#define MMS_ERRCODE_OBJ_NON_EXISTENT 2 +#define MMS_ERRCODE_OBJ_ACCESS_DENIED 3 +#define MMS_ERRCODE_OBJ_INVALIDATED 4 + +/* Defines for "Initiate" error class. */ +#define MMS_ERRCLASS_INITIATE 8 +/* Value 1 reserved for further definition */ +/* Value 2 reserved for further definition */ +#define MMS_ERRCODE_MAX_SRV_OUTSTD_CALLING_INSUFF 3 +#define MMS_ERRCODE_MAX_SRV_OUTSTD_CALLED_INSUFF 4 +#define MMS_ERRCODE_SERVICE_CBB_INSUFF 5 +#define MMS_ERRCODE_PARAM_CBB_INSUFF 6 +#define MMS_ERRCODE_NESTING_LEVEL_INSUFF 7 + +/* Defines for "Conclude" error class. */ +#define MMS_ERRCLASS_CONCLUDE 9 +#define MMS_ERRCODE_FURTHER_COMM_REQUIRED 1 + +/* Defines for "Cancel" error class. */ +#define MMS_ERRCLASS_CANCEL 10 +#define MMS_ERRCODE_INVOKE_ID_UNKNOWN 1 +#define MMS_ERRCODE_CANCEL_NOT_POSSIBLE 2 + +/* Defines for "File" error class. */ +#define MMS_ERRCLASS_FILE 11 +#define MMS_ERRCODE_FILENAME_AMBIGUOUS 1 +#define MMS_ERRCODE_FILE_BUSY 2 +#define MMS_ERRCODE_FILENAME_SYNTAX_ERROR 3 +#define MMS_ERRCODE_CONTENT_TYPE_INVALID 4 +#define MMS_ERRCODE_POSITION_INVALID 5 +#define MMS_ERRCODE_FILE_ACCESS_DENIED 6 +#define MMS_ERRCODE_FILE_NON_EXISTENT 7 +#define MMS_ERRCODE_DUPLICATE_FILENAME 8 +#define MMS_ERRCODE_INSUFF_SPACE_IN_FILESTORE 9 + +/************************************************************************/ +/* Additional Error Response Information - */ +/* This information is set whenever there is optional additional */ +/* error response information. */ +/************************************************************************/ + +struct adtnl_err_resp_info + { + ST_BOOLEAN mod_pos_pres;/* Confirmed-ErrorPDU only: modifier pos pres */ + ST_INT32 mod_pos; /* Confirmed-ErrorPDU only: modifier position */ + ST_BOOLEAN info_pres; /* global additional info present indicator */ + ST_BOOLEAN code_pres; /* additional code present indicator */ + ST_INT32 code; /* additional code */ + ST_BOOLEAN descr_pres;/* additional description present indicator */ + ST_CHAR *descr; /* pointer to the additional description */ + ST_BOOLEAN ssi_pres; /* service specific info present indicator */ + ST_INT16 service; /* number indicating the service (0-10) */ + ST_UINT32 ss_error_val; /* service specific error value, when service */ + /* is 0-7, or 9 (IS) */ + /* service specific object name, when service */ + /* is 8 (IS-Define Event Enrollment) */ + OBJECT_NAME ss_error_oname; + /* service specific additional service error, */ + /* when service is 10 (IS-Companion Standard) */ + ST_INT ss_error_len; /* service specific additional service length */ + ST_UCHAR *ss_error_data;/* service specific additional service data ptr */ + }; +typedef struct adtnl_err_resp_info ADTNL_ERR_RESP_INFO; + + +/************************************************************************/ +/* RECEIVED ERROR RESPONSE INFORMATION */ +/************************************************************************/ +/* The structure below is filled in when an error message is received, */ +/* before the u_xxxx_conf function is invoked. */ +/************************************************************************/ + +struct err_info + { + ST_INT16 eclass; /* error class */ + ST_INT16 code; /* error code */ + ADTNL_ERR_RESP_INFO adtnl; /* additional error information */ + }; +typedef struct err_info ERR_INFO; + +/************************************************************************/ +/* Error Response Decode Function - */ +/* This routine is called to decode an error response PDU. */ +/************************************************************************/ + +ST_VOID mms_err_rsp (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/* SEND ERROR RESPONSE INFORMATION */ +/************************************************************************/ +/* The structure below is filled in when an error response is to be */ +/* sent that includes the optional additional error information. */ +/* Note : this information must be set prior to issuing the call to */ +/* mp_err_resp, if it is to be included in the response. */ +/************************************************************************/ + +extern ADTNL_ERR_RESP_INFO adtnl_err_info; + +/************************************************************************/ +/* Error Response Encode & Send Functions - */ +/* These routines are called to build and send error response PDU's, */ +/* one for the case of a Cancel indication, the other for all other */ +/* cases. The parameters are : a pointer to the request information, */ +/* the error class, and the error code. */ +/************************************************************************/ + +#ifndef MMS_LITE +ST_RET mp_err_resp (MMSREQ_IND *ind, ST_INT16 err_class, ST_INT16 code); +ST_RET mp_init_err (MMSREQ_IND *ind, ST_INT16 err_class, ST_INT16 code); +ST_RET mp_conclude_err (MMSREQ_IND *ind, ST_INT16 err_class, ST_INT16 code); +ST_RET mp_cancel_err (MMSREQ_IND *ind, ST_INT16 err_class, ST_INT16 code); +#else +ST_RET mpl_err_resp (ST_INT op, ST_UINT32 invoke, ST_INT16 err_class, ST_INT16 code); +ST_RET mpl_init_err (ST_INT16 err_class, ST_INT16 code); +ST_RET mpl_conclude_err (ST_INT16 err_class, ST_INT16 code); +ST_RET mpl_cancel_err (ST_UINT32 invoke, ST_INT16 err_class, ST_INT16 code); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MMS_ERR_INCLUDED */ diff --git a/mmslib/inc/mms_log.h b/mmslib/inc/mms_log.h new file mode 100644 index 0000000..7260b0e --- /dev/null +++ b/mmslib/inc/mms_log.h @@ -0,0 +1,109 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2003, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_log.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains MMS-EASE logging definitions */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/04/03 EJV 04 Chg mms_debug_sel to ST_UINT, and deleted */ +/* L suffix from MMS_LOG_... masks. */ +/* 03/15/01 JRB 03 Added user_debug_sel to control USER logging.*/ +/* 10/08/98 MDE 02 Migrated to updated SLOG interface */ +/* 06/09/97 MDE 01 Added 2 new Log macros */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_LOG_INCLUDED +#define MMS_LOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ + +#include "slog.h" + +/************************************************************************/ +/* mms_debug_sel bit assignments */ +#define MMS_LOG_DEC 0x00000001 +#define MMS_LOG_ENC 0x00000002 +#define MMS_LOG_ACSE 0x00000004 +#define MMS_LOG_LLC 0x00000008 +#define MMS_LOG_IQUE 0x00000010 +#define MMS_LOG_RQUE 0x00000020 + +/* Keep the next two reserved for the user (not used internally) */ +#define MMS_LOG_USR_IND 0x00000040 +#define MMS_LOG_USR_CONF 0x00000080 + +#define MMS_LOG_VM 0x00000100 +#define MMS_LOG_DATA 0x00000200 + +/* Defines used for selecting MMSEASE que servicing debug levels. */ +#define MMSREQQUE_HOLD 0x00004000 +#define MMSINDQUE_HOLD 0x00008000 + +#define MMS_LOG_ERR 0x00010000 +#define MMS_LOG_NERR 0x00020000 +#define MMS_LOG_PDU 0x00040000 +#define MMS_LOG_CONFIG 0x00080000 + +#define MMS_LOG_RT 0x00100000 +#define MMS_LOG_RTAA 0x00200000 +#define MMS_LOG_AA 0x00400000 + +#define MMS_LOG_REQ 0x01000000 +#define MMS_LOG_RESP 0x02000000 +#define MMS_LOG_IND 0x04000000 +#define MMS_LOG_CONF 0x08000000 + +/************************************************************************/ +/* These are S_LOG control items for MMS-EASE logging */ + +extern ST_UINT mms_debug_sel; + +/************************************************************************/ +/* user_debug_sel bit assignments */ +#define USER_LOG_ERR 0x00000001 +#define USER_LOG_CLIENT 0x00000002 +#define USER_LOG_SERVER 0x00000004 + +extern ST_UINT user_debug_sel; /* global var to control USER logging */ + +/************************************************************************/ +/* User selectable function to log MMS actions (MLOG, for instance) */ + +#ifndef MMS_LITE +extern ST_VOID (*m_log_ureq_info_fun) (ST_INT chan, ST_INT op, ST_VOID *info); +extern ST_VOID (*m_log_req_info_fun) (MMSREQ_PEND *req, ST_VOID *info); +extern ST_VOID (*m_log_resp_info_fun) (MMSREQ_IND *ind, ST_VOID *info); +extern ST_VOID (*m_log_ind_info_fun) (MMSREQ_IND *ind); +extern ST_VOID (*m_log_conf_info_fun) (MMSREQ_PEND *conf); +extern ST_VOID (*m_log_error_resp_fun) (MMSREQ_IND *ind, ST_INT16 err_class, ST_INT16 code); +#endif + +/************************************************************************/ +/* Some SLOG Logging control macros */ + +#define MLOG_CLOSE_FILE() {slogCloseFile (sLogCtrl);} +#define MLOG_DUMP_MEM_LOG() {slogDumpMem (sLogCtrl);} +#define MLOG_STOP_FILE_LOGGING() {sLogCtrl->logCtrl &= ~LOG_FILE_EN;} +#define MLOG_START_FILE_LOGGING() {sLogCtrl->logCtrl |= LOG_FILE_EN;} + +#ifdef __cplusplus +} +#endif + +/************************************************************************/ +#endif /* End of MMS_LOG_INCLUDED */ +/************************************************************************/ diff --git a/mmslib/inc/mms_mp.h b/mmslib/inc/mms_mp.h new file mode 100644 index 0000000..26d2682 --- /dev/null +++ b/mmslib/inc/mms_mp.h @@ -0,0 +1,234 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_mp.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the common data structures and general function */ +/* declarations required to interface with MMS at the primitive */ +/* level. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 05 Convert to use ASN1R. */ +/* 08/15/97 MDE 04 BTOD handling changes */ +/* 08/14/97 RKR 03 Format changes */ +/* 06/11/97 RKR 02 Added constants for EXTERNAL encoding tag */ +/* 06/09/97 MDE 01 MMS-LITE define changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_MP_INCLUDED +#define MMS_MP_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "asn1defs.h" +#ifndef MMS_LITE +#include "mms_defs.h" +#endif + +/************************************************************************/ +/* MMS-LITE specific defines */ + +#if defined(MMS_LITE) +/* For MMS-LITE, we will use 'lite' versions of some data structures */ +#define USE_COMPACT_MMS_STRUCTS + +/* For MMS-LITE, we will supply a single static decode info buffer */ +#define M_USR_DEC_BUF +#endif + +/************************************************************************/ +/* Common default values for priority and severity */ +/************************************************************************/ + +#define MMS_NORM_PRIORITY 64 +#define MMS_NORM_SEVERITY 64 + +/************************************************************************/ +/* Object Name - This structure is used to reference MMS objects */ +/************************************************************************/ + +/* These defines may be used for the object_tag element selector */ +#define VMD_SPEC 0 +#define DOM_SPEC 1 +#define AA_SPEC 2 + +#if !defined (USE_COMPACT_MMS_STRUCTS) + +/* Standard form of object name */ +struct object_name + { + ST_INT object_tag; /* See above for legal values */ + union + { + ST_CHAR vmd_spec [MAX_IDENT_LEN+1]; /* vmd specific identifier */ + ST_CHAR item_id [MAX_IDENT_LEN+1]; /* item identifier */ + ST_CHAR aa_spec [MAX_IDENT_LEN+1]; /* aa specific identifier */ + } obj_name; + ST_CHAR domain_id [MAX_IDENT_LEN+1]; /* domain identifier */ + SD_END_STRUCT + }; + +#else /* Use compact form */ + +/* Compact form of object name */ +struct object_name + { + ST_INT object_tag; /* See above for legal values */ + union + { + ST_CHAR *vmd_spec; /* vmd specific identifier */ + ST_CHAR *item_id; /* item identifier */ + ST_CHAR *aa_spec; /* aa specific identifier */ + } obj_name; + ST_CHAR *domain_id; /* domain identifier */ + SD_END_STRUCT + }; +#endif + +typedef struct object_name OBJECT_NAME; + + +/************************************************************************/ +/* timeofday, event_time, attach_to_evcon, attach_to_semaphore and */ +/* modifier structure definitions. */ +/************************************************************************/ + +struct event_time + { + ST_INT16 evtime_tag; /* event time tag */ + /* 0: time of day */ + /* 1: time sequence identifier */ + /* 2: undefined */ + union + { + MMS_BTOD time_of_day; /* time of day */ + ST_UINT32 time_seq_id; /* time sequence identifier */ + } evtime; + }; +typedef struct event_time EVENT_TIME; + +struct attach_to_evcon + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + OBJECT_NAME evcon_name; /* event condition name */ + ST_UCHAR causing_transitions; /* causing transitions: */ + /* bitstring */ + /* 0 : idle to disabled */ + /* 1 : active to disabled */ + /* 2 : disabled to idle */ + /* 3 : active to idle */ + /* 4 : disabled to active */ + /* 5 : idle to active */ + /* 6 : any to deleted */ + ST_BOOLEAN acc_delay_pres; /* acceptable delay present */ + ST_UINT32 acc_delay; /* acceptable delay */ + SD_END_STRUCT + }; +typedef struct attach_to_evcon ATTACH_TO_EVCON; + +struct attach_to_semaphore + { + OBJECT_NAME sem_name; /* semaphore name */ + ST_BOOLEAN named_token_pres; /* named token present ind */ + ST_CHAR named_token[MAX_IDENT_LEN+1];/* named token */ + ST_UCHAR priority; /* priority */ + /* 0 - highest */ + /* 64 - normal (default) */ + /* 127 - lowest */ + ST_BOOLEAN acc_delay_pres; /* acceptable delay present */ + ST_UINT32 acc_delay; /* acceptable delay */ + ST_BOOLEAN ctrl_timeout_pres; /* control timeout present */ + ST_UINT32 ctrl_timeout; /* control timeout */ + ST_BOOLEAN abrt_on_timeout_pres; /* Abort On Timeout present */ + ST_BOOLEAN abrt_on_timeout; /* Abort On Timeout */ + ST_BOOLEAN rel_conn_lost; /* relinquish if connection */ + SD_END_STRUCT + }; /* lost (default = true) */ +typedef struct attach_to_semaphore ATTACH_TO_SEMAPHORE; + +struct modifier + { + ST_INT modifier_tag; /* modifier tag */ + /* 0:attach to event condition */ + /* 1:attach to semaphore */ + union + { + ATTACH_TO_EVCON atec; /* attach to event condition */ + ATTACH_TO_SEMAPHORE atsem; /* attach to semaphore */ + } mod; + SD_END_STRUCT + }; +typedef struct modifier MODIFIER; + +/************************************************************************/ +/* File Name */ +/************************************************************************/ + +struct file_name + { + ST_INT fn_len; /* The length of the string */ + ST_CHAR *fname; /* pointer to actual filename string */ + SD_END_STRUCT + }; +typedef struct file_name FILE_NAME; + +/************************************************************************/ +/* Values for the encoding_tag of an EXTERN_INFO */ +/************************************************************************/ + +#define M_EXT_TAG_ANY 0 +#define M_EXT_TAG_OCT_ALIGNED 1 +#define M_EXT_TAG_ARB 2 + +/************************************************************************/ +/* EXTERNAL */ +/* The structure below is used to store ASN.1 type EXTERNAL in "C" */ +/* format. */ +/************************************************************************/ + +struct extern_info + { + ST_BOOLEAN dir_ref_pres; /* direct reference present */ + MMS_OBJ_ID dir_ref; + + ST_BOOLEAN indir_ref_pres; /* indirect reference present */ + ST_INT32 indir_ref; /* indirect reference value */ + + ST_BOOLEAN dv_descr_pres; /* data value descript pres */ + ST_INT dv_descr_len; /* data value descr. len */ + ST_UCHAR *dv_descr; /* data value descr. ptr */ + + ST_CHAR encoding_tag; /* type of encoding */ + ST_INT num_bits; /* for arbitrary only */ + ST_INT data_len; /* # bytes of data */ + ST_UCHAR *data_ptr; /* data pointer */ + SD_END_STRUCT + }; +typedef struct extern_info EXTERN_INFO; + + +ST_RET ms_encode_extern (EXTERN_INFO *src, + ST_UCHAR *asn1dest, ST_INT destlen, + ST_INT *len_out, ST_UCHAR **asn1_start_out); + +ST_RET ms_decode_extern (ST_UCHAR *asn1, ST_INT asn1len, EXTERN_INFO *dest); + +ST_VOID wr_external (ASN1_ENC_CTXT *aCtx, EXTERN_INFO *ext); + + +#ifdef __cplusplus +} +#endif + +#endif /* MMS_MP_INCLUDED */ diff --git a/mmslib/inc/mms_pcon.h b/mmslib/inc/mms_pcon.h new file mode 100644 index 0000000..4a8fb07 --- /dev/null +++ b/mmslib/inc/mms_pcon.h @@ -0,0 +1,294 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pcon.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS context management services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/13/05 MDE 07 Added defines for reject class and code */ +/* 03/23/05 JRB 06 Include asn1r instead of suicacse because */ +/* APP_REF moved to asn1r. */ +/* 07/10/02 JRB 05 Clarify description of maxreq_calling/called.*/ +/* 12/10/97 MDE 04 Changed max_nest to ST_INT8 */ +/* 11/06/97 MDE 03 Added suicacse.h, use APP_REF typedef */ +/* 08/13/97 RKR 02 Format changes */ +/* 07/29/97 DSF 01 Moved APP_REF to SUIC */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PCON_INCLUDED +#define MMS_PCON_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_err.h" +#include "mms_mp.h" +#include "asn1r.h" /* need APP_REF */ + +/************************************************************************/ +/************************************************************************/ +/* CONTEXT MANAGEMENT SERVICES */ +/************************************************************************/ +/* The structures below are used to pass CONTEXT MANAGEMENT information */ +/* to/from the MMS primitives. */ +/************************************************************************/ + +/************************************************************************/ +/* INITIATE */ +/************************************************************************/ + +struct init_rslt + { + ST_BOOLEAN accept_context; /* SD_TRUE if not error */ + ST_BOOLEAN err_info_pres; /* error information available */ + ERR_INFO err; /* otherwise look here */ + }; +typedef struct init_rslt INIT_RSLT; + + +/* This structure is used for non-core MMS-EASE P-Context's. */ +/* It is attached to the primary initiate info structure as an array */ + +struct cs_init_info + { + ST_UINT p_context; /* P-Context for this init */ + ST_BOOLEAN local_detail_pres; /* flag if local_detail is present */ + ST_INT32 local_detail; /* local detail */ + ST_INT16 maxreq_calling; /* max outst. "ind" allowed at "calling" app*/ + /* DEBUG: chg name to max_ind_calling? */ + ST_INT16 maxreq_called; /* max outst. "ind" allowed at "called" app*/ + /* DEBUG: chg name to max_ind_called? */ + ST_BOOLEAN max_nest_pres; /* indicates if max_nest is present */ + ST_INT8 max_nest; /* maximum data nesting */ + ST_INT init_detail_len; /* init detail */ + ST_UCHAR *init_detail; /* this is an ASN.1 encoded sequence */ + INIT_RSLT rslt; + }; +typedef struct cs_init_info CS_INIT_INFO; + + +/* REQUEST & RESPONSE : */ + +struct init_info + { /* Proposed (req) / Negiotiated (resp) */ + ST_BOOLEAN mms_p_context_pres;/* MMS Core context used */ + ST_BOOLEAN max_segsize_pres; /* flag if max_segsize is present */ + ST_INT32 max_segsize; /* maximum segment size */ + ST_INT16 maxreq_calling; /* max outst. "ind" allowed at "calling" app*/ + /* DEBUG: chg name to max_ind_calling? */ + ST_INT16 maxreq_called; /* max outst. "ind" allowed at "called" app*/ + /* DEBUG: chg name to max_ind_called? */ + ST_BOOLEAN max_nest_pres; /* indicates if max_nest is present */ + ST_INT8 max_nest; /* maximum data nesting */ + ST_BOOLEAN mms_detail_pres; /* mms init detail enable */ + ST_INT16 version; /* version */ + ST_UCHAR param_supp[2]; /* parameter support options: bitstring */ + ST_UCHAR serv_supp[11]; /* service support options: bitstring */ + INIT_RSLT rslt; /* success/failure & error info */ + ST_INT num_cs_init; /* number of CS init info's attached */ + ST_INT core_position; /* Position for CORE CONTEXT in list */ + /* (0 = first, num_cs_init = last, etc. */ +/* followed by CS_INIT_INFO cs_init[num_cs_init] */ + SD_END_STRUCT + }; +typedef struct init_info INIT_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_init (ST_INT chan, ST_CHAR *partner, INIT_INFO *info_ptr); +ST_RET mp_init_resp (MMSREQ_IND *indptr, INIT_INFO *info); +#else +ST_RET mpl_init (INIT_INFO *info); +ST_RET mpl_cs_init (CS_INIT_INFO *info); +ST_RET mpl_init_resp (INIT_INFO *info); +ST_RET mpl_cs_init_resp (CS_INIT_INFO *info); +#endif + +/************************************************************************/ +/* CONCLUDE */ +/************************************************************************/ + +/* REQUEST : NULL */ +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_conclude (ST_INT chan); +ST_RET mp_conclude_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_conclude (ST_VOID); +ST_RET mpl_conclude_resp (ST_VOID); +#endif + +/************************************************************************/ +/* CANCEL */ +/************************************************************************/ + +/* REQUEST : NULL */ +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_cancel (MMSREQ_PEND *req); +ST_RET mp_cancel_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_cancel (ST_VOID); +ST_RET mpl_cancel_resp (ST_VOID); +#endif + +/************************************************************************/ +/* REJECT */ +/************************************************************************/ + + +#define MMS_REJ_CLASS_CONFIRMED_REQUEST_PDU 1 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_OTHER 0 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_UNRECOGNIZED_SERVICE 1 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_UNRECOGNIZED_MODIFIER 2 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_INVALID_INVOKEID 3 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_INVALID_ARGUMENT 4 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_INVALID_MODIFIER 5 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_MAX_SERV_OUTSTANDING_EXCEEDED 6 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_MAX_RECURSION_EXCEEDED 8 +#define MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_VALUE_OUT_OF_RANGE 9 + +#define MMS_REJ_CLASS_CONFIRMED_RESPONSE_PDU 2 +#define MMS_REJ_CODE_CONFIRMED_RESPONSE_PDU_OTHER 0 +#define MMS_REJ_CODE_CONFIRMED_RESPONSE_PDU_UNRECOGNIZED_SERVICE 1 +#define MMS_REJ_CODE_CONFIRMED_RESPONSE_PDU_INVALID_INVOKEID 2 +#define MMS_REJ_CODE_CONFIRMED_RESPONSE_PDU_INVALID_RESULT 3 +#define MMS_REJ_CODE_CONFIRMED_RESPONSE_PDU_MAX_RECURSION_EXCEEDED 5 +#define MMS_REJ_CODE_CONFIRMED_RESPONSE_PDU_VALUE_OUT_OF_RANGE 6 + +#define MMS_REJ_CLASS_CONFIRMED_ERROR_PDU 3 +#define MMS_REJ_CODE_CONFIRMED_ERROR_PDU_OTHER 0 +#define MMS_REJ_CODE_CONFIRMED_ERROR_PDU_UNRECOGNIZED_SERVICE 1 +#define MMS_REJ_CODE_CONFIRMED_ERROR_PDU_INVALID_INVOKEID 2 +#define MMS_REJ_CODE_CONFIRMED_ERROR_PDU_INVALID_SERVICEERROR 3 +#define MMS_REJ_CODE_CONFIRMED_ERROR_PDU_VALUE_OUT_OF_RANGE 4 + +#define MMS_REJ_CLASS_UNCONFIRMED_PDU 4 +#define MMS_REJ_CODE_UNCONFIRMED_PDU_OTHER 0 +#define MMS_REJ_CODE_UNCONFIRMED_PDU_UNRECOGNIZED_SERVICE 1 +#define MMS_REJ_CODE_UNCONFIRMED_PDU_INVALID_ARGUMENT 2 +#define MMS_REJ_CODE_UNCONFIRMED_PDU_MAX_RECURSION_EXCEEDED 3 +#define MMS_REJ_CODE_UNCONFIRMED_PDU_VALUE_OUT_OF_RANGE 4 + +#define MMS_REJ_CLASS_PDU_ERROR 5 +#define MMS_REJ_CODE_PDU_ERROR_UNKNOWN_PDU_TYPE 0 +#define MMS_REJ_CODE_PDU_ERROR_INVALID_PDU 1 +#define MMS_REJ_CODE_PDU_ERROR_ILLEGAL_ACSE_MAPPING 2 + +#define MMS_REJ_CLASS_CANCEL_REQUEST_PDU 6 +#define MMS_REJ_CODE_CANCEL_REQUEST_PDU_OTHER 0 +#define MMS_REJ_CODE_CANCEL_REQUEST_PDU_INVALID_INVOKEID 1 + +#define MMS_REJ_CLASS_CANCEL_RESPONSE_PDU 7 +#define MMS_REJ_CODE_CANCEL_RESPONSE_PDU_OTHER 0 +#define MMS_REJ_CODE_CANCEL_RESPONSE_PDU_INVALID_INVOKEID 1 + +#define MMS_REJ_CLASS_CANCEL_ERROR_PDU 8 +#define MMS_REJ_CODE_CANCEL_ERROR_PDU_OTHER 0 +#define MMS_REJ_CODE_CANCEL_ERROR_PDU_INVALID_INVOKEID 1 +#define MMS_REJ_CODE_CANCEL_ERROR_PDU_INVALID_SERVICEERROR 2 +#define MMS_REJ_CODE_CANCEL_ERROR_PDU_VALUE_OUT_OF_RANGE 3 + +#define MMS_REJ_CLASS_CONCLUDE_REQUEST_PDU 9 +#define MMS_REJ_CODE_CONCLUDE_REQUEST_PDU_OTHER 0 +#define MMS_REJ_CODE_CONCLUDE_REQUEST_PDU_INVALID_ARGUMENT 1 + +#define MMS_REJ_CLASS_CONCLUDE_RESPONSE_PDU 10 +#define MMS_REJ_CODE_CONCLUDE_RESPONSE_PDU_OTHER 0 +#define MMS_REJ_CODE_CONCLUDE_RESPONSE_PDU_INVALID_RESULT 1 + +#define MMS_REJ_CLASS_CONCLUDE_ERROR_PDU 11 +#define MMS_REJ_CODE_CONCLUDE_ERROR_PDU_OTHER 0 +#define MMS_REJ_CODE_CONCLUDE_ERROR_PDU_INVALID_SERVICEERROR 1 +#define MMS_REJ_CODE_CONCLUDE_ERROR_PDU_VALUE_OUT_OF_RANGE 2 + + +struct reject_resp_info + { + ST_BOOLEAN detected_here; /* flag indicating where error occurred */ + ST_BOOLEAN invoke_known; /* flag indicating if invoke ID known */ + ST_UINT32 invoke; /* invoke ID of service rejected */ + ST_INT pdu_type; /* pdu type of service rejected */ + ST_INT16 rej_class; /* reject class */ + ST_INT16 rej_code; /* reject code */ + }; +typedef struct reject_resp_info REJECT_RESP_INFO; + +#ifndef MMS_LITE +ST_RET mp_reject_resp (ST_INT chan, REJECT_RESP_INFO *info); +ST_RET mp_reject_ind (MMSREQ_IND *ind,REJECT_RESP_INFO *info); +ST_RET mp_reject_conf (MMSREQ_PEND *req,REJECT_RESP_INFO *info); +#else +ST_RET mpl_reject_resp (REJECT_RESP_INFO *info); +#endif + +/************************************************************************/ +/* ABORT REQUEST FUNCTION */ +/************************************************************************/ + +ST_RET mp_abort (ST_INT chan, ST_INT reason); + +/************************************************************************/ +/************************************************************************/ +/* This function is used to convert convert an AR Name into an ASN.1 */ +/* encoded ApplicationReference based on the TPY DIB information */ +/************************************************************************/ + +ST_RET ms_arname_to_asn1 (ST_CHAR *arname, ST_UCHAR *asn1_buf, ST_INT asn1_buf_len, + ST_UCHAR **asn1_out, ST_INT *asn1_len_out); + +/* This function is used to convert an ASN.1 encoded */ +/* ApplicationReference to the AR Name */ +ST_RET ms_asn1_to_arname (ST_CHAR *arname, ST_UCHAR *asn1, ST_INT asn1len); + +/* This function is used to find an AR Name based on the app_ref */ +/* information. */ +ST_RET ms_appref_to_arname (ST_CHAR *arname, APP_REF *appref); + +/* This function is used to transition between an AR Name and its' */ +/* corresponding app_ref information. */ +ST_RET ms_arname_to_appref (ST_CHAR *arname, APP_REF **appref_out); + +/* This function is used to convert to an ApplicationReference to ASN.1 */ +ST_RET ms_appref_to_asn1 (APP_REF *appref, ST_UCHAR *dest, ST_INT dest_len, + ST_UCHAR **asn1_out, ST_INT *asn1_len_out); + +/* This function is used to convert ASN.1 encoded ApplicationReference */ +/* data to an intermediate form. */ +ST_RET ms_asn1_to_appref (APP_REF *appref, ST_UCHAR *asn1, ST_INT asn1len); + + +#ifdef __cplusplus +} +#endif + +#endif /* MMS_PCON_INCLUDED */ + diff --git a/mmslib/inc/mms_pdom.h b/mmslib/inc/mms_pdom.h new file mode 100644 index 0000000..5562993 --- /dev/null +++ b/mmslib/inc/mms_pdom.h @@ -0,0 +1,419 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pdom.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS domain management services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/13/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PDOM_INCLUDED +#define MMS_PDOM_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_err.h" /* need for service error definition */ +#include "mms_mp.h" + +/************************************************************************/ +/************************************************************************/ +/* DOMAIN MANAGEMENT SERVICES */ +/************************************************************************/ +/* The structures below are used to pass DOMAIN MANAGEMENT information */ +/* to/from the MMS primitives. */ +/************************************************************************/ + +/* use these defines to determine whether load data is coded or not */ +/* If coded, the data pointer points to a complete ASN.1 EXTERNAL */ + +#define LOAD_DATA_NON_CODED 0 +#define LOAD_DATA_CODED 1 + + +/************************************************************************/ +/* INITIATE DOWNLOAD SEQUENCE */ +/************************************************************************/ + +/* REQUEST : */ + +struct initdown_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + ST_BOOLEAN sharable; /* boolean, no default */ + ST_INT num_of_capab; /* number of capabilities */ +/* list of capabilities */ +/* ST_CHAR * capab_list [num_of_capab]; */ + SD_END_STRUCT + }; +typedef struct initdown_req_info INITDOWN_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_initdown (ST_INT chan, INITDOWN_REQ_INFO *info); +ST_RET mp_initdown_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_initdown (INITDOWN_REQ_INFO *info); +ST_RET mpl_initdown_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DOWNLOAD SEGMENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct download_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + }; +typedef struct download_req_info DOWNLOAD_REQ_INFO; + +/* RESPONSE : */ + + +struct download_resp_info + { + ST_INT load_data_type; /* coded/non-coded */ + ST_INT load_data_len; /* number of load data octets */ + ST_UCHAR *load_data; /* pointer to load data octets */ + ST_BOOLEAN more_follows; /* boolean, default to true */ + }; +typedef struct download_resp_info DOWNLOAD_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_download (ST_INT chan, DOWNLOAD_REQ_INFO *info); +ST_RET mp_download_resp (MMSREQ_IND *ind, DOWNLOAD_RESP_INFO *info); +#else +ST_RET mpl_download (DOWNLOAD_REQ_INFO *info); +ST_RET mpl_download_resp (ST_UINT32 invoke, DOWNLOAD_RESP_INFO *info); +#endif + +/************************************************************************/ +/* TERMINATE DOWNLOAD SEQUENCE */ +/************************************************************************/ + +/* REQUEST : */ + +struct termdown_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + ST_BOOLEAN discarded; /* boolean, default to false */ + ERR_INFO *err; /* points to service error */ + }; /* (IS only, for discarded != 0 */ +typedef struct termdown_req_info TERMDOWN_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_termdown (ST_INT chan, TERMDOWN_REQ_INFO *info); +ST_RET mp_termdown_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_termdown (TERMDOWN_REQ_INFO *info); +ST_RET mpl_termdown_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* INITIATE UPLOAD SEQUENCE */ +/************************************************************************/ + +/* REQUEST : */ + +struct initupl_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + }; +typedef struct initupl_req_info INITUPL_REQ_INFO; + +/* RESPONSE : */ + +struct initupl_resp_info + { + ST_INT32 ulsmid; /* upload state machine id */ + ST_INT num_of_capab; /* number of capabilities */ +/* list of capabilities */ +/* ST_CHAR *capab_list [num_of_capab]; */ + SD_END_STRUCT + }; +typedef struct initupl_resp_info INITUPL_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_initupl (ST_INT chan, INITUPL_REQ_INFO *info); +ST_RET mp_initupl_resp (MMSREQ_IND *ind, INITUPL_RESP_INFO *info); +#else +ST_RET mpl_initupl (INITUPL_REQ_INFO *info); +ST_RET mpl_initupl_resp (ST_UINT32 invoke, INITUPL_RESP_INFO *info); +#endif + +/************************************************************************/ +/* UPLOAD SEGMENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct upload_req_info + { + ST_INT32 ulsmid; /* upload state machine id */ + }; +typedef struct upload_req_info UPLOAD_REQ_INFO; + +/* RESPONSE : */ + +struct upload_resp_info + { + ST_INT load_data_type; /* coded/non-coded */ + ST_INT load_data_len; /* number of load data octets */ + ST_UCHAR *load_data; /* pointer to load data octets */ + ST_BOOLEAN more_follows; /* boolean, default to true */ + }; +typedef struct upload_resp_info UPLOAD_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_upload (ST_INT chan, UPLOAD_REQ_INFO *info); +ST_RET mp_upload_resp (MMSREQ_IND *ind, UPLOAD_RESP_INFO *info); +#else +ST_RET mpl_upload (UPLOAD_REQ_INFO *info); +ST_RET mpl_upload_resp (ST_UINT32 invoke, UPLOAD_RESP_INFO *info); +#endif + +/************************************************************************/ +/* TERMINATE UPLOAD SEQUENCE */ +/************************************************************************/ + +/* REQUEST : */ + +struct termupl_req_info + { + ST_INT32 ulsmid; /* upload state machine id */ + }; +typedef struct termupl_req_info TERMUPL_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_termupl (ST_INT chan, TERMUPL_REQ_INFO *info); +ST_RET mp_termupl_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_termupl (TERMUPL_REQ_INFO *info); +ST_RET mpl_termupl_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* REQUEST DOMAIN DOWNLOAD */ +/************************************************************************/ + +/* REQUEST : */ + +struct rddwn_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + ST_BOOLEAN sharable; /* boolean, no default */ + ST_INT num_of_capab; /* number of capabilities */ + ST_INT num_of_fname; /* num of fname elements */ +/* list of capabilities */ +/* ST_CHAR * capab_list [num_of_capab]; */ +/* list of file names */ +/* FILE_NAME fname_list[ num_of_fname ]; */ + SD_END_STRUCT + }; +typedef struct rddwn_req_info RDDWN_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_rddwn (ST_INT chan, RDDWN_REQ_INFO *info); +ST_RET mp_rddwn_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_rddwn (RDDWN_REQ_INFO *info); +ST_RET mpl_rddwn_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* REQUEST DOMAIN UPLOAD */ +/************************************************************************/ + +/* REQUEST : */ + +struct rdupl_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + ST_INT num_of_fname; /* num of fname elements */ +/* list of file names */ +/* FILE_NAME fname_list[ num_of_fname ]; */ + SD_END_STRUCT + }; +typedef struct rdupl_req_info RDUPL_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_rdupl (ST_INT chan, RDUPL_REQ_INFO *info); +ST_RET mp_rdupl_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_rdupl (RDUPL_REQ_INFO *info); +ST_RET mpl_rdupl_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* LOAD DOMAIN CONTENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct loaddom_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + ST_BOOLEAN sharable; /* boolean, no default */ + ST_BOOLEAN third_pty_pres; /* third party used */ + ST_INT third_pty_len; /* the length of third party */ + ST_UCHAR *third_pty; /* ptr to third party ASN.1 */ + ST_INT num_of_capab; /* number of capabilities */ + ST_INT num_of_fname; /* num of fname elements */ +/* list of capabilities */ +/* ST_CHAR *capab_list [num_of_capab]; */ +/* list of file names */ +/* FILE_NAME fname_list[ num_of_fname ]; */ + SD_END_STRUCT + }; +typedef struct loaddom_req_info LOADDOM_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_loaddom (ST_INT chan, LOADDOM_REQ_INFO *info); +ST_RET mp_loaddom_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_loaddom (LOADDOM_REQ_INFO *info); +ST_RET mpl_loaddom_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* STORE DOMAIN CONTENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct storedom_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + ST_INT num_of_fname; /* num of fname elements */ + ST_BOOLEAN third_pty_pres; /* third party used */ + ST_INT third_pty_len; /* the length of third party */ + ST_UCHAR *third_pty; /* ptr to third party ASN.1 */ +/* list of file names */ +/* FILE_NAME fname_list[ num_of_fname ]; */ + SD_END_STRUCT + }; +typedef struct storedom_req_info STOREDOM_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_storedom (ST_INT chan, STOREDOM_REQ_INFO *info); +ST_RET mp_storedom_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_storedom (STOREDOM_REQ_INFO *info); +ST_RET mpl_storedom_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DELETE DOMAIN */ +/************************************************************************/ + +/* REQUEST : */ + +struct deldom_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + }; +typedef struct deldom_req_info DELDOM_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_deldom (ST_INT chan, DELDOM_REQ_INFO *info); +ST_RET mp_deldom_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_deldom (DELDOM_REQ_INFO *info); +ST_RET mpl_deldom_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET DOMAIN ATTRIBUTE */ +/************************************************************************/ + +/* REQUEST : */ + +struct getdom_req_info + { + ST_CHAR dname [MAX_IDENT_LEN +1]; /* domain name */ + }; +typedef struct getdom_req_info GETDOM_REQ_INFO; + +/* RESPONSE : */ + +struct getdom_resp_info + { + ST_INT num_of_capab; /* number of capabilities */ + ST_BOOLEAN mms_deletable; /* MMS deletable, no default */ + ST_BOOLEAN sharable; /* boolean, no default */ + ST_INT num_of_pinames; /* number of pi names */ + ST_INT16 state; /* 0 : non-existent */ + /* 1 : loaded */ + /* 2 : ready */ + /* 3 : in use */ + /* 4 : complete */ + /* 5 : incomplete */ + /* 6-15 : d1-d8 (IS) */ + ST_INT8 upload_in_progress; /* upload in progress */ +/* list of pointers to capabilities */ +/* ST_CHAR *capab_list [num_of_capab]; */ +/* list of pointers to program invocation names */ +/* ST_CHAR *pinames_list [num_of_pinames]; */ + SD_END_STRUCT + }; +typedef struct getdom_resp_info GETDOM_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getdom (ST_INT chan, GETDOM_REQ_INFO *info); +ST_RET mp_getdom_resp (MMSREQ_IND *ind, GETDOM_RESP_INFO *info); +#else +ST_RET mpl_getdom (GETDOM_REQ_INFO *info); +ST_RET mpl_getdom_resp (ST_UINT32 invoke, GETDOM_RESP_INFO *info); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PDOM_INCLUDED */ + diff --git a/mmslib/inc/mms_perr.h b/mmslib/inc/mms_perr.h new file mode 100644 index 0000000..d387f91 --- /dev/null +++ b/mmslib/inc/mms_perr.h @@ -0,0 +1,248 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2007, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_perr.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains structure & function definitions used for */ +/* decoding and encoding an error response. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/05/07 EJV 03 Removed obsolete LLC30_LLP Type code. */ +/* 07/02/98 NAV 02 Add MVE_JOURNAL_NAME error code */ +/* 06/09/97 MDE 01 Fixed indenting */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PERR_INCLUDED +#define MMS_PERR_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/* Global MMS operation error code, written when error is detected in */ +/* functions which return pointers. */ +/************************************************************************/ + +extern ST_RET mms_op_err; + +/************************************************************************/ +/* Error Codes */ +/* MMSEASE error codes start at E_MMS_GEN(found in glberror.h). */ +/* When the return valus from a user accessable function is a pointer, */ +/* an error is indicated by a pointer value of 0L. In this case the */ +/* error code may be found in the global variable 'mms_op_err'. */ +/* */ +/* Note that SUIC error codes are passed through, and are in the range */ +/* 1 - 99. Refer to SUIC documentation for specific error definitions. */ +/* */ +/* */ +/* Error codes returned from any request or response function */ +/************************************************************************/ + +#define ME_CHAN_STATE 0x6401 +#define ME_CHAN_NUM 0x6402 +#define ME_TITLE_LEN 0x6403 +#define ME_SEND_SIZE 0x6404 +#define ME_REQ_PEND_COUNT 0x6405 +#define ME_INACTIVE_IND 0x6406 +#define ME_PARTNER_NAME 0x6407 +#define ME_AR_NAME 0x6408 +#define ME_OBJ_ID_ERR 0x6409 +#define ME_SEND_ERROR 0x640A +#define ME_ACSE_CHAN_RANGE 0x640B +#define ME_LLC_CHAN_RANGE 0x640D +#define ME_LLP_TYPE 0x640E +#define ME_TRANS_ID_UNAVAILABLE 0x640F +#define ME_CHAN_TYPE 0x6410 +#define ME_TOO_MANY_CONTEXTS 0x6411 +#define ME_UNKNOWN_P_CONTEXT 0x6412 +#define ME_P_CONTEXT_ERROR 0x6413 +#define ME_ASN1_ENCODE_OVERRUN 0x6414 + +/************************************************************************/ +/* Error codes returned from mp_xxx_req functions */ +/* Values begin from E_MMS_PPI(found in glberror.h). */ +/************************************************************************/ + +#define ME_QUEFULL 0x6501 + +/************************************************************************/ +/* Error codes found in resp_err */ +/* Values begin from E_MMS_RESP(found in glberror.h). */ +/************************************************************************/ + +#define CNF_RESP_OK 0 +#define CNF_PARSE_ERR 0x6601 +#define CNF_REJ_ERR 0x6602 +#define CNF_ERR_OK 0x6603 +#define CNF_DISCONNECTED 0x6604 +#define CNF_CHAN_OP_ERR 0x6605 +#define CNF_CANST_ERR 0x6606 +#define CNF_ASS_REQ_REJECTED 0x6607 +#define CNF_ASS_RESP_PARAM 0x6608 +#define CNF_ASS_USER_REJ_CONF 0x6609 +#define CNF_REM_FOPEN 0x660A +#define CNF_INIT_PARAM 0x660B +#define CNF_REM_FREAD 0x660C +#define CNF_LOC_FWRITE 0x660D +#define CNF_REM_FCLOSE 0x660E +#define CNF_LOC_FCLOSE 0x660F +#define CNF_MVREAD_RESP_PARAM 0x6610 +#define CNF_VM_RESP_ERR 0x6611 +#define CNF_LLC_SEND_ERROR 0x6612 +#define CNF_REQ_NOT_DONE 0x6613 + +/************************************************************************/ +/* Error codes returned from 'mv_xxxx_resp' functions. */ +/* Values begin from E_MMS_VMI(found in glberror.h). */ +/************************************************************************/ + +#define MVE_VARNAME 0x6701 +#define MVE_TYPENAME 0x6702 +#define MVE_ADDR 0x6703 +#define MVE_FOPEN 0x6704 +#define MVE_REM_FILE_COUNT 0x6705 +#define MVE_LOC_FILE_COUNT 0x6706 +#define MVE_FILE_REFNUM 0x6707 +#define MVE_FRENAME 0x6708 +#define MVE_FDELETE 0x6709 +#define MVE_FDIR 0x670A +#define MVE_LOC_FOPEN 0x670B +#define MVE_CANCEL_STATE 0x670C +#define MVE_DOM_ERR 0x670D +#define MVE_RT_TYPE 0x670E +#define MVE_DOM_STATE 0x670F +#define MVE_AT_UPPER_LIMIT 0x6710 +#define MVE_DATA_CONVERT 0x6711 +#define MVE_VM_SERVICE_NOTSUPP 0x6712 +#define MVE_MVWRITE_REQ_PARAM 0x6713 +#define MVE_DOMAIN_NAME 0x6714 +#define MVE_OBJECT_SCOPE 0x6715 +#define MVE_VAR_LIST 0x6716 +#define MVE_VAR_NUMBER 0x6717 +#define MVE_NOT_NAMED_VAR 0x6718 +#define MVE_WRONG_OP 0x6719 +#define MVE_MVINFO_ACCESS_ERR 0x671A +#define MVE_TYPEDEF_LEN0 0x671B +#define MVE_TYPEDEF_SYM_GT 0x671C +#define MVE_TYPEDEF_SYM_LT 0x671D +#define MVE_TYPEDEF_OBJNAME 0x671E +#define MVE_TYPEDEF_SYM_RBRACE 0x671F +#define MVE_TYPEDEF_SYM_LBRACE 0x6720 +#define MVE_TYPEDEF_SYM_COMMA 0x6721 +#define MVE_TYPEDEF_SYM_RPAREN 0x6722 +#define MVE_TYPEDEF_SYM_LPAREN 0x6723 +#define MVE_TYPEDEF_SYM_P 0x6724 +#define MVE_TYPEDEF_SYM_PLUS 0x6725 +#define MVE_TYPEDEF_SYM_MINUS 0x6726 +#define MVE_TYPEDEF_SYM_T 0x6727 +#define MVE_TYPEDEF_BADLEN3 0x6728 +#define MVE_TYPEDEF_BADLEN4 0x6729 +#define MVE_TYPEDEF_BADLEN5 0x672A +#define MVE_TYPEDEF_BADLEN7 0x672B +#define MVE_TYPEDEF_BADTYPE 0x672C +#define MVE_TYPEDEF_SYM_COLON 0x672D +#define MVE_TYPEDEF_SYM_RBRACKET 0x672E +#define MVE_TYPEDEF_SYM_LBRACKET 0x672F +#define MVE_TYPEDEF_NUM_ELTS 0x6730 +#define MVE_TYPEDEF_SYM_DIGIT 0x6731 +#define MVE_TYPEDEF_SYM_OTHER 0x6732 +#define MVE_DATA_SPACE 0x6733 +#define MVE_VM_REQ_ERR 0x6734 +#define MVE_VMD_NOT_EMPTY 0x6735 +#define MVE_BAD_APP_REF_FORM 0x6736 +#define MVE_ASN1_TO_RT 0x6737 +#define MVE_ASN1_ENCODE_ERR 0x6738 +#define MVE_ASN1_DECODE_ERR 0x6739 +#define MVE_FP_SAVE_REQ_ERR 0x673A +#define MVE_FP_REQ_DONE_ERR 0x673B +#define MVE_LLP_DIB_FOPEN_ERR 0x673C +#define MVE_ADD_APPREF_ERR 0x673D +#define MVE_RESP_NOT_SUPP 0x673E +#define MVE_REQ_NOT_SUPP 0x673F +#define MVE_INVALID_PDU 0x6740 +#define MVE_DOM_DISCARDED 0x6741 +#define MVE_DOM_PROTECTED 0x6742 +#define MVE_DOM_DEL_ERR 0x6743 +#define MVE_DEL_PI_ERR 0x6744 +#define MVE_RTAA_TYPE 0x6745 +#define MVE_RTAA_SIZE 0x6746 +#define MVE_AA_SELECT 0x6747 +#define MVE_INVALID_ADL 0x6748 +#define MVE_DATA_TO_RT 0x6749 +#define MVE_LOC_FILE_READ 0x6750 + +/************************************************************************/ +/* Errors related to VM Program Invocation handling */ + +#define PI_NAME 0x6770 +#define PI_STATE 0x6771 +#define PI_NOT_REUSABLE 0x6772 +#define PI_NOT_DELETABLE 0x6773 +#define ME_PI_PROTECTION 0x6774 +#define ME_PI_INVALID_ID 0x6775 + +/************************************************************************/ +/* Errors related to VM Journal handling */ + +#define MVE_JOURNAL_NAME 0x6776 +#define MVE_INVALID_DOMAIN_OBJ 0x6777 + +/************************************************************************/ +/* ACSE ERROR CODES */ +/* The codes below are used in the info.ACSE.err_code in the case where */ +/* the event is an ACSE_ERROR. The user defined function */ +/* 'u_llp_error_ind' is called with these codes when this occurs. */ +/* Values begin from E_LLP_ACSE(found in glberror.h). */ +/************************************************************************/ + +#define ACSE_RECEIVE_ERR 0x6901L +#define ACSE_LISTEN_ERR 0x6902L +#define ACSE_DISCONNECT_RCV_ERR 0x6903L +#define ACSE_STOP_LISTEN_ERR 0x6904L +#define ACSE_ASS_REQ_ERR 0x6905L +#define ACSE_ASS_RESP_ERR 0x6906L +#define ACSE_REL_RESP_ERR 0x6907L +#define ACSE_REL_REQ_ERR 0x6908L +#define ACSE_SEND_REQ_ERR 0x6909L +#define ACSE_SET_DEBUG_ERR 0x690AL +#define ACSE_ABORT_ERR 0x690BL + + +/************************************************************************/ +/* MMS Exception Codes */ +/* These codes are passed to the user when the user exception function */ +/* (u_mmsexcept_ind) is called. */ +/* Values begin from E_MMS_EXCPT(found in glberror.h). */ +/************************************************************************/ + +#define MX_REJECT 0x6801 +#define MX_BOARD_ERR 0x6802 +#define MX_LLP_EVENT_ERROR 0x6803 +#define MX_MEMORY_ALLOC 0x6804 +#define MX_RUNTIME_TDEF 0x6805 +#define MX_LLP_QUE_OVERFLOW 0x6806 +#define MX_MMSIND_QUE 0x6807 +#define MX_MMSCONF_QUE 0x6808 +#define MX_INTERNAL_ERROR 0x6809 +#define MX_LLP_ADD_INFO_ALLOC 0x680A + + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PERR_INCLUDED */ + + + diff --git a/mmslib/inc/mms_pevn.h b/mmslib/inc/mms_pevn.h new file mode 100644 index 0000000..f32f230 --- /dev/null +++ b/mmslib/inc/mms_pevn.h @@ -0,0 +1,956 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pevn.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS event management services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/12/02 JRB 03 Add ASN1_ENC_CTXT arg to mpl_evnot */ +/* 07/15/97 MDE 02 Added cur_state defines */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PEVN_INCLUDED +#define MMS_PEVN_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_pvar.h" /* needed for variable specification defs */ +#include "mms_err.h" /* needed for service error definitions */ +#include "mms_mp.h" + + +/************************************************************************/ +/* Event cur_state defines */ + +#define EC_STATE_DISABLED 0 +#define EC_STATE_IDLE 1 +#define EC_STATE_ACTIVE 2 + +#define EC_STATE_ACTIVE_NOACK_A 3 +#define EC_STATE_IDLE_NOACK_I 4 +#define EC_STATE_IDLE_NOACK_A 5 +#define EC_STATE_IDLE_ACKED 6 +#define EC_STATE_ACTIVE_ACKED 7 + +/************************************************************************/ +/* EVENT MANAGEMENT FUNCTIONS */ +/************************************************************************/ +/* The structures below are used to pass EVENT MANAGEMENT operation */ +/* information to/from the MMS primitives. */ +/************************************************************************/ + +struct event_enrollment + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + ST_CHAR evcon_name_tag; /* 0 : event condition name */ + /* 1 : undefined */ + OBJECT_NAME evcon_name; /* event condition name - for */ + /* evcon_name_tag = 0 only */ + ST_BOOLEAN evact_name_pres; /* event action name present */ + ST_CHAR evact_name_tag; /* 0 : event action name */ + /* 1 : undefined */ + OBJECT_NAME evact_name; /* event action name - for */ + /* evact_name_tag = 0 only */ + ST_BOOLEAN client_app_pres; /* client application present */ + ST_INT client_app_len; /* client application length */ + ST_UCHAR *client_app; /* client application reference */ + ST_BOOLEAN mms_deletable; /* mms deletable (def = false) */ + ST_INT16 ee_class; /* event enrollment class: */ + /* 0 - modifier */ + /* 1 - notification */ + ST_INT16 duration; /* duration: */ + /* 0 - current (default) */ + /* 1 - permanent */ + ST_BOOLEAN invoke_id_pres; /* invoke id present */ + ST_UINT32 invoke_id; /* invoke id */ + ST_BOOLEAN rem_acc_delay_pres; /* rem acceptable delay present */ + ST_UINT32 rem_acc_delay; /* remaining acceptable delay */ + ST_BOOLEAN addl_detail_pres; /* additional detail present */ + ST_INT addl_detail_len; /* length of additional detail */ + ST_UCHAR *addl_detail; /* pointer to additional detail */ + ST_BOOLEAN ackec_name_pres; /* ack event cond name present */ + ST_CHAR ackec_name_tag; /* 0 : ack event condition name */ + /* 1 : undefined */ + OBJECT_NAME ackec_name; /* ack event cond name - for */ + /* ackec_name_tag = 0 only */ + SD_END_STRUCT + }; +typedef struct event_enrollment EVENT_ENROLLMENT; + +struct alarm_summary + { + OBJECT_NAME evcon_name; /* event condition name */ + ST_UCHAR severity; /* severity */ + ST_INT16 cur_state; /* current state */ + /* 0 : disabled */ + /* 1 : idle */ + /* 2 : active */ + ST_INT16 unack_state; /* unacknowledged state */ + /* 0 : none */ + /* 1 : active */ + /* 2 : idle */ + /* 3 : both */ + ST_BOOLEAN addl_detail_pres; /* additional detail present */ + ST_INT addl_detail_len; /* length of additional detail */ + ST_UCHAR *addl_detail; /* pointer to additional detail */ + ST_BOOLEAN tta_time_pres; /* transition to active time */ + /* present */ + EVENT_TIME tta_time; /* transition to active time */ + ST_BOOLEAN tti_time_pres; /* transition to idle time */ + /* present */ + EVENT_TIME tti_time; /* transition to idle time */ + SD_END_STRUCT + }; +typedef struct alarm_summary ALARM_SUMMARY; + +struct alarm_enroll_summary + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + ST_BOOLEAN client_app_pres; /* client application present */ + ST_INT client_app_len; /* client application length */ + ST_UCHAR *client_app; /* client application reference */ + ST_UCHAR severity; /* severity */ + ST_INT16 cur_state; /* current state */ + /* 0 : disabled */ + /* 1 : idle */ + /* 2 : active */ + ST_BOOLEAN addl_detail_pres; /* additional detail present */ + ST_INT addl_detail_len; /* length of additional detail */ + ST_UCHAR *addl_detail; /* pointer to additional detail */ + ST_BOOLEAN not_lost; /* notification lost */ + /* (default = false) */ + ST_INT16 alarm_ack_rule; /* alarm acknowledgment rule */ + /* 0 : none */ + /* 1 : simple */ + /* 2 : ack active */ + /* 3 : ack all */ + ST_BOOLEAN ee_state_pres; /* enrollment state present */ + ST_INT16 ee_state; /* enrollment state */ + /* 0 : disabled */ + /* 1 : idle */ + /* 2 : active */ + /* 3 : active, no ack a */ + /* 4 : idle, no ack i */ + /* 5 : idle, no ack a */ + /* 6 : idle, acked */ + /* 7 : active, acked */ + ST_BOOLEAN tta_time_pres; /* transition to active time */ + /* present */ + EVENT_TIME tta_time; /* transition to active time */ + ST_BOOLEAN aack_time_pres; /* active acknowledgment time */ + /* present */ + EVENT_TIME aack_time; /* active acknowledgment time */ + ST_BOOLEAN tti_time_pres; /* transition to idle time */ + /* present */ + EVENT_TIME tti_time; /* transition to idle time */ + ST_BOOLEAN iack_time_pres; /* idle acknowledgment time */ + /* present */ + EVENT_TIME iack_time; /* idle acknowledgment time */ + SD_END_STRUCT + }; +typedef struct alarm_enroll_summary ALARM_ENROLL_SUMMARY; + + +/************************************************************************/ +/************************************************************************/ +/* DEFINE EVENT CONDITION */ +/************************************************************************/ + +/* REQUEST : */ + +struct defec_req_info + { + OBJECT_NAME evcon_name; /* event condition name */ + ST_INT16 eclass; /* event condition class: */ + ST_UCHAR priority; /* priority */ + /* 0 - highest */ + /* 64 - normal (default) */ + /* 127 - lowest */ + ST_UCHAR severity; /* severity (default = 64) */ + ST_BOOLEAN as_reports_pres; /* alarm summaray rpts present */ + ST_BOOLEAN as_reports; /* alarm summaray reports */ + ST_BOOLEAN mon_var_pres; /* monitored variable present */ + VARIABLE_SPEC var_ref; /* variable reference */ + ST_BOOLEAN eval_int_pres; /* evaluation interval present */ + ST_UINT32 eval_interval; /* evaluation interval */ + SD_END_STRUCT + }; +typedef struct defec_req_info DEFEC_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_defec (ST_INT chan, DEFEC_REQ_INFO *info); +ST_RET mp_defec_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_defec (DEFEC_REQ_INFO *info); +ST_RET mpl_defec_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DELETE EVENT CONDITION */ +/************************************************************************/ + +/* REQUEST : */ + +struct delec_req_info + { + ST_INT16 req_tag; /* request tag */ + /* 0 : specific */ + /* 1 : aa specific */ + /* 2 : domain */ + /* 3 : vmd */ + ST_CHAR dname [MAX_IDENT_LEN+1]; /* domain name, if req_tag = 2 */ + ST_INT num_of_names; /* number of names, if tag = 0 */ +/* list of object names */ +/* OBJECT_NAME name_list [num_of_names]; */ + SD_END_STRUCT + }; +typedef struct delec_req_info DELEC_REQ_INFO; + +/* RESPONSE : */ + +struct delec_resp_info + { + ST_UINT32 cand_not_deleted; /* canditates not deleted */ + }; +typedef struct delec_resp_info DELEC_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_delec (ST_INT chan, DELEC_REQ_INFO *info); +ST_RET mp_delec_resp (MMSREQ_IND *ind, DELEC_RESP_INFO *info); +#else +ST_RET mpl_delec (DELEC_REQ_INFO *info); +ST_RET mpl_delec_resp (ST_UINT32 invoke, DELEC_RESP_INFO *info); +#endif + +/************************************************************************/ +/* GET EVENT CONDITION ATTRIBUTES */ +/************************************************************************/ + +/* REQUEST : */ + +struct geteca_req_info + { + OBJECT_NAME evcon_name; /* event condition name */ + }; +typedef struct geteca_req_info GETECA_REQ_INFO; + +/* RESPONSE : */ + +struct geteca_resp_info + { + ST_BOOLEAN mms_deletable; /* mms deletable */ + ST_INT16 eclass; /* event condition class: */ + ST_UCHAR priority; /* priority */ + /* 0 - highest */ + /* 64 - normal (default) */ + /* 127 - lowest */ + ST_UCHAR severity; /* severity */ + /* 0 - highest */ + /* 64 - normal (default) */ + /* 127 - lowest */ + ST_BOOLEAN as_reports; /* alarm summaray reports */ + ST_BOOLEAN mon_var_pres; /* monitored variable present */ + ST_INT16 mon_var_tag; /* monitored variable tag */ + /* 0 : variable reference */ + /* 1 : undefined (NULL) */ + VARIABLE_SPEC var_ref; /* variable reference */ + ST_BOOLEAN eval_int_pres; /* evaluation interval present */ + ST_UINT32 eval_interval; /* evaluation interval */ + SD_END_STRUCT + }; +typedef struct geteca_resp_info GETECA_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_geteca (ST_INT chan, GETECA_REQ_INFO *info); +ST_RET mp_geteca_resp (MMSREQ_IND *ind, GETECA_RESP_INFO *info); +#else +ST_RET mpl_geteca (GETECA_REQ_INFO *info); +ST_RET mpl_geteca_resp (ST_UINT32 invoke, GETECA_RESP_INFO *info); +#endif + +/************************************************************************/ +/* REPORT EVENT CONDITION STATUS */ +/************************************************************************/ + +/* REQUEST : */ + +struct repecs_req_info + { + OBJECT_NAME evcon_name; /* event condition name */ + }; +typedef struct repecs_req_info REPECS_REQ_INFO; + +/* RESPONSE : */ + +struct repecs_resp_info + { + ST_INT16 cur_state; /* event condition state: */ + /* 0 - disabled */ + /* 1 - idle */ + /* 2 - active */ + ST_UINT32 num_of_ev_enroll; /* number of event enrollments */ + ST_BOOLEAN enabled_pres; /* enabled indicator present */ + ST_BOOLEAN enabled; /* enabled indicator */ + ST_BOOLEAN tta_time_pres; /* transition to active present */ + EVENT_TIME tta_time; /* transition to active time */ + ST_BOOLEAN tti_time_pres; /* transition to idle present */ + EVENT_TIME tti_time; /* transition to idle time */ + SD_END_STRUCT + }; +typedef struct repecs_resp_info REPECS_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_repecs (ST_INT chan, REPECS_REQ_INFO *info); +ST_RET mp_repecs_resp (MMSREQ_IND *ind, REPECS_RESP_INFO *info); +#else +ST_RET mpl_repecs (REPECS_REQ_INFO *info); +ST_RET mpl_repecs_resp (ST_UINT32 invoke, REPECS_RESP_INFO *info); +#endif + +/************************************************************************/ +/* ALTER EVENT CONDITION MONITORING */ +/************************************************************************/ + +/* REQUEST : */ + +struct altecm_req_info + { + OBJECT_NAME evcon_name; /* event condition name */ + ST_BOOLEAN enabled_pres; /* enabled present */ + ST_BOOLEAN enabled; /* enabled */ + ST_BOOLEAN priority_pres; /* priority present */ + ST_UCHAR priority; /* priority */ + /* 0 - highest */ + /* 64 - normal */ + /* 127 - lowest */ + ST_BOOLEAN as_reports_pres; /* alarm summaray rpts present */ + ST_BOOLEAN as_reports; /* alarm summaray reports */ + ST_BOOLEAN eval_int_pres; /* evaluation interval present */ + ST_UINT32 eval_int; /* evaluation interval */ + SD_END_STRUCT + }; +typedef struct altecm_req_info ALTECM_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_altecm (ST_INT chan, ALTECM_REQ_INFO *info); +ST_RET mp_altecm_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_altecm (ALTECM_REQ_INFO *info); +ST_RET mpl_altecm_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* TRIGGER EVENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct trige_req_info + { + OBJECT_NAME evcon_name; /* event condition name */ + ST_BOOLEAN priority_pres; /* priority present */ + ST_UCHAR priority; /* priority */ + /* 0 - highest */ + /* 64 - normal */ + /* 127 - lowest */ + SD_END_STRUCT + }; +typedef struct trige_req_info TRIGE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_trige (ST_INT chan, TRIGE_REQ_INFO *info); +ST_RET mp_trige_resp (MMSREQ_IND *info); +#else +ST_RET mpl_trige (TRIGE_REQ_INFO *info); +ST_RET mpl_trige_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DEFINE EVENT ACTION */ +/************************************************************************/ + +/* REQUEST : */ + +struct defea_req_info + { + OBJECT_NAME evact_name; /* event action name */ + ST_INT conf_serv_req_len; /* confirmed service req length */ + ST_UCHAR *conf_serv_req; /* confirmed service request */ + ST_BOOLEAN modlist_pres; /* list of modifiers present */ + ST_INT num_of_modifiers; /* number of modifiers */ + ST_BOOLEAN cs_rdetail_pres; /* CS request detail present */ + ST_INT cs_rdetail_len; /* CS request detail length */ + ST_UCHAR *cs_rdetail; /* CS request detail pointer */ +/* list of modifiers */ +/* MODIFIER mod_list [num_of_modifiers]; */ + SD_END_STRUCT + }; +typedef struct defea_req_info DEFEA_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_defea (ST_INT chan, DEFEA_REQ_INFO *info); +ST_RET mp_defea_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_defea (DEFEA_REQ_INFO *info); +ST_RET mpl_defea_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DELETE EVENT ACTION */ +/************************************************************************/ + +/* REQUEST : */ + +struct delea_req_info + { + ST_INT16 req_tag; /* request tag */ + /* 0 : specific */ + /* 1 : aa specific */ + /* 2 : domain */ + /* 3 : vmd */ + ST_CHAR dname [MAX_IDENT_LEN+1]; /* domain name, if req_tag = 2 */ + ST_INT num_of_names; /* number of names, if tag = 0 */ +/* list of object names */ +/* OBJECT_NAME name_list [num_of_names]; */ + SD_END_STRUCT + }; +typedef struct delea_req_info DELEA_REQ_INFO; + +/* RESPONSE : */ + +struct delea_resp_info + { + ST_UINT32 cand_not_deleted; /* canditates not deleted */ + }; +typedef struct delea_resp_info DELEA_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_delea (ST_INT chan, DELEA_REQ_INFO *info); +ST_RET mp_delea_resp (MMSREQ_IND *ind, DELEA_RESP_INFO *info); +#else +ST_RET mpl_delea (DELEA_REQ_INFO *info); +ST_RET mpl_delea_resp (ST_UINT32 invoke, DELEA_RESP_INFO *info); +#endif + +/************************************************************************/ +/* GET EVENT ACTION ATTRIBUTES */ +/************************************************************************/ + +/* REQUEST : */ + +struct geteaa_req_info + { + OBJECT_NAME evact_name; /* event action name */ + }; +typedef struct geteaa_req_info GETEAA_REQ_INFO; + +/* RESPONSE : */ + +struct geteaa_resp_info + { + ST_BOOLEAN mms_deletable; /* mms deletable (def = false) */ + ST_INT conf_serv_req_len; /* confirmed service req length */ + ST_UCHAR *conf_serv_req; /* confirmed service request */ + ST_BOOLEAN cs_rdetail_pres; /* CS request detail present */ + ST_INT cs_rdetail_len; /* CS request detail length */ + ST_UCHAR *cs_rdetail; /* CS request detail pointer */ + ST_INT num_of_modifiers; /* number of modifiers */ +/* list of modifiers */ +/* MODIFIER mod_list [num_of_modifiers]; */ + SD_END_STRUCT + }; +typedef struct geteaa_resp_info GETEAA_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_geteaa (ST_INT chan, GETEAA_REQ_INFO *info); +ST_RET mp_geteaa_resp (MMSREQ_IND *ind, GETEAA_RESP_INFO *info); +#else +ST_RET mpl_geteaa (GETEAA_REQ_INFO *info); +ST_RET mpl_geteaa_resp (ST_UINT32 invoke, GETEAA_RESP_INFO *info); +#endif + +/************************************************************************/ +/* REPORT EVENT ACTION STATUS */ +/************************************************************************/ + +/* REQUEST : */ + +struct repeas_req_info + { + OBJECT_NAME evact_name; /* event action name */ + }; +typedef struct repeas_req_info REPEAS_REQ_INFO; + +/* RESPONSE : */ + +struct repeas_resp_info + { + ST_UINT32 num_of_ev_enroll; /* number of event enrollments */ + }; +typedef struct repeas_resp_info REPEAS_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_repeas (ST_INT chan, REPEAS_REQ_INFO *info); +ST_RET mp_repeas_resp (MMSREQ_IND *ind, REPEAS_RESP_INFO *info); +#else +ST_RET mpl_repeas (REPEAS_REQ_INFO *info); +ST_RET mpl_repeas_resp (ST_UINT32 invoke, REPEAS_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DEFINE EVENT ENROLLMENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct defee_req_info + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + OBJECT_NAME evcon_name; /* event condition name */ + ST_UCHAR ec_transitions; /* causing transitions: */ + /* bitstring */ + /* 0 : idle to disabled */ + /* 1 : active to disabled */ + /* 2 : disabled to idle */ + /* 3 : active to idle */ + /* 4 : disabled to active */ + /* 5 : idle to active */ + /* 6 : any to deleted */ + ST_INT16 alarm_ack_rule; /* alarm acknowledgment rule */ + /* 0 : none */ + /* 1 : simple */ + /* 2 : ack active */ + /* 3 : ack all */ + ST_BOOLEAN evact_name_pres; /* event action name present */ + OBJECT_NAME evact_name; /* event action name */ + ST_BOOLEAN client_app_pres; /* client application present */ + ST_INT client_app_len; /* client application length */ + ST_UCHAR *client_app; /* client application reference */ + ST_BOOLEAN ackec_name_pres; /* ack event cond name present */ + OBJECT_NAME ackec_name; /* acknowledge event cond name */ + SD_END_STRUCT + }; +typedef struct defee_req_info DEFEE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_defee (ST_INT chan, DEFEE_REQ_INFO *info); +ST_RET mp_defee_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_defee (DEFEE_REQ_INFO *info); +ST_RET mpl_defee_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DELETE EVENT ENROLLMENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct delee_req_info + { + ST_INT16 req_tag; /* request tag */ + /* 0 : specific */ + /* 1 : event condition */ + /* 2 : event action */ + union + { + OBJECT_NAME evcon_name; /* event condition name */ + OBJECT_NAME evact_name; /* event action name */ + ST_INT num_of_names; /* number of object names */ + } sod; +/* list of object names */ +/* OBJECT_NAME name_list [num_of_names]; */ + SD_END_STRUCT + }; +typedef struct delee_req_info DELEE_REQ_INFO; + +/* RESPONSE : */ + +struct delee_resp_info + { + ST_UINT32 cand_not_deleted; /* canditates not deleted */ + }; +typedef struct delee_resp_info DELEE_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_delee (ST_INT chan, DELEE_REQ_INFO *info); +ST_RET mp_delee_resp (MMSREQ_IND *ind, DELEE_RESP_INFO *info); +#else +ST_RET mpl_delee (DELEE_REQ_INFO *info); +ST_RET mpl_delee_resp (ST_UINT32 invoke, DELEE_RESP_INFO *info); +#endif + +/************************************************************************/ +/* GET EVENT ENROLLMENT ATTRIBUTES */ +/************************************************************************/ + +/* REQUEST : */ + +struct geteea_req_info + { + ST_INT16 scope_of_req; /* scope of request */ + /* 0 : specific */ + /* 1 : client (default) */ + /* 2 : event condition */ + /* 3 : event action */ + ST_BOOLEAN client_app_pres; /* client application present */ + ST_INT client_app_len; /* client application length */ + ST_UCHAR *client_app; /* client application reference */ + ST_BOOLEAN evcon_name_pres; /* event condition name present */ + OBJECT_NAME evcon_name; /* event condition name */ + ST_BOOLEAN evact_name_pres; /* event action name present */ + OBJECT_NAME evact_name; /* event action name */ + ST_BOOLEAN ca_name_pres; /* continue after name present */ + OBJECT_NAME ca_name; /* continue after name */ + ST_BOOLEAN eenames_pres; /* event enroll names present */ + ST_INT num_of_eenames; /* number of event enroll names */ +/* list of event enroll names */ +/* OBJECT_NAME name_list [num_of_eenames]; */ + SD_END_STRUCT + }; +typedef struct geteea_req_info GETEEA_REQ_INFO; + +/* RESPONSE : */ + +struct geteea_resp_info + { + ST_BOOLEAN more_follows; /* default = false */ + ST_INT num_of_evenroll; /* number of event enrollments */ +/* list of event enrollments */ +/* EVENT_ENROLLMENT evenroll_list [num_of_evenroll]; */ + SD_END_STRUCT + }; +typedef struct geteea_resp_info GETEEA_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_geteea (ST_INT chan, GETEEA_REQ_INFO *info); +ST_RET mp_geteea_resp (MMSREQ_IND *ind, GETEEA_RESP_INFO *info); +#else +ST_RET mpl_geteea (GETEEA_REQ_INFO *info); +ST_RET mpl_geteea_resp (ST_UINT32 invoke, GETEEA_RESP_INFO *info); +#endif + +/************************************************************************/ +/* REPORT EVENT ENROLLMENT STATUS */ +/************************************************************************/ + +/* REQUEST : */ + +struct repees_req_info + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + }; +typedef struct repees_req_info REPEES_REQ_INFO; + +/* RESPONSE : */ + +struct repees_resp_info + { + ST_UCHAR ec_transitions; /* event condition transitions: */ + /* bitstring */ + /* 0 : idle to disabled */ + /* 1 : active to disabled */ + /* 2 : disabled to idle */ + /* 3 : active to idle */ + /* 4 : disabled to active */ + /* 5 : idle to active */ + /* 6 : any to deleted */ + ST_UCHAR not_lost; /* notification lost */ + /* (default = false) */ + ST_INT16 duration; /* duration: */ + /* 0 - current (default) */ + /* 1 - permanent */ + ST_BOOLEAN alarm_ack_rule_pres; /* alarm ack rule present */ + ST_INT16 alarm_ack_rule; /* alarm acknowledgment rule */ + /* 0 : none */ + /* 1 : simple */ + /* 2 : ack active */ + /* 3 : ack all */ + ST_INT16 cur_state; /* current state */ + /* 0 : disabled */ + /* 1 : idle */ + /* 2 : active */ + /* 3 : active, no ack a */ + /* 4 : idle, no ack i */ + /* 5 : idle, no ack a */ + /* 6 : idle, acked */ + /* 7 : active, acked */ + }; +typedef struct repees_resp_info REPEES_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_repees (ST_INT chan, REPEES_REQ_INFO *info); +ST_RET mp_repees_resp (MMSREQ_IND *ind, REPEES_RESP_INFO *info); +#else +ST_RET mpl_repees (REPEES_REQ_INFO *info); +ST_RET mpl_repees_resp (ST_UINT32 invoke, REPEES_RESP_INFO *info); +#endif + +/************************************************************************/ +/* ALTER EVENT ENROLLMENT */ +/************************************************************************/ + +/* REQUEST : */ + +struct altee_req_info + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + ST_BOOLEAN ec_transitions_pres; /* ec transitions present */ + ST_UCHAR ec_transitions; /* event condition transitions: */ + /* bitstring */ + /* 0 : idle to disabled */ + /* 1 : active to disabled */ + /* 2 : disabled to idle */ + /* 3 : active to idle */ + /* 4 : disabled to active */ + /* 5 : idle to active */ + /* 6 : any to deleted */ + ST_BOOLEAN alarm_ack_rule_pres; /* alarm ack rule present */ + ST_INT16 alarm_ack_rule; /* alarm acknowledgment rule */ + /* 0 : none */ + /* 1 : simple */ + /* 2 : ack active */ + /* 3 : ack all */ + SD_END_STRUCT + }; +typedef struct altee_req_info ALTEE_REQ_INFO; + +/* RESPONSE : */ + +struct altee_resp_info + { + ST_INT16 cur_state_tag; /* current state tag */ + /* 0 : state */ + /* 1 : undefined */ + ST_INT16 state; /* state, if cur_state_tag = 0 */ + /* 0 : disabled */ + /* 1 : idle */ + /* 2 : active */ + /* 3 : active, no ack a */ + /* 4 : idle, no ack i */ + /* 5 : idle, no ack a */ + /* 6 : idle, acked */ + /* 7 : active, acked */ + EVENT_TIME trans_time; /* transition time */ + SD_END_STRUCT + }; +typedef struct altee_resp_info ALTEE_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_altee (ST_INT chan, ALTEE_REQ_INFO *info); +ST_RET mp_altee_resp (MMSREQ_IND *ind, ALTEE_RESP_INFO *info); +#else +ST_RET mpl_altee (ALTEE_REQ_INFO *info); +ST_RET mpl_altee_resp (ST_UINT32 invoke, ALTEE_RESP_INFO *info); +#endif + +/************************************************************************/ +/* EVENT NOTIFICATION, Conformance: MCW1 (EVN3) */ +/************************************************************************/ + +/* REQUEST : */ + +struct evnot_req_info + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + OBJECT_NAME evcon_name; /* event condition name */ + ST_UCHAR severity; /* severity */ + ST_BOOLEAN cur_state_pres; /* current state enable */ + ST_INT16 cur_state; /* current state */ + /* 0 : disabled */ + /* 1 : idle */ + /* 2 : active */ + EVENT_TIME trans_time; /* transition time */ + ST_UCHAR not_lost; /* notification lost */ + /* (default = false) */ + ST_BOOLEAN alarm_ack_rule_pres; /* alarm acknowledge rule pres */ + ST_INT16 alarm_ack_rule; /* alarm acknowledgment rule */ + /* 0 : none */ + /* 1 : simple */ + /* 2 : ack-active */ + /* 3 : ack-all */ + ST_BOOLEAN evact_result_pres; /* action result present */ + OBJECT_NAME evact_name; /* event action name */ + ST_INT16 evact_result_tag; /* event action result tag */ + /* 0 : success */ + /* 1 : failure */ + ST_INT conf_serv_resp_len; /* success: conf serv resp len */ + ST_UCHAR *conf_serv_resp; /* success: conf serv resp ptr */ + ST_BOOLEAN cs_rdetail_pres; /* success: CS resp detail pres */ + ST_INT cs_rdetail_len; /* success: CS resp detail len */ + ST_UCHAR *cs_rdetail; /* success: CS resp detail ptr */ + + ST_BOOLEAN mod_pos_pres; /* failure: mod pos present */ + ST_UINT32 mod_pos; /* failure: modifier position */ + ERR_INFO *serv_err; /* failure: service error ptr */ + + SD_END_STRUCT + }; +typedef struct evnot_req_info EVNOT_REQ_INFO; + +/* RESPONSE : NONE (unconfirmed) */ + +#ifndef MMS_LITE +ST_RET mp_evnot (ST_INT chan, EVNOT_REQ_INFO *info); +#else +ST_RET mpl_evnot (ASN1_ENC_CTXT *aCtx, EVNOT_REQ_INFO *info); +#endif + +/************************************************************************/ +/* ACKNOWLEDGE EVENT NOTIFICATION, Conformance: MCW1 (EVN3) */ +/************************************************************************/ + +/* REQUEST : */ + +struct ackevnot_req_info + { + OBJECT_NAME evenroll_name; /* event enrollment name */ + ST_INT16 ack_state; /* acknowledge state */ + EVENT_TIME evtime; /* event time */ + ST_BOOLEAN ackec_name_pres; /* ack event cond name present */ + OBJECT_NAME ackec_name; /* acknowledge event cond name */ + }; +typedef struct ackevnot_req_info ACKEVNOT_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_ackevnot (ST_INT chan, ACKEVNOT_REQ_INFO *info); +ST_RET mp_ackevnot_resp (MMSREQ_IND *info); +#else +ST_RET mpl_ackevnot (ACKEVNOT_REQ_INFO *info); +ST_RET mpl_ackevnot_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET ALARM SUMMARY, Conformance: EVN5 */ +/************************************************************************/ + +/* REQUEST : */ + +struct getas_req_info + { + ST_BOOLEAN enroll_only; /* enrollments only */ + /* (default = true) */ + ST_BOOLEAN act_alarms_only; /* active alarms only */ + /* (default = true) */ + ST_INT16 ack_filter; /* acknowledgement filter */ + /* 0 : not acked (default) */ + /* 1 : acked */ + /* 2 : all */ + /* severity filter */ + ST_UCHAR most_sev_filter; /* most severe (default=0) */ + ST_UCHAR least_sev_filter; /* least severe (default=127) */ + ST_BOOLEAN ca_pres; /* continue after name present */ + OBJECT_NAME ca_name; /* continue after name */ + }; +typedef struct getas_req_info GETAS_REQ_INFO; + +/* RESPONSE : */ + +struct getas_resp_info + { + ST_BOOLEAN more_follows; /* default = false */ + ST_INT num_of_alarm_sum; /* number of alarm summary */ +/* list of alarm summary data */ +/* ALARM_SUMMARY alarm_sum [num_of_alarm_sum]; */ + SD_END_STRUCT + }; +typedef struct getas_resp_info GETAS_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getas (ST_INT chan, GETAS_REQ_INFO *info); +ST_RET mp_getas_resp (MMSREQ_IND *ind, GETAS_RESP_INFO *info); +#else +ST_RET mpl_getas (GETAS_REQ_INFO *info); +ST_RET mpl_getas_resp (ST_UINT32 invoke, GETAS_RESP_INFO *info); +#endif + +/************************************************************************/ +/* GET ALARM ENROLLMENT SUMMARY */ +/************************************************************************/ + +/* REQUEST : */ + +struct getaes_req_info + { + ST_BOOLEAN enroll_only; /* enrollments only */ + /* (default = true) */ + ST_BOOLEAN act_alarms_only; /* active alarms only */ + /* (default = true) */ + ST_INT16 ack_filter; /* acknowledgement filter */ + /* 0 : not acked (default) */ + /* 1 : acked */ + /* 2 : all */ + /* severity filter */ + ST_UCHAR most_sev_filter; /* most severe (default=0) */ + ST_UCHAR least_sev_filter; /* least severe (default=127) */ + ST_BOOLEAN ca_name_pres; /* continue after name present */ + OBJECT_NAME ca_name; /* continue after name */ + }; +typedef struct getaes_req_info GETAES_REQ_INFO; + +/* RESPONSE : */ + +struct getaes_resp_info + { + ST_BOOLEAN more_follows; /* default = false */ + ST_INT num_of_alarm_esum; /* # of alarm enroll summary */ +/* list of alarm enroll summary */ +/* ALARM_ENROLL_SUMMARY alarm_enroll_sum [num_of_alarm_esum]; */ + SD_END_STRUCT + }; +typedef struct getaes_resp_info GETAES_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getaes (ST_INT chan, GETAES_REQ_INFO *info); +ST_RET mp_getaes_resp (MMSREQ_IND *ind, GETAES_RESP_INFO *info); +#else +ST_RET mpl_getaes (GETAES_REQ_INFO *info); +ST_RET mpl_getaes_resp (ST_UINT32 invoke, GETAES_RESP_INFO *info); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PEVN_INCLUDED */ diff --git a/mmslib/inc/mms_pfil.h b/mmslib/inc/mms_pfil.h new file mode 100644 index 0000000..f1cf773 --- /dev/null +++ b/mmslib/inc/mms_pfil.h @@ -0,0 +1,297 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pfil.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS file services at the primitive */ +/* level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PFIL_INCLUDED +#define MMS_PFIL_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_mp.h" + +/************************************************************************/ +/************************************************************************/ +/* FILE MANAGEMENT SERVICES */ +/************************************************************************/ +/* The structures below are used to pass FILE MANAGEMENT information */ +/* to/from the MMS primitives. */ +/************************************************************************/ + +#define MFSTAT_NO_ACT 0 +#define MFSTAT_PEND_OPEN 1 +#define MFSTAT_OPENED 2 +#define MFSTAT_PEND_CLOSE 3 + +/************************************************************************/ +/* OBTAIN FILE, Conformance: FIL1 */ +/************************************************************************/ + +/* REQUEST : */ + +struct obtfile_req_info + { + ST_BOOLEAN ar_title_pres; /* application title present */ + ST_INT ar_len; /* length of app proc title */ + ST_UCHAR *ar_title; /* application process title */ + ST_INT num_of_src_fname; /* num of source fname elements */ + ST_INT num_of_dest_fname; /* num of dest. fname elements */ +/* list of source file names */ +/* FILE_NAME src_fname_list[ num_of_src_fname ]; */ +/* list of dest. file names */ +/* FILE_NAME dest_fname_list[ num_of_dest_fname ]; */ + SD_END_STRUCT + }; +typedef struct obtfile_req_info OBTFILE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_obtfile (ST_INT chan, OBTFILE_REQ_INFO *info); +ST_RET mp_obtfile_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_obtfile (OBTFILE_REQ_INFO *info); +ST_RET mpl_obtfile_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* FILE OPEN, Conformance: FIL2 */ +/************************************************************************/ + +/* REQUEST : */ + +struct fopen_req_info + { + ST_INT num_of_fname; /* num of fname elements */ + ST_UINT32 init_pos; /* initial position */ +/* list of file names */ +/* FILE_NAME fname_list[ num_of_fname ]; */ + SD_END_STRUCT + }; +typedef struct fopen_req_info FOPEN_REQ_INFO; + +/* RESPONSE : */ + +struct file_attr + { + ST_UINT32 fsize; /* file size (# bytes) */ + ST_BOOLEAN mtimpres; /* last modified time present */ + time_t mtime; /* last modified time */ + }; +typedef struct file_attr FILE_ATTR; + +struct fopen_resp_info + { + ST_INT32 frsmid; /* file read state machine ID */ + FILE_ATTR ent; /* file attributes */ + }; +typedef struct fopen_resp_info FOPEN_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_fopen (ST_INT chan, FOPEN_REQ_INFO *info); +ST_RET mp_fopen_resp (MMSREQ_IND *ind, FOPEN_RESP_INFO *info); +#else +ST_RET mpl_fopen (FOPEN_REQ_INFO *info); +ST_RET mpl_fopen_resp (ST_UINT32 invoke, FOPEN_RESP_INFO *info); +#endif + +/************************************************************************/ +/* FILE READ, Conformance: FIL2 */ +/************************************************************************/ + +/* REQUEST : */ + +struct fread_req_info + { + ST_INT32 frsmid; /* file read state maching ID */ + }; +typedef struct fread_req_info FREAD_REQ_INFO; + +/* RESPONSE : */ + +struct fread_resp_info + { + ST_INT fd_len; /* length of file data octets */ + ST_UCHAR *filedata; /* pointer to file data octets */ + ST_BOOLEAN more_follows; /* additional file content */ + /* default: SD_TRUE */ + SD_END_STRUCT + }; +typedef struct fread_resp_info FREAD_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_fread (ST_INT chan,FREAD_REQ_INFO *info); +ST_RET mp_fread_resp (MMSREQ_IND *ind, FREAD_RESP_INFO *info); +#else +ST_RET mpl_fread (FREAD_REQ_INFO *info); +ST_RET mpl_fread_resp (ST_UINT32 invoke, FREAD_RESP_INFO *info); +#endif + +/************************************************************************/ +/* FILE CLOSE, Conformance: FIL2 */ +/************************************************************************/ + +/* REQUEST : */ + +struct fclose_req_info + { + ST_INT32 frsmid; /* file read state maching ID */ + }; +typedef struct fclose_req_info FCLOSE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_fclose (ST_INT chan, FCLOSE_REQ_INFO *info); +ST_RET mp_fclose_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_fclose (FCLOSE_REQ_INFO *info); +ST_RET mpl_fclose_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* FILE RENAME, Conformance: FIL3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct frename_req_info + { + ST_INT num_of_cur_fname; /* num of current fname elements*/ + ST_INT num_of_new_fname; /* num of new fname elements */ +/* list of current file names */ +/* FILE_NAME cur_fname_list[ num_of_cur_fname ]; */ +/* list of new file names */ +/* FILE_NAME new_fname_list[ num_of_new_fname ]; */ + SD_END_STRUCT + }; +typedef struct frename_req_info FRENAME_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_frename (ST_INT chan, FRENAME_REQ_INFO *info); +ST_RET mp_frename_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_frename (FRENAME_REQ_INFO *info); +ST_RET mpl_frename_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* FILE DELETE, Conformance: FIL3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct fdelete_req_info + { + ST_INT num_of_fname; /* num of fname elements */ +/* list of file names */ +/* FILE_NAME fname_list[ num_of_fname ]; */ + SD_END_STRUCT + }; +typedef struct fdelete_req_info FDELETE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_fdelete (ST_INT chan, FDELETE_REQ_INFO *info); +ST_RET mp_fdelete_resp (MMSREQ_IND *info); +#else +ST_RET mpl_fdelete (FDELETE_REQ_INFO *info); +ST_RET mpl_fdelete_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* FILE DIRECTORY, Conformance: FIL3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct fdir_req_info + { + ST_BOOLEAN filespec_pres; /* file specification present */ + ST_BOOLEAN cont_after_pres; /* continue after name present */ + ST_INT num_of_fs_fname; /* num of fname elements */ + ST_INT num_of_ca_fname; /* num of cont after elements */ +/* list of current file names */ +/* FILE_NAME fs_fname_list[ num_of_fs_fname ]; */ +/* list of new file names */ +/* FILE_NAME ca_fname_list[ num_of_ca_fname ]; */ + SD_END_STRUCT + }; +typedef struct fdir_req_info FDIR_REQ_INFO; + +/* RESPONSE : */ + +struct fdir_dir_ent + { + ST_UINT32 fsize; /* file size (# bytes) */ + ST_BOOLEAN mtimpres; /* last modified time present */ + time_t mtime; /* last modified time */ + ST_INT num_of_fname; /* num of fname elements */ +/* list of file names */ +/* FILE_NAME fname_list[ num_of_fname ]; */ + SD_END_STRUCT + }; +typedef struct fdir_dir_ent FDIR_DIR_ENT; + +struct fdir_resp_info + { + ST_INT num_dir_ent; /* number of directory entries */ + ST_BOOLEAN more_follows; /* more dir entries follow */ + /* default: SD_FALSE */ +/* list of directory entries */ +/* FDIR_DIR_ENT dir_ent_list [num_dir_ent] */ + SD_END_STRUCT + }; +typedef struct fdir_resp_info FDIR_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_fdir (ST_INT chan,FDIR_REQ_INFO *info); +ST_RET mp_fdir_resp (MMSREQ_IND *ind, FDIR_RESP_INFO *info); +#else +ST_RET mpl_fdir (FDIR_REQ_INFO *info); +ST_RET mpl_fdir_resp (ST_UINT32 invoke, FDIR_RESP_INFO *info); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PFIL_INCLUDED */ + + diff --git a/mmslib/inc/mms_pjou.h b/mmslib/inc/mms_pjou.h new file mode 100644 index 0000000..3c7ea62 --- /dev/null +++ b/mmslib/inc/mms_pjou.h @@ -0,0 +1,299 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pjou.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS journal management services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/15/98 MDE 03 Added entry_form_tag defines */ +/* 08/15/97 MDE 02 BTOD handling changes */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PJOU_INCLUDED +#define MMS_PJOU_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_pvar.h" +#include "mms_mp.h" + +/************************************************************************/ +/************************************************************************/ +/* JOURNAL MANAGEMENT SERVICES */ +/************************************************************************/ +/* The structures below are used to pass JOURNAL MANAGEMENT information */ +/* to/from the MMS primitives. */ +/************************************************************************/ + +/* entry_form_tag value defines */ +#define JE_FORM_DATA 2 +#define JE_FORM_ANNOTATION 3 + +struct var_info + { + ST_CHAR *var_tag; /* variable tag */ + VAR_ACC_DATA value_spec; /* value specification data */ + }; +typedef struct var_info VAR_INFO; + +struct entry_content + { + MMS_BTOD occur_time; /* occurrence time */ + ST_BOOLEAN addl_detail_pres; /* additional detail present */ + ST_INT addl_detail_len; /* length of additional detail */ + ST_UCHAR *addl_detail; /* pointer to additional detail */ + ST_INT16 entry_form_tag; /* entry form tag */ + union + { + struct /* entry form is DATA */ + { + ST_BOOLEAN event_pres; /* event present */ + OBJECT_NAME evcon_name; /* event condition name */ + ST_INT16 cur_state; /* current state */ + /* 0 : disabled */ + /* 1 : idle */ + /* 2 : active */ + ST_BOOLEAN list_of_var_pres; /* list of variables present */ + ST_INT num_of_var; /* number of variables */ + } data; + ST_CHAR *annotation; /* pointer to annotation */ + }ef; +/* for form == DATA, need a */ +/* list of variables */ +/* VAR_INFO list_of_var [num_of_var]; */ + SD_END_STRUCT + }; +typedef struct entry_content ENTRY_CONTENT; + +struct journal_entry + { + ST_INT entry_id_len; /* length of entry identifier */ + ST_UCHAR *entry_id; /* ptr to entry identifier */ + ST_INT orig_ae_len; /* originating app entity len */ + ST_UCHAR *orig_ae; /* originating app entity */ + ENTRY_CONTENT ent_content; /* entry content */ + }; +typedef struct journal_entry JOURNAL_ENTRY; + +/************************************************************************/ +/* READ JOURNAL, Conformance: JOU2 */ +/************************************************************************/ + +/* REQUEST : */ + +struct jread_req_info + { + OBJECT_NAME jou_name; /* journal name */ + ST_BOOLEAN range_start_pres; /* range start spec present */ + ST_INT16 start_tag; /* start tag */ + /* 0 - starting time */ + /* 1 - starting entry */ + MMS_BTOD start_time; /* range starting time */ + ST_INT start_entry_len; /* length of starting entry */ + ST_UCHAR *start_entry; /* pointer to starting entry */ + ST_BOOLEAN range_stop_pres; /* range stop spec present */ + ST_INT16 stop_tag; /* stop tag */ + /* 0 - ending time */ + /* 1 - number of entries */ + MMS_BTOD end_time; /* range ending time */ + ST_INT32 num_of_entries; /* number of entries */ + ST_BOOLEAN list_of_var_pres; /* list of variables present */ + ST_INT num_of_var; /* number of variables */ + ST_BOOLEAN sa_entry_pres; /* start after entry present */ + MMS_BTOD time_spec; /* time specification */ + ST_INT entry_spec_len; /* entry specification length */ + ST_UCHAR *entry_spec; /* entry specification */ +/* list of pointers to variables*/ +/* ST_CHAR *list_of_var [num_of_var]; */ + SD_END_STRUCT + }; +typedef struct jread_req_info JREAD_REQ_INFO; + +/* RESPONSE : */ + +struct jread_resp_info + { + ST_INT num_of_jou_entry; /* number of journal entries */ + ST_BOOLEAN more_follows; /* default = false */ +/* list of journal entries */ +/* JOURNAL_ENTRY list_of_jou_entry [num_of_jou_entry]; */ + SD_END_STRUCT + }; +typedef struct jread_resp_info JREAD_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_jread (ST_INT chan, JREAD_REQ_INFO *info); +ST_RET mp_jread_resp (MMSREQ_IND *ind, JREAD_RESP_INFO *info); +#else +ST_RET mpl_jread (JREAD_REQ_INFO *info); +ST_RET mpl_jread_resp (ST_UINT32 invoke, JREAD_RESP_INFO *info); +#endif + +/************************************************************************/ +/* WRITE JOURNAL, Conformance: JOU1 */ +/************************************************************************/ + +/* REQUEST : */ + +struct jwrite_req_info + { + OBJECT_NAME jou_name; /* journal name */ + ST_INT num_of_jou_entry; /* number of journal entries */ +/* list of journal entries */ +/* ENTRY_CONTENT list_of_jou_entry [num_of_jou_entry]; */ + SD_END_STRUCT + }; +typedef struct jwrite_req_info JWRITE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_jwrite (ST_INT chan, JWRITE_REQ_INFO *info); +ST_RET mp_jwrite_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_jwrite (JWRITE_REQ_INFO *info); +ST_RET mpl_jwrite_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* INITIALIZE JOURNAL, Conformance: JOU2 */ +/************************************************************************/ + +/* REQUEST : */ + +struct jinit_req_info + { + OBJECT_NAME jou_name; /* journal name */ + ST_BOOLEAN limit_spec_pres; /* limit specification present */ + MMS_BTOD limit_time; /* limiting time */ + ST_BOOLEAN limit_entry_pres; /* limiting entry present */ + ST_INT limit_entry_len; /* length of limiting entry */ + ST_UCHAR *limit_entry; /* pointer to limiting entry */ + SD_END_STRUCT + }; +typedef struct jinit_req_info JINIT_REQ_INFO; + +/* RESPONSE : */ + +struct jinit_resp_info + { + ST_UINT32 del_entries; /* deleted entries */ + }; +typedef struct jinit_resp_info JINIT_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_jinit (ST_INT chan, JINIT_REQ_INFO *info); +ST_RET mp_jinit_resp (MMSREQ_IND *ind, JINIT_RESP_INFO *info); +#else +ST_RET mpl_jinit (JINIT_REQ_INFO *info); +ST_RET mpl_jinit_resp (ST_UINT32 invoke, JINIT_RESP_INFO *info); +#endif + +/************************************************************************/ +/* REPORT JOURNAL STATUS, Conformance: JOU2 */ +/************************************************************************/ + +/* REQUEST : */ + +struct jstat_req_info + { + OBJECT_NAME jou_name; /* journal name */ + }; +typedef struct jstat_req_info JSTAT_REQ_INFO; + +/* RESPONSE : */ + +struct jstat_resp_info + { + ST_UINT32 cur_entries; /* current entries */ + ST_BOOLEAN mms_deletable; /* MMS deletable */ + SD_END_STRUCT + }; +typedef struct jstat_resp_info JSTAT_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_jstat (ST_INT chan, JSTAT_REQ_INFO *info); +ST_RET mp_jstat_resp (MMSREQ_IND *ind, JSTAT_RESP_INFO *info); +#else +ST_RET mpl_jstat (JSTAT_REQ_INFO *info); +ST_RET mpl_jstat_resp (ST_UINT32 invoke, JSTAT_RESP_INFO *info); +#endif + +/************************************************************************/ +/* CREATE JOURNAL */ +/************************************************************************/ + +/* REQUEST : */ + +struct jcreate_req_info + { + OBJECT_NAME jou_name; /* journal name */ + }; +typedef struct jcreate_req_info JCREATE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_jcreate (ST_INT chan, JCREATE_REQ_INFO *info); +ST_RET mp_jcreate_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_jcreate (JCREATE_REQ_INFO *info); +ST_RET mpl_jcreate_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DELETE JOURNAL */ +/************************************************************************/ + +/* REQUEST : */ + +struct jdelete_req_info + { + OBJECT_NAME jou_name; /* journal name */ + }; +typedef struct jdelete_req_info JDELETE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_jdelete (ST_INT chan, JDELETE_REQ_INFO *info); +ST_RET mp_jdelete_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_jdelete (JDELETE_REQ_INFO *info); +ST_RET mpl_jdelete_resp (ST_UINT32 invoke); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PJOU_INCLUDED */ diff --git a/mmslib/inc/mms_pocs.h b/mmslib/inc/mms_pocs.h new file mode 100644 index 0000000..b52bff2 --- /dev/null +++ b/mmslib/inc/mms_pocs.h @@ -0,0 +1,120 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pocs.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS operator communication services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_POCS_INCLUDED +#define MMS_POCS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_mp.h" + +/************************************************************************/ +/************************************************************************/ +/* OPERATOR COMMUNICATION FUNCTIONS */ +/************************************************************************/ +/* The structures below are used to pass OPERATOR COMMUNICATION */ +/* operation information to/from the MMS primitives. */ +/************************************************************************/ + +/************************************************************************/ +/* OUTPUT OPERATION, Conformance: OCS1 */ +/************************************************************************/ + +/* REQUEST : */ + +struct output_req_info + { + ST_CHAR station_name [MAX_IDENT_LEN+1]; /* operator station name */ + ST_INT data_count; /* number of data strings */ +/* list of pointers to the output data */ +/* ST_CHAR *output_data [data_count]; */ + SD_END_STRUCT + }; +typedef struct output_req_info OUTPUT_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_output (ST_INT chan, OUTPUT_REQ_INFO *info); +ST_RET mp_output_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_output (OUTPUT_REQ_INFO *info); +ST_RET mpl_output_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* INPUT OPERATION, Conformance: OCS2 */ +/************************************************************************/ + +/* REQUEST : */ + +struct input_req_info + { + ST_CHAR station_name [MAX_IDENT_LEN+1]; /* operator station name */ + ST_BOOLEAN echo; /* echo, default: SD_TRUE */ + ST_BOOLEAN timeout_pres; /* input timeout present ind */ + ST_UINT32 timeout; /* input timeout */ + ST_BOOLEAN prompt_pres; /* prompt data present ind */ + ST_INT prompt_count; /* number of prompt strings */ +/* list of pointers to the prompt data */ +/* ST_CHAR *prompt_data [prompt_count]; */ + SD_END_STRUCT + }; +typedef struct input_req_info INPUT_REQ_INFO; + +/* RESPONSE : */ + +struct input_resp_info + { + ST_CHAR *input_resp; /* input response */ + }; +typedef struct input_resp_info INPUT_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_input (ST_INT chan, INPUT_REQ_INFO *info); +ST_RET mp_input_resp (MMSREQ_IND *ind, INPUT_RESP_INFO *info); +#else +ST_RET mpl_input (INPUT_REQ_INFO *info); +ST_RET mpl_input_resp (ST_UINT32 invoke, INPUT_RESP_INFO *info); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_POCS_INCLUDED */ diff --git a/mmslib/inc/mms_pprg.h b/mmslib/inc/mms_pprg.h new file mode 100644 index 0000000..b2259c1 --- /dev/null +++ b/mmslib/inc/mms_pprg.h @@ -0,0 +1,287 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pprg.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS program invocation management */ +/* services at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/14/97 RKR 02 Format changes */ +/* 06/09/97 MDE 01 Added PI State defines (from mms_vprg.h) */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PPRG_INCLUDED +#define MMS_PPRG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/************************************************************************/ +/* PROGRAM INVOCATION MANAGEMENT SERVICES */ +/************************************************************************/ +/* The structures below are used to pass PROGRAM INVOCATION MANAGEMENT */ +/* information to/from the MMS primitives. */ +/************************************************************************/ +/* use these defines to determine whether string is simple or encoded */ +/* If encoded, the data pointer points to a complete ASN.1 EXTERNAL */ + +#define ARG_TYPE_SIMPLE 0 +#define ARG_TYPE_ENCODED 1 + +/************************************************************************/ +/* CREATE PROGRAM INVOCATION */ +/************************************************************************/ + +/* REQUEST : */ + +struct crepi_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + ST_INT num_of_dnames; /* number of domain names */ + ST_BOOLEAN reusable; + ST_BOOLEAN monitor_pres; /* monitoring present */ + ST_BOOLEAN monitor; /* SD_TRUE : permanent monitoring */ + /* SD_FALSE: current monitoring */ + +/* list of ptrs to domain names */ +/* ST_CHAR *dnames_list [num_of_dnames]; */ + SD_END_STRUCT + }; +typedef struct crepi_req_info CREPI_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_crepi (ST_INT chan, CREPI_REQ_INFO *info); +ST_RET mp_crepi_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_crepi (CREPI_REQ_INFO *info); +ST_RET mpl_crepi_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DELETE PROGRAM INVOCATION */ +/************************************************************************/ + +/* REQUEST : */ + +struct delpi_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + }; +typedef struct delpi_req_info DELPI_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_delpi (ST_INT chan, DELPI_REQ_INFO *info); +ST_RET mp_delpi_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_delpi (DELPI_REQ_INFO *info); +ST_RET mpl_delpi_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* START */ +/************************************************************************/ + +/* REQUEST : */ + +struct start_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + + ST_INT16 start_arg_type; /* start argument present */ + ST_BOOLEAN start_arg_pres; /* start argument present */ + ST_INT start_arg_len; /* Only used for ENCODED */ + ST_UCHAR *start_arg; /* pointer to start argument */ + SD_END_STRUCT + }; +typedef struct start_req_info START_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_start (ST_INT chan, START_REQ_INFO *info); +ST_RET mp_start_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_start (START_REQ_INFO *info); +ST_RET mpl_start_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* STOP */ +/************************************************************************/ + +/* REQUEST : */ + +struct stop_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + }; +typedef struct stop_req_info STOP_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_stop (ST_INT chan, STOP_REQ_INFO *info); +ST_RET mp_stop_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_stop (STOP_REQ_INFO *info); +ST_RET mpl_stop_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* RESUME */ +/************************************************************************/ + +/* REQUEST : */ + +struct resume_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + + ST_INT16 resume_arg_type; /* resume argument present */ + ST_BOOLEAN resume_arg_pres; /* resume argument present */ + ST_INT resume_arg_len; /* Only used for ENCODED */ + ST_UCHAR *resume_arg; /* pointer to resume argument */ + }; +typedef struct resume_req_info RESUME_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_resume (ST_INT chan, RESUME_REQ_INFO *info); +ST_RET mp_resume_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_resume (RESUME_REQ_INFO *info); +ST_RET mpl_resume_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* RESET */ +/************************************************************************/ + +/* REQUEST : */ + +struct reset_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + }; +typedef struct reset_req_info RESET_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_reset (ST_INT chan, RESET_REQ_INFO *info); +ST_RET mp_reset_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_reset (RESET_REQ_INFO *info); +ST_RET mpl_reset_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* KILL */ +/************************************************************************/ + +/* REQUEST : */ + +struct kill_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + }; +typedef struct kill_req_info KILL_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_kill (ST_INT chan, KILL_REQ_INFO *info); +ST_RET mp_kill_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_kill (KILL_REQ_INFO *info); +ST_RET mpl_kill_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET PROGRAM INVOCATION ATTRIBUTE */ +/************************************************************************/ + +#define PI_NON_EXISTENT 0 +#define PI_UNRUNNABLE 1 +#define PI_IDLE 2 +#define PI_RUNNING 3 +#define PI_STOPPED 4 +#define PI_STARTING 5 +#define PI_STOPPING 6 +#define PI_RESUMING 7 +#define PI_RESETTING 8 + +/* REQUEST : */ + +struct getpi_req_info + { + ST_CHAR piname [MAX_IDENT_LEN+1]; /* program invocation name */ + }; +typedef struct getpi_req_info GETPI_REQ_INFO; + +/* RESPONSE : */ + +struct getpi_resp_info + { + ST_INT16 state; /* program invocation state */ + ST_BOOLEAN mms_deletable; /* MMS deletable */ + ST_BOOLEAN reusable; /* Reusable */ + ST_BOOLEAN monitor; /* SD_TRUE : permanent monitoring */ + /* SD_FALSE: current monitoring */ + + ST_INT16 start_arg_type; /* start argument present */ + ST_INT start_arg_len; /* Only used for ENCODED */ + ST_UCHAR *start_arg; /* pointer to start argument */ + + ST_INT num_of_dnames; /* number of domain names */ +/* list of ptrs to domain names */ +/* ST_CHAR *dnames_list [num_of_dnames]; */ + SD_END_STRUCT + }; +typedef struct getpi_resp_info GETPI_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getpi (ST_INT chan, GETPI_REQ_INFO *info); +ST_RET mp_getpi_resp (MMSREQ_IND *ind, GETPI_RESP_INFO *info); +#else +ST_RET mpl_getpi (GETPI_REQ_INFO *info); +ST_RET mpl_getpi_resp (ST_UINT32 invoke, GETPI_RESP_INFO *info); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PPRG_INCLUDED */ diff --git a/mmslib/inc/mms_psem.h b/mmslib/inc/mms_psem.h new file mode 100644 index 0000000..bdca016 --- /dev/null +++ b/mmslib/inc/mms_psem.h @@ -0,0 +1,338 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_psem.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS semaphore management services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/10/97 MDE 02 Changed entry_class to ST_INT8 */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PSEM_INCLUDED +#define MMS_PSEM_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_mp.h" + +/************************************************************************/ +/************************************************************************/ +/* SEMAPHORE MANAGEMENT FUNCTIONS */ +/************************************************************************/ +/* The structures below are used to pass SEMAPHORE MANAGEMENT operation */ +/* information to/from the MMS primitives. */ +/************************************************************************/ + +/************************************************************************/ +/* TAKE CONTROL, Conformance: SEM1/SEM3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct takectrl_req_info + { + OBJECT_NAME sem_name; /* semaphore name */ + ST_BOOLEAN named_token_pres; /* named token present ind */ + ST_CHAR named_token[MAX_IDENT_LEN+1]; /* named token */ + ST_UCHAR priority; /* priority */ + /* 0 - highest */ + /* 64 - normal (default) */ + /* 127 - lowest */ + ST_BOOLEAN acc_delay_pres; /* acceptable delay present ind */ + ST_UINT32 acc_delay; /* acceptable delay */ + ST_BOOLEAN ctrl_timeout_pres; /* control timeout present */ + ST_UINT32 ctrl_timeout; /* control timeout */ + ST_BOOLEAN abrt_on_timeout_pres; /* Abort on Timeout present */ + ST_BOOLEAN abrt_on_timeout; /* Abort on Timeout */ + ST_BOOLEAN rel_conn_lost; /* relenquish if connection lost*/ + ST_BOOLEAN app_preempt_pres; /* app preempt present ind */ + ST_INT app_len; /* length of app. to preempt */ + ST_UCHAR *app_preempt; /* application to preempt */ + SD_END_STRUCT + }; +typedef struct takectrl_req_info TAKECTRL_REQ_INFO; + +/* RESPONSE : */ + +struct takectrl_resp_info + { + ST_INT16 resp_tag; /* response tag */ + /* 0 : NULL response */ + /* 1 : named token response */ + ST_CHAR named_token [MAX_IDENT_LEN+1]; /* named token identifier */ + SD_END_STRUCT + }; +typedef struct takectrl_resp_info TAKECTRL_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_takectrl (ST_INT chan, TAKECTRL_REQ_INFO *info); +ST_RET mp_takectrl_resp (MMSREQ_IND *ind, TAKECTRL_RESP_INFO *info); +#else +ST_RET mpl_takectrl (TAKECTRL_REQ_INFO *info); +ST_RET mpl_takectrl_resp (ST_UINT32 invoke, TAKECTRL_RESP_INFO *info); +#endif + +/************************************************************************/ +/* RELINQUISH CONTROL, Conformance: SEM1/SEM3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct relctrl_req_info + { + OBJECT_NAME sem_name; /* semaphore name */ + ST_BOOLEAN named_token_pres; /* named token present ind */ + ST_CHAR named_token [MAX_IDENT_LEN+1];/* named token */ + SD_END_STRUCT + }; +typedef struct relctrl_req_info RELCTRL_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_relctrl (ST_INT chan, RELCTRL_REQ_INFO *info); +ST_RET mp_relctrl_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_relctrl (RELCTRL_REQ_INFO *info); +ST_RET mpl_relctrl_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* REPORT SEMAPHORE STATUS, Conformance: SEM1/SEM3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct rsstat_req_info + { + OBJECT_NAME sem_name; /* semaphore name */ + }; +typedef struct rsstat_req_info RSSTAT_REQ_INFO; + +/* RESPONSE : */ + +struct rsstat_resp_info + { + ST_BOOLEAN mms_deletable; /* mms deletable */ + ST_INT16 tclass; /* class: token (0) or pool (1) */ + ST_UINT16 num_of_tokens; /* number of tokens */ + ST_UINT16 num_of_owned; /* number of owned tokens */ + ST_UINT16 num_of_hung; /* number of hung tokens */ + SD_END_STRUCT + }; +typedef struct rsstat_resp_info RSSTAT_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_rsstat (ST_INT chan, RSSTAT_REQ_INFO *info); +ST_RET mp_rsstat_resp (MMSREQ_IND *ind, RSSTAT_RESP_INFO *info); +#else +ST_RET mpl_rsstat (RSSTAT_REQ_INFO *info); +ST_RET mpl_rsstat_resp (ST_UINT32 invoke, RSSTAT_RESP_INFO *info); +#endif + +/************************************************************************/ +/* REPORT POOL SEMAPHORE STATUS, Conformance: SEM1/SEM3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct rspool_req_info + { + OBJECT_NAME sem_name; /* semaphore name */ + ST_BOOLEAN start_after_pres; /* start after name present ind */ + ST_CHAR start_after [MAX_IDENT_LEN+1]; /* name to start after */ + SD_END_STRUCT + }; +typedef struct rspool_req_info RSPOOL_REQ_INFO; + +/* RESPONSE : */ + +#if !defined (USE_COMPACT_MMS_STRUCTS) + +struct token_id + { + ST_INT16 token_tag; /* named token tag */ + /* 0 : free named token */ + /* 1 : owned named token */ + /* 2 : hung named token */ + ST_CHAR named_token[MAX_IDENT_LEN+1];/* named token id */ + SD_END_STRUCT + }; + +#else /* Use compact form */ + +struct token_id + { + ST_INT16 token_tag; /* named token tag */ + /* 0 : free named token */ + /* 1 : owned named token */ + /* 2 : hung named token */ + ST_CHAR *named_token; /* named token id */ + SD_END_STRUCT + }; +#endif + +typedef struct token_id TOKEN_ID; + +struct rspool_resp_info + { + ST_INT16 num_of_tokens; /* number of named tokens */ + ST_BOOLEAN more_follows; /* more follows indicator */ +/* list of named tokens */ +/* TOKEN_ID named_token_list [num_of_tokens]; */ + SD_END_STRUCT + }; +typedef struct rspool_resp_info RSPOOL_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_rspool (ST_INT chan, RSPOOL_REQ_INFO *info); +ST_RET mp_rspool_resp (MMSREQ_IND *ind, RSPOOL_RESP_INFO *info); +#else +ST_RET mpl_rspool (RSPOOL_REQ_INFO *info); +ST_RET mpl_rspool_resp (ST_UINT32 invoke, RSPOOL_RESP_INFO *info); +#endif + + +/************************************************************************/ +/* REPORT SEMAPHORE ENTRY STATUS, Conformance: SEM1/SEM3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct rsentry_req_info + { + OBJECT_NAME sem_name; /* semaphore name */ + ST_INT16 state; /* state: 0 : queued */ + /* 1 : owner */ + /* 2 : hung */ + ST_BOOLEAN start_after_pres; /* start after id present ind */ + ST_INT sa_len; /* length of entry id to start */ + /* after */ + ST_UCHAR *start_after; /* pointer to entry id to start */ + /* after */ + SD_END_STRUCT + }; +typedef struct rsentry_req_info RSENTRY_REQ_INFO; + +/* RESPONSE : */ + +struct semaphore_entry + { + ST_INT ei_len; /* entry id length */ + ST_UCHAR *entry_id; /* entry id */ + ST_INT8 entry_class; /* entry class */ + ST_INT app_ref_len; /* app ref length (obj ident) */ + ST_UCHAR *app_ref; /* application reference */ + ST_BOOLEAN named_token_pres; /* named token present ind */ + ST_CHAR named_token[MAX_IDENT_LEN+1];/* named token */ + ST_UCHAR priority; /* priority */ + /* 0 - highest */ + /* 64 - normal (default) */ + /* 127 - lowest */ + ST_BOOLEAN rem_timeout_pres; /* relinquish timeout present */ + ST_UINT32 rem_timeout; /* relinquish timeout */ + ST_BOOLEAN abrt_on_timeout_pres; /* Abort On Timeout present */ + ST_BOOLEAN abrt_on_timeout; /* Abort On Timeout */ + ST_BOOLEAN rel_conn_lost; /* relenquish if connection lost*/ + SD_END_STRUCT + }; +typedef struct semaphore_entry SEMAPHORE_ENTRY; + +struct rsentry_resp_info + { + ST_INT num_of_sent; /* number of semaphore entries */ + ST_BOOLEAN more_follows; /* more follows indicator */ +/* list of semaphore entries */ +/* SEMAPHORE_ENTRY sent_list [num_of_sent]; */ + SD_END_STRUCT + }; +typedef struct rsentry_resp_info RSENTRY_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_rsentry (ST_INT chan, RSENTRY_REQ_INFO *info); +ST_RET mp_rsentry_resp (MMSREQ_IND *ind, RSENTRY_RESP_INFO *info); +#else +ST_RET mpl_rsentry (RSENTRY_REQ_INFO *info); +ST_RET mpl_rsentry_resp (ST_UINT32 invoke, RSENTRY_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DEFINE SEMAPHORE, Conformance: SEM3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct defsem_req_info + { + OBJECT_NAME sem_name; /* semaphore name */ + ST_UINT16 num_of_tokens; /* number of tokens */ + SD_END_STRUCT + }; +typedef struct defsem_req_info DEFSEM_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_defsem (ST_INT chan, DEFSEM_REQ_INFO *info); +ST_RET mp_defsem_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_defsem (DEFSEM_REQ_INFO *info); +ST_RET mpl_defsem_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* DELETE SEMAPHORE, Conformance: SEM3 */ +/************************************************************************/ + +/* REQUEST : */ + +struct delsem_req_info + { + OBJECT_NAME sem_name; /* semaphore name */ + }; +typedef struct delsem_req_info DELSEM_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_delsem (ST_INT chan, DELSEM_REQ_INFO *info); +ST_RET mp_delsem_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_delsem (DELSEM_REQ_INFO *info); +ST_RET mpl_delsem_resp (ST_UINT32 invoke); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PSEM_INCLUDED */ diff --git a/mmslib/inc/mms_pvar.h b/mmslib/inc/mms_pvar.h new file mode 100644 index 0000000..1043150 --- /dev/null +++ b/mmslib/inc/mms_pvar.h @@ -0,0 +1,683 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pvar.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS variable access services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/04/06 JRB 03 Add ARE_OBJ_VALUE_INVALID (new in MMS V2). */ +/* 12/12/02 JRB 02 Add ASN1_ENC_CTXT arg to mpl_info */ +/* 08/13/97 RKR 01 format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PVAR_INCLUDED +#define MMS_PVAR_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_mp.h" + +/************************************************************************/ +/************************************************************************/ +/* DEFINES FOR THE VARIABLE ACCESS SERVICES */ +/************************************************************************/ + +/* defines to be used for addr_tag */ +#define NUM_ADDR 0 /* numeric address */ +#define SYM_ADDR 1 /* symbolic address */ +#define UNCON_ADDR 2 /* unconstrained address */ + +/* #defines to be used for var_spec_tag */ +#define VA_SPEC_NAMED 0 +#define VA_SPEC_ADDRESSED 1 +#define VA_SPEC_DESCRIBED 2 +#define VA_SPEC_SCATTERED 3 +#define VA_SPEC_INVALIDATED 4 + +/* #defines to be used for var_acc_tag */ +#define VAR_ACC_VARLIST 0 /* list of variables */ +#define VAR_ACC_NAMEDLIST 1 /* variable list name */ + +/* defines to be used for 'access result' */ +#define ACC_RSLT_SUCCESS 1 +#define ACC_RSLT_FAILURE 0 + +/* defines to be used for DataAccessError codes */ +#define ARE_OBJ_INVALIDATED 0 +#define ARE_HW_FAULT 1 +#define ARE_TEMP_UNAVAIL 2 +#define ARE_OBJ_ACCESS_DENIED 3 +#define ARE_OBJ_UNDEFINED 4 +#define ARE_INVAL_ADDR 5 +#define ARE_TYPE_UNSUPPORTED 6 +#define ARE_TYPE_INCONSISTENT 7 +#define ARE_OBJ_ATTR_INCONSISTENT 8 +#define ARE_OBJ_ACC_UNSUPPORTED 9 +#define ARE_OBJ_NONEXISTENT 10 +#define ARE_OBJ_VALUE_INVALID 11 + +/* #defines to be used for 'resp_tag' (write response) */ +#define WR_RSLT_SUCCESS 1 +#define WR_RSLT_FAILURE 0 + +/* #defines to be used for 'scope' selector (used for delete var, */ +/* varlist, type requests) */ +#define SPECIFIC_SCOPE 0 +#define ALL_AA_SCOPE 1 +#define ALL_DOM_SCOPE 2 +#define ALL_VMD_SCOPE 3 + + +/************************************************************************/ +/************************************************************************/ +/* The structures below are used to pass VARIABLE ACCESS information */ +/* to/from the MMS primitives. */ +/************************************************************************/ + +struct unconst_addr + { + ST_INT unc_len; /* unconstrained address length */ + ST_UCHAR *unc_ptr; /* unconstrained address ptr */ + SD_END_STRUCT + }; +typedef struct unconst_addr UNCONST_ADDR; + +struct var_acc_addr + { + ST_INT16 addr_tag; /* address tag */ + union + { + ST_UINT32 num_addr; /* numeric address */ + ST_CHAR *sym_addr; /* symbolic address */ + UNCONST_ADDR unc_addr; /* unconstrained address */ + } addr; + }; +typedef struct var_acc_addr VAR_ACC_ADDR; + +struct var_acc_data + { + ST_INT len; /* len of variable access data */ + ST_UCHAR *data; /* ptr to variable access data */ + }; +typedef struct var_acc_data VAR_ACC_DATA; + +struct var_acc_tspec + { + ST_INT len; /* len of type specification */ + ST_UCHAR *data; /* ptr to type specification */ + }; +typedef struct var_acc_tspec VAR_ACC_TSPEC; + +struct scattered_access + { + ST_INT len; /* len of scattered access descr*/ + ST_UCHAR *data; /* ptr to scattered access descr*/ + }; +typedef struct scattered_access SCATTERED_ACCESS; + +struct alternate_access + { + ST_INT len; /* len of alternate access data */ + ST_UCHAR *data; /* ptr to alternate access data */ + }; +typedef struct alternate_access ALTERNATE_ACCESS; + +struct variable_descr + { + VAR_ACC_ADDR address; /* variable address */ + VAR_ACC_TSPEC type; /* variable type */ + }; +typedef struct variable_descr VARIABLE_DESCR; + +struct variable_spec + { + ST_INT16 var_spec_tag; /* variable specification tag */ + union + { + OBJECT_NAME name; /* name */ + VAR_ACC_ADDR address; /* address */ + VARIABLE_DESCR var_descr; /* variable description */ + SCATTERED_ACCESS sa_descr; /* scattered access description */ + } vs; + }; +typedef struct variable_spec VARIABLE_SPEC; + +struct variable_list + { + VARIABLE_SPEC var_spec; /* variable access specification*/ + ST_BOOLEAN alt_access_pres; /* alternate access present */ + ALTERNATE_ACCESS alt_access; /* alternate access */ + }; +typedef struct variable_list VARIABLE_LIST; + +struct var_acc_spec + { + ST_INT16 var_acc_tag; /* variable access tag */ + OBJECT_NAME vl_name; /* variable list name */ + ST_INT num_of_variables; /* number of variables */ +/* list of variables */ +/* VARIABLE_LIST var_list [num_of_variables]; */ + SD_END_STRUCT + }; +typedef struct var_acc_spec VAR_ACC_SPEC; + +struct access_result + { + ST_INT16 acc_rslt_tag; /* access result tag */ + ST_INT16 failure; /* data access error */ + VAR_ACC_DATA va_data; /* success data */ + }; +typedef struct access_result ACCESS_RESULT; + +struct write_result + { + ST_INT16 resp_tag; /* response tag */ + ST_INT16 failure; /* data access error */ + SD_END_STRUCT + }; +typedef struct write_result WRITE_RESULT; + + +/************************************************************************/ +/************************************************************************/ +/* VARIABLE READ */ +/************************************************************************/ + +/* REQUEST : */ + +struct read_req_info + { + ST_BOOLEAN spec_in_result; /* specification with result, */ + /* default to false */ + VAR_ACC_SPEC va_spec; /* variable access spec */ +/* which "includes" */ +/* a list of variables */ +/* VARIABLE_LIST var_list [va_spec.num_of_variables]; */ +/* SD_END_STRUCT */ + }; +typedef struct read_req_info READ_REQ_INFO; + +/* RESPONSE : */ + +struct read_resp_info + { + ST_BOOLEAN va_spec_pres; /* variable access spec present */ + ST_INT num_of_acc_result; /* number of access result */ + ACCESS_RESULT *acc_rslt_list; /* ptr to list of access result */ + VAR_ACC_SPEC va_spec; /* variable access spec */ +/* which "includes" */ +/* a list of variables */ +/* VARIABLE_LIST var_list [va_spec.num_of_variables]; */ +/* list of access result */ +/* ACCESS_RESULT acc_result_list [num_of_acc_result]; */ +/* SD_END_STRUCT */ + }; +typedef struct read_resp_info READ_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_read (ST_INT chan, READ_REQ_INFO *info); +ST_RET mp_read_resp (MMSREQ_IND *ind, READ_RESP_INFO *info); +#else +ST_RET mpl_read (READ_REQ_INFO *info); +ST_RET mpl_read_resp (ST_UINT32 invoke, READ_RESP_INFO *info); +#endif + +/************************************************************************/ +/* VARIABLE WRITE */ +/************************************************************************/ + +/* REQUEST : */ + +struct write_req_info + { + ST_INT num_of_data; /* number of data */ + VAR_ACC_DATA *va_data; /* ptr to list of variable data */ + VAR_ACC_SPEC va_spec; /* variable access spec */ +/* which "includes" */ +/* a list of variables */ +/* VARIABLE_LIST var_list [va_spec.num_of_variables]; */ +/* list of variable data */ +/* VAR_ACC_DATA var_data_list [num_of_data]; */ + }; +typedef struct write_req_info WRITE_REQ_INFO; + +/* RESPONSE : */ + +struct write_resp_info + { + ST_INT num_of_result; +/* WRITE_RESULT wr_result[num_of_result] */ + SD_END_STRUCT + }; +/* Where: */ +/* num_of_result = The number of members in wr_result. This */ +/* number should match the number of */ +/* variables included in the Write request. */ +/* */ +/* wr_result = Array of structures of type write_result */ +/* containing the results of the write */ +/* (success or failure) for each variable */ +/* written. The result array members should */ +/* align with the var_list members that were */ +/* included in the Write request. */ +typedef struct write_resp_info WRITE_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_write (ST_INT chan, WRITE_REQ_INFO *info); +ST_RET mp_write_resp (MMSREQ_IND *ind, WRITE_RESP_INFO *info); +#else +ST_RET mpl_write (WRITE_REQ_INFO *info); +ST_RET mpl_write_resp (ST_UINT32 invoke, WRITE_RESP_INFO *info); +#endif + +/************************************************************************/ +/* INFORMATION REPORT */ +/************************************************************************/ + +/* REQUEST : */ + +struct info_req_info + { + ST_INT num_of_acc_result; /* number of access result */ + ACCESS_RESULT *acc_rslt_list; /* ptr to list of access result */ + VAR_ACC_SPEC va_spec; /* variable access spec */ +/* which "includes" */ +/* a list of variables */ +/* VARIABLE_LIST var_list [va_spec.num_of_variables]; */ +/* list of access result */ +/* ACCESS_RESULT acc_result_list [num_of_acc_result]; */ +/* SD_END_STRUCT */ + }; +typedef struct info_req_info INFO_REQ_INFO; + +/* No Response : (unsolicited) */ + +#ifndef MMS_LITE +ST_RET mp_info (ST_INT chan, INFO_REQ_INFO *info); +#else +ST_RET mpl_info (ASN1_ENC_CTXT *aCtx, INFO_REQ_INFO *info); +#endif + +/************************************************************************/ +/* DEFINE VARIABLE NAME */ +/************************************************************************/ + +/* REQUEST : */ + +struct defvar_req_info + { + OBJECT_NAME name; /* object name */ + VAR_ACC_ADDR address; /* address */ + ST_BOOLEAN type_spec_pres; /* type specification present */ + VAR_ACC_TSPEC type_spec; /* type specification */ + }; +typedef struct defvar_req_info DEFVAR_REQ_INFO; + + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_defvar (ST_INT chan, DEFVAR_REQ_INFO *info); +ST_RET mp_defvar_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_defvar (DEFVAR_REQ_INFO *info); +ST_RET mpl_defvar_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET VARIABLE NAME DEFINITION */ +/************************************************************************/ + +/* REQUEST : */ + +#define GETVAR_NAME 0 +#define GETVAR_ADDR 1 + +struct getvar_req_info + { + ST_INT16 req_tag; /* request tag */ + /* 0 : object name request */ + /* 1 : address request */ + OBJECT_NAME name; /* object name */ + VAR_ACC_ADDR address; /* address */ + }; +typedef struct getvar_req_info GETVAR_REQ_INFO; + +/* RESPONSE : */ + +struct getvar_resp_info + { + ST_BOOLEAN mms_deletable; /* MMS deletable */ + ST_BOOLEAN address_pres; /* address present */ + VAR_ACC_ADDR address; /* address */ + VAR_ACC_TSPEC type_spec; /* type specification */ + }; +typedef struct getvar_resp_info GETVAR_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getvar (ST_INT chan, GETVAR_REQ_INFO *info); +ST_RET mp_getvar_resp (MMSREQ_IND *ind, GETVAR_RESP_INFO *info); +#else +ST_RET mpl_getvar (GETVAR_REQ_INFO *info); +ST_RET mpl_getvar_resp (ST_UINT32 invoke, GETVAR_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DELETE VARIABLE NAME */ +/************************************************************************/ + +/* REQUEST : */ + +#define DELVAR_SPEC 0 +#define DELVAR_AA 1 +#define DELVAR_DOM 2 +#define DELVAR_VMD 3 + +struct delvar_req_info + { + ST_INT16 scope; /* scope of delete (see above) */ + ST_BOOLEAN dname_pres; /* domain name present */ + ST_CHAR dname [MAX_IDENT_LEN+1]; /* domain name */ + ST_BOOLEAN vnames_pres; /* variable names present */ + ST_INT num_of_vnames; /* number of variable names */ +/* list of variable names */ +/* OBJECT_NAME vname_list [num_of_vnames]; */ + SD_END_STRUCT + }; +typedef struct delvar_req_info DELVAR_REQ_INFO; + + +/* RESPONSE : */ + +struct delvar_resp_info + { + ST_UINT32 num_matched; /* Number matched */ + ST_UINT32 num_deleted; /* Number deleted */ + }; +typedef struct delvar_resp_info DELVAR_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_delvar (ST_INT chan, DELVAR_REQ_INFO *info); +ST_RET mp_delvar_resp (MMSREQ_IND *ind,DELVAR_RESP_INFO *info); +#else +ST_RET mpl_delvar (DELVAR_REQ_INFO *info); +ST_RET mpl_delvar_resp (ST_UINT32 invoke, DELVAR_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DEFINE SCATTERED ACCESS */ +/************************************************************************/ + +/* REQUEST : */ + +struct defscat_req_info + { + OBJECT_NAME sa_name; /* scattered access name */ + SCATTERED_ACCESS sa_descr; /* scattered access description */ + }; +typedef struct defscat_req_info DEFSCAT_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_defscat (ST_INT chan, DEFSCAT_REQ_INFO *info); +ST_RET mp_defscat_resp (MMSREQ_IND *info); +#else +ST_RET mpl_defscat (DEFSCAT_REQ_INFO *info); +ST_RET mpl_defscat_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET SCATTERED ACCESS ATTRIBUTES */ +/************************************************************************/ + +/* REQUEST : */ + +struct getscat_req_info + { + OBJECT_NAME sa_name; /* scattered access name */ + }; +typedef struct getscat_req_info GETSCAT_REQ_INFO; + +/* RESPONSE : */ + +struct getscat_resp_info + { + ST_BOOLEAN mms_deletable; /* MMS deletable */ + SCATTERED_ACCESS sa_descr; /* scattered access description */ + }; +typedef struct getscat_resp_info GETSCAT_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getscat (ST_INT chan, GETSCAT_REQ_INFO *info); +ST_RET mp_getscat_resp (MMSREQ_IND *ind, GETSCAT_RESP_INFO *info); +#else +ST_RET mpl_getscat (GETSCAT_REQ_INFO *info); +ST_RET mpl_getscat_resp (ST_UINT32 invoke, GETSCAT_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DEFINE NAMED VARIABLE LIST */ +/************************************************************************/ + +/* REQUEST : */ + +struct defvlist_req_info + { + OBJECT_NAME vl_name; /* variable list name */ + ST_INT num_of_variables; /* number of variables */ +/* list of variables */ +/* VARIABLE_LIST var_list [num_of_variables]; */ + SD_END_STRUCT + }; +typedef struct defvlist_req_info DEFVLIST_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_defvlist (ST_INT chan, DEFVLIST_REQ_INFO *info); +ST_RET mp_defvlist_resp (MMSREQ_IND *info); +#else +ST_RET mpl_defvlist (DEFVLIST_REQ_INFO *info); +ST_RET mpl_defvlist_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET NAMED VARIABLE LIST ATTRIBUTES */ +/************************************************************************/ + +/* REQUEST : */ + +struct getvlist_req_info + { + OBJECT_NAME vl_name; /* variable list name */ + }; +typedef struct getvlist_req_info GETVLIST_REQ_INFO; + +/* RESPONSE : */ + +struct getvlist_resp_info + { + ST_BOOLEAN mms_deletable; /* MMS deletable */ + ST_INT num_of_variables; /* number of variables */ +/* list of variables */ +/* VARIABLE_LIST var_list [num_of_variables]; */ + SD_END_STRUCT + }; +typedef struct getvlist_resp_info GETVLIST_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getvlist (ST_INT chan, GETVLIST_REQ_INFO *info); +ST_RET mp_getvlist_resp (MMSREQ_IND *ind, GETVLIST_RESP_INFO *info); +#else +ST_RET mpl_getvlist (GETVLIST_REQ_INFO *info); +ST_RET mpl_getvlist_resp (ST_UINT32 invoke, GETVLIST_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DELETE NAMED VARIABLE LIST */ +/************************************************************************/ + +/* REQUEST : */ + +#define DELVL_SPEC 0 +#define DELVL_AA 1 +#define DELVL_DOM 2 +#define DELVL_VMD 3 + +struct delvlist_req_info + { + ST_INT16 scope; /* scope of delete (see above) */ + ST_BOOLEAN dname_pres; /* domain name present */ + ST_CHAR dname [MAX_IDENT_LEN+1]; /* domain name */ + ST_BOOLEAN vnames_pres; /* variable names present */ + ST_INT num_of_vnames; /* number of var list names */ +/* list of var list names */ +/* OBJECT_NAME vname_list [num_of_vnames]; */ + SD_END_STRUCT + }; +typedef struct delvlist_req_info DELVLIST_REQ_INFO; + +/* RESPONSE : */ + +struct delvlist_resp_info + { + ST_UINT32 num_matched; /* Number matched */ + ST_UINT32 num_deleted; /* Number deleted */ + }; +typedef struct delvlist_resp_info DELVLIST_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_delvlist (ST_INT chan, DELVLIST_REQ_INFO *info); +ST_RET mp_delvlist_resp (MMSREQ_IND *ind, DELVLIST_RESP_INFO *info); +#else +ST_RET mpl_delvlist (DELVLIST_REQ_INFO *info); +ST_RET mpl_delvlist_resp (ST_UINT32 invoke, DELVLIST_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DEFINE TYPE */ +/************************************************************************/ + +/* REQUEST : */ + +struct deftype_req_info + { + OBJECT_NAME type_name; /* object name */ + VAR_ACC_TSPEC type_spec; /* type specification */ + }; +typedef struct deftype_req_info DEFTYPE_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_deftype (ST_INT chan, DEFTYPE_REQ_INFO *info); +ST_RET mp_deftype_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_deftype (DEFTYPE_REQ_INFO *info); +ST_RET mpl_deftype_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET TYPE NAME DEFINITION */ +/************************************************************************/ + +/* REQUEST : */ + +struct gettype_req_info + { + OBJECT_NAME type_name; /* object name */ + }; +typedef struct gettype_req_info GETTYPE_REQ_INFO; + +/* RESPONSE : */ + +struct gettype_resp_info + { + ST_BOOLEAN mms_deletable; /* MMS deletable */ + VAR_ACC_TSPEC type_spec; /* type specification */ + }; +typedef struct gettype_resp_info GETTYPE_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_gettype (ST_INT chan, GETTYPE_REQ_INFO *info); +ST_RET mp_gettype_resp (MMSREQ_IND *ind, GETTYPE_RESP_INFO *info); +#else +ST_RET mpl_gettype (GETTYPE_REQ_INFO *info); +ST_RET mpl_gettype_resp (ST_UINT32 invoke, GETTYPE_RESP_INFO *info); +#endif + +/************************************************************************/ +/* DELETE TYPE NAME */ +/************************************************************************/ + +/* REQUEST : */ + +#define DELTYPE_SPEC 0 +#define DELTYPE_AA 1 +#define DELTYPE_DOM 2 +#define DELTYPE_VMD 3 + +struct deltype_req_info + { + ST_INT16 scope; /* scope of delete (see above) */ + ST_BOOLEAN dname_pres; /* domain name present */ + ST_CHAR dname [MAX_IDENT_LEN+1]; /* domain name */ + ST_BOOLEAN tnames_pres; /* type names present */ + ST_INT num_of_tnames; /* number of type names */ +/* list of type names */ +/* OBJECT_NAME tname_list [num_of_tnames]; */ + SD_END_STRUCT + }; +typedef struct deltype_req_info DELTYPE_REQ_INFO; + +/* RESPONSE : */ + +struct deltype_resp_info + { + ST_UINT32 num_matched; /* Number matched */ + ST_UINT32 num_deleted; /* Number deleted */ + }; +typedef struct deltype_resp_info DELTYPE_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_deltype (ST_INT chan, DELTYPE_REQ_INFO *info); +ST_RET mp_deltype_resp (MMSREQ_IND *ind, DELTYPE_RESP_INFO *info); +#else +ST_RET mpl_deltype (DELTYPE_REQ_INFO *info); +ST_RET mpl_deltype_resp (ST_UINT32 invoke, DELTYPE_RESP_INFO *info); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PVAR_INCLUDED */ diff --git a/mmslib/inc/mms_pvmd.h b/mmslib/inc/mms_pvmd.h new file mode 100644 index 0000000..6024d16 --- /dev/null +++ b/mmslib/inc/mms_pvmd.h @@ -0,0 +1,291 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_pvmd.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the data structures and function definitions */ +/* required to interface with MMS vmd management services */ +/* at the primitive level. */ +/* */ +/* Parameters : In general, the first parameter is the channel */ +/* that the request or response is to be sent over. */ +/* For Responses, the second parameter is the Invoke */ +/* ID to be used. The last parameter is used to pass */ +/* operation specific information by pointer. */ +/* */ +/* Return */ +/* Values : Request functions return a pointer to the pending */ +/* request tracking structure, of type MMSREQ_PEND. */ +/* In case of error, the pointer is returned == 0 */ +/* and mms_op_err is written with the err code. */ +/* Response functions return 0 if OK, else an error */ +/* code. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/12/02 JRB 02 Add ASN1_ENC_CTXT arg to mpl_ustatus */ +/* 09/09/97 MDE 02 Added 'mms_class' defines */ +/* 08/14/97 RKR 01 Format changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_PVMD_INCLUDED +#define MMS_PVMD_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_mp.h" + +/************************************************************************/ +/************************************************************************/ +/* VMD MANAGEMENT SERVICES */ +/************************************************************************/ +/* The structures below are used to pass VMD MANAGEMENT information */ +/* to/from the MMS primitives. */ +/************************************************************************/ + +/* Defines for 'mms_class' for GNL and RENAME */ +#define MMS_CLASS_VAR 0 +#define MMS_CLASS_SCAT_ACC 1 +#define MMS_CLASS_VARLIST 2 +#define MMS_CLASS_TYPE 3 +#define MMS_CLASS_SEM 4 +#define MMS_CLASS_EV_COND 5 +#define MMS_CLASS_EV_ACT 6 +#define MMS_CLASS_EV_ENROLL 7 +#define MMS_CLASS_JOU 8 +#define MMS_CLASS_DOM 9 +#define MMS_CLASS_PI 10 +#define MMS_CLASS_OPER_STA 11 + +/************************************************************************/ +/************************************************************************/ +/* STATUS */ +/************************************************************************/ + +/* REQUEST : */ + +#define MAX_STAT_DTL_LEN 16 + +struct status_req_info + { + ST_BOOLEAN extended; /* flag indicating if extended status */ + }; /* is desired */ +typedef struct status_req_info STATUS_REQ_INFO; + +/* RESPONSE : */ + +struct status_resp_info + { + ST_INT16 logical_stat; /* logical status - not optional */ + ST_INT16 physical_stat; /* physical status - not optional */ + ST_BOOLEAN local_detail_pres; /* flag if logical detail is present */ + ST_INT local_detail_len; /* length of logical detail (in bits) */ + ST_UCHAR local_detail[MAX_STAT_DTL_LEN]; /* vendor-specific detailed info*/ + }; +typedef struct status_resp_info STATUS_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_status (ST_INT chan,STATUS_REQ_INFO *info); +ST_RET mp_status_resp (MMSREQ_IND *ind,STATUS_RESP_INFO *info); +#else +ST_RET mpl_status (STATUS_REQ_INFO *info); +ST_RET mpl_status_resp (ST_UINT32 invoke, STATUS_RESP_INFO *info); +#endif + +/************************************************************************/ +/* UNSOLICITED STATUS */ +/************************************************************************/ + +/* REQUEST : */ + +struct ustatus_req_info + { + ST_INT16 logical_stat; /* logical status - not optional */ + ST_INT16 physical_stat; /* physical status - not optional */ + ST_BOOLEAN local_detail_pres; /* flag if logical detail is present */ + ST_INT local_detail_len; /* length of logical detail (in bits) */ + ST_UCHAR local_detail[MAX_STAT_DTL_LEN]; /* vendor-specific detailed info*/ + }; +typedef struct ustatus_req_info USTATUS_REQ_INFO; + +/* RESPONSE : No response (unsolicited) */ + +#ifndef MMS_LITE +ST_RET mp_ustatus (ST_INT chan,USTATUS_REQ_INFO *info); +#else +ST_RET mpl_ustatus (ASN1_ENC_CTXT *aCtx, USTATUS_REQ_INFO *info); +#endif + +/************************************************************************/ +/* GET NAME LIST */ +/************************************************************************/ + +/* REQUEST : */ + +struct namelist_req_info + { + ST_BOOLEAN cs_objclass_pres; /* set for use CS object class */ + union + { + ST_INT16 mms_class; /* object class */ + struct /* CS context object sel */ + { + ST_INT len; /* length of ASN.1 CS class */ + ST_UCHAR *cs_class; /* CS object class ASN.1 */ + } cs; + } obj; + + ST_INT16 objscope; /* object scope */ + ST_CHAR dname[MAX_IDENT_LEN+1]; /* domain name, for scope = dom */ + ST_BOOLEAN cont_after_pres; /* flag if continue param pres. */ + ST_CHAR continue_after[MAX_IDENT_LEN+1]; /* continue-after name */ + SD_END_STRUCT + }; +typedef struct namelist_req_info NAMELIST_REQ_INFO; + +/* RESPONSE : */ + +struct namelist_resp_info + { + ST_BOOLEAN more_follows; /* end of list boolean value */ + ST_INT num_names; /* number of names */ + SD_END_STRUCT + }; +/* ST_CHAR *name_list[]; */ /* array of pointers to object names */ + +/* NOTE: Immediately below this structure (contiguous in memory) is a */ +/* list of character pointers, one for each name in the name list. */ +/* Essentially the structure and name pointers are allocated in a */ +/* single call to malloc of size: (sizeof(NAMELIST_RESP_INFO) */ +/* + num_names * sizeof(ST_CHAR *)). The requesting user makes use of */ +/* the contiguous list of pointers as appropriate. The responding */ +/* user must pass the mp_namelist_resp function a pointer to a contig- */ +/* uous block of memory containing the namelist_resp_info structure at */ +/* the top and the list of character pointers below it. */ +typedef struct namelist_resp_info NAMELIST_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_namelist (ST_INT chan,NAMELIST_REQ_INFO *info); +ST_RET mp_namelist_resp (MMSREQ_IND *ind,NAMELIST_RESP_INFO *info); +#else +ST_RET mpl_namelist (NAMELIST_REQ_INFO *info); +ST_RET mpl_namelist_resp (ST_UINT32 invoke, NAMELIST_RESP_INFO *info); +#endif + +/************************************************************************/ +/* IDENTIFY */ +/************************************************************************/ + +/* REQUEST : NULL */ +/* RESPONSE : */ + +/* This is the structure used for the info pass to/from the MMS prims */ + +#define MAX_VEND_LEN 64 /* vendor name max len */ +#define MAX_REV_LEN 16 /* revision max len */ +#define MAX_MOD_LEN 16 /* model max len */ + +struct ident_resp_info + { + ST_CHAR vend[MAX_VEND_LEN+1]; /* vendor */ + ST_CHAR model[MAX_MOD_LEN+1]; /* model */ + ST_CHAR rev[MAX_REV_LEN+1]; /* revision */ + ST_INT num_as; /* number abstract syntax's */ +/* this structure may be followed by the abstract syntax's */ +/* MMS_OBJ_ID as[num_as]; */ + SD_END_STRUCT + }; +typedef struct ident_resp_info IDENT_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_ident (ST_INT chan); +ST_RET mp_ident_resp (MMSREQ_IND *ind,IDENT_RESP_INFO *info); +#else +ST_RET mpl_ident (ST_VOID); +ST_RET mpl_ident_resp (ST_UINT32 invoke, IDENT_RESP_INFO *info); +#endif + +/************************************************************************/ +/* RENAME */ +/************************************************************************/ + +/* REQUEST : */ + +struct rename_req_info + { + ST_BOOLEAN cs_objclass_pres; /* set for use CS object class */ + union + { + ST_INT16 mms_class; /* object class */ + struct /* CS context object sel */ + { + ST_INT len; /* length of ASN.1 CS class */ + ST_UCHAR *cs_class; /* CS object class ASN.1 */ + } cs; + } obj; + + OBJECT_NAME cur_name; /* current name */ + ST_CHAR new_ident [MAX_IDENT_LEN+1]; /* new identifier */ + SD_END_STRUCT + }; +typedef struct rename_req_info RENAME_REQ_INFO; + +/* RESPONSE : NULL */ + +#ifndef MMS_LITE +MMSREQ_PEND *mp_rename (ST_INT chan,RENAME_REQ_INFO *info); +ST_RET mp_rename_resp (MMSREQ_IND *ind); +#else +ST_RET mpl_rename (RENAME_REQ_INFO *info); +ST_RET mpl_rename_resp (ST_UINT32 invoke); +#endif + +/************************************************************************/ +/* GET CAPABILITY LIST */ +/************************************************************************/ + +/* REQUEST : */ + +struct getcl_req_info + { + ST_BOOLEAN cont_after_pres; /* flag if continue param pres. */ + ST_CHAR *continue_after; /* pointer continue-after name */ + }; +typedef struct getcl_req_info GETCL_REQ_INFO; + +/* RESPONSE : */ + +struct getcl_resp_info + { + ST_BOOLEAN more_follows; /* end of list boolean value */ + ST_INT num_of_capab; /* number of capabilities */ +/* list of capabilities */ +/* ST_CHAR * capab_list [num_of_capab]; */ + SD_END_STRUCT + }; +typedef struct getcl_resp_info GETCL_RESP_INFO; + +#ifndef MMS_LITE +MMSREQ_PEND *mp_getcl (ST_INT chan,GETCL_REQ_INFO *info); +ST_RET mp_getcl_resp (MMSREQ_IND *ind,GETCL_RESP_INFO *info); +#else +ST_RET mpl_getcl (GETCL_REQ_INFO *info); +ST_RET mpl_getcl_resp (ST_UINT32 invoke, GETCL_RESP_INFO *info); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* #define MMS_PVMD_INCLUDED */ + diff --git a/mmslib/inc/mms_vvar.h b/mmslib/inc/mms_vvar.h new file mode 100644 index 0000000..1896958 --- /dev/null +++ b/mmslib/inc/mms_vvar.h @@ -0,0 +1,1090 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2006, All Rights Reserved. */ +/* */ +/* MODULE NAME : mms_vvar.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains data and function definitions associated */ +/* with the MMS virtual machine variable access operations. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/02/07 JRB 58 Add elements to RUNTIME_BUILD_CTXT to allow */ +/* 2 pass build process. Add more ms_rt_bld*. */ +/* 05/10/07 JRB 57 Chg el_size, etc. to ST_INT to avoid warnings*/ +/* 04/30/07 JRB 56 Chg el_size, el_len, etc. in RUNTIME_TYPE to */ +/* ST_INT32 to allow larger primitives, arrays. */ +/* 04/17/07 JRB 55 Add prim_count to MVLU_TYPE_INFO. */ +/* 10/30/06 JRB 54 Add reserved_1 to RUNTIME_CTRL. */ +/* Add "ms_rt_bld_*" prototypes. */ +/* 08/09/06 JRB 53 Add ms_local_to_asn1_2. */ +/* Add ms_adl_to_asn1_2, ms_aa_to_asn1_2. */ +/* 03/22/06 EJV 52 Added GENERAL_TIME_ALGN (time_t is 64-bits in VS 2005)*/ +/* 07/29/05 MDE 51 Select USE_RT_TYPE_3 for USPS_IOS */ +/* 05/09/05 JRB 50 Default to USE_RT_TYPE_2 (was USE_RT_TYPE_3).*/ +/* 03/10/05 JRB 49 Add ms_rt_el_tag_text proto. */ +/* 02/22/05 JRB 48 ms_is_rt_prim: add SD_CONST to arg. */ +/* 01/27/05 JRB 47 Add m_lite_data_algn_tbl extern. */ +/* 07/22/04 JRB 46 Add rt_index_q, rt_index_t, data_offset to */ +/* RUNTIME_TYPE if !MMS_LITE. */ +/* 07/12/04 JRB 45 Chg RT_UTF8_STRING tag from 18 to 16 to */ +/* match latest 61850-8-1. */ +/* 01/22/04 JRB 44 Add ms_local_to_text. */ +/* 10/03/03 JRB 43 Chg offset_to_last & offSet to ST_INT32 in */ +/* RUNTIME_TYPE to handle BIG IEC-61850 types. */ +/* 03/31/03 JRB 42 Add UTF8string support (see RT_UTF8_STRING). */ +/* Add "utf8" to M_ARB_DATA_CTRL. */ +/* 03/13/03 JRB 41 u_ml_get_rt_type: Chg from "func ptr" to func.*/ +/* 01/02/03 JRB 40 Add arg to u_ml_get_rt_type. */ +/* Add ASN1_TO_RT_DEC_INFO struct. */ +/* 12/27/02 MDE 39 Allow use of ms_asn1_to_runtime */ +/* 12/17/02 JRB 38 Del SD_CONST from numMvlRtNames. */ +/* 12/16/02 JRB 37 Chg ms_is_rt_prim from macro to function. */ +/* 11/27/02 MDE 36 Added ms_is_rt_prim */ +/* 11/11/02 JRB 35 Add RUNTIME_CTRL, chg ms_runtime_create & */ +/* ms_runtime_destroy to use it. */ +/* Del ms_asn1_to_runtime (use ms_runtime_create)*/ +/* Add ms_tdl_to_runtime proto. */ +/* 03/01/02 JRB 34 Add SD_CONST to (RUNTIME_TYPE *) in RT_AA_CTRL.*/ +/* 02/06/02 JRB 33 Deleted unused MMS_ALTA_DATA */ +/* 12/20/01 JRB 32 Convert to use ASN1R. */ +/* Add ASN1_ENC_CTXT arg to ms_*_to_asn1*. */ +/* Add new function ms_local_to_asn1_easy. */ +/* 11/13/01 EJV 31 Added support for new MMS type UtcTime: */ +/* Added RT_UTC_TIME, chg RT_STR_END, RT_ARR_END*/ +/* M_ARB_DATA_CTRL: added utc fun proto. */ +/* 06/20/01 EJV 30 Added () around rt in ms_comp_name_xxx macros*/ +/* to handle rt+1, rt-1 arguments. */ +/* 04/11/01 MDE 29 Added ms_comp_name_pres macros */ +/* 01/21/01 EJV 28 M_ARB_DATA_CTRL: changed bool to booln, */ +/* to avoid conflict w/ bool type in C++ files. */ +/* 11/02/00 JRB 27 Del #if MVL_UCA. Use #if MMS_LITE instead. */ +/* 10/25/00 JRB 26 Del MVL_UCA define (define in makefile). */ +/* Move ST_RTREF typedef so always defined. */ +/* 08/29/00 JRB 25 Chg ms_comp_name_find from funct to macro. */ +/* 07/28/00 JRB 24 Simplify RT_TYPE ifdefs. */ +/* Fix SD_CONST in some prototypes. */ +/* Del m_type_nam* externs, only used in 1 file.*/ +/* 07/13/00 JRB 23 Add "#ifdef USE_RT_TYPE_2". */ +/* Add ms_runtime_create, ms_runtime_destroy, */ +/* ms_comp_name_find. */ +/* 06/22/00 MDE 22 Added numMvlRtNames declaration */ +/* 06/16/00 JRB 21 Add #if INT64_SUPP... */ +/* 04/20/00 JRB 20 Del SD_CONST from (RUNTIME_TYPE **) args. */ +/* 09/13/99 MDE 19 Added SD_CONST modifiers */ +/* 09/10/98 MDE 18 Added 'mvlRtNames' declaration */ +/* 08/11/98 MDE 17 Minor changes for Foundry */ +/* 06/30/98 MDE 16 Changed ST_REF to ST_VOID * */ +/* 04/07/98 MDE 15 Added struct/arr start/end alignment mode */ +/* 03/23/98 MDE 14 Now let user supply AA derived type (RD/WR) */ +/* 03/12/98 MDE 13 MMS-Lite related runtime type changes */ +/* 03/11/98 MDE 12 Removed NEST_RT_TYPES */ +/* 02/10/98 MDE 11 Changed runtime type */ +/* 12/29/97 MDE 10 Added 'typeCtrl' to RUNTIME_TYPE for use */ +/* with 'mktypes.exe' only. */ +/* 09/11/97 MDE 09 MMS ARB user funs now return ST_RET */ +/* 09/04/97 NAV 08 Split ARB Btime functions & add */ +/* have them return a ST_BOOLEAN */ +/* 08/15/97 MDE 07 BTOD handling comments */ +/* 08/14/97 RKR 06 Format changes */ +/* 07/16/97 RKR 05 Added more 64 bit integer support */ +/* 06/23/97 RKR 04 Added arbitrary data handling */ +/* 06/20/97 MDE 03 Added 64 bit integer support */ +/* 06/09/97 MDE 02 Changed Runtime Type and it's use */ +/* 06/05/97 RKR 01 Removed AA_OUTER_NEST rearranged AA constants*/ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMS_VVAR_INCLUDED +#define MMS_VVAR_INCLUDED + +#ifndef MMS_LITE +#include "mms_mv.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************************************/ +/************************************************************************/ +/* BINARY TIME OF DAY NOTES */ +/* There are two forms of TimeOfDay, 4 byte and 6 byte. */ +/* The 6 byte form contains the number of milliseconds since midnight */ +/* and the number of days since Jan 1, 1984. The 4 byte form contains */ +/* only the millisecond number. */ +/* */ +/* In memory, the Btime6 data looks like a pair of 32 bit integers: */ +/* ST_INT32 ms; Number of milliseconds since midnight */ +/* ST_INT32 day; Number of days since Jan 1, 1984 */ +/* */ +/* and the Btime4 data looks like a single 32 bit integer: */ +/* ST_INT32 ms; Number of milliseconds since midnight */ +/* */ +/* Data alignment for either form is that of a ST_INT32. */ +/* Note that MMS-EASE simply encodes/decodes the values to/from the */ +/* MMS PDU and does not perform any local time localization. */ +/************************************************************************/ + +/************************************************************************/ +/************************************************************************/ +/* MMS-LITE */ +/************************************************************************/ + +/* Default to USE_RT_TYPE_2 for MMS Lite (allows dynamic type creation).*/ +/* NOTE: define USE_RT_TYPE_3 only if you need to store RUNTIME_TYPES */ +/* in ROM, and you DO NOT need dynamic type creation. */ + +#if defined(MMS_LITE) && (!defined(USE_RT_TYPE_3)) +#define USE_RT_TYPE_2 +#endif + +/* The IOS Toolkit requires RT_TYPE_3 */ +#ifdef USPS_IOS +#undef USE_RT_TYPE_2 +#define USE_RT_TYPE_3 +#endif + +#if defined(FOUNDRY) /* Overwride defines when compiling Foundry */ +#undef USE_RT_TYPE_2 +#undef USE_RT_TYPE_3 +#endif + +/* RUNTIME TYPE INTEGER FORM */ +/* In MMS-LITE the size of the RUNTIME_TYPE must be minimized, so we */ +/* will use 16 bit integers for the compoments. This puts a 32K limit */ +/* on the size of a variable. */ + +#if !defined(MMS_LITE) +#define ST_RTINT ST_INT +#else +#define ST_RTINT ST_INT16 +#endif + +/************************************************************************/ +/* MMS-LITE UCA SPECIFIC SECTION */ +/************************************************************************/ +/* MMS-LITE uses an extended RUNTIME_TYPE for use with the MVL UCA */ +/* object handling extensions. */ +/* To use the UCA extensions, MVL_UCA must be defined. */ +/* NOTE: MVL_UCA is NOT defined by default. */ + +/* This typedef is for the application use only and can be changed as */ +/* required. Normally it is used to allow the applcation to consolidate */ +/* MVL_UCA read and write indication handler functions. */ +typedef ST_VOID * ST_RTREF; + +/* These elements are designed to be used to assist in implementing the */ +/* UCA device models in MMS-EASE Lite. Note that 'MVL_UCA' must be */ +/* defined when creating the MMS-EASE libraries if these features are */ +/* to be used. */ + +/* You may comment out the defines for those components that will not */ +/* bs used in the target application to reduce the size of the */ +/* RUNTIME_TYPE table. */ +#define MVLU_USE_REF + +typedef struct mvluTypeStruct + { + ST_RTINT prim_count; /* number of prims in this ARR, STRUCT, or prim */ + ST_RTINT sortedNum; /* For use by MVLU GNL code */ + ST_INT32 offSet; /* Offset from start of mother structure */ + ST_RTINT rdIndFunIndex; + ST_RTINT wrIndFunIndex; + +/* These elements can be used by the application as needed, and are */ +/* copied into the derived variable association. MVLU does not use them */ +/* directly. */ +#if defined(MVLU_USE_REF) + ST_RTREF ref; /* set to 'XXX$YYY_REF' by foundry */ +#endif + } MVLU_TYPE_INFO; + +/************************************************************************/ +/* RUNTIME TYPE DEFINITION STRUCTURE */ +/************************************************************************/ +/* The following defines specify the various data parameters */ +/************************************************************************/ + +#define RT_ARR_START 1 +#define RT_STR_START 2 +#define RT_BOOL 3 +#define RT_BIT_STRING 4 +#define RT_INTEGER 5 +#define RT_UNSIGNED 6 +#define RT_FLOATING_POINT 7 +#define RT_OCTET_STRING 9 +#define RT_VISIBLE_STRING 10 +#define RT_GENERAL_TIME 11 +#define RT_BINARY_TIME 12 +#define RT_BCD 13 +#define RT_BOOLEANARRAY 14 +#define RT_UTC_TIME 17 +#define RT_UTF8_STRING 16 /* specified in IEC-61850-8-1 */ +/* ADD new tags here and bump up RT_MAX_PRIM_TAG accordingly. */ +#define RT_MAX_PRIM_TAG 18 /* use when looking for max tag val*/ +#define RT_STR_END (RT_MAX_PRIM_TAG+1) +#define RT_ARR_END (RT_MAX_PRIM_TAG+2) + +struct runtime_type + { + ST_UCHAR el_tag; /* ID tag expected for this element, or special */ + /* values for end of array, end of struct */ + /* or nested runtime types */ + + ST_INT el_size; /* number of bytes occupied by this element */ + ST_INT32 offset_to_last; /* offset in bytes from the start of the */ + /* data to the last element */ + union + { + /* CRITICAL: element types in each structure in this union must */ + /* match. If not, the Foundry would misalign data in this union. */ + struct /* primitive element */ + { + ST_INT el_len; /* precision, in bytes except bitstr, time */ + ST_RTINT pad; /* included to allow aggregate initialization */ + } p; + struct /* structure (top or bottom) */ + { + ST_INT num_rt_blks; /* # runtime blks to get to strt/end elmnt */ + ST_RTINT pad; /* included to allow aggregate initialization */ +#if !defined(USE_RT_TYPE_2) && !defined(USE_RT_TYPE_3) + ST_BOOLEAN packd; /* Indicates if packed or not. */ +#endif + } str; + struct /* Array (top or bottom) */ + { + ST_INT num_elmnts; /* # array elements (index limit) */ + ST_RTINT num_rt_blks; /* # runtime blks to get to strt/end elmnt */ +#if !defined(USE_RT_TYPE_2) && !defined(USE_RT_TYPE_3) + ST_BOOLEAN packd; /* Indicates if packed or not. */ +#endif + } arr; + } u; + +#if defined(USE_RT_TYPE_2) + ST_CHAR *comp_name_ptr; /* ptr to comp name string */ +#elif defined(USE_RT_TYPE_3) + ST_RTINT name_index; /* Index into mvlRtNames table */ +#else /* Default */ + ST_CHAR name[MAX_IDENT_LEN+1]; +#endif + +#if defined(MMS_LITE) + MVLU_TYPE_INFO mvluTypeInfo; /* MMS-LITE UCA handler use */ +#endif +#if defined(FOUNDRY) + ST_CHAR *refBuf; + ST_CHAR *rdIndexBuf; + ST_CHAR *wrIndexBuf; +#endif +#if !defined (MMS_LITE) + ST_RTINT rt_index_q; /* index into RUNTIME_TYPE array for 'q'*/ + /* attribute of IEC-61850 type */ + ST_RTINT rt_index_t; /* index into RUNTIME_TYPE array for 't'*/ + /* attribute of IEC-61850 type */ + ST_INT32 data_offset; /* offset in bytes from start of data */ + /* NOTE: should be same as offSet in */ + /* mvluTypeInfo above for MMS_LITE */ +#endif + }; +typedef struct runtime_type RUNTIME_TYPE; + +/* Runtime type HEAD struct contains info about RUNTIME_TYPE array. */ +typedef struct + { + RUNTIME_TYPE *rt_first; /* ptr to first in array of structs */ + ST_INT rt_num; /* num entries in RUNTIME_TYPE array */ + ST_VOID *reserved_1; /* ptr to any optional info for this type*/ + } RUNTIME_CTRL; + +/************************************************************************/ +/* ASN1_TO_RT_DEC_INFO - structure to store temporary decode info. */ +/************************************************************************/ +typedef struct + { +#if defined(USE_RT_TYPE_2) +/* These are used for saving component names. */ + ST_CHAR *comp_name_buf; /* Alloc'd buf to store ALL component names.*/ + ST_INT comp_name_size; /* Buffer size (in bytes) */ + ST_INT comp_name_used; /* Running count of bytes needed OR used.*/ + + ST_CHAR *comp_name_ptr; /* current position in buffer. */ +#endif + RUNTIME_TYPE *rt_start; /* ptr to runtime table start */ + ST_BOOLEAN calc_only; /* flag to calculate num rt blocks */ + /* DEBUG: add rt_ptr, rt_count, rt_limit, etc. & delete global vars.*/ + } ASN1_TO_RT_DEC_INFO; + +/************************************************************************/ +/* RUNTIME_BUILD_CTXT: info for dynamic building of runtime type defs. */ +/************************************************************************/ +typedef struct + { + RUNTIME_CTRL *rt_ctrl; /* type definition being built */ + RUNTIME_TYPE *rt_type; /* ptr to current type */ + RUNTIME_TYPE *max_rt_type; /* ptr after last RUNTIME_TYPE struct */ + ST_INT nest_level; /* index into "nest_start_ptr" array */ + RUNTIME_TYPE *nest_start_ptr [ASN1_MAX_LEVEL]; /* array of ptrs to*/ + /* STR_START or ARR_START */ + ST_CHAR *comp_name_buf; /* allocated buf to store comp names */ + /* [MAX_IDENT_LEN+1] for each */ + ST_RET errcode; /* Set when first error detected */ + /* Initialized to SD_SUCCESS. */ + + ST_BOOLEAN do_count; /* If SD_TRUE, bld functions just count */ + /* num of RUNTIME_TYPE elements needed */ + /* (nothing allocated or initialized) */ + ST_INT curr_count; /* current count of RUNTIME_TYPE elems */ + /* (used only when do_count=SD_TRUE) */ + ST_INT max_count; /* max count of RUNTIME_TYPE elems */ + /* (used only when do_count=SD_TRUE) */ + } RUNTIME_BUILD_CTXT; + +#if defined(MMS_LITE) +ST_RET u_ml_get_rt_type (ASN1_DEC_CTXT *aCtx, OBJECT_NAME *type_name, + RUNTIME_TYPE **rt_out, ST_INT *num_rt_out); + +extern ST_INT maxMvlRtNames; +extern ST_INT numMvlRtNames; +extern ST_CHAR **mvlRtNames; +#endif + +ST_BOOLEAN ms_is_rt_prim (SD_CONST RUNTIME_TYPE *rt); +ST_CHAR *ms_rt_el_tag_text (SD_CONST RUNTIME_TYPE *rt_type); + +/************************************************************************/ +/* ALTERNATE ACCESS DEFINITION STRUCTURE */ +/************************************************************************/ + +/* Possible values for sel_type */ +#define AA_COMP 0 +#define AA_INDEX 1 +#define AA_INDEX_RANGE 2 +#define AA_ALL 3 +#define AA_COMP_NEST 4 +#define AA_INDEX_NEST 5 +#define AA_INDEX_RANGE_NEST 6 +#define AA_ALL_NEST 7 +#define AA_END_NEST 8 + +#define MAX_NUM_AA_EL 100 + +struct alt_acc_el + { + ST_BOOLEAN comp_name_pres; + ST_CHAR comp_name[MAX_IDENT_LEN+1];/* named component for derived */ + /* type */ + ST_INT sel_type; /* type of access selection */ + union + { + ST_CHAR component[MAX_IDENT_LEN+1]; /* Used for AA_COMP */ + ST_UINT32 index; /* Used for AA_INDEX */ + struct /* Used for AA_INDEX_RANGE */ + { + ST_UINT32 low_index; + ST_UINT32 num_elmnts; + } ir; + } u; + }; +typedef struct alt_acc_el ALT_ACC_EL; + +struct alt_access + { + ST_INT num_aa; + ALT_ACC_EL *aa; + }; +typedef struct alt_access ALT_ACCESS; + + +/* This data structure is used in table form to implement alternate */ +/* access from the server perspective (NEWDATA <-> ASN1DATA) */ +/* It allows re-ordering of elements as well as limited selection */ + +struct rt_aa_ctrl + { + SD_CONST RUNTIME_TYPE *rt; + ST_UINT offset_to_data; /* offset to data element */ + ST_INT el_size; /* Size of the element in memory */ + }; +typedef struct rt_aa_ctrl RT_AA_CTRL; + +ST_RET ms_adl_to_aa (ST_CHAR *adl_str,ALT_ACCESS *alt_acc); +ST_RET ms_adl_to_asn1_2 (ST_CHAR *adl_str, + ST_UCHAR *buf_ptr, + ST_INT buf_len, + ST_UCHAR **asn1_ptr_out, + ST_INT *asn1_len_out); + +ST_RET ms_aa_to_adl (ALT_ACCESS *alt_acc, + ST_CHAR *adl_str, + ST_INT max_adl_len); + +ST_RET ms_local_to_asn1_aa (ASN1_ENC_CTXT *aCtx, SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, + ALT_ACCESS *alt_acc, + ST_CHAR *dptr); + +ST_RET ms_asn1_to_local_aa (SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, + ALT_ACCESS *alt_acc, + ST_UCHAR *asn1ptr, + ST_INT asn1len, + ST_CHAR *dptr); + + +ST_VOID ms_log_alt_access (ALT_ACCESS *alt_acc); + + +ST_RET ms_aa_to_asn1 (ASN1_ENC_CTXT *aCtx, ALT_ACCESS *alt_acc); +/* ms_aa_to_asn1_2 usually easier to use than ms_aa_to_asn1. */ +ST_RET ms_aa_to_asn1_2 (ALT_ACCESS *alt_acc, + ST_UCHAR *buf_ptr, + ST_INT buf_len, + ST_UCHAR **asn1_ptr_out, + ST_INT *asn1_len_out); +ST_RET ms_asn1_to_aa (ST_UCHAR *asn1ptr, ST_INT asn1len, + ALT_ACCESS *alt_acc_out); + + +/************************************************************************/ +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* Type definition structures and manipulation functions */ +/************************************************************************/ + +struct named_type /* type definition table structure */ + { + DBL_LNK link; /* generic list links */ + ST_CHAR type_name[MAX_IDENT_LEN+1]; /* name of data type */ + ST_BOOLEAN deletable; /* set != 0 if deletable */ + ST_UCHAR protection; /* protection afforded for type */ + ST_BOOLEAN erased; /* flags if deleted, but nref !=0 */ + ST_INT nref; /* number of var def'ns referencing this*/ + RUNTIME_CTRL *rt_ctrl; /* May be NULL */ + RUNTIME_TYPE *rt_head; /* ptr to runtime type def head */ + ST_INT rt_num; /* # of rt_blocks in runtime type def */ + ST_INT asn1len; /* # bytes in ASN.1 definition */ + ST_UCHAR *asn1ptr; /* pointer to ASN.1 definition */ + ST_INT blocked_len; /* length of blocked (packed) data type */ + ST_CHAR *(*read_ind_fun)(ST_CHAR *src, ST_INT len); /* std read ind function ptr */ + ST_INT (*write_ind_fun)(ST_CHAR *src, ST_CHAR *dest, ST_INT len); /* std write ind */ + }; +typedef struct named_type NAMED_TYPE; + +ST_RET ms_locl_to_asn1_aa (ASN1_ENC_CTXT *aCtx, NAMED_TYPE *tptr, + ALT_ACCESS *alt_acc, + ST_CHAR *dptr); + +ST_RET ms_asn1_to_locl_aa (NAMED_TYPE *tptr, + ALT_ACCESS *alt_acc, + ST_UCHAR *asn1ptr, + ST_INT asn1len, + ST_CHAR *dptr); + +extern ST_INT max_mmsease_types; /* max number allowed */ +extern ST_INT mms_type_count; /* number currently defined */ + +NAMED_TYPE *ms_add_named_type (DOMAIN_OBJS *dom, ST_CHAR *name, + ST_UCHAR *asn1, ST_INT asn1len); +NAMED_TYPE *ms_find_named_type_obj (OBJECT_NAME *obj, + ST_INT chan); +NAMED_TYPE *ms_find_named_type (DOMAIN_OBJS *dom,ST_CHAR *name); +ST_RET ms_del_named_type (DOMAIN_OBJS *dom,ST_CHAR *name); +ST_RET ms_del_type (DOMAIN_OBJS *dom, NAMED_TYPE *name); +ST_VOID ms_del_all_named_types (DOMAIN_OBJS *dom_objs); +ST_RET ms_del_named_type_obj (OBJECT_NAME *obj, ST_INT chan); +ST_RET ms_add_std_types (DOMAIN_OBJS *dom); + +ST_CHAR *rdind_fun (ST_CHAR *addr, ST_INT len); +ST_RET wrind_fun (ST_CHAR *data, ST_CHAR *addr, ST_INT len); + +ST_RET mv_gettype_resp (MMSREQ_IND *ind); +ST_RET mv_gettype_resp (MMSREQ_IND *ind); +ST_RET mv_deltype_resp (MMSREQ_IND *ind); +ST_RET mv_deftype_resp (MMSREQ_IND *ind); + + +/************************************************************************/ +/* Variable definition structures and manipulation functions */ +/************************************************************************/ + +struct named_var /* name table structure */ + { + DBL_LNK link; /* generic list links */ + ST_CHAR varname[MAX_IDENT_LEN+1];/* variable name */ + ST_BOOLEAN invalid; /* variable invalidated due */ + /* to type or addr deleted */ + NAMED_TYPE *type; /* type name/domain */ + ST_BOOLEAN deletable; /* != 0 if deletable */ + ST_UCHAR rd_pro; /* read protection */ + ST_UCHAR wr_pro; /* write protection */ + VAR_ACC_ADDR addr; /* address */ + ST_CHAR *(*read_ind_fun)(ST_CHAR *src, ST_INT len); /* std read ind function ptr */ + ST_INT (*write_ind_fun)(ST_CHAR *src, ST_CHAR *dest, ST_INT len); /* std write ind */ +/* Followed by the address, for symbolic or unconstrained address */ +/* types. The length of this address is determined when the var added */ + SD_END_STRUCT + }; +typedef struct named_var NAMED_VAR; + +struct named_var_list /* name variable list structure */ + { + DBL_LNK link; /* generic list links */ + ST_CHAR name[MAX_IDENT_LEN+1]; /* variable list name */ + ST_BOOLEAN deletable; /* != 0 if deletable */ + ST_INT num_vars; /* # of vars in Named Variable List. */ + /* VARIABLE_LIST var_list [num_of_variables]; */ + SD_END_STRUCT + }; +typedef struct named_var_list NAMED_VAR_LIST; + +extern ST_INT max_mmsease_vars; /* max number allowed */ +extern ST_INT mms_var_count; /* number currently defined */ +extern ST_INT max_mmsease_nvlists; +extern ST_INT mms_nvlist_count; + +/************************************************************************/ +/* This function selects the binary search mechansisms (default) */ +ST_VOID ms_bs_init (ST_VOID); + +/* This function selects the linked list search mechansisms */ +ST_VOID ms_ll_init (ST_VOID); + +NAMED_VAR *ms_add_named_var (DOMAIN_OBJS *dom, ST_CHAR *name, + OBJECT_NAME *type, VAR_ACC_ADDR *addr, + ST_INT chan); +NAMED_VAR *ms_add_var (DOMAIN_OBJS *dom, ST_CHAR *name, + NAMED_TYPE *type, VAR_ACC_ADDR *addr, ST_INT chan); + +NAMED_VAR *ms_find_named_var (DOMAIN_OBJS *dom, ST_CHAR *name); +NAMED_VAR *ms_find_named_var_obj (OBJECT_NAME *obj, ST_INT chan); + +ST_RET ms_del_named_var (DOMAIN_OBJS *dom, ST_CHAR *name); +ST_RET ms_del_named_var_obj (OBJECT_NAME *obj, ST_INT chan); + +ST_VOID ms_del_all_named_vars (DOMAIN_OBJS *dom); + +NAMED_VAR_LIST *ms_add_nvlist (DOMAIN_OBJS *dom, ST_CHAR *name, + ST_INT num_vars, VARIABLE_LIST *var_list); +NAMED_VAR_LIST *ms_find_nvlist (DOMAIN_OBJS *dom, ST_CHAR *name); +NAMED_VAR_LIST *ms_find_nvlist_obj (OBJECT_NAME *obj, ST_INT chan); + +ST_RET ms_del_nvlist (DOMAIN_OBJS *dom, ST_CHAR *name); +ST_RET ms_del_nvlist_obj (OBJECT_NAME *obj, ST_INT chan); + +ST_VOID ms_del_all_nvlists (DOMAIN_OBJS *dom); + +ST_RET mv_getvar_resp (MMSREQ_IND *ind); +ST_RET mv_delvar_resp (MMSREQ_IND *ind); +ST_RET mv_defvar_resp (MMSREQ_IND *ind); +ST_RET mv_namelist_resp (MMSREQ_IND *ind); + +ST_RET mv_getvlist_resp (MMSREQ_IND *ind); +ST_RET mv_delvlist_resp (MMSREQ_IND *ind); +ST_RET mv_defvlist_resp (MMSREQ_IND *ind); + +/************************************************************************/ +/* VIRTUAL MACHINE READ, WRITE, INFORMATION REPORT */ +/* The structure below are used for most variable access VM req funs, */ +/* and allows multiple variables per transaction. */ +/************************************************************************/ +/* VM defines to be used for DataAccessError codes */ +#define ERROR_RESPONSE 20 /* for error response only */ +#define NUM_VAR_MISMATCH 21 + + +struct mv_vardesc /* virtual machine variable description */ + { + OBJECT_NAME name; /* name of variable */ + OBJECT_NAME type; /* type of variable */ + ST_CHAR *data; /* destination/source pointer */ + }; +typedef struct mv_vardesc MV_VARDESC; + +/* This structure is provided as request information for a MV read req. */ +/* If desired, this info may be examined in the user confirm function. */ + +struct readvars_req_info + { /* virtual machine read req structure */ + ST_INT num_of_vars; /* number of variables */ +/* list of variables */ +/* MV_VARDESC vardesc_list [num_of_vars]; */ + SD_END_STRUCT + }; +typedef struct readvars_req_info READVARS_REQ_INFO; + + +/***** READ REQUEST **** */ + +/* a pointer to an array of these structures are passed into the */ +/* 'mv_read_variables' function */ + +struct mv_read_req_info + { + struct /* input (request) information */ + { + ST_CHAR *data_ptr; /* Dest data buffer (for success) */ + NAMED_TYPE *type; /* pointer to associated type */ + ST_BOOLEAN alt_acc_pres; /* set SD_TRUE if Alt Access is present */ + ST_BOOLEAN alt_acc_type_aa; /* set SD_TRUE if type is Alt Acc ready */ + ST_BOOLEAN alt_acc_data_packed; /* set SD_TRUE if local data is packed */ + ALT_ACCESS alt_acc; /* Alternate Access specification */ + }i; + struct /* output (result) information */ + { + ST_RET result; /* !=0 for success, else SD_FAILURE */ + ST_INT16 err_code; /* DataAccessError (for failure) */ + +/* If a named type is not supplied, and the read was a success, this */ +/* is the derived runtime type. It was allocated using 'chk_calloc' */ +/* and must be free'd using 'chk_free' */ + + ST_INT num_rt; + RUNTIME_TYPE *rt_out; + +/* If a data_ptr is not supplied, and the read was a success, this */ +/* is the buffer allocated for the data. It was allocated using */ +/* 'chk_calloc' and must be free'd using 'chk_free' */ + + ST_CHAR *data_ptr_out; /* Dest data buffer (for success) */ + }o; + }; +typedef struct mv_read_req_info MV_READ_REQ_INFO; + +MMSREQ_PEND *mv_read (ST_INT chan, OBJECT_NAME *name, + OBJECT_NAME *type, ST_CHAR *dest); +MMSREQ_PEND *mv_readvars (ST_INT chan, ST_INT num_var, MV_VARDESC *info); +MMSREQ_PEND *mv_read_variables (ST_INT chan, ST_INT num_var, + READ_REQ_INFO *prim, + MV_READ_REQ_INFO *vminfo); + +/***** READ RESPONSE ***** */ + +/* a pointer to an array of these structures are passed into the */ +/* 'mv_read_response' function */ + +struct mv_read_resp_info + { + ST_INT16 result; /* ACC_RSLT_SUCCESS, ACC_RSLT_FAILURE */ + ST_INT16 err_code; /* DataAccessError (for failure) */ + ST_CHAR *data_ptr; /* Source data buffer (for success) */ + NAMED_TYPE *type; /* pointer to associated type */ + ST_BOOLEAN alt_acc_pres; /* set SD_TRUE if Alt Access is present */ + ST_BOOLEAN alt_acc_data_packed;/* set SD_TRUE if local data is packed */ + ALT_ACCESS alt_acc; /* Alternate Access specification */ + }; +typedef struct mv_read_resp_info MV_READ_RESP_INFO; + +ST_RET mv_read_resp (MMSREQ_IND *ind); +ST_RET mv_read_response (MMSREQ_IND *ind, ST_INT num_var, + MV_READ_RESP_INFO *info); + +/***** WRITE REQUEST **** */ + +/* a pointer to an array of these structures are passed into the */ +/* 'mv_write_variables' function */ + +struct mv_write_req_info + { + ST_CHAR *data_ptr; /* Source data buffer */ + NAMED_TYPE *type; /* pointer to associated type */ + ST_BOOLEAN alt_acc_pres; /* set SD_TRUE if Alt Access is present */ + ST_BOOLEAN alt_acc_type_aa; /* set SD_TRUE if type is Alt Acc ready */ + ST_BOOLEAN alt_acc_data_packed;/* set SD_TRUE if local data is packed */ + ALT_ACCESS alt_acc; /* Alternate Access specification */ + }; +typedef struct mv_write_req_info MV_WRITE_REQ_INFO; + +MMSREQ_PEND *mv_write (ST_INT chan, OBJECT_NAME *var, + OBJECT_NAME *type, ST_CHAR *src); +MMSREQ_PEND *mv_writevars (ST_INT chan, ST_INT num_var, MV_VARDESC *info); +MMSREQ_PEND *mv_write_variables (ST_INT chan, ST_INT num_data, + VAR_ACC_SPEC *reqinfo, + MV_WRITE_REQ_INFO *vminfo); + +/***** WRITE RESPONSE **** */ + +ST_RET mv_write_resp (MMSREQ_IND *ind); +WRITE_RESP_INFO *mv_write_decode (MMSREQ_IND *indptr); +ST_RET ms_extract_write_data (MMSREQ_IND *ind, ST_INT index, + NAMED_TYPE *type, + ST_CHAR *dest, ST_BOOLEAN alt_acc_packed); + +ST_RET ms_extract_wr_data (MMSREQ_IND *indptr, ST_INT i, + NAMED_TYPE *type, ST_CHAR *dest, + ST_BOOLEAN alt_acc_packed, ALT_ACCESS *alt_acc_ptr); + +/***** INFORMATION REPORT REQUEST ***** */ + +/* a pointer to an array of these structures are passed into the */ +/* 'mv_info_req' function */ + +struct mv_info_req_info + { + ST_CHAR *data_ptr; /* Source data buffer */ + NAMED_TYPE *type; /* pointer to associated type */ + ST_BOOLEAN alt_acc_pres; /* set SD_TRUE if Alt Access is present */ + ST_BOOLEAN alt_acc_data_packed;/* set SD_TRUE if local data is packed */ + ALT_ACCESS alt_acc; /* Alternate Access specification */ + }; +typedef struct mv_info_req_info MV_INFO_REQ_INFO; + +ST_RET mv_info (ST_INT chan, OBJECT_NAME *var, OBJECT_NAME *type, + ST_CHAR *src); +ST_RET mv_infovars (ST_INT chan, ST_INT num_vars, MV_VARDESC *vminfo); +ST_RET mv_info_report (ST_INT chan, VAR_ACC_SPEC *req, + ST_INT num_var, MV_INFO_REQ_INFO *vminfo); +ST_RET mv_info_nvlist (ST_INT chan, OBJECT_NAME *obj); + +ST_RET ms_extract_info_data (MMSREQ_IND *ind, ST_INT index, + NAMED_TYPE *type, ST_CHAR *dest, + ST_BOOLEAN alt_acc_packed); + +ST_RET ms_extract_inf_data (MMSREQ_IND *indptr, ST_INT i, + NAMED_TYPE *type, ST_CHAR *dest, + ST_BOOLEAN alt_acc_packed, + ALT_ACCESS *alt_acc_ptr); + +/************************************************************************/ + +OBJECT_NAME *ms_extract_varname (ST_CHAR *reqinfo, ST_INT op, ST_INT indx); + +/************************************************************************/ +/************************************************************************/ +#endif /* end of MMS_LITE not defined */ +/************************************************************************/ +/************************************************************************/ + +#define MMS_EASE_BUILDER 0 +#define UNKNOWN_BUILDER 1 + +extern ST_INT ms_req_bld_id; +extern ST_INT ms_resp_bld_id; + +ST_RET ms_init_va_size (ST_INT chan, ST_UCHAR spec_in_rslt, + ST_INT16 var_acc_tag, OBJECT_NAME *vl_name, + ST_LONG *req_size_out, ST_LONG *resp_size_out); + +#ifndef MMS_LITE +ST_RET ms_va_size (ST_INT op, ST_UCHAR spec_in_rslt, ST_INT16 var_acc_tag, + VARIABLE_LIST *vl, NAMED_TYPE *type, + ST_LONG *req_size_out, ST_LONG *resp_size_out); +#else +ST_RET ms_va_size (ST_INT op, ST_UCHAR spec_in_rslt, ST_INT16 var_acc_tag, + VARIABLE_LIST *vl_ptr, ST_INT type_id, + ST_LONG *req_size, ST_LONG *resp_size); +#endif + +/************************************************************************/ +/************************************************************************/ + +extern ST_INT m_rt_type_limit; /* max num of runtime blks per def */ + + +#ifndef MMS_LITE +ST_INT ms_get_blocked_len (NAMED_TYPE *type); +#endif + +ST_INT ms_get_blocked_length (SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt); + +ST_RET ms_runtime_to_asn1 (ASN1_ENC_CTXT *aCtx, SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt); + +ST_UCHAR *ms_mk_asn1_type (ST_INT *asn1_len, ST_UCHAR *asn1_buf, + ST_CHAR *tdl); + +ST_VOID ms_log_runtime (SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt); + +ST_CHAR *ms_asn1_to_tdl (ST_UCHAR *asn1_ptr, ST_INT asn1_len, + ST_INT max_tdl_len); +ST_INT ms_runtime_to_tdl (SD_CONST RUNTIME_TYPE *rt, ST_INT rt_num, + ST_CHAR *tdl_buf, ST_INT max_tdl_len); + +RUNTIME_CTRL *ms_tdl_to_runtime (ST_CHAR *tdl, /* TDL string */ + ST_UCHAR *asn1_buf, /* ASN.1 buffer */ + ST_INT asn1_buf_len); /* buffer len */ + +ST_RET ms_rt_to_typedef (ST_CHAR *typedefName, SD_CONST RUNTIME_TYPE *rt, + ST_INT numRt, ST_CHAR *dest, ST_INT destSize); + +RUNTIME_CTRL *ms_runtime_create (ST_UCHAR *asn1_data, + ST_UINT asn1_len, + ST_INT max_num_rt); +ST_VOID ms_runtime_destroy (RUNTIME_CTRL *rt_head); + +#if !defined(MMS_LITE) +/* For backward compatibility only. */ +/* New programs should use ms_runtime_create. */ + +ST_INT ms_asn1_to_runtime_x (ST_UCHAR *asn1_data, ST_UINT asn1_len, + RUNTIME_TYPE *rt_table, ST_INT rt_len, + ST_BOOLEAN calc_only); + +#define ms_asn1_to_runtime(asn1,asn1_len,rt,num_rt)\ + ms_asn1_to_runtime_x(asn1,asn1_len,rt, num_rt,m_calc_rt_size) + +/* Note: This variable is no longer used internally by MMS-EASE, but */ +/* can be used in the application space for the following: */ +/* 1. Is used in the macro 'ms_asn1_to_runtime' for the */ +/* 'ms_asn1_to_runtime_x' calc_only parameter. This is done to */ +/* maintain backward compatibility, and users are encouraged to */ +/* use 'ms_runtime_create' instead. */ +extern ST_BOOLEAN m_calc_rt_size; /* flag to calculate num rt blocks */ + /* in ms_asn1_to_runtime */ +#endif /* !MMS_LITE */ + +/************************************************************************/ +/* ms_comp_name_find */ +/* These macros find the component name in a runtime type structure. */ +/* There are different macros for different RUNTIME_TYPE structures. */ +/* Macro argument = ptr to RUNTIME_TYPE struct. */ +/* RETURN: pointer to component name string */ +/************************************************************************/ +#if defined(USE_RT_TYPE_2) + +/* rt->comp_name_ptr = pointer to string */ +/* NOTE: ptr may be NULL. If so return empty string (i.e. "") instead */ +/* of NULL. Caller might not handle NULL. */ +#define ms_comp_name_find(rt) ((rt)->comp_name_ptr ? (rt)->comp_name_ptr : "") +#define ms_comp_name_pres(rt) ((rt)->comp_name_ptr ? SD_TRUE : SD_FALSE) + +#elif defined(USE_RT_TYPE_3) + +/* rt->name_index = index to global array of strings "mvlRtNames" */ +#define ms_comp_name_find(rt) (mvlRtNames[(rt)->name_index]) +#define ms_comp_name_pres(rt) ((rt)->name_index > 0 ? SD_TRUE : SD_FALSE) + +#else /* Default */ + +/* rt->name = character array. */ +#define ms_comp_name_find(rt) ((rt)->name) +#define ms_comp_name_pres(rt) ((rt)->name[0] != 0 ? SD_TRUE : SD_FALSE) + +#endif /* Default */ + + +/************************************************************************/ +/* VIRTUAL MACHINE ASN.1 TO?FROM LOCAL REPRESENTATION FUNCTIONS */ +/* These functions are used to translate ASN.1 encoded data to/from */ +/* local format */ +/************************************************************************/ + +#ifndef MMS_LITE +ST_RET ms_asn1_to_locl (NAMED_TYPE *type, + ST_UCHAR *asn1, ST_INT asn1_len, ST_CHAR *dest); +ST_RET ms_locl_to_asn1 (ASN1_ENC_CTXT *aCtx, NAMED_TYPE *type, ST_CHAR *src); +#endif + +/* These 2 are Re-entrant functions. Based on ASN1R tools. */ +ST_RET ms_asn1_to_local (SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt, + ST_UCHAR *asn1, ST_INT asn1_len, ST_CHAR *dest); +ST_RET ms_local_to_asn1 (ASN1_ENC_CTXT *aCtx, + SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, + ST_CHAR *dptr); +/* "ms_local_to_asn1_2" is almost the same as "ms_local_to_asn1_easy" */ +/* but its arguments are more consistent with other encoding functions. */ +ST_RET ms_local_to_asn1_2 (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + ST_CHAR *dptr, + ST_UCHAR *buf_ptr, + ST_INT buf_len, + ST_UCHAR **asn1_ptr_out, + ST_INT *asn1_len_out); +ST_UCHAR *ms_local_to_asn1_easy (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + ST_CHAR *dptr, + ST_UCHAR *asn1Buf, + ST_INT asn1BufLen, + ST_INT *asn1LenOut); +ST_CHAR *ms_local_to_text (ST_CHAR *datptr, SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + ST_CHAR *textBuf, ST_UINT textBufSize); + + + +/* Index definitions into the alignment table */ +#define ARRSTRT_ALGN 0 +#define ARREND_ALGN 1 +#define STRSTRT_ALGN 2 +#define STREND_ALGN 3 +#define INT8_ALGN 4 +#define INT16_ALGN 5 +#define INT32_ALGN 6 +#define INT64_ALGN 7 +#define FLOAT_ALGN 8 +#define DOUBLE_ALGN 9 +#define OCT_ALGN 10 +#define BOOL_ALGN 11 +#define BCD1_ALGN 12 +#define BCD2_ALGN 13 +#define BCD4_ALGN 14 +#define BIT_ALGN 15 +#define VIS_ALGN 16 + +#define NUM_ALGN_TYPES 17 + +/* define alignment for Generalized Time (in VS 2005 time_t is 64-bits) */ +#define GENERAL_TIME_ALGN (sizeof(time_t) == 8 ? INT64_ALGN : INT32_ALGN) + + +extern SD_CONST ST_INT *m_data_algn_tbl; +extern SD_CONST ST_INT m_packed_data_algn_tbl[NUM_ALGN_TYPES]; +extern SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES]; +extern ST_INT m_lite_data_algn_tbl[NUM_ALGN_TYPES]; /* created by Foundry */ + +#define M_STRSTART_MODE_NONE 0 +#define M_STRSTART_MODE_FIRST 1 +#define M_STRSTART_MODE_LARGEST 2 +extern ST_INT m_struct_start_algn_mode; + +#define M_STREND_MODE_NONE 0 +#define M_STREND_MODE_LARGEST 1 +extern ST_INT m_struct_end_algn_mode; + +/* User defined runtime type post processing function */ +extern ST_VOID (*u_rt_type_process) (SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt); + + +/************************************************************************/ +/************************************************************************/ + +/* For encoding and decoding 'alternateAccess', the outer constructor */ +/* usually has a value of 5. If a different value is required (for */ +/* scattered access, for instance), this value can be modified. */ +/* Used in both encoding and decode of alternateAccess */ +extern ST_INT16 m_alt_acc_outer_tag; + +/* When decoding an ASN.1 alternateAccess, this variable determines the */ +/* size of the table that is allocated for the decoded AA (and so */ +/* limits the complexity of the alternate access that can be handled */ +/* The default value is 50. */ +extern ST_INT m_max_dec_aa; + +/* This variable is the 'high water' mark of how many AA were actually */ +/* required. This can be used to tune memory usage if desired. */ +extern ST_INT m_hw_dec_aa; + +/* When performing ASN1 <-> local data format, the runtime type is */ +/* 'unrolled', and one element is required for each data element and */ +/* structure/array start/end. This variable determines the size of the */ +/* of the table that is allocated for this operation (and so limits the */ +/* size and complexity of the data types that can be handled. */ +/* The default value is 1000. */ +extern ST_INT m_max_rt_aa_ctrl; + +/* This variable is the 'high water' mark of how many elements were */ +/* actually required for m_max_rt_aa_ctrl. This can be used to tune */ +/* memory usage if desired. */ +extern ST_INT m_hw_rt_aa_ctrl; + +/* This variable is used to determine whether the local data format is */ +/* in 'packed type' or 'original type' form. Used in all conversions */ +/* to/from local data form when the AA_DATA library is used. */ +/* Temporarily set to SD_FALSE for the non-AA data conversion functions. */ +extern ST_BOOLEAN m_alt_acc_packed; + +/************************************************************************/ + +extern ST_RET (*ms_asn1_data_to_runtime_fun) (RUNTIME_TYPE **tptr, + ST_INT *t_len, + ST_UCHAR *asn1ptr, + ST_INT asn1_len); + +ST_RET ms_asn1_data_to_runtime (RUNTIME_TYPE **tptr, + ST_INT *t_len, + ST_UCHAR *asn1ptr, + ST_INT asn1_len); + +ST_RET ms_asn1_data_to_locl (ST_UCHAR *asn1_data, + ST_INT asn1_data_len, + ST_VOID **data_dest, + ST_INT *data_dest_len, + RUNTIME_TYPE **rt, + ST_INT *t_len); + +ST_VOID ms_rt_size_calc (RUNTIME_TYPE *rt_head, ST_INT rt_num); + +/************************************************************************/ +/* ARBITRARY DATA HANDLING */ +/************************************************************************/ + +typedef struct m_arb_data_ctrl + { + ST_RET (*arrStart) (RT_AA_CTRL *rtaa); + ST_RET (*arrEnd) (RT_AA_CTRL *rtaa); + ST_RET (*strStart) (RT_AA_CTRL *rtaa); + ST_RET (*strEnd) (RT_AA_CTRL *rtaa); + ST_RET (*int8) (ST_INT8 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*int16) (ST_INT16 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*int32) (ST_INT32 *data_dest, RT_AA_CTRL *rtaa); +#ifdef INT64_SUPPORT + ST_RET (*int64) (ST_INT64 *data_dest, RT_AA_CTRL *rtaa); +#endif + ST_RET (*uint8) (ST_UINT8 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*uint16) (ST_UINT16 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*uint32) (ST_UINT32 *data_dest, RT_AA_CTRL *rtaa); +#ifdef INT64_SUPPORT + ST_RET (*uint64) (ST_UINT64 *data_dest, RT_AA_CTRL *rtaa); +#endif + ST_RET (*flt) (ST_FLOAT *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*dbl) (ST_DOUBLE *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*oct) (ST_UCHAR *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*booln) (ST_BOOLEAN *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*bcd1) (ST_INT8 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*bcd2) (ST_INT16 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*bcd4) (ST_INT32 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*bs) (ST_UCHAR *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*vis) (ST_CHAR *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*bt4) (ST_INT32 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*bt6) (ST_INT32 *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*gt) (time_t *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*utc) (MMS_UTC_TIME *data_dest, RT_AA_CTRL *rtaa); + ST_RET (*utf8) (ST_UCHAR *data_dest, RT_AA_CTRL *rtaa); + } M_ARB_DATA_CTRL; + +ST_RET ms_process_arb_data (ST_CHAR *data_base, + SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + ST_BOOLEAN alt_acc_pres, ST_BOOLEAN alt_acc_packed, + ALT_ACCESS *alt_acc, + M_ARB_DATA_CTRL *ac); + +/************************************************************************/ +/* Functions for building a type definition one component at a time. */ +/************************************************************************/ +ST_VOID ms_rt_bld_start (RUNTIME_BUILD_CTXT *rt_ctxt, ST_INT max_rt_num); +ST_VOID ms_rt_bld_cancel (RUNTIME_BUILD_CTXT *rt_ctxt); +ST_VOID ms_rt_bld_finish (RUNTIME_BUILD_CTXT *rt_ctxt); +ST_RET ms_rt_bld_add_str_start (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name); +ST_RET ms_rt_bld_add_str_end (RUNTIME_BUILD_CTXT *ctxt); +ST_RET ms_rt_bld_add_arr_start (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT array_count); +ST_RET ms_rt_bld_add_arr_end (RUNTIME_BUILD_CTXT *ctxt); +ST_RET ms_rt_bld_add_bool (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name); +ST_RET ms_rt_bld_add_int (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_uint (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_float (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_bstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_bvstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_vstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_utctime (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name); +ST_RET ms_rt_bld_add_btime6 (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name); +ST_RET ms_rt_bld_add_ostring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_ovstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_utf8vstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len); +ST_RET ms_rt_bld_add_special (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, RUNTIME_TYPE *special); +ST_RET ms_rt_bld_remove_last (RUNTIME_BUILD_CTXT *ctxt); +ST_RET ms_rt_bld_chk_state (RUNTIME_BUILD_CTXT *ctxt); +ST_INT ms_rt_bld_get_count (RUNTIME_BUILD_CTXT *ctxt); +ST_INT ms_rt_bld_get_max_count (RUNTIME_BUILD_CTXT *ctxt); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/mmslib/inc/mmsdefs.h b/mmslib/inc/mmsdefs.h new file mode 100644 index 0000000..5caa0c4 --- /dev/null +++ b/mmslib/inc/mmsdefs.h @@ -0,0 +1,235 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2004, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsdefs.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This include file is for MMS-EASE or SMALL-MMS programmer use, */ +/* and calls out all needed include files. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/09/07 JRB 14 Add forward references. */ +/* 04/09/07 MDE 13 Enhanced filtered logging */ +/* 09/17/04 EJV 12 Added mms_chk_resource. */ +/* 10/13/03 EJV 11 Moved MMSEASE_VERSION define to mms_defs.h. */ +/* 10/07/03 EJV 10 Added MMSEASE_VERSION define. */ +/* 12/12/02 JRB 09 Add ASN1_ENC_CTXT arg to _mms_unconf_req_fin */ +/* 01/18/02 JRB 08 Replace _ms_fin_pdu_debug with _ms_fin_pdu */ +/* and _ms_fin_pdu_log. */ +/* 12/20/01 JRB 07 Convert to use ASN1R. */ +/* 09/26/00 JRB 06 Add SD_CONST on ms_mk_rt_aa* */ +/* 06/01/00 RKR 05 Removed prot mms_null_pdu_dec use mms_dfun.h */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 More changes to allow compile under C++ */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/20/98 JRB 01 Del mmsop_en.h. Only user code needs it now. */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMSDEFS_INCLUDED +#define MMSDEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "glberror.h" + +#ifndef MMS_LITE +#include "gen_list.h" +#include "mem_chk.h" +#include "mms_defs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mmsintrn.h" +#include "mms_mp.h" +#include "mms_mv.h" +#include "mms_err.h" +#else +#include "mem_chk.h" +#include "mms_def2.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mmsintr2.h" +#include "mms_mp.h" +#include "mmsldefs.h" +#endif + +#include "mms_dfun.h" +#include "mms_perr.h" +#include "mms_log.h" +#include "mmslog.h" + +#include "mms_pcon.h" +#include "mms_pdom.h" +#include "mms_pevn.h" +#include "mms_pfil.h" +#include "mms_pjou.h" +#include "mms_pocs.h" +#include "mms_pprg.h" +#include "mms_psem.h" +#include "mms_pvmd.h" + +/************************************************************************/ +/* For use when global variables cannot be initialized at compile time */ + +#if defined (NO_GLB_VAR_INIT) +ST_VOID m_init_glb_vars (ST_VOID); +#endif + +/************************************************************************/ +ST_VOID _ms_wr_service_err (ASN1_ENC_CTXT *ac, ST_INT16 eclass, ST_INT16 code, + ADTNL_ERR_RESP_INFO *adtnl_info); + +/************************************************************************/ +/* Variable Access Functions. */ +/************************************************************************/ + +ST_VOID _mms_get_service_err (ASN1_DEC_CTXT *ac, ERR_INFO *dest); +ST_VOID _ms_get_mms_fname (ASN1_DEC_CTXT *ac, FILE_NAME *dest, ST_INT max_fnames, ST_INT *num_out); +ST_VOID _ms_get_mms_app_ref (ASN1_DEC_CTXT *ac, ST_UCHAR **dest, ST_INT *dest_size, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_mms_evtime (ASN1_DEC_CTXT *ac, EVENT_TIME *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_mms_modlist (ASN1_DEC_CTXT *ac, MODIFIER *dest, ST_INT *num_out, ST_INT max_mods, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_mms_objname (ASN1_DEC_CTXT *ac, OBJECT_NAME *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_jou_ent_cont (ASN1_DEC_CTXT *ac, ENTRY_CONTENT *dest, ST_INT dest_size, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_address (ASN1_DEC_CTXT *ac, VAR_ACC_ADDR *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_access_rslt (ASN1_DEC_CTXT *ac, ACCESS_RESULT *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_data (ASN1_DEC_CTXT *ac, VAR_ACC_DATA *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_type_spec (ASN1_DEC_CTXT *ac, VAR_ACC_TSPEC *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_scat_access (ASN1_DEC_CTXT *ac, SCATTERED_ACCESS *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_alt_access (ASN1_DEC_CTXT *ac, ALTERNATE_ACCESS *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_var_spec (ASN1_DEC_CTXT *ac, VARIABLE_SPEC *dest, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_var_list (ASN1_DEC_CTXT *ac, VARIABLE_LIST *dest, ST_INT *num_out, ST_INT max_num, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_get_va_spec (ASN1_DEC_CTXT *ac, VAR_ACC_SPEC *dest, ST_INT max_vars, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); + +ST_VOID _ms_wr_mms_fname (ASN1_ENC_CTXT *ac, FILE_NAME *src, ST_INT num); +ST_VOID _ms_wr_mms_evtime (ASN1_ENC_CTXT *ac, EVENT_TIME *src); +ST_VOID _ms_wr_mms_modlist (ASN1_ENC_CTXT *ac, MODIFIER *src, ST_INT num); +ST_VOID _ms_wr_mms_objname (ASN1_ENC_CTXT *ac, OBJECT_NAME *src); +ST_VOID _ms_wr_jou_ent_cont (ASN1_ENC_CTXT *ac, ENTRY_CONTENT *src); +ST_VOID _ms_wr_va_address (ASN1_ENC_CTXT *ac, VAR_ACC_ADDR *src); +ST_VOID _ms_wr_va_access_rslt (ASN1_ENC_CTXT *ac, ACCESS_RESULT *src); +ST_VOID _ms_wr_va_data (ASN1_ENC_CTXT *ac, VAR_ACC_DATA *src); +ST_VOID _ms_wr_va_type_spec (ASN1_ENC_CTXT *ac, VAR_ACC_TSPEC *src); +ST_VOID _ms_wr_va_scat_access (ASN1_ENC_CTXT *ac, SCATTERED_ACCESS *src); +ST_VOID _ms_wr_va_alt_access (ASN1_ENC_CTXT *ac, ALTERNATE_ACCESS *src); +ST_VOID _ms_wr_va_var_spec (ASN1_ENC_CTXT *ac, VARIABLE_SPEC *src); +ST_VOID _ms_wr_va_var_list (ASN1_ENC_CTXT *ac, VARIABLE_LIST *src, ST_INT num); +ST_VOID _ms_wr_va_spec (ASN1_ENC_CTXT *ac, VAR_ACC_SPEC *src); + +ST_VOID _mms_init_dec (ASN1_DEC_CTXT *ac, ST_BOOLEAN req); + +/************************************************************************/ +/* Alternate Access Functions */ +/************************************************************************/ +ST_VOID _ms_log_runtime_aa (RT_AA_CTRL *rt_aa, ST_INT num_aa); + +ST_RET _ms_mk_rt_aa_all (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + RT_AA_CTRL **rt_aa_out, ST_INT *num_aa_out); + +ST_RET _ms_mk_rt_aa (SD_CONST RUNTIME_TYPE *rt, ST_INT rt_num, + ALT_ACCESS *alt_acc, + RT_AA_CTRL **rt_aa_out, ST_INT *num_aa_out); + +ST_INT _ms_get_rtaa_data_size (RT_AA_CTRL *runtime_aa, ST_INT num_rt_aa); + +/************************************************************************/ +/* Special ASN.1 buffer handling functions for VM operations where */ +/* a series of ASN.1 encoded AA must be created. */ + +ST_UCHAR *_m_get_aa_asn1_buf (ST_INT *size_out); +ST_VOID _m_free_aa_asn1_buf (ST_VOID); +ST_VOID _m_set_aa_asn1_buf_end (ST_UCHAR *new_end); + +/************************************************************************/ +/************************************************************************/ +/* General function declarations used by the mp_xxx series. */ +/* These are not of general use to the application programmer. */ +/************************************************************************/ + +ST_VOID _ms_chk_for_extern (ASN1_DEC_CTXT *ac, ST_INT *len_ptr, ST_UCHAR **buf_ptr, ST_VOID (*done)(ASN1_DEC_CTXT *ac)); +ST_VOID _ms_set_cs_check (ASN1_DEC_CTXT *ac); +ST_VOID _ms_set_cs_check2 (ASN1_DEC_CTXT *ac); +ST_VOID _mms_dec_done_ok (ASN1_DEC_CTXT *ac); + +ST_UCHAR *_ms_fin_pdu (ASN1_ENC_CTXT *aCtx, ST_INT type, ST_INT *pPduLen); +#ifdef DEBUG_SISCO +ST_VOID _ms_fin_pdu_log (ST_INT type, ST_CHAR *txt, + ST_UCHAR *pduPtr, ST_INT pduLen); +#endif + +ST_VOID _mms_dec_buf_free (ASN1_DEC_CTXT *ac, ST_RET err_code); +#ifndef MMS_LITE +ST_RET _mms_send_null_resp (MMSREQ_IND *indptr, ST_INT opcode); +MMSREQ_PEND *_mms_send_null_req (ST_INT chan, ST_INT opcode); + +MMSREQ_PEND *_mms_req_send (ST_INT opcode, + ST_VOID (*mk_ptr)(ASN1_ENC_CTXT *, ST_CHAR *), + ST_INT chan, + ST_CHAR *info_ptr); + +ST_INT _mms_chk_resource (ST_INT chan); +ST_RET _mms_unconf_req_send (ST_INT opcode, + ST_VOID (*mk_ptr)(ASN1_ENC_CTXT *, ST_CHAR *), + ST_INT chan, + ST_CHAR *info_ptr); + +ST_RET _mms_resp_send (ST_INT opcode, + MMSREQ_IND *indptr, + ST_VOID (*mk_fun)(ASN1_ENC_CTXT *, ST_CHAR *), + ST_CHAR *info_ptr); + +#else +ST_RET _mms_fin_null_resp (ST_UINT32 invoke_id, ST_INT opcode); +ST_RET _mms_fin_null_req (ST_INT opcode); + +ST_RET _mms_resp_fin (ST_INT opcode, ST_UINT32 invoke_id, + ST_VOID (*mk_fun)(ASN1_ENC_CTXT *, ST_CHAR *), + ST_CHAR *info_ptr); + +ST_RET _mms_req_fin (ST_INT opcode, + ST_VOID (*mk_ptr)(ASN1_ENC_CTXT *, ST_CHAR *), + ST_CHAR *info_ptr); + +ST_RET _mms_unconf_req_fin (ASN1_ENC_CTXT *aCtx, ST_INT opcode, + ST_VOID (*mk_ptr)(ASN1_ENC_CTXT *, ST_CHAR *), + ST_CHAR *info_ptr); + +struct mvl_req_pend; /* forward reference */ +struct mvl_ind_pend; /* forward reference */ +struct mvl_net_info; /* forward reference */ + +ST_VOID mpl_req_log (struct mvl_req_pend *reqCtrl, ST_VOID *reqInfo); +ST_VOID mpl_resp_log (struct mvl_ind_pend *indCtrl, ST_VOID *respInfo); +ST_VOID mpl_unsol_req_log (struct mvl_net_info *netInfo, ST_INT op, ST_VOID *reqInfo); + +#endif + +/* A casting aid ... */ +#define M_CAST_MK_FUN(x) ((ST_VOID(*)(ASN1_ENC_CTXT *, ST_CHAR *)) x) + + +#ifndef MMS_LITE +#include "mms_llp.h" +#include "mmsllp.h" +#endif + +#include "mmsefun.h" /* Bruder moved this here */ +#ifdef __cplusplus +} +#endif + +#endif /* MMSDEFS_INCLUDED */ + + diff --git a/mmslib/inc/mmsefun.h b/mmslib/inc/mmsefun.h new file mode 100644 index 0000000..4db5135 --- /dev/null +++ b/mmslib/inc/mmsefun.h @@ -0,0 +1,188 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsefun.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file has the function declarations used by the primitive */ +/* level encode routines (mp_xxxx). */ +/* */ +/* Parameters : pointer to the operation specific data structure. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Convert to use ASN1R. */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMSEFUN_INCLUDED +#define MMSEFUN_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/* primitive encode functions */ +/************************************************************************/ + +ST_UCHAR *_ms_mk_init (ASN1_ENC_CTXT *ac, ST_UCHAR *buf_ptr, ST_INT buf_len, + INIT_INFO *info_ptr, ST_INT pdutype, + ST_BOOLEAN cs_init); + +ST_UCHAR *_ms_mk_conclude (ASN1_ENC_CTXT *ac, ST_UCHAR *buf_ptr,ST_INT buf_len,ST_INT pdutype); + +ST_UCHAR *_ms_mk_cancel (ASN1_ENC_CTXT *ac, ST_BOOLEAN request, ST_UCHAR *msg_ptr, + ST_INT buf_len, ST_UINT32 id); + +ST_UCHAR *_ms_mk_reject (ASN1_ENC_CTXT *ac, ST_UCHAR *msg_ptr, ST_INT buf_len, + REJECT_RESP_INFO *info_ptr); + +ST_UCHAR *_ms_mk_err_resp (ASN1_ENC_CTXT *ac, ST_UCHAR *buf_ptr, ST_INT buf_len, ST_INT op, + ST_UINT32 id, ST_INT16 err_class, ST_INT16 code); + +ST_VOID _ms_mk_stat_req (ASN1_ENC_CTXT *ac, STATUS_REQ_INFO *info); +ST_VOID _ms_mk_stat_resp (ASN1_ENC_CTXT *ac, STATUS_RESP_INFO *info); +ST_VOID _ms_mk_ustat_req (ASN1_ENC_CTXT *ac, USTATUS_REQ_INFO *info); +ST_VOID _ms_mk_namel_req (ASN1_ENC_CTXT *ac, NAMELIST_REQ_INFO *info); +ST_VOID _ms_mk_namel_resp (ASN1_ENC_CTXT *ac, NAMELIST_RESP_INFO *info); +ST_VOID _ms_mk_ident_resp (ASN1_ENC_CTXT *ac, IDENT_RESP_INFO *info); +ST_VOID _ms_mk_rename_req (ASN1_ENC_CTXT *ac, RENAME_REQ_INFO *info); +ST_VOID _ms_mk_getcl_req (ASN1_ENC_CTXT *ac, GETCL_REQ_INFO *info); +ST_VOID _ms_mk_getcl_resp (ASN1_ENC_CTXT *ac, GETCL_RESP_INFO *info); + +ST_VOID _ms_mk_initdown_req (ASN1_ENC_CTXT *ac, INITDOWN_REQ_INFO *info); +ST_VOID _ms_mk_initdown_resp (ASN1_ENC_CTXT *ac, ST_VOID *dummy_info); +ST_VOID _ms_mk_download_req (ASN1_ENC_CTXT *ac, DOWNLOAD_REQ_INFO *info); +ST_VOID _ms_mk_download_resp (ASN1_ENC_CTXT *ac, DOWNLOAD_RESP_INFO *info); +ST_VOID _ms_mk_termdown_req (ASN1_ENC_CTXT *ac, TERMDOWN_REQ_INFO *info); +ST_VOID _ms_mk_initupl_req (ASN1_ENC_CTXT *ac, INITUPL_REQ_INFO *info); +ST_VOID _ms_mk_initupl_resp (ASN1_ENC_CTXT *ac, INITUPL_RESP_INFO *info); +ST_VOID _ms_mk_upload_req (ASN1_ENC_CTXT *ac, UPLOAD_REQ_INFO *info); +ST_VOID _ms_mk_upload_resp (ASN1_ENC_CTXT *ac, UPLOAD_RESP_INFO *info); +ST_VOID _ms_mk_termupl_req (ASN1_ENC_CTXT *ac, TERMUPL_REQ_INFO *info); +ST_VOID _ms_mk_rddwn_req (ASN1_ENC_CTXT *ac, RDDWN_REQ_INFO *info); +ST_VOID _ms_mk_rdupl_req (ASN1_ENC_CTXT *ac, RDUPL_REQ_INFO *info); +ST_VOID _ms_mk_loaddom_req (ASN1_ENC_CTXT *ac, LOADDOM_REQ_INFO *info); +ST_VOID _ms_mk_storedom_req (ASN1_ENC_CTXT *ac, STOREDOM_REQ_INFO *info); +ST_VOID _ms_mk_deldom_req (ASN1_ENC_CTXT *ac, DELDOM_REQ_INFO *info); +ST_VOID _ms_mk_getdom_req (ASN1_ENC_CTXT *ac, GETDOM_REQ_INFO *info); +ST_VOID _ms_mk_getdom_resp (ASN1_ENC_CTXT *ac, GETDOM_RESP_INFO *info); + +ST_VOID _ms_mk_crepi_req (ASN1_ENC_CTXT *ac, CREPI_REQ_INFO *info); +ST_VOID _ms_mk_delpi_req (ASN1_ENC_CTXT *ac, DELPI_REQ_INFO *info); +ST_VOID _ms_mk_start_req (ASN1_ENC_CTXT *ac, START_REQ_INFO *info); +ST_VOID _ms_mk_stop_req (ASN1_ENC_CTXT *ac, STOP_REQ_INFO *info); +ST_VOID _ms_mk_resume_req (ASN1_ENC_CTXT *ac, RESUME_REQ_INFO *info); +ST_VOID _ms_mk_reset_req (ASN1_ENC_CTXT *ac, RESET_REQ_INFO *info); +ST_VOID _ms_mk_kill_req (ASN1_ENC_CTXT *ac, KILL_REQ_INFO *info); +ST_VOID _ms_mk_getpi_req (ASN1_ENC_CTXT *ac, GETPI_REQ_INFO *info); +ST_VOID _ms_mk_getpi_resp (ASN1_ENC_CTXT *ac, GETPI_RESP_INFO *info); + +ST_VOID _ms_mk_read_req (ASN1_ENC_CTXT *ac, READ_REQ_INFO *info); +ST_VOID _ms_mk_read_resp (ASN1_ENC_CTXT *ac, READ_RESP_INFO *info); +ST_VOID _ms_mk_write_req (ASN1_ENC_CTXT *ac, WRITE_REQ_INFO *info); +ST_VOID _ms_mk_write_resp (ASN1_ENC_CTXT *ac, WRITE_RESP_INFO *info); +ST_VOID _ms_mk_info_req (ASN1_ENC_CTXT *ac, INFO_REQ_INFO *info); +ST_VOID _ms_mk_getvar_req (ASN1_ENC_CTXT *ac, GETVAR_REQ_INFO *info); +ST_VOID _ms_mk_getvar_resp (ASN1_ENC_CTXT *ac, GETVAR_RESP_INFO *info); +ST_VOID _ms_mk_defvar_req (ASN1_ENC_CTXT *ac, DEFVAR_REQ_INFO *info); +ST_VOID _ms_mk_delvar_req (ASN1_ENC_CTXT *ac, DELVAR_REQ_INFO *info); +ST_VOID _ms_mk_delvar_resp (ASN1_ENC_CTXT *ac, DELVAR_RESP_INFO *info); +ST_VOID _ms_mk_defscat_req (ASN1_ENC_CTXT *ac, DEFSCAT_REQ_INFO *info); +ST_VOID _ms_mk_getscat_req (ASN1_ENC_CTXT *ac, GETSCAT_REQ_INFO *info); +ST_VOID _ms_mk_getscat_resp (ASN1_ENC_CTXT *ac, GETSCAT_RESP_INFO *info); +ST_VOID _ms_mk_defvlist_req (ASN1_ENC_CTXT *ac, DEFVLIST_REQ_INFO *info); +ST_VOID _ms_mk_getvlist_req (ASN1_ENC_CTXT *ac, GETVLIST_REQ_INFO *info); +ST_VOID _ms_mk_getvlist_resp (ASN1_ENC_CTXT *ac, GETVLIST_RESP_INFO *info); +ST_VOID _ms_mk_delvlist_req (ASN1_ENC_CTXT *ac, DELVLIST_REQ_INFO *info); +ST_VOID _ms_mk_delvlist_resp (ASN1_ENC_CTXT *ac, DELVLIST_RESP_INFO *info); +ST_VOID _ms_mk_gettype_req (ASN1_ENC_CTXT *ac, GETTYPE_REQ_INFO *info); +ST_VOID _ms_mk_gettype_resp (ASN1_ENC_CTXT *ac, GETTYPE_RESP_INFO *info); +ST_VOID _ms_mk_deftype_req (ASN1_ENC_CTXT *ac, DEFTYPE_REQ_INFO *info); +ST_VOID _ms_mk_deltype_req (ASN1_ENC_CTXT *ac, DELTYPE_REQ_INFO *info); +ST_VOID _ms_mk_deltype_resp (ASN1_ENC_CTXT *ac, DELTYPE_RESP_INFO *info); + +ST_VOID _ms_mk_takectrl_req (ASN1_ENC_CTXT *ac, TAKECTRL_REQ_INFO *info); +ST_VOID _ms_mk_takectrl_resp (ASN1_ENC_CTXT *ac, TAKECTRL_RESP_INFO *info); +ST_VOID _ms_mk_relctrl_req (ASN1_ENC_CTXT *ac, RELCTRL_REQ_INFO *info); +ST_VOID _ms_mk_rsstat_req (ASN1_ENC_CTXT *ac, RSSTAT_REQ_INFO *info); +ST_VOID _ms_mk_rsstat_resp (ASN1_ENC_CTXT *ac, RSSTAT_RESP_INFO *info); +ST_VOID _ms_mk_rspool_req (ASN1_ENC_CTXT *ac, RSPOOL_REQ_INFO *info); +ST_VOID _ms_mk_rspool_resp (ASN1_ENC_CTXT *ac, RSPOOL_RESP_INFO *info); +ST_VOID _ms_mk_rsentry_req (ASN1_ENC_CTXT *ac, RSENTRY_REQ_INFO *info); +ST_VOID _ms_mk_rsentry_resp (ASN1_ENC_CTXT *ac, RSENTRY_RESP_INFO *info); +ST_VOID _ms_mk_defsem_req (ASN1_ENC_CTXT *ac, DEFSEM_REQ_INFO *info); +ST_VOID _ms_mk_delsem_req (ASN1_ENC_CTXT *ac, DELSEM_REQ_INFO *info); + +ST_VOID _ms_mk_output_req (ASN1_ENC_CTXT *ac, OUTPUT_REQ_INFO *info); +ST_VOID _ms_mk_input_req (ASN1_ENC_CTXT *ac, INPUT_REQ_INFO *info); +ST_VOID _ms_mk_input_resp (ASN1_ENC_CTXT *ac, INPUT_RESP_INFO *info); + +ST_VOID _ms_mk_defec_req (ASN1_ENC_CTXT *ac, DEFEC_REQ_INFO *info); +ST_VOID _ms_mk_delec_req (ASN1_ENC_CTXT *ac, DELEC_REQ_INFO *info); +ST_VOID _ms_mk_delec_resp (ASN1_ENC_CTXT *ac, DELEC_RESP_INFO *info); +ST_VOID _ms_mk_geteca_req (ASN1_ENC_CTXT *ac, GETECA_REQ_INFO *info); +ST_VOID _ms_mk_geteca_resp (ASN1_ENC_CTXT *ac, GETECA_RESP_INFO *info); +ST_VOID _ms_mk_repecs_req (ASN1_ENC_CTXT *ac, REPECS_REQ_INFO *info); +ST_VOID _ms_mk_repecs_resp (ASN1_ENC_CTXT *ac, REPECS_RESP_INFO *info); +ST_VOID _ms_mk_altecm_req (ASN1_ENC_CTXT *ac, ALTECM_REQ_INFO *info); +ST_VOID _ms_mk_trige_req (ASN1_ENC_CTXT *ac, TRIGE_REQ_INFO *info); +ST_VOID _ms_mk_defea_req (ASN1_ENC_CTXT *ac, DEFEA_REQ_INFO *info); +ST_VOID _ms_mk_delea_req (ASN1_ENC_CTXT *ac, DELEA_REQ_INFO *info); +ST_VOID _ms_mk_delea_resp (ASN1_ENC_CTXT *ac, DELEA_RESP_INFO *info); +ST_VOID _ms_mk_geteaa_req (ASN1_ENC_CTXT *ac, GETEAA_REQ_INFO *info); +ST_VOID _ms_mk_geteaa_resp (ASN1_ENC_CTXT *ac, GETEAA_RESP_INFO *info); +ST_VOID _ms_mk_repeas_req (ASN1_ENC_CTXT *ac, REPEAS_REQ_INFO *info); +ST_VOID _ms_mk_repeas_resp (ASN1_ENC_CTXT *ac, REPEAS_RESP_INFO *info); +ST_VOID _ms_mk_defee_req (ASN1_ENC_CTXT *ac, DEFEE_REQ_INFO *info); +ST_VOID _ms_mk_delee_req (ASN1_ENC_CTXT *ac, DELEE_REQ_INFO *info); +ST_VOID _ms_mk_delee_resp (ASN1_ENC_CTXT *ac, DELEE_RESP_INFO *info); +ST_VOID _ms_mk_altee_req (ASN1_ENC_CTXT *ac, ALTEE_REQ_INFO *info); +ST_VOID _ms_mk_altee_resp (ASN1_ENC_CTXT *ac, ALTEE_RESP_INFO *info); +ST_VOID _ms_mk_repees_req (ASN1_ENC_CTXT *ac, REPEES_REQ_INFO *info); +ST_VOID _ms_mk_repees_resp (ASN1_ENC_CTXT *ac, REPEES_RESP_INFO *info); +ST_VOID _ms_mk_geteea_req (ASN1_ENC_CTXT *ac, GETEEA_REQ_INFO *info); +ST_VOID _ms_mk_geteea_resp (ASN1_ENC_CTXT *ac, GETEEA_RESP_INFO *info); +ST_VOID _ms_mk_evnot_req (ASN1_ENC_CTXT *ac, EVNOT_REQ_INFO *info); +ST_VOID _ms_mk_ackevnot_req (ASN1_ENC_CTXT *ac, ACKEVNOT_REQ_INFO *info); +ST_VOID _ms_mk_getas_req (ASN1_ENC_CTXT *ac, GETAS_REQ_INFO *info); +ST_VOID _ms_mk_getas_resp (ASN1_ENC_CTXT *ac, GETAS_RESP_INFO *info); +ST_VOID _ms_mk_getaes_req (ASN1_ENC_CTXT *ac, GETAES_REQ_INFO *info); +ST_VOID _ms_mk_getaes_resp (ASN1_ENC_CTXT *ac, GETAES_RESP_INFO *info); + +ST_VOID _ms_mk_jwrite_req (ASN1_ENC_CTXT *ac, JWRITE_REQ_INFO *info); +ST_VOID _ms_mk_jread_req (ASN1_ENC_CTXT *ac, JREAD_REQ_INFO *info); +ST_VOID _ms_mk_jread_resp (ASN1_ENC_CTXT *ac, JREAD_RESP_INFO *info); +ST_VOID _ms_mk_jinit_req (ASN1_ENC_CTXT *ac, JINIT_REQ_INFO *info); +ST_VOID _ms_mk_jinit_resp (ASN1_ENC_CTXT *ac, JINIT_RESP_INFO *info); +ST_VOID _ms_mk_jstat_req (ASN1_ENC_CTXT *ac, JSTAT_REQ_INFO *info); +ST_VOID _ms_mk_jstat_resp (ASN1_ENC_CTXT *ac, JSTAT_RESP_INFO *info); +ST_VOID _ms_mk_jcreate_req (ASN1_ENC_CTXT *ac, JCREATE_REQ_INFO *info); +ST_VOID _ms_mk_jdelete_req (ASN1_ENC_CTXT *ac, JDELETE_REQ_INFO *info); + +ST_VOID _ms_mk_obtfile_req (ASN1_ENC_CTXT *ac, OBTFILE_REQ_INFO *info); +ST_VOID _ms_mk_fopen_req (ASN1_ENC_CTXT *ac, FOPEN_REQ_INFO *info); +ST_VOID _ms_mk_fopen_resp (ASN1_ENC_CTXT *ac, FOPEN_RESP_INFO *info); +ST_VOID _ms_mk_fread_req (ASN1_ENC_CTXT *ac, FREAD_REQ_INFO *info); +ST_VOID _ms_mk_fread_resp (ASN1_ENC_CTXT *ac, FREAD_RESP_INFO *info); +ST_VOID _ms_mk_fclose_req (ASN1_ENC_CTXT *ac, FCLOSE_REQ_INFO *info); +ST_VOID _ms_mk_frename_req (ASN1_ENC_CTXT *ac, FRENAME_REQ_INFO *info); +ST_VOID _ms_mk_fdelete_req (ASN1_ENC_CTXT *ac, FDELETE_REQ_INFO *info); +ST_VOID _ms_mk_fdir_req (ASN1_ENC_CTXT *ac, FDIR_REQ_INFO *info); +ST_VOID _ms_mk_fdir_resp (ASN1_ENC_CTXT *ac, FDIR_RESP_INFO *info); + +#ifdef __cplusplus +} +#endif + +#endif /* MMSEFUN_INCLUDED */ diff --git a/mmslib/inc/mmsintr2.h b/mmslib/inc/mmsintr2.h new file mode 100644 index 0000000..5215103 --- /dev/null +++ b/mmslib/inc/mmsintr2.h @@ -0,0 +1,317 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsintr2.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Functions and variables below this point are typically not */ +/* used by the application, and need not be exposed. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/04/02 JRB 11 Use SD_CONST on ALL (RUNTIME_TYPE *) vars. */ +/* 12/20/01 JRB 10 Convert to use ASN1R. */ +/* 04/19/00 JRB 09 Fix SD_CONST for decode funct ptr arrays. */ +/* 09/13/99 MDE 08 Added SD_CONST modifiers */ +/* 03/23/99 MDE 07 Changes to decode buffer allocation scheme */ +/* 03/19/98 JRB 06 Move ASN.1 error codes to "asn1defs.h". */ +/* 03/12/98 MDE 05 '_ms_m_get_rt_info' use change */ +/* 02/10/98 MDE 04 Removed unused 'm_cl_max_event_attributes' */ +/* 07/16/97 MDE 03 Added m_param, m_service_resp for MMS_LITE */ +/* 07/03/97 MDE 02 Removed CALLOC_OS */ +/* 06/09/97 MDE 01 Added decode buffer size control variables */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMSINTR2_INCLUDED +#define MMSINTR2_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/************************************************************************/ +/* Defines for Modifier and Companion Standard support. */ +/* MMSEASE defaults to supporting both, MMSEASE-LITE defaults to */ +/* supporting neither. */ +/************************************************************************/ + +#ifndef MMS_LITE +#define MOD_SUPPORT /* MMSEASE - support modifiers */ +#define CS_SUPPORT /* MMSEASE - support companion standards */ +#endif + +/************************************************************************/ +/************************************************************************/ +/* Operation Specific Decode Buffer Management */ + +extern ST_VOID *(*m_calloc_os_fun)(ST_UINT num, ST_UINT size); +extern ST_VOID *(*m_realloc_os_fun)(ST_VOID *old, ST_UINT new_size); +extern ST_VOID (*m_free_os_fun)(ST_VOID *buf); + +ST_VOID *_m_get_dec_buf (ASN1_DEC_CTXT *aCtx, ST_UINT size); + +/************************************************************************/ +/************************************************************************/ +/* Defines for the fourteen types of MMS PDUs */ +/************************************************************************/ + +#define MMSREQ 0 /* MMS request PDU for normal confirmed services */ +#define MMSRESP 1 /* MMS response PDU for normal confirmed services*/ +#define MMSERROR 2 /* MMS error PDU for normal confirmed services */ +#define MMSUNREQ 3 /* MMS response PDU for unconfirmed services */ +#define MMSREJECT 4 /* MMS reject PDU */ +#define MMSCANREQ 5 /* MMS request PDU for Cancel service */ +#define MMSCANRESP 6 /* MMS response PDU for Cancel service */ +#define MMSCANERR 7 /* MMS error PDU for Cancel service */ +#define MMSINITREQ 8 /* MMS request PDU for Initiate service */ +#define MMSINITRESP 9 /* MMS response PDU for Initiate service */ +#define MMSINITERR 10 /* MMS error PDU for Initiate service */ +#define MMSCNCLREQ 11 /* MMS request PDU for Conclude service */ +#define MMSCNCLRESP 12 /* MMS response PDU for Conclude service */ +#define MMSCNCLERR 13 /* MMS error PDU for Conclude service */ +#define UNKNOWNTYPE 14 /* not known - used in reject info structure */ + +/************************************************************************/ +/************************************************************************/ +/* Define base reserved invoke IDs for the Initiate and Conclude */ +/* services. Allows for up to 4096 associations with reserved */ +/* invoke IDs. */ +/************************************************************************/ + +#define INIT_INVOKE_ID 0x8000 /* base invoke ID for Initiate requests */ +#define CONCL_INVOKE_ID 0x9000 /* base invoke ID for Conclude requests */ + +/************************************************************************/ +/* Define the reserved invoke ID for unconfirmed requests. */ +/************************************************************************/ + +#define UNREQ_INVOKE 0xFFFF /* reserved invoke ID for unconf req's */ + +/************************************************************************/ +/************************************************************************/ +/* The following function pointer arrays are used for the request and */ +/* response decode functions. The operation opcode is used as the index */ +/* into the table. */ +/************************************************************************/ + +#define MAX_REQ_DFUN 85 /* highest request decode array entry */ +#define MAX_RSP_DFUN 85 /* highest response decode array entry */ + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* This structure is used to return the results of a MMS PDU decode. */ +/* The user passes a pointer to a struct of this type to decode_mms, */ +/* and when the decode is complete, the struct info will be filled in. */ +/* */ +/* dec_level : */ +/* 0 - Nothing valid */ +/* 1 - type valid */ +/* 2 - type, invoke ID valid */ +/* 3 - type, invoke ID, op valid */ +/************************************************************************/ + +struct mmsdec_info + { + ST_RET err_code; /* decode error code (NO_DECODE_ERR) */ + ST_INT dec_level; /* indicates valid members */ + ST_INT type; /* MMS pdu type (req,resp,err,rej) */ + ST_INT op; /* operation opcode */ + ST_UINT32 id; /* invoke ID */ + struct list_of_mods mods; /* tracking of modifiers */ + struct csi cs; /* Companion Standard Info */ + ST_BOOLEAN data_pres; /* flag to indicate data buffer present */ + ST_VOID *data_ptr; /* pointer to data if present */ + }; +typedef struct mmsdec_info MMSDEC_INFO; + +extern ST_VOID (* SD_CONST mms_req_decode_fun [MAX_REQ_DFUN+1]) (ASN1_DEC_CTXT *aCtx); +extern ST_VOID (* SD_CONST mms_rsp_decode_fun [MAX_RSP_DFUN+1]) (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mms_decode is used at MMS decode level, not generally used by */ +/* application directly. */ +/************************************************************************/ + +ST_RET _ms_mms_decode (ST_UCHAR *ptr, ST_INT len, MMSDEC_INFO *rslt); + +extern MMSDEC_INFO *_mmsdec_rslt; +extern ST_UINT _mmsdec_ctxt; /* default to core context */ +extern ST_INT _mmsdec_msglen; /* MMS decode message length */ +extern ST_UCHAR *_mmsdec_msgptr; /* MMS decode message ptr */ +extern ST_BOOLEAN _mms_dec_info_pres; +extern ST_VOID *_mms_dec_info; /* operation specific info */ + + +/************************************************************************/ +/************************************************************************/ +/* These variables are used help control decode operation specific data */ +/* structure allocation. For MMS-LITE (M_USR_DEC_BUF), these variables */ +/* are used to tell the decode system how many objects the allocated */ +/* buffer (_mms_dec_info). For MMS-EASE, these are normally not used; */ +/* if they are set non-zero, they will be used in calculating the size */ +/* of the dec info buffer to be allocated. */ + +/* Client Decode Limits. */ +extern ST_INT m_cl_read_spec_in_result; +extern ST_INT m_cl_max_read_var_spec; +extern ST_INT m_cl_max_read_acc_rslt; +extern ST_INT m_cl_max_info_var_spec; +extern ST_INT m_cl_max_info_acc_rslt; +extern ST_INT m_cl_max_getvla_vars; +extern ST_INT m_cl_max_write_rslts; +extern ST_INT m_cl_max_namel_names; +extern ST_INT m_cl_max_getcl_cap; +extern ST_INT m_cl_max_getpi_doms; +extern ST_INT m_cl_max_getdom_cap; +extern ST_INT m_cl_max_getdom_pi; +extern ST_INT m_cl_max_initupl_cap; +extern ST_INT m_cl_max_alarm_summary; +extern ST_INT m_cl_max_journal_entries; +extern ST_INT m_cl_max_entry_content; +extern ST_INT m_cl_max_semaphore_entries; +extern ST_INT m_cl_max_named_tokens; +extern ST_INT m_cl_max_file_directory; +extern ST_INT m_cl_max_event_enrollment; +extern ST_INT m_cl_max_enrollment_summary; + +/* Server Decode Limits. */ +extern ST_INT m_sv_max_loadd_cap; +extern ST_INT m_sv_max_read_var_spec; +extern ST_INT m_sv_max_write_var_spec; +extern ST_INT m_sv_max_write_data; +extern ST_INT m_sv_max_rqdlnl_cap; +extern ST_INT m_sv_max_initdnld_cap; +extern ST_INT m_sv_max_vstr; +extern ST_INT m_sv_max_file_names; +extern ST_INT m_sv_max_obj_name; +extern ST_INT m_sv_max_prompt_count; +extern ST_INT m_sv_max_num_vars; +extern ST_INT m_sv_max_data_count; +extern ST_INT m_sv_max_entry_content; +extern ST_INT m_sv_max_data_vars; +extern ST_INT m_sv_max_jread_vars; + +/************************************************************************/ +/* These bitstrings are located in mmsop_en.c and indicate which */ +/* services and CBB's are supported by this application. */ +#ifdef MMS_LITE +extern SD_CONST ST_UCHAR m_param[2]; /* parameter support */ + /* services supported as responder */ +extern SD_CONST ST_UCHAR m_service_resp[11]; +#endif + +/************************************************************************/ +/************************************************************************/ +/* This variable can be set to force use of the DIS MMS floating point */ +/* type protocol (used in any over the wire and internal ASN.1 type */ +/* definitions). */ + +extern ST_BOOLEAN m_use_dis_float; /* = SD_FALSE; */ + +/************************************************************************/ +/************************************************************************/ +/* ALTERNATE ACCESS */ + +/* This structure is used to control the creation of RTAA types */ +/* and contains state information for the various functions to use */ +/* during the process. */ + +struct aa_apply_ctrl + { +/* Alternate Access spec */ + ST_INT num_aa; /* # elements in AA table */ + struct alt_acc_el *aa_head; /* Head of AA table */ + struct alt_acc_el *aa_end; /* Last element in AA table */ + struct alt_acc_el *curr_aa; /* Current location in table */ + +/* 'All'runtime aa */ + ST_INT num_all_rtaa; + struct rt_aa_ctrl *all_rtaa_head; + struct rt_aa_ctrl *all_rtaa_end; + +/* New (output) runtime aa */ + ST_INT num_rtaa; + struct rt_aa_ctrl *rtaa_head; + struct rt_aa_ctrl *curr_rtaa; + +/* Nest Level */ + ST_INT nest; + }; +typedef struct aa_apply_ctrl AA_APPLY_CTRL; + +/************************************************************************/ +/* Floating point type ASN.1 definition values */ + +#define SNGL_WHOLE 32 +#define SNGL_FRACT 23 +#define SNGL_EXP 8 + +#define DOUBL_WHOLE 64 +#define DOUBL_FRACT 52 +#define DOUBL_EXP 11 + +/* Used to determine number of bytes required to hold a number of bits */ +#define CALC_BIT_LEN(x) (((x)+7)/8) + +/************************************************************************/ +ST_RET _ms_m_get_rt_info (SD_CONST RUNTIME_TYPE *rt, + ST_INT *algn_out, + ST_INT *ellen_out); + +/************************************************************************/ +/* Function pointers for Variable manipulation functions. */ +/* User exposed functions (i.e. ms_add_named_var, etc.) call these */ +/* function pointers which should point to "linked list" functions */ +/* by default (see "_ms_ll_*" functions below). If the "ms_bs_init" */ +/* function is called, these will point to "binary search" functions */ +/* (see "_ms_bs_*" functions below). */ +/************************************************************************/ +#ifndef MMS_LITE + +extern NAMED_VAR *(*_ms_fp_add_named_var) (DOMAIN_OBJS *dom, ST_CHAR *name, + OBJECT_NAME *type, VAR_ACC_ADDR *addr, ST_INT chan); +extern NAMED_VAR *(*_ms_fp_add_var) (DOMAIN_OBJS *dom, ST_CHAR *name, + NAMED_TYPE *type_ptr, VAR_ACC_ADDR *addr, ST_INT chan); +extern NAMED_VAR *(*_ms_fp_find_named_var) + (DOMAIN_OBJS *dom, ST_CHAR *name); +extern ST_RET (*_ms_fp_del_named_var) (DOMAIN_OBJS *dom, ST_CHAR *name); +extern ST_VOID (*_ms_fp_del_all_named_vars) (DOMAIN_OBJS *dom); +extern ST_VOID (*_ms_fp_del_deletable_named_vars) (DOMAIN_OBJS *, DELVAR_RESP_INFO *); +extern NAMED_VAR_LIST *(*_ms_fp_add_nvlist) (DOMAIN_OBJS *dom, + ST_CHAR *name, ST_INT num_vars, VARIABLE_LIST *var_list); +extern NAMED_VAR_LIST *(*_ms_fp_find_nvlist) (DOMAIN_OBJS *dom, ST_CHAR *name); +extern ST_RET (*_ms_fp_del_nvlist) (DOMAIN_OBJS *dom, ST_CHAR *name); +extern ST_VOID (*_ms_fp_del_all_nvlists) (DOMAIN_OBJS *dom); +extern ST_VOID (*_ms_fp_del_deletable_nvlists) (DOMAIN_OBJS *, DELVLIST_RESP_INFO *); + +extern NAMED_DOM_CTRL *(*_ms_fp_add_named_domain) (INITDOWN_REQ_INFO *dom_info, + ST_UCHAR pro); +extern NAMED_DOM_CTRL *(*_ms_fp_find_named_dom)(ST_CHAR dname[MAX_IDENT_LEN+1]); +extern ST_RET (*_ms_fp_del_named_dom) (ST_CHAR *dname); +extern ST_VOID (*_ms_fp_del_all_named_doms)(NAMED_DOM_CTRL *head_of_dom_list); + +extern ST_VOID (*_ms_fp_write_object_names) (ST_VOID *dom_or_vmd, + NAMELIST_REQ_INFO *reqinfo, NAMELIST_RESP_INFO *respinfo, + ST_INT max_names); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* MMSINTR2_INCLUDED */ diff --git a/mmslib/inc/mmsldefs.h b/mmslib/inc/mmsldefs.h new file mode 100644 index 0000000..fe8b2c8 --- /dev/null +++ b/mmslib/inc/mmsldefs.h @@ -0,0 +1,94 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsldefs.h */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Functions and variables below this point are used by the */ +/* application. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/27/09 JRB 26 Updated version. */ +/* 02/18/09 RKR 25 Updated version. */ +/* 01/19/09 RKR 24 Updated version. */ +/* 12/01/08 GLB 23 Updated version. */ +/* 11/10/08 GLB 22 Updated version. */ +/* 04/23/08 GLB 21 Updated version. */ +/* 01/02/07 JRB 20 Updated version. */ +/* 04/10/06 RKR 19 Updated copyright and version for SMV Beta */ +/* 10/28/05 EJV 18 Update ver to 5.0250 for MMS-LITE-SECURE rel.*/ +/* 09/09/05 JRB 17 Update ver to 5.02 & Copyright info. */ +/* BUILD_NUM is OBSOLETE. */ +/* 04/28/05 PLM 16 Update ver to 5.01 Build 1 */ +/* 07/21/04 DWL 15 Update to 5.0052 */ +/* 02/20/04 ASK 14 Chg ver to 5.0051 for USPS release */ +/* 01/26/04 DWL 13 Update copyright date to 2004. */ +/* 09/10/03 EJV 12 Chg ver to 5.0050 (Security ready MMS-LITE) */ +/* 04/29/03 DWL 11 Updated build number */ +/* 04/08/03 DWL 10 Updated copyright/version/build number */ +/* 12/20/02 DWL 09 Updated version/build number */ +/* 03/22/02 DWL 08 Updated build number */ +/* 03/12/02 DWL 07 Updated version */ +/* 02/25/02 MDE 06 Removed mmsl_max_msg_size */ +/* 10/09/01 JRB 05 Add MMSLITE_* product identification defines.*/ +/* 02/20/98 MDE 04 Fixed __cplusplus problem */ +/* 11/05/97 MDE 03 Changed mmsl_msg_start to ST_UCHAR * */ +/* 08/24/97 MDE 02 Added 'mmsl_max_msg_size', 'ml_init_buffers' */ +/* 11/10/93 DGE 01 Initial MMSEASE-LITE Release. */ +/************************************************************************/ + +#ifndef LMMSDEFS_INCLUDED +#define LMMSDEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/* Defines for Product Identification. */ +/* Write these parameters on screen and in log file at startup. */ +/* Use MMSLITE_NAME & MMSLITE_VERSION in MMS Identify response. */ +/************************************************************************/ +#define MMSLITE_COPYRIGHT "Copyright (c) 1986-2008 SISCO, Inc. All Rights Reserved." +#define MMSLITE_NAME "MMS-LITE-80X-001" +#define MMSLITE_VERSION "5.1005" +#define MMSLITE_BUILD_NUM 0 /* OBSOLETE: for backward compatibility only*/ + +/************************************************************************/ +/************************************************************************/ +/* MMSEASE-LITE specific Global Variables */ +/************************************************************************/ +#define MMS_PCI 0x0001 + +extern ST_INT mmsl_enc_buf_size; +extern ST_UCHAR *mmsl_enc_buf; +extern ST_INT mmsl_dec_info_size; + +extern ST_INT16 mmsl_version; +extern ST_UINT32 mmsl_invoke_id; + +extern ST_UCHAR *mmsl_msg_start; +extern ST_INT mmsl_msg_len; + + +/************************************************************************/ +/* This function initializes the encode/decode buffers and the decode */ +/* object limitations, and is normally generated using the 'mbufcalc' */ +/* utility program. */ + +ST_VOID ml_init_buffers (ST_VOID); + + +#ifdef __cplusplus +} +#endif + +#endif /* MMSLDEFS_INCLUDED */ diff --git a/mmslib/inc/mmslog.h b/mmslib/inc/mmslog.h new file mode 100644 index 0000000..cfa0e38 --- /dev/null +++ b/mmslib/inc/mmslog.h @@ -0,0 +1,735 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2007, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmslog.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains MMS-EASE logging macros used */ +/* internally by MMS-EASE for SLOGGING */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/05/07 EJV 07 Removed obsolete LLC30_LLP code. */ +/* 11/01/04 JRB 06 Use new "Base" macros SLOG_*, SLOGC_*, SLOGH.*/ +/* Change MLOG_ALWAYS* like SLOGALWAYS*. */ +/* 03/13/02 JRB 05 MLOG_PAUSE* macros do nothing. */ +/* 10/05/01 EJV 04 Corrected comment. */ +/* 03/15/01 JRB 03 Added USER log macros. */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 10/08/98 MDE 01 Migrated to updated SLOG interface */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMSLOG_INCLUDED +#define MMSLOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +extern SD_CONST ST_CHAR *SD_CONST _mms_log_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_enc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_acse_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_ique_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_rque_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_ind_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_conf_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_vm_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_nerr_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_pdu_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_config_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mms_log_always_logstr; + +extern SD_CONST ST_CHAR *SD_CONST _user_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _user_client_logstr; +extern SD_CONST ST_CHAR *SD_CONST _user_server_logstr; + +/*********************** PAUSE Macros ***********************************/ +#define MLOG_PAUSEDEC(msg) +#define MLOG_PAUSEENC(msg) +#define MLOG_PAUSEIQUE(msg) +#define MLOG_PAUSERQUE(msg) +#define MLOG_PAUSEPDU(msg) + +/*********************** DECODE Macros **********************************/ +#define MLOG_DEC0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a) +#define MLOG_DEC1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b) +#define MLOG_DEC2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b,c) +#define MLOG_DEC3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b,c,d) +#define MLOG_DEC4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b,c,d,e) +#define MLOG_DEC5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b,c,d,e,f) +#define MLOG_DEC6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b,c,d,e,f,g) +#define MLOG_DEC7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b,c,d,e,f,g,h) +#define MLOG_DEC8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_DEC,_mms_log_dec_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CDEC0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_DEC,a) +#define MLOG_CDEC1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_DEC,a,b) +#define MLOG_CDEC2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_DEC,a,b,c) +#define MLOG_CDEC3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_DEC,a,b,c,d) +#define MLOG_CDEC4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_DEC,a,b,c,d,e) +#define MLOG_CDEC5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_DEC,a,b,c,d,e,f) +#define MLOG_CDEC6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_DEC,a,b,c,d,e,f,g) +#define MLOG_CDEC7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_DEC,a,b,c,d,e,f,g,h) +#define MLOG_CDEC8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_DEC,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_DECH(a,b) \ + +/*********************** ENCODE Macros **********************************/ +#define MLOG_ENC0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a) +#define MLOG_ENC1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b) +#define MLOG_ENC2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b,c) +#define MLOG_ENC3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b,c,d) +#define MLOG_ENC4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b,c,d,e) +#define MLOG_ENC5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b,c,d,e,f) +#define MLOG_ENC6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b,c,d,e,f,g) +#define MLOG_ENC7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b,c,d,e,f,g,h) +#define MLOG_ENC8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_ENC,_mms_log_enc_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CENC0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_ENC,a) +#define MLOG_CENC1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_ENC,a,b) +#define MLOG_CENC2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_ENC,a,b,c) +#define MLOG_CENC3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_ENC,a,b,c,d) +#define MLOG_CENC4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_ENC,a,b,c,d,e) +#define MLOG_CENC5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_ENC,a,b,c,d,e,f) +#define MLOG_CENC6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_ENC,a,b,c,d,e,f,g) +#define MLOG_CENC7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_ENC,a,b,c,d,e,f,g,h) +#define MLOG_CENC8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_ENC,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_ENCH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_ENC,a,b) + +/*********************** ACSE Macros ***********************************/ +#define MLOG_ACSE0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a) +#define MLOG_ACSE1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b) +#define MLOG_ACSE2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b,c) +#define MLOG_ACSE3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b,c,d) +#define MLOG_ACSE4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b,c,d,e) +#define MLOG_ACSE5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b,c,d,e,f) +#define MLOG_ACSE6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b,c,d,e,f,g) +#define MLOG_ACSE7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b,c,d,e,f,g,h) +#define MLOG_ACSE8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_ACSE,_mms_log_acse_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CACSE0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_ACSE,a) +#define MLOG_CACSE1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_ACSE,a,b) +#define MLOG_CACSE2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_ACSE,a,b,c) +#define MLOG_CACSE3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_ACSE,a,b,c,d) +#define MLOG_CACSE4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_ACSE,a,b,c,d,e) +#define MLOG_CACSE5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_ACSE,a,b,c,d,e,f) +#define MLOG_CACSE6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_ACSE,a,b,c,d,e,f,g) +#define MLOG_CACSE7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_ACSE,a,b,c,d,e,f,g,h) +#define MLOG_CACSE8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_ACSE,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_ACSEH(a,b) \ + +/*********************** IQUE Macros **************************************/ +#define MLOG_IQUE0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a) +#define MLOG_IQUE1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b) +#define MLOG_IQUE2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b,c) +#define MLOG_IQUE3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b,c,d) +#define MLOG_IQUE4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b,c,d,e) +#define MLOG_IQUE5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b,c,d,e,f) +#define MLOG_IQUE6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b,c,d,e,f,g) +#define MLOG_IQUE7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b,c,d,e,f,g,h) +#define MLOG_IQUE8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_IQUE,_mms_log_ique_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CIQUE0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_IQUE,a) +#define MLOG_CIQUE1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_IQUE,a,b) +#define MLOG_CIQUE2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_IQUE,a,b,c) +#define MLOG_CIQUE3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_IQUE,a,b,c,d) +#define MLOG_CIQUE4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_IQUE,a,b,c,d,e) +#define MLOG_CIQUE5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_IQUE,a,b,c,d,e,f) +#define MLOG_CIQUE6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_IQUE,a,b,c,d,e,f,g) +#define MLOG_CIQUE7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_IQUE,a,b,c,d,e,f,g,h) +#define MLOG_CIQUE8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_IQUE,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_IQUEH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_IQUE,a,b) + +/*********************** RQUE Macros **************************************/ +#define MLOG_RQUE0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a) +#define MLOG_RQUE1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b) +#define MLOG_RQUE2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b,c) +#define MLOG_RQUE3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b,c,d) +#define MLOG_RQUE4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b,c,d,e) +#define MLOG_RQUE5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b,c,d,e,f) +#define MLOG_RQUE6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b,c,d,e,f,g) +#define MLOG_RQUE7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b,c,d,e,f,g,h) +#define MLOG_RQUE8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_RQUE,_mms_log_rque_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CRQUE0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_RQUE,a) +#define MLOG_CRQUE1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_RQUE,a,b) +#define MLOG_CRQUE2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_RQUE,a,b,c) +#define MLOG_CRQUE3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_RQUE,a,b,c,d) +#define MLOG_CRQUE4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_RQUE,a,b,c,d,e) +#define MLOG_CRQUE5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_RQUE,a,b,c,d,e,f) +#define MLOG_CRQUE6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_RQUE,a,b,c,d,e,f,g) +#define MLOG_CRQUE7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_RQUE,a,b,c,d,e,f,g,h) +#define MLOG_CRQUE8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_RQUE,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_RQUEH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_RQUE,a,b) + +/*********************** REQ Macros **************************************/ +#define MLOG_REQ0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a) +#define MLOG_REQ1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b) +#define MLOG_REQ2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b,c) +#define MLOG_REQ3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b,c,d) +#define MLOG_REQ4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b,c,d,e) +#define MLOG_REQ5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b,c,d,e,f) +#define MLOG_REQ6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b,c,d,e,f,g) +#define MLOG_REQ7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b,c,d,e,f,g,h) +#define MLOG_REQ8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_REQ,_mms_log_req_logstr,a,b,c,d,e,f,g,h,i) + +/* DEBUG: Add Continuation log macros? */ + +/* Hex log macro */ +#define MLOG_REQH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_REQ,a,b) + +/*********************** IND Macros **************************************/ +#define MLOG_IND0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a) +#define MLOG_IND1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b) +#define MLOG_IND2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b,c) +#define MLOG_IND3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b,c,d) +#define MLOG_IND4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b,c,d,e) +#define MLOG_IND5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b,c,d,e,f) +#define MLOG_IND6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b,c,d,e,f,g) +#define MLOG_IND7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b,c,d,e,f,g,h) +#define MLOG_IND8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_IND,_mms_log_ind_logstr,a,b,c,d,e,f,g,h,i) + +/* DEBUG: Add Continuation log macros? */ + +/* Hex log macro */ +#define MLOG_INDH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_IND,a,b) + +/*********************** RESP Macros **************************************/ +#define MLOG_RESP0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a) +#define MLOG_RESP1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b) +#define MLOG_RESP2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b,c) +#define MLOG_RESP3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b,c,d) +#define MLOG_RESP4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b,c,d,e) +#define MLOG_RESP5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b,c,d,e,f) +#define MLOG_RESP6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b,c,d,e,f,g) +#define MLOG_RESP7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b,c,d,e,f,g,h) +#define MLOG_RESP8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_RESP,_mms_log_resp_logstr,a,b,c,d,e,f,g,h,i) + +/* DEBUG: Add Continuation log macros? */ + +/* Hex log macro */ +#define MLOG_RESPH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_RESP,a,b) + +/*********************** CONF Macros **************************************/ +#define MLOG_CONF0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a) +#define MLOG_CONF1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b) +#define MLOG_CONF2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b,c) +#define MLOG_CONF3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b,c,d) +#define MLOG_CONF4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b,c,d,e) +#define MLOG_CONF5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b,c,d,e,f) +#define MLOG_CONF6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b,c,d,e,f,g) +#define MLOG_CONF7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b,c,d,e,f,g,h) +#define MLOG_CONF8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_CONF,_mms_log_conf_logstr,a,b,c,d,e,f,g,h,i) + + +/* DEBUG: Add Continuation log macros? */ + +/* Hex log macro */ +#define MLOG_CONFH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_CONF,a,b) + +/*********************** VM Macros **************************************/ +#define MLOG_VM0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a) +#define MLOG_VM1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b) +#define MLOG_VM2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b,c) +#define MLOG_VM3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b,c,d) +#define MLOG_VM4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b,c,d,e) +#define MLOG_VM5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b,c,d,e,f) +#define MLOG_VM6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b,c,d,e,f,g) +#define MLOG_VM7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b,c,d,e,f,g,h) +#define MLOG_VM8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_VM,_mms_log_vm_logstr,a,b,c,d,e,f,g,h,i) + +/* DEBUG: Add Continuation log macros? */ + +/* Hex log macro */ +#define MLOG_VMH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_VM,a,b) + +/*********************** ERR Macros **************************************/ +#define MLOG_ERR0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a) +#define MLOG_ERR1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b) +#define MLOG_ERR2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b,c) +#define MLOG_ERR3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b,c,d) +#define MLOG_ERR4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b,c,d,e) +#define MLOG_ERR5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b,c,d,e,f) +#define MLOG_ERR6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b,c,d,e,f,g) +#define MLOG_ERR7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b,c,d,e,f,g,h) +#define MLOG_ERR8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_ERR,_mms_log_err_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CERR0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_ERR,a) +#define MLOG_CERR1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_ERR,a,b) +#define MLOG_CERR2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_ERR,a,b,c) +#define MLOG_CERR3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_ERR,a,b,c,d) +#define MLOG_CERR4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_ERR,a,b,c,d,e) +#define MLOG_CERR5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_ERR,a,b,c,d,e,f) +#define MLOG_CERR6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_ERR,a,b,c,d,e,f,g) +#define MLOG_CERR7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_ERR,a,b,c,d,e,f,g,h) +#define MLOG_CERR8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_ERR,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_ERRH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_ERR,a,b) + +/*********************** NERR Macros *************************************/ +#define MLOG_NERR0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a) +#define MLOG_NERR1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b) +#define MLOG_NERR2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b,c) +#define MLOG_NERR3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b,c,d) +#define MLOG_NERR4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b,c,d,e) +#define MLOG_NERR5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b,c,d,e,f) +#define MLOG_NERR6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b,c,d,e,f,g) +#define MLOG_NERR7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b,c,d,e,f,g,h) +#define MLOG_NERR8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_NERR,_mms_log_nerr_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CNERR0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_NERR,a) +#define MLOG_CNERR1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_NERR,a,b) +#define MLOG_CNERR2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_NERR,a,b,c) +#define MLOG_CNERR3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_NERR,a,b,c,d) +#define MLOG_CNERR4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_NERR,a,b,c,d,e) +#define MLOG_CNERR5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_NERR,a,b,c,d,e,f) +#define MLOG_CNERR6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_NERR,a,b,c,d,e,f,g) +#define MLOG_CNERR7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_NERR,a,b,c,d,e,f,g,h) +#define MLOG_CNERR8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_NERR,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_NERRH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_NERR,a,b) + +/*********************** PDU Macros **************************************/ +#define MLOG_PDU0(a) \ + SLOG_0 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a) +#define MLOG_PDU1(a,b) \ + SLOG_1 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b) +#define MLOG_PDU2(a,b,c) \ + SLOG_2 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b,c) +#define MLOG_PDU3(a,b,c,d) \ + SLOG_3 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b,c,d) +#define MLOG_PDU4(a,b,c,d,e) \ + SLOG_4 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b,c,d,e) +#define MLOG_PDU5(a,b,c,d,e,f) \ + SLOG_5 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b,c,d,e,f) +#define MLOG_PDU6(a,b,c,d,e,f,g) \ + SLOG_6 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b,c,d,e,f,g) +#define MLOG_PDU7(a,b,c,d,e,f,g,h) \ + SLOG_7 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b,c,d,e,f,g,h) +#define MLOG_PDU8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (mms_debug_sel & MMS_LOG_PDU,_mms_log_pdu_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define MLOG_CPDU0(a) \ + SLOGC_0 (mms_debug_sel & MMS_LOG_PDU,a) +#define MLOG_CPDU1(a,b) \ + SLOGC_1 (mms_debug_sel & MMS_LOG_PDU,a,b) +#define MLOG_CPDU2(a,b,c) \ + SLOGC_2 (mms_debug_sel & MMS_LOG_PDU,a,b,c) +#define MLOG_CPDU3(a,b,c,d) \ + SLOGC_3 (mms_debug_sel & MMS_LOG_PDU,a,b,c,d) +#define MLOG_CPDU4(a,b,c,d,e) \ + SLOGC_4 (mms_debug_sel & MMS_LOG_PDU,a,b,c,d,e) +#define MLOG_CPDU5(a,b,c,d,e,f) \ + SLOGC_5 (mms_debug_sel & MMS_LOG_PDU,a,b,c,d,e,f) +#define MLOG_CPDU6(a,b,c,d,e,f,g) \ + SLOGC_6 (mms_debug_sel & MMS_LOG_PDU,a,b,c,d,e,f,g) +#define MLOG_CPDU7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (mms_debug_sel & MMS_LOG_PDU,a,b,c,d,e,f,g,h) +#define MLOG_CPDU8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (mms_debug_sel & MMS_LOG_PDU,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define MLOG_PDUH(a,b) \ + SLOGH (mms_debug_sel & MMS_LOG_PDU,a,b) + + +/*********************** ALWAYS Macros *********************************/ +/* DEBUG: these are same as "SLOGALWAYS*" except header txt */ +/* "mms_log_always_logstr". If text is not important, just remap */ +/* "MLOG_ALWAYS*" like this (#define MLOG_ALWAYS0 SLOGALWAYS0). */ +#if defined(DEBUG_SISCO) +#define MLOG_ALWAYS0(a) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a) +#define MLOG_ALWAYS1(a,b) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b) +#define MLOG_ALWAYS2(a,b,c) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b,c) +#define MLOG_ALWAYS3(a,b,c,d) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b,c,d) +#define MLOG_ALWAYS4(a,b,c,d,e) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b,c,d,e) +#define MLOG_ALWAYS5(a,b,c,d,e,f) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b,c,d,e,f) +#define MLOG_ALWAYS6(a,b,c,d,e,f,g) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b,c,d,e,f,g) +#define MLOG_ALWAYS7(a,b,c,d,e,f,g,h) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b,c,d,e,f,g,h) +#define MLOG_ALWAYS8(a,b,c,d,e,f,g,h,i) \ + _slog (sLogCtrl,_mms_log_always_logstr, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i) +#else /* !DEBUG_SISCO */ +#define MLOG_ALWAYS0(a) +#define MLOG_ALWAYS1(a,b) +#define MLOG_ALWAYS2(a,b,c) +#define MLOG_ALWAYS3(a,b,c,d) +#define MLOG_ALWAYS4(a,b,c,d,e) +#define MLOG_ALWAYS5(a,b,c,d,e,f) +#define MLOG_ALWAYS6(a,b,c,d,e,f,g) +#define MLOG_ALWAYS7(a,b,c,d,e,f,g,h) +#define MLOG_ALWAYS8(a,b,c,d,e,f,g,h,i) +#endif /* !DEBUG_SISCO */ + +/* Continuation & Hex macros are exactly the same as "SLOG*" macros, so just remap to them.*/ +#define MLOG_CALWAYS0 SLOGCALWAYS0 +#define MLOG_CALWAYS1 SLOGCALWAYS1 +#define MLOG_CALWAYS2 SLOGCALWAYS2 +#define MLOG_CALWAYS3 SLOGCALWAYS3 +#define MLOG_CALWAYS4 SLOGCALWAYS4 +#define MLOG_CALWAYS5 SLOGCALWAYS5 +#define MLOG_CALWAYS6 SLOGCALWAYS6 +#define MLOG_CALWAYS7 SLOGCALWAYS7 +#define MLOG_CALWAYS8 SLOGCALWAYS8 + +#define MLOG_ALWAYSH SLOGALWAYSH + + +/*********************** USER ERR Macros********************************/ +#define USER_LOG_ERR0(a) \ + SLOG_0 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a) +#define USER_LOG_ERR1(a,b) \ + SLOG_1 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b) +#define USER_LOG_ERR2(a,b,c) \ + SLOG_2 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b,c) +#define USER_LOG_ERR3(a,b,c,d) \ + SLOG_3 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b,c,d) +#define USER_LOG_ERR4(a,b,c,d,e) \ + SLOG_4 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b,c,d,e) +#define USER_LOG_ERR5(a,b,c,d,e,f) \ + SLOG_5 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b,c,d,e,f) +#define USER_LOG_ERR6(a,b,c,d,e,f,g) \ + SLOG_6 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b,c,d,e,f,g) +#define USER_LOG_ERR7(a,b,c,d,e,f,g,h) \ + SLOG_7 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b,c,d,e,f,g,h) +#define USER_LOG_ERR8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (user_debug_sel & USER_LOG_ERR,_user_err_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define USER_LOG_ERRC0(a) \ + SLOGC_0 (user_debug_sel & USER_LOG_ERR,a) +#define USER_LOG_ERRC1(a,b) \ + SLOGC_1 (user_debug_sel & USER_LOG_ERR,a,b) +#define USER_LOG_ERRC2(a,b,c) \ + SLOGC_2 (user_debug_sel & USER_LOG_ERR,a,b,c) +#define USER_LOG_ERRC3(a,b,c,d) \ + SLOGC_3 (user_debug_sel & USER_LOG_ERR,a,b,c,d) +#define USER_LOG_ERRC4(a,b,c,d,e) \ + SLOGC_4 (user_debug_sel & USER_LOG_ERR,a,b,c,d,e) +#define USER_LOG_ERRC5(a,b,c,d,e,f) \ + SLOGC_5 (user_debug_sel & USER_LOG_ERR,a,b,c,d,e,f) +#define USER_LOG_ERRC6(a,b,c,d,e,f,g) \ + SLOGC_6 (user_debug_sel & USER_LOG_ERR,a,b,c,d,e,f,g) +#define USER_LOG_ERRC7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (user_debug_sel & USER_LOG_ERR,a,b,c,d,e,f,g,h) +#define USER_LOG_ERRC8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (user_debug_sel & USER_LOG_ERR,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define USER_LOG_ERRH(a,b) \ + SLOGH (user_debug_sel & USER_LOG_ERR,a,b) + +/*********************** USER Client Macros ****************************/ +#define USER_LOG_CLIENT0(a) \ + SLOG_0 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a) +#define USER_LOG_CLIENT1(a,b) \ + SLOG_1 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b) +#define USER_LOG_CLIENT2(a,b,c) \ + SLOG_2 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b,c) +#define USER_LOG_CLIENT3(a,b,c,d) \ + SLOG_3 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b,c,d) +#define USER_LOG_CLIENT4(a,b,c,d,e) \ + SLOG_4 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b,c,d,e) +#define USER_LOG_CLIENT5(a,b,c,d,e,f) \ + SLOG_5 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b,c,d,e,f) +#define USER_LOG_CLIENT6(a,b,c,d,e,f,g) \ + SLOG_6 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b,c,d,e,f,g) +#define USER_LOG_CLIENT7(a,b,c,d,e,f,g,h) \ + SLOG_7 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b,c,d,e,f,g,h) +#define USER_LOG_CLIENT8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (user_debug_sel & USER_LOG_CLIENT,_user_client_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define USER_LOG_CLIENTC0(a) \ + SLOGC_0 (user_debug_sel & USER_LOG_CLIENT,a) +#define USER_LOG_CLIENTC1(a,b) \ + SLOGC_1 (user_debug_sel & USER_LOG_CLIENT,a,b) +#define USER_LOG_CLIENTC2(a,b,c) \ + SLOGC_2 (user_debug_sel & USER_LOG_CLIENT,a,b,c) +#define USER_LOG_CLIENTC3(a,b,c,d) \ + SLOGC_3 (user_debug_sel & USER_LOG_CLIENT,a,b,c,d) +#define USER_LOG_CLIENTC4(a,b,c,d,e) \ + SLOGC_4 (user_debug_sel & USER_LOG_CLIENT,a,b,c,d,e) +#define USER_LOG_CLIENTC5(a,b,c,d,e,f) \ + SLOGC_5 (user_debug_sel & USER_LOG_CLIENT,a,b,c,d,e,f) +#define USER_LOG_CLIENTC6(a,b,c,d,e,f,g) \ + SLOGC_6 (user_debug_sel & USER_LOG_CLIENT,a,b,c,d,e,f,g) +#define USER_LOG_CLIENTC7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (user_debug_sel & USER_LOG_CLIENT,a,b,c,d,e,f,g,h) +#define USER_LOG_CLIENTC8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (user_debug_sel & USER_LOG_CLIENT,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define USER_LOG_CLIENTH(a,b) \ + SLOGH (user_debug_sel & USER_LOG_CLIENT,a,b) + +/*********************** USER Server Macros ****************************/ +#define USER_LOG_SERVER0(a) \ + SLOG_0 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a) +#define USER_LOG_SERVER1(a,b) \ + SLOG_1 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b) +#define USER_LOG_SERVER2(a,b,c) \ + SLOG_2 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b,c) +#define USER_LOG_SERVER3(a,b,c,d) \ + SLOG_3 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b,c,d) +#define USER_LOG_SERVER4(a,b,c,d,e) \ + SLOG_4 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b,c,d,e) +#define USER_LOG_SERVER5(a,b,c,d,e,f) \ + SLOG_5 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b,c,d,e,f) +#define USER_LOG_SERVER6(a,b,c,d,e,f,g) \ + SLOG_6 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b,c,d,e,f,g) +#define USER_LOG_SERVER7(a,b,c,d,e,f,g,h) \ + SLOG_7 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b,c,d,e,f,g,h) +#define USER_LOG_SERVER8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (user_debug_sel & USER_LOG_SERVER,_user_server_logstr,a,b,c,d,e,f,g,h,i) + +/* Continuation log macros */ +#define USER_LOG_SERVERC0(a) \ + SLOGC_0 (user_debug_sel & USER_LOG_SERVER,a) +#define USER_LOG_SERVERC1(a,b) \ + SLOGC_1 (user_debug_sel & USER_LOG_SERVER,a,b) +#define USER_LOG_SERVERC2(a,b,c) \ + SLOGC_2 (user_debug_sel & USER_LOG_SERVER,a,b,c) +#define USER_LOG_SERVERC3(a,b,c,d) \ + SLOGC_3 (user_debug_sel & USER_LOG_SERVER,a,b,c,d) +#define USER_LOG_SERVERC4(a,b,c,d,e) \ + SLOGC_4 (user_debug_sel & USER_LOG_SERVER,a,b,c,d,e) +#define USER_LOG_SERVERC5(a,b,c,d,e,f) \ + SLOGC_5 (user_debug_sel & USER_LOG_SERVER,a,b,c,d,e,f) +#define USER_LOG_SERVERC6(a,b,c,d,e,f,g) \ + SLOGC_6 (user_debug_sel & USER_LOG_SERVER,a,b,c,d,e,f,g) +#define USER_LOG_SERVERC7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (user_debug_sel & USER_LOG_SERVER,a,b,c,d,e,f,g,h) +#define USER_LOG_SERVERC8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (user_debug_sel & USER_LOG_SERVER,a,b,c,d,e,f,g,h,i) + +/* Hex log macro */ +#define USER_LOG_SERVERH(a,b) \ + SLOGH (user_debug_sel & USER_LOG_SERVER,a,b) + +#define USER_LOG_SERVER_HEX USER_LOG_SERVERH /* for backward compatibility*/ + +#ifdef __cplusplus +} +#endif + +/************************************************************************/ +#endif /* End of MMS_LOG_INCLUDED */ +/************************************************************************/ + diff --git a/mmslib/inc/mmslusec.h b/mmslib/inc/mmslusec.h new file mode 100644 index 0000000..f0f4b4f --- /dev/null +++ b/mmslib/inc/mmslusec.h @@ -0,0 +1,58 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003 - 2004, All Rights Reserved. */ +/* */ +/* MODULE NAME : mmslusec.h */ +/* PRODUCT(S) : MMS-EASE Lite with LITESECURE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Prototypes for Security related user functions. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/20/04 EJV 03 ulFreeAssocSecurity: del cc param. */ +/* 01/06/04 EJV 02 Merged with MMS-EASE mms_usec.h. */ +/* 07/08/03 EJV 01 Adopted from MMS-EASE mms_usec.h. */ +/************************************************************************/ +#ifndef MMS_USEC_H +#define MMS_USEC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------------------*/ +/* NOTE: The MMS-EASE Lite Secured applications (Client, Server) */ +/* are designed to work with Security Toolkit for MMS-EASE Lite */ +/* (LITESECURE-000-001). */ +/*----------------------------------------------------------------------*/ + +#if defined(S_SEC_ENABLED) + +#include "acseauth.h" +#include "ssec.h" + + +ST_RET ulSetSecurityCalling (ST_CHAR *locArName, + ST_CHAR *remArName, + S_SEC_LOC_AR **locArSecOut, + S_SEC_REM_AR **remArSecOut, + ACSE_AUTH_INFO *locAuthInfo, + S_SEC_ENCRYPT_CTRL *encryptCtrl); +ST_RET ulCheckSecureAssocConf (MVL_NET_INFO *cc); +ST_RET ulCheckSecureAssocInd (MVL_NET_INFO *cc, ACSE_AUTH_INFO *rspAuthInfo); +ST_RET ulFreeAssocSecurity (ACSE_AUTH_INFO *authInfo); +ST_RET ulCheckSecurityConfiguration (ST_VOID); + +#endif /* defined(S_SEC_ENABLED) */ + +#ifdef __cplusplus +} +#endif + +#endif /* MMS_USEC_H */ diff --git a/mmslib/inc/mmsop_en/mmsop_en.h b/mmslib/inc/mmsop_en/mmsop_en.h new file mode 100644 index 0000000..8a9038a --- /dev/null +++ b/mmslib/inc/mmsop_en/mmsop_en.h @@ -0,0 +1,185 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* MODULE NAME : mmsop_en.h */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the operation enable switches used to */ +/* configure the decode system, the user service system, & the */ +/* supported services bit strings. */ +/* */ +/* Note that by enabling (or disabling) only the desired MMS */ +/* operations, a limited subset may be created (the subset */ +/* creation module is mmsop_en.c), thus allowing the creation of */ +/* a smaller executable because: */ +/* 1) references to the various MMS-EASE functions are removed */ +/* and therefore are not included from the library, and */ +/* 2) operation specific user application code is eliminated. */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/14/98 JRB 04 Put "MPARAM*" defines back. */ +/* Only user code needs them. */ +/* 03/20/98 JRB 03 Move defines used by libraries to mms_def2.h */ +/* Only user code needs this file now. */ +/* 09/16/97 DSF 02 Fixed comments */ +/* 08/18/97 MDE 01 Added parameter support defines */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef MMSOP_EN_INCLUDED +#define MMSOP_EN_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mms_def2.h" /* for REQ_RESP_EN, etc. */ + +/************************************************************************/ +/* define the opcode enable switches */ +/************************************************************************/ +#define MMS_INIT_EN REQ_RESP_EN +#define MMS_CONCLUDE_EN REQ_RESP_EN +#define MMS_CANCEL_EN REQ_RESP_EN + +#define MMS_STATUS_EN REQ_RESP_EN +#define MMS_USTATUS_EN REQ_RESP_EN +#define MMS_GETNAMES_EN REQ_RESP_EN +#define MMS_IDENT_EN REQ_RESP_EN +#define MMS_RENAME_EN REQ_RESP_EN +#define MMS_GETCL_EN REQ_RESP_EN +#define MMS_VMD_EN 0 + +#define MMS_NAMED_DOM_EN 0 +#define MMS_MV_DWN_EN REQ_RESP_EN /* VM download */ +#define MMS_INIT_DWN_EN REQ_RESP_EN +#define MMS_DWN_LOAD_EN REQ_RESP_EN +#define MMS_TERM_DWN_EN REQ_RESP_EN +#define MMS_MV_UPL_EN REQ_RESP_EN /* VM upload */ +#define MMS_INIT_UPL_EN REQ_RESP_EN +#define MMS_UP_LOAD_EN REQ_RESP_EN +#define MMS_TERM_UPL_EN REQ_RESP_EN +#define MMS_RDDWN_EN REQ_RESP_EN +#define MMS_RDUPL_EN REQ_RESP_EN +#define MMS_LOAD_DOM_EN REQ_RESP_EN +#define MMS_STR_DOM_EN REQ_RESP_EN +#define MMS_DEL_DOM_EN REQ_RESP_EN +#define MMS_GET_DOM_EN REQ_RESP_EN + +#define MMS_CRE_PI_EN REQ_RESP_EN +#define MMS_DEL_PI_EN REQ_RESP_EN +#define MMS_START_EN REQ_RESP_EN +#define MMS_STOP_EN REQ_RESP_EN +#define MMS_RESUME_EN REQ_RESP_EN +#define MMS_RESET_EN REQ_RESP_EN +#define MMS_KILL_EN REQ_RESP_EN +#define MMS_GET_PI_EN REQ_RESP_EN + +#define MMS_VA_EN 1 +#define MMS_MV_READ_EN REQ_RESP_EN /* VM Read variable(s) */ +#define MMS_MV_RDVARS_EN REQ_RESP_EN /* General VM Rd var's */ +#define MMS_READ_EN REQ_RESP_EN +#define MMS_MV_WRITE_EN REQ_RESP_EN /* VM Write variable(s) */ +#define MMS_MV_WRVARS_EN REQ_RESP_EN /* General VM WR var's */ +#define MMS_WRITE_EN REQ_RESP_EN +#define MMS_INFO_EN REQ_RESP_EN +#define MMS_GETVAR_EN REQ_RESP_EN +#define MMS_DEFVAR_EN REQ_RESP_EN +#define MMS_DEFSCAT_EN REQ_RESP_EN +#define MMS_GETSCAT_EN REQ_RESP_EN +#define MMS_DELVAR_EN REQ_RESP_EN +#define MMS_DEFVLIST_EN REQ_RESP_EN +#define MMS_GETVLIST_EN REQ_RESP_EN +#define MMS_DELVLIST_EN REQ_RESP_EN +#define MMS_MV_DEFTYPE_EN REQ_RESP_EN /* VM DefineType */ +#define MMS_DEFTYPE_EN REQ_RESP_EN +#define MMS_GETTYPE_EN REQ_RESP_EN +#define MMS_DELTYPE_EN REQ_RESP_EN + +#define MMS_TAKECTRL_EN REQ_RESP_EN +#define MMS_RELCTRL_EN REQ_RESP_EN +#define MMS_DEFINE_SEM_EN REQ_RESP_EN +#define MMS_DELETE_SEM_EN REQ_RESP_EN +#define MMS_REP_SEMSTAT_EN REQ_RESP_EN +#define MMS_REP_SEMPOOL_EN REQ_RESP_EN +#define MMS_REP_SEMENTRY_EN REQ_RESP_EN + +#define MMS_JREAD_EN REQ_RESP_EN +#define MMS_JWRITE_EN REQ_RESP_EN +#define MMS_JINIT_EN REQ_RESP_EN +#define MMS_JSTAT_EN REQ_RESP_EN +#define MMS_JCREATE_EN REQ_RESP_EN +#define MMS_JDELETE_EN REQ_RESP_EN + +#define MMS_DEFEC_EN REQ_RESP_EN +#define MMS_DELEC_EN REQ_RESP_EN +#define MMS_GETECA_EN REQ_RESP_EN +#define MMS_REPECS_EN REQ_RESP_EN +#define MMS_ALTECM_EN REQ_RESP_EN +#define MMS_TRIGE_EN REQ_RESP_EN +#define MMS_DEFEA_EN REQ_RESP_EN +#define MMS_DELEA_EN REQ_RESP_EN +#define MMS_GETEAA_EN REQ_RESP_EN +#define MMS_REPEAS_EN REQ_RESP_EN +#define MMS_DEFEE_EN REQ_RESP_EN +#define MMS_DELEE_EN REQ_RESP_EN +#define MMS_GETEEA_EN REQ_RESP_EN +#define MMS_REPEES_EN REQ_RESP_EN +#define MMS_ALTEE_EN REQ_RESP_EN +#define MMS_EVNOT_EN REQ_RESP_EN +#define MMS_ACKEVNOT_EN REQ_RESP_EN +#define MMS_GETAS_EN REQ_RESP_EN +#define MMS_GETAES_EN REQ_RESP_EN + +#define MMS_INPUT_EN REQ_RESP_EN +#define MMS_OUTPUT_EN REQ_RESP_EN + +#define MMS_MV_FOPEN_EN REQ_RESP_EN /* VM FileOpen */ +#define MMS_MV_FREAD_EN REQ_RESP_EN /* VM FileRead */ +#define MMS_MV_FCLOSE_EN REQ_RESP_EN /* VM FileClose */ +#define MMS_MV_FCOPY_EN REQ_RESP_EN /* VM FileCopy */ +#define MMS_OBTAINFILE_EN REQ_RESP_EN +#define MMS_FOPEN_EN REQ_RESP_EN +#define MMS_FREAD_EN REQ_RESP_EN +#define MMS_FCLOSE_EN REQ_RESP_EN +#define MMS_FRENAME_EN REQ_RESP_EN +#define MMS_FDELETE_EN REQ_RESP_EN +#define MMS_FDIR_EN REQ_RESP_EN + + +/************************************************************************/ +/************************************************************************/ +/* PARAMETER SUPPORTED BITSTRING VALUES */ +/************************************************************************/ + +#define MPARAM_STR1 0x80 /* 0x80 arrays */ +#define MPARAM_STR2 0x40 /* 0x40 structures */ +#define MPARAM_VNAM 0x20 /* 0x20 named variables */ +#define MPARAM_VALT 0x10 /* 0x10 alternate access */ +#define MPARAM_VADR 0x08 /* 0x08 address formed variables */ +#define MPARAM_VSCA 0x00 /* 0x04 scattered access */ +#define MPARAM_TPY 0x02 /* 0x02 third party */ +#define MPARAM_VLIS 0x01 /* 0x01 variable list */ +#define MPARAM_REAL 0x00 /* 0x80 real data type */ +#define MPARAM_AKEC 0x00 /* 0x40 ack event cond. */ +#define MPARAM_CEI 0x00 /* 0x20 cond. eval. interval */ + +#define MPARAM0 MPARAM_STR1 | MPARAM_STR2 | MPARAM_VNAM | MPARAM_VALT |\ + MPARAM_VADR | MPARAM_VSCA | MPARAM_TPY | MPARAM_VLIS +#define MPARAM1 MPARAM_REAL | MPARAM_AKEC | MPARAM_CEI + + +#ifdef __cplusplus +} +#endif + +#endif /* MMSOP_EN_INCLUDED */ + diff --git a/mmslib/inc/mvl_acse.h b/mmslib/inc/mvl_acse.h new file mode 100644 index 0000000..0a79fbb --- /dev/null +++ b/mmslib/inc/mvl_acse.h @@ -0,0 +1,234 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2005, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_acse.h */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/10/05 EJV 26 Moved up osicfgx proto. */ +/* 04/06/05 EJV 25 Added MMSEASE_MOSI. */ +/* 03/28/05 JRB 24 Del suicacse header. */ +/* 08/11/04 JRB 23 Del global funct ptr u_mvl_connect_ind_fun. */ +/* Fix mvl_abort_req_ex return (ST_RET). */ +/* 07/08/04 JRB 22 Del unused global var mvl_local_cl_ar_name. */ +/* 07/23/03 MDE 21 Removed ACSE_AUTH_ENABLED */ +/* 06/16/03 EJV 20 Removed m_match.h, s_match.h includes */ +/* Chg M_MATCH_CTRL to DIB_MATCH_CTRL. */ +/* 06/10/03 MDE 19 Added address matching */ +/* 10/11/02 ASK 18 Added mvla_initiate_req_ex and */ +/* u_mvl_connect_*_ex */ +/* 05/13/02 MDE 17 Added structure element comments */ +/* 05/03/02 MDE 16 Added mvl_add_bind_ctrl, associated changes */ +/* 02/25/02 MDE 15 More changes to MVL_CFG_INFO */ +/* 02/20/02 MDE 14 Changes to new MVL_CFG_INFO, for mult. bind */ +/* 02/07/02 JRB 13 Define MVL_CFG_INFO & pass to mvl_start_acse.*/ +/* Move osicfgx proto here, add MVL_CFG_INFO arg*/ +/* Del global var mvl_local_ar_name. */ +/* 01/29/02 JRB 12 Replace mvl_init_cl_netinfo funct with */ +/* mvl_init_audt_addr. */ +/* 11/28/01 MDE 11 mvl_set_num_connections,mvl_set_max_msg_size */ +/* 01/05/01 MDE 10 Changes for use over Marben */ +/* 06/26/00 JRB 09 Del "#define MVL_ACSE". Not used. */ +/* Move "#define COACSE" to mvl_defs.h (avoids */ +/* mvl_defs.h dependence on mvl_acse.h). */ +/* 03/09/00 MDE 08 Added _mvl_init_conn_ctrl */ +/* 07/30/99 JRB 07 Chg ma_clbind_ctrl from static to global. */ +/* 04/13/99 MDE 06 Added '_mvla_initiate_locDe' */ +/* 03/18/99 MDE 05 Made connection limits runtime settable */ +/* 11/16/98 MDE 04 Removed mvl_release, mvla_release (obsolete) */ +/* 07/16/98 MDE 03 Addded 'mvl_dib_entry_to_app_ref' */ +/* 06/19/98 JRB 02 Add tp_type, etc. to NET_BIND_CTRL. */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#ifndef MVL_ACSE_INCLUDED +#define MVL_ACSE_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MMSEASE_MOSI) +/* min includes */ +#include "mms_def2.h" +#else +#include "acse2usr.h" +#include "mvl_defs.h" + +/************************************************************************/ +/* Some error return codes */ +#define REQ_INCOMPLETE 0x100 +#define LOCAL_NAME_NOT_FOUND 0x101 +#define REMOTE_NAME_NOT_FOUND 0x102 + +#define MVLE_LOCAL_NAME 0x101 +#define MVLE_REMOTE_NAME 0x102 +#define MVLE_NUM_CONNECTIONS 0x103 + +/************************************************************************/ +/* Bind and Connection control structures */ + +struct dib_entry; /* Forward declaration */ +#endif /* !defined(MMSEASE_MOSI) */ + +typedef struct net_bind_ctrl + { +/* These parameters must be set before using in mvl_start_acse */ + ST_CHAR ar_name[MAX_AR_LEN+1]; + ST_INT num_calling; + ST_INT num_called; + +/* Internal */ + ST_VOID *user_info; +#ifdef LEAN_T + ST_INT tp_type; + ST_INT32 copp_bind_id_tcp; + ST_INT32 copp_bind_id_tp4; +#else + ST_INT32 copp_bind_id; +#endif + ST_INT32 clpp_bind_id; + struct dib_entry *de; + } NET_BIND_CTRL; + +/************************************************************************/ +/* MVL configuration information. Filled in by user or configuration */ +/* and passed to mvl_start_acse. */ +/************************************************************************/ + +typedef struct + { + ST_INT max_msg_size; /* Max MMS message size */ + ST_INT num_calling; /* total number of calling connections */ + ST_INT num_called; /* total number of called connections */ + +/* Used for single local address binding (LEAN-T) */ + ST_CHAR local_ar_name[MAX_AR_LEN+1]; + +/* Used for multiple local address binding only (MARBEN) */ +#ifdef MAP30_ACSE /* Select bind mode */ + ST_BOOLEAN use_bind_ctrl; /* Set to 0 for single local */ +#endif + +/* User sets these only when use_bind_ctrl is SD_TRUE (MARBEN) */ + ST_INT max_bind_ctrl; /* Max allowed */ + ST_INT num_bind_ctrl; /* Active bindings */ + NET_BIND_CTRL *bind_ctrl; /* Array of NET_BIND_CTRL */ + +/* Internal use */ + ST_INT calling_used; /* Number mvl_calling_conn_ctrl bound */ + ST_INT called_used; /* Number mvl_called_conn_ctrl bound */ + } MVL_CFG_INFO; + +/* Persistant config information; set by MVL during mvl_start_acse */ +extern MVL_CFG_INFO *mvl_cfg_info; + +ST_RET osicfgx (ST_CHAR *xml_filename, MVL_CFG_INFO *mvlCfg); + +#if !defined(MMSEASE_MOSI) + +/************************************************************************/ +/* Global configuration variables */ + +extern INIT_INFO *mvl_init_resp_info; +extern NET_BIND_CTRL ma_clbind_ctrl; /* to save clpp_bind info. */ + +#if defined(MAP30_ACSE) +extern ST_INT mvl_num_bind_ctrl; +extern NET_BIND_CTRL *mvl_bind_ctrl; +#endif +ST_RET mvla_set_init_ar (ST_CHAR *ar_name); + +/************************************************************************/ +/* ACSE interface related MVL ACSE functions */ + +ST_VOID mvl_set_max_msg_size (ST_INT max_msg_size); + +ST_RET mvl_start_acse (MVL_CFG_INFO *cfgInfo); +ST_RET mvl_end_acse (ST_VOID); + + +ST_VOID _mvl_init_conn_ctrl (ST_VOID); + +ST_RET mvl_initiate_req (ST_CHAR *remAr, + INIT_INFO *req_info, + INIT_INFO *resp_info, + MVL_NET_INFO **net_info_out); + +ST_RET mvla_initiate_req (ST_CHAR *remAr, + INIT_INFO *req_info, + INIT_INFO *resp_info, + MVL_NET_INFO **net_info_out, + MVL_REQ_PEND **req_out); + +ST_INT mvla_initiate_req_ex (ST_CHAR *remAr, + INIT_INFO *req_info, + INIT_INFO *resp_info, + MVL_NET_INFO **net_info_out, + MVL_REQ_PEND **req_out, + ACSE_AUTH_INFO *auth_info, + S_SEC_ENCRYPT_CTRL *encrypt_info); + +/* If this variable is not NULL, MVL will use it as the source for the */ +/* local dib entry for an initiate request. */ +extern struct dib_entry *_mvla_initiate_locDe; + +ST_RET mvl_abort_req (MVL_NET_INFO *cc); +ST_RET mvl_abort_req_ex (MVL_NET_INFO *cc, + ST_BOOLEAN diagnostic_pres, + ST_ACSE_AUTH diagnostic); + +ST_RET mvl_init_audt_addr (AUDT_APDU *audt, ST_CHAR *locArName, ST_CHAR *remArName); +ST_VOID mvl_dib_entry_to_app_ref (struct dib_entry *de, struct app_ref *appRef); +ST_RET mvl_add_bind_ctrl (NET_BIND_CTRL *bc); + +/************************************************************************/ +/* User defined function pointer to handle disconnect indications */ + +#define MVL_ACSE_RELEASE_IND 1 +#define MVL_ACSE_ABORT_IND 2 +extern ST_VOID (*u_mvl_disc_ind_fun) (MVL_NET_INFO *cc, ST_INT discType); + +/************************************************************************/ +/* User defined functions to handle connect indications & confirms. */ +/* User must supply these functions. */ + +extern ST_ACSE_AUTH u_mvl_connect_ind_ex (MVL_NET_INFO *cc, INIT_INFO *init_info, ACSE_AUTH_INFO *req_auth_info, ACSE_AUTH_INFO *rsp_auth_info); +extern ST_ACSE_AUTH u_mvl_connect_cnf_ex (MVL_NET_INFO *cc, AARE_APDU *ass_rsp_info); + +/************************************************************************/ + +/* MVL level address matching functions */ +ST_RET mvl_match_remote_ar (DIB_MATCH_CTRL *matchCtrl, struct mvl_net_info *cc, + struct dib_entry **dib_entry_out); +ST_RET mvl_match_local_ar (DIB_MATCH_CTRL *matchCtrl, struct mvl_net_info *cc, + struct dib_entry **dib_entry_out); +ST_INT mvl_cmp_local_addr (DIB_MATCH_CTRL *matchCtrl, struct mvl_net_info *cc, + struct dib_entry *dib_entry); +ST_INT mvl_cmp_remote_addr (DIB_MATCH_CTRL *matchCtrl, struct mvl_net_info *cc, + struct dib_entry *dib_entry); + +#if defined(MAP30_ACSE) +ST_RET mvl_net_info_to_chan (MVL_NET_INFO *cc, ST_INT *chanOut); +#endif + +#endif /* !defined(MMSEASE_MOSI) */ + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* MVL_ACSE_INCLUDED */ +/************************************************************************/ + diff --git a/mmslib/inc/mvl_defs.h b/mmslib/inc/mvl_defs.h new file mode 100644 index 0000000..3c047f5 --- /dev/null +++ b/mmslib/inc/mvl_defs.h @@ -0,0 +1,2552 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2003, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_defs.h */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/27/09 JRB 132 MVLAS_WRITE_CTRL: add ind_funct_done. */ +/* 09/25/08 MDE 131 Added MMS result info for READ/WRITE */ +/* 07/23/08 JRB 130 Move defs from mvl_uca.h to here (need earlier).*/ +/* Fix CntrlObj size. */ +/* 06/24/08 MDE 129 Added _mvl_persist_aa_objs */ +/* 06/04/08 JRB 128 Add file_list to MVL_NET_INFO. */ +/* Add mplas_concl_err. */ +/* Del mvl_type_ctrl from typedef (global var */ +/* with same name confused some debuggers). */ +/* 04/08/08 JRB 127 Chg () to (ST_VOID) in 2 prototypes. */ +/* 02/26/08 JRB 126 Add mvl_var_add_alloc, mvl_var_create_alloc. */ +/* Add mvl_var_create_derived. */ +/* mvl_dom_destroy: chg ret to void (can't fail)*/ +/* Add _mvl_clear_aa_objs. */ +/* 11/12/07 MDE 125 Added _mvl_getpath, changed _mvl_tmpnam */ +/* 04/16/07 JRB 124 Add prim_num to MVL_VAR_ASSOC. */ +/* 03/19/07 JRB 123 Del obsolete "mvl_vmd_*" macros. */ +/* 12/04/06 JRB 122 mvl_vmd_destroy: add arg to specify which VMD.*/ +/* 11/21/06 JRB 121 Move ..LAST_APPL_ERROR struct def to here */ +/* and add it to MVLAS_WR_VA_CTRL. */ +/* 10/30/06 JRB 120 Del #ifdef in structs so they do not change */ +/* with compiler options. */ +/* Del MVL_DYN_ASN1_TYPES option, always use */ +/* dynamic ASN1. Del asn1 from MVL_TYPE_CTRL. */ +/* 10/30/06 JRB 119 New object handling functions take VMD arg */ +/* & have "mvl_vmd_" prefix. Macros provided */ +/* for backward compatibility only. */ +/* mvl_nvl_create: change args. */ +/* Add "mvl_vmd_type_id_*". */ +/* Add mvl_vmd_create, */ +/* mvlu_rpt_ctrl_destroy_all, */ +/* mvl61850_rpt_ctrl_destroy_all. */ +/* u_mvl_get_va_aa: add vmd_ctrl arg. */ +/* u_gnl_ind_*: add net_info arg. */ +/* _mvl_objname_to_va: add vmd_ctrl, net_info args*/ +/* Del global var _mvl_curr_net_info. */ +/* Del global var _mvl_curr_usr_ind_ctrl. */ +/* 10/17/06 MDE 118 Added mvlas_obtfile_resp_ex */ +/* 07/21/06 JRB 117 Add rpt_reason & type_ctrl to MVL_VAR_ASSOC. */ +/* Add already_scanned to MVL_NVLIST_CTRL. */ +/* 07/13/05 MDE 116 Added u_mvl_reject_ind */ +/* 06/29/05 CRM 115 Add mvl_vmd_destroy. */ +/* 06/27/05 JRB 114 MVL_VAR_ASSOC: del mvl_internal, add last_data.*/ +/* 06/27/05 CRM 113 Added mvl_dom_find_last and */ +/* mvl_type_id_destroy_all_dyn. */ +/* 05/04/05 MDE 112 Added mvl_init_ind_hold */ +/* 03/28/05 JRB 111 Del suicacse header. */ +/* 03/14/05 CRM 110 Add mvl_max_dyn global variable. */ +/* Del _mvlu_num_dyn_types, add backward compat def*/ +/* 03/08/05 CRM 109 Add mvlas_fdir_resp(MVL_IND_PEND *ind) */ +/* 03/07/05 MDE 108 Added startTime to stats */ +/* 09/20/04 JRB 107 Add comments. */ +/* 08/30/04 JRB 106 Add sboCtrl to MVLAS_WR_VA_CTRL. */ +/* 06/29/04 JRB 105 Add mvl_type_id_create_from_tdl proto. */ +/* Add use_static_data flag to MVL_VAR_ASSOC. */ +/* Increase MAX_JREAD_RESP_ENTRIES define. */ +/* 07/10/03 EJV 104 Chg loc_ar_sec/rem_ar_sec to (S_SEC_LOC_AR *)*/ +/* 04/11/03 MDE 103 Added security elements */ +/* 04/11/03 MDE 102 Added _mvl_tmpnam */ +/* 04/04/03 JRB 101 MVL_IND_PEND: Add scan_va_done_fun for */ +/* IEC/UCA integrity scan. */ +/* 03/13/03 JRB 100 mvl_type_id_create: Add type_name arg. */ +/* MVL_TYPE_CTRL: Chg type_name to array. */ +/* MVL_TYPE_CTRL: Add rt_ctrl for dynamic types.*/ +/* Add mvl_type_ctrl_find_dyn. */ +/* Add mvl_scope_set proto. */ +/* Del mvlu_add_rt_type_x (not needed). */ +/* 12/12/02 JRB 99 Add usr_resp_fun to MVL_IND_PEND */ +/* Add mvl_internal to MVL_VAR_ASSOC */ +/* Chg acse_conn_id to ST_LONG to match ACSE */ +/* Add net_info arg to mvl_get_va_asn1_data */ +/* Add mvl_encode_info_rpt proto */ +/* Add enc_buf allocation macros. */ +/* 12/10/02 JRB 98 Moved UCA defs to new mvl_uca.h */ +/* 12/09/02 MDE 96 Added mvlu_find_uca_var */ +/* 12/09/02 MDE 96 Changed SBO reference handling */ +/* 11/27/02 MDE 95 Addded runtime leaf parameter manipulation */ +/* Added type_name to MVL_TYPE_CTRL */ +/* Added mvlu_add_rt_type_x */ +/* Added mvlu_proc_rt_type */ +/* 07/17/02 JRB 94 Del _mvla_send_write.. proto. Use static fct.*/ +/* 07/09/02 JRB 93 Add mvl_(u)req_bufs_avail functions. */ +/* 07/09/02 MDE 92 Add maxpend_ind support */ +/* 05/13/02 MDE 91 Added 'skip' arg to _mvl_set_net_req_done */ +/* 03/25/02 MDE 90 Moved error/reject elements outside union */ +/* 02/27/02 JRB 89 Fix mvl_print... proto. */ +/* 02/25/02 MDE 88 Deleted mvl_num_call* vars */ +/* 01/29/02 JRB 87 Del use of MVL_NUM_CALL* & COACSE. */ +/* Del a_unit_data_info,stack_sel from MVL_NET_INFO.*/ +/* 01/23/02 EJV 86 Added journals to MVL_DOM_CTRL */ +/* mvl_init_dom - added max_jou param */ +/* mvl_dom_resize - added max_jou param */ +/* mvl_dom_create - added max_num_jou param */ +/* mvl_dom_add - added max_num_jou param */ +/* 12/20/01 HSF 85 Added usr field to MVLU_RPT_SCAN_CTRL */ +/* 12/12/01 MDE 84 Moved acse_conn_id outside ifdef */ +/* 11/31/01 MDE 83 Added GOOSE scan support */ +/* 11/01/01 JRB 82 Chg mvl_wait_req_done return to ST_RET. */ +/* Add wait_any_event proto (user must supply). */ +/* 07/31/01 MDE 81 Added mvl_conn_filtered_logging support */ +/* 03/19/01 JRB 80 Move SMEM context defs to "smem.h". */ +/* 03/15/01 JRB 79 Add clientUstatus, serverUstatus statistics. */ +/* 03/13/01 JRB 78 Add mvl_ustatus, _mvl_process_ustatus_ind, */ +/* u_mvl_ustatus_ind prototypes. */ +/* 01/19/00 MDE 77 Removed SMEM idx defines (now in mem_chk.h) */ +/* 01/05/01 MDE 76 Changes for use over Marben */ +/* 10/25/00 JRB 75 Del u_mvl*, u_gnl* & _ml_* funct ptrs. */ +/* Add u_mvl_concl_ind, mplas_concl_resp. */ +/* Add req_pend_list to mvl_net_info. */ +/* Del usrNvl from MVLAS_READ_CTRL (not needed).*/ +/* Add "Server" support for Upl/Downl. */ +/* 10/06/00 MDE 74 Added _mvlu_num_dyn_types */ +/* 09/05/00 JRB 73 Add mvl_get_runtime_dyn. */ +/* 08/18/00 JRB 72 Fixed mvl_type_id_cre.. proto. */ +/* 08/18/00 RKR 71 Added rt field to MVLU_ typedefs */ +/* 07/26/00 MDE 70 Added user field to MVL_FGET_REQ_INFO */ +/* 07/12/00 JRB 69 Add dynamic type creation prototypes. */ +/* 07/11/00 MDE 68 Changed seqNum to sqNum, made INT8U */ +/* 06/26/00 JRB 67 Move "#define COACSE" from mvl_acse.h to */ +/* here (avoids dependence on mvl_acse.h). */ +/* 06/12/00 GLB 66 Added info for asynchronous File Get */ +/* 06/01/00 RKR 65 Removed some prototypes redundant in MMS-EASE*/ +/* 05/01/00 JRB 64 Del mvl_init_type_ctrl proto; now it's static*/ +/* 04/14/00 JRB 63 Fix SD_CONST for ??IndFunTbl, mvl_get_run... */ +/* Delete remnants of MVL_REQ_BUF_ENABLED. */ +/* 04/12/00 MDE 62 Added MVL_STATISTICS, _mvl_resize_ptr_tbl */ +/* 04/05/00 RKR 61 Made MVL_XNAME a compile time option */ +/* 04/04/00 RKR 60 Added expanded UCA variable name to RD and WR*/ +/* 03/10/00 JRB 59 Add scan_va_scope to MVLU_RPT_SCAN_CTRL. */ +/* 03/07/00 MDE 58 Added type_id to string declarations */ +/* 01/21/00 MDE 57 Now use MEM_SMEM for dynamic memory */ +/* 10/20/99 NAV 56 Add maxpend_req support */ +/* 09/28/99 NAV 55 Modified UCA Report REASON Bits */ +/* 09/13/99 MDE 54 Added SD_CONST modifiers */ +/* 11/04/99 RKR 53 Removed action_required from MVL_NET_INFO */ +/* 11/03/99 RKR 52 Added MVL error constants */ +/* 10/28/99 RKR 51 Added pending indications to MVL_NET_INFO */ +/* 10/07/99 GLB 50 Added support for file rename & obtain file. */ +/* 10/05/99 RKR 49 Added prototypes for deriving types */ +/* 09/30/99 JRB 48 Added forward declaration to reduce warnings.*/ +/* 09/30/99 RKR 47 Changed the Reason for Inclusion bit strings */ +/* 09/24/99 JRB 46 Added extern to mvlu_rpt_scan_list */ +/* 09/13/99 MDE 45 Added SD_CONST modifiers */ +/* 09/07/99 MDE 44 Revised and enhanced the UCA report system */ +/* 09/07/99 MDE 43 Changed MVL_VA_SCOPE to MVL_SCOPE, added */ +/* scope to MVL_NVLIST_CTRL */ +/* 07/30/99 MDE 42 Removed unused defines */ +/* 04/01/99 MDE 41 Changes to decode buffer allocation scheme */ +/* 03/18/99 MDE 40 Enhanced dynamic object facilities */ +/* 03/18/99 MDE 39 Changes to support runtime connection limits */ +/* 03/09/99 MDE 38 Added ICCP Lite support */ +/* 01/22/99 JRB 37 Chg all objects to array of ptrs so bsearch */ +/* can be used. Add bsearch functs (mvl_obj_*). */ +/* Use "mvl_nvl" prefix on all NVL obj functs. */ +/* Add "flags" to MVL_VAR_ASSOC for UCA. */ +/* 12/08/98 MDE 36 Added client alternate access support */ +/* 12/08/98 MDE 35 Added dynamic object handling */ +/* 11/17/98 MDE 34 Added _mvl_destroy_nvl_entries */ +/* 11/16/98 MDE 33 Cleanup and rearrange for readability */ +/* 11/16/98 MDE 32 Added 'locl_init_info' to MVL_NET_CTRL' */ +/* 11/16/98 MDE 30 Renamed MVL interal functions ('_'prefix) */ +/* 11/16/98 MDE 29 Added mvl_concl, mvla_concl */ +/* 11/16/98 MDE 28 Removed 'wait_any_event', 'read_log_cfg_file'*/ +/* 11/13/98 JRB 27 Add wait_any_event proto. */ +/* 10/12/98 MDE 26 Merged JRB's and MDE's changes */ +/* 10/09/98 JRB 25 Chg MVL_JOURNAL_ENTRY to use VAR_INFO. */ +/* Del MVL_CLI_JOURNAL_ENTRY, use only */ +/* MVL_JOURNAL_ENTRY everywhere. */ +/* Add 'read_log_cfg_file' prototype. */ +/* 10/09/98 DWL 24 Added get_dom stuff */ +/* Added get_nam stuff */ +/* Added status stuff */ +/* 10/09/98 DWL 23 Added get_var stuff */ +/* 10/01/98 MDE 22 Changed 'SD_CONST' define */ +/* 10/01/98 MDE 21 Changed rcb to ptr, removed MVL_NUM_CALLED */ +/* 10/01/98 MDE 20 Changed MVL_JOURNAL_ENTRY entry_id to */ +/* ST_UCHAR[8] */ +/* 09/21/98 MDE 19 Minor lint cleanup */ +/* 09/16/98 MDE 18 Fixed possible UCA report 'reason' overwrite */ +/* Added 'mvlu_rpt_ctrl_ptrs[MVLU_NUM_RPT_CTRL]'*/ +/* Added SBO support */ +/* 09/10/98 MDE 17 Added 'SD_CONST' declaration */ +/* 08/13/98 MDE 16 Removed USE_RT_DATA stuff */ +/* 08/11/98 MDE 15 Added UCA variable array support */ +/* 08/10/98 MDE 14 Changes to UCA report handling */ +/* 07/28/98 MDE 13 Added USE_RT_DATA define, related changes */ +/* 07/16/98 MDE 12 More journal work */ +/* 07/15/98 MDE 11 Changed Journal Read user functions */ +/* 07/13/98 MDE 10 Report and Journal work */ +/* 06/30/98 MDE 09 Added more flexable CLient Info Rpt code */ +/* 06/22/98 MDE 08 SeqNum now ST_UINT16 */ +/* 06/15/98 MDE 07 Changes to allow compile under C++ */ +/* 05/14/98 JRB 06 Add support for more services. */ +/* Add u_mvl_read_ind, u_mvl_write_ind, and */ +/* delete corresponding function ptrs. */ +/* Del mvl_ident_resp_info, mvl_status_resp_info*/ +/* Chg "Conf" function arg to (MVL_REQ_PEND *). */ +/* Chg "Ind" function arg to (MVL_IND_PEND *). */ +/* Add (MVL_REQ_PEND**) to sync client functs. */ +/* 03/15/98 MDE 05 Added support for user loaded Runtime Types, */ +/* dynamic NVL's */ +/* 02/10/98 MDE 04 Always support AA, added 'index' to conn */ +/* control, added UCA support, more. */ +/* 12/22/97 MDE 03 Changed '_mvl_net_service', 'mvl_comm_serv' */ +/* 12/29/97 MDE 02 Added Journal stuff, general cleanup */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#ifndef MVL_DEFS_INCLUDED +#define MVL_DEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mmsdefs.h" +#include "gen_list.h" + +#include "acse2usr.h" + +/************************************************************************/ +/* This define adds items to the MVL_NET_INFO and MVL_REQ_PEND data */ +/* structures. This small memory cost may be eliminated by commenting */ +/* out this define (when ICCP-Lite is not to be used). */ +/* This is being done so we can build a single MVL library for use with */ +/* both ICCP and non-ICCP implementations. */ + +#define ICCP_LITE_SUPP + +/************************************************************************/ +/* COMPILE TIME OPTIONS */ + +/* Comment this out to save code when using only the Async interface */ +/* for client applications. Used in making the MVL library. */ +#define MVL_SYNC_REQ_INTERFACE + +/* These values are used in the MVL object initialization code to allow */ +/* the user to dynamically add additional objects. */ + +#define MVL_NUM_DYN_DOMS 10 + +#if !defined(MVL_NUM_DYN_VMD_VARS) +#define MVL_NUM_DYN_VMD_VARS 0 +#endif + +#define MVL_NUM_DYN_VMD_NVLS 10 +#define MVL_NUM_DYN_JOUS 10 +#define MVL_NUM_DYN_DOM_VARS 10 +#define MVL_NUM_DYN_DOM_NVLS 10 +#define MVL_NUM_DYN_AA_VARS 10 +#define MVL_NUM_DYN_AA_NVLS 10 + +/* MVL_UCA requires dynamic types to function */ +#define MVLU_NUM_DYN_TYPES 100 + +typedef struct + { + ST_INT aa_nvls; + ST_INT aa_vars; + ST_INT doms; + ST_INT dom_nvls; + ST_INT dom_vars; + ST_INT journals; + ST_INT types; + ST_INT vmd_nvls; + ST_INT vmd_vars; + } MVL_MAX_DYN; + +extern MVL_MAX_DYN mvl_max_dyn; + +/* OBSOLETE: For backward compatibility only */ +#define _mvlu_num_dyn_types mvl_max_dyn.types + +/* Comment this out to use statically allocated buffers */ +/* Note that dynamic buffers are required for async server responses. */ +#define MVL_DYN_MEM + +/* This define can be uncomented in order to use binary search for */ +/* MMS-LITE object searches (variables, named variable lists, etc.). */ +/* #define MVL_USE_BSEARCH */ + +/* Define this to support receiving Information Reports */ +#define MVL_INFO_RPT_CLIENT + +/* Uncomment this to enable support for described access as server */ +/* #define MVL_DESCR_SUPP */ /* Warning, not currently supported */ + +/* Uncomment this to enable support for expanded UCA variable names */ +/* This will save some processing and a small bit of code. */ +/* #define MVL_XNAME */ + +/* Comment this to disable Alternate Access support for as server */ +/* This will save a small bit of code. */ +#define MVL_AA_SUPP + +/************************************************************************/ +/* Miscellaneous defines. */ +/************************************************************************/ +/* Max size of some IEC 61850 objects. */ +#define MVL61850_MAX_OBJREF_LEN 129 /* Value specified by Tissue 141*/ +#define MVL61850_MAX_RPTID_LEN 65 + +/************************************************************************/ +/* MMS OBJECT INITIALIZATION */ +/* This function must be called to initialize all MVL types and other */ +/* MMS objects. */ + +ST_VOID mvl_init (ST_VOID); +ST_VOID mvl_init_mms_objs (ST_VOID); + +/* COMMUNICATION SERVICE */ +/* This is the high level function to be called periodicly by the */ +/* application. It will check for communications events and act on them,*/ +/* which will include decoding MMS PDU's and calling service functions. */ +/* The mechanism used to determine when this function should be called */ +/* will depend on the lower layer service provider. */ + +ST_BOOLEAN mvl_comm_serve (ST_VOID); + +/* SYNCHRONOUS REQUEST USER SERVICE/TIMEOUT */ +/* User defined function, called repetitively by MVL client functions */ +/* while waiting for confirm. If this function returns SD_TRUE, the */ +/* request will timeout and return SD_FAILURE. */ + +extern ST_BOOLEAN (*u_mvl_check_timeout)(ST_VOID); + + +/* For use when global variables cannot be initialized at compile time */ +#if defined(NO_GLB_VAR_INIT) +ST_VOID mvl_init_glb_vars (ST_VOID); + +/* Internal use only */ +ST_VOID _mvlop_en_init (ST_VOID); +ST_VOID _s_getnam_init_glb_vars (ST_VOID); +#endif + +/* If set == SD_TRUE, MVL will not delete AA objects when connection */ +/* terminates */ +extern ST_BOOLEAN _mvl_persist_aa_objs; + +/************************************************************************/ +/* CAPACITY/STACK USAGE CONTROL DEFINES */ +/* These defines work along with the MMS PDU buffer sizes to control */ +/* the maximum number of MMS objects and the size of the objects that */ +/* can be handled per MMS PDU. */ + +#define MAX_JREAD_RESP_ENTRIES 10 +/*renxiaobao ÈÕÖ¾¸ü¸Ä*/ +/*#define MAX_JREAD_RESP_VARS 100*/ +#define MAX_JREAD_RESP_VARS 512 + +#define MVL_MAX_GNL_NAMES 100 + +/************************************************************************/ +/* MVL ERROR CODES */ + +/* #define E_MMS_LITE 0x6A00 */ +#define MVL_ERR_USR_TIMEOUT 0x6A01 +#define MVL_ERR_REQ_CONTROL 0x6A02 +#define MVL_ERR_UNKNOWN_PDU_TYPE 0x6A03 +#define MVL_ERR_RUNTIME_TYPE_ID 0x6A04 +#define MVL_ERR_ASN1_TO_RUNTIME 0x6A05 +#define MVL_ERR_NOT_SYM_ADDR 0x6A06 +#define MVL_ERR_ARRAY_ELEMENT_CNT 0x6A07 +#define MVL_ERR_LOCAL_ADDRESS 0x6A08 +#define MVL_ERR_BUFFER_SIZE 0x6A09 +#define MVL_ERR_DOM_CONTROL 0x6A0A +#define MVL_ERR_AA_CONTROL 0x6A0B +#define MVL_ERR_AA_SPECIFIC 0x6A0C +#define MVL_ERR_NVL_NOT_FOUND 0x6A0D +#define MVL_ERR_ALT_ACCESS 0x6A0E +#define MVL_ERR_VA_NOT_FOUND 0x6A0F +#define MVL_ERR_VA_SPEC 0x6A10 +#define MVL_ERR_NO_REQ_CTRL 0x6A11 +#define MVL_ERR_NO_CONN_CTRL 0x6A12 +#define MVL_ERR_ASSOC_REQ 0x6A13 +#define MVL_ERR_COMM_SERVE_ACTIVE 0x6A14 +#define MVL_ERR_REQ_PEND_COUNT 0x6A15 +#define MVL_ERR_CNF_REJ_ERR 0x6A16 +#define MVL_ERR_CNF_ERR_OK 0x6A17 +#define MVL_ERR_CNF_DISCONNECTED 0x6A18 +#define MVL_ERR_BAD_TYPE 0x6A19 +#define MVL_ERR_RESOURCE_NOT_AVAIL 0x6A1A + +/************************************************************************/ +/* Structure used to create linked list of all open files for one */ +/* connection (see connection structure MVL_NET_INFO). */ +typedef struct mvl_net_file + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct mvl_net_file *next; /* CRITICAL: DON'T MOVE. */ + struct mvl_net_file *prev; /* CRITICAL: DON'T MOVE. */ + FILE *fp; /* file pointer from fopen */ + } MVL_NET_FILE; + +/************************************************************************/ +/************************************************************************/ +/* NETWORK CONNECTION CONTROL */ +/* MVL_NET_INFO is used to specify the remote node to which the PDU is */ +/* to be sent, or from which the PDU was received. This element and */ +/* it's use are implementation specific. */ + +struct mvl_ind_pend; /* Forward declare this to eliminate warnings. */ +struct mvl_req_pend; /* Forward declare this to eliminate warnings. */ + +typedef struct mvl_net_info + { + struct mvl_aa_obj_ctrl *aa_objs; /* AA object ctrl */ + struct mvl_vmd_ctrl *rem_vmd; /* Remote VMD */ + struct mvl_ind_pend *pend_ind; + struct mvl_req_pend *req_pend_list; /* link list of pending reqs*/ + + ST_BOOLEAN conn_active; /* Set SD_TRUE when the connection is up */ + ST_INT max_pdu_size; + ST_INT index; /* NET_INFO table index for this elmnt */ + + ST_INT maxpend_req; /* num outstanding reqs negotiated */ + ST_INT numpend_req; /* num reqs currently outstanding */ + + ST_INT maxpend_ind; /* num outstanding inds negotiated */ + ST_INT numpend_ind; /* num inds currently outstanding */ + + ST_BOOLEAN log_enable; /* For use w/mvl_conn_filtered_logging */ + + ST_LONG acse_conn_id; /* ACSE's connection ID, internal */ + + ST_BOOLEAN mi_in_use; /* used only for ICCP_LITE_SUPP */ + struct _mi_conn *mi_conn; /* used only for ICCP_LITE_SUPP */ + + INIT_INFO rem_init_info; /* Services supported by remote device */ + INIT_INFO locl_init_info; /* Initiate info we sent */ + AARQ_APDU ass_ind_info; + /* Items below are used by MVL only */ + ST_BOOLEAN in_use; /* Flag that this 'NET_INFO' is in use */ + struct net_bind_ctrl *bind_ctrl; + + S_SEC_LOC_AR *loc_ar_sec; + S_SEC_REM_AR *rem_ar_sec; + + ST_VOID *user_info; /* MVL user can use this for 'whatever' */ + MVL_NET_FILE *file_list; /* linked list of open files on this conn*/ + } MVL_NET_INFO; + +/* Our connection control structures */ +extern MVL_NET_INFO *mvl_calling_conn_ctrl; +extern MVL_NET_INFO *mvl_called_conn_ctrl; + +/************************************************************************/ +/* MMS COMMUNICATIONS EVENT */ +/* MMS_COMM_EVENT is the data structure used to pass a communication */ +/* event from the lower layer provider to the MVL communication service */ +/* subsystem. This structure may be expanded to fit the needs of the */ +/* application. */ + +#define MMS_MSG_RCVD 1 +#define RECEIVE_ERROR 2 +#define COMM_LINK_UP 3 +#define COMM_LINK_DOWN 4 +#define MVLU_RPT_COMM_EVENT 5 + +typedef struct mvl_comm_event + { + DBL_LNK l; /* For linked list */ + MVL_NET_INFO *net_info; + ST_INT event_type; + union + { + struct /* used for MMS_MSG_RCVD event types */ + { + ST_UCHAR *pdu; + ST_INT pdu_len; + MMSDEC_INFO dec_rslt; + } mms; + struct /* possibly add more structs to handle other event types*/ + { + ST_RET code; + } error; + }u; + } MVL_COMM_EVENT; + +/************************************************************************/ +/************************************************************************/ +/* MVL TYPE HANDLING */ +/* Runtime type handling functions and structures */ +/* Note that the source code to create this table can be generated */ +/* using the 'mktypes' utility */ + +typedef struct + { + RUNTIME_CTRL *rt_ctrl; /* For dyn types ONLY, otherwise = NULL */ + ST_INT num_rt; /* Runtime type table */ + SD_CONST RUNTIME_TYPE *rt; + ST_INT data_size; /* size of data element */ + ST_CHAR type_name [MAX_IDENT_LEN+1]; /* name passed to Foundry (1st after :T)*/ + struct mvl_vmd_ctrl *vmd_ctrl; /* ptr to VMD which uses this type*/ + } MVL_TYPE_CTRL; + +/* These variables can be provided via the source code generated by */ +/* the 'foundry' utility program */ +extern MVL_TYPE_CTRL *mvl_type_ctrl; +extern ST_INT mvl_num_types; + +/* This function takes the type ID and provides a pointer to the runtime*/ +/* type and it's size as output. It returns SD_SUCCESS for success. */ +/* The type information is currently stored internally as ASN.1 encoded */ +/* types. */ + +ST_RET mvl_get_runtime (ST_INT type_id, + RUNTIME_TYPE **rt_ptr_out, + ST_INT *num_rt_out); + +/* Same function but only succeeds if type was dynamically created. */ +ST_RET mvl_get_runtime_dyn (ST_INT type_id, + RUNTIME_TYPE **rt_ptr_out, + ST_INT *num_rt_out); + + + +/* If USR_SUPPLIED_RT is defined (and not USE_RT_DATA) then the user */ +/* will supply the runtime table data structures using local means. */ +ST_VOID u_mvl_start_init_rt_tbl (ST_INT numTypes, ST_INT totalNumRt); +ST_VOID u_mvl_end_init_rt_tbl (ST_VOID); +RUNTIME_TYPE *u_mvl_get_rt_tbl (ST_INT typeId, ST_INT numRt); + +/* global variables in Foundry Object Realization File */ +extern SD_CONST RUNTIME_TYPE * SD_CONST mvl_rt_tables[]; +extern ST_INT rt_table_index; + +/************************************************************************/ +/* This function can be used to modify the number of elements */ +/* in an array runtime type. */ + +ST_VOID mvl_mod_arr_size (RUNTIME_TYPE *rt, ST_RTINT num_elmnts); + +/* This function converts an ASN.1 type definition to a runtime type. */ +/* The runtime type is allocated by chk_calloc and the user must free */ +/* the runtime type when done with it (using chk_free). */ + +ST_RET mvl_mk_rt_from_asn1 (ST_UCHAR *asn1ptr, ST_INT asn1len, + RUNTIME_TYPE **rt_out, ST_INT *num_rt_out); + +/************************************************************************/ +/************************************************************************/ +/* MMS OBJECT CONTROL ELEMENTS */ +/* Functions and structures used to map MMS objects to local elements */ +/************************************************************************/ +/* VARIABLE ASSOCIATION */ +/************************************************************************/ + +/* This structure is used in the Variable Association for use by */ +/* MVL_UCA in handling array alternate access */ + +typedef struct mvl_arr_ctrl + { + ST_BOOLEAN arrAltAccPres; + ST_BOOLEAN nested; /* Furter nesting is done on this arr */ + ST_RTINT low_index; + ST_RTINT num_elmnts; + ST_RTINT curr_index; + ALT_ACCESS alt_acc; /* Nested AA on the array */ + } MVL_ARR_CTRL; + + +/* MVL_VAR_PROC */ +/* The functions selected by these pointers will be called during */ +/* read/write indication processing (NULL pointers are not called, of */ +/* course!). The 'pre' funs must return SD_SUCCESS or SD_FAILURE, which */ +/* will be reflected in the MMS response. */ + +/* Values for 'aa_mode_out' */ +#define MVL_USE_NO_AA 1 +#define MVL_USE_PACKED_AA 2 +#define MVL_USE_UNPACKED_AA 3 + +struct mvl_var_assoc; /* Forward declare this to eliminate warnings. */ + +typedef struct mvl_var_proc + { + ST_RET (*pre_read_aa)(struct mvl_var_assoc **va, + ST_BOOLEAN alt_acc_pres, + ALT_ACCESS *alt_acc, + MVL_NET_INFO *ni, + ST_INT *aa_mode_out); + ST_VOID (*post_read_aa)(struct mvl_var_assoc *va, + ST_BOOLEAN alt_acc_pres, + ALT_ACCESS *alt_acc, + MVL_NET_INFO *ni); + + ST_RET (*proc_write_aa)(struct mvl_var_assoc **va, + ALT_ACCESS *alt_acc, + MVL_NET_INFO *ni, + ST_INT *aa_mode_out); + + ST_RET (*pre_write_aa) (struct mvl_var_assoc *va, + ST_BOOLEAN alt_acc_pres, + ALT_ACCESS *alt_acc, + MVL_NET_INFO *ni, + ST_CHAR *write_data, + ST_INT write_data_size); + ST_VOID (*post_write_aa)(struct mvl_var_assoc *va, + ST_BOOLEAN alt_acc_pres, + ALT_ACCESS *alt_acc, + MVL_NET_INFO *ni); + + ST_RET (*pre_info) (struct mvl_var_assoc *va, MVL_NET_INFO *ni); + ST_VOID (*post_info) (struct mvl_var_assoc *va, MVL_NET_INFO *ni); + } MVL_VAR_PROC; + +#define MVL_VAR_FLAG_UCA 0x01 /* for "flags" of MVL_VAR_ASSOC */ + +/* MVL_VAR_ASSOC */ +typedef struct mvl_var_assoc + { + ST_CHAR *name; /* variable name */ + ST_VOID *data; /* pointer to local data */ + ST_VOID *last_data; /* to save last value of this variable */ + /* only allocated if va is in nvl */ + /* used by IEC/UCA rpt code. */ + /*renxiaobao ÈÕÖ¾ + ST_VOID *last_log_data;*/ + ST_INT type_id; /* type of variable */ + MVL_TYPE_CTRL *type_ctrl; /* type of variable details */ + /* set by mvl_var_create */ + ST_UCHAR flags; /* MVL_VAR_FLAG_UCA, etc. */ + MVL_VAR_PROC *proc; /* User defined pre/post processing */ + ST_VOID *user_info; /* MVL user can use this for 'whatever' */ + ST_VOID *usr_ind_ctrl; + + struct mvl_var_assoc *va_to_free; /* Used in NVL processing */ + + struct mvl_var_assoc *base_va; /* VA from which this was derived */ + ST_INT offset_from_base; /* Used only for static data buffer */ + ST_RTINT prim_num; /* Index to first prim in RUNTIME_TYPE */ + /* (used only when MVL_UCA defined) */ + ST_RTREF ref; + MVL_ARR_CTRL arrCtrl; + + ST_BOOLEAN use_static_data; /* "data" in this struct points to */ + /* permanent data. */ + ST_UCHAR rpt_reason; /* 61850 RPT reason bitstring */ + ST_RET result; /* Used only if MVL_INFO_RPT_CLIENT */ + } MVL_VAR_ASSOC; + + +ST_RET mvl_get_va_asn1_data (MVL_NET_INFO *net_info, + MVL_VAR_ASSOC *va, + ST_BOOLEAN alt_acc_pres, + ALT_ACCESS *alt_acc, + ST_UCHAR *asn1_dest_buffer, + ST_INT asn1_buffer_len, + ST_INT *asn1_len_out); + + +/************************************************************************/ +/* DESCRIBED VARIABLE SUPPORT: Warning, not currently supported */ + +#if defined (MVL_DESCR_SUPP) +typedef struct mvl_descr_addr_assoc + { + ST_CHAR *base_name; /* base part of address */ + ST_VOID *data; /* pointer to local data base */ + ST_INT data_size; /* size of data element */ + ST_INT max_elmnts; + ST_VOID *user_info; /* MVL user can use this for 'whatever' */ + } MVL_DESCR_ADDR_ASSOC; + +ST_RET mvl_get_descr_local_addr (VAR_ACC_ADDR *addr, + RUNTIME_TYPE *rt, + ST_INT mum_rt, + ST_CHAR **data_out, + ST_INT *data_size_out); + +ST_RET mvl_get_descr_asn1_data (VARIABLE_LIST *vl, + ST_UCHAR *asn1_dest_buffer, + ST_INT asn1_buffer_len, + ST_INT *asn1_len_out); +#endif + +/************************************************************************/ +/* NAMED VARIABLE LISTS */ + +typedef struct mvl_scope + { + ST_INT16 scope; + struct mvl_dom_ctrl *dom; + } MVL_SCOPE; + +/* For backward compatibility only */ +#define MVL_VA_SCOPE MVL_SCOPE + +typedef struct mvl_nvlist_ctrl + { + ST_CHAR *name; /* name of the named variable list */ + ST_INT num_of_entries; /* number of variables in the list */ + MVL_VAR_ASSOC **entries; + MVL_SCOPE nvl_scope; /* scope of this NVL */ + MVL_SCOPE *va_scope; + ALT_ACCESS **altAcc; /* Alternate Access array for var's */ + ST_BOOLEAN mms_deletable; + ST_VOID *user_info; /* MVL user can use this for 'whatever' */ + ST_BOOLEAN already_scanned; /* flag to indicate this NVL already */ + /* scanned for rpt changes. Avoids */ + /* scanning same data multiple times. */ + } MVL_NVLIST_CTRL; + + +/************************************************************************/ +/* JOURNALS */ + +typedef struct mvlJouVar + { + ST_CHAR *varTag; /* variable tag */ + MVL_VAR_ASSOC *va; + } MVL_JOU_VAR; + +/* entry_form_tag value defines are in mms_pjou.h */ +/* #define JE_FORM_DATA 2 */ +/* #define JE_FORM_ANNOTATION 3 */ + +/* cur_state value defines are in mms_pevn.h */ +/* #define EC_STATE_DISABLED 0 */ +/* #define EC_STATE_IDLE 1 */ +/* #define EC_STATE_ACTIVE 2 */ + +typedef struct mvlJournalEntry + { + DBL_LNK l; /* for user, not used by MVL */ + + ST_INT entry_id_len; /* Octet string ID, size 1-8 */ + ST_UCHAR entry_id[8]; + + APP_REF orig_app; + MMS_BTOD occur_time; /* occurrence time */ + + ST_INT16 entry_form_tag; /* entry form tag */ + union + { + struct /* entry form is DATA */ + { + ST_BOOLEAN event_pres; /* event present */ + OBJECT_NAME evcon_name; /* event condition name */ + ST_INT16 cur_state; /* current state */ + ST_BOOLEAN list_of_var_pres; /* list of variables present */ + ST_INT num_of_var; /* number of variables */ + VAR_INFO *list_of_var; /* ptr to array */ + } data; + ST_CHAR *annotation; /* pointer to annotation */ + }ef; + } MVL_JOURNAL_ENTRY; + +/* MVL Journal control structure. Used by MVL for GNL response */ +typedef struct mvlJournal + { + ST_CHAR *name; /* journal name */ + ST_BOOLEAN mms_deletable; + ST_INT numEntries; + MVL_JOURNAL_ENTRY *entries; + } MVL_JOURNAL_CTRL; + +/************************************************************************/ +/* MMS OBJECT CONTROL */ +/************************************************************************/ + +/* Application Association Scope Objects */ +typedef struct mvl_aa_obj_ctrl + { + ST_INT max_num_var_assoc; + ST_INT num_var_assoc; + MVL_VAR_ASSOC **var_assoc_tbl; + + ST_INT max_num_nvlist; + ST_INT num_nvlist; + MVL_NVLIST_CTRL **nvlist_tbl; + + ST_INT max_num_jou; + ST_INT num_jou; + MVL_JOURNAL_CTRL **jou_tbl; + + ST_BOOLEAN foundry_objects; /* Flag for internal use */ + ST_VOID *user_info; /* MVL user can use this for 'whatever' */ + } MVL_AA_OBJ_CTRL; + + +/* Domain Scope Objects */ +typedef struct mvl_dom_ctrl + { + ST_CHAR *name; + + ST_INT max_num_var_assoc; + ST_INT num_var_assoc; + MVL_VAR_ASSOC **var_assoc_tbl; + + ST_INT max_num_nvlist; + ST_INT num_nvlist; + MVL_NVLIST_CTRL **nvlist_tbl; + + ST_INT max_num_jou; + ST_INT num_jou; + MVL_JOURNAL_CTRL **jou_tbl; + + GETDOM_RESP_INFO *get_dom_resp_info; /* Optional */ + + ST_BOOLEAN foundry_objects; /* Flag for internal use */ + ST_VOID *user_info; /* MVL user can use this for 'whatever' */ + } MVL_DOM_CTRL; + + +/* VMD Scope Objects */ +typedef struct mvl_vmd_ctrl + { + ST_INT max_num_var_assoc; + ST_INT num_var_assoc; + MVL_VAR_ASSOC **var_assoc_tbl; + +#if defined (MVL_DESCR_SUPP) + ST_INT num_descr_addr; + MVL_DESCR_ADDR_ASSOC *descr_addr_assoc_tbl; +#endif + + ST_INT max_num_nvlist; + ST_INT num_nvlist; + MVL_NVLIST_CTRL **nvlist_tbl; + + ST_INT max_num_dom; + ST_INT num_dom; + MVL_DOM_CTRL **dom_tbl; + + ST_INT max_num_jou; + ST_INT num_jou; + MVL_JOURNAL_CTRL **jou_tbl; + + ST_BOOLEAN foundry_objects; /* Flag for internal use */ + + ST_VOID *user_info; /* MVL user can use this for 'whatever' */ + } MVL_VMD_CTRL; +extern MVL_VMD_CTRL mvl_vmd; + + +/************************************************************************/ +/************************************************************************/ +/* MMS OBJECT CONTROL MANIPULUATION */ +/************************************************************************/ +/************************************************************************/ +/* Naming Conventions */ +/* */ +/* Find: Locate the object, given the object name */ +/* */ +/* Init: Delete all sub objects and resize tables */ +/* Clear: Delete all sub objects */ +/* Resize: Adjust table sizes */ +/* */ +/* Add: Create and Insert */ +/* Create: Allocate & initialize the object */ +/* Insert: Insert into tables */ +/* */ +/* Remove: Delete and Destroy */ +/* Delete: Delete from tables */ +/* Destroy: Free object and sub objects as approptiate */ +/* */ +/* Pairs - Add/Remove, Insert/Delete, Create/Destroy */ +/* */ +/* Usages: */ +/* All dynamic, startup and reconfigure, online object changes */ +/* * Use Foundry for types only */ +/* * Use 'mvl_init_vmd' for startup/reconfigure */ +/* * Use Add/Insert to construct object set */ +/* * Use Remove/Delete to remove unwanted objects */ +/* * Use Resize to modify storage as appropriate */ +/* */ +/* Both Foundry & Dynamic, startup & reconfigure, online changes */ +/* * Use Foundry for types and other objects */ +/* * Use Resize to modify storage for dynamic objects */ +/* * Use Add/Insert to add to object set */ +/* * Use Remove/Delete to remove unwanted objects */ +/* */ +/* Renaming an object */ +/* * Delete, change the name, and insert. Be careful of the name */ +/* buffer handling. */ +/* */ +/************************************************************************/ + +/**** OBJECT BULK UPDATE */ + +/* These defines can be used to speed loading of multiple objects. */ +/* After the 'start' call, MVL stops sorting objects as they are */ +/* inserted. When the 'end' call is made, all objects are sorted. */ + +/* NOTE: The 'end' call must be made before NVL's are added, so that */ +/* the variable associations can be resolved. This rule can be ignored */ +/* if domains and variable associations are added in sorted order. */ + +extern ST_BOOLEAN mvl_obj_nosort; +ST_VOID mvl_sort_objs (ST_VOID); +#define MVL_START_BULK_OBJ_UPDATE() {mvl_obj_nosort = SD_TRUE;} +#define MVL_END_BULK_OBJ_UPDATE() {if (mvl_obj_nosort == SD_TRUE){\ + mvl_obj_nosort = SD_FALSE;\ + mvl_sort_objs ();\ + }}\ + +/**** SCOPE LEVEL - VMD, DOMAIN */ + +/* Deletes all objects in the scope, allocates new object ctrl tables */ +/* NOTE: Works only on scopes with NO foundry objects. */ +ST_RET mvl_init_vmd (ST_INT max_dom, ST_INT max_var, + ST_INT max_nvl, ST_INT max_jou); +ST_RET mvl_init_dom (MVL_DOM_CTRL *dom, ST_INT max_var, + ST_INT max_nvl, ST_INT max_jou); +ST_RET mvl_init_aa (ST_INT max_var, ST_INT max_nvl, ST_INT max_jou); + +/* Deletes all objects in the scope */ +/* NOTE: Works only on scopes with NO foundry objects. */ +ST_RET mvl_clear_vmd_objs (ST_VOID); +ST_RET mvl_clear_dom_objs (MVL_DOM_CTRL *dom); +ST_RET mvl_clear_aa_objs (ST_VOID); +ST_VOID _mvl_clear_aa_objs (MVL_AA_OBJ_CTRL *aa_objs); + +/* Resize scope capacities, w/o affecting objects */ +ST_VOID mvl_vmd_resize (ST_INT max_dom, ST_INT max_var, + ST_INT max_nvl, ST_INT max_jou); +ST_VOID mvl_dom_resize (MVL_DOM_CTRL *dom, ST_INT max_var, + ST_INT max_nvl, ST_INT max_jou); +ST_VOID mvl_aa_resize (ST_INT max_var, ST_INT max_nvl, ST_INT max_jou); +ST_VOID mvl_aa_resize_conn (MVL_AA_OBJ_CTRL *aa_objs, ST_INT max_num_var, ST_INT max_num_nvl, + ST_INT max_num_jou); + +/**** DOMAINS */ + +MVL_DOM_CTRL *mvl_dom_create (ST_CHAR *name, ST_INT max_var, + ST_INT max_nvl, ST_INT max_jou, ST_BOOLEAN copy_name); +ST_VOID mvl_dom_destroy (MVL_DOM_CTRL *dom); + +/* User can be notified when domain is being destroyed */ +extern ST_VOID (*u_mvl_dom_destroy) (MVL_DOM_CTRL *dom); + + +/**** VARIABLE ASSOCIATIONS */ + +MVL_VAR_ASSOC *mvl_var_create (OBJECT_NAME *obj, ST_INT type_id, /* NEW */ + ST_VOID *data, MVL_VAR_PROC *proc, + ST_BOOLEAN copy_name); +MVL_VAR_ASSOC *mvl_var_create_alloc (ST_CHAR *name, + ST_INT type_id, + MVL_VAR_PROC *proc); +MVL_VAR_ASSOC *mvl_var_create_derived (ST_CHAR *name, + ST_INT type_id, + MVL_VAR_ASSOC *baseVa, /* base variable from which to derive */ + ST_INT offset_from_base, + ST_RTINT prim_num); +ST_VOID mvl_var_destroy (MVL_VAR_ASSOC *va); + +/* User can be notified when VA is being destroyed */ +extern ST_VOID (*u_mvl_var_destroy)(MVL_VAR_ASSOC *va); + +/**** NAMED VARIABLE LISTS */ + +MVL_NVLIST_CTRL *mvl_nvl_create (MVL_VMD_CTRL *vmd_ctrl, + ST_CHAR *nvlName, + ST_INT numNames, + OBJECT_NAME *var_obj, /* array of var obj names*/ + MVL_NET_INFO *net_info, /* where to find var_obj*/ + /* if it is AA_SPEC */ + ST_BOOLEAN copy_name); +ST_VOID mvl_nvl_destroy (MVL_NVLIST_CTRL *nvl); + +/* User can be notified when NVL is being destroyed */ +extern ST_VOID (*u_mvl_nvl_destroy) (MVL_NVLIST_CTRL *nvl); + + +/**** JOURNALS */ + +MVL_JOURNAL_CTRL *mvl_jou_create (OBJECT_NAME *obj, MVL_NET_INFO *net_info, + ST_BOOLEAN copy_name); +ST_VOID mvl_jou_destroy (MVL_JOURNAL_CTRL *jou); + +/* User can be notified when journal is being destroyed */ +extern ST_VOID (*u_mvl_jou_destroy) (MVL_JOURNAL_CTRL *jou); + +MVL_VMD_CTRL *mvl_vmd_create (ST_INT max_num_dom, ST_INT max_num_var, ST_INT max_num_nvl, ST_INT max_num_journal); +/* NOTE: old mvl_vmd_destroy function destroyed the global VMD and all */ +/* report controls. If that's what you want, you must now do like this: */ +/* mvlu_rpt_ctrl_destroy_all (); */ +/* mvl61850_rpt_ctrl_destroy_all (); */ +/* mvl_vmd_destroy (&mvl_vmd); */ +ST_RET mvl_vmd_destroy (MVL_VMD_CTRL *vmd_ctrl); +ST_VOID mvlu_rpt_ctrl_destroy_all (ST_VOID); +ST_VOID mvl61850_rpt_ctrl_destroy_all (ST_VOID); + +/************************************************************************/ +/************************************************************************/ +/* MANUFACTURED VARIABLE SUPPORT */ +/* Handlers for manufactured server variable names && lists */ +/************************************************************************/ + +/* This function will be called when an */ +/* undefined object is being accessed using alternate access. */ +/* If '*alt_access_done_out' is set SD_TRUE, MVL will assume that the */ +/* alternate access operation has been addressed by the called function */ + +MVL_VAR_ASSOC *u_mvl_get_va_aa (struct mvl_vmd_ctrl *vmd_ctrl, + ST_INT service, + OBJECT_NAME *obj, + MVL_NET_INFO *netInfo, + ST_BOOLEAN alt_access_pres, + ALT_ACCESS *alt_acc, + ST_BOOLEAN *alt_access_done_out); +ST_VOID u_mvl_free_va (ST_INT service, + MVL_VAR_ASSOC *va, + MVL_NET_INFO *netInfo); + +MVL_NVLIST_CTRL *u_mvl_get_nvl (ST_INT service, + OBJECT_NAME *obj, + MVL_NET_INFO *netInfo); +ST_VOID u_mvl_free_nvl (ST_INT service, + MVL_NVLIST_CTRL *nvl, + MVL_NET_INFO *netInfo); + +/************************************************************************/ +/************************************************************************/ +/* GET NAME LIST INDICATION HANDLERS */ +/* Default versions of these functs are found in s_getnam.c. They may */ +/* be replaced with customized functs (e.g. for UCA, see mvl_uca.c). */ + +ST_INT u_gnl_ind_vars(MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames); + +ST_INT u_gnl_ind_nvls(MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames); + +ST_INT u_gnl_ind_doms(NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames); + +ST_INT u_gnl_ind_jous(MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames); + +ST_VOID u_gnl_done(ST_INT16 mms_class, + NAMELIST_RESP_INFO *resp_info); + + +/************************************************************************/ +/************************************************************************/ +/* MVL SERVER SERVICE SUPPORT */ +/************************************************************************/ +/************************************************************************/ +/* Type for IEC 61850 "LastApplError" var (sent in report when control fails).*/ +/* NOTE: must be before MVLAS_WR_VA_CTRL. */ +/************************************************************************/ +typedef struct + { + ST_CHAR CntrlObj [MVL61850_MAX_OBJREF_LEN+1]; + ST_INT8 Error; + struct + { + ST_INT8 orCat; + struct + { + ST_INT16 len; + ST_UINT8 data[64]; + } orIdent; /* OVstring64 */ + } Origin; + ST_UINT8 ctlNum; + ST_INT8 AddCause; + } MVL61850_LAST_APPL_ERROR; + +/************************************************************************/ +/* INDICATION CONTROL */ +/************************************************************************/ +/* The data structure 'MVL_IND_PEND' is used to keep track of MMS */ +/* indications pending. */ + +/* Identify */ +typedef struct + { + IDENT_RESP_INFO *resp_info; + } MVLAS_IDENT_CTRL; + +/* Status */ +typedef struct + { + STATUS_REQ_INFO *req_info; + STATUS_RESP_INFO *resp_info; + } MVLAS_STATUS_CTRL; + +/* GetNameList */ +typedef struct + { + NAMELIST_REQ_INFO *req_info; + NAMELIST_RESP_INFO *resp_info; + } MVLAS_NAMELIST_CTRL; + +/* Read */ +/* This structure represents one Variable Association being read. The */ +/* user can set the 'acc_rslt_tag' to 'ACC_RSLT_FAILURE' if the read */ +/* does not succeed. */ + +typedef struct mvlas_rd_va_ctrl + { + MVL_VAR_ASSOC *va; + MVL_SCOPE va_scope; + + ST_INT16 acc_rslt_tag; /* ACC_RSLT_SUCCESS or ACC_RSLT_FAILURE */ + ST_INT16 failure; /* DataAccessError code for failure */ + ST_BOOLEAN alt_access_pres; + ALT_ACCESS alt_acc; + + ST_INT numPrimData; /* Total primitive elements for var */ + ST_INT numPrimDataDone; /* Number complete */ + + ST_VOID *usr; /* For user to use as she sees fit */ + } MVLAS_RD_VA_CTRL; + +typedef struct mvlas_read_ctrl + { + ST_INT16 var_acc_tag; /* VAR_ACC_NAMEDLIST or VAR_ACC_VARLIST */ + + ST_INT numVar; /* Variables being read */ + MVLAS_RD_VA_CTRL *vaCtrlTbl; + + MVL_NVLIST_CTRL *nvList; + } MVLAS_READ_CTRL; + + +/* Write */ +/* This structure represents one Variable Assoc being written. The */ +/* user can set the 'acc_rslt_tag' to 'ACC_RSLT_FAILURE' if the read */ +/* does not succeed. */ +struct mvl_sbo_ctrl; /* Forward declaration (defined in mvl_uca.h) */ +typedef struct mvlas_wr_va_ctrl + { + MVL_VAR_ASSOC *va; + MVL_SCOPE va_scope; + ST_INT16 resp_tag; /* WR_RSLT_FAILURE or WR_RSLT_SUCCESS */ + ST_INT16 failure; /* DataAccessError code for failure */ + ST_BOOLEAN alt_access_pres; + ALT_ACCESS alt_acc; /* Alternate Access specification */ + + ST_INT numPrimData; /* Total primitive elements for var */ + ST_INT numPrimDataDone; /* Number complete */ + struct mvl_sbo_ctrl *sboCtrl; /* SBO Control Info. */ + /* NOTE: "sboCtrl" used when writing IEC 61850 "Oper" or "Cancel". */ + /* Not used (i.e. NULL) for all other writes. */ + + ST_UCHAR *oldData; + + /* Used only when writing Oper, Cancel, SBOw (for IEC 61850). */ + MVL61850_LAST_APPL_ERROR LastApplError; + + ST_VOID *usr; /* For user to use as she sees fit */ + } MVLAS_WR_VA_CTRL; + +typedef struct mvlas_write_ctrl + { + ST_INT numVar; /* Variables being written */ + MVLAS_WR_VA_CTRL *vaCtrlTbl; + ST_BOOLEAN ind_funct_done; /* indication function completed? */ + } MVLAS_WRITE_CTRL; + + +/* GetVariableAccessAttributes */ +typedef struct + { + GETVAR_REQ_INFO *req_info; + GETVAR_RESP_INFO *resp_info; + } MVLAS_GETVAR_CTRL; + +/* DefineNamedVariableList */ +typedef struct + { + DEFVLIST_REQ_INFO *req_info; + } MVLAS_DEFVLIST_CTRL; + +/* GetNamedVariableListAttributes */ +typedef struct + { + GETVLIST_REQ_INFO *req_info; + GETVLIST_RESP_INFO *resp_info; /* allocate appropriate size */ + } MVLAS_GETVLIST_CTRL; + +/* DeleteNamedVariableList */ +typedef struct + { + DELVLIST_REQ_INFO *req_info; + DELVLIST_RESP_INFO *resp_info; + } MVLAS_DELVLIST_CTRL; + +/* GetDomainAttributes */ +typedef struct + { + GETDOM_REQ_INFO *req_info; + GETDOM_RESP_INFO *resp_info; + } MVLAS_GETDOM_CTRL; + +/* File Open */ +typedef struct + { + ST_CHAR filename [MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + ST_UINT32 init_pos; + FOPEN_RESP_INFO *resp_info; + } MVLAS_FOPEN_CTRL; + +/* File Read */ +typedef struct + { + FREAD_REQ_INFO *req_info; + ST_INT max_size; + FREAD_RESP_INFO *resp_info; + } MVLAS_FREAD_CTRL; + +/* File Close */ +typedef struct + { + FCLOSE_REQ_INFO *req_info; + } MVLAS_FCLOSE_CTRL; + +/* File Directory */ +typedef struct + { + ST_UINT32 fsize; /* file size (# bytes) */ + ST_BOOLEAN mtimpres; /* last modified time present */ + time_t mtime; /* last modified time */ + ST_CHAR filename [MAX_FILE_NAME+1]; + } MVL_DIR_ENT; + +typedef struct + { + ST_INT num_dir_ent; /* number of directory entries */ + ST_BOOLEAN more_follows; /* more dir entries follow */ + /* default: SD_FALSE */ + MVL_DIR_ENT *dir_ent; /* ptr to array of dir entries */ + } MVL_FDIR_RESP_INFO; + +typedef struct + { + ST_CHAR fs_filename[MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + ST_CHAR ca_filename[MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + MVL_FDIR_RESP_INFO *resp_info; + } MVLAS_FDIR_CTRL; + +/* ObtainFile */ +typedef struct + { + ST_CHAR srcfilename [MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + ST_CHAR destfilename [MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + } MVLAS_OBTFILE_CTRL; + +/* File Delete */ +typedef struct + { + ST_CHAR filename [MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + } MVLAS_FDELETE_CTRL; + +/* File Rename */ +typedef struct + { + ST_CHAR curfilename [MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + ST_CHAR newfilename [MAX_FILE_NAME+1]; /* array (not ptr) so always valid*/ + } MVLAS_FRENAME_CTRL; + +/* InitializeJournal */ +typedef struct + { + JINIT_REQ_INFO *req_info; + JINIT_RESP_INFO *resp_info; + } MVLAS_JINIT_CTRL; + +/* ReadJournal */ +typedef struct + { + JREAD_REQ_INFO *req_info; + JREAD_RESP_INFO *resp_info; /* Variable size. User or mvlas_* must alloc.*/ + } MVLAS_JREAD_CTRL; + +/* JournalStatus */ +typedef struct + { + JSTAT_REQ_INFO *req_info; + JSTAT_RESP_INFO *resp_info; + } MVLAS_JSTAT_CTRL; + +typedef struct + { + INITUPL_REQ_INFO *req_info; + INITUPL_RESP_INFO *resp_info; + } MVLAS_INITUPL_CTRL; + +typedef struct + { + UPLOAD_REQ_INFO *req_info; + UPLOAD_RESP_INFO *resp_info; + } MVLAS_UPLOAD_CTRL; + +typedef struct + { + TERMUPL_REQ_INFO *req_info; + } MVLAS_TERMUPL_CTRL; + +typedef struct + { + INITDOWN_REQ_INFO *req_info; + } MVLAS_INITDOWN_CTRL; + +typedef struct + { + DELDOM_REQ_INFO *req_info; + } MVLAS_DELDOM_CTRL; + +typedef struct + { + CREPI_REQ_INFO *req_info; + } MVLAS_CREPI_CTRL; + +typedef struct + { + DELPI_REQ_INFO *req_info; + } MVLAS_DELPI_CTRL; + +typedef struct + { + GETPI_REQ_INFO *req_info; + GETPI_RESP_INFO *resp_info; + } MVLAS_GETPI_CTRL; + +typedef struct + { + START_REQ_INFO *req_info; + } MVLAS_START_CTRL; + +typedef struct + { + STOP_REQ_INFO *req_info; + } MVLAS_STOP_CTRL; + +typedef struct + { + RESUME_REQ_INFO *req_info; + } MVLAS_RESUME_CTRL; + +typedef struct + { + RESET_REQ_INFO *req_info; + } MVLAS_RESET_CTRL; + +typedef struct + { + GETCL_REQ_INFO *req_info; + GETCL_RESP_INFO *resp_info; + } MVLAS_GETCL_CTRL; + +/* MVL Indication Control */ +typedef struct mvl_ind_pend + { + DBL_LNK l; + MVL_COMM_EVENT *event; + ST_INT op; /* MMS Opcode (MMSOP_READ, etc.) */ + union + { + MVLAS_READ_CTRL rd; + MVLAS_WRITE_CTRL wr; + MVLAS_IDENT_CTRL ident; + MVLAS_STATUS_CTRL status; + MVLAS_NAMELIST_CTRL namelist; + MVLAS_GETVAR_CTRL getvar; + MVLAS_GETDOM_CTRL getdom; + MVLAS_FOPEN_CTRL fopen; + MVLAS_FREAD_CTRL fread; + MVLAS_FCLOSE_CTRL fclose; + MVLAS_FDIR_CTRL fdir; + MVLAS_OBTFILE_CTRL obtfile; + MVLAS_FDELETE_CTRL fdelete; + MVLAS_FRENAME_CTRL frename; + MVLAS_DEFVLIST_CTRL defvlist; + MVLAS_GETVLIST_CTRL getvlist; + MVLAS_DELVLIST_CTRL delvlist; + MVLAS_JINIT_CTRL jinit; + MVLAS_JREAD_CTRL jread; + MVLAS_JSTAT_CTRL jstat; + MVLAS_INITUPL_CTRL initupl; + MVLAS_UPLOAD_CTRL upload; + MVLAS_TERMUPL_CTRL termupl; + MVLAS_INITDOWN_CTRL initdown; + MVLAS_DELDOM_CTRL deldom; + MVLAS_CREPI_CTRL crepi; + MVLAS_DELPI_CTRL delpi; + MVLAS_GETPI_CTRL getpi; + MVLAS_START_CTRL start; + MVLAS_STOP_CTRL stop; + MVLAS_RESUME_CTRL resume; + MVLAS_RESET_CTRL reset; + MVLAS_GETCL_CTRL getcl; + } u; + /* For IEC/UCA Report scanning: */ + /* This function is called when scan completes for "one" variable */ + /* (i.e. all primitive reads complete for "one" variable of rpt). */ + ST_VOID (*scan_va_done_fun)(struct mvl_ind_pend *ind, MVL_VAR_ASSOC *va); + + /* User function to call INSTEAD of default Response function. */ + /* Currently only allowed for Read service (i.e. replaces call to */ + /* mvlas_read_resp). */ + ST_RET (*usr_resp_fun) (struct mvl_ind_pend *ind_pend); + + ST_VOID *usr_ind_ctrl; + ST_VOID *usr; /* For user to use as she sees fit */ + } MVL_IND_PEND; + +/************************************************************************/ +/* USER INDICATION and MVL RESPONSE FUNCTIONS */ +/* MVL calls the 'u_mvl_xxx_ind' function from within 'mvl_comm_serve' */ +/* to notify the user of the indication. The user must call a response */ +/* function ('mvlas_xxx_resp or 'mplas_xxx_resp') either from within */ +/* the user indication function or some time later. */ + +/* Identify */ +ST_VOID u_mvl_ident_ind (MVL_IND_PEND *ind); +ST_VOID mplas_ident_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* Status */ +ST_VOID u_mvl_status_ind (MVL_IND_PEND *ind); +ST_VOID mplas_status_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* Unsolicited Status */ +ST_VOID u_mvl_ustatus_ind (MVL_COMM_EVENT *event); /* NOTE: different arg*/ + +/* GetNameList */ +ST_VOID u_mvl_namelist_ind (MVL_IND_PEND *ind); +ST_VOID mplas_namelist_resp (MVL_IND_PEND *ind);/* Primitive */ +ST_VOID mvlas_namelist_resp (MVL_IND_PEND *ind);/* Virtual Machine */ + +/* Read */ +ST_VOID u_mvl_read_ind (MVL_IND_PEND *indCtrl); +ST_RET mvlas_read_resp (MVL_IND_PEND *indCtrl); + +/* Write */ +ST_VOID u_mvl_write_ind (MVL_IND_PEND *indCtrl); +ST_VOID mvlas_write_resp (MVL_IND_PEND *indCtrl); + +/* GetVariableAccessAttributes */ +ST_VOID u_mvl_getvar_ind (MVL_IND_PEND *ind); +ST_VOID mplas_getvar_resp (MVL_IND_PEND *ind); /* Primitive */ +ST_VOID mvlas_getvar_resp (MVL_IND_PEND *ind); /* Virtual Machine */ + +/* DefineNamedVariableList */ +ST_VOID u_mvl_defvlist_ind (MVL_IND_PEND *ind); +ST_VOID mplas_defvlist_resp (MVL_IND_PEND *ind);/* Primitive */ +ST_VOID mvlas_defvlist_resp (MVL_IND_PEND *ind);/* Virtual Machine */ + +/* GetNamedVariableListAttributes */ +ST_VOID u_mvl_getvlist_ind (MVL_IND_PEND *ind); +ST_VOID mplas_getvlist_resp (MVL_IND_PEND *ind);/* Primitive */ +ST_VOID mvlas_getvlist_resp (MVL_IND_PEND *ind);/* Virtual Machine */ + +/* DeleteNamedVariableList */ +ST_VOID u_mvl_delvlist_ind (MVL_IND_PEND *ind); +ST_VOID mplas_delvlist_resp (MVL_IND_PEND *ind);/* Primitive */ +ST_VOID mvlas_delvlist_resp (MVL_IND_PEND *ind);/* Virtual Machine */ + +/* GetDomainAttributes */ +ST_VOID u_mvl_getdom_ind (MVL_IND_PEND *ind); +ST_VOID mplas_getdom_resp (MVL_IND_PEND *ind); /* Primitive */ +ST_VOID mvlas_getdom_resp (MVL_IND_PEND *ind); /* Virtual Machine */ + +/* FileOpen */ +ST_VOID u_mvl_fopen_ind (MVL_IND_PEND *ind); +ST_VOID mplas_fopen_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* FileRead */ +ST_VOID u_mvl_fread_ind (MVL_IND_PEND *ind); +ST_VOID mplas_fread_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* FileClose */ +ST_VOID u_mvl_fclose_ind (MVL_IND_PEND *ind); +ST_VOID mplas_fclose_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* FileDirectory */ +ST_VOID u_mvl_fdir_ind (MVL_IND_PEND *ind); +ST_VOID mvlas_fdir_resp (MVL_IND_PEND *ind); +ST_VOID mplas_fdir_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* ObtainFile */ +ST_VOID u_mvl_obtfile_ind (MVL_IND_PEND *ind); +ST_VOID mplas_obtfile_resp (MVL_IND_PEND *ind); /* Primitive */ +ST_VOID mvlas_obtfile_resp (MVL_IND_PEND *ind); /* VirtualMachine */ +ST_VOID mvlas_obtfile_resp_ex (MVL_IND_PEND *indCtrl, ST_UINT32 fileSizeLimit); + +/* FileDelete */ +ST_VOID u_mvl_fdelete_ind (MVL_IND_PEND *ind); +ST_VOID mplas_fdelete_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* FileRename */ +ST_VOID u_mvl_frename_ind (MVL_IND_PEND *ind); +ST_VOID mplas_frename_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* InitializeJournal */ +ST_VOID u_mvl_jinit_ind (MVL_IND_PEND *ind); +ST_VOID mplas_jinit_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* ReadJournal */ +ST_VOID u_mvl_jread_ind (MVL_IND_PEND *ind); +ST_VOID mplas_jread_resp (MVL_IND_PEND *ind); /* Primitive */ +ST_VOID mvlas_jread_resp (MVL_IND_PEND *ind); /* Virtual Machine */ + +/* ReportJournalStatus */ +ST_VOID u_mvl_jstat_ind (MVL_IND_PEND *ind); +ST_VOID mplas_jstat_resp (MVL_IND_PEND *ind); /* Primitive */ + +/* Conclude */ +ST_VOID u_mvl_concl_ind (MVL_COMM_EVENT *event); +ST_VOID mplas_concl_resp (MVL_COMM_EVENT *event); /* Primitive */ +ST_RET mplas_concl_err (MVL_COMM_EVENT *event, ST_INT16 err_class, ST_INT16 err_code); + +ST_VOID u_mvl_initupl_ind (MVL_IND_PEND *ind); +ST_VOID mplas_initupl_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_upload_ind (MVL_IND_PEND *ind); +ST_VOID mplas_upload_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_termupl_ind (MVL_IND_PEND *ind); +ST_VOID mplas_termupl_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_initdown_ind (MVL_IND_PEND *ind); +ST_VOID mplas_initdown_resp (MVL_IND_PEND *ind);/* Primitive */ + +ST_VOID u_mvl_deldom_ind (MVL_IND_PEND *ind); +ST_VOID mplas_deldom_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_crepi_ind (MVL_IND_PEND *ind); +ST_VOID mplas_crepi_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_delpi_ind (MVL_IND_PEND *ind); +ST_VOID mplas_delpi_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_getpi_ind (MVL_IND_PEND *ind); +ST_VOID mplas_getpi_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_start_ind (MVL_IND_PEND *ind); +ST_VOID mplas_start_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_stop_ind (MVL_IND_PEND *ind); +ST_VOID mplas_stop_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_reset_ind (MVL_IND_PEND *ind); +ST_VOID mplas_reset_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_resume_ind (MVL_IND_PEND *ind); +ST_VOID mplas_resume_resp (MVL_IND_PEND *ind); /* Primitive */ + +ST_VOID u_mvl_getcl_ind (MVL_IND_PEND *ind); +ST_VOID mplas_getcl_resp (MVL_IND_PEND *ind); /* Primitive */ + +/************************************************************************/ +/* Server Read/Write Start and End Function Pointers */ + +/* These function pointers are invoked to allow the user application */ +/* to prepare for handling the indication. */ +extern ST_RET (*u_mvl_rd_ind_start) (MVL_IND_PEND *indCtrl); +extern ST_RET (*u_mvl_wr_ind_start) (MVL_IND_PEND *indCtrl); + +/* These function pointers are invoked to allow the user application */ +/* to free resources used in VA data buffer management. */ +extern ST_VOID (*u_mvl_rd_resp_sent) (MVL_IND_PEND *indCtrl); +extern ST_VOID (*u_mvl_wr_resp_sent) (MVL_IND_PEND *indCtrl); + + +/************************************************************************/ +/* Server Information Report */ +/* This function is used to send an information report. */ + +ST_RET mvl_info_variables (MVL_NET_INFO *net_info, MVL_NVLIST_CTRL *nvl, + ST_BOOLEAN listOfVariables); + +/************************************************************************/ +/* Server Journal Read */ + +/* Jread User Interaction */ +/* 1. A Journal Read indication is received by MVL. */ +/* 2. MVL calls 'u_mvl_start_jread'. User applies filter to it's journal */ +/* data and returns the number of entries and variables that meet */ +/* the filter as well as JREAD buffer control information and a */ +/* user handle. */ +/* Note that the defines: */ +/* MAX_JREAD_RESP_ENTRIES */ +/* MAX_JREAD_RESP_VARS */ +/* are used to limit the amount of information that MVL will return */ +/* in the MMS response. */ +/* The buffer control allows the user to supply MVL with data buffers */ +/* to be used to save the volitile Journal information (Entry ID, */ +/* Variable Tag, Annotation). */ +/* 3. MVL calls 'u_mvl_get_next_jread_entry' and 'u_mvl_free_jread_entry' */ +/* repetitively until the max MMS PDU size is reached or the number of */ +/* user entries is reached. */ +/* 4. MVL sends the JREAD response. */ +/* 5. MVL calls 'u_mvl_end_jread' and the user may then free resources */ +/* as necessary. */ + +/* These defines control the way that MVL handles the potentially */ +/* volitile information presented by the user via MVL_JOURNAL_ENTRY. */ +/* If these defines are defined, MVL will assume that the pointers */ +/* in MVL_JOURNAL_ENTRY will become invalid after the free call and */ +/* so it must copy the data into a buffer. These buffers are to be */ +/* supplied by the user, and must be large enough for the data. */ + +/* #define MVL_JREAD_ENTRYID_DYNAMIC */ +/* #define MVL_JREAD_VARTAG_DYNAMIC */ +/* #define MVL_JREAD_ANNOTATION_DYNAMIC */ + +typedef struct mvlJreadBufCtrl + { + ST_INT numUsrEntries; /* User must supply */ + ST_INT numVarInfo; /* User must supply */ + +#if defined (MVL_JREAD_ENTRYID_DYNAMIC) + ST_UCHAR *entryIdBuf; /* User must supply */ + ST_UCHAR *nextEntryId; /* MVL use only */ +#endif + +#if defined (MVL_JREAD_VARTAG_DYNAMIC) + ST_CHAR *varTagBuf; /* User must supply */ + ST_CHAR *nextVarTag; /* MVL use only */ +#endif + +#if defined (MVL_JREAD_ANNOTATION_DYNAMIC) + ST_CHAR *annotationBuf; /* User must supply */ + ST_CHAR *nextAnnotation; /* MVL use only */ +#endif + + } MVL_JREAD_BUF_CTRL; + + +/* User defined Journal Read response functions. These functions are */ +/* to be supplied by the application in order to get the information */ +/* required for a Journal Read response. */ + +/* This function should be used to apply the filter and returns the */ +/* total number of Journal Entries and Journal Variables that meet */ +/* the filter criteria. */ +ST_RET u_mvl_start_jread (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo, + MVL_JREAD_BUF_CTRL *bufCtrl, + ST_VOID **usrHandleOut); + +/* MVL calls this function repetitively to get entries from the app. */ +/* MVL will use the entry then will call the free function below to */ +/* allow the application free the resources as required. */ +ST_RET u_mvl_get_next_jread_entry (MVL_JOURNAL_CTRL *jCtrl, + ST_VOID *usrHandle, + ST_BOOLEAN *moreFollowsOut, + MVL_JOURNAL_ENTRY **mvlJeDest); +ST_VOID u_mvl_free_jread_entry (MVL_JOURNAL_CTRL *jCtrl, + ST_VOID *usrHandle, + MVL_JOURNAL_ENTRY *mvlJe); + +/* When complete, MVL will call this function. */ +ST_VOID u_mvl_end_jread (MVL_JOURNAL_CTRL *jCtrl, + ST_VOID *usrHandle, + MVL_JREAD_BUF_CTRL *bufCtrl, + JREAD_REQ_INFO *reqInfo); + +/************************************************************************/ +/************************************************************************/ +/* Temporary file name */ + +/* User can supply path for temp files, prefix for file name */ +/* Typical forms are: */ +/* "/temp/" */ +/* "S:/temp/" */ +/* "//mike/temp/" */ +/* "X:" */ + +#define MVL_MAX_TMPFILE_PATH MAX_FILE_NAME +//extern ST_CHAR *mvl_tmpfile_path; + +/* Users should have a buffer at least this big, unless they can */ +/* control the temp filename path to be used. */ +#define MVL_MAX_TMPNAM_LEN (MVL_MAX_TMPFILE_PATH + 12) +ST_RET _mvl_tmpnam (ST_CHAR *dest, ST_CHAR *tmpfile_path); +ST_VOID _mvl_getpath (ST_CHAR *file_spec, ST_CHAR *dest); + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* MVL CLIENT SERVICE SUPPORT */ +/************************************************************************/ +/* conf_process_mode defines */ +/* When the confirm is received (and ICCP support is enabled) this flag */ +/* is used to tell MVL how to process the confirm. */ +#define MI_CONF_ICCP_DV 0x0001 + + +/* Read */ +typedef struct mvl_read_resp_parse_info + { + ST_RET result; /* SD_SUCCESS for OK */ + + /* MMS level result information */ + ST_INT16 acc_rslt_tag; /* access result tag */ + ST_INT16 failure; /* data access error */ + + ST_VOID *dest; /* Where data is to be put */ + ST_INT type_id; /* type of variable */ + + ST_BOOLEAN alt_acc_pres; + ALT_ACCESS *alt_acc; + ST_BOOLEAN alt_acc_type_aa; /* type_id is derived type */ + ST_BOOLEAN alt_acc_data_packed; + + ST_BOOLEAN descr_arr; /* for described read of array */ + ST_RTINT arr_size; /* number of elements */ + } MVL_READ_RESP_PARSE_INFO; + +/* Write */ +typedef struct mvl_write_req_info + { + ST_RET result; /* SD_SUCCESS for OK */ + + /* MMS level result detail */ + ST_INT16 resp_tag; /* response tag */ + ST_INT16 failure; /* data access error */ + + ST_VOID *local_data; /* Source of local data */ + ST_INT type_id; /* type of variable */ + + ST_BOOLEAN alt_acc_pres; + ALT_ACCESS *alt_acc; + ST_BOOLEAN alt_acc_type_aa; /* type_id is derived type */ + ST_BOOLEAN alt_acc_data_packed; + + ST_BOOLEAN arr; /* SD_TRUE if type is array and the # */ + ST_RTINT num_el; /* elements needs to be set */ + } MVL_WRITE_REQ_INFO ; + +/* JournalRead */ +typedef struct + { + ST_INT num_of_jou_entry; /* number of journal entries */ + ST_BOOLEAN more_follows; /* default = false */ + MVL_JOURNAL_ENTRY *jou_entry; /* ptr to array of entries */ + } MVL_JREAD_RESP_INFO; + +/* Outstanding Request Control */ +typedef struct mvl_req_pend + { + DBL_LNK l; /* For linked list */ + ST_UINT32 invoke_id; + time_t request_time; + MVL_NET_INFO *net_info; /* Who it was sent to */ + ST_INT op; /* MMS Opcode */ + union + { + struct + { + MVL_READ_RESP_PARSE_INFO *parse_info; + ST_INT num_data; + } rd; + struct + { + MVL_WRITE_REQ_INFO *w_info; + ST_INT num_data; + } wr; + struct + { + IDENT_RESP_INFO *resp_info; + } ident; + struct + { + INIT_INFO *resp_info; + } init; + struct + { + FOPEN_RESP_INFO *resp_info; + } fopen; + struct + { + FREAD_RESP_INFO *resp_info; + } fread; + struct + { + MVL_FDIR_RESP_INFO *resp_info; + } fdir; + struct + { + JINIT_RESP_INFO *resp_info; + } jinit; + struct + { + JSTAT_RESP_INFO *resp_info; + } jstat; + struct + { + MVL_JREAD_RESP_INFO *resp_info; + } jread; + struct + { + GETVLIST_RESP_INFO *resp_info; + } getvlist; + struct + { + DELVLIST_RESP_INFO *resp_info; + } delvlist; + struct + { + GETVAR_RESP_INFO *resp_info; + } getvar; + struct + { + GETDOM_RESP_INFO *resp_info; + } getdom; + struct + { + NAMELIST_RESP_INFO *resp_info; + } getnam; + struct + { + STATUS_RESP_INFO *resp_info; + } status; + struct + { + DOWNLOAD_RESP_INFO *resp_info; + } download; /* DownloadSegment resp info */ + } u; + MVL_COMM_EVENT *event; /* save event ptr to free later.*/ + ST_BOOLEAN done; + ST_RET result; /* SD_SUCCESS or error code */ + ERR_INFO *error_info; /* When result == MVL_ERR_CNF_ERR_OK */ + REJECT_RESP_INFO *reject_info; /* When result == MVL_ERR_CNF_REJ_ERR */ + + + /* User done function for async functions */ + ST_VOID (*u_req_done) (struct mvl_req_pend *req); + ST_VOID *v; /* For MVL user's use */ + + struct _mi_req_ctrl *mi_req; /* used for ICCP_LITE_SUPP */ + } MVL_REQ_PEND; + + +struct mvl_fget_req_info; /* forward declaration */ + +typedef struct mvl_fget_req_info + { + ST_BOOLEAN fget_done; + ST_INT fget_error; + /* pointer to user's fget confirm function */ + ST_VOID (*fget_cnf_ptr)(struct mvl_fget_req_info *state); + ST_CHAR srcfilename[MAX_FILE_NAME+1]; + ST_CHAR destfilename[MAX_FILE_NAME+1]; + + ST_VOID *v; /* For MVL user's use */ + + /* The rest of this structure is not normally accessed by the user. */ + char tempfilename[MVL_MAX_TMPNAM_LEN+1]; + FILE *fp; + ST_INT32 frsmid; + ST_UINT32 fsize; + } MVL_FGET_REQ_INFO; + + +ST_RET _mvla_send_status (MVL_NET_INFO *net_info, + STATUS_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_getname (MVL_NET_INFO *net_info, + NAMELIST_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_read_variables (MVL_NET_INFO *net_info, + READ_REQ_INFO *read_info, + ST_INT num_data, + MVL_READ_RESP_PARSE_INFO *parse_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_getvar (MVL_NET_INFO *net_info, + GETVAR_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_defvlist (MVL_NET_INFO *net_info, + DEFVLIST_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_getvlist (MVL_NET_INFO *net_info, + GETVLIST_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_delvlist (MVL_NET_INFO *net_info, + DELVLIST_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_getdom (MVL_NET_INFO *net_info, + GETDOM_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_fopen (MVL_NET_INFO *net_info, + ST_CHAR *filename, + ST_UINT32 init_pos, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_fread (MVL_NET_INFO *net_info, + FREAD_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_fclose (MVL_NET_INFO *net_info, + FCLOSE_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_fdir (MVL_NET_INFO *net_info, + ST_CHAR *filename, + ST_CHAR *ca_filename, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_fdelete (MVL_NET_INFO *net_info, + ST_CHAR *filename, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_jinit (MVL_NET_INFO *net_info, + JINIT_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_jread (MVL_NET_INFO *net_info, + JREAD_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); +ST_RET _mvla_send_jstat (MVL_NET_INFO *net_info, + JSTAT_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend); + +/* Function to make async function sync */ +ST_RET mvl_wait_req_done (MVL_REQ_PEND *req); + +/* Use this to free a request contrl after the confirm has been rx'd */ +ST_VOID mvl_free_req_ctrl (MVL_REQ_PEND *pend_req); + +/* Use this to free any pending Indication Ctrl structures */ +ST_VOID mvl_clr_ind_que (MVL_NET_INFO *net_info); + +/************************************************************************/ +/* CLIENT REQUEST FUNCTIONS */ +/* Most client request functions come in two versions - synchronous */ +/* and asynchronous. Both have identical arguments - the only */ +/* difference is that the synchronous versions do not return until */ +/* the confirm/error has been received, or the user gives up (via */ +/* the 'u_mvl_check_timeout' function). */ + +/* Identify */ +ST_RET mvl_identify (MVL_NET_INFO *net_info, MVL_REQ_PEND **req_out); +ST_RET mvla_identify (MVL_NET_INFO *net_info, MVL_REQ_PEND **req_out); + +/* Status */ +ST_RET mvl_status (MVL_NET_INFO *net_info, STATUS_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_status (MVL_NET_INFO *net_info, STATUS_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* Unsolicited Status */ +ST_RET mvl_ustatus (MVL_NET_INFO *net_info, USTATUS_REQ_INFO *req_info); + +/* GetNameList */ +ST_RET mvl_getnam (MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_getnam (MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + + +/* Read */ +ST_RET mvl_read_variables (MVL_NET_INFO *net_info, READ_REQ_INFO *read_info, + ST_INT num_data, + MVL_READ_RESP_PARSE_INFO *parse_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_read_variables (MVL_NET_INFO *net_info, READ_REQ_INFO *read_info, + ST_INT num_data, + MVL_READ_RESP_PARSE_INFO *parse_info, + MVL_REQ_PEND **req_out); + + +/* Write */ +ST_RET mvl_write_variables (MVL_NET_INFO *net_info, WRITE_REQ_INFO *write_info, + ST_INT num_data, MVL_WRITE_REQ_INFO *w_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_write_variables (MVL_NET_INFO *net_info, WRITE_REQ_INFO *write_info, + ST_INT num_data, MVL_WRITE_REQ_INFO *w_info, + MVL_REQ_PEND **req_out); + +/* GetVariableAccessAttributes */ +ST_RET mvl_getvar (MVL_NET_INFO *net_info, GETVAR_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_getvar (MVL_NET_INFO *net_info, GETVAR_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* DefineNamedVariableList */ +ST_RET mvl_defvlist (MVL_NET_INFO *net_info, DEFVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_defvlist (MVL_NET_INFO *net_info, DEFVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* GetNamedVariableListAttributes */ +ST_RET mvl_getvlist (MVL_NET_INFO *net_info, GETVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_getvlist (MVL_NET_INFO *net_info, GETVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* DeleteNamedVariableList */ +ST_RET mvl_delvlist (MVL_NET_INFO *net_info, DELVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_delvlist (MVL_NET_INFO *net_info, DELVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* GetDomainAttributes */ +ST_RET mvl_getdom (MVL_NET_INFO *net_info, GETDOM_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_getdom (MVL_NET_INFO *net_info, GETDOM_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* File Open */ +ST_RET mvl_fopen (MVL_NET_INFO *net_info, ST_CHAR *filename, + ST_UINT32 init_pos, MVL_REQ_PEND **req_out); +ST_RET mvla_fopen (MVL_NET_INFO *net_info, ST_CHAR *filename, + ST_UINT32 init_pos, MVL_REQ_PEND **req_out); + +/* File Read */ +ST_RET mvl_fread (MVL_NET_INFO *net_info, FREAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_fread (MVL_NET_INFO *net_info, FREAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* File Close */ +ST_RET mvl_fclose (MVL_NET_INFO *net_info, FCLOSE_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_fclose (MVL_NET_INFO *net_info, FCLOSE_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* File Directory */ +ST_RET mvl_fdir (MVL_NET_INFO *net_info, ST_CHAR *filename, + ST_CHAR *ca_filename, MVL_REQ_PEND **req_out); +ST_RET mvla_fdir (MVL_NET_INFO *net_info, ST_CHAR *filename, + ST_CHAR *ca_filename, MVL_REQ_PEND **req_out); + +/* File Delete */ +ST_RET mvl_fdelete (MVL_NET_INFO *net_info, ST_CHAR *filename, + MVL_REQ_PEND **req_out); +ST_RET mvla_fdelete (MVL_NET_INFO *net_info, ST_CHAR *filename, + MVL_REQ_PEND **req_out); + +/* File Rename */ +ST_RET mvl_frename (MVL_NET_INFO *net_info, ST_CHAR *curfilename, + ST_CHAR *newfilename, MVL_REQ_PEND **req_out); +ST_RET mvla_frename (MVL_NET_INFO *net_info, ST_CHAR *curfilename, + ST_CHAR *newfilename, MVL_REQ_PEND **req_out); + +/* Obtainfile */ +ST_RET mvl_obtfile (MVL_NET_INFO *net_info, ST_CHAR *srcfilename, + ST_CHAR *destfilename, MVL_REQ_PEND **req_out); +ST_RET mvla_obtfile (MVL_NET_INFO *net_info, ST_CHAR *srcfilename, + ST_CHAR *destfilename, MVL_REQ_PEND **req_out); + +/* File Get */ +/* No synchronous File Get function "mvl_fget". Requires multiple reqs, */ +/* so cannot be synchronous. */ +ST_RET mvla_fget (MVL_NET_INFO *net_info, ST_CHAR *srcfilename, + ST_CHAR *destfilename, MVL_FGET_REQ_INFO *fget_req_info); + +/* InitializeJournal */ +ST_RET mvl_jinit (MVL_NET_INFO *net_info, JINIT_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_jinit (MVL_NET_INFO *net_info, JINIT_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* ReadJournal */ +ST_RET mvl_jread (MVL_NET_INFO *net_info, JREAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_jread (MVL_NET_INFO *net_info, JREAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* WriteJournal */ +ST_RET mvl_jwrite (MVL_NET_INFO *net_info, JWRITE_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_jwrite (MVL_NET_INFO *net_info, JWRITE_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* JournalStatus */ +ST_RET mvl_jstat (MVL_NET_INFO *net_info, JSTAT_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_jstat (MVL_NET_INFO *net_info, JSTAT_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* InitiateDownload */ +/* NOT YET IMPLEMENTED! ONLY NEEDED FOR CLIENT */ + +/* DownloadSegment */ +ST_RET mvl_download (MVL_NET_INFO *net_info, DOWNLOAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_download (MVL_NET_INFO *net_info, DOWNLOAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* TerminateDownload */ +ST_RET mvl_termdown (MVL_NET_INFO *net_info, TERMDOWN_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); +ST_RET mvla_termdown (MVL_NET_INFO *net_info, TERMDOWN_REQ_INFO *req_info, + MVL_REQ_PEND **req_out); + +/* Conclude */ +ST_RET mvl_concl (MVL_NET_INFO *net_info, MVL_REQ_PEND **req_out); +ST_RET mvla_concl (MVL_NET_INFO *net_info, MVL_REQ_PEND **req_out); +ST_RET _mvla_send_concl (MVL_NET_INFO *net_info, MVL_REQ_PEND *req_pend); + +/* Obsolete function, please use mvl_conc or mvla_conc */ +/* ST_RET mvl_conclude (MVL_NET_INFO *net_info ); */ + +/************************************************************************/ +/* ENCODE FUNCTIONS - each encodes a req or resp but does NOT send it. */ +/************************************************************************/ +/* Information Report Request */ +ST_RET mvl_encode_info_rpt (MVL_NET_INFO *net_info, + MVL_NVLIST_CTRL *nvl, + ST_BOOLEAN listOfVariables, + ASN1_ENC_CTXT *aCtx); + +/* NOTE: other encode functions not currently needed. */ + +/************************************************************************/ +/* Client Info Rpt indication */ + +/* This function is called when thje client application received an */ +/* information report */ +extern ST_VOID u_mvl_info_rpt_ind (MVL_COMM_EVENT *event); + +/* This function is used to convert Info Report data to local format */ +/* The user supplies a table of variable associations, which speify the */ +/* data type, destination, and pre/post processing functions. */ +/* This function free's the info report resources when the conversion */ +/* are complete. */ + +ST_VOID mvl_info_data_to_local (MVL_COMM_EVENT *event, + ST_INT num_va, + MVL_VAR_ASSOC **info_va); + +#if defined(MVL_REM_VMD_SUPPORT) +extern MVL_VMD_CTRL *(*u_mvl_get_rem_vmd_fun) (MVL_NET_INFO *net_info); +ST_VOID mvl_info_rpt_rem_process (MVL_COMM_EVENT *event); +#endif + +ST_RET mvlu_add_rt_type (RUNTIME_TYPE *rt, ST_INT numRt, ST_INT *typeIdOut); +ST_VOID mvlu_free_rt_type (ST_INT typeId); + +/* Type to String and visa-versa */ +ST_INT mvl_typename_to_typeid (ST_CHAR *type_id_string); +ST_CHAR *mvl_typeid_to_typename (ST_INT type_id); + + +/************************************************************************/ +/************************************************************************/ + +typedef struct + { + ST_DOUBLE startTime; + ST_INT32 callingConn; /* Calling Connections */ + ST_INT32 callingConnOk; /* Calling Connections Succesful*/ + ST_INT32 callingConnFail; /* Calling Connections Failed */ + ST_INT32 calledConn; /* Called Connections */ + ST_INT32 calledConnOK; /* Called Connections Succesful */ + ST_INT32 calledConnFail; /* Called Connections Failed */ + ST_INT32 clientConcl; /* Client Concludes */ + ST_INT32 serverConcl; /* Server Concludes */ + ST_INT32 localAbort; /* Local Aborts */ + ST_INT32 remoteAbort; /* Remote Aborts */ + ST_INT32 rejectsSent; /* Rejects Sent */ + ST_INT32 rejectsRcvd; /* Rejects Received */ + ST_INT32 clientReq; /* Client Requests */ + ST_INT32 clientReqOk; /* Client Requests OK */ + ST_INT32 clientReqErr; /* Client Requests Error */ + ST_INT32 clientVarRdOk; /* Client Variables Read OK */ + ST_INT32 clientVarRdFail; /* Client Variables Read Error */ + ST_INT32 clientVarWrOk; /* Client Variables Write OK */ + ST_INT32 clientVarWrErr; /* Client Variables Write Error */ + ST_INT32 clientInfoRpt; /* Client Information Reports */ + ST_INT32 clientUstatus; /* Client Unsolicited Status */ + ST_INT32 serverInd; /* Server Indications */ + ST_INT32 serverRespOk; /* Server Responses OK */ + ST_INT32 serverRespErr; /* Server Responses Error */ + ST_INT32 serverVarRdOk; /* Server Variables Read OK */ + ST_INT32 serverVarRdErr; /* Server Variables Read Error */ + ST_INT32 serverVarWrOk; /* Server Variables Write OK */ + ST_INT32 serverVarWrErr; /* Server Variables Write Error */ + ST_INT32 serverInfoRpt; /* Server Information Reports */ + ST_INT32 serverUstatus; /* Server Unsolicited Status */ + } MVL_MMS_STATISTICS; + +extern MVL_MMS_STATISTICS mvl_mms_statistics; + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* MVL INTERNAL DECLARATIONS */ +/************************************************************************/ +/************************************************************************/ + +/* Built in MVL Indication and Confirm functions, typically called */ +/* from "mvlop_en.c" if service is enabled. */ + +ST_VOID _mvl_process_read_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_write_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_ident_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_info_ind (MVL_COMM_EVENT *event); +ST_VOID _mvl_process_status_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_ustatus_ind (MVL_COMM_EVENT *event); +ST_VOID _mvl_process_getnam_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_getvaa_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_getvla_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_getdom_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_fopen_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_fread_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_fclose_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_fdir_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_obtfile_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_fdelete_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_frename_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_jinit_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_jread_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_concl_ind (MVL_COMM_EVENT *event); +ST_VOID _mvl_process_cancel_ind (MVL_COMM_EVENT *event); +ST_VOID _mvl_process_defvlist_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_delvlist_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_jstat_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_initdown_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_download_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_termdown_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_initupl_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_upload_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_termupl_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_deldom_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_crepi_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_delpi_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_start_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_stop_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_resume_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_reset_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_kill_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_getpi_ind (MVL_IND_PEND *ind_pend); +ST_VOID _mvl_process_getcl_ind (MVL_IND_PEND *ind_pend); + +ST_VOID _mvl_process_read_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_write_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_ident_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_getvar_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_getnam_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_status_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_getdom_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_fopen_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_fread_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_fclose_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_fdir_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_obtfile_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_fdelete_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_frename_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_jinit_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_jread_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_jwrite_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_jstat_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_defvlist_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_getvlist_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_delvlist_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_initdown_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_download_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_termdown_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_initupl_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_upload_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_termupl_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_deldom_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_crepi_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_delpi_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_start_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_stop_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_resume_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_reset_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_kill_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_getpi_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_getcl_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_process_concl_conf (MVL_REQ_PEND *req); +ST_VOID _mvl_release (MVL_REQ_PEND *req); + +/************************************************************************/ + +ST_VOID mvl_ind_rcvd (MVL_COMM_EVENT *event); +ST_VOID mvl_conf_rcvd (MVL_COMM_EVENT *event); +ST_VOID mvl_cancel_ind_rcvd (MVL_COMM_EVENT *event); +ST_VOID mvl_concl_ind_rcvd (MVL_COMM_EVENT *event); +ST_VOID mvl_concl_conf_rcvd (MVL_REQ_PEND *req_pend); + +ST_VOID _mvl_ind_reject (MVL_IND_PEND *ind); +ST_VOID _mvl_conf_reject (MVL_REQ_PEND *req); +ST_VOID _mvl_send_reject (MVL_COMM_EVENT *event); +ST_RET _mvl_send_error (MVL_COMM_EVENT *event, ST_INT16 eClass, ST_INT16 code); +ST_RET _mvl_send_err_f (MVL_COMM_EVENT *event, ST_INT16 eClass, ST_INT16 code); + +#define mplas_err_resp(indCtrl, eClass, code) _mplas_err_resp(indCtrl, eClass, code) +ST_RET _mplas_err_resp (MVL_IND_PEND *indCtrl, ST_INT16 eClass, ST_INT16 code); + +ST_VOID _mvl_send_resp (MVL_COMM_EVENT *event, ST_RET build_rc); +ST_VOID _mvl_send_resp_i (MVL_IND_PEND *indCtrl, ST_RET build_rc); +ST_RET _mvl_send_req (MVL_NET_INFO *net_info, + MVL_REQ_PEND *req, ST_RET build_rc); + +MVL_VAR_ASSOC *_mvl_objname_to_va (MVL_VMD_CTRL *vmd_ctrl, + MVL_NET_INFO *net_info, + ST_INT service, + OBJECT_NAME *obj, + MVL_SCOPE *va_scope_out, + ST_BOOLEAN alt_access_pres, + ALT_ACCESS *alt_acc, + ST_BOOLEAN *alt_access_done_out); + +/* This function does everything required to send a MMS message - */ +/* adds CLNP/CLTP/HDLC components then does whatever is required to send*/ +/* the complete message. Does not return until done, returns SD_SUCCESS */ +/* or an error code. */ +ST_RET _mvl_send_msg (ST_UCHAR *mms_msg, ST_INT mms_msg_len, MVL_NET_INFO *net_info); + + +/* This function is called to get MMS PDU's that have been received, */ +/* as well as other communications events. Returns a pointer to a */ +/* MMS Comm Event control structure that must be free'd via the */ +ST_BOOLEAN _mvl_net_service (MVL_COMM_EVENT **eventOut); +ST_VOID _mvl_free_comm_event (MVL_COMM_EVENT *event); + +extern ST_BOOLEAN mvl_init_ind_hold; + +/* Functions to manipulate request control list */ +MVL_REQ_PEND *_mvl_get_req_ctrl (MVL_NET_INFO *net_info, ST_INT16 op); +MVL_REQ_PEND *_mvl_find_req_ctrl (MVL_NET_INFO *net_info, + ST_INT op, ST_UINT32 id); +ST_VOID _mvl_set_net_req_done (MVL_REQ_PEND *skip, + MVL_NET_INFO *net_info, ST_RET result); +ST_VOID _mvl_set_req_done (MVL_REQ_PEND *req, ST_RET result); + +/* Alternate Access creation buffer management */ +ST_RET _mvl_get_asn1_aa (ALT_ACCESS *alt_acc, VARIABLE_LIST *vl); + +ST_RET _mvl_concat_filename (ST_CHAR *good_name, ST_INT num_of_fname, + FILE_NAME *fname_arr, ST_INT max_len); + +ST_VOID mvl_log_req (ST_INT opcode, ST_VOID *info); +ST_VOID mvl_log_resp (ST_INT opcode, ST_VOID *info); + +ST_VOID mvl_scope_set (OBJECT_NAME *obj, MVL_SCOPE *mvl_scope_out); + + +/************************************************************************/ + +extern ST_BOOLEAN _mvl_comm_serve_active; + +/************************************************************************/ +/* MVL_OBJ (generic MVL object) */ +/* This structure is used by all the MVL object manipulation functions */ +/* (mvl_obj_insert, mvl_obj_delete, mvl_obj_find, etc.) to represent */ +/* any named object (i.e. Named Variable, Named Variable List, */ +/* Domain, Journal, etc.). */ +/* A pointer to a "real" structure must be cast to (MVL_OBJ *) */ +/* for any call to the functions. */ +/* WARNING: It is assumed that the first item in the "real" structure */ +/* is a pointer to the "name" of the object. */ +/************************************************************************/ + +typedef struct + { + ST_CHAR *name; + } MVL_OBJ; + +/************************************************************************/ + +ST_VOID *_mvl_calloc_os (ST_UINT num, ST_UINT size); +ST_VOID *_mvl_realloc_os (ST_VOID *old, ST_UINT new_size); +ST_VOID _mvl_free_os (ST_VOID *buf); + +/************************************************************************/ +/* MVL object manipulation function prototypes. */ +/************************************************************************/ + +ST_RET mvl_obj_insert (MVL_OBJ **ObjTable, ST_INT *numObj, ST_INT maxObj, + MVL_OBJ *newObj); +MVL_OBJ *mvl_obj_delete (MVL_OBJ **ObjTable, ST_INT *numObj, + ST_CHAR *ObjName); +MVL_OBJ *mvl_obj_find (MVL_OBJ **ObjTable, ST_INT numObj, + ST_CHAR *ObjName); +MVL_OBJ ** mvl_obj_find_key (MVL_OBJ **ObjTable, ST_INT numObj, + ST_CHAR *ObjName); +ST_VOID _mvl_resize_ptr_tbl (ST_INT *p_max_num, + ST_VOID ***p_ptr_tbl, ST_INT new_size); +/************************************************************************/ +/* MVL type derivation functions */ +/************************************************************************/ + +ST_RET mvl_derive_new_type (ST_CHAR *base_name, ST_INT typeIdIn, + ST_INT *typeIdOut, ST_CHAR *handle); +ST_RET mvl_derive_type_members (ST_CHAR *base_name, ST_INT typeIdIn, + ST_UCHAR **membership, ST_RTREF *refs, ST_CHAR *handle); +ST_VOID mvl_print_derived_type( ST_CHAR *base_name, ST_INT typeIdIn, + ST_UCHAR *membership, ST_UCHAR **labels); +ST_RET mvl_add_derived_type( ST_CHAR *base_name, ST_INT typeIdIn, + ST_UCHAR *membership, ST_RTREF *refs, + ST_INT *typeIdOut); +#ifndef __ECOS +ST_BOOLEAN u_mvl_rt_element_supported( RUNTIME_TYPE *rt, + ST_CHAR *element_name, + ST_RTREF *ui, ST_CHAR *handle); +#endif +/************************************************************************/ + +ST_INT mi_connect_ind_fun (MVL_NET_INFO *net_info, + INIT_INFO *init_ind_info, + ACSE_AUTH_INFO *rsp_auth_info); +ST_VOID mi_release_ind_fun (MVL_NET_INFO *mvl_net_info); +ST_VOID mi_abort_ind_fun (MVL_NET_INFO *mvl_net_info); + +ST_VOID _mvl_free_req_pend (ST_VOID); +ST_VOID u_mvl_reject_ind (MVL_NET_INFO *net_info, REJECT_RESP_INFO *rej_info); + +/************************************************************************/ +/* Dynamic type creation functions. */ +/************************************************************************/ +MVL_TYPE_CTRL *mvl_type_ctrl_find (ST_INT TypeId); +MVL_TYPE_CTRL *mvl_type_ctrl_find_dyn (ST_INT TypeId); +ST_INT mvl_type_id_create (ST_CHAR *type_name, ST_UCHAR *asn1_data, ST_UINT asn1_len); +ST_INT mvl_type_id_create_from_tdl (ST_CHAR *type_name, ST_CHAR *tdl); +ST_VOID mvl_type_id_destroy (ST_INT TypeId); +ST_RET mvl_type_id_destroy_all_dyn (ST_VOID); +ST_INT mvl_type_count (ST_VOID); + +/* These take additional "vmd_ctrl" argument. */ +ST_INT mvl_vmd_type_id_create (MVL_VMD_CTRL *vmd_ctrl, ST_CHAR *type_name, RUNTIME_CTRL *rt_ctrl); +ST_RET mvl_vmd_type_id_destroy (MVL_VMD_CTRL *vmd_ctrl, ST_INT TypeId); +ST_RET mvl_vmd_type_id_destroy_all (MVL_VMD_CTRL *vmd_ctrl); +MVL_TYPE_CTRL *mvl_vmd_type_ctrl_find (MVL_VMD_CTRL *vmd_ctrl, ST_INT type_id); + +#define mvlu_install() /* OBSOLETE: For backward compatibility only */ + +/************************************************************************/ +/* Allocation functions/macros. */ +/************************************************************************/ +#define mvl_enc_buf_alloc(size) M_MALLOC (MSMEM_PDU_ENC, size) +#define mvl_enc_buf_free(ptr) M_FREE (MSMEM_PDU_ENC, ptr) + +/************************************************************************/ +/* Miscellaneous functions. */ +/************************************************************************/ +ST_VOID wait_any_event (ST_LONG max_ms_delay); /* called by sync fcts */ + /* user MUST supply this fct*/ +ST_INT mvl_req_bufs_avail (MVL_NET_INFO *net_info); +ST_INT mvl_ureq_bufs_avail (MVL_NET_INFO *net_info); + +/************************************************************************/ +/* Object add/remove functions. */ +/************************************************************************/ +MVL_DOM_CTRL *mvl_vmd_dom_add (MVL_VMD_CTRL *vmd_ctrl, + ST_CHAR *name, + ST_INT max_num_var, + ST_INT max_num_nvl, + ST_INT max_num_jou, + ST_BOOLEAN copy_name); +ST_RET mvl_vmd_dom_remove (MVL_VMD_CTRL *vmd_ctrl, ST_CHAR *dom_name); + +MVL_VAR_ASSOC *mvl_vmd_var_add (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info, + ST_INT type_id, + ST_VOID *data, + MVL_VAR_PROC *proc, + ST_BOOLEAN copy_name); +MVL_VAR_ASSOC *mvl_var_add_alloc (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info, + ST_INT type_id, + MVL_VAR_PROC *proc); +ST_RET mvl_vmd_var_remove (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); + +MVL_NVLIST_CTRL *mvl_vmd_nvl_add (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *nvl_obj, + MVL_NET_INFO *net_info, + ST_INT num_var, + OBJECT_NAME *var_obj, /* array of var names */ + ST_BOOLEAN copy_name); +ST_RET mvl_vmd_nvl_remove (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); + +MVL_JOURNAL_CTRL *mvl_vmd_jou_add (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info, + ST_BOOLEAN copy_name); +ST_RET mvl_vmd_jou_remove (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); + +/************************************************************************/ +/* Object insert/delete functions. */ +/************************************************************************/ +ST_RET mvl_vmd_dom_insert (MVL_VMD_CTRL *vmd_ctrl, + MVL_DOM_CTRL *dom); +MVL_DOM_CTRL *mvl_vmd_dom_delete (MVL_VMD_CTRL *vmd_ctrl, ST_CHAR *dom_name); + +ST_RET mvl_vmd_var_insert (MVL_VMD_CTRL *vmd_ctrl, + MVL_VAR_ASSOC *va, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); /* Only used if AA_SPEC */ +MVL_VAR_ASSOC *mvl_vmd_var_delete (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); + +ST_RET mvl_vmd_nvl_insert (MVL_VMD_CTRL *vmd_ctrl, + MVL_NVLIST_CTRL *nvl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); /* Only used if AA_SPEC */ +MVL_NVLIST_CTRL *mvl_vmd_nvl_delete (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); /* Only used if AA_SPEC */ + +ST_RET mvl_vmd_jou_insert (MVL_VMD_CTRL *vmd_ctrl, + MVL_JOURNAL_CTRL *jou, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); /* Only used if AA_SPEC */ +MVL_JOURNAL_CTRL *mvl_vmd_jou_delete (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); + + +/************************************************************************/ +/* Object "find" functions. */ +/************************************************************************/ +MVL_DOM_CTRL *mvl_vmd_find_dom (MVL_VMD_CTRL *vmd_ctrl, + ST_CHAR *name); +MVL_DOM_CTRL *mvl_vmd_dom_find_last (MVL_VMD_CTRL *vmd_ctrl); +MVL_VAR_ASSOC *mvl_vmd_find_var (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); /* Only used if AA_SPEC */ +MVL_NVLIST_CTRL *mvl_vmd_find_nvl (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); /* Only used if AA_SPEC */ +MVL_JOURNAL_CTRL *mvl_vmd_find_jou (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info); /* Only used if AA_SPEC */ + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* MVL_DEFS_INCLUDED */ +/************************************************************************/ + diff --git a/mmslib/inc/mvl_log.h b/mmslib/inc/mvl_log.h new file mode 100644 index 0000000..49f092b --- /dev/null +++ b/mmslib/inc/mvl_log.h @@ -0,0 +1,198 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2002, All Rights Reserved. */ +/* */ +/* MODULE NAME : mvl_log.h */ +/* PRODUCT(S) : Tool */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/22/08 JRB 14 Del unused MVLULOG_TIMING macros. */ +/* 04/09/07 MDE 13 Enhanced filtered logging */ +/* 09/12/05 JRB 12 Added more ERR, NERR macros */ +/* 07/13/05 MDE 11 Added more CNERR macros */ +/* 08/12/04 JRB 10 Fix MVLU_LOG_CTIMING.. macros. */ +/* 12/12/02 JRB 09 Use new "Base" macros SLOG_*, SLOGC_*, SLOGH.*/ +/* 07/31/01 MDE 08 Added mvl_conn_filtered_logging */ +/* 03/28/01 JRB 07 Add ..ACSEDATA3 macro. */ +/* 03/22/01 GLB 06 Added: MVLULOG_DEBUG, MVLULOG_TIMING */ +/* 12/13/99 JRB 05 Delete ";" from non-debug macros. Get extra */ +/* ";" when expanded (doesn't always compile). */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 09/07/99 MDE 03 Added FLOW3, CFLOW3 macros */ +/* 10/08/98 MDE 02 Migrated to updated SLOG interface */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#ifndef MVL_LOG_INCLUDED +#define MVL_LOG_INCLUDED + +#include "slog.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ +/* MMS-EASE Lite logging control */ + +#define MVLLOG_ERR 0x00000001 +#define MVLLOG_NERR 0x00000002 +#define MVLLOG_ACSE 0x00000040 +#define MVLLOG_ACSEDATA 0x00000080 +#define MVLULOG_FLOW 0x00000200 +#define MVLULOG_DEBUG 0x00000400 + + +/* For backward compatability only */ +#define mvl_log_mask mvl_debug_sel +extern ST_UINT mvl_debug_sel; + +/* Allows filtering of ACSE data logging by connection */ +extern ST_BOOLEAN mvl_conn_filtered_logging; + +/* Log type strings */ +extern SD_CONST ST_CHAR *SD_CONST _mvllog_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mvllog_nerr_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mvllog_acse_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mvllog_acsedata_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mvlulog_flow_logstr; +extern SD_CONST ST_CHAR *SD_CONST _mvlulog_debug_logstr; + + +/*********************** ERR Macros *************************************/ +#define MVL_LOG_ERR0(a) \ + SLOG_0 (mvl_debug_sel & MVLLOG_ERR,_mvllog_err_logstr,a) +#define MVL_LOG_ERR1(a,b) \ + SLOG_1 (mvl_debug_sel & MVLLOG_ERR,_mvllog_err_logstr,a,b) +#define MVL_LOG_ERR2(a,b,c) \ + SLOG_2 (mvl_debug_sel & MVLLOG_ERR,_mvllog_err_logstr,a,b,c) +#define MVL_LOG_ERR3(a,b,c,d) \ + SLOG_3 (mvl_debug_sel & MVLLOG_ERR,_mvllog_err_logstr,a,b,c,d) +#define MVL_LOG_ERR4(a,b,c,d,e) \ + SLOG_4 (mvl_debug_sel & MVLLOG_ERR,_mvllog_err_logstr,a,b,c,d,e) +#define MVL_LOG_ERR5(a,b,c,d,e,f) \ + SLOG_5 (mvl_debug_sel & MVLLOG_ERR,_mvllog_err_logstr,a,b,c,d,e,f) + +#define MVL_LOG_CERR0(a) \ + SLOGC_0 (mvl_debug_sel & MVLLOG_ERR,a) +#define MVL_LOG_CERR1(a,b) \ + SLOGC_1 (mvl_debug_sel & MVLLOG_ERR,a,b) +#define MVL_LOG_CERR2(a,b,c) \ + SLOGC_2 (mvl_debug_sel & MVLLOG_ERR,a,b,c) +#define MVL_LOG_CERR3(a,b,c,d) \ + SLOGC_3 (mvl_debug_sel & MVLLOG_ERR,a,b,c,d) +#define MVL_LOG_CERR4(a,b,c,d,e) \ + SLOGC_4 (mvl_debug_sel & MVLLOG_ERR,a,b,c,d,e) +#define MVL_LOG_CERR5(a,b,c,d,e,f) \ + SLOGC_5 (mvl_debug_sel & MVLLOG_ERR,a,b,c,d,e,f) + + +/*********************** NERR Macros *************************************/ + +#define MVL_LOG_NERR0(a) \ + SLOG_0 (mvl_debug_sel & MVLLOG_NERR,_mvllog_nerr_logstr,a) +#define MVL_LOG_NERR1(a,b) \ + SLOG_1 (mvl_debug_sel & MVLLOG_NERR,_mvllog_nerr_logstr,a,b) +#define MVL_LOG_NERR2(a,b,c) \ + SLOG_2 (mvl_debug_sel & MVLLOG_NERR,_mvllog_nerr_logstr,a,b,c) +#define MVL_LOG_NERR3(a,b,c,d) \ + SLOG_3 (mvl_debug_sel & MVLLOG_NERR,_mvllog_nerr_logstr,a,b,c,d) +#define MVL_LOG_NERR4(a,b,c,d,e) \ + SLOG_4 (mvl_debug_sel & MVLLOG_NERR,_mvllog_nerr_logstr,a,b,c,d,e) +#define MVL_LOG_NERR5(a,b,c,d,e,f) \ + SLOG_5 (mvl_debug_sel & MVLLOG_NERR,_mvllog_nerr_logstr,a,b,c,d,e,f) + +#define MVL_LOG_CNERR0(a) \ + SLOGC_0 (mvl_debug_sel & MVLLOG_NERR,a) +#define MVL_LOG_CNERR1(a,b) \ + SLOGC_1 (mvl_debug_sel & MVLLOG_NERR,a,b) +#define MVL_LOG_CNERR2(a,b,c) \ + SLOGC_2 (mvl_debug_sel & MVLLOG_NERR,a,b,c) +#define MVL_LOG_CNERR3(a,b,c,d) \ + SLOGC_3 (mvl_debug_sel & MVLLOG_NERR,a,b,c,d) +#define MVL_LOG_CNERR4(a,b,c,d,e) \ + SLOGC_4 (mvl_debug_sel & MVLLOG_NERR,a,b,c,d,e) +#define MVL_LOG_CNERR5(a,b,c,d,e,f) \ + SLOGC_5 (mvl_debug_sel & MVLLOG_NERR,a,b,c,d,e,f) + +/*********************** ACSE Macros *************************************/ + +#define MVL_LOG_ACSE0(a) \ + SLOG_0 (mvl_debug_sel & MVLLOG_ACSE,_mvllog_acse_logstr,a) +#define MVL_LOG_ACSE1(a,b) \ + SLOG_1 (mvl_debug_sel & MVLLOG_ACSE,_mvllog_acse_logstr,a,b) + + +#define MVL_LOG_CACSE0(a) \ + SLOGC_0 (mvl_debug_sel & MVLLOG_ACSE,a) +#define MVL_LOG_CACSE1(a,b) \ + SLOGC_1 (mvl_debug_sel & MVLLOG_ACSE,a,b) + + +#define MVL_LOG_ACSEDATA1(a,b) \ + SLOG_1 (mvl_debug_sel & MVLLOG_ACSEDATA,_mvllog_acsedata_logstr,a,b) +#define MVL_LOG_ACSEDATA2(a,b,c) \ + SLOG_2 (mvl_debug_sel & MVLLOG_ACSEDATA,_mvllog_acsedata_logstr,a,b,c) +#define MVL_LOG_ACSEDATA3(a,b,c,d) \ + SLOG_3 (mvl_debug_sel & MVLLOG_ACSEDATA,_mvllog_acsedata_logstr,a,b,c,d) + + +#define MVL_LOG_ACSEDATAH(a,b) \ + SLOGH (mvl_debug_sel & MVLLOG_ACSEDATA,a,b) + + +/*********************** MVLU FLOW Macros *******************************/ + +#define MVLU_LOG_FLOW0(a) \ + SLOG_0 (mvl_debug_sel & MVLULOG_FLOW,_mvlulog_flow_logstr,a) +#define MVLU_LOG_FLOW1(a,b) \ + SLOG_1 (mvl_debug_sel & MVLULOG_FLOW,_mvlulog_flow_logstr,a,b) +#define MVLU_LOG_FLOW2(a,b,c) \ + SLOG_2 (mvl_debug_sel & MVLULOG_FLOW,_mvlulog_flow_logstr,a,b,c) +#define MVLU_LOG_FLOW3(a,b,c,d) \ + SLOG_3 (mvl_debug_sel & MVLULOG_FLOW,_mvlulog_flow_logstr,a,b,c,d) + + +#define MVLU_LOG_CFLOW0(a) \ + SLOGC_0 (mvl_debug_sel & MVLULOG_FLOW,a) +#define MVLU_LOG_CFLOW1(a,b) \ + SLOGC_1 (mvl_debug_sel & MVLULOG_FLOW,a,b) +#define MVLU_LOG_CFLOW2(a,b,c) \ + SLOGC_2 (mvl_debug_sel & MVLULOG_FLOW,a,b,c) +#define MVLU_LOG_CFLOW3(a,b,c,d) \ + SLOGC_3 (mvl_debug_sel & MVLULOG_FLOW,a,b,c,d) + + +/*********************** MVLU DEBUG Macros *******************************/ + +#define MVLU_LOG_DEBUG0(a) \ + SLOG_0 (mvl_debug_sel & MVLULOG_DEBUG,_mvlulog_debug_logstr,a) +#define MVLU_LOG_DEBUG1(a,b) \ + SLOG_1 (mvl_debug_sel & MVLULOG_DEBUG,_mvlulog_debug_logstr,a,b) +#define MVLU_LOG_DEBUG2(a,b,c) \ + SLOG_2 (mvl_debug_sel & MVLULOG_DEBUG,_mvlulog_debug_logstr,a,b,c) +#define MVLU_LOG_DEBUG3(a,b,c,d) \ + SLOG_3 (mvl_debug_sel & MVLULOG_DEBUG,_mvlulog_debug_logstr,a,b,c,d) + + +#define MVLU_LOG_CDEBUG0(a) \ + SLOGC_0 (mvl_debug_sel & MVLULOG_DEBUG,a) +#define MVLU_LOG_CDEBUG1(a,b) \ + SLOGC_1 (mvl_debug_sel & MVLULOG_DEBUG,a,b) +#define MVLU_LOG_CDEBUG2(a,b,c) \ + SLOGC_2 (mvl_debug_sel & MVLULOG_DEBUG,a,b,c) +#define MVLU_LOG_CDEBUG3(a,b,c,d) \ + SLOGC_3 (mvl_debug_sel & MVLULOG_DEBUG,a,b,c,d) + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/mmslib/inc/mvl_uca.h b/mmslib/inc/mvl_uca.h new file mode 100644 index 0000000..df3aa8d --- /dev/null +++ b/mmslib/inc/mvl_uca.h @@ -0,0 +1,898 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2002, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_uca.h */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/27/09 JRB 39 Add funct ptrs u_mvl_wr_ind_var_start/end. */ +/* 07/23/08 JRB 38 Move some defs to mvl_defs.h (need earlier). */ +/* Add mvl61850_objref_create. */ +/* 06/30/08 JRB 37 MVL_SBO_CTRL: repl cmd_executing w/ ctlState.*/ +/* Add MVL61850_CTLSTATE_* for setting ctlState.*/ +/* Increase size of sbo_var for IEC 61850. */ +/* MVL61850_BRCB_CTRL: Add lastSentTimeOfEntry. */ +/* 05/15/08 JRB 36 Add mvl61850_integrity_timeout for 61850 only*/ +/* 05/08/08 JRB 35 Add ctlModel to MVL_SBO_CTRL. */ +/* 05/06/08 JRB 34 Add cmd_executing to MVL_SBO_CTRL. */ +/* 03/03/08 JRB 33 Add mvl61850_ctl_req_done. */ +/* Add sboClass to MVL_SBO_CTRL. */ +/* Add MVL61850_SBOCLASS_* defines. */ +/* 11/12/07 MDE 32 Moved MMSOP_RDWR_USR_HANDLED to mms_def2.h */ +/* 03/07/07 JRB 31 Add mvlu_get_leaf_val_int_any. */ +/* 02/26/07 JRB 30 initSboCtrl: add use_ms_timer arg. */ +/* MVL_SBO_CTRL: add millisecond timer support. */ +/* 02/13/07 JRB 29 mvl61850_get_rcb: del unused net_info arg. */ +/* Add scan timers to MVL_RPT_CTRL. Add helper fct*/ +/* 11/30/06 JRB 28 Fix *_brcb_entryid_init so user can call it. */ +/* 11/21/06 JRB 27 Add mvl61850_ctl_lastapplerror_send. */ +/* Move ..LAST_APPL_ERROR def to mvl_defs.h. */ +/* 10/10/06 JRB 26 Add mvlu_set_leaf_param_name2. */ +/* 09/27/06 MDE 25 Added MMSOP_RDWR_USR_HANDLED for IOS */ +/* 08/09/06 JRB 24 MVL61850_BRCB_CTRL, BUFLIST_ENTRY: big changes.*/ +/* Add mvl61850_create(free)_rpt_ctrl, */ +/* mvl61850_rpt_service, */ +/* mvl61850_rpt_dataset_create(destroy). */ +/* Chg EntryID storage from ST_INT to Ostring. */ +/* Del obsolete MVLU_RPT_VA_CTRL. */ +/* Chg/add/del several internal report functions.*/ +/* Add vstring129 to MVLU_RPT_TYPEIDS. */ +/* 08/09/06 JRB 23 Fix MVL61850_MAX_OBJREF_LEN per Tissue 141. */ +/* 03/27/06 JRB 22 Add more mvlu_get_leaf_* functions. */ +/* 09/12/05 JRB 21 Add mvl61850_ctl_chk_sbow. */ +/* 07/11/05 JRB 20 Add more "mvl61850_ctl_*" functions. */ +/* 06/27/05 JRB 19 Del mvlu_rpt_nvl_add/destroy. */ +/* 06/27/05 JRB 18 _mvlu_get_rd_rcb: add (MVLU_RPT_CLIENT **) arg.*/ +/* MVL61850_BRCB_CTRL: Add lastSentEntryID. */ +/* 05/27/05 CRM 17 Add mvlu_rpt_destroy_scan_ctrl. */ +/* 05/09/05 JRB 16 Define MVLU_LEAF_FUN_LOOKUP_ENABLE by default*/ +/* 12/09/04 JRB 15 Add "MVL61850_CTLMODEL_*" defines. */ +/* Add MVL61850_LAST_APPL.. struct. */ +/* Add mvlu_trim_branch_name, mvlu_find_comp_type,*/ +/* mvlu_get_leaf_val_*. */ +/* Add mvl61850_ctl_chk_sbo, mvl61850_ctl_chk_state.*/ +/* Add initSboCtrl. */ +/* 09/20/04 JRB 14 More SBO changes for IEC 61850. */ +/* 08/30/04 JRB 13 Add mvlu_sbo_chk_* prototypes. */ +/* 07/06/04 JRB 12 Add mvlu_rpt_create_scan_ctrl2 proto. */ +/* 06/30/04 JRB 11 Add "prim_num", "prim_offset_base" to */ +/* MVLU_RD_VA_CTRL, MVLU_WR_VA_CTRL. */ +/* Del global var mvluUseStaticData. */ +/* Del SCL parsing functions & related structs: */ +/* mvl61850_ln_create_start, mvl61850_do_create,*/ +/* mvl61850_da_create, mvl61850_ln_create_finish,*/ +/* & mvl61850_ln_destroy. New SCL standard */ +/* makes these obsolete. */ +/* 05/13/04 JRB 10 Add SqNumInt16u to MVLU_BASRCB. */ +/* Add define MVL61850_MAX_OBJREF_LEN. */ +/* 04/20/04 JRB 09 Add TRGOPS_BITNUM_* defines. */ +/* 12/17/03 JRB 08 61850-8-1 FDIS changes: */ +/* MVLU_BASRCB: Add TimeofEntry for 61850 BRCB. */ +/* Add OPTFLD_BITNUM_CONFREV = 8. */ +/* Chg OPTFLD_BITNUM_SUBSEQNUM from 8 to 9. */ +/* Increase MVLU_MAX_RPT_OPTS to 11. */ +/* 04/22/03 JRB 07 Add comments to dynamic 61850 type functs. */ +/* 04/17/03 JRB 06 Add mvlu_setup_scan_read. */ +/* 04/04/03 JRB 05 Fix integrity/GI scan code so multiple */ +/* concurrent scans don't corrupt one another. */ +/* u_mvlu_rpt_scan_done deleted. */ +/* 03/13/03 JRB 04 Add funcs for 61850 dynamic type creation. */ +/* Add 61850 URCB support. */ +/* MVLU_RPT_TYPEIDS: Use clearer member names. */ +/* MVLU_RPT_CTRL: Del inclusion_data & all */ +/* MVL_VAR_ASSOC vars. */ +/* MVLU_BASRCB: Add "Resv". */ +/* ucaName: Chg from ptr to array. */ +/* mvlu_proc_rt_type: Chg to use RUNTIME_CTRL. */ +/* TrgOps: Chg to Bvstring (variable len). */ +/* MVLU_RPT_CLIENT: add/delete members. */ +/* Add mvlu_integrity_timeout funct. */ +/* 12/17/02 JRB 03 Chg prefix to "MVLU_STR:" */ +/* Del all *typeId globals, use MVLU_RPT_TYPEIDS*/ +/* 12/14/02 JRB 02 Chg mvlu_create_rpt_ctrl, mvlu_send_report args*/ +/* Add mvlu_integrity_scan_* functions. */ +/* Add callback funct u_mvlu_rpt_time_get. */ +/* Chg OptFlds to BVstring9, add "bitnum" defines*/ +/* Add defs, protos, etc. fof IEC-61850. */ +/* Add ConfRev, EntryID to MVLU_BASRCB */ +/* Add scan_read_ind to MVLU_RPT_CLIENT */ +/* Add MVLU_RPT_TYPEIDS */ +/* Del rptTim_data, rptTim_va, rptTim_typeId */ +/* Del outDat_data, outDat_va, outDat_typeId */ +/* 12/10/02 JRB 01 Created from defs moved here from mvl_defs.h */ +/************************************************************************/ +#ifndef MVL_UCA_INCLUDED +#define MVL_UCA_INCLUDED + +#include "mvl_defs.h" /* This uses many common MVL definitions. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Max number of mandatory and optional variables in IEC/UCA report. + * IEC & UCA share RPT code, so max must accomodate both. + * Includes RptID, OptFlds, SqNum, RptTim, OutDat (DataSetNa), + * & InclusionBitstring (plus BufOvfl, SubSeqNum, MoreSegmentsFollow, + * EntryId, & ConfRev for IEC only). + */ +#define MVLU_MAX_RPT_OPTS 11 + +/* Defines for IEC 61850 control model. */ +#define MVL61850_CTLMODEL_STATUS_ONLY 0 +#define MVL61850_CTLMODEL_DIRECT_NORMAL 1 +#define MVL61850_CTLMODEL_SBO_NORMAL 2 +#define MVL61850_CTLMODEL_DIRECT_ENHANCED 3 +#define MVL61850_CTLMODEL_SBO_ENHANCED 4 + +#define MVL61850_SBOCLASS_OPERATE_ONCE 0 +#define MVL61850_SBOCLASS_OPERATE_MANY 1 + +#define MVL61850_CTLSTATE_UNSELECTED 0 /* SBO only */ +#define MVL61850_CTLSTATE_READY 1 +#define MVL61850_CTLSTATE_WAIT_ACTIVATION_TIME 2 +#define MVL61850_CTLSTATE_WAIT_CHANGE 3 /* enhanced only*/ + +/* renxiaobao ±¨¸æ + ¿ØÖÆ´íÎ󱨸æµÄ¸½¼ÓÔ­ÒòÕï¶Ï(AddCause) + #define NO_ERROR 0 +*/ +#define ServiceError_type 1 /* 7-2±í5Öж¨ÒåµÄ²î´í*/ +#define Blocked_CB 2 /* ±»¿ª¹Ø±ÕËø (Blocked-by-switching-hierarchy) */ +#define Select_fail 3 /* Ñ¡Ôñʧ°Ü (Select-failed)*/ +#define Invalid_Pos 4 /* ²»ÕýȷλÖà (Invalid-position) */ +#define Position_reached 5 /* ¿ª¹ØÒÑ´¦ÓÚÆÚÍûµÄλÖà (Position-reached) */ +#define Parameter_change 6 /* Ö´ÐÐÖвÎÊý¸Ä±ä (Parameter-change-in-execution) */ +#define Step_limit 7 /* ²½ÏÞÖÆ,·Ö½ÓÍ·µÄλÖÃÒÑ´ïµ½ÉÏ/ÏÂÏÞ (Step-limit) */ +#define Blocked_by_Mode 8 /* LN(CSWI¡¢XCBRµÈ)´¦ÓÚ²»ÔÊÐíµÄ²Ù×÷ģʽ (Blocked-by-Mode)*/ +#define Blocked_by_process 9 /* ÓÉÓÚ¹ý³Ì²ãµÄÍⲿʼþ×èÖ¹³É¹¦²Ù×÷ (Blocked-by-process) */ +#define Blocked_by_interlocking 10 /* ÓÉÓÚ¿ª¹ØÉ豸»¥Ëø,±ÕËø¿ØÖƶ¯×÷ (Blocked-by-interlocking) */ +#define Blocked_by_synchrocheck 11 /* ÓÉÓÚ³¬Ê±»òͬÆÚÌõ¼þ²»Âú×ã,ÖÕÖ¹¿ØÖÆ (Blocked-by-synchrocheck) */ +#define Command_already 12 /* ÃüÁîÒѾ­ÔÚÖ´ÐÐÖÐ (Command-already-in-execution)*/ +#define Blocked_by_health 13 /* ±»½¡¿µ×´¿öËù±ÕËø (Blocked-by-health) */ +#define n_of_1_control 14 /* ÓÉÓÚÆäËû¿ØÖƶ¯×÷ÒÑÔËÐÐ,±ÕËø¿ØÖÆ (1-of-n-control) */ +#define Abortion_by_cancel 15 /* ±»Cancel·þÎñÖÐÖ¹ (Abortion-by-cancel) */ +#define Time_limit_over 16 /* ÓÉÓÚ³¬Ê±,ÖÕÖ¹¿ØÖƶ¯×÷ (Time-limit-over) */ +#define Abortion_by_trip 17 /* ÓÉÓÚ±£»¤ÌøÕ¢,ÖÕÖ¹¿ØÖÆ (Abortion-by-trip) */ +#define Object_not_selected 18 /* ¶ÔÏóδ±»Ñ¡Ôñ (Object-not-selected) */ +/*À뿪WaitForChange״̬֮ºó*/ +#define OPERATE_ONCE 0 /* Èç¹ûsboClassΪoperate_once,ÐÂ״̬ΪδѡÔñµÄ*/ +#define OPERATE_MANY 1 /* Èç¹ûsboClassΪoperate_many,ÐÂ״̬Ϊ׼±¸¾ÍÐ÷*/ + +#define WaitForChangeTimer 5000 +/************************************************************************/ +/* UCA SPECIFIC DATA ELEMENTS */ +/************************************************************************/ + +typedef struct mvlu_rd_va_ctrl + { + MVL_IND_PEND *indCtrl; + MVLAS_RD_VA_CTRL *rdVaCtrl; + RUNTIME_TYPE *rt; +#if defined(MVL_UCA) +#if defined(MVL_XNAME) + ST_CHAR xName[MAX_IDENT_LEN+1]; +#endif + ST_CHAR *primData; + ST_RTREF primRef; + ST_UINT prim_num; /* index to data */ + ST_UINT prim_offset_base; /* mem offset from start of "base" var */ +#endif /* defined(MVL_UCA) */ + } MVLU_RD_VA_CTRL; + +typedef struct mvlu_wr_va_ctrl + { + MVL_IND_PEND *indCtrl; + MVLAS_WR_VA_CTRL *wrVaCtrl; + RUNTIME_TYPE *rt; +#if defined(MVL_UCA) +#if defined(MVL_XNAME) + ST_CHAR xName[MAX_IDENT_LEN+1]; +#endif + ST_CHAR *primData; + ST_RTREF primRef; + ST_UINT prim_num; /* index to data */ + ST_UINT prim_offset_base; /* mem offset from start of "base" var */ +#endif /* defined(MVL_UCA) */ + } MVLU_WR_VA_CTRL; + +ST_VOID mvlu_wr_prim_done (MVLU_WR_VA_CTRL *mvluWrVaCtrl, ST_RET rc); +ST_VOID mvlu_rd_prim_done (MVLU_RD_VA_CTRL *mvluRdVaCtrl, ST_RET rc); +ST_VOID mvlu_read_ind (MVL_IND_PEND *indCtrl); + +/* These function pointers are invoked to initialize the va->data */ +/* element for each VariableAssociation required to handle the MMS */ +/* indication. */ + +extern ST_VOID(*mvluAsyncWrIndFun)(struct mvlu_wr_va_ctrl *mvluWrVaCtrl); + +/* Alternate leaf handler function pointers */ +extern ST_VOID (*u_mvlu_leaf_rd_ind_fun)(MVLU_RD_VA_CTRL *mvluRdVaCtrl); +extern ST_VOID (*u_mvlu_leaf_wr_ind_fun)(MVLU_WR_VA_CTRL *mvluWrVaCtrl); + +/* Finding and setting leaf access parameters */ +RUNTIME_TYPE *mvlu_find_rt_leaf (ST_INT type_id, ST_CHAR *leafName); + +#define MVLU_SET_RD_FUN 0x01 +#define MVLU_SET_WR_FUN 0x02 +#define MVLU_SET_REF 0x04 +#define MVLU_SET_ALL (MVLU_SET_RD_FUN | MVLU_SET_WR_FUN | MVLU_SET_REF) + +ST_RET mvlu_set_leaf_param (ST_INT setFlags, ST_CHAR *leafName, + ST_RTINT rdIndFunIndex, ST_RTINT wrIndFunIndex, + ST_RTREF ref); + + +/************************************************************************/ +/************************************************************************/ +/* Leaf Access Function Tables. To be supplied by the user. */ + +/* Comment the following line out to compile out the Foundry supplied */ +/* Leaf Access function pointer tables, so custom tables can be used */ +/*#define MVLU_USR_FUN_TBLS */ + +/* Remove this MVLU_LEAF_FUN_LOOKUP_ENABLE define to save memory, + * but ONLY IF NOT mapping leaf functions at run-time (i.e. not calling + * mvlu_set_leaf_param_name or mvlu_find_rd(wr)_ind_fun_index). + * NOTE: this define is required if SCL configuration is used. + */ +#define MVLU_LEAF_FUN_LOOKUP_ENABLE + +typedef struct + { +#if defined MVLU_LEAF_FUN_LOOKUP_ENABLE + ST_CHAR *fun_name; +#endif + ST_VOID (*fun_ptr) (MVLU_RD_VA_CTRL *rdCtrl); + } MVLU_RD_FUN_INFO; +extern MVLU_RD_FUN_INFO mvluRdFunInfoTbl[]; +extern ST_INT mvluNumRdFunEntries; + +typedef struct + { +#if defined MVLU_LEAF_FUN_LOOKUP_ENABLE + ST_CHAR *fun_name; +#endif + ST_VOID (*fun_ptr) (MVLU_WR_VA_CTRL *wrCtrl); + } MVLU_WR_FUN_INFO; +extern MVLU_WR_FUN_INFO mvluWrFunInfoTbl[]; +extern ST_INT mvluNumWrFunEntries; + +/* Useful for flexible initialization of leaf function tables */ +#if defined MVLU_LEAF_FUN_LOOKUP_ENABLE +#define _MVLU_LEAF_FUN_INIT(_funName) #_funName, _funName +#else +#define _MVLU_LEAF_FUN_INIT(_funName) _funName +#endif +ST_RTINT mvlu_find_rd_ind_fun_index (ST_CHAR *funName); +ST_RTINT mvlu_find_wr_ind_fun_index (ST_CHAR *funName); + + +/************************************************************************/ + +ST_RET mvlu_set_leaf_param_name (ST_INT setFlags, ST_CHAR *leafName, + ST_CHAR *rdIndFunName, ST_CHAR *wrIndFunName, + ST_CHAR *refString); +ST_RET mvlu_set_leaf_param_name2 (ST_INT base_var_type_id, + ST_INT setFlags, + ST_CHAR *leafName, + ST_CHAR *rdIndFunName, + ST_CHAR *wrIndFunName, + ST_CHAR *refString); +ST_RET mvlu_load_xml_leaf_file (ST_CHAR *fileName); +ST_RET u_mvlu_resolve_leaf_ref (ST_CHAR *leafName, ST_INT *setFlags, + ST_CHAR *refText, ST_RTREF *refOut); + +/* Prefix to use in XML LAP file, or when calling "mvlu_set_leaf_param_name" + * if you want a quoted string to be saved as the Reference. + * Following this is the string to be saved. + * This is used for SBO select, in which case the saved string must be + * the name of the protected element. Foundry and the sample "reference + * resolve leaf" function look for this prefix. + */ +#define MVLU_STRING_REF_PREFIX "MVLU_STR:" + +/* Internal */ +ST_VOID _mvlu_null_read_ind (MVLU_RD_VA_CTRL *mvluRdVaCtrl); +ST_VOID _mvlu_null_write_ind (MVLU_WR_VA_CTRL *mvluWrVaCtrl); + + + +typedef struct + { + ST_CHAR ucaName [MAX_IDENT_LEN+1]; + RUNTIME_TYPE *rt; + ST_INT sortedNum; + ST_INT rtIndex; + } MVLU_UCA_NAME_CTRL; + +ST_RET mvlu_proc_rt_type (ST_CHAR *typeName, RUNTIME_CTRL *rtCtrl, + MVLU_UCA_NAME_CTRL **ucaNamesOut); + +/************************************************************************/ +/************************************************************************/ +/* UCA REPORT CONTROL */ +/************************************************************************/ + +#define MVLU_RPT_NUM_VA_DATA_BUF 3 + +/* TrgOpsvalues, also used as Reason values */ +#define MVLU_TRGOPS_DATA 0x40 +#define MVLU_TRGOPS_QUALITY 0x20 +#define MVLU_TRGOPS_FREEZE 0x10 +#define MVLU_TRGOPS_INTEGRITY 0x08 /* Bit 4 */ +#define MVLU_TRGOPS_GI 0x04 /* Bit 5 */ + +/* OptFlds bit masks */ +#define MVLU_SQNUM_MASK 0x40 +#define MVLU_RPTTIM_MASK 0x20 +#define MVLU_REASONS_MASK 0x10 +#define MVLU_OUTDAT_MASK 0x08 + +/* TrgOps bit numbers for IEC-61850. */ +/* Use "bit" macros (BSTR_BIT_*) to access each individual bit. */ +#define TRGOPS_BITNUM_RESERVED 0 +#define TRGOPS_BITNUM_DATA_CHANGE 1 /* "dchg" in some specs */ +#define TRGOPS_BITNUM_QUALITY_CHANGE 2 /* "qchg" in some specs */ +#define TRGOPS_BITNUM_DATA_UPDATE 3 /* "dupd" in some specs */ +#define TRGOPS_BITNUM_INTEGRITY 4 /* "period" in 61850-6 */ +#define TRGOPS_BITNUM_GENERAL_INTERROGATION 5 + +/* OptFlds bit numbers for IEC-61850. */ +/* Use "bit" macros (BSTR_BIT_*) to access each individual bit. */ +/* NOTE: DATSETNAME in IEC-61850 same as OUTDAT in UCA. */ +/* NOTE: bit numbers 1 thru 4 correspond to the masks MVLU_SQNUM_MASK, */ +/* MVLU_RPTTIM_MASK, MVLU_REASONS_MASK, MVLU_OUTDAT_MASK above. */ +/* Bit masks don't work well beyond 8 bits. */ +#define OPTFLD_BITNUM_RESERVED 0 +#define OPTFLD_BITNUM_SQNUM 1 +#define OPTFLD_BITNUM_TIMESTAMP 2 +#define OPTFLD_BITNUM_REASON 3 +#define OPTFLD_BITNUM_DATSETNAME 4 +#define OPTFLD_BITNUM_DATAREF 5 +#define OPTFLD_BITNUM_BUFOVFL 6 +#define OPTFLD_BITNUM_ENTRYID 7 +#define OPTFLD_BITNUM_CONFREV 8 +#define OPTFLD_BITNUM_SUBSEQNUM 9 /* segmentation in 61850-8-1*/ + +/* Flags to pass as "rcb_type" arg to mvlu_create_rpt_ctrl. */ +/* Saved in "rcb_type" parameter of MVLU_RPT_CTRL. */ +#define RCB_TYPE_UCA 0 +#define RCB_TYPE_IEC_BRCB 1 +#define RCB_TYPE_IEC_URCB 2 + +/* Flags to pass as "buftim_action" arg to mvlu_create_rpt_ctrl. */ +/* Saved in "buftim_action" parameter of MVLU_RPT_CTRL. */ +#define MVLU_RPT_BUFTIM_REPLACE 0 +#define MVLU_RPT_BUFTIM_SEND_NOW 1 + +/* Basic Report Control Block data */ +typedef struct + { + ST_BOOLEAN RptEna; + ST_BOOLEAN Resv; /* Used only for 61850 URCB. */ + ST_CHAR RptID[MVL61850_MAX_RPTID_LEN+1]; + /* NOTE: DatSetNa is shorter for UCA, but bigger buffer shouldn't hurt.*/ + ST_CHAR DatSetNa[MVL61850_MAX_OBJREF_LEN+1]; + struct /* BVstring */ + { + ST_INT16 len_1; + ST_UCHAR data_1[2]; /* BVstring9 - need 2 bytes */ + } OptFlds; + ST_UINT32 BufTim; + ST_UINT16 Trgs; + ST_UINT8 SqNum; /* Used for UCA & 61850 URCB */ + ST_UINT16 SqNumInt16u; /* Used for 61850 BRCB */ + struct /* BVstring */ + { + ST_INT16 len; + ST_UCHAR data[1]; /* BVstring8 - need 1 byte */ + } TrgOps; + ST_UINT32 RBEPd; + ST_UINT32 IntgPd; + ST_UINT32 ConfRev; /* Used only for 61850 BRCB/URCB. */ + ST_UCHAR EntryID[8]; /* Used only for 61850 BRCB (Ostring8). */ + MMS_BTIME6 TimeofEntry; /* Used only for 61850 BRCB. */ + } MVLU_BASRCB; + +/* UCA Report Client control */ +typedef struct + { + DBL_LNK l; /* Internal use */ + MVL_NET_INFO *netInfo; + struct mvlu_rpt_ctrl *rpt_ctrl; /* report control */ + MVLU_BASRCB basrcb; /* report data */ + +/* Transmit timing control */ + ST_DOUBLE next_integ_rpt_time; + ST_DOUBLE next_rbe_rpt_time; + ST_DOUBLE buf_time_done; + ST_BOOLEAN integ_scan_in_progress; + +/* Data state control */ + ST_UINT16 numTrgs; + ST_UINT8 *reasons_data; /* array of reasons */ + ST_UINT8 *changed_flags; /* bitstring */ + ST_UINT8 *segmented_inclusion;/* inclusion bitstring for segmented rpt*/ + MVL_IND_PEND *scan_read_ind; /* Indication to pass to u_mvl_read_ind for scan*/ + } MVLU_RPT_CLIENT; + +/************************************************************************/ +/* Structures for saving Buffered report data. */ +/************************************************************************/ +/* VAR_DATA - data for one variable of a Report Dataset. */ +typedef struct var_data + { + ST_VOID *data_ptr; /* ptr to raw MMS Variable data */ + /* (allocated) */ + ST_INT data_len; /* length of raw MMS Variable data */ + ST_UINT8 reason_for_incl; /* reason for inclusion */ + } VAR_DATA; + +/* BUFLIST_ENTRY - data for one buffered rpt (stored on linked list). */ +/* Data in this struct usually changes with each Report, so must be */ +/* saved in the buffer. Other data may be taken directly from the RCB */ +/* when a Report is sent. */ +typedef struct buflist_entry + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct buflist_entry *next; /* CRITICAL: DON'T MOVE. */ + struct buflist_entry *prev; /* CRITICAL: DON'T MOVE. */ + ST_UCHAR EntryID[8]; /* Rpt EntryID (Ostring8) */ + MMS_BTIME6 TimeOfEntry; /* Rpt TimeOfEntry */ + ST_INT num_var; /* Num of var in var_data array */ + VAR_DATA *var_data; /* Ptr to array of structs, one for each*/ + /* var (allocated) */ + ST_INT *asn1_len_array; /* Array of ASN.1 lengths, one for each */ + /* var in Dataset (allocated) */ + ST_INT cur_va_index; /* Index to next var in Dataset to send */ + /* (used when segmenting) */ + ST_UINT16 SubSeqNum; /* SubSeqNum of next segment to send */ + } BUFLIST_ENTRY; + +/* MVL61850_BRCB_CTRL */ +typedef struct + { + /* Optional parameters to send in rpt (if appropriate OptFlds bit set).*/ + ST_BOOLEAN BufOvfl; + /* Internal parameters */ + BUFLIST_ENTRY *rpt_list; /* Linked list of buffered reports */ + BUFLIST_ENTRY *rpt_list_next; /* Next rpt to send from "rpt_list" */ + /* (NULL if list empty or all sent) */ + ST_INT rpt_count; /* count of entries in "rpt_list" */ + /* once buffer's full, shouldn't change much*/ + ST_UINT rpts_lost_count; /* # rpts lost because of overflow */ + ST_INT rpts_sent_total;/*renxiaobao ±¨¸æ*/ + ST_INT brcb_bufsize; + ST_INT cur_bufsize; + ST_BOOLEAN enabled_once; /* TRUE if BRCB was enabled at least once*/ + ST_UCHAR lastSentEntryID[8]; + MMS_BTIME6 lastSentTimeOfEntry; + } MVL61850_BRCB_CTRL; + +/* TypeIDs for special report types created by mvlu_rpt_init_types. */ +typedef struct + { + ST_INT mmsbool; /* named so not confused with C++ 'bool' type */ + ST_INT int8u; /* for SqNum */ + ST_INT int16u; + ST_INT int32u; + ST_INT vstring65; /* for RptID */ + ST_INT btime6; /* for EntryTime */ + ST_INT ostring8; /* for EntryID */ + ST_INT vstring32; /* for RptId */ + ST_INT bvstring6; /* for TrgOps (IEC) */ + ST_INT bvstring8; /* for OptFlds,TrgOps (UCA) */ + ST_INT bvstring10; /* for OptFlds (IEC) */ + ST_INT bstr6; /* for Reason (IEC) */ + ST_INT bstr8; /* for Reason (UCA) */ + ST_INT vstring129; /* for ObjectReference (IEC) */ + } MVLU_RPT_TYPEIDS; + +/* For backward compatibility ... do not use */ +#define MVLU_SEQNUM_MASK MVLU_SQNUM_MASK + +#define MVLU_MAX_RPTID_LEN 65 +#define MVLU_MAX_OUTDAT_LEN 65 + + +/* MVLU_RPT_CTRL */ +typedef struct mvlu_rpt_ctrl + { + DBL_LNK l; /* Internal use */ + +/* Active clients */ + +/* NOTE: "only_client" for 61850 only. */ + MVLU_RPT_CLIENT only_client; /* exactly 1. Don't need list */ + +/* NOTE: "num_rpt_clients", "rpt_client_list", "common_basrcb" for UCA only.*/ + ST_INT num_rpt_clients; + MVLU_RPT_CLIENT *rpt_client_list; + +/* basrcb data for passive read clients */ + MVLU_BASRCB common_basrcb; + ST_CHAR *basrcb_name; + +/* Used in read/write indication functions in finding the report ctrl */ + RUNTIME_TYPE *rcbRtHead; + MVL_VAR_ASSOC *base_va; + +/* Used to support different report schemes */ + ST_INT rcb_type; /* RCB_TYPE_UCA, RCB_TYPE_IEC_BRCB, etc. */ + +/* Action to be taken if var changes twice before buftim expires */ + ST_INT buftim_action; /* MVLU_RPT_BUFTIM_REPLACE/SEND_NOW */ + +/* The information below is used internally by MVLU */ + MVL_NVLIST_CTRL *dsNvl; /* The base dataSet for the report */ + MVL_NVLIST_CTRL rptNvl; /* The NVL used to send the InfoRpt */ + RUNTIME_TYPE incRt; /* Used in building the inclusion_va */ + ST_INT maxNumRptVars; /* Max vars allowed in report. */ + MVLU_RPT_TYPEIDS rpt_typeids; /* Types needed for reports. */ + ST_INT inclusion_typeid; /* One more special type. */ + MVL61850_BRCB_CTRL brcbCtrl; /* Used only for 61850 BRCB. */ + ST_DOUBLE scan_rate; /* Scan rate in milliseconds */ + ST_DOUBLE next_scan_start; /* Time for next scan */ + } MVLU_RPT_CTRL; + +extern MVLU_RPT_CTRL *mvlu_rpt_ctrl_list; /* List of only UCA RCBs.*/ +extern MVLU_RPT_CTRL *mvl61850_rpt_ctrl_list; /* List of only 61850 RCBs.*/ + +/* UCA VA Scan Control */ +typedef struct + { + DBL_LNK l; /* Internal use */ + ST_BOOLEAN enable; + ST_DOUBLE scan_period; + ST_DOUBLE next_scan_start; + ST_BOOLEAN saturated; + ST_INT num_va_changes; + + ST_INT num_scan_va; + MVL_VAR_ASSOC **scan_va; + ST_INT num_va_read_pend; + + MVL_IND_PEND indCtrl; + MVL_COMM_EVENT commEvent; + MVL_SCOPE *scan_va_scope; /* ptr to array of structs. */ + ST_VOID *usr; /* user assignable pointer to use in scan callbacks*/ + } MVLU_RPT_SCAN_CTRL; +extern MVLU_RPT_SCAN_CTRL *mvlu_rpt_scan_list; + + +/* Report Service */ +ST_VOID mvlu_rpt_service (ST_VOID); + +/* Report Variable Scanning */ +MVLU_RPT_SCAN_CTRL *mvlu_rpt_create_scan_ctrl (ST_INT numScanVa); +MVLU_RPT_SCAN_CTRL *mvlu_rpt_create_scan_ctrl2 ( + MVL_NVLIST_CTRL *nvl, + ST_RET (*scan_done_fun) (struct mvl_ind_pend *ind_pend), + ST_UINT report_scan_rate); /* report scan rate (millisec) */ +ST_VOID mvlu_rpt_destroy_scan_ctrl (MVLU_RPT_SCAN_CTRL *scanCtrl); +ST_VOID mvlu_rpt_va_scan (ST_VOID); +ST_VOID mvlu_rpt_scan_read (MVLU_RPT_SCAN_CTRL *scanCtrl); + +/* Asynchronous Change Reporting */ +ST_VOID mvlu_rpt_va_change (MVL_VAR_ASSOC *va, + ST_UCHAR reason, + ST_VOID *new_data); + +/* Creating Report Dataset NVL's */ +MVL_NVLIST_CTRL *mvlu_derive_rpt_ds (ST_CHAR *domName, ST_CHAR *nvlName, + ST_INT numNodes, ST_CHAR **nodeNames); + +/* Structure Element name derivation */ +ST_RET mvlu_derive_ds_va_names (ST_CHAR *domName, + ST_INT numNodes, ST_CHAR **nodeNames, + ST_INT *numObjNamesOut, + OBJECT_NAME **objNameTblOut, + ST_CHAR **nameBufOut); + + +/* Report Control Create/Free */ +/* NOTE: The "buftim_action" arg may be set to + * MVLU_RPT_BUFTIM_REPLACE or MVLU_RPT_BUFTIM_SEND_NOW. + * This arg is only used in the case when buffer + * time (BufTim) is used, and a second data change is detected for the + * same "va", before the BufTim expires. To satisfy the requirements of + * IEC61850-7-2, the caller must set this flag to indicate whether to + * replace the buffered value with the new value and continue timing + * (MVLU_RPT_BUFTIM_REPLACE), OR to send a report immediately with the + * buffered value, save the new value in the buffer, and restart the timer + * (MVLU_RPT_BUFTIM_SEND_NOW). + */ +MVLU_RPT_CTRL *mvlu_create_rpt_ctrl (ST_CHAR *basrcbName, + MVL_NVLIST_CTRL *dsNvl, + MVL_VAR_ASSOC *base_va, + ST_INT rcb_type, + ST_INT buftim_action, /* MVLU_RPT_BUFTIM_* */ + ST_INT brcb_bufsize, /* for BRCB only */ + ST_UINT32 ConfRev); /* for BRCB/URCB only */ +ST_VOID mvlu_free_rpt_ctrl (MVLU_RPT_CTRL *rptCtrl); + +/* Main reporting functions for IEC 61850 only. */ +MVLU_RPT_CTRL *mvl61850_create_rpt_ctrl (ST_CHAR *basrcbName, + MVL_NVLIST_CTRL *dsNvl, + MVL_VAR_ASSOC *base_va, + ST_INT rcb_type, + ST_INT buftim_action, /* MVLU_RPT_BUFTIM_* */ + ST_INT brcb_bufsize, /* for BRCB only */ + ST_UINT32 ConfRev); /* for BRCB/URCB only */ +ST_VOID mvl61850_free_rpt_ctrl (MVLU_RPT_CTRL *rptCtrl); +ST_VOID mvl61850_rpt_service (char *dom,char CHG); +ST_RET mvl61850_rpt_dataset_create (MVLU_RPT_CTRL *rptCtrl, + MVL_NVLIST_CTRL *dsNvl); +ST_VOID mvl61850_rpt_dataset_destroy (MVLU_RPT_CTRL *rptCtrl); + +/************************************************************************/ +/* mvlu_integrity_scan_destroy */ +/* Free temporary MVL_IND_PEND allocated by mvlu_integrity_scan_read. */ +/************************************************************************/ +ST_VOID mvlu_integrity_scan_destroy (MVL_IND_PEND *indCtrl); + +/* + * mvlu_integrity_scan_read + * This function "BEGINS" the scan of ALL data for one Report DataSet (NVL). + * It is called automatically when an Integrity Report or a + * General Interrogation Report needs to be sent. This is much more + * efficient than constantly scanning. + * - It allocates & initializes a temporary MVL_IND_PEND structure. + * - It calls "u_mvl_read_ind" to begin the scan. + * - The scan may complete synchronously or asynchronously. + * - When the scan completes, the funct pointed to by "scan_done_fun" arg + * is called to build the report and cleanup. + * CRITICAL: Function pointed to by "scan_done_fun" must call + * "mvlu_integrity_scan_destroy" to free temporary MVL_IND_PEND struct. + */ + +ST_VOID mvlu_integrity_scan_read (MVLU_RPT_CLIENT *rptClient, + ST_VOID (*scan_va_done_fun)(MVL_IND_PEND *indCtrl, + MVL_VAR_ASSOC *va), + ST_RET (*scan_done_fun)(MVL_IND_PEND *indCtrl) + ); + +MVL_IND_PEND *mvlu_setup_scan_read (MVL_NVLIST_CTRL *nvl, + ST_VOID (*scan_va_done_fun)(MVL_IND_PEND *indCtrl, + MVL_VAR_ASSOC *va), + ST_RET (*scan_done_fun)(MVL_IND_PEND *indCtrl) + ); + +/************************************************************************/ +/* mvlu_integrity_timeout */ +/* Check for Integrity period timeout. If timeout occurred, start */ +/* integrity scan. */ +/* RETURNS: SD_TRUE if IntgPd is set and timeout occurred */ +/* SD_FALSE otherwise */ +/************************************************************************/ +ST_RET mvlu_integrity_timeout (MVLU_RPT_CLIENT *rptClient, ST_DOUBLE timeNow); + +/* Pointer to one of these functions passed to "mvlu_integrity_scan_read", + * saved in "usr_done_fun" in MVL_IND_PEND struct. Called when scan completes. + */ +ST_RET mvlu_integrity_scan_done (MVL_IND_PEND *indCtrl); +ST_RET mvlu_gi_scan_done (MVL_IND_PEND *indCtrl); + +/* Pointer to one of these functions passed to "mvlu_integrity_scan_read", + * stored in global var. Called when each va read completes. + */ +ST_VOID mvlu_integrity_scan_va_done (MVL_IND_PEND *indCtrl, MVL_VAR_ASSOC *va); +ST_VOID mvlu_gi_scan_va_done (MVL_IND_PEND *indCtrl, MVL_VAR_ASSOC *va); + +extern ST_VOID (*_mvlu_rpt_disconnect_rcvd_fun)(MVL_NET_INFO *netInfo); + +MVL_NVLIST_CTRL *mvlu_resolve_uca_nvl (MVL_NVLIST_CTRL *ucaNvl, + OBJECT_NAME *scopeSel); + +/* Defines for UCA/IEC report type, "rpt_type" arg to "mvlu_send_report"*/ +#define MVLU_RPT_TYPE_INTEGRITY_OR_GI 0 +#define MVLU_RPT_TYPE_RBE 1 + +ST_RET mvlu_send_report (MVLU_RPT_CLIENT *rptClient, ST_INT rpt_type); + +/* u_mvlu_rpt_time_get - User callback function to set accurate time + * that UCA/IEC report is built, called by "mvlu_send_report" or + * "mvl61850_rcb_build" when report is being built. + */ +ST_VOID u_mvlu_rpt_time_get (MMS_BTIME6 *TimeOfEntry); + +/* Misc. Helper Functions */ +ST_INT mvlu_rpt_get_va_index (MVLU_RPT_CTRL *rptCtrl, MVL_VAR_ASSOC *va); +MVLU_BASRCB *_mvlu_get_rd_rcb (MVLU_RD_VA_CTRL *mvluRdVaCtrl, + MVLU_RPT_CLIENT **rptClientOut); +MVLU_BASRCB *_mvlu_get_wr_rcb (MVLU_WR_VA_CTRL *mvluWrVaCtrl, + MVLU_RPT_CLIENT **rptClientOut); +MVLU_BASRCB *mvl61850_get_rcb (MVL_VAR_ASSOC *baseVa, + RUNTIME_TYPE *rt, + MVLU_RPT_CLIENT **rptClientOut); + +ST_VOID _mvlu_rpt_disconnect_rcvd (MVL_NET_INFO *netInfo); +ST_RET mvlu_rpt_find_typeids (MVLU_RPT_TYPEIDS *rpt_typeids); +ST_RET mvlu_rpt_rcb_type_find (ST_INT type_id, ST_CHAR *basrcbName, + RUNTIME_TYPE **rcbHeadOut, ST_INT *numRtOut); + + +ST_RET mvlu_find_uca_var (RUNTIME_TYPE **rtIo, ST_INT *numRtIo, + ST_CHAR *varName); + + +/************************************************************************/ +/************************************************************************/ +/* SBO HANDLING ELEMENTS */ + +#define SBO_SELECT_TIMEOUT 30 /* seconds */ +#define MAX_NUM_SBO_PEND 10 /* Number of SBOs to be pending */ +#define MAX_SBO_NAME_SIZE 66 + +typedef struct mvl_sbo_ctrl + { + ST_BOOLEAN in_use; /* control element management */ + ST_INT ctlState; /* Control state (MVL61850_CTLSTATE_*) */ + ST_BOOLEAN use_ms_timer; /* if TRUE, use expire_time_ms below*/ + ST_CHAR sbo_var[MVL61850_MAX_OBJREF_LEN+1]; /* ObjRef of "Oper" attr*/ + MVL_NET_INFO *net_info; /* Connection ID */ + time_t expire_time; /* SELECT expiration time */ + ST_DOUBLE expire_time_ms; /* SELECT expiration time in ms */ + ST_INT8 ctlModel; /* sbo-with-normal-security, etc*/ + ST_INT8 sboClass; /* operate-once or operate-many */ + /* renxiaobao ¿ØÖÆ*/ + double Oper_WaitForChangeTimer; + short Oper_data_len; + void *Oper_map_entry; + void *Oper_ctlVal; + void *Oper_stVal; + MVL61850_LAST_APPL_ERROR LastApplError; + } MVL_SBO_CTRL; + + +ST_VOID u_mvl_sbo_operate (MVL_SBO_CTRL *sboSelect, + MVLU_WR_VA_CTRL *mvluWrVaCtrl); + +ST_VOID mvlu_clr_pend_sbo (MVL_NET_INFO *net_info); + +MVL_SBO_CTRL *mvlu_sbo_chk_state (ST_CHAR *sboName, + MVL_NET_INFO *net_info); +ST_VOID mvlu_sbo_chk_timers (ST_VOID); +ST_VOID mvlu_sbo_ctrl_free (MVL_SBO_CTRL *sboCtrl); +MVL_SBO_CTRL *initSboCtrl (MVL_NET_INFO *net_info, + ST_CHAR *sbo_name, + ST_UINT32 sboTimeout, + ST_BOOLEAN use_ms_timer); + + +/************************************************************************/ +/************************************************************************/ +/* IEC-61850 functions */ +/************************************************************************/ + +/* + * mvl61850_brcb_client_service + * + * Check the BRCB state and, if necessary, + * encode, queue, AND/OR send IEC "Buffered" reports. + */ +ST_VOID mvl61850_brcb_client_service (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + ST_DOUBLE timeNow); + +/** + * mvl61850_urcb_client_service + * + * Check the URCB state and, if necessary, + * encode AND send IEC "Unbuffered" reports. + */ +ST_VOID mvl61850_urcb_client_service (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + ST_DOUBLE timeNow); + +ST_RET mvlu_rpt_ready (MVLU_RPT_CLIENT *rptClient, ST_INT rpt_type); +ST_RET mvl61850_urcb_rpt_send (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + ST_INT rpt_type); +ST_RET mvl61850_brcb_rpt_save (MVLU_RPT_CLIENT *rptClient); +ST_RET mvl61850_brcb_rpt_send (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + BUFLIST_ENTRY *buflist_entry, + ST_BOOLEAN *all_seg_done); +ST_VOID mvl61850_brcb_entryid_init (MVLU_RPT_CTRL *rptCtrl, ST_UINT8 *EntryID); + +ST_VOID mvl61850_brcb_rpt_lists_clean (MVL61850_BRCB_CTRL *brcbCtrl); + +/* Internal IEC 61850 reporting functions (not called by user). */ +ST_RET mvl61850_mk_rptid (MVLU_RPT_CTRL *rptCtrl, ST_CHAR *RptID, size_t max_len); +ST_VOID mvl61850_mk_dataref (MVL_VAR_ASSOC *va, MVL_SCOPE *va_scope, + ST_CHAR *databuf, ST_INT maxlen); +ST_VOID mvl61850_rcb_cleanup (MVLU_RPT_CLIENT *rptClient); +ST_RET mvl61850_brcb_rpt_set_entryid (MVLU_RPT_CLIENT *rptClient, ST_UCHAR *EntryID); +ST_VOID mvl61850_rcb_chk_state (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + ST_DOUBLE timeNow); +ST_RET mvl61850_integrity_timeout (MVLU_RPT_CLIENT *rptClient, ST_DOUBLE timeNow); +ST_BOOLEAN chk_seg_needed (MVLU_RPT_CLIENT *rptClient, + ST_INT *asn1_len_array, + ST_INT cur_va_index, /* input arg */ + ST_INT *next_va_index); /* output arg */ + +/************************************************************************/ +/* IEC 61850 "Control Model" functions. */ +/************************************************************************/ +ST_VOID mvl61850_sbo_create_sboname (MVL_VAR_ASSOC *va, MVL_SCOPE *va_scope, + ST_CHAR *sboName); + +MVL_SBO_CTRL *mvl61850_ctl_chk_sbo (MVLU_RD_VA_CTRL *mvluRdVaCtrl); +MVL_SBO_CTRL *mvl61850_ctl_chk_sbow (MVLU_WR_VA_CTRL *mvluWrVaCtrl); + +ST_RET mvl61850_ctl_chk_state (MVLU_WR_VA_CTRL *mvluWrVaCtrl); + +ST_RET mvl61850_ctl_lastapplerror_create (ST_VOID); +ST_RET mvl61850_ctl_lastapplerror_send (MVL_NET_INFO *net_info, + MVL61850_LAST_APPL_ERROR *last_appl_error); +ST_RET mvl61850_ctl_command_termination (MVL_NET_INFO *net_info, ST_CHAR *oper_ref, + ST_RET status, MVL61850_LAST_APPL_ERROR *last_appl_error); +ST_VOID mvl61850_ctl_req_done (MVLAS_WR_VA_CTRL *wrVaCtrl, MVL_NET_INFO *net_info); + +/* These callback functions must be supplied by user. */ +ST_VOID u_mvl61850_ctl_oper_begin (ST_CHAR *oper_ref); +/*renxiaobao ¿ØÖÆ*/ +/*ST_VOID u_mvl61850_ctl_oper_end (MVL_NET_INFO *net_info, ST_CHAR *oper_ref, MVL_VAR_ASSOC *base_var);*/ +ST_VOID u_mvl61850_ctl_oper_end (MVL_NET_INFO *net_info, ST_CHAR *oper_ref, MVL_VAR_ASSOC *base_var, + void *ctlVal,void *stVal,short len,void *map_entry,MVL61850_LAST_APPL_ERROR *LastApplError); + +ST_RET mvl61850_mkname_ctlmodel (ST_CHAR *var_name, ST_CHAR *flatname, size_t flatname_len); + +/************************************************************************/ +/* Miscellaneous helper functions */ +/************************************************************************/ +ST_VOID mvlu_trim_branch_name (ST_CHAR *branch_name); +ST_RET mvlu_find_comp_type (ST_INT base_type_id, ST_CHAR *flat_name, + RUNTIME_TYPE **sub_rt_type, /* out */ + ST_INT *sub_rt_num); /* out */ + +ST_RET mvlu_get_leaf_val_int8 (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_INT8 *data); +ST_RET mvlu_get_leaf_val_int32 (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_INT32 *data); +ST_RET mvlu_get_leaf_val_int_any (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_INT32 *data); +ST_RET mvlu_get_leaf_val_uint32 (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_UINT32 *data); +ST_RET mvlu_get_leaf_val_boolean (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_BOOLEAN *data); +ST_RET mvlu_get_leaf_val_bvstring (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, + MMS_BVSTRING *data, ST_INT max_num_bits); +ST_VOID *mvlu_get_leaf_data_ptr (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, RUNTIME_TYPE **rt_type); +ST_RET _rcb_writable (MVLU_BASRCB *rcb, MVLU_RPT_CLIENT *rptClient, + MVLU_WR_VA_CTRL *mvluWrVaCtrl); +ST_RET mvl61850_objref_create (ST_CHAR *objName, + MVL_SCOPE *objScope, + ST_CHAR *objRef); /* ptr to ObjectReference */ + +/************************************************************************/ +/* Global variables. */ +/************************************************************************/ +extern MVL_SBO_CTRL sbo_pool[]; /* array of SBO control structures. */ + +/* This function pointer called BEFORE all write leaf functions. */ +/* NOTE: called only for complex variables (struct or array). */ +extern ST_RET (*u_mvl_wr_ind_var_start)(MVL_IND_PEND *indCtrl, + MVLAS_WR_VA_CTRL *wrVaCtrl); /* current var in list of var */ + +/* This function pointer called AFTER all write leaf functions. */ +/* NOTE: called only for complex variables (struct or array). */ +extern ST_RET (*u_mvl_wr_ind_var_end)(MVL_IND_PEND *indCtrl, + MVLAS_WR_VA_CTRL *wrVaCtrl); /* current var in list of var */ + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* MVL_UCA_INCLUDED */ + diff --git a/mmslib/inc/ntddosi.h b/mmslib/inc/ntddosi.h new file mode 100644 index 0000000..0cf01a6 --- /dev/null +++ b/mmslib/inc/ntddosi.h @@ -0,0 +1,114 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : osillc.h */ +/* PRODUCT(S) : OSI LLC NDIS 3.0 Device Driver for NT */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/13/98 DSF 05 Added SeqNumber field to PACKET_BLOCK */ +/* 05/07/98 DSF 04 The size of PACKET_BLOCK is now user-settable*/ +/* 06/19/97 DSF 03 Added Stats */ +/* 09/10/96 DSF 02 Used Length field in SET_MULTI */ +/* 05/22/96 DSF 01 Initial Release */ +/* */ +/************************************************************************/ + +#ifndef __NTDDOSILLC +#define __NTDDOSILLC + +#if defined (_NTDDK_) +#include +#else +#include +#endif + +#pragma pack(1) + +// +// standard 802.3 defines (not defined elsewhere) +// +#define ETH_LENGTH_OF_HEADER 14 +#define ETH_MINIMUM_LENGTH_OF_DATA 46 +#define ETH_MAXIMUM_LENGTH_OF_DATA 1500 +#define ETH_LENGTH_OF_FRAME 1514 + + +// max number of packets that will be returned at a time +#define OSILLC_MAX_RXPACKETS 10 + +typedef struct _NT_PACKET_DATA +{ + ULONG Length; + UCHAR Data[ETH_LENGTH_OF_FRAME]; +} NT_PACKET_DATA, * PNT_PACKET_DATA; + +typedef struct _NT_PACKET_BLOCK +{ + ULONG NumberOfPackets; + ULONG SeqNumber; + NT_PACKET_DATA PacketData[1]; +} NT_PACKET_BLOCK, * PNT_PACKET_BLOCK; + + +#if 0 +typedef struct _NT_ARM_EVENT +{ + UINT Status; +} NT_ARM_EVENT; +#endif + + +typedef struct _PACKET_OID_DATA +{ + ULONG Oid; + ULONG Length; + UCHAR Data[1]; +} PACKET_OID_DATA, * PPACKET_OID_DATA; + + +#if !defined (GET_STATS_DEFINED) +typedef struct _GET_STATS +{ + ULONG XmitOk; + ULONG RcvOk; + ULONG XmitError; + ULONG RcvError; + ULONG RcvUnknown; + ULONG XmitInd; + ULONG RcvInd; + ULONG AllocError; +} GET_STATS; + +#define GET_STATS_DEFINED +#endif + +// base for IOCTLs +#define FILE_DEVICE_PROTOCOL 0x8000 + +#define OSILLC_CONTROL_CODE(request, method) \ + CTL_CODE(FILE_DEVICE_PROTOCOL, request, method, FILE_ANY_ACCESS) + +#define IOCTL_OSILLC_QUERY_OID OSILLC_CONTROL_CODE(0, METHOD_BUFFERED) +#define IOCTL_OSILLC_SET_OID OSILLC_CONTROL_CODE(1, METHOD_BUFFERED) +#define IOCTL_OSILLC_GET_STATS OSILLC_CONTROL_CODE(2, METHOD_BUFFERED) +#define IOCTL_OSILLC_SET_EVENT OSILLC_CONTROL_CODE(3, METHOD_BUFFERED) +#define IOCTL_OSILLC_CLEAR_EVENT OSILLC_CONTROL_CODE(4, METHOD_BUFFERED) +#define IOCTL_OSILLC_GET_MACNAME OSILLC_CONTROL_CODE(5, METHOD_BUFFERED) +#define IOCTL_OSILLC_ARM_EVENT OSILLC_CONTROL_CODE(6, METHOD_BUFFERED) +#define IOCTL_OSILLC_RESET OSILLC_CONTROL_CODE(7, METHOD_BUFFERED) + +#define IOCTL_OSILLC_GET_PACKETS OSILLC_CONTROL_CODE(8, METHOD_OUT_DIRECT) +#define IOCTL_OSILLC_SEND_PACKETS OSILLC_CONTROL_CODE(9, METHOD_IN_DIRECT) + +#endif + +#pragma pack() diff --git a/mmslib/inc/osillc.h b/mmslib/inc/osillc.h new file mode 100644 index 0000000..b433d5c --- /dev/null +++ b/mmslib/inc/osillc.h @@ -0,0 +1,97 @@ +//--------------------------------------------------------------------------- +// +// File: osillc.h +// +// Copyright (c) 1998,1999 SISCO, Inc. All rights reserved. +// +// Description: Driver external definitions. +// +// Author: A. Shajenko/Stratos Technology, Inc. +// +// History: +// 13-Sep-98 A. Shajenko Implemented. +// +//--------------------------------------------------------------------------- + +#ifndef _OSILLC_H +#define _OSILLC_H + +#if defined (_NTDDK_) +#include +#else +#include +#endif + +//////////////////////////////////////////////////////////////////////////////////// + +#pragma pack(1) + +// +// standard 802.3 defines (not defined elsewhere) +// +#define ETH_LENGTH_OF_HEADER 14 +#define ETH_MINIMUM_LENGTH_OF_DATA 46 +#define ETH_MAXIMUM_LENGTH_OF_DATA 1500 +#define ETH_LENGTH_OF_FRAME 1514 + + +// max number of packets that will be returned at a time +#define OSILLC_MAX_RXPACKETS 10 + +typedef struct _OSILLC_PACKET_DATA +{ + ULONG Length; + UCHAR Data[ETH_LENGTH_OF_FRAME]; +} OSILLC_PACKET_DATA, * POSILLC_PACKET_DATA; + +typedef struct _OSILLC_PACKET_BLOCK +{ + ULONG NumberOfPackets; + ULONG SeqNumber; + OSILLC_PACKET_DATA PacketData[OSILLC_MAX_RXPACKETS]; +} OSILLC_PACKET_BLOCK, * POSILLC_PACKET_BLOCK; + + +typedef struct _OSILLC_OID_DATA +{ + ULONG Oid; + ULONG Length; + ULONG BytesProcessed; + ULONG BytesNeeded; + ULONG Status; + UCHAR Data[1]; +} OSILLC_OID_DATA, * POSILLC_OID_DATA; + +typedef struct _OSILLC_GET_STATS +{ + ULONG XmitOk; + ULONG RcvOk; + ULONG XmitError; + ULONG RcvError; + ULONG RcvUnknown; + ULONG XmitInd; + ULONG RcvInd; + ULONG AllocError; +} OSILLC_GET_STATS, * POSILLC_GET_STATS; + +// base for IOCTLs +#define FILE_DEVICE_PROTOCOL 0x8000 + +#define OSILLC_CONTROL_CODE(request, method) \ + CTL_CODE(FILE_DEVICE_PROTOCOL, request, method, FILE_ANY_ACCESS) + +#define IOCTL_OSILLC_QUERY_OID OSILLC_CONTROL_CODE(0, METHOD_BUFFERED) +#define IOCTL_OSILLC_SET_OID OSILLC_CONTROL_CODE(1, METHOD_BUFFERED) +#define IOCTL_OSILLC_GET_STATS OSILLC_CONTROL_CODE(2, METHOD_BUFFERED) +#define IOCTL_OSILLC_GET_MACNAME OSILLC_CONTROL_CODE(3, METHOD_BUFFERED) +#define IOCTL_OSILLC_RESET OSILLC_CONTROL_CODE(4, METHOD_BUFFERED) + +#define IOCTL_OSILLC_BIND OSILLC_CONTROL_CODE(10, METHOD_BUFFERED) +#define IOCTL_OSILLC_UNBIND OSILLC_CONTROL_CODE(11, METHOD_BUFFERED) +#define IOCTL_OSILLC_WRITE OSILLC_CONTROL_CODE(12, METHOD_BUFFERED) +#define IOCTL_OSILLC_READ OSILLC_CONTROL_CODE(13, METHOD_BUFFERED) + +#pragma pack() + +#endif _OSILLC_H + diff --git a/mmslib/inc/qmem.h b/mmslib/inc/qmem.h new file mode 100644 index 0000000..a9bdcbc --- /dev/null +++ b/mmslib/inc/qmem.h @@ -0,0 +1,35 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved */ +/* */ +/* MODULE NAME : qmem.h */ +/* PRODUCT(S) : Quick Memory Allocator */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +ST_RET qMemInit (ST_INT NumElem); +ST_VOID *qMemAlloc (ST_INT size); +ST_VOID qMemFree (ST_VOID *ptr); + +extern ST_INT qMemElemSize; /* default = 126 (must be power */ + /* of 2 - 2) */ + + +#ifdef __cplusplus +} +#endif diff --git a/mmslib/inc/rs_a.h b/mmslib/inc/rs_a.h new file mode 100644 index 0000000..3eec10c --- /dev/null +++ b/mmslib/inc/rs_a.h @@ -0,0 +1,119 @@ +#ifndef RS_A_H +#define RS_A_H + +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993, 1994, All Rights Reserved */ +/* */ +/* MODULE NAME : rs_a.h */ +/* PRODUCT(S) : REDUCED STACK SUIC */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/09/98 JRB 02 Chg MAX_SUIC_CHAN from 256 to 1024. */ +/* 10/20/97 JRB 01 Added #include "asn1defs.h" for MMS_OBJ_ID. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 05/01/97 JRB 03 Move MAX_SUIC_CHAN define to here. */ +/* 01/02/96 JRB 02 Add MMSEventName and hMMSEvent. */ +/* 05/29/96 MDE 01 Changed DIB_ENTRY - name is now a pointer */ +/* 03/27/96 MDE Created */ +/************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined (_WIN32) +#include +#endif /* _WIN32 */ + +#if defined (__OS2__) +#define INCL_BASE +#include +#endif /* __OS2__ */ + +#include "asn1defs.h" /* for MMS_OBJ_ID definition */ + +#define MAX_SUIC_CHAN 1024 /* number of channels */ + +/************************************************************************/ +/* The structure below is used to save Directory and other information */ +/* about local and remote AE's read in from SUIC.DIB */ +/************************************************************************/ + +#define DIB_ENTRY_DEFINED + +struct dib_entry +{ + ST_LONG reserved; /* reserved field */ + ST_CHAR *name; /* user-defined ASCII character string */ + ST_CHAR local; /* local or remote name */ + ST_UCHAR AP_title_pres; /* present flag */ + MMS_OBJ_ID AP_title; /* AP title */ + ST_UCHAR AP_inv_id_pres; /* present flag */ + ST_INT32 AP_invoke_id; /* AP invocation ID */ + ST_UCHAR AE_qual_pres; /* present flag */ + ST_INT32 AE_qual; /* AE qualifier */ + ST_UCHAR AE_inv_id_pres; /* present flag */ + ST_INT32 AE_invoke_id; /* AE invocation ID */ + ST_UINT16 adlcAddr; +} ; +typedef struct dib_entry DIB_ENTRY; + +/************************************************************************/ +/* Channel-oriented control structure used to hold connection-specific */ +/* information */ +/************************************************************************/ + +#define MAX_TX_OUT 10 /* max. outstanding TX requests allowed */ + +struct chanctrl + { + DIB_ENTRY *loc_de; /* Pointer to Local DIB Entry */ + DIB_ENTRY *rem_de; /* Pointer to Remote DIB Entry */ + } ; +extern struct chanctrl *s_chan_ctrl; + +/************************************************************************/ +/* Structure to store incoming associate indication in case no listen */ +/* channel is available */ +/************************************************************************/ + +extern ST_INT num_loc_dib_entries; +extern ST_INT num_rem_dib_entries; +extern DIB_ENTRY *loc_dib_table; +extern DIB_ENTRY *rem_dib_table; + +/************************************************************************/ +/* Event handling variables for WIN32. */ +/************************************************************************/ +#ifdef _WIN32 +extern ST_CHAR *MMSEventName; /* Pointer to the globally unique name of Event Object */ +extern HANDLE hMMSEvent; /* Handle to Event Object to be signalled when */ + /* s_serve () needs to be called */ +#endif /* _WIN32 */ + +/************************************************************************/ +/* Prototypes */ +/************************************************************************/ +ST_VOID s_reset_ctrl (ST_INT); +ST_RET init_dirser (ST_VOID); +DIB_ENTRY *find_dib_entry (ST_CHAR *); +DIB_ENTRY *find_loc_dib_entry (ST_CHAR *ar_name); +DIB_ENTRY *find_rem_dib_entry (ST_CHAR *ar_name); + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/mmslib/inc/rs_defs.h b/mmslib/inc/rs_defs.h new file mode 100644 index 0000000..bbdb66c --- /dev/null +++ b/mmslib/inc/rs_defs.h @@ -0,0 +1,241 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 All Rights Reserved */ +/* */ +/* MODULE NAME : rs_defs.h */ +/* PRODUCT(S) : TP4/RS API internal include file */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/13/99 MDE 13 Added SD_CONST modifiers */ +/* 02/05/99 JRB 12 Del get_rs_event proto. It is now "static". */ +/* 10/08/98 MDE 11 Migrated to updated SLOG interface */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 01/02/96 EJV 10 Added RS_DEFS_INCLUDED */ +/* 11/12/96 MDE 09 Changed to DEBUG_SISCO */ +/* 07/22/96 MDE 08 Changes towards A-Unit Data support */ +/* 03/26/96 MDE 07 Added REDUCED_STACK support */ +/* 02/16/96 JRB 06 Use thisFileName. */ +/* 01/02/96 JRB 05 Removed ipcuptyp for __OS2__ */ +/* 12/28/95 KCW 04 Removed ipcuptyp for AIX */ +/* 12/14/95 DSF 03 Changes for CONN list management */ +/* 10/06/95 JRB 02 For _DOS16M, add hVipcTp4 global */ +/* so that multiple Stack users allowed. */ +/* 04/17/95 DSF 01 Created */ +/* */ +/************************************************************************/ + +#ifndef RS_DEFS_INCLUDED +#define RS_DEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "gen_list.h" +#include "slog.h" + +/****************************************************************/ + +#undef local + +/****************************************************************/ +/****************************************************************/ +/* Local ADLC Address control variables */ +extern ST_UINT16 rsBaseSrcAdlcAddr; +extern ST_UINT16 rsNumSrcAdlcAddr; + +/****************************************************************/ +/* Internal structure definitions */ +/****************************************************************/ + +typedef struct + { + DBL_LNK *l; + TP4_ADDR localTp4Addr; + ST_LONG user_bind_id; /* User-supplied Bind ID */ + } REGINFO; + +typedef struct + { + DBL_LNK lnk; /* linkage */ + REGINFO *reginfo; /* pointer to Bind Control Info */ + ST_LONG user_conn_id; /* User-supplied Connection ID */ + ST_LONG osi_conn_id; /* Connection ID returned by OSIAM */ + ST_UINT16 localAddr; /* ADLC addresses, which define the */ + ST_UINT16 remAddr; /* ADLC connection. */ + ST_BOOLEAN connFlag; + } CONNINFO; + +extern CONNINFO *conn_list; /* pointer to list of conn structs */ + +/****************************************************************/ +extern REGINFO *reg_list; /* pointer to list of REG structs */ + +/****************************************************************/ + +extern SD_CONST ST_UCHAR rs_co_dest; +extern SD_CONST ST_UCHAR rs_co_src; +extern SD_CONST ST_UCHAR rs_co_qos; + +extern SD_CONST ST_UCHAR rs_cl_dest; +extern SD_CONST ST_UCHAR rs_cl_src; +extern SD_CONST ST_UCHAR rs_cl_qos; + +/****************************************************************/ + +extern ST_VOID *co_rs_event; +extern ST_INT co_rs_op; +extern ST_RET co_rs_rslt; + +extern ST_VOID *cl_rs_event; +extern ST_INT cl_rs_op; +extern ST_RET cl_rs_rslt; + +/****************************************************************/ +/* Log Control macros */ +/****************************************************************/ + +extern SD_CONST ST_CHAR *SD_CONST _tp4_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _tp4_flowup_logstr; +extern SD_CONST ST_CHAR *SD_CONST _tp4_flowdown_logstr; + +/****************************************************************/ +#ifdef DEBUG_SISCO + +#define SFLOWUP0(a) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWUP) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_flowup_logstr,\ + thisFileName,__LINE__,a);\ + } +#define SFLOWUP0C(a) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWUP) && sLogCtrl)\ + _slogc (sLogCtrl,a);\ + } +#define SFLOWUP1(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWUP) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_flowup_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define SFLOWUP1C(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWUP) && sLogCtrl)\ + _slogc (sLogCtrl,a,b);\ + } +#define SFLOWUP2(a,b,c) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWUP) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_flowup_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define SFLOWUP2C(a,b,c) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWUP) && sLogCtrl)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define SFLOWUPH(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWUP) && sLogCtrl)\ + _slogHex (sLogCtrl,a,b);\ + } +#define SFLOWDOWN0(a) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWDOWN) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_flowup_logstr,\ + thisFileName,__LINE__,a);\ + } +#define SFLOWDOWN0C(a) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWDOWN) && sLogCtrl)\ + _slogc (sLogCtrl,a);\ + } +#define SFLOWDOWN1(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWDOWN) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_flowdown_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define SFLOWDOWN1C(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWDOWN) && sLogCtrl)\ + _slogc (sLogCtrl,a,b);\ + } +#define SFLOWDOWN2(a,b,c) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWDOWN) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_flowdown_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define SFLOWDOWN2C(a,b,c) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWDOWN) && sLogCtrl)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define SFLOWDOWNH(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_FLOWDOWN) && sLogCtrl)\ + _slogHex (sLogCtrl,a,b);\ + } +#define SERR0(a) {\ + if ((tp4_debug_sel & TP4_LOG_ERR) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_err_logstr,\ + thisFileName,__LINE__,a);\ + } +#define SERR0C(a) {\ + if ((tp4_debug_sel & TP4_LOG_ERR) && sLogCtrl)\ + _slogc (sLogCtrl,a);\ + } +#define SERR1(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_ERR) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_err_logstr,\ + thisFileName,__LINE__,a,b);\ + } +#define SERR1C(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_ERR) && sLogCtrl)\ + _slogc (sLogCtrl,a,b);\ + } +#define SERR2(a,b,c) {\ + if ((tp4_debug_sel & TP4_LOG_ERR) && sLogCtrl)\ + _slog (sLogCtrl,_tp4_err_logstr,\ + thisFileName,__LINE__,a,b,c);\ + } +#define SERR2C(a,b,c) {\ + if ((tp4_debug_sel & TP4_LOG_ERR) && sLogCtrl)\ + _slogc (sLogCtrl,a,b,c);\ + } +#define SERRH(a,b) {\ + if ((tp4_debug_sel & TP4_LOG_ERR) && sLogCtrl)\ + _slogHex (sLogCtrl,a,b);\ + } + +#else /* Not DEBUG_SISCO */ + +#define SFLOWUP0(a) +#define SFLOWUP0C(a) +#define SFLOWUP1(a,b) +#define SFLOWUP1C(a,b) +#define SFLOWUP2(a,b,c) +#define SFLOWUP2C(a,b,c) +#define SFLOWUPH(a,b) +#define SFLOWDOWN0(a) +#define SFLOWDOWN0C(a) +#define SFLOWDOWN1(a,b) +#define SFLOWDOWN1C(a,b) +#define SFLOWDOWN2(a,b,c) +#define SFLOWDOWN2C(a,b,c) +#define SFLOWDOWNH(a,b) +#define SERR0(a) +#define SERR0C(a) +#define SERR1(a,b) +#define SERR1C(a,b) +#define SERR2(a,b,c) +#define SERR2C(a,b,c) +#define SERRH(a,b) +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* RS_DEFS_INCLUDED */ + diff --git a/mmslib/inc/scl.h b/mmslib/inc/scl.h new file mode 100644 index 0000000..bd32cef --- /dev/null +++ b/mmslib/inc/scl.h @@ -0,0 +1,715 @@ +#ifndef SCL_INCLUDED +#define SCL_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2004-2004 All Rights Reserved */ +/* */ +/* MODULE NAME : scl.h */ +/* PRODUCT(S) : MMS-EASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* SCL main header file. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/24/08 JRB 17 Fix len of appID in SCL_GCB (maps to GoID). */ +/* 04/23/08 JRB 16 Add SCL_SGCB, scl_sgcb_add. */ +/* 07/03/07 JRB 15 Add scl_gse_find. */ +/* 06/12/07 JRB 14 Add VLANID in SCL_GSE & SCL_SMV. */ +/* 05/21/07 RKR 13 Changed MAC type to ST_UCHAR for GSE and SMV */ +/* 10/30/06 JRB 12 scl2_datatype_create_all: all args changed. */ +/* scl2_ld_create_all: add vmd_ctrl, is_client args.*/ +/* Add type_id to SCL_LN, SCL_LNTYPE. */ +/* Chg SCL2_BTYPE. */ +/* 08/04/06 MDE 11 Added scl_debug_mode, scl2_add_btype, etc. */ +/* 07/26/06 JRB 10 Add structs,functs for parsing Communication.*/ +/* 04/19/06 JRB 09 Add maxClient to SCL_RCB for "RptEnabled max".*/ +/* 03/16/06 JRB 08 Add SCL_SVCB struct & scl_svcb_add proto. */ +/* 03/15/06 JRB 07 Chg almost all function prototypes. */ +/* Del scl_dotype_add_da_val, */ +/* scl_datype_add_bda_val, scl_header_save. */ +/* Add sGroup to SCL_DAI. */ +/* Chg desc to ptr (allocated during parse). */ +/* Increase MAX_CDC_LEN for user-defined CDCs. */ +/* 07/25/05 JRB 12 scl2_ld_create_all: Add brcb_bufsize arg. */ +/* SCL_INFO: add brcb_bufsize element. */ +/* 06/28/05 JRB 11 Del scl2_ld_destroy_all. Use mvl_vmd_destroy.*/ +/* 06/24/05 JRB 10 Chg "ord" from unsigned to signed value. */ +/* 05/27/05 CRM 09 Add scl_info_destroy & scl2_ld_destroy_all. */ +/* 03/22/05 JRB 08 Add ifdef __cplusplus to work with C++ code. */ +/* 02/15/05 JRB 07 Add iedName to SCL_INFO. */ +/* Add domName to SCL_LD & SCL_FCDA. */ +/* Add varName to SCL_LN. */ +/* Define SCL_HEADER struct & add it to SCL_INFO.*/ +/* Add scl_header_save. */ +/* 08/06/04 JRB 06 Add scl_parse. */ +/* Move mapping functions to user header. */ +/* 07/19/04 JRB 05 Add out_filename arg to datamap_cfg_read. */ +/* Add any_cfg_count proto. */ +/* 07/15/04 JRB 04 Clean up SCL_GCB, scl_gcb_add. */ +/* 07/09/04 JRB 03 scl2_ld_create_all: add reportScanRate arg. */ +/* 07/02/04 JRB 02 Add SCL_LCB, SCL_GCB, scl_lcb_add, scl_gcb_add.*/ +/* 06/08/04 JRB 01 Initial Revision. */ +/************************************************************************/ +#include "gen_list.h" +#include "mms_def2.h" /* need MAX_IDENT_LEN */ +#include "mvl_defs.h" /* need MVL_VAR_ASSOC, etc. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_VALKIND_LEN 4 /* Spec, Conf, RO, or Set */ +#define MAX_CDC_LEN 50 /* SPS, DPS, etc. (CURVE is longest */ + /* predefined CDC but user may define others)*/ +#define MAX_FC_LEN 2 /* ST, MX, etc. */ + +/* These defines used in SCL_DA struct to differentiate between structs */ +/* containing DA info and structs containing SDO info. */ +#define SCL_OBJTYPE_DA 0 +#define SCL_OBJTYPE_SDO 1 + +/* This def used for flattened leaf names (longer to allow array indices)*/ +#define MAX_FLAT_LEN (MAX_IDENT_LEN*2) + +/************************************************************************/ +/* Structures to contain information from "Header" section of SCL. */ +/************************************************************************/ +typedef struct + { + /* NOTE: only required elements included here. Add optional elements as needed.*/ + ST_CHAR id [MAX_IDENT_LEN+1]; + + /* Defined values for "nameStructure" attribute */ + #define SCL_NAMESTRUCTURE_IEDNAME 0 /* value="IEDName" */ + #define SCL_NAMESTRUCTURE_FUNCNAME 1 /* value="FuncName" */ + ST_INT nameStructure; + } SCL_HEADER; + +/************************************************************************/ +/* Structures to contain information from "Communications" section of SCL.*/ +/************************************************************************/ +/* Data from "GSE" element (inside "ConnectedAP" element) */ +typedef struct scl_gse + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct scl_gse *next; /* CRITICAL: DON'T MOVE. */ + struct scl_gse *prev; /* CRITICAL: DON'T MOVE. */ + ST_CHAR ldInst[MAX_IDENT_LEN+1]; + ST_CHAR cbName[MAX_IDENT_LEN+1]; + ST_UCHAR MAC[CLNP_MAX_LEN_MAC]; /* Multicast MAC address */ + ST_UINT APPID; + ST_UINT VLANPRI; + ST_UINT VLANID; + /* renxiaobao GSE ½âÎö*/ + ST_UINT MinTime; + ST_UINT MaxTime; + } SCL_GSE; + +/* Data from "SMV" element (inside "ConnectedAP" element) */ +typedef struct scl_smv + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct scl_smv *next; /* CRITICAL: DON'T MOVE. */ + struct scl_smv *prev; /* CRITICAL: DON'T MOVE. */ + ST_CHAR ldInst[MAX_IDENT_LEN+1]; + ST_CHAR cbName[MAX_IDENT_LEN+1]; + ST_UCHAR MAC[CLNP_MAX_LEN_MAC]; /* Multicast MAC address */ + ST_UINT APPID; + ST_UINT VLANPRI; + ST_UINT VLANID; + } SCL_SMV; + +/* Data from "ConnectedAP" element */ +typedef struct scl_cap + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct scl_cap *next; /* CRITICAL: DON'T MOVE. */ + struct scl_cap *prev; /* CRITICAL: DON'T MOVE. */ + ST_CHAR iedName[MAX_IDENT_LEN+1]; + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR apName[MAX_IDENT_LEN+1]; + SCL_GSE *gseHead; /* head of list of GSE defs */ + SCL_SMV *smvHead; /* head of list of SMV defs */ + } SCL_CAP; + +/* Data from "Subnetwork" element */ +typedef struct scl_subnet + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct scl_subnet *next; /* CRITICAL: DON'T MOVE. */ + struct scl_subnet *prev; /* CRITICAL: DON'T MOVE. */ + ST_CHAR name[MAX_IDENT_LEN+1]; + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR type[MAX_IDENT_LEN+1]; + SCL_CAP *capHead; /* head of list of ConnectedAP defs */ + } SCL_SUBNET; + +/************************************************************************/ +/* Structures to contain information from "AccessPoint" section of SCL.*/ +/************************************************************************/ + +/* "scl_fcda_add" allocates this struct, fills it in, */ +/* and adds it to the linked list "fcdaHead" in SCL_DATASET. */ +typedef struct + { + DBL_LNK l; + ST_CHAR domName[MAX_IDENT_LEN+1]; /* domain name (constructed) */ + ST_CHAR ldInst [MAX_IDENT_LEN+1]; + ST_CHAR prefix [MAX_IDENT_LEN+1]; + ST_CHAR lnInst [MAX_IDENT_LEN+1]; + ST_CHAR lnClass [MAX_IDENT_LEN+1]; + ST_CHAR doName [MAX_IDENT_LEN+1]; + ST_CHAR daName [MAX_IDENT_LEN+1]; + ST_CHAR fc [MAX_FC_LEN+1]; /* ST, MX, etc. */ + } SCL_FCDA; + +/* "scl_dai_add" allocates this struct, fills it in, */ +/* and adds it to the linked list "daiHead" in SCL_LN. */ +/* The "flattened" name must be constructed from the "name" & "ix" */ +/* attribute of the DOI and DAI and possibly the intervening SDI, */ +/* where "ix" is an array index (we'll need some new flattened name */ +/* syntax to handle the array index). */ +/* The "accessControl" attr of DOI is ignored (don't know what it means).*/ +/* The "desc" attr of DOI, SDI, & DAI are ignored (not useful). */ +typedef struct + { + DBL_LNK l; + ST_CHAR flattened[MAX_FLAT_LEN+1]; /* flattened attribute name */ + /* constructed from "name" & "ix"*/ + /* from DOI, SDI, & DAI */ + ST_CHAR *Val; /* attribute value text */ + /* allocate appropriate size buffer*/ + ST_UINT sGroup; /* optional Setting Group Number*/ + ST_CHAR sAddr[MAX_IDENT_LEN+1]; /* from DAI */ + ST_CHAR valKind[MAX_VALKIND_LEN+1]; /* from DAI */ + } SCL_DAI; + +/*renxiaobao Êý¾ÝÓ³Éä*/ +typedef struct +{ + DBL_LNK l; + ST_CHAR ldevice[MAX_IDENT_LEN+1]; + ST_CHAR leaf[MAX_IDENT_LEN+1]; + ST_CHAR usr_data_info[MAX_IDENT_LEN+1]; +}DATA_MAP_LINK; +extern DATA_MAP_LINK *DATA_MAP_saddr; + + +/* "scl_dataset_add" allocates this struct, */ +/* and adds it to the linked list "datasetHead" in SCL_LN. */ +typedef struct + { + DBL_LNK l; + ST_CHAR name[MAX_IDENT_LEN+1]; /* dataset name */ + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + SCL_FCDA *fcdaHead; /* head of list of FCDA */ + } SCL_DATASET; + +/* "scl_rcb_add" allocates this struct, fills it in, */ +/* and adds it to the linked list "rcbHead" in SCL_LN. */ +typedef struct + { + DBL_LNK l; + ST_CHAR name[MAX_IDENT_LEN+1]; + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR datSet[MAX_IDENT_LEN+1]; + ST_UINT intgPd; + ST_CHAR rptID[MAX_IDENT_LEN+1]; + ST_UINT confRev; + ST_BOOLEAN buffered; /* TRUE if this is buffered RCB */ + ST_UINT bufTime; + ST_UINT8 TrgOps [1]; /* 8-bit bitstring */ + /* Boolean vals from SCL file */ + /* (dchg, qchg, dupd, & period) */ + /* used to set bits in TrgOps bitstring */ + ST_UINT8 OptFlds [2]; /* 9-bit bitstring */ + /* Boolean vals from SCL file */ + /* (seqNum, timeStamp, dataSet, */ + /* reasonCode, dataRef, bufOvfl, */ + /* entryID, configRef) */ + /* segmentation boolean is ignored */ + /* used to set bits in OptFlds bitstring*/ + ST_UINT maxClient; /* value of "RptEnabled max" attr. */ + } SCL_RCB; /* Report Control Block */ + +typedef struct + { + /* Counters of different types of BRCB. */ + ST_UINT brcb_count_complex; + ST_UINT brcb_count_ST; + ST_UINT brcb_count_MX; + ST_UINT brcb_count_CO; + ST_UINT brcb_count_SP; + ST_UINT brcb_count_SG; + ST_UINT brcb_count_SE; + ST_UINT brcb_count_SV; + ST_UINT brcb_count_CF; + ST_UINT brcb_count_DC; + ST_UINT brcb_count_EX; + + /* Counters of different types of URCB. */ + ST_UINT urcb_count_complex; + ST_UINT urcb_count_ST; + ST_UINT urcb_count_MX; + ST_UINT urcb_count_CO; + ST_UINT urcb_count_SP; + ST_UINT urcb_count_SG; + ST_UINT urcb_count_SE; + ST_UINT urcb_count_SV; + ST_UINT urcb_count_CF; + ST_UINT urcb_count_DC; + ST_UINT urcb_count_EX; + } SCL_RCB_COUNTERS; + +/************************************************************************/ +/* LOG Control Block */ +/* "scl_lcb_add" allocates this struct, fills it in, */ +/* and adds it to the linked list "lcbHead" in SCL_LN. */ +typedef struct + { + DBL_LNK l; + ST_CHAR name[MAX_IDENT_LEN+1]; + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR datSet[MAX_IDENT_LEN+1]; + ST_UINT intgPd; + ST_CHAR logName[MAX_IDENT_LEN+1]; + ST_BOOLEAN logEna; + ST_BOOLEAN reasonCode; + ST_UINT8 TrgOps [1]; /* 8-bit bitstring */ + /* Boolean vals from SCL file */ + /* (dchg, qchg, dupd, & period) */ + /* used to set bits in TrgOps bitstring */ + } SCL_LCB; + +/************************************************************************/ +/* GOOSE Control Block */ +/* "scl_gcb_add" allocates this struct, fills it in, */ +/* and adds it to the linked list "gcbHead" in SCL_LN. */ +typedef struct + { + DBL_LNK l; + ST_CHAR name[MAX_IDENT_LEN+1]; /* Name of CB. Used to construct*/ + /* GoCBRef or GsCBRef */ + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR datSet[MAX_IDENT_LEN+1]; /* for GOOSE only */ + /* used to construct GOOSE DatSet*/ + ST_UINT confRev; /* for GOOSE only */ + ST_BOOLEAN isGoose; /* SD_TRUE if "GOOSE", SD_FALSE if "GSSE"*/ + ST_CHAR appID[MVL61850_MAX_RPTID_LEN+1]; /* for GOOSE only */ + /* maps to GoID in 61850-7-2 */ + /* The SCL file may also contain one or more "IEDName" elements to */ + /* indicate IEDs that should subscribe for GOOSE data. We have no */ + /* way to use this information, so it is ignored. */ + } SCL_GCB; + +/************************************************************************/ +/* Sampled Value Control Block */ +/* "scl_parse" allocates this struct and fills it in. */ +/* "scl_svcb_add" adds it to the linked list "svcbHead" in SCL_LN. */ +typedef struct + { + DBL_LNK l; + ST_CHAR name[MAX_IDENT_LEN+1]; + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR datSet[MAX_IDENT_LEN+1]; + ST_CHAR smvID[MAX_IDENT_LEN+1]; + ST_UINT smpRate; + ST_UINT nofASDU; + ST_UINT confRev; + ST_BOOLEAN multicast; /* TRUE if this is MsvCB */ + ST_UINT8 OptFlds [1]; /* 8-bit bitstring */ + /* Boolean vals from "SmvOpts" in SCL */ + /* (sampleRate, etc.) */ + /* used to set bits in this bitstring */ + ST_BOOLEAN securityPres; /* SmvOpts security flag */ + ST_BOOLEAN dataRefPres; /* SmvOpts dataRef flag */ + } SCL_SVCB; /* Sampled Value Control Block */ + +/************************************************************************/ +/* Setting Group Control Block */ +typedef struct + { + /* NOTE: no DBL_LNK here. Only 2 allowed so never put on a linked list.*/ + ST_CHAR *desc; /* description (optional) */ + /* may be long so allocate if present */ + ST_UINT numOfSGs; /* mandatory */ + ST_UINT actSG; /* optional */ + } SCL_SGCB; + +/************************************************************************/ +/* Logical Node structure */ +/* "scl_ln_add" allocates this struct, fills it in, */ +/* and adds it to the linked list "lnHead" in SCL_LD. */ +typedef struct + { + DBL_LNK l; + ST_CHAR varName[MAX_IDENT_LEN+1]; /* variable name (constructed) */ + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR lnType[MAX_IDENT_LEN+1]; /* LN Type name */ + ST_CHAR lnClass[MAX_IDENT_LEN+1]; /* LN Class name */ + /* for LN0, must be "LLN0" */ + ST_CHAR inst[MAX_IDENT_LEN+1]; /* LN inst name */ + /* for LN0, must be "" (empty string)*/ + ST_CHAR prefix[MAX_IDENT_LEN+1]; /* LN prefix name */ + /* for LNO, ignored */ + SCL_DAI *daiHead; /* head of list of DAI */ + SCL_DATASET *datasetHead; /* head of list of DataSet */ + SCL_RCB *rcbHead; /* head of list of RCB (Report Control) */ + SCL_LCB *lcbHead; /* head of list of LCB (Log Control) */ + SCL_GCB *gcbHead; /* head of list of GCB (GOOSE Control) */ + SCL_SVCB *svcbHead; /* head of list of SVCB (Sampled Value Control)*/ + SCL_SGCB *sgcb; /* SGCB (Setting Group Control)(only 1 allowed)*/ + /* NOTE: In LN or LN0: Inputs ignored */ + /* NOTE: In LN0: SCLControl ignored */ + + ST_INT type_id; /* Initialized by "scl2_datatype_create_all"*/ + MVL_VAR_ASSOC *mvl_var_assoc; /* MVL Variable Association created from LN info*/ + } SCL_LN; /* Logical Node (LN or LN0 in SCL) */ + +/************************************************************************/ +/* Logical Device structure */ +/* "scl_ld_create" allocates this struct */ +/* and adds it to the linked list "ldHead" in SCL_INFO. */ +typedef struct + { + DBL_LNK l; + ST_CHAR domName[MAX_IDENT_LEN+1]; /* domain name (constructed) */ + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR inst[MAX_IDENT_LEN+1]; /* LD inst name */ + SCL_LN *lnHead; /* head of list of LN */ + /* NOTE: AccessControl in LDevice is ignored */ + } SCL_LD; /* Logical Device (LDevice in SCL)*/ + +/************************************************************************/ +/* Structures to contain information from "DataTypeTemplates" section of SCL.*/ +/************************************************************************/ +/* This structure should be allocated and filled in by the function */ +/* "scl_lntype_add_do". */ +typedef struct scl_do + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct scl_do *next; /* CRITICAL: DON'T MOVE. */ + struct scl_do *prev; /* CRITICAL: DON'T MOVE. */ + ST_CHAR name[MAX_IDENT_LEN+1]; /* data object name */ + ST_CHAR type[MAX_IDENT_LEN+1]; /* data object type */ + } SCL_DO; + +typedef struct scl_lntype + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct scl_lntype *next; /* CRITICAL: DON'T MOVE. */ + struct scl_lntype *prev; /* CRITICAL: DON'T MOVE. */ + ST_CHAR id[MAX_IDENT_LEN+1]; /* name used to reference this LN Type*/ + ST_CHAR lnClass[MAX_IDENT_LEN+1]; /* logical node class */ + SCL_DO *doHead; /* head of list of DO */ + /* scl_lntype_add_do adds to list */ + ST_INT type_id; /* Initialized by "scl2_datatype_create_all"*/ + } SCL_LNTYPE; + + +/* This structure should be allocated and filled in by the function */ +/* "scl_dotype_add_da" OR "scl_dotype_add_sdo", and possibly modified by the optional */ +/* function "scl_dotype_add_da_val". */ +/* NOTE: the same structure must be used for DA or SDO because each must */ +/* be put on the same linked list in the order they are read from the SCL file.*/ +/* Most of the parameters are relevant only for DA elements. They are */ +/* ignored if this is an SDO (i.e. objtype=SCL_OBJTYPE_SDO). */ +typedef struct + { + DBL_LNK l; + ST_INT objtype; /* SCL_OBJTYPE_DA or SCL_OBJTYPE_SDO */ + ST_CHAR name[MAX_IDENT_LEN+1]; /* DA or SDO name */ + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR sAddr[MAX_IDENT_LEN+1]; /* for DA only: DA sAddr */ + ST_CHAR bType[MAX_IDENT_LEN+1]; /* for DA only: DA bType */ + ST_CHAR valKind[MAX_VALKIND_LEN+1]; /* for DA only: Spec, Conf, RO, or Set */ + ST_CHAR type[MAX_IDENT_LEN+1]; /* for DA: needed if bType="Struct" or "Enum"*/ + /* for SDO: required */ + ST_UINT count; /* for DA only: num array entries*/ + ST_CHAR fc[MAX_FC_LEN+1]; /* for DA only: functional constraint */ + ST_BOOLEAN dchg; /* for DA only: TrgOp (data change) */ + ST_BOOLEAN qchg; /* for DA only: TrgOp (quality change) */ + ST_BOOLEAN dupd; /* for DA only: TrgOp (data update) */ + + /* The "Val" and "sGroup" parameters are only set if the SCL file contains the + * optional "Val" element, in which case "scl_dotype_add_da_val" is called. + */ + ST_CHAR *Val; /* for DA only: attribute value text */ + /* allocate appropriate size buffer*/ + ST_UINT sGroup; /* for DA only: optional Setting Group Number*/ + } SCL_DA; + +typedef struct scl_dotype + { + /* CRITICAL: First 2 parameters used to add this struct to linked */ + /* lists using list_add_last, etc. */ + struct scl_dotype *next; /* CRITICAL: DON'T MOVE. */ + struct scl_dotype *prev; /* CRITICAL: DON'T MOVE. */ + ST_CHAR id[MAX_IDENT_LEN+1]; /* name used to reference this DO Type */ + ST_CHAR cdc[MAX_CDC_LEN+1]; /* CDC name */ + SCL_DA *daHead; /* head of list of DA or SDO */ + /* scl_dotype_add_da OR */ + /* scl_dotype_add_sdo adds to list */ + } SCL_DOTYPE; + +/* This structure should be allocated and filled in by the function */ +/* "scl_datype_add_bda". */ +typedef struct + { + DBL_LNK l; + ST_CHAR name[MAX_IDENT_LEN+1]; /* data attribute name */ + ST_CHAR *desc; /* description (optional)*/ + /* may be long so allocate if present*/ + ST_CHAR sAddr[MAX_IDENT_LEN+1]; /* for DA only: DA sAddr */ + ST_CHAR bType[MAX_IDENT_LEN+1]; /* data attribute type */ + ST_CHAR valKind[MAX_VALKIND_LEN+1]; /* Spec, Conf, RO, or Set */ + ST_CHAR type[MAX_IDENT_LEN+1]; /* only used if btype="Struct" or "Enum"*/ + ST_UINT count; /* for DA only: num array entries*/ + + /* The "Val" and "sGroup" parameters are only set if the SCL file contains the + * optional "Val" element, in which case "scl_datype_add_bda_val" is called. + */ + ST_CHAR *Val; /* attribute value text */ + /* allocate appropriate size buffer*/ + ST_UINT sGroup; /* optional Setting Group Number*/ + } SCL_BDA; /* Basic Data Attribute */ +typedef struct + { + DBL_LNK l; + ST_CHAR id[MAX_IDENT_LEN+1]; /* name used to reference this DA Type*/ + SCL_BDA *bdaHead; /* head of list of BDA */ + /* scl_datype_add_bda adds to list */ + } SCL_DATYPE; + + +/* This structure should be allocated and filled in by the function */ +/* "scl_enumtype_add_enumval". */ +typedef struct + { + DBL_LNK l; + ST_INT ord; /* ord attribute */ + ST_CHAR EnumVal[MAX_IDENT_LEN+1]; /* EnumVal element */ + /* TRUNCATED if longer than buffer */ + } SCL_ENUMVAL; +typedef struct + { + DBL_LNK l; + ST_CHAR id[MAX_IDENT_LEN+1]; /* name used to reference this DA Type*/ + SCL_ENUMVAL *enumvalHead; /* head of list of EnumVal */ + /* scl_enumtype_add_enumval adds to list*/ + } SCL_ENUMTYPE; + +/************************************************************************/ +/* SCL_INFO */ +/* This structure contains all information extracted from the SCL file */ +/* to be used for MMS-EASE Lite initialization. */ +/************************************************************************/ +typedef struct + { + ST_CHAR iedName [MAX_IDENT_LEN+1]; /* passed to scl_parse */ + + SCL_HEADER Header; /* Info from "Header" section of SCL file*/ + + /* SubNetwork definitions from (from Communication section) */ + SCL_SUBNET *subnetHead; /* head of list of SubNetwork defs */ + + /* Logical Node Type definitions (from DataTypeTemplates section) */ + SCL_LNTYPE *lnTypeHead; /* head of list of LNodeType defs */ + SCL_DOTYPE *doTypeHead; /* head of list of DOType defs */ + SCL_DATYPE *daTypeHead; /* head of list of DAType defs */ + SCL_ENUMTYPE *enumTypeHead; /* head of list of EnumType defs */ + + /* Logical Device (MMS Domain) definitions (from AccessPoint section) */ + SCL_LD *ldHead; /* head of list of LDevice defs */ + + ST_INT brcb_bufsize; /* BRCB buffer size */ + /* scl2_ld_create_all uses arg to set it*/ + ST_BOOLEAN datatype_create_done; /* flag set by scl2_datatype_create_all*/ + ST_BOOLEAN ld_create_done; /* flag set by scl2_ld_create_all*/ + } SCL_INFO; + + +/************************************************************************/ +/************************************************************************/ +/* FUNCTIONS to store SCL info in "SCL_INFO" structure. */ +/************************************************************************/ +/************************************************************************/ + +SCL_LNTYPE *scl_lntype_create ( + SCL_INFO *scl_info); + +SCL_DO *scl_lntype_add_do ( + SCL_INFO *scl_info); + +SCL_DOTYPE *scl_dotype_create ( + SCL_INFO *scl_info); + +SCL_DA *scl_dotype_add_da ( + SCL_INFO *scl_info); + +SCL_DA *scl_dotype_add_sdo ( + SCL_INFO *scl_info); + +SCL_DATYPE *scl_datype_create ( + SCL_INFO *scl_info); + +SCL_BDA *scl_datype_add_bda ( + SCL_INFO *scl_info); + +SCL_ENUMTYPE *scl_enumtype_create ( + SCL_INFO *scl_info); + +SCL_ENUMVAL *scl_enumtype_add_enumval ( + SCL_INFO *scl_info); + +SCL_FCDA *scl_fcda_add ( + SCL_INFO *scl_info); + +SCL_DAI *scl_dai_add ( + SCL_INFO *scl_info); + +SCL_DATASET *scl_dataset_add ( + SCL_INFO *scl_info); + +SCL_RCB *scl_rcb_add ( + SCL_INFO *scl_info); + +SCL_LCB *scl_lcb_add ( + SCL_INFO *scl_info); + +SCL_GCB *scl_gcb_add ( + SCL_INFO *scl_info); + +SCL_SGCB *scl_sgcb_add ( + SCL_INFO *scl_info); + +SCL_SVCB *scl_svcb_add ( + SCL_INFO *scl_info); + +SCL_LN *scl_ln_add ( + SCL_INFO *scl_info); + +SCL_LD *scl_ld_create ( + SCL_INFO *scl_info); + +SCL_SUBNET *scl_subnet_add ( + SCL_INFO *scl_info); + +SCL_CAP *scl_cap_add ( + SCL_INFO *scl_info); + +SCL_GSE *scl_gse_add ( + SCL_INFO *scl_info); + +SCL_SMV *scl_smv_add ( + SCL_INFO *scl_info); + +/************************************************************************/ +/* scl_parse */ +/* Parses SCL file and stores extracted info in SCL_INFO structure. */ +/************************************************************************/ +ST_RET scl_parse (ST_CHAR *xmlFileName, ST_CHAR *iedName, + ST_CHAR *accessPointName, SCL_INFO *sclInfo); +ST_VOID scl_log_all (SCL_INFO *scl_info); + +/************************************************************************/ +/* scl_info_destroy */ +/* Destroy all info stored in the SCL_INFO structure by "scl_parse". */ +/************************************************************************/ +ST_VOID scl_info_destroy (SCL_INFO *scl_info); + +/************************************************************************/ +/* scl2_datatype_create_all */ +/* Create MMS Data types for all Logical Node Types (LNodeType) */ +/* defined in SCL. */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +ST_RET scl2_datatype_create_all ( + MVL_VMD_CTRL *vmd_ctrl, /* VMD in which to add types. */ + SCL_INFO *sclInfo, /* main struct where all SCL info stored*/ + ST_INT max_rt_num, /* max num of RUNTIME_TYPE for each LNodeType*/ + ST_BOOLEAN use_names, /* if SD_TRUE, generate a name for each type*/ + ST_CHAR *name_prefix); /* unique prefix to add to each type name*/ + /* only used if "use_names==SD_TRUE". */ + +/************************************************************************/ +/* scl2_ld_create_all */ +/* Create all Logical Devices from SCL info saved in "sclInfo". */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +ST_RET scl2_ld_create_all ( + MVL_VMD_CTRL *vmd_ctrl, /* VMD in which to add Logical Devices. */ + SCL_INFO *sclInfo, /* main struct where all SCL info stored*/ + ST_UINT reportScanRate, /* report scan rate (millisec) */ + ST_INT brcb_bufsize, /* BRCB buffer size */ + ST_BOOLEAN is_client); /* If this flag is set, Client model is */ + /* created (i.e. Control Blocks NOT created).*/ + +/************************************************************************/ +/* u_set_all_leaf_functions */ +/* User customizable function to set all leaf functions for a data type.*/ +/************************************************************************/ +ST_RET u_set_all_leaf_functions (RUNTIME_CTRL *rt_ctrl); + + +/************************************************************************/ +/************************************************************************/ + +extern ST_BOOLEAN scl_debug_mode; +extern ST_INT scl_debug_mode_error_count; + +typedef struct + { + DBL_LNK l; + ST_CHAR *btype; + RUNTIME_CTRL *rt_ctrl; + } SCL2_BTYPE; +extern SCL2_BTYPE *scl2_btype_list; +SCL2_BTYPE *scl2_add_btype (ST_CHAR *btype, ST_CHAR *tdl); + + + +typedef struct + { + SCL_INFO *scl_info; + SCL_LD *scl_ld; + SCL_LN *scl_ln; + ST_CHAR *valText; + ST_CHAR *attrib; + ST_VOID *dest; + ST_INT numRt; + SD_CONST RUNTIME_TYPE *rtHead; + } SCL2_IV_TRANSLATE_CTRL; + +ST_RET u_mvl_scl_set_initial_value (SCL2_IV_TRANSLATE_CTRL *sclXlateIv); + +/************************************************************************/ +/* Functions to find objects in SCL_INFO. */ +/************************************************************************/ +SCL_GSE *scl_gse_find (SCL_INFO *scl_info, SCL_LD *scl_ld, SCL_GCB *scl_gcb); + +#ifdef __cplusplus +} +#endif + +#endif /* !SCL_INCLUDED */ diff --git a/mmslib/inc/scrndefs.h b/mmslib/inc/scrndefs.h new file mode 100644 index 0000000..bd1d40b --- /dev/null +++ b/mmslib/inc/scrndefs.h @@ -0,0 +1,97 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2005, All Rights Reserved */ +/* */ +/* MODULE NAME : scrndefs.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : This include file contains definitions needed */ +/* for screen handling */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/06/05 EJV 20 linux: no fancy screen. */ +/* 03/31/03 EJV 19 Removed _WINDOWS code. */ +/* 03/18/03 JRB 18 Fix QNX #ifdefs. */ +/* 02/17/03 CRM 17 Added "defined(linux)" code. */ +/* 02/17/03 JRB 16 Stop using SYSTEM_SEL define. */ +/* Del QNX_C86 support. */ +/* 08/24/98 EJV 15 Eliminated semicoln in some macros. */ +/* 04/29/98 EJV 14 CLEARSCR on sparc beeps. */ +/* 01/08/98 EJV 13 Deleted CLEARSCR specific to sun sparc */ +/* 05/16/97 RKR 12 Changes for HP-UX */ +/* 12/07/95 DSF 11 Minor corrections */ +/* 11/08/95 MDE 10 Tweaked WINDOWS defines a bit */ +/* 05/04/95 JRB 09 Added SYS_QNX4 for QNX 4.x port. */ +/* 05/04/95 JRB 08 Simplified macros: removed LINE?COL?, */ +/* added GOTOLINE(line) an CLEARLINE(line). */ +/* 04/20/95 KCW 07 Changes for SUN Solaris */ +/* 01/05/95 JRB 06 Change BSD to SYS_BSD. */ +/* 12/09/94 JRB 05 Disable ANSI escape sequences for VXWORKS. */ +/* 10/12/93 DSF 04 Changed MMSWIN to _WINDOWS */ +/* 04/08/93 WEO 03 Added MMSWIN defines for screen formatting */ +/* 12/03/92 JRB 02 Added LINE9COL0 for QNX. */ +/* 04/16/92 WEO 01 Added CLEARSCR for SUN */ +/* 06/25/91 5.00 MMSEASE 5.0 release. See UTILML50.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef SCRNDEFS_INCLUDED +#define SCRNDEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__QNX__) + +#define CLEARSCR printf( "\33H\33J" ) +#define SAVESCR printf( "\33S" ) +#define BOTTOMSCR printf( "\33=7 " ) /* "7" means row 23, " " means col 0 */ +#define CLEAREOL printf( "\33K" ) +#define GOTOLINE(line) printf("\33=%c ",line+0x1f) /* line=1 thru 24*/ +#define CLEARLINE(line) printf("\33=%c \33K",line+0x1f) /* line=1 thru 24*/ + +#else /* non QNX system */ + +#if defined (_WIN32) || defined (VXWORKS) || \ + defined(__hpux) || defined(sparc) || defined(linux) +#define CLEARSCR printf("\n") +#define RESTORESCR +#define SAVESCR +#define BOTTOMSCR +#define CLEAREOL +#define GOTOLINE(line) printf("\n") +#define CLEARLINE(line) +#else +#define CLEARSCR printf( "\33[2J\33[0;0H" ) +#define RESTORESCR printf( "\33[u" ) +#define SAVESCR printf( "\33[s" ) +#define BOTTOMSCR printf( "\33[23;0H" ) +#define CLEAREOL printf( "\33[K" ) +#define GOTOLINE(line) printf( "\33[%d;1H", line) /* line= 1 thru 24*/ +#define CLEARLINE(line) printf( "\33[%d;1H\33[K", line) /* line= 1 thru 24*/ +#endif +#endif + +#define PRINTSTR printf( "%s", str_ptr ) +#define ADD_LF printf( "\n" ) + +#if defined(_AIX) || defined(sun) || defined(__hpux) || defined(linux) \ + || (defined(__alpha) && !defined(__VMS)) \ + || defined(VXWORKS) || defined(__QNX__) +#define CR '\012' +#else +#define CR '\015' +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mmslib/inc/slog.h b/mmslib/inc/slog.h new file mode 100644 index 0000000..3fccaf8 --- /dev/null +++ b/mmslib/inc/slog.h @@ -0,0 +1,1599 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2008, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : slog.h */ +/* PRODUCT(S) : SLOG */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/01/08 JRB 82 Move forward references to top of file. */ +/* 11/07/08 MDE 82 Added 'Get Log Masks' feature support */ +/* 10/08/08 MDE 81 Added SEAL */ +/* 08/22/08 RKR 80 Added ICCP Lite */ +/* 08/11/08 MDE 79 Added 'initialized' */ +/* 08/04/08 MDE 78 Added slogIpcEventEx */ +/* 07/30/08 DWL 77 Added COMTRADE listening port */ +/* 07/25/08 MDE 76 Moved slogIpcCtx into LOG_CTRL */ +/* 07/07/08 MDE 75 Added slogIpcActiveCount */ +/* 05/09/08 RKR 74 Added new IPC Commands for Clone and Reset */ +/* 03/27/08 EJV 73 slog_get_index_file_name: added destLen param*/ +/* and changed to return result. */ +/* 03/04/08 EJV 72 Added IPC_LOG_PORT_SNAP_LITE_* ports. */ +/* Removed MMSEASE_MOSI def in description. */ +/* Added LogMaskMapCtrl for 142-XXX products, */ +/* revised comments. */ +/* 03/10/08 MDE 71 Added slog_ipc_std_cmd_service */ +/* 03/04/08 RWM 70 Changed MAX_LOG_SIZE to 5000 */ +/* 12/14/07 DSF 69 Added sNonStandardLogMode to support .NET */ +/* Logger class */ +/* 11/30/07 DSF 68 Added IPC_LOG_IOS_GATEWAY */ +/* 11/08/07 MDE 67 Added IPC_LOG_PORT_SDE_OPCUA_SERVER */ +/* 10/23/07 MDE 66 Added ElapsedTime option for Windows */ +/* 10/11/07 MDE 65 Added UAP ports */ +/* 09/20/07 MDE 64 Added slogIpcCallingEnable, listen port */ +/* 03/01/07 MDE 63 Tweaks to SLOGIPC command message types */ +/* 02/20/07 CRM 62 Added SLOGIPCCALLING_NAME */ +/* 01/22/07 MDE 61 Added Standard command message types */ +/* 01/08/07 EJV 60 slogIpcStop: added lc param. */ +/* 04/07/06 MDE 59 Added IPC_LOG_PORT_ICCPCFG */ +/* 03/14/06 MDE 58 Increased SLOG_MAX_FNAME to 64 (was 32) */ +/* 03/30/06 CRM 57 Added _slogXML, and macros */ +/* 02/17/06 MDE 56 Added logcfg_exx, preferredTag, etc.. */ +/* 02/15/06 EJV 55 IPC_LOG_PORT_MMS_EASE - changed comment. */ +/* 02/02/06 EJV 54 LOGCFGX_TAG_VAL: added/changed fields. */ +/* 12/05/05 EJV 53 Added IPC_LOG_PORT_MMS_EASE. Changed comment.*/ +/* 10/28/05 EJV 52 Added MMS-LITE ports */ +/* 10/14/05 EJV 51 Add SLOGIPC_NAME def & slogIpcEvent proto */ +/* 08/10/05 MDE 50 Added slog_start, slog_end, index file */ +/* 08/05/05 EJV 49 Added extern ssleLogMaskMapCtrl. */ +/* 08/02/05 MDE 48 Added IOS ports */ +/* 06/30/05 EJV 47 Added extern genlistDebugMapCtrl. */ +/* Arranged xxxMaskMapCtrl in alphabetical order*/ +/* Del duplicate logCfgAddMaskGroup proto. */ +/* Del logCfgAddAll proto (user must add all). */ +/* Del logcfgx (use logcfgx_ex instead) */ +/* 04/29/05 EJV 46 Added IPC_LOG_PORT_RFC1006_LISTENER def. */ +/* 03/31/05 MDE 45 Added more SLOGALWAYS macros */ +/* 02/22/05 JRB 44 slogIpc: add SD_CONST to some args. */ +/* 02/16/05 JRB 43 Del #if around forward references. */ +/* 02/10/05 MDE 42 Added STRINGBUF and DOUBLE DATATYPE's */ +/* 02/02/05 MDE 41 Smart mode work */ +/* 01/27/05 MDE 40 LINUX warning cleanup */ +/* 01/19/05 MDE 39 Added LogCfg defines, etc.. */ +/* 01/19/05 EJV 38 AIX:del extern in struct tag_GEN_SOCK,C++ err*/ +/* 12/06/04 ASK 37 Added SLOG IPC "smart" client features. Added*/ +/* RUINT define for new logcfgx. */ +/* 11/22/04 JRB 36 Add max_msg_size & msg_buf to LOG_CTRL. */ +/* Add slog_max_msg_size_set proto. */ +/* Add slog_max_msg_size_get macro. */ +/* slogDelBuf: add (LOG_CTRL *) arg. */ +/* 10/12/04 MDE 35 Added logcfgx mask extension mechanism */ +/* 08/04/04 EJV 34 LOGMEM_ITEM: chg log time,related to prev chg*/ +/* Del slogTime, slogMs global variables. */ +/* 07/09/04 EJV 33 Del DATETIME_MILLI_EN,add 'obsolete' comments*/ +/* 06/24/04 DSF 32 Added DATETIME_MILLI_EN */ +/* 06/24/04 EJV 31 IPC_LOG_CTRL: add portUsed. */ +/* 06/21/04 EJV 30 IPC_LOG_CTRL: add portCnt, appId fields. */ +/* 05/26/04 EJV 29 Added comment to keep track on used IPC ports*/ +/* 05/20/04 EJV 28 IPC_LOG_CTRL: limited log message queue. */ +/* 05/18/04 MDE 27 Removed LOG_IPC_SUPPORT #ifdef's */ +/* 05/11/04 EJV 26 Revised LOG_IPC_SUPPORT code to use gensock2.*/ +/* Added SLOG_MAX_LOGTYPESTR, SLOG_MAX_HDR. */ +/* Added slogSetHdr() proto. */ +/* 02/10/04 KCR 25 Added slogDelBuf() */ +/* 10/24/03 JRB 24 Move gs_debug_sel from glbsem.h to here. */ +/* Move clnp_debug_sel from clnp_usr.h to here. */ +/* Del windows.h (see sysincs.h). */ +/* 06/20/03 JRB 23 Del ; from SLOGALWAYS* too. */ +/* 05/08/03 JRB 22 Del {} from SLOGALWAYS* so they work in */ +/* almost any context. */ +/* 05/07/03 DSF 21 Increased the value of SLOG_MAX_FNAME */ +/* Added support for sErrLogCtrl */ +/* 10/17/02 JRB 20 Add "Base" macros SLOG_*, SLOGC_*, SLOGH. */ +/* 03/11/02 JRB 19 SLOG_PAUSE, SLOG_LF, SLOG_CLRSCR do nothing. */ +/* 04/26/01 DSF 18 Define SOCKET if not yet defined */ +/* 04/16/01 DSF 17 Include windows.h instead of including */ +/* winsock.h directly */ +/* 03/23/01 MDE 16 Added _slogStr, SLOGALWAYSS */ +/* 11/27/00 JRB 15 Added read_log_cfg_file, logcfgx protos. */ +/* 08/22/00 KCR 14 Added FIL_CTRL_NO_LOG_HDR */ +/* 03/09/00 MDE 13 Added SD_CONST modifiers to LOGMEM_ITEM */ +/* 09/13/99 MDE 12 Added SD_CONST modifiers */ +/* 11/11/98 DSF 11 Minor changes to _slog_dyn_log_fun */ +/* 10/16/98 DSF 10 Spelling */ +/* 10/08/98 MDE 09 Migrated to updated SLOG interface */ +/* 06/15/98 NAV 08 Conditionally include winsock.h or winsock2.h*/ +/* 06/03/98 MDE 07 Replaced 'winsock.h' with 'windows.h' */ +/* 12/12/97 MDE 06 Added DEBUG_SISCO versions of SLOGALWAYSx */ +/* 11/05/97 DSF 05 Added SYSTIME_EN */ +/* 09/12/97 DSF 04 Expose slogSetTimeText () */ +/* 06/11/97 MDE 03 Include time.h for all */ +/* 05/27/97 DSF 02 Added IPC logging capability */ +/* 05/27/97 DSF 01 Include time.h for sun */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef SLOG_INCLUDED +#define SLOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + + +/*#define SLOGIPC_SEAL Disable for now, phase in ... */ + +#include "gen_list.h" +#ifdef SLOGIPC_SEAL +#include "sseal.h" +#endif + +#include +#include /* for time_t */ + +#define TIME_BUF_LEN 30 + +/************************************************************************/ +struct tag_GEN_SOCK; /* forward reference */ +struct tag_GEN_SOCK_DATA; /* forward reference */ +struct log_ctrl; /* forward reference */ + +/************************************************************************/ +/* Memory logging string buffer size limit */ +/* NOTE : Do not change this lightly! QMEM.C should be looked at */ +/************************************************************************/ + +#define SLOG_MEM_BUF_SIZE 125 + +/* Memory logging item control */ +/* A table of these is established at initialization time */ + +#define LMF_USED 0x0001 +#define LMF_HEADER 0x0002 +#define LMF_HEX 0x0004 + + +typedef struct logmem_item + { + ST_UINT flags; /* see LMF_xxx flags */ + ST_INT logType; /* log type storage */ + SD_CONST ST_CHAR *logTypeStr; /* log type string */ + ST_INT lineNum; /* source file line number */ + SD_CONST ST_CHAR *sourceFile; /* source file name, NULL for none */ + ST_CHAR slogTimeText[TIME_BUF_LEN]; + ST_CHAR *string; /* text */ + } LOGMEM_ITEM; + + +/************************************************************************/ +/* File Logging State flags */ +/************************************************************************/ + +#define FIL_STATE_OPEN 0x0001 +#define FIL_STATE_NEED_WIPE 0x0002 + +/* File Logging Control flags */ + +#define FIL_CTRL_WIPE_EN 0x0001 +#define FIL_CTRL_WRAP_EN 0x0002 +#define FIL_CTRL_MSG_HDR_EN 0x0004 +#define FIL_CTRL_NO_LOG_HDR 0x0040 + +/* File output mode flags */ + +#define FIL_CTRL_NO_APPEND 0x0008 +#define FIL_CTRL_HARD_FLUSH 0x0010 +#define FIL_CTRL_SETBUF_EN 0x0020 + +typedef struct file_log_ctrl + { +/* User sets these elements */ + ST_ULONG maxSize; + ST_CHAR *fileName; /* destination filename */ + ST_UINT ctrl; /* see FIL_CTRL_xxx flags */ + ST_LONG wipeFilePos; + +/* Internal use only */ + ST_UINT state; /* see FIL_STATE_xxx flags */ + FILE *fp; + } FILE_LOG_CTRL; + +/* Memory Logging State flags */ + +#define MEM_STATE_INIT 0x0001 + +/* Memory Logging Control flags */ + +#define MEM_CTRL_MSG_HDR_EN 0x0001 +#define MEM_CTRL_AUTODUMP_EN 0x0002 +#define MEM_CTRL_HEX_LOG 0x0004 + +typedef struct mem_log_ctrl + { +/* User sets these elements */ + ST_INT maxItems; /* # items to allocate at powerup */ + ST_CHAR *dumpFileName; /* where memory dump goes */ + ST_UINT ctrl; /* see MEM_CTRL_xxx flags */ + +/* Internal use only */ + ST_UINT state; /* see MEM_STATE_xxx flags */ + LOGMEM_ITEM *item; /* Item table */ + ST_INT nextPut; /* Current position (where last was put */ + } MEM_LOG_CTRL; + +/************************************************************************/ +/* Socket Slogging Subsystem */ +/************************************************************************/ + +#define SLOGIPC_NAME "SLOGIPC" /* used in GEN_SOCK */ +#define SLOGIPCCALLING_NAME "SLOGIPCCALLING" /* used in GEN_SOCK */ + +/* Default listen port for LogViewer */ +#define IPC_LOG_LOGVIEWER_PORT 55146 + +/* default parameters for socket logging subsystem */ +#define IPC_LOG_BASE_PORT 55147 + +/* ports below are taken by following SISCO applications: */ +#define IPC_LOG_PORT_AXS4ICCP IPC_LOG_BASE_PORT+1 /* 55148 */ +#define IPC_LOG_PORT_OSILL2 IPC_LOG_BASE_PORT+2 /* 55149 */ +#define IPC_LOG_PORT_OSILL2_IPC IPC_LOG_BASE_PORT+3 /* 55150 */ +#define IPC_LOG_PORT_AXS4MMS IPC_LOG_BASE_PORT+4 /* 55151 */ +#define IPC_LOG_PORT_AXS4IEC61850 IPC_LOG_BASE_PORT+5 /* 55152 */ +#define IPC_LOG_PORT_AXS4GOOSE_OLD IPC_LOG_BASE_PORT+6 /* 55153 */ +#define IPC_LOG_PORT_RFC1006_LISTENER IPC_LOG_BASE_PORT+7 /* 55154 */ +#define IPC_LOG_PORT_ICCPCFG IPC_LOG_BASE_PORT+8 /* 55155 */ + +/* UIB ports: reserve 10: 55157-55167 */ +#define IPC_LOG_PORT_UIBBASE IPC_LOG_BASE_PORT+10 /* 55157 */ +#define IPC_LOG_NUMPORTS_UIB 10 + +#define IPC_LOG_PORT_SNAP_LITE_DAEMON IPC_LOG_BASE_PORT+33 /* 55180 */ +#define IPC_LOG_PORT_SNAP_LITE_UTIL IPC_LOG_BASE_PORT+34 /* 55181 */ + +/* MMS-EASE demo programs: reserve 10 55190-55199 */ +#define IPC_LOG_PORT_MMS_EASE IPC_LOG_BASE_PORT+43 /* 55190 */ + +/* MMS-LITE demo programs: reserve 10 55200-55209 */ +#define IPC_LOG_PORT_MMS_LITE IPC_LOG_BASE_PORT+53 /* 55200 */ + +/* ICCP-LITE demo programs: reserve 5 55210-55214 */ +#define IPC_LOG_PORT_ICCP_LITE IPC_LOG_BASE_PORT+63 /* 55210 */ + +/* USPS IOS ports: reserve 100 : 55347-55447 */ +#define IPC_LOG_IOS_MPECOM IPC_LOG_BASE_PORT+200 /* 55347 */ +#define IPC_LOG_IOS_MPE IPC_LOG_BASE_PORT+201 /* 55348 */ +#define IPC_LOG_IOS_GATEWAY IPC_LOG_BASE_PORT+202 /* 55349 */ + +/* UAP related elements */ +#define IPC_LOG_PORT_AXS4GOOSE IPC_LOG_BASE_PORT+300 /* 55447 */ +#define IPC_LOG_PORT_DSPI IPC_LOG_BASE_PORT+301 /* 55448 */ +#define IPC_LOG_PORT_SCLDEVLOADEX IPC_LOG_BASE_PORT+302 /* 55449 */ +#define IPC_LOG_PORT_UAPPC IPC_LOG_BASE_PORT+303 /* 55450 */ +#define IPC_LOG_PORT_GOOSEBLASTER IPC_LOG_BASE_PORT+304 /* 55451 */ +#define IPC_LOG_PORT_GOOSEBLASTERCONTROL IPC_LOG_BASE_PORT+305 /* 55452 */ +#define IPC_LOG_PORT_SDE_ATM IPC_LOG_BASE_PORT+306 /* 55453 */ +#define IPC_LOG_PORT_SDE_MONITOR IPC_LOG_BASE_PORT+307 /* 55454 */ +#define IPC_LOG_PORT_SDE_DRIVER IPC_LOG_BASE_PORT+308 /* 55455 */ +#define IPC_LOG_PORT_SDE_OPCUA_SERVER IPC_LOG_BASE_PORT+309 /* 55456 */ + +/* COMTRADE Utility ports */ +#define IPC_LOG_PORT_COMTRADE_UTILITY IPC_LOG_BASE_PORT+350 /* 55497 */ + + +#define IPC_LOG_MAX_CONNECTIONS 10 +#define IPC_LOG_MAX_QUEUE_CNT 100 + +/* SMART MODE */ +/* Format of smart message is 3 unsigned long integers: */ +/* unsigned long magicNumber = SLOGIPC_MAGIC_NUMBER; */ +/* unsigned long messageType = SLOGIPC_MSG_TYPE_XXX */ +/* unsigned long messageLen = dataLength */ + +/* Followed by one of: */ +/* nothing */ +/* char[messageLen] */ +/* unsigned long missedMessageCount */ + +#define SLOGIPC_MAGIC_NUMBER_SEAL 0x1F2E3D4D +#define SLOGIPC_MAGIC_NUMBER_NOSEAL 0x1F2E3D4C + +typedef struct + { + ST_UINT32 magicNumber; + ST_UINT32 messageType; + ST_UINT32 messageLen; + } SLOGIPC_SMART_MSG_HDR; + +ST_VOID _slogIpcInitHdr (struct tag_GEN_SOCK *pSock, + struct tag_GEN_SOCK_DATA *sockData, + ST_UINT32 msgType, ST_INT dataLen); + +#ifdef SLOGIPC_SEAL +typedef struct + { + ST_UINT32 magicNumber; + ST_UINT32 messageType; + ST_UINT32 messageLen; + S_SEAL seal; + } SLOGIPC_SMART_MSG_HDRS; +ST_VOID _slogIpcSetSeal (SLOGIPC_SMART_MSG_HDRS *sHdrS); +ST_RET _slogIpcCheckSeal (struct log_ctrl *lc, SLOGIPC_SMART_MSG_HDRS *sHdrS); +#endif + +/* message types */ +#define SLOGIPC_MSG_TYPE_LOG 0x00000000 +#define SLOGIPC_MSG_TYPE_RESERVED 0x00000001 +#define SLOGIPC_MSG_TYPE_APPID 0x00000002 +#define SLOGIPC_MSG_TYPE_START 0x00000003 +#define SLOGIPC_MSG_TYPE_STOP 0x00000004 + +/* Standard command message response types */ +#define SLOGIPC_MSG_TYPE_RESP_SUCCESS 0x00000005 +#define SLOGIPC_MSG_TYPE_RESP_FAILURE 0x00000006 + +/* Standard command message types */ +#define SLOGIPC_MSG_TYPE_OPTIONS 0x00000007 +#define SLOGIPC_MSG_TYPE_READ_LOGCFG 0x00000008 +#define SLOGIPC_MSG_TYPE_WRITE_LOGCFG 0x00000009 + +/* IF we missed log messages ... */ +#define SLOGIPC_MSG_TYPE_LOG_MISSED 0x0000000A + +#define SLOGIPC_MSG_TYPE_CLONE_LOG 0x00000010 +#define SLOGIPC_MSG_TYPE_RESET_LOG 0x00000020 +#define SLOGIPC_MSG_TYPE_WRITE_MSGDATA 0x00000030 +#define SLOGIPC_MSG_TYPE_GET_LOGMASKS 0x00000040 + + +/* General application specific command */ +#define SLOGIPC_MSG_TYPE_CMD 0x00000100 + +/* Defines for options (bitmasked) */ +#define LOG_IPC_EDIT_LOGCFG 0x00000001 + +/* configuration parameters for socket logging & command subsystem */ +typedef struct ipc_log_ctrl_tag + { + /* Used for client (calling) connections */ + ST_CHAR *callingIp; /* IP or host name of host to connect to*/ + ST_UINT16 callingPort; /* port of host to connect to */ + ST_ULONG callingBackoff; /* ms */ + ST_INT sealMode; + ST_INT sealTimeWindow; + + /* Used for server (called) connections */ + ST_UINT16 port; /* listening port number */ + ST_UINT16 portCnt; /* num of listening ports starting with */ + /* base port, for multiple app instances*/ + + ST_UINT16 portUsed; /* this the listening port actually used*/ + ST_UINT maxConns; /* max connections that can be accepted */ + + /* Misc parameters */ + ST_UINT maxQueCnt; /* max num of logs that can be queued */ + + ST_CHAR *appId; /* pointer to NULL terminated string */ + /* identifying the application, sent to */ + /* IPC Logging Client in first message */ + + ST_UINT32 options; /* Options supported by the app */ + + /* command processing function pointer - to be set by user application */ + ST_VOID (*slog_ipc_cmd_fun) (struct tag_GEN_SOCK *pSock, struct tag_GEN_SOCK_DATA *sockData, + ST_UINT32 msgType, ST_UINT32 msgDataLen, ST_CHAR *msgData); + + } IPC_LOG_CTRL; + + +/* Standard command handling support */ +typedef struct + { + DBL_LNK l; + struct tag_GEN_SOCK *pSock; + struct tag_GEN_SOCK_DATA *sockData; + ST_UINT32 msgType; + ST_UINT32 msgDataLen; + ST_CHAR *msgData; + } SLOGIPC_CMD; + +extern SLOGIPC_CMD *slogIpcCmdList; +extern ST_INT slogIpcMaxCmdPend; + +ST_VOID slog_ipc_std_cmd_fun (struct tag_GEN_SOCK *pSock, + struct tag_GEN_SOCK_DATA *sockData, + ST_UINT32 msgType, ST_UINT32 msgDataLen, + ST_CHAR *msgData); + +ST_VOID slog_ipc_std_cmd_service (ST_CHAR *logCfgFile, /* As used in logcfgx_exx */ + ST_CHAR *fileNamePrefix, /* ditto */ + ST_CHAR *cName, /* ditto */ + ST_BOOLEAN callingEnable, + ST_RET (*logReloadHandler) (ST_VOID), + ST_RET (*extendedCmdHandler) (SLOGIPC_CMD *slogIpcCmd)); + +ST_VOID slog_ipc_std_cmd_service_ex (struct log_ctrl *lc, + ST_CHAR *logCfgFile, /* As used in logcfgx_exx */ + ST_CHAR *fileNamePrefix, /* ditto */ + ST_CHAR *cName, /* ditto */ + ST_BOOLEAN callingEnable, + ST_RET (*logReloadHandler) (ST_VOID), + ST_RET (*extendedCmdHandler) (SLOGIPC_CMD *slogIpcCmd)); + +ST_VOID slogIpcCallingEnable (ST_BOOLEAN enable); +ST_VOID slogIpcCallingEnableEx (struct log_ctrl *lc, ST_BOOLEAN enable); + +ST_INT slogIpcActiveCount (struct log_ctrl *lc); + +/************************************************************************/ +/* SLOG IPC Context */ + +/* connection states */ +#define SLOGIPC_CON_IDLE 0 +#define SLOGIPC_CONNECTED 1 +#define SLOGIPC_CON_CLOSING 2 + +/* Remote connection info */ +typedef struct slogipc_con_ctrl_tag + { + DBL_LNK link; /* link list */ + struct tag_GEN_SOCK *conSock; /* pointer to socket info */ + ST_UINT conState; /* connection state */ + ST_BOOLEAN txEnable; /* Used in smart mode */ + struct tag_GEN_SOCK_DATA *sendQue; /* Pending send queue to the Remote */ + ST_UINT sendQueCnt; /* number of messages to send in queue */ + struct tag_GEN_SOCK_DATA *rcvBuf; /* alloc buf to drain any rcvd bytes */ + } SLOGIPC_CON_CTRL; + + +/* SLOGIPC context states */ +#define SLOGIPC_CTX_IDLE 0 +#define SLOGIPC_CTX_ACTIVE 1 +#define SLOGIPC_CTX_TERMINATING 2 + +/* This structure holds core parameters */ +typedef struct slogipc_ctx_tag + { + ST_UINT state; /* SLOGIPC_CTX_* */ + ST_BOOLEAN smartMode; /* SD_TRUE if smart mode enabled, SD_FALSE otherwise */ + + ST_INT sealMode; + + SLOGIPC_CON_CTRL *conCtrlList; /* list of connect CTRLs */ + struct tag_GEN_SOCK *listenSock; /* listen socket for conns from remote slog Clients */ + struct tag_GEN_SOCK *callingSock; /* calling socket for conns to remote slog Client */ + struct log_ctrl *lc; /* save to access appId when connected */ + struct tag_GEN_SOCK_CTXT *sockCtx; /* this is gensock2 context for slogipc.c */ + + ST_INT hdrSize; /* Calculated at startup */ + ST_INT magicNumber; + + ST_BOOLEAN callingEnabled; + ST_DOUBLE nextCallingConnectTime; + } SLOGIPC_CTX; + + +/************************************************************************/ +/* LOG CONTROL */ +/* A structure of this type is used for each independent logging entity */ +/************************************************************************/ + +/* Log control mask values */ +#define LOG_MEM_EN 0x0001L +#define LOG_FILE_EN 0x0002L +#define LOG_TIME_EN 0x0008L +#define LOG_ELAPSEDTIME_EN 0x0020L /* Windows only */ + +#define LOG_TIMEDATE_EN 0x0010L /* obsolete - ignored */ +#define LOG_DIFFTIME_EN 0x0020L /* obsolete - ignored */ +#define LOG_TIME_INITIALIZED 0x0040L /* obsolete - ignored */ +#define LOG_SYSTIME_EN 0x0100L /* obsolete - ignored */ + +#define LOG_NO_HEADER_CR 0x0200L +#define LOG_FILENAME_SUPPRESS 0x0400L +#define LOG_LOGTYPE_SUPPRESS 0x0800L + +#define LOG_IPC_LISTEN_EN 0x1000L +#define LOG_IPC_CALL_EN 0x2000L +#define LOG_IPC_SMART 0x4000L +#define LOG_IPC_EN (LOG_IPC_LISTEN_EN|LOG_IPC_CALL_EN) + +#define SLOG_NORMAL 0 +#define SLOG_CONT -1 +/* Dynamic logging standard command definitions */ +#define SLOG_DYN_PAUSE -10 /* OBSOLETE */ +#define SLOG_DYN_LF -11 /* OBSOLETE */ +#define SLOG_DYN_CLRSCR -12 /* OBSOLETE */ + +typedef struct log_ctrl + { +/* User sets these elements */ + ST_UINT32 logCtrl; /* Logging Control flags - see LOG_xxx defines */ + FILE_LOG_CTRL fc; /* File logging control */ + MEM_LOG_CTRL mc; /* Memory logging control */ + IPC_LOG_CTRL ipc; /* IPC logging control */ + + +/* Application specific information */ + ST_UINT32 logMask1; /* These bit masked variables are used by the */ + ST_UINT32 logMask2; /* user application to determine whether a item */ + ST_UINT32 logMask3; /* is to be logged. 6 ST_INT32's == 192 bits */ + ST_UINT32 logMask4; + ST_UINT32 logMask5; + ST_UINT32 logMask6; + +/* Internal variables. */ + ST_BOOLEAN initialized; /* Set when LOG_CTRL has been initializled */ + ST_INT max_msg_size; /* max allowed log msg size. */ + ST_CHAR *msg_buf; /* buffer for log msg */ + +/* static vars */ + SLOGIPC_CTX slogIpcCtx; + } LOG_CTRL; + + +/* Max size of any single log statement (sprintf) */ + +#define MAX_LOG_SIZE 5000 + +/* Set the following variable to a number larger than the default of */ +/* MAX_LOG_SIZE if you want to log more than 500 bytes in a single */ +/* message. */ + +extern ST_INT sl_max_msg_size; + +/************************************************************************/ +/* Main entry points into the SLOG library */ +/************************************************************************/ + +ST_VOID slog (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_CHAR *format, ...); + +ST_VOID slogx (ST_UINT32 doit, LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_CHAR *format, ...); + +ST_VOID slogHex (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST fileName, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT numBytes, + SD_CONST ST_VOID *hexData); + + +ST_VOID _slog (LOG_CTRL *lc, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_CHAR *format, ...); +ST_VOID _slogc (LOG_CTRL *lc, SD_CONST ST_CHAR *format, ...); + +ST_VOID _slogx (ST_UINT32 doit, LOG_CTRL *lc, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_CHAR *format, ...); + +ST_VOID _slogHex (LOG_CTRL *lc, + ST_INT numBytes, + SD_CONST ST_VOID *hexData); + +ST_VOID _slogXML (LOG_CTRL *lc, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + ST_UINT numBytes, + SD_CONST ST_CHAR *textData); + +ST_VOID _slogStr (LOG_CTRL *lc, ST_CHAR *strData); + +ST_RET slog_start (LOG_CTRL *lc, ST_INT max_msg_size); +ST_RET slog_end (LOG_CTRL *lc); + +ST_RET slog_max_msg_size_set (LOG_CTRL *lc, ST_INT max_msg_size); +/* Use macro to get max msg size. Faster. */ +#define slog_max_msg_size_get(log_ctrl) (log_ctrl->max_msg_size) + +ST_VOID slogIpcSendData (struct tag_GEN_SOCK *pSock, ST_UINT32 msgType, + ST_INT dataLen, ST_UCHAR *data); +ST_VOID slogIpcSendRawData (LOG_CTRL *lc, ST_INT bufLen, ST_CHAR *buf, ST_BOOLEAN sendAlways); + + +/************************************************************************/ +/* Main entry points into the SLOG library */ +/************************************************************************/ + +/* File Logging Utility Functions */ + +ST_VOID slogCloseFile (LOG_CTRL *lc); +ST_VOID slogCloneFile (LOG_CTRL *lc, SD_CONST ST_CHAR *newfile); +ST_VOID slogCloneFileEx (LOG_CTRL *lc, SD_CONST ST_CHAR *newFile); +ST_VOID slogDeleteFile (LOG_CTRL *lc); +ST_VOID slogCallStack (LOG_CTRL *lc, SD_CONST ST_CHAR *txt); +ST_VOID slogDelBuf (LOG_CTRL *lc); + +/* Memory Logging Utility Functions */ + +ST_VOID slogDumpMem (LOG_CTRL *lc); +ST_VOID slogResetMem (LOG_CTRL *lc); +ST_CHAR *slogGetMemMsg (LOG_CTRL *lc, SD_CONST ST_INT msgNum); +ST_INT slogGetMemCount (LOG_CTRL *lc); + +/* Internal functions */ + +ST_VOID slogFile (LOG_CTRL *lc, SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, SD_CONST ST_CHAR *buf); + +ST_VOID slogMem (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + ST_INT bufLen, SD_CONST ST_CHAR *buf); + +ST_RET slogIpcInit (LOG_CTRL *lc); +ST_RET slogIpcStop (LOG_CTRL *lc); +ST_RET slogIpcEvent (ST_VOID); +ST_RET slogIpcEventEx (LOG_CTRL *lc); + +ST_VOID slogIpc (LOG_CTRL *lc, ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + ST_INT lineNum, ST_INT bufLen, + ST_CHAR *buf); + +ST_VOID slogMemInit (LOG_CTRL *lc); +ST_RET read_log_cfg_file (ST_CHAR *cfg_filename); +ST_RET slog_get_index_file_name (LOG_CTRL *lc, ST_CHAR *dest, ST_INT destLen); + +/************************************************************************/ + +/* dataType defines */ +#define _LOGCFG_DATATYPE_UINT_MASK 0 +#define _LOGCFG_DATATYPE_UINT32_MASK 1 +#define _LOGCFG_DATATYPE_RUINT32_MASK 2 +#define _LOGCFG_DATATYPE_BOOLEAN 3 +#define _LOGCFG_DATATYPE_INT 4 +#define _LOGCFG_DATATYPE_LONG 5 +#define _LOGCFG_DATATYPE_INT16 6 +#define _LOGCFG_DATATYPE_INT32 7 +#define _LOGCFG_DATATYPE_UINT 8 +#define _LOGCFG_DATATYPE_ULONG 9 +#define _LOGCFG_DATATYPE_UINT16 10 +#define _LOGCFG_DATATYPE_UINT32 11 +#define _LOGCFG_DATATYPE_STRING 12 +#define _LOGCFG_DATATYPE_STRINGBUF 13 +#define _LOGCFG_DATATYPE_DOUBLE 14 +#define _LOGCFG_DATATYPE_FILENAME 15 +#define _LOGCFG_DATATYPE_CALLBACK 16 + + +typedef struct + { + ST_CHAR *tag; /* NULL if must use perferredTag field */ + ST_UINT mask; + ST_VOID *addr; + ST_INT dataType; + ST_CHAR *description; /* NULL for no description */ + ST_CHAR *preferredTag; /* NULL if must use tag field */ + } LOGCFGX_VALUE_MAP; + +typedef struct + { + DBL_LNK l; + ST_CHAR *name; + ST_INT numMaskMap; + LOGCFGX_VALUE_MAP *maskMapTbl; + } LOGCFG_VALUE_GROUP; + + +ST_RET logcfgx_exx (LOG_CTRL *destLogCtrl, ST_CHAR *logFileName, ST_CHAR *fileNamePrefix, + ST_BOOLEAN masksOnly, ST_BOOLEAN saveTagVals, ST_CHAR *compName); +ST_RET logcfgx_ex (LOG_CTRL *destLogCtrl, ST_CHAR *logFileName, ST_CHAR *fileNamePrefix, + ST_BOOLEAN masksOnly, ST_BOOLEAN saveTagVals); +ST_VOID logCfgAddMaskGroup (LOGCFG_VALUE_GROUP *logMaskGroup); +ST_VOID logCfgRemoveMaskGroup (LOGCFG_VALUE_GROUP *logMaskGroup); +ST_VOID logCfgRemoveAllMaskGroups (ST_VOID); +ST_RET _logcfg_get_logmasks (ST_CHAR *xmlBuf, ST_INT *xmlSizeIo); +ST_INT _logcfg_get_logmasks_size (ST_VOID); + +/* ST_VOID (*logCfgCallbackFun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag, LOGCFGX_VALUE_MAP *valMap); */ + + +extern LOGCFG_VALUE_GROUP acseLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP adlcLogMaskMapCtrl; /* MMS-LITE */ +extern LOGCFG_VALUE_GROUP asn1LogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP clnpLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE */ +extern LOGCFG_VALUE_GROUP genlistDebugMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP gsLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP icfgLogMaskMapCtrl; /* ICCP-LITE */ +extern LOGCFG_VALUE_GROUP logcfgMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP logCfgLogCtrlMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP memDebugMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP memLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP miLogMaskMapCtrl; /* ICCP-LITE */ +extern LOGCFG_VALUE_GROUP mmsLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP mvlLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE */ +extern LOGCFG_VALUE_GROUP secLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP ssleLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP ssleASN1LogMaskMapCtrl; +extern LOGCFG_VALUE_GROUP smpLogMaskMapCtrl; /* MMS-LITE */ +extern LOGCFG_VALUE_GROUP sockLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP suicLogMaskMapCtrl; /* MMS-EASE */ +extern LOGCFG_VALUE_GROUP sxLogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP tp4LogMaskMapCtrl; /* MMS-LITE, ICCP-LITE, MMS-EASE */ +extern LOGCFG_VALUE_GROUP usrLogMaskMapCtrl; /* MMS-LITE */ +/* For 142-XXX products (MMS_EASE over Lite Stack) */ +extern LOGCFG_VALUE_GROUP ipcLogMaskMapCtrl; +extern LOGCFG_VALUE_GROUP sscLogMaskMapCtrl; + + +typedef struct + { + DBL_LNK l; + ST_CHAR *tag; + ST_CHAR *tagPath; + ST_INT dataType; + union + { + ST_BOOLEAN b; + ST_INT sInt; + ST_LONG sLong; + ST_INT16 sInt16; + ST_INT32 sInt32; + ST_UINT uInt; + ST_ULONG uLong; + ST_UINT16 uInt16; + ST_UINT32 uInt32; + ST_DOUBLE dbl; + ST_CHAR *str; + }u; + } LOGCFGX_TAG_VAL; + +LOGCFGX_TAG_VAL *logCfgFindTagVal (ST_CHAR *tag); +ST_VOID logCfgClearTagVals (ST_VOID); + + +/************************************************************************/ +/************************************************************************/ +/* logcfg_debug_sel bit assignments */ +#define LOGCFG_ERR 0x0001 +#define LOGCFG_NERR 0x0002 +#define LOGCFG_FLOW 0x0004 + +extern ST_UINT logcfg_debug_sel; + +/* Log type strings */ +extern SD_CONST ST_CHAR *SD_CONST _logcfg_log_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _logcfg_log_nerr_logstr; +extern SD_CONST ST_CHAR *SD_CONST _logcfg_log_flow_logstr; + +/************************************************************************/ +/* Err log macros */ +#define LOGCFG_ERR0(a) \ + SLOG_0 (logcfg_debug_sel & LOGCFG_ERR,_logcfg_log_err_logstr,a) +#define LOGCFG_ERR1(a,b) \ + SLOG_1 (logcfg_debug_sel & LOGCFG_ERR,_logcfg_log_err_logstr,a,b) +#define LOGCFG_ERR2(a,b,c) \ + SLOG_2 (logcfg_debug_sel & LOGCFG_ERR,_logcfg_log_err_logstr,a,b,c) +#define LOGCFG_ERR3(a,b,c,d) \ + SLOG_3 (logcfg_debug_sel & LOGCFG_ERR,_logcfg_log_err_logstr,a,b,c,d) +#define LOGCFG_ERR4(a,b,c,d,e) \ + SLOG_4 (logcfg_debug_sel & LOGCFG_ERR,_logcfg_log_err_logstr,a,b,c,d,e) + +/* Err continuation log macros */ +#define LOGCFG_CERR0(a) \ + SLOGC_0 (logcfg_debug_sel & LOGCFG_ERR,a) +#define LOGCFG_CERR1(a,b) \ + SLOGC_1 (logcfg_debug_sel & LOGCFG_ERR,a,b) +#define LOGCFG_CERR2(a,b,c) \ + SLOGC_2 (logcfg_debug_sel & LOGCFG_ERR,a,b,c) +#define LOGCFG_CERR3(a,b,c,d) \ + SLOGC_3 (logcfg_debug_sel & LOGCFG_ERR,a,b,c,d) +#define LOGCFG_CERR4(a,b,c,d,e) \ + SLOGC_4 (logcfg_debug_sel & LOGCFG_ERR,a,b,c,d,e) + +/************************************************************************/ +/* NErr log macros */ +#define LOGCFG_NERR0(a) \ + SLOG_0 (logcfg_debug_sel & LOGCFG_NERR,_logcfg_log_nerr_logstr,a) +#define LOGCFG_NERR1(a,b) \ + SLOG_1 (logcfg_debug_sel & LOGCFG_NERR,_logcfg_log_nerr_logstr,a,b) +#define LOGCFG_NERR2(a,b,c) \ + SLOG_2 (logcfg_debug_sel & LOGCFG_NERR,_logcfg_log_nerr_logstr,a,b,c) +#define LOGCFG_NERR3(a,b,c,d) \ + SLOG_3 (logcfg_debug_sel & LOGCFG_NERR,_logcfg_log_nerr_logstr,a,b,c,d) +#define LOGCFG_NERR4(a,b,c,d,e) \ + SLOG_4 (logcfg_debug_sel & LOGCFG_NERR,_logcfg_log_nerr_logstr,a,b,c,d,e) + +/* NErr continuation log macros */ +#define LOGCFG_CNERR0(a) \ + SLOGC_0 (logcfg_debug_sel & LOGCFG_NERR,a) +#define LOGCFG_CNERR1(a,b) \ + SLOGC_1 (logcfg_debug_sel & LOGCFG_NERR,a,b) +#define LOGCFG_CNERR2(a,b,c) \ + SLOGC_2 (logcfg_debug_sel & LOGCFG_NERR,a,b,c) +#define LOGCFG_CNERR3(a,b,c,d) \ + SLOGC_3 (logcfg_debug_sel & LOGCFG_NERR,a,b,c,d) +#define LOGCFG_CNERR4(a,b,c,d,e) \ + SLOGC_4 (logcfg_debug_sel & LOGCFG_NERR,a,b,c,d,e) + +/************************************************************************/ +/* Flow log macros */ +#define LOGCFG_FLOW0(a) \ + SLOG_0 (logcfg_debug_sel & LOGCFG_FLOW,_logcfg_log_flow_logstr,a) +#define LOGCFG_FLOW1(a,b) \ + SLOG_1 (logcfg_debug_sel & LOGCFG_FLOW,_logcfg_log_flow_logstr,a,b) +#define LOGCFG_FLOW2(a,b,c) \ + SLOG_2 (logcfg_debug_sel & LOGCFG_FLOW,_logcfg_log_flow_logstr,a,b,c) +#define LOGCFG_FLOW3(a,b,c,d) \ + SLOG_3 (logcfg_debug_sel & LOGCFG_FLOW,_logcfg_log_flow_logstr,a,b,c,d) +#define LOGCFG_FLOW4(a,b,c,d,e) \ + SLOG_4 (logcfg_debug_sel & LOGCFG_FLOW,_logcfg_log_flow_logstr,a,b,c,d,e) + +/* Flow continuation log macros */ +#define LOGCFG_CFLOW0(a) \ + SLOGC_0 (logcfg_debug_sel & LOGCFG_FLOW,a) +#define LOGCFG_CFLOW1(a,b) \ + SLOGC_1 (logcfg_debug_sel & LOGCFG_FLOW,a,b) +#define LOGCFG_CFLOW2(a,b,c) \ + SLOGC_2 (logcfg_debug_sel & LOGCFG_FLOW,a,b,c) +#define LOGCFG_CFLOW3(a,b,c,d) \ + SLOGC_3 (logcfg_debug_sel & LOGCFG_FLOW,a,b,c,d) +#define LOGCFG_CFLOW4(a,b,c,d,e) \ + SLOGC_4 (logcfg_debug_sel & LOGCFG_FLOW,a,b,c,d,e) + + +/************************************************************************/ +/************************************************************************/ +/* Global variables for the SLOG library. */ +/************************************************************************/ + +/* Log masks for different components of SISCO products. */ +extern ST_UINT gs_debug_sel; +extern ST_UINT clnp_debug_sel; + + +extern LOG_CTRL *sLogCtrl; +extern LOG_CTRL *sErrLogCtrl; + +extern ST_BOOLEAN sNonStandardLogMode; + +/************************************************************************/ +/* These elements are used for creating time strings */ +/************************************************************************/ + +extern ST_CHAR slogTimeText[TIME_BUF_LEN]; +ST_VOID slogSetTimeText (LOG_CTRL *lc); + +/************************************************************************/ +/* slog header defines and buffer */ +/************************************************************************/ + +#define SLOG_MAX_FNAME 64 +#define SLOG_MAX_LOGTYPESTR 40 /* logTypeStr cutoff if too long*/ +#define SLOG_MAX_HDR (2 + \ + TIME_BUF_LEN + \ + SLOG_MAX_LOGTYPESTR+1 + \ + SLOG_MAX_FNAME+14 + \ + 1 + 2) + +/* (2 NL , NL */ +/* TIME_BUF_LEN + slogTimeText buf size */ +/* SLOG_MAX_LOGTYPESTR+1 + limit for logTypeStr */ +/* SLOG_MAX_FNAME+14 + fName & lineNum formatting */ +/* 1 + 2) NL + 2 spaces before msg */ + +ST_VOID slogTrimFileName (ST_CHAR *dest, SD_CONST ST_CHAR *fullName); +ST_VOID slogSetHdr (LOG_CTRL *lc, SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + ST_CHAR *slogHdr, ST_CHAR *lineBreak); + +/************************************************************************/ +/* dynamic loging function */ +/************************************************************************/ + +extern ST_VOID (*slog_dyn_log_fun) (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); +extern ST_VOID (*_slog_dyn_log_fun) (LOG_CTRL *lc, + SD_CONST ST_CHAR *timeStr, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); + +/************************************************************************/ +/* This function pointer is invoked during slow SLOG operations, such */ +/* as 'clone' and 'find oldest message' */ + +extern ST_VOID (*slog_service_fun) (ST_VOID); + +/************************************************************************/ +/* Remote logging function */ +/************************************************************************/ + +extern ST_VOID (*slog_remote_fun) (ST_UINT32 slog_remote_flags, + LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); + +extern ST_VOID (*_slog_remote_fun) (ST_UINT32 slog_remote_flags, + LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); + +/* Parameter for use with remote logging function pointer */ +/* SLOG will pass this global variable to the slog_remote_fun function */ +extern ST_UINT32 slogRemoteFlags; + +/************************************************************************/ +/* Standard dynamic logging control definitions */ +/************************************************************************/ +/* These macros are OBSOLETE. They now do nothing. Previously they */ +/* passed logType values of SLOG_DYN_PAUSE, SLOG_DYN_LF, SLOG_DYN_CLRSCR*/ +/* respectively to slog. */ + +#define SLOG_PAUSE(lc,msg) +#define SLOG_LF(lc) +#define SLOG_CLRSCR(lc) + +/************************************************************************/ +/* Base macro types, useful for typical user logging, to reduce user */ +/* macro verbosity */ +/************************************************************************/ + +#define SLOGH1(lc,mask,id,x,y) {\ + if (lc->logMask1 & mask)\ + slogHex (sLogCtrl,id, thisFileName,__LINE__,x,y);} + + +#define SLOGH2(lc,mask,id,x,y) {\ + if (lc->logMask2 & mask)\ + slogHex (sLogCtrl,id, thisFileName,__LINE__,x,y);} + +#define SLOGH3(lc,mask,id,x,y) {\ + if (lc->logMask3 & mask)\ + slogHex (sLogCtrl,id, thisFileName,__LINE__,x,y);} + +#define SLOGH4(lc,mask,id,x,y) {\ + if (lc->logMask4 & mask)\ + slogHex (sLogCtrl,id, thisFileName,__LINE__,x,y);} + +#define SLOGH5(lc,mask,id,x,y) {\ + if (lc->logMask5 & mask)\ + slogHex (sLogCtrl,id, thisFileName,__LINE__,x,y);} + +#define SLOGH6(lc,mask,id,x,y) {\ + if (lc->logMask6 & mask)\ + slogHex (sLogCtrl,id, thisFileName,__LINE__,x,y);} + + + +/* ******************* LOG MASK 1 MACROS ************************* */ + +#define SLOG1_0(lc,mask,id,a) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a);\ + } + +#define SLOG1_1(lc,mask,id,a,b) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b);\ + } + +#define SLOG1_2(lc,mask,id,a,b,c) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c);\ + } + +#define SLOG1_3(lc,mask,id,a,b,c,d) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d);\ + } + +#define SLOG1_4(lc,mask,id,a,b,c,d,e) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define SLOG1_5(lc,mask,id,a,b,c,d,e,f) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +#define SLOG1_6(lc,mask,id,a,b,c,d,e,f,g) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + +#define SLOG1_7(lc,mask,id,a,b,c,d,e,f,g,h) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h);\ + } + +#define SLOG1_8(lc,mask,id,a,b,c,d,e,f,g,h,i) {\ + if (lc->logMask1 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i);\ + } + + + +/* ******************* LOG MASK 2 MACROS ************************* */ +#define SLOG2_0(lc,mask,id,a) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a);\ + } + +#define SLOG2_1(lc,mask,id,a,b) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b);\ + } + +#define SLOG2_2(lc,mask,id,a,b,c) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c);\ + } + +#define SLOG2_3(lc,mask,id,a,b,c,d) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d);\ + } + +#define SLOG2_4(lc,mask,id,a,b,c,d,e) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define SLOG2_5(lc,mask,id,a,b,c,d,e,f) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +#define SLOG2_6(lc,mask,id,a,b,c,d,e,f,g) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + +#define SLOG2_7(lc,mask,id,a,b,c,d,e,f,g,h) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h);\ + } + +#define SLOG2_8(lc,mask,id,a,b,c,d,e,f,g,h,i) {\ + if (lc->logMask2 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i);\ + } + + + +/* ******************* LOG MASK 3 MACROS ************************* */ +#define SLOG3_0(lc,mask,id,a) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a);\ + } + +#define SLOG3_1(lc,mask,id,a,b) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b);\ + } + +#define SLOG3_2(lc,mask,id,a,b,c) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c);\ + } + +#define SLOG3_3(lc,mask,id,a,b,c,d) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d);\ + } + +#define SLOG3_4(lc,mask,id,a,b,c,d,e) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define SLOG3_5(lc,mask,id,a,b,c,d,e,f) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +#define SLOG3_6(lc,mask,id,a,b,c,d,e,f,g) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + +#define SLOG3_7(lc,mask,id,a,b,c,d,e,f,g,h) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h);\ + } + +#define SLOG3_8(lc,mask,id,a,b,c,d,e,f,g,h,i) {\ + if (lc->logMask3 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i);\ + } + + + +/* ******************* LOG MASK 4 MACROS ************************* */ +#define SLOG4_0(lc,mask,id,a) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a);\ + } + +#define SLOG4_1(lc,mask,id,a,b) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b);\ + } + +#define SLOG4_2(lc,mask,id,a,b,c) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c);\ + } + +#define SLOG4_3(lc,mask,id,a,b,c,d) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d);\ + } + +#define SLOG4_4(lc,mask,id,a,b,c,d,e) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define SLOG4_5(lc,mask,id,a,b,c,d,e,f) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +#define SLOG4_6(lc,mask,id,a,b,c,d,e,f,g) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + +#define SLOG4_7(lc,mask,id,a,b,c,d,e,f,g,h) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h);\ + } + +#define SLOG4_8(lc,mask,id,a,b,c,d,e,f,g,h,i) {\ + if (lc->logMask4 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i);\ + } + + + + +/* ******************* LOG MASK 5 MACROS ************************* */ +#define SLOG5_0(lc,mask,id,a) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a);\ + } + +#define SLOG5_1(lc,mask,id,a,b) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b);\ + } + +#define SLOG5_2(lc,mask,id,a,b,c) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c);\ + } + +#define SLOG5_3(lc,mask,id,a,b,c,d) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d);\ + } + +#define SLOG5_4(lc,mask,id,a,b,c,d,e) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define SLOG5_5(lc,mask,id,a,b,c,d,e,f) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +#define SLOG5_6(lc,mask,id,a,b,c,d,e,f,g) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + +#define SLOG5_7(lc,mask,id,a,b,c,d,e,f,g,h) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h);\ + } + +#define SLOG5_8(lc,mask,id,a,b,c,d,e,f,g,h,i) {\ + if (lc->logMask5 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i);\ + } + + + +/* ******************* LOG MASK 6 MACROS ************************* */ +#define SLOG6_0(lc,mask,id,a) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a);\ + } + +#define SLOG6_1(lc,mask,id,a,b) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b);\ + } + +#define SLOG6_2(lc,mask,id,a,b,c) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c);\ + } + +#define SLOG6_3(lc,mask,id,a,b,c,d) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d);\ + } + +#define SLOG6_4(lc,mask,id,a,b,c,d,e) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e);\ + } + +#define SLOG6_5(lc,mask,id,a,b,c,d,e,f) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f);\ + } + +#define SLOG6_6(lc,mask,id,a,b,c,d,e,f,g) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + +#define SLOG6_7(lc,mask,id,a,b,c,d,e,f,g,h) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h);\ + } + +#define SLOG6_8(lc,mask,id,a,b,c,d,e,f,g,h,i) {\ + if (lc->logMask6 & mask)\ + slog (sLogCtrl,id, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i);\ + } + + + +/************************************************************************/ +/************************************************************************/ +#if defined(DEBUG_SISCO) +/************************************************************************/ + +extern ST_CHAR *_slogAlwaysLogTypeStr; +extern ST_CHAR *_slogXMLLogTypeStr; + +#define SLOGALWAYS0(a) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a) +#define SLOGALWAYS1(a,b) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b) +#define SLOGALWAYS2(a,b,c) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c) +#define SLOGALWAYS3(a,b,c,d) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d) +#define SLOGALWAYS4(a,b,c,d,e) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e) +#define SLOGALWAYS5(a,b,c,d,e,f) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e,f) +#define SLOGALWAYS6(a,b,c,d,e,f,g) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e,f,g) +#define SLOGALWAYS7(a,b,c,d,e,f,g,h) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e,f,g,h) +#define SLOGALWAYS8(a,b,c,d,e,f,g,h,i) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i) +#define SLOGALWAYS9(a,b,c,d,e,f,g,h,i,j) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i,j) +#define SLOGALWAYS10(a,b,c,d,e,f,g,h,i,j,k) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i,j,k) +#define SLOGALWAYS11(a,b,c,d,e,f,g,h,i,j,k,l) \ + _slog (sLogCtrl,_slogAlwaysLogTypeStr, thisFileName,__LINE__,a,b,c,d,e,f,g,h,i,j,k,l) + +#define SLOGCALWAYS0(a) \ + _slogc (sLogCtrl,a) +#define SLOGCALWAYS1(a,b) \ + _slogc (sLogCtrl,a,b) +#define SLOGCALWAYS2(a,b,c) \ + _slogc (sLogCtrl,a,b,c) +#define SLOGCALWAYS3(a,b,c,d) \ + _slogc (sLogCtrl,a,b,c,d) +#define SLOGCALWAYS4(a,b,c,d,e) \ + _slogc (sLogCtrl,a,b,c,d,e) +#define SLOGCALWAYS5(a,b,c,d,e,f) \ + _slogc (sLogCtrl,a,b,c,d,e,f) +#define SLOGCALWAYS6(a,b,c,d,e,f,g) \ + _slogc (sLogCtrl,a,b,c,d,e,f,g) +#define SLOGCALWAYS7(a,b,c,d,e,f,g,h) \ + _slogc (sLogCtrl,a,b,c,d,e,f,g,h) +#define SLOGCALWAYS8(a,b,c,d,e,f,g,h,i) \ + _slogc (sLogCtrl,a,b,c,d,e,f,g,h,i) + +#define SLOGALWAYSH(numBytes,dataPtr) \ + _slogHex (sLogCtrl, numBytes, dataPtr) + +#define SLOGALWAYSS(dataPtr) \ + _slogStr (sLogCtrl, dataPtr) + +#define SLOGALWAYSX(numBytes, dataPtr) \ + _slogXML (sLogCtrl, _slogXMLLogTypeStr, thisFileName, __LINE__, numBytes, dataPtr) + +/************************************************************************/ +#else /* #if defined(DEBUG_SISCO) */ +/************************************************************************/ + +#define SLOGALWAYS0(a) +#define SLOGALWAYS1(a,b) +#define SLOGALWAYS2(a,b,c) +#define SLOGALWAYS3(a,b,c,d) +#define SLOGALWAYS4(a,b,c,d,e) +#define SLOGALWAYS5(a,b,c,d,e,f) +#define SLOGALWAYS6(a,b,c,d,e,f,g) +#define SLOGALWAYS7(a,b,c,d,e,f,g,h) +#define SLOGALWAYS8(a,b,c,d,e,f,g,h,i) +#define SLOGALWAYS9(a,b,c,d,e,f,g,h,i,j) +#define SLOGALWAYS10(a,b,c,d,e,f,g,h,i,j,k) +#define SLOGALWAYS11(a,b,c,d,e,f,g,h,i,j,k,l) +#define SLOGCALWAYS0(a) +#define SLOGCALWAYS1(a,b) +#define SLOGCALWAYS2(a,b,c) +#define SLOGCALWAYS3(a,b,c,d) +#define SLOGCALWAYS4(a,b,c,d,e) +#define SLOGCALWAYS5(a,b,c,d,e,f) +#define SLOGCALWAYS6(a,b,c,d,e,f,g) +#define SLOGCALWAYS7(a,b,c,d,e,f,g,h) +#define SLOGCALWAYS8(a,b,c,d,e,f,g,h,i) +#define SLOGALWAYSH(numBytes,dataPtr) +#define SLOGALWAYSS(dataPtr) +#define SLOGALWAYSX(numBytes,dataPtr) + +#endif +/************************************************************************/ + +/************************************************************************/ +/* "Base" set of macros. */ +/* All other LOG macros should call these macros. */ +/* TRICK: These macros all use "do{...}while(0)". */ +/* This works in any context without adding extra {}. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +/* Basic log macros (all call _slog) */ +#define SLOG_0(ena,str,fmt) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt);} while(0) + +#define SLOG_1(ena,str,fmt,a) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a);} while(0) + +#define SLOG_2(ena,str,fmt,a,b) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a,b);} while(0) + +#define SLOG_3(ena,str,fmt,a,b,c) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c);} while(0) + +#define SLOG_4(ena,str,fmt,a,b,c,d) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d);} while(0) + +#define SLOG_5(ena,str,fmt,a,b,c,d,e) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e);} while(0) + +#define SLOG_6(ena,str,fmt,a,b,c,d,e,f) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e,f);} while(0) + +#define SLOG_7(ena,str,fmt,a,b,c,d,e,f,g) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e,f,g);} while(0) + +#define SLOG_8(ena,str,fmt,a,b,c,d,e,f,g,h) \ + do {if (ena) _slog (sLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e,f,g,h);} while(0) + +/* Continuation macros (all call _slogc). */ +#define SLOGC_0(ena,fmt) \ + do {if (ena) _slogc (sLogCtrl,fmt);} while(0) + +#define SLOGC_1(ena,fmt,a) \ + do {if (ena) _slogc (sLogCtrl,fmt,a);} while(0) + +#define SLOGC_2(ena,fmt,a,b) \ + do {if (ena) _slogc (sLogCtrl,fmt,a,b);} while(0) + +#define SLOGC_3(ena,fmt,a,b,c) \ + do {if (ena) _slogc (sLogCtrl,fmt,a,b,c);} while(0) + +#define SLOGC_4(ena,fmt,a,b,c,d) \ + do {if (ena) _slogc (sLogCtrl,fmt,a,b,c,d);} while(0) + +#define SLOGC_5(ena,fmt,a,b,c,d,e) \ + do {if (ena) _slogc (sLogCtrl,fmt,a,b,c,d,e);} while(0) + +#define SLOGC_6(ena,fmt,a,b,c,d,e,f) \ + do {if (ena) _slogc (sLogCtrl,fmt,a,b,c,d,e,f);} while(0) + +#define SLOGC_7(ena,fmt,a,b,c,d,e,f,g) \ + do {if (ena) _slogc (sLogCtrl,fmt,a,b,c,d,e,f,g);} while(0) + +#define SLOGC_8(ena,fmt,a,b,c,d,e,f,g,h) \ + do {if (ena) _slogc (sLogCtrl,fmt,a,b,c,d,e,f,g,h);} while(0) + +/* Hex logging macro (calls _slogHex) */ +#define SLOGH(ena,num,ptr) \ + do {if (ena) _slogHex (sLogCtrl,num,ptr);} while(0) + +/* XML logging macro (calls _slogXML) */ +#define SLOGX(ena,num,ptr) \ + do {if (ena) _slogXML (sLogCtrl, _slogXMLLogTypeStr, thisFileName, __LINE__, num, ptr);} while(0) + +#else /* !DEBUG_SISCO */ + +/* Non-DEBUG macros for EVERYONE! Yeah!! Never have to create another one.*/ +/* Basic log macros (do nothing) */ +#define SLOG_0(ena,str,fmt) +#define SLOG_1(ena,str,fmt,a) +#define SLOG_2(ena,str,fmt,a,b) +#define SLOG_3(ena,str,fmt,a,b,c) +#define SLOG_4(ena,str,fmt,a,b,c,d) +#define SLOG_5(ena,str,fmt,a,b,c,d,e) +#define SLOG_6(ena,str,fmt,a,b,c,d,e,f) +#define SLOG_7(ena,str,fmt,a,b,c,d,e,f,g) +#define SLOG_8(ena,str,fmt,a,b,c,d,e,f,g,h) + +/* Continuation macros (do nothing). */ +#define SLOGC_0(ena,fmt) +#define SLOGC_1(ena,fmt,a) +#define SLOGC_2(ena,fmt,a,b) +#define SLOGC_3(ena,fmt,a,b,c) +#define SLOGC_4(ena,fmt,a,b,c,d) +#define SLOGC_5(ena,fmt,a,b,c,d,e) +#define SLOGC_6(ena,fmt,a,b,c,d,e,f) +#define SLOGC_7(ena,fmt,a,b,c,d,e,f,g) +#define SLOGC_8(ena,fmt,a,b,c,d,e,f,g,h) + +/* Hex logging macro (do nothing) */ +#define SLOGH(ena,num,ptr) +/* XML logging macro (do nothing) */ +#define SLOGX(ena,num,ptr) +#endif /* !DEBUG_SISCO */ + + +/************************************************************************/ +/* "Base" set of macros for error log */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +/* Basic log macros (all call _slog) */ +#define SELOG_0(ena,str,fmt) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt);} while(0) + +#define SELOG_1(ena,str,fmt,a) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a);} while(0) + +#define SELOG_2(ena,str,fmt,a,b) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a,b);} while(0) + +#define SELOG_3(ena,str,fmt,a,b,c) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c);} while(0) + +#define SELOG_4(ena,str,fmt,a,b,c,d) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d);} while(0) + +#define SELOG_5(ena,str,fmt,a,b,c,d,e) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e);} while(0) + +#define SELOG_6(ena,str,fmt,a,b,c,d,e,f) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e,f);} while(0) + +#define SELOG_7(ena,str,fmt,a,b,c,d,e,f,g) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e,f,g);} while(0) + +#define SELOG_8(ena,str,fmt,a,b,c,d,e,f,g,h) \ + do {if (ena) _slog (sErrLogCtrl,str,thisFileName,__LINE__,fmt,a,b,c,d,e,f,g,h);} while(0) + +/* Continuation macros (all call _slogc). */ +#define SELOGC_0(ena,fmt) \ + do {if (ena) _slogc (sErrLogCtrl,fmt);} while(0) + +#define SELOGC_1(ena,fmt,a) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a);} while(0) + +#define SELOGC_2(ena,fmt,a,b) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a,b);} while(0) + +#define SELOGC_3(ena,fmt,a,b,c) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a,b,c);} while(0) + +#define SELOGC_4(ena,fmt,a,b,c,d) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a,b,c,d);} while(0) + +#define SELOGC_5(ena,fmt,a,b,c,d,e) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a,b,c,d,e);} while(0) + +#define SELOGC_6(ena,fmt,a,b,c,d,e,f) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a,b,c,d,e,f);} while(0) + +#define SELOGC_7(ena,fmt,a,b,c,d,e,f,g) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a,b,c,d,e,f,g);} while(0) + +#define SELOGC_8(ena,fmt,a,b,c,d,e,f,g,h) \ + do {if (ena) _slogc (sErrLogCtrl,fmt,a,b,c,d,e,f,g,h);} while(0) + +/* Hex logging macro (calls _slogHex) */ +#define SELOGH(ena,num,ptr) \ + do {if (ena) _slogHex (sErrLogCtrl,num,ptr);} while(0) + +/* XML logging macro (calls _slogXML) */ +#define SELOGX(ena,num,ptr) \ + do {if (ena) _slogXML (sErrLogCtrl, _slogXMLLogTypeStr, thisFileName, __LINE__, num, ptr);} while(0) + +#else /* !DEBUG_SISCO */ + +/* Non-DEBUG macros for EVERYONE! Yeah!! Never have to create another one.*/ +/* Basic log macros (do nothing) */ +#define SELOG_0(ena,str,fmt) +#define SELOG_1(ena,str,fmt,a) +#define SELOG_2(ena,str,fmt,a,b) +#define SELOG_3(ena,str,fmt,a,b,c) +#define SELOG_4(ena,str,fmt,a,b,c,d) +#define SELOG_5(ena,str,fmt,a,b,c,d,e) +#define SELOG_6(ena,str,fmt,a,b,c,d,e,f) +#define SELOG_7(ena,str,fmt,a,b,c,d,e,f,g) +#define SELOG_8(ena,str,fmt,a,b,c,d,e,f,g,h) + +/* Continuation macros (do nothing). */ +#define SELOGC_0(ena,fmt) +#define SELOGC_1(ena,fmt,a) +#define SELOGC_2(ena,fmt,a,b) +#define SELOGC_3(ena,fmt,a,b,c) +#define SELOGC_4(ena,fmt,a,b,c,d) +#define SELOGC_5(ena,fmt,a,b,c,d,e) +#define SELOGC_6(ena,fmt,a,b,c,d,e,f) +#define SELOGC_7(ena,fmt,a,b,c,d,e,f,g) +#define SELOGC_8(ena,fmt,a,b,c,d,e,f,g,h) + +/* Hex logging macro (do nothing) */ +#define SELOGH(ena,num,ptr) +/* XML logging macro (do nothing) */ +#define SELOGX(ena,num,ptr) +#endif /* !DEBUG_SISCO */ + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + diff --git a/mmslib/inc/smp.h b/mmslib/inc/smp.h new file mode 100644 index 0000000..739c156 --- /dev/null +++ b/mmslib/inc/smp.h @@ -0,0 +1,110 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : smp.h */ +/* PRODUCT(S) : UCA Station Management Protocol (UCA SMP). */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file specifies internal defines and function */ +/* prototypes for UCA Station Management Protocol (UCA SMP). */ +/* */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/09/96 EJV 01 Created */ +/************************************************************************/ + +#ifndef SMP_INCLUDED +#define SMP_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + + /*--------------------------------------*/ + /* LLC level encoding values */ + /*--------------------------------------*/ + + /* (same in clnp_llc.h) */ +#define LLC_LSAP_SMP (ST_UCHAR) 0xFB /* For UCA SMP (Station Mgt Prot) */ +#define LLC_CONTROL_SMP (ST_UCHAR) 0x03 /* For UCA SMP (Station Mgt Prot) */ + + /*--------------------------------------*/ + /* Max size of Autorization field */ + /*--------------------------------------*/ + +#define SMP_SIZE_OF_AUTH 8 + + /*----------------------------------------------*/ + /* Valid codes SMP UCA PDU type */ + /*----------------------------------------------*/ + +#define SMP_UCA_PDU_ERROR 0 +#define SMP_UCA_PDU_TIMESYNC 1 + +#define SMP_PDU_INVALID_TYPE 255 + + /*----------------------------------------------*/ + /* Valid codes for TimeSync PDU type */ + /*----------------------------------------------*/ + +#define SMP_TIMESYNC_PDU_MEASURE_REQ 0 +#define SMP_TIMESYNC_PDU_MEASURE_RSP 1 +#define SMP_TIMESYNC_PDU_SYNC_REQ 2 +#define SMP_TIMESYNC_PDU_SYNC_RSP 3 +#define SMP_TIMESYNC_PDU_ERROR 4 +#define SMP_TIMESYNC_PDU_PREPARE 5 + + + /*----------------------------------------------*/ + /* Valid error codes in the UCA ErrorPDU */ + /*----------------------------------------------*/ + +#define SMP_ERR_NO_ERROR 0 +#define SMP_ERR_UNSUPPORTED 1 +#define SMP_ERR_UNRECOGNIZED_SERVICE 2 +#define SMP_ERR_PDU_ERROR 3 +#define SMP_ERR_OUT_OF_RESOURCES 4 + + /*----------------------------------------------*/ + /* Valid error codes in the Sync-ErrorPDU */ + /*----------------------------------------------*/ + +#define SMP_SYNC_ERR_NO_ERROR 0 +#define SMP_SYNC_ERR_LOCALLY_SYNCED 1 +#define SMP_SYNC_ERR_NOT_AUTHORIZED 2 +#define SMP_SYNC_ERR_NOT_MEASURED 3 +#define SMP_SYNC_ERR_SEQUENCE_PROBLEM 4 + + /*--------------------------------------*/ + /* globals in smp_dec.c module */ + /*--------------------------------------*/ + +extern ST_UCHAR smp_uca_pdu_type; +extern ST_UCHAR smp_err_code; +extern ST_UCHAR smp_timesync_pdu_type; +extern SMP_TIME smp_time_req; +extern SMP_TIME smp_time_rsp; +extern ST_UCHAR smp_auth [SMP_SIZE_OF_AUTH]; /* authentication */ +extern SMP_TIME smp_delta_time; +extern ST_UCHAR smp_sync_err_code; + +ST_RET smp_dec_uca_pdu (ST_UCHAR *pdu_buf, ST_UINT16 pdu_len); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + diff --git a/mmslib/inc/smp_log.h b/mmslib/inc/smp_log.h new file mode 100644 index 0000000..0b60ca4 --- /dev/null +++ b/mmslib/inc/smp_log.h @@ -0,0 +1,286 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : smp_log.h */ +/* PRODUCT(S) : UCA Station Management Protocol (UCA SMP). */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file contains logging macros for SMP. */ +/* Note: To compile logging functions use the DEBUG_SISCO define */ +/* in the project make file. */ +/* */ +/* MODIFICATION LOG : */ +/* */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 10/08/98 MDE 05 Migrated to updated SLOG interface */ +/* 02/20/98 EJV 04 Corrected non-debug macro def */ +/* 11/17/97 EJV 03 Added check for HEX logging mask */ +/* 10/15/97 MDE 02 Added missing no debug macros */ +/* 09/09/97 EJV 01 Created */ +/************************************************************************/ + +#ifndef SMP_LOG_INCLUDED +#define SMP_LOG_INCLUDED + +#include "slog.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* NOTE: SMP uses log masks defined in the smp_usr.h set in the smp_debug_sel */ + + +#if defined(DEBUG_SISCO) + +/* Log type strings */ +extern SD_CONST ST_CHAR *SD_CONST _smp_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smp_req_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smp_ind_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smp_deb_logstr; +extern SD_CONST ST_CHAR *SD_CONST _smp_hex_logstr; + + /*--------------------------------------------*/ + /* hard errors logging */ + /*--------------------------------------------*/ + + #define SMP_LOG_ERR0(a) {\ + if (smp_debug_sel & SMP_LOG_ERR)\ + _slog (sLogCtrl,_smp_err_logstr,thisFileName,__LINE__,a);\ + } + #define SMP_LOG_ERR1(a,b) {\ + if (smp_debug_sel & SMP_LOG_ERR)\ + _slog (sLogCtrl,_smp_err_logstr,thisFileName,__LINE__,a,b);\ + } + #define SMP_LOG_ERR2(a,b,c) {\ + if (smp_debug_sel & SMP_LOG_ERR)\ + _slog (sLogCtrl,_smp_err_logstr,thisFileName,__LINE__,a,b,c);\ + } + #define SMP_LOG_ERR3(a,b,c,d) {\ + if (smp_debug_sel & SMP_LOG_ERR)\ + _slog (sLogCtrl,_smp_err_logstr,thisFileName,__LINE__,a,b,c,d);\ + } + + /*--------------------------------------------*/ + /* SMP-user request logging */ + /*--------------------------------------------*/ + + #define SMP_LOG_REQ0(a) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slog (sLogCtrl,_smp_req_logstr,thisFileName,__LINE__,a);\ + } + #define SMP_LOG_REQ1(a,b) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slog (sLogCtrl,_smp_req_logstr,thisFileName,__LINE__,a,b);\ + } + #define SMP_LOG_REQ2(a,b,c) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slog (sLogCtrl,_smp_req_logstr,thisFileName,__LINE__,a,b,c);\ + } + #define SMP_LOG_REQ3(a,b,c,d) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slog (sLogCtrl,_smp_req_logstr,thisFileName,__LINE__,a,b,c,d);\ + } + #define SMP_LOG_REQ6(a,b,c,d,e,f,g) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slog (sLogCtrl,_smp_req_logstr,thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + + /* continuation log */ + #define SMP_LOGC_REQ0(a) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slogc (sLogCtrl,a);\ + } + #define SMP_LOGC_REQ1(a,b) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slogc (sLogCtrl,a,b);\ + } + #define SMP_LOGC_REQ2(a,b,c) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slogc (sLogCtrl,a,b,c);\ + } + #define SMP_LOGC_REQ6(a,b,c,d,e,f,g) {\ + if (smp_debug_sel & SMP_LOG_REQ)\ + _slogc (sLogCtrl,a,b,c,d,e,f,g);\ + } + + /* hex logging */ + #define SMP_LOGH_REQ(a,b) {\ + if (smp_debug_sel & SMP_LOG_REQ && \ + smp_debug_sel & SMP_LOG_HEX)\ + _slogHex (sLogCtrl,a,b);\ + } + + /* hex continuation logging */ + #define SMP_LOGHC_REQ(a,b) {\ + if (smp_debug_sel & SMP_LOG_REQ && \ + smp_debug_sel & SMP_LOG_HEX)\ + _slogHex (sLogCtrl,a,b);\ + } + /*--------------------------------------------*/ + /* SMP_user indication logging */ + /*--------------------------------------------*/ + + #define SMP_LOG_IND0(a) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slog (sLogCtrl,_smp_ind_logstr,thisFileName,__LINE__,a);\ + } + #define SMP_LOG_IND1(a,b) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slog (sLogCtrl,_smp_ind_logstr,thisFileName,__LINE__,a,b);\ + } + #define SMP_LOG_IND2(a,b,c) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slog (sLogCtrl,_smp_ind_logstr,thisFileName,__LINE__,a,b,c);\ + } + #define SMP_LOG_IND3(a,b,c,d) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slog (sLogCtrl,_smp_ind_logstr,thisFileName,__LINE__,a,b,c,d);\ + } + #define SMP_LOG_IND6(a,b,c,d,e,f,g) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slog (sLogCtrl,_smp_ind_logstr,thisFileName,__LINE__,a,b,c,d,e,f,g);\ + } + /* continuation log */ + #define SMP_LOGC_IND0(a) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slogc (sLogCtrl,a);\ + } + #define SMP_LOGC_IND1(a,b) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slogc (sLogCtrl,a,b);\ + } + #define SMP_LOGC_IND2(a,b,c) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slogc (sLogCtrl,a,b,c);\ + } + #define SMP_LOGC_IND6(a,b,c,d,e,f,g) {\ + if (smp_debug_sel & SMP_LOG_IND)\ + _slogc (sLogCtrl,a,b,c,d,e,f,g);\ + } + + /* hex logging */ + #define SMP_LOGH_IND(a,b) {\ + if (smp_debug_sel & SMP_LOG_IND && \ + smp_debug_sel & SMP_LOG_HEX)\ + _slogHex (sLogCtrl,a,b);\ + } + + /* hex continuation logging */ + #define SMP_LOGHC_IND(a,b) {\ + if (smp_debug_sel & SMP_LOG_IND && \ + smp_debug_sel & SMP_LOG_HEX)\ + _slogHex (sLogCtrl,a,b);\ + } + + /*--------------------------------------------*/ + /* debugging app logging */ + /*--------------------------------------------*/ + + #define SMP_LOG_DEB0(a) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slog (sLogCtrl,_smp_deb_logstr,thisFileName,__LINE__,a);\ + } + #define SMP_LOG_DEB1(a,b) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slog (sLogCtrl,_smp_deb_logstr,thisFileName,__LINE__,a,b);\ + } + #define SMP_LOG_DEB2(a,b,c) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slog (sLogCtrl,_smp_deb_logstr,thisFileName,__LINE__,a,b,c);\ + } + #define SMP_LOG_DEB3(a,b,c,d) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slog (sLogCtrl,_smp_deb_logstr,thisFileName,__LINE__,a,b,c,d);\ + } + + #define SMP_LOGC_DEB0(a) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slogc (sLogCtrl,a);\ + } + #define SMP_LOGC_DEB1(a,b) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slogc (sLogCtrl,a,b);\ + } + #define SMP_LOGC_DEB2(a,b,c) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slogc (sLogCtrl,a,b,c);\ + } + #define SMP_LOGC_DEB3(a,b,c,d) {\ + if (smp_debug_sel & SMP_LOG_DEB)\ + _slogc (sLogCtrl,a,b,c,d);\ + } + +#else + + /* this are empty macros for compilation without the DEBUG_SISCO define */ + + /*--------------------------------------------*/ + /* hard errors logging */ + /*--------------------------------------------*/ + #define SMP_LOG_ERR0(a) + #define SMP_LOG_ERR1(a,b) + #define SMP_LOG_ERR2(a,b,c) + #define SMP_LOG_ERR3(a,b,c,d) + + /*--------------------------------------------*/ + /* SMP-user request (write) logging */ + /*--------------------------------------------*/ + + #define SMP_LOG_REQ0(a) + #define SMP_LOG_REQ1(a,b) + #define SMP_LOG_REQ2(a,b,c) + #define SMP_LOG_REQ3(a,b,c,d) + #define SMP_LOG_REQ6(a,b,c,d,e,f,g) + #define SMP_LOGC_REQ0(a) + #define SMP_LOGC_REQ1(a,b) + #define SMP_LOGC_REQ2(a,b,c) + #define SMP_LOGC_REQ6(a,b,c,d,e,f,g) + #define SMP_LOGH_REQ(a,b) + #define SMP_LOGHC_REQ(a,b) + + /*--------------------------------------------*/ + /* SMP-user indication (read) logging */ + /*--------------------------------------------*/ + + #define SMP_LOG_IND0(a) + #define SMP_LOG_IND1(a,b) + #define SMP_LOG_IND2(a,b,c) + #define SMP_LOG_IND3(a,b,c,d) + #define SMP_LOG_IND6(a,b,c,d,e,f,g) + #define SMP_LOGC_IND0(a) + #define SMP_LOGC_IND1(a,b) + #define SMP_LOGC_IND2(a,b,c) + #define SMP_LOGC_IND6(a,b,c,d,e,f,g) + #define SMP_LOGH_IND(a,b) + #define SMP_LOGHC_IND(a,b) + + /*--------------------------------------------*/ + /* debugging app logging */ + /*--------------------------------------------*/ + + #define SMP_LOG_DEB0(a) + #define SMP_LOG_DEB1(a,b) + #define SMP_LOG_DEB2(a,b,c) + #define SMP_LOG_DEB3(a,b,c,d) + #define SMP_LOGC_DEB0(a) + #define SMP_LOGC_DEB1(a,b) + #define SMP_LOGC_DEB2(a,b,c) + #define SMP_LOGC_DEB3(a,b,c,d) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ diff --git a/mmslib/inc/smp_usr.h b/mmslib/inc/smp_usr.h new file mode 100644 index 0000000..dc3030e --- /dev/null +++ b/mmslib/inc/smp_usr.h @@ -0,0 +1,344 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997 - 1998, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : smp_usr.h */ +/* PRODUCT(S) : UCA Station Management Protocol (UCA SMP). */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module provides interface function to the SLAVE/MASTER */ +/* side of the UCA Station Management Protocol. */ +/* */ +/* Implemented Services: */ +/* Time Synchronization */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/18/98 EJV 04 Added smp_init function. */ +/* 11/17/97 EJV 03 Added HEX logging. Added par to smp_hc_config*/ +/* 10/13/97 EJV 02 Added defs for DLL. */ +/* 09/09/97 EJV 01 Created */ +/************************************************************************/ + +#ifndef SMP_USR_INCLUDED +#define SMP_USR_INCLUDED + + +#ifdef __cplusplus +extern "C" { +#endif + + /*--------------------------------------*/ + /* Max size of MAC and NSAP */ + /* (same in clnp_llc.h) */ + /*--------------------------------------*/ + +#define SMP_MAX_LEN_MAC 6 +#define SMP_MAX_LEN_NSAP 20 + + + /*--------------------------------------*/ + /* SMP logging types (for debugging) */ + /*--------------------------------------*/ + +#define SMP_LOG_ERR 0x00000001L +#define SMP_LOG_REQ 0x00000010L +#define SMP_LOG_IND 0x00000020L +#define SMP_LOG_DEB 0x00000040L +#define SMP_LOG_HEX 0x00000080L + +extern ST_UINT smp_debug_sel; + + /*--------------------------------------*/ + /* SMP_TIME struct */ + /*--------------------------------------*/ + +#define SMP_SIZE_OF_REC_TIME 32 /* buf size used to record binary time */ + +#define SMP_SIZE_OF_TIME 6 /* TimeOfDay size, see ISO/IEC 9506-2, clause 7.6.1 */ + +typedef struct + { + ST_INT32 days; /* number of days since January 1, 1984 */ + ST_INT32 msec; /* milliseconds since midnight for the current date */ + ST_INT32 usec; /* microseconds whithin current msec, if implemented */ + } SMP_TIME; + +/* This struct is used also to pass the time difference returned from */ +/* remote node after time synchronization */ + + /*--------------------------------------------------------------*/ + /* SLAVE application may disallow Time Synchronization from */ + /* Master by setting the smp_time_locally_sync to SD_TRUE. */ + /*--------------------------------------------------------------*/ + +extern ST_BOOLEAN smp_time_locally_sync; + + + /*======================================================*/ + /* Initialization functions */ + /*======================================================*/ + +/************************************************************************/ +/* smp_init */ +/*----------------------------------------------------------------------*/ +/* This function is called from the user code to initialize all global */ +/* variables used in SMP modules. */ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +ST_RET smp_init (ST_VOID); + + + /*======================================================*/ + /* SMP MASTER functions */ + /*======================================================*/ + +/************************************************************************/ +/* smp_time_sync_req_ar_name */ +/*----------------------------------------------------------------------*/ +/* Function called by Master to request Time Synchronization with */ +/* remote node. Implemented for TRIM7 stack . */ +/* This function will map remote rem_ar_name into a MAC address and call*/ +/* the smp_time_sync_req function. */ +/* */ +/* Parameters: */ +/* ST_LONG user_id */ +/* ST_UCHAR *rem_ar_name */ +/* ST_VOID (*callBackFun) */ +/* (ST_LONG user_id, ST_RET result, SMP_TIME *delta_time));*/ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +ST_RET smp_time_sync_req_ar_name ( + ST_LONG user_id, + ST_UCHAR *rem_ar_name, + ST_VOID (*callBackFun)(ST_LONG user_id, ST_RET result, SMP_TIME *delta_time)); + + + +/************************************************************************/ +/* smp_time_sync_req_chan */ +/*----------------------------------------------------------------------*/ +/* Function called by Master to request Time Synchronization with */ +/* remote node. Implemented for REDUCED STACK (only for ADLC subnet). */ +/* This function will map chan_num into a loc,rem MAC address pair and */ +/* call the smp_time_sync_req function. */ +/* */ +/* Note: A MMS connection must be established before calling this func. */ +/* */ +/* Parameters: */ +/* ST_LONG user_id */ +/* ST_INT chan_num */ +/* ST_VOID (*callBackFun) */ +/* (ST_LONG user_id, ST_RET result, SMP_TIME *delta_time));*/ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +ST_RET smp_time_sync_req_chan ( + ST_LONG user_id, + ST_INT chan_num, + ST_VOID (*callBackFun)(ST_LONG user_id, ST_RET result, SMP_TIME *delta_time)); + + +/************************************************************************/ +/* smp_time_sync_req */ +/*----------------------------------------------------------------------*/ +/* Function called by Master to request Time Synchronization with */ +/* remote node. */ +/* When the time synchronization has been completed or error occurred, */ +/* then the callBackFun will be used to notify the Master application */ +/* about the result of time synchronization request. */ +/* */ +/* !Note: This function requires that the application establishes */ +/* ADLC connection (for REDUCED_STACK) with given node before */ +/* calling this function. For TRIM7 stack ADLC connections are */ +/* maintained by ADLC_ML. */ +/* On the Ethernet there is no need to establish connection. */ +/* */ +/* Parameters: */ +/* ST_LONG user_id; for user to use */ +/* ST_UCHAR *loc_mac; Ptr to Local MAC address */ +/* ST_UCHAR *rem_mac; Ptr to Remote MAC address */ +/* ST_VOID (*callBackFun) */ +/* (ST_LONG user_id, ST_RET result, SMP_TIME *delta_time); */ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +ST_RET smp_time_sync_req ( + ST_LONG user_id, /* for user to use */ + ST_UCHAR *loc_mac, /* Ptr to Local MAC address */ + ST_UCHAR *rem_mac, /* Ptr to Remote MAC address */ + ST_VOID (*callBackFun)(ST_LONG user_id, ST_RET result, SMP_TIME *delta_time)); + + + + /*======================================================*/ + /* SMP common SLAVE/MASTER functions */ + /*======================================================*/ + +typedef struct + { + ST_UCHAR *pdu_buf; + ST_UINT16 pdu_len; + ST_UCHAR *loc_mac; + ST_UCHAR *rem_mac; + ST_UCHAR *rec_time; + } SMP_DATAUNIT; + + +/************************************************************************/ +/* smp_decode_uca_pdu */ +/*----------------------------------------------------------------------*/ +/* Function called by Slave application to decode received UCA Station */ +/* Management Protocol PDU after LLC header has been decoded (dest=0xFB)*/ +/* If the Slave application is a TRIM7 or Reduced Stack application */ +/* this function will be called automatically from proper decoding */ +/* functions. */ +/* */ +/* Parameters: */ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +ST_RET smp_decode_uca_pdu (SMP_DATAUNIT *smp_du); + + +/************************************************************************/ +/* smp_send_pdu_callback */ +/*----------------------------------------------------------------------*/ +/* This callback function called by ADLC sub-network layer when a PDU */ +/* has been sent. Saves time stamp of Measure-Response PDU only. */ +/* */ +/* Parameters: */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID smp_send_pdu_callback (ST_RET result, ST_LONG user_id, + ST_UCHAR *rec_time, ST_UINT rec_time_len); + + + /*======================================================*/ + /* SMP time SLAVE/MASTER functions implemented by user */ + /*======================================================*/ + + +#if defined(SMP_DLL) +#include +#define DllImport __declspec (dllimport) +#define DllExport __declspec (dllexport) +#endif + +/************************************************************************/ +/* u_smp_record_time */ +/*----------------------------------------------------------------------*/ +/* Function implemented by user to record time. */ +/* The rec_time is a buffer of rec_time_len bytes (SMP_SIZE_OF_REC_TIME)*/ +/* */ +/* Parameters: */ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +#if defined(SMP_DLL) +DllExport ST_RET WINAPI u_smp_record_time (ST_UCHAR *rec_time, ST_UINT rec_time_len); +#else +ST_RET u_smp_record_time (ST_UCHAR *rec_time, ST_UINT rec_time_len); +#endif + + +/************************************************************************/ +/* u_smp_convert_time */ +/*----------------------------------------------------------------------*/ +/* Function implemented by user converting recorded time in rec_time */ +/* buffer to the SMP_TIME struct the application uses. */ +/* The rec_time is a buffer of rec_time_len bytes (SMP_SIZE_OF_REC_TIME)*/ +/* */ +/* Parameters: */ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +#if defined(SMP_DLL) +DllExport ST_RET WINAPI u_smp_convert_time (ST_UCHAR *rec_time, + ST_UINT rec_time_len, + SMP_TIME *smp_time); +#else +ST_RET u_smp_convert_time (ST_UCHAR *rec_time, + ST_UINT rec_time_len, + SMP_TIME *smp_time); +#endif + + + /*======================================================*/ + /* SMP SLAVE functions implemented by user */ + /*======================================================*/ + + +/************************************************************************/ +/* u_smp_time_sync_ind */ +/*----------------------------------------------------------------------*/ +/* SLAVE function implemented by user to synchronize time. */ +/* */ +/* Parameters: */ +/* SLAVE side: */ +/* SMP_TIME *a1 recorded time of Measure-RequestPDU reception */ +/* SMP_TIME *a2 recorded time of Measure-ResponsePDU sending */ +/* MASTER side: */ +/* SMP_TIME *b1 recorded time of Measure-RequestPDU sending */ +/* SMP_TIME *b2 recorded time of Measure-ResponsePDU arrival */ +/* SMP_TIME *delta_time return the local_adjustement. */ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE. */ +/************************************************************************/ +ST_RET u_smp_time_sync_ind (SMP_TIME *a1, SMP_TIME *a2, + SMP_TIME *b1, SMP_TIME *b2, + SMP_TIME *delta_time); + + + + + /*======================================================*/ + /* For applications which do not link with TRIM7 or */ + /* Reduced Stack the smp_hc_config function may be */ + /* called to initialize needed parameters. */ + /*======================================================*/ + +/************************************************************************/ +/* smp_hc_config */ +/*----------------------------------------------------------------------*/ +/* This USER's func provides hard coded initialization of few parameters*/ +/* for applications which DO NOT link to TRIM7 or REDUCED STACK. */ +/* */ +/* Parameters: */ +/* ST_VOID *loc_addr Local ADLC address */ +/* (ignored for other subnet) */ +/* ST_CHAR *smpLogFile Pointer log file name buffer */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if initialization successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET smp_hc_config (ST_VOID *loc_addr, ST_CHAR *smpLogFile); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + diff --git a/mmslib/inc/smpval.h b/mmslib/inc/smpval.h new file mode 100644 index 0000000..c7c2535 --- /dev/null +++ b/mmslib/inc/smpval.h @@ -0,0 +1,138 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2006-2006, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : smpval.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* Structures, functions for sending/receiving IEC 61850 Sampled */ +/* Value messages (according to IEC 61850-9-2). */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/15/08 JRB 03 Fix securityLen type (ST_UINT -> ST_INT). */ +/* 08/09/06 JRB 02 Fix svID len (Vstring65). */ +/* Change DatSet to Vstring129 (ObjectReference)*/ +/* 03/17/05 JRB 01 Created */ +/************************************************************************/ +#ifndef SMPVAL_INCLUDED +#define SMPVAL_INCLUDED + +#include "asn1r.h" /* need MMS_UTC_TIME */ +#include "ethertyp.h" /* need ETYPE_INFO */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_SMPVAL_SVID_LEN 65 /* 61850 MsvID, UsvID len */ +#define MAX_SMPVAL_OBJREF_LEN 129 /* 61850 ObjectReference len */ +#define MAX_SMPVAL_SECURITY_LEN 20 /* max len of security info */ + +/* Bit numbers in OptFlds bitstring (configured by SmvOpts in SCL file) */ +#define SVOPT_BITNUM_SMPRATE 0 +#define SVOPT_BITNUM_REFRTM 1 +#define SVOPT_BITNUM_SMPSYNCH 2 + +/************************************************************************/ +/* STRUCTURE DEFINITIONS */ +/************************************************************************/ +typedef struct + { + ST_UINT8 *SamplePtr; /* pointer to "Sample" data */ + ST_INT SampleLen; /* length of "Sample" data in bytes */ + ST_CHAR svID [MAX_SMPVAL_SVID_LEN+1]; /* MsvID or UsvID - Vstring65 */ + ST_BOOLEAN DatSetPres; /* is "DatSet" present in ASDU? */ + ST_CHAR DatSet [MAX_SMPVAL_OBJREF_LEN+1]; /* Vstring129 (ObjectReference)*/ + /* (Optional) */ + ST_UINT16 SmpCnt; + ST_UINT32 ConfRev; + ST_BOOLEAN SmpSynch; + ST_BOOLEAN RefrTmPres; /* is "RefrTm" present in ASDU? */ + MMS_UTC_TIME RefrTm; /* Optional */ + ST_BOOLEAN SmpRatePres; /* is "SmpRate" present in ASDU? */ + ST_UINT16 SmpRate; /* Optional */ + } SMPVAL_ASDU; + +typedef struct + { + ST_UINT16 numASDU; /* Num of ASDU concatenated into one APDU */ + SMPVAL_ASDU *asduArray; /* array of "numASDU" structs */ + /* allocated by smpval_msg_create OR */ + /* allocated during decode */ + ST_UCHAR securityBuf [MAX_SMPVAL_SECURITY_LEN]; /* security info*/ + ST_INT securityLen; /* len of security info */ + }SMPVAL_MSG; + + +/************************************************************************/ +/* Functions for sending SMPVAL messages. */ +/************************************************************************/ +SMPVAL_MSG *smpval_msg_create ( + ST_UINT numASDU); /* Num of ASDU concatenated into one APDU*/ + +ST_VOID smpval_msg_destroy (SMPVAL_MSG *smpvalMsg); + +/* Updates data stored for one ASDU to be sent in a SMPVAL message */ +ST_RET smpval_asdu_data_update ( + SMPVAL_MSG *smpvalMsg, /* SMPVAL msg info structure */ + ST_INT asduIdx, /* index into array of ASDU for this SMPVAL msg*/ + ST_UINT8 *SamplePtr, /* pointer to data */ + ST_INT SampleLen, /* length of data in bytes */ + ST_CHAR *svID, + ST_INT SmpCnt, + ST_BOOLEAN DatSetPres, /* SD_TRUE if optional DatSet should be sent*/ + ST_CHAR *DatSet, /* Optional (chk DatSetPres arg) */ + ST_UINT32 ConfRev, + ST_BOOLEAN SmpSynch, + ST_BOOLEAN RefrTmPres, /* SD_TRUE if optional RefrTm should be sent*/ + MMS_UTC_TIME *RefrTm, /* Optional (chk_RefrTmPres arg) */ + ST_BOOLEAN SmpRatePres, /* SD_TRUE if optional SmpRate should be sent*/ + ST_UINT16 SmpRate); /* Optional (chk SmpRatePres arg) */ + +/* Encodes complete SMPVAL message (APDU plus Ethertype header). */ +/* RETURNS: ptr to start of encoded message (or NULL on error) */ +ST_UCHAR *smpval_msg_encode ( + SMPVAL_MSG *smpvalMsg, /* SMPVAL msg info structure */ + ETYPE_INFO *etypeInfo, /* Ethertype info */ + ST_UCHAR *asn1DataBuf, /* buffer to encode in */ + ST_INT asn1DataBufLen, /* len of buffer */ + ST_INT *asn1DataLenOut);/* ptr to len encoded */ +ST_RET smpval_msg_send ( + SMPVAL_MSG *smpvalMsg, /* SMPVAL msg info structure */ + ETYPE_INFO *etypeInfo, /* Ethertype info */ + ST_UCHAR *dstMac); /* Destination (Multicast) MAC address */ + +/************************************************************************/ +/* Functions for receiving SMPVAL messages. */ +/************************************************************************/ +/* Decode SMPVAL message and fill in SMPVAL_MSG struct.*/ +SMPVAL_MSG *smpval_msg_decode ( + SN_UNITDATA *sn_req, /* message to decode */ + ETYPE_INFO *etypeInfo); /* where to store decoded Ethertype info*/ + +/* Must be called to free structure returned from smpval_msg_decode. */ +ST_VOID smpval_msg_free (SMPVAL_MSG *smpvalMsg); + +/************************************************************************/ +/* Utility functions */ +/************************************************************************/ +/* Copies data from source to destination but reverses the order of the */ +/* bytes (i.e. converts Big-Endian to Little-Endian or vice versa). */ +ST_VOID reverse_bytes ( + ST_UINT8 *dst, /* ptr to destination buffer */ + ST_UINT8 *src, /* ptr to source buffer */ + ST_INT numbytes); /* number of bytes to copy */ + +#ifdef __cplusplus +} +#endif +#endif /* included */ diff --git a/mmslib/inc/sock_log.h b/mmslib/inc/sock_log.h new file mode 100644 index 0000000..67c1ebb --- /dev/null +++ b/mmslib/inc/sock_log.h @@ -0,0 +1,210 @@ +/************************************************************************/ +/* SOFTWARE MODULE HEADER ***********************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2002 - 2003, All Rights Reserved */ +/* */ +/* MODULE NAME : sock_log.h */ +/* PRODUCT(S) : General Sockets Interface logging */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/20/07 MDE 02 Modified macros to take ctx, log_disable */ +/* 06/25/03 JRB 01 Move log macros from "gensock2.h". */ +/************************************************************************/ +#ifndef SOCK_LOG_INCLUDED +#define SOCK_LOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define SOCK_LOG_ERR 0x0001 +#define SOCK_LOG_NERR 0x0002 +#define SOCK_LOG_FLOW 0x0004 +#define SOCK_LOG_RX 0x0008 +#define SOCK_LOG_TX 0x0010 + +extern ST_UINT sock_debug_sel; + +/* Log type strings */ +extern SD_CONST ST_CHAR *SD_CONST SOCK_LOG_ERR_TEXT; +extern SD_CONST ST_CHAR *SD_CONST SOCK_LOG_NERR_TEXT; +extern SD_CONST ST_CHAR *SD_CONST SOCK_LOG_FLOW_TEXT; +extern SD_CONST ST_CHAR *SD_CONST SOCK_LOG_RX_TEXT; +extern SD_CONST ST_CHAR *SD_CONST SOCK_LOG_TX_TEXT; + +/*********************** SOCK_LOG_ERR Macros *****************************/ + +#define SOCK_LOG_ERR0(ctx,a) \ + SLOG_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),SOCK_LOG_ERR_TEXT,a) +#define SOCK_LOG_ERR1(ctx,a,b) \ + SLOG_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),SOCK_LOG_ERR_TEXT,a,b) +#define SOCK_LOG_ERR2(ctx,a,b,c) \ + SLOG_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),SOCK_LOG_ERR_TEXT,a,b,c) +#define SOCK_LOG_ERR3(ctx,a,b,c,d) \ + SLOG_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),SOCK_LOG_ERR_TEXT,a,b,c,d) +#define SOCK_LOG_ERR4(ctx,a,b,c,d,e) \ + SLOG_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),SOCK_LOG_ERR_TEXT,a,b,c,d,e) +#define SOCK_LOG_ERR5(ctx,a,b,c,d,e,f) \ + SLOG_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),SOCK_LOG_ERR_TEXT,a,b,c,d,e,f) + +/* Continuation log macros */ +#define SOCK_LOG_ERRC0(ctx,a) \ + SLOGC_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),a) +#define SOCK_LOG_ERRC1(ctx,a,b) \ + SLOGC_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),a,b) +#define SOCK_LOG_ERRC2(ctx,a,b,c) \ + SLOGC_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),a,b,c) +#define SOCK_LOG_ERRC3(ctx,a,b,c,d) \ + SLOGC_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),a,b,c,d) +#define SOCK_LOG_ERRC4(ctx,a,b,c,d,e) \ + SLOGC_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),a,b,c,d,e) +#define SOCK_LOG_ERRC5(ctx,a,b,c,d,e,f) \ + SLOGC_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),a,b,c,d,e,f) + +/* Hex log macro */ +#define SOCK_LOG_ERRH(ctx,a,b) \ + SLOGH ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_ERR),a,b) + +/*********************** SOCK_LOG_NERR Macros *****************************/ + +#define SOCK_LOG_NERR0(ctx,a) \ + SLOG_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),SOCK_LOG_NERR_TEXT,a) +#define SOCK_LOG_NERR1(ctx,a,b) \ + SLOG_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),SOCK_LOG_NERR_TEXT,a,b) +#define SOCK_LOG_NERR2(ctx,a,b,c) \ + SLOG_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),SOCK_LOG_NERR_TEXT,a,b,c) +#define SOCK_LOG_NERR3(ctx,a,b,c,d) \ + SLOG_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),SOCK_LOG_NERR_TEXT,a,b,c,d) +#define SOCK_LOG_NERR4(ctx,a,b,c,d,e) \ + SLOG_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),SOCK_LOG_NERR_TEXT,a,b,c,d,e) +#define SOCK_LOG_NERR5(ctx,a,b,c,d,e,f) \ + SLOG_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),SOCK_LOG_NERR_TEXT,a,b,c,d,e,f) + +/* Continuation log macros */ +#define SOCK_LOG_NERRC0(ctx,a) \ + SLOGC_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),a) +#define SOCK_LOG_NERRC1(ctx,a,b) \ + SLOGC_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),a,b) +#define SOCK_LOG_NERRC2(ctx,a,b,c) \ + SLOGC_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),a,b,c) +#define SOCK_LOG_NERRC3(ctx,a,b,c,d) \ + SLOGC_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),a,b,c,d) +#define SOCK_LOG_NERRC4(ctx,a,b,c,d,e) \ + SLOGC_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),a,b,c,d,e) +#define SOCK_LOG_NERRC5(ctx,a,b,c,d,e,f) \ + SLOGC_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),a,b,c,d,e,f) + +/* Hex log macro */ +#define SOCK_LOG_NERRH(ctx,a,b) \ + SLOGH ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_NERR),a,b) + +/*********************** SOCK_LOG_FLOW Macros *****************************/ + +#define SOCK_LOG_FLOW0(ctx,a) \ + SLOG_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),SOCK_LOG_FLOW_TEXT,a) +#define SOCK_LOG_FLOW1(ctx,a,b) \ + SLOG_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),SOCK_LOG_FLOW_TEXT,a,b) +#define SOCK_LOG_FLOW2(ctx,a,b,c) \ + SLOG_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),SOCK_LOG_FLOW_TEXT,a,b,c) +#define SOCK_LOG_FLOW3(ctx,a,b,c,d) \ + SLOG_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),SOCK_LOG_FLOW_TEXT,a,b,c,d) +#define SOCK_LOG_FLOW4(ctx,a,b,c,d,e) \ + SLOG_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),SOCK_LOG_FLOW_TEXT,a,b,c,d,e) +#define SOCK_LOG_FLOW5(ctx,a,b,c,d,e,f) \ + SLOG_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),SOCK_LOG_FLOW_TEXT,a,b,c,d,e,f) + +/* Continuation log macros */ +#define SOCK_LOG_FLOWC0(ctx,a) \ + SLOGC_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),a) +#define SOCK_LOG_FLOWC1(ctx,a,b) \ + SLOGC_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),a,b) +#define SOCK_LOG_FLOWC2(ctx,a,b,c) \ + SLOGC_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),a,b,c) +#define SOCK_LOG_FLOWC3(ctx,a,b,c,d) \ + SLOGC_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),a,b,c,d) +#define SOCK_LOG_FLOWC4(ctx,a,b,c,d,e) \ + SLOGC_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),a,b,c,d,e) +#define SOCK_LOG_FLOWC5(ctx,a,b,c,d,e,f) \ + SLOGC_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),a,b,c,d,e,f) + +/* Hex log macro */ +#define SOCK_LOG_FLOWH(ctx,a,b) \ + SLOGH ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_FLOW),a,b) + +/*********************** SOCK_LOG_RX Macros *****************************/ + +#define SOCK_LOG_RX0(ctx,a) \ + SLOG_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),SOCK_LOG_RX_TEXT,a) +#define SOCK_LOG_RX1(ctx,a,b) \ + SLOG_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),SOCK_LOG_RX_TEXT,a,b) +#define SOCK_LOG_RX2(ctx,a,b,c) \ + SLOG_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),SOCK_LOG_RX_TEXT,a,b,c) +#define SOCK_LOG_RX3(ctx,a,b,c,d) \ + SLOG_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),SOCK_LOG_RX_TEXT,a,b,c,d) +#define SOCK_LOG_RX4(ctx,a,b,c,d,e) \ + SLOG_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),SOCK_LOG_RX_TEXT,a,b,c,d,e) +#define SOCK_LOG_RX5(ctx,a,b,c,d,e,f) \ + SLOG_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),SOCK_LOG_RX_TEXT,a,b,c,d,e,f) + +/* Continuation log macros */ +#define SOCK_LOG_RXC0(ctx,a) \ + SLOGC_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),a) +#define SOCK_LOG_RXC1(ctx,a,b) \ + SLOGC_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),a,b) +#define SOCK_LOG_RXC2(ctx,a,b,c) \ + SLOGC_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),a,b,c) +#define SOCK_LOG_RXC3(ctx,a,b,c,d) \ + SLOGC_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),a,b,c,d) +#define SOCK_LOG_RXC4(ctx,a,b,c,d,e) \ + SLOGC_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),a,b,c,d,e) +#define SOCK_LOG_RXC5(ctx,a,b,c,d,e,f) \ + SLOGC_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),a,b,c,d,e,f) + +/* Hex log macro */ +#define SOCK_LOG_RXH(ctx,a,b) \ + SLOGH ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_RX),a,b) + +/*********************** SOCK_LOG_TX Macros *****************************/ + +#define SOCK_LOG_TX0(ctx,a) \ + SLOG_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),SOCK_LOG_TX_TEXT,a) +#define SOCK_LOG_TX1(ctx,a,b) \ + SLOG_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),SOCK_LOG_TX_TEXT,a,b) +#define SOCK_LOG_TX2(ctx,a,b,c) \ + SLOG_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),SOCK_LOG_TX_TEXT,a,b,c) +#define SOCK_LOG_TX3(ctx,a,b,c,d) \ + SLOG_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),SOCK_LOG_TX_TEXT,a,b,c,d) +#define SOCK_LOG_TX4(ctx,a,b,c,d,e) \ + SLOG_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),SOCK_LOG_TX_TEXT,a,b,c,d,e) +#define SOCK_LOG_TX5(ctx,a,b,c,d,e,f) \ + SLOG_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),SOCK_LOG_TX_TEXT,a,b,c,d,e,f) + +/* Continuation log macros */ +#define SOCK_LOG_TXC0(ctx,a) \ + SLOGC_0 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),a) +#define SOCK_LOG_TXC1(ctx,a,b) \ + SLOGC_1 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),a,b) +#define SOCK_LOG_TXC2(ctx,a,b,c) \ + SLOGC_2 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),a,b,c) +#define SOCK_LOG_TXC3(ctx,a,b,c,d) \ + SLOGC_3 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),a,b,c,d) +#define SOCK_LOG_TXC4(ctx,a,b,c,d,e) \ + SLOGC_4 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),a,b,c,d,e) +#define SOCK_LOG_TXC5(ctx,a,b,c,d,e,f) \ + SLOGC_5 ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),a,b,c,d,e,f) + +/* Hex log macro */ +#define SOCK_LOG_TXH(ctx,a,b) \ + SLOGH ((ctx == NULL || !ctx->log_disable) && (sock_debug_sel & SOCK_LOG_TX),a,b) + +#ifdef __cplusplus +} +#endif + +#endif /* SOCK_LOG_INCLUDED */ diff --git a/mmslib/inc/ssec.h b/mmslib/inc/ssec.h new file mode 100644 index 0000000..123907c --- /dev/null +++ b/mmslib/inc/ssec.h @@ -0,0 +1,1182 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003 - 2008, All Rights Reserved */ +/* */ +/* MODULE NAME : ssec.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : This module provides user defines for SISCO's */ +/* Security Extensions for MMS-EASE, MMS-EASE Lite,*/ +/* ICCP, AXS4-MMS, AXS4-ICCP products. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/01/08 EJV 87 Chg S_SEC_VERSION_STR to 1.20 (for Win Vista)*/ +/* 05/14/08 EJV 86 Merged with non-Marben version. */ +/* 03/27/08 EJV 85 Use S_MAX_PATH instead of MAX_PATH. */ +/* 02/18/08 EJV 84 Changed to V2.00 for Sun Solaris. */ +/* 02/01/08 EJV 83 Added tags to typedef structs */ +/* 12/04/07 EJV 82 Added updateCRLists, ssleLoadCRLists (sh lib)*/ +/* 11/21/07 EJV 81 Added ssleSetCertStorePath */ +/* 09/05/07 EJV 80 Port to SNAP-Lite and LEAN-T stack. Cleanup. */ +/* cfgId is now CRC-32 computed on S_CERT_ID. */ +/* Merged S_SEC_LOC_AR and S_SEC_REM_AR into */ +/* S_SEC_LOC_REM_AR struct. */ +/* Merged sslLocalCertList and sslRemoteCertList*/ +/* into locRemCertList in S_SEC_CFG. */ +/* Del secManGetDebugSel (secman.dll eliminated)*/ +/* 03/06/07 EJV 79 Moved extern ssle_debug_sel from sslelog.h. */ +/* Changed to V1.9950 for MMS-SECURE-145-015. */ +/* 04/08/08 JRB 79 Chg () to (ST_VOID) in several prototypes. */ +/* 08/28/06 EJV 78 MMS-LITE SECURE: chg version to 1.10. */ +/* 03/02/06 EJV 77 Chg S_SEC_VERSION_STR to 1.10 (VS .NET 2005) */ +/* 01/04/06 EJV 76 Added DLLs incompatibility comments. */ +/* 10/25/05 EJV 75 Chg S_SEC_LITESECURE_NAME to fit identify */ +/* 09/22/05 EJV 74 Any new build use S_SEC_VERSION_STR 1.04 */ +/* 08/09/05 EJV 73 MMS-LITE SECURE: chg version to 1.0050. */ +/* Add extern LocalCertStorePath,CACertStorePath*/ +/* 02/25/05 MDE 72 Added sSecAssocConfChkEx */ +/* 01/31/05 ASK 71 Fix ST_MUTEX_SEM_SSEC to compile on QNX */ +/* 01/18/05 ASK 70 Chg ver back to 1.03 for (Win release) */ +/* 01/11/05 ASK 69 Added ST_MUTEX_SEM_SSEC for non-Windows */ +/* 01/10/05 ASK 68 Added ST_MUTEX_SEM_SSEC struct to ensure */ +/* alignment between S_SEC_CFG between */ +/* secman.dll and calling application */ +/* 01/06/05 ASK 67 Temporarily Chg ver to 1.0260 for Symantec */ +/* release. */ +/* 09/29/04 EJV 66 Chg ver to 1.03 for (Win release) */ +/* 09/02/04 EJV 65 Added S_SEC_PATH for sun. */ +/* 08/24/04 EJV 64 Chg from WIN32 to _WIN32. */ +/* Chg ver to 1.0251 for Windows ICCP-SECURE. */ +/* 04/08/04 EJV 63 _AIX: added S_SEC_PATH. */ +/* Chg ver to 1.02 for (AIX release) */ +/* 04/01/04 EJV 62 Chg ver to 1.0051 for (AIX beta) */ +/* 03/30/04 ASK 61 Added secManLckEnd proto */ +/* Added ssleCertFileToText proto for AIX */ +/* 03/12/04 ASK 60 Added ssleCertFileToXml proto for AIX */ +/* 03/10/04 EJV 59 Corr ver to 1.0050 for (AIX beta) */ +/* 03/05/04 MDE 58 Added AE Title for AR Security mode */ +/* 02/16/04 EJV 57 Chg S_SEC_DEF_SSL_PORT to 3782. */ +/* Added S_SEC_PORT_DELIM_CHAR. */ +/* Chg ver to 1.0150 for (AIX beta) */ +/* 02/09/04 EJV 56 Changed S_SEC_LITESECURE_NAME. */ +/* 01/16/04 EJV 55 Del forward reference to DIB_MATCH_CTRL. */ +/* Added _WIN32 for dllimport secManCfgChange. */ +/* 01/12/04 EJV 54 Added secManCfgChange proto for MMS_LITE */ +/* 12/04/03 ASK 53 Added secManCfgChange proto */ +/* 10/31/03 ASK 52 Rem CName type 'Unknown' */ +/* 10/21/03 EJV 51 Rem sSecFreeSecParam, sSecFreePartSecParam */ +/* 10/20/03 ASK 50 Added params to sSecUpdate, added */ +/* secManGetDebugSel proto, added */ +/* crlDropExisting to cfg */ +/* 10/16/03 ASK 49 Added sSecEnd and stopSSLEngine protos, */ +/* Chg ver to 1.00 */ +/* 10/10/03 MDE 48 Added crlCheckTime */ +/* 09/30/03 EJV 47 MMS-LITE: added S_SEC_LITESECURE_VERSION_STR */ +/* and S_SEC_LITESECURE_NAME. */ +/* Redefined macros SECLOG..._ to SEC_LOG_... */ +/* Added S_SEC_SSLE_LOG_DATA, S_SEC_SOCK_LOG_TX,*/ +/* S_SEC_SOCK_LOG_RX (reworked numbers). */ +/* Chg secLogMasks from ST_ULONG to ST_UINT. */ +/* MMS_LITE: Added global secManCfgXmlFile */ +/* 09/29/03 EJV 46 Chg ver to 0.9955 (snap.exe fix) */ +/* 08/25/03 EJV 45 Moved protos with GEN_SOCK to ssec_int.h */ +/* 08/21/03 ASK 44 Add clearTime to S_MACE_INFO struct. Chg some*/ +/* protos to pass this to verify time sig */ +/* 08/21/03 EJV 43 Added setGenSockSSL, ssecGetCipherSuite, */ +/* sSecGetCertId, sSecGetCertCtrl protos. */ +/* Chg ver to 0.9954 */ +/* 07/28/03 EJV 42 Chg MMS_LITE protos. */ +/* 07/18/03 ASK 41 Add software lock protos from secmanlck.c */ +/* 07/16/03 MDE 40 Changes to appAuthRequired values */ +/* 07/14/03 ASK 39 Add sSecUpdate and sslUpdate protos */ +/* 06/30/03 ASK 38 Added secManAccessCfg and secManReleaseCfg */ +/* protos. #include glbsem.h. Add mutex to */ +/* S_SEC_CONFIG struct. */ +/* 06/26/03 EJV 37 Chg GSOCK_... to SOCK_... log macros */ +/* 06/25/03 EJV 36 Chg ver to 0.9953 */ +/* 06/24/03 ASK 35 Added dynamic config API func protos */ +/* 06/20/03 EJV 34 Added SNAP_EXIT_EVENT_NAME. */ +/* 06/20/03 ASK 33 add S_SEC_EVENT_REKEY_FAILURE define */ +/* 06/19/03 MDE 32 Added rekeying to S_CERT_CTRL */ +/* 06/16/03 EJV 31 Del m_match.h, s_match.h; added suicacse.h; */ +/* Changed M_MATCH_CTRL to DIB_MATCH_CTRL. */ +/* 06/12/03 MDE 30 sSecAssocConfChk added srcChkDest parameter. */ +/* 06/12/03 MDE 29 Fixed up MMS_LITE over Marben */ +/* 06/12/03 MDE 28 Added M_MATCH support */ +/* 05/27/03 EJV 27 Chg ver to 0.9952 */ +/* 05/27/03 EJV 26 sSecAssocIndChk added parameter srcChkDest. */ +/* 05/27/03 EJV 25 S_SEC_PORT_DELIM_STR chg to '+' for compatib.*/ +/* 05/23/03 ASK 24 Changed secManLog to secManEventLog. Added */ +/* event define S_SEC_EVENT_SSL_FAILURE. Change */ +/* sSecPrintSrlNum to secManPrintSrlNum. */ +/* 05/14/03 MDE 23 Fixed up rekey parameters */ +/* 05/09/03 MDE 22 Corrected S_CIPHER_0C04xx, _0D02xx to use MD5*/ +/* 05/06/03 ASK 21 Add sSecUsrStart proto, changed secManStart */ +/* and startSSLEngine protos for new logging. */ +/* 05/01/03 ASK 20 Change to use S_SEC_SPARAMS for SUIC */ +/* 04/30/03 ASK 19 Add public key to S_CERT_INFO. Changed */ +/* S_SEC_MAX_SIGNED_TIME_LEN to 128 bytes. */ +/* Added protos for new signing time functions. */ +/* Added sSecCmpIssuer proto. */ +/* 04/29/03 EJV 18 Added S_SEC_MAX_IP_ADDR_LEN */ +/* Chg ver to 0.9951 */ +/* 04/21/03 MDE 17 Added cipher suites */ +/* 04/18/03 MDE 16 S_SEC_CONFIG changes */ +/* 04/18/03 MDE 15 Added S_APP_AUTHREQ_xxx defines */ +/* 04/18/03 MDE 14 Added Masks for Cipher Suite elements */ +/* 04/17/03 EJV 13 Moved asn1log.h. */ +/* 04/16/03 EJV 12 Added version string. */ +/* 04/15/03 JRB 11 Add forward ref for mvl_net_info. */ +/* 04/15/03 ASK 10 Added sSecPrintSrlNum proto. */ +/* 04/11/03 EJV 09 sSecAuthChk: changed ret to ST_RET */ +/* 04/10/03 EJV 08 Added sSecCmpCertId proto. */ +/* 04/10/03 MDE 07 Added ArSec support */ +/* 04/09/03 MDE 06 Merged ssecusr.c function protos */ +/* 04/09/03 MDE 05 Added AR security context declarations */ +/* 04/08/03 EJV 05 Added defs for all log masks in secLogMasks. */ +/* Changed secLogMasks to ST_ULONG. */ +/* 04/07/03 EJV 04 Added protos from ssecusr.c */ +/* 04/04/03 ASK 03 Changed serial number format. Added */ +/* SECLOG_DATA and SECLOG_DEBUG masks. Added */ +/* startSSLEngine proto. */ +/* 03/04/03 EJV 02 Added IPAddr string parsing tokens */ +/* 02/21/03 MDE 01 Created */ +/************************************************************************/ + +#ifndef S_SEC_INCLUDED +#define S_SEC_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "glbsem.h" +#include "acseauth.h" +#include "gen_list.h" +#include "asn1r.h" +#include "dibmatch.h" + +#if !defined(MMS_LITE) || defined(MAP30_ACSE) +/* for MMS-EASE, MMS-EASE Lite based products over Marben Stack */ +#define S_SEC_VERSION_STR "1.20" +#else +/* for MMS-EASE Lite products over LEAN-T Stack */ +#define S_SEC_LITESECURE_NAME "MMS-LITE-SECURE" +#define S_SEC_LITESECURE_VERSION_STR "1.10" +#endif + +#if !defined(MMS_LITE) || defined(MAP30_ACSE) +/* for MMS-EASE, MMS-EASE Lite based products over Marben Stack */ +#if !defined(_WIN32) +/* Security installation path on UNIX systems is fixed but diff on each system */ +#if defined(_AIX) +#define S_SEC_PATH "/usr/lpp/osill2/security" +#else /* other UNIX systems */ +#define S_SEC_PATH "/usr/osill2/security" +#endif +#endif /* !defined(_WIN32) */ +#endif /* !defined(MMS_LITE) || defined(MAP30_ACSE) */ + +#if defined(_WIN32) + #if defined(MMS_LITE) + #define SISCO_REGISTRY_SECURITY "SOFTWARE\\SISCO\\Secure MMS-EASE Lite\\CurrentVersion" + #else /* !defined(MMS_LITE) */ + #define SISCO_REGISTRY_SECURITY "SOFTWARE\\SISCO\\Security\\CurrentVersion" + #endif /* !defined(MMS_LITE) */ +#endif /* defined(_WIN32) */ + + + +/************************************************************************/ +/************************************************************************/ +/* NOTES ON CERTIFICATE NAME MATCHING */ +/* This sSec API has a number of functions that must match certificates */ +/* based on a S_CERT_ID data structure. In all cases the matching */ +/* process works as follows: */ +/* */ +/* The matching can be based on certificate number, subject, */ +/* issuer, or any combination of these as specified in the certId. */ +/* For instance, the following specifications are valid: */ +/* 1. Serial Number only */ +/* 2. Subject only */ +/* 3. Issuer only */ +/* 4. Subject and Issuer */ +/* 5. Subject and Serial Number */ +/* 6. Issuer and Serial Number */ +/* 7. Subject, Issuer, Serial Number */ + +/* Note that the all elements of the input 'certId' must be present and */ +/* match exactly in the local certificate. That is, all elements of the */ +/* certificate name must be present and in the specified order. */ + +/************************************************************************/ +/************************************************************************/ +#define SEC_LOG_ERR 0x00000001 +#define SEC_LOG_NERR 0x00000002 +#define SEC_LOG_FLOW 0x00000004 +#define SEC_LOG_DATA 0x00000008 +#define SEC_LOG_DEBUG 0x00000010 + +extern ST_UINT sec_debug_sel; + +/************************************************************************/ +/* LOGGING */ +/* The logging masks defined here are used to set the secLogMasks field */ +/* in the S_SEC_CONFIG (defined below). The application can set the */ +/* proper module logging masks by examining the secLogMasks. */ +/* Note that ERR logging is set by default to ON in all modules. */ +/* The name of masks have been copied here and prefixed with S_SEC_... */ +/* for easy reference. */ + +/* log masks for sec_debug_sel (ssec.h) */ +#define S_SEC_SEC_LOG_NERR 0x00000001 +#define S_SEC_SEC_LOG_FLOW 0x00000002 +#define S_SEC_SEC_LOG_DATA 0x00000004 +#define S_SEC_SEC_LOG_DEBUG 0x00000008 +/* log masks for ssle_debug_sel (sslEngine.h) */ +#define S_SEC_SSLE_LOG_NERR 0x00000010 +#define S_SEC_SSLE_LOG_FLOW 0x00000020 +#define S_SEC_SSLE_LOG_DATA 0x00000040 +#define S_SEC_SSLE_LOG_DEBUG 0x00000080 +/* log masks for snap_debug_sel (snaplog.h) */ +#define S_SEC_SNAP_LOG_NERR 0x00000100 +#define S_SEC_SNAP_LOG_FLOW 0x00000200 +/* log masks for sock_debug_sel (gensock2.h) */ +#define S_SEC_SOCK_LOG_NERR 0x00000400 +#define S_SEC_SOCK_LOG_FLOW 0x00000800 +#define S_SEC_SOCK_LOG_TX 0x00001000 +#define S_SEC_SOCK_LOG_RX 0x00002000 +/* log masks for sx_debug_sel (sx_defs.h) */ +#define S_SEC_SX_LOG_NERR 0x00004000 +#define S_SEC_SX_LOG_DEC 0x00008000 +#define S_SEC_SX_LOG_ENC 0x00010000 +#define S_SEC_SX_LOG_FLOW 0x00020000 +#define S_SEC_SX_LOG_DEBUG 0x00040000 +/* log masks for asn1_debug_sel (asn1r.h) */ +#define S_SEC_ASN1_LOG_NERR 0x00080000 +#define S_SEC_ASN1_LOG_DEC 0x00100000 +#define S_SEC_ASN1_LOG_ENC 0x00200000 +/* log masks for gs_debug_sel (glbsem.h) */ +#define S_SEC_GS_LOG_NERR 0x00400000 +#define S_SEC_GS_LOG_FLOW 0x00800000 +/* log masks for chk_debug_en (mem_chk.h) */ +#define S_SEC_MEM_LOG_CALLOC 0x01000000 +#define S_SEC_MEM_LOG_MALLOC 0x02000000 +#define S_SEC_MEM_LOG_REALLOC 0x04000000 +#define S_SEC_MEM_LOG_FREE 0x08000000 +/* the rest of bits are used for memory debugging flags: */ +#define S_SEC_m_check_list_enable 0x10000000 +#define S_SEC_m_find_node_enable 0x20000000 +#define S_SEC_m_no_realloc_smaller 0x40000000 +/* 0x80000000 free */ + +/************************************************************************/ +/* SNAP Startup Event Names */ + +#if defined(_WIN32) +#define SNAP_STARTED_EVENT_NAME "snap.started" +#define SNAP_RUNNING_EVENT_NAME "snap.running" +#define SNAP_EXIT_EVENT_NAME "snap.exit" +#endif + +/************************************************************************/ +/* Allowed authType values */ + +#define S_SEC_AUTHTYPE_NONE 0 +#define S_SEC_AUTHTYPE_CERTIFICATE 1 +#define S_SEC_AUTHTYPE_SYMMETRIC 2 + +/************************************************************************/ +/* General Defines */ + +/* Maximum signed time data size */ +#define S_SEC_MAX_SIGNED_TIME_LEN 128 + +/* Help in sizing the asn1 buffer (really more like 25 ...) */ +#define S_SEC_ASN1_BUF_OH 50 + +/* Maximum size of the certificate serial number (in bytes) */ +#define S_SEC_MAX_SERIAL_LEN 64 + +/************************************************************************/ +/* MACE decode error codes */ + +#define MACE_ASN1_INCOMPLETE 0x9102 +#define MACE_ASN1_SYMMETRIC_NOT_SUPPORTED 0x9103 + +/************************************************************************/ +/* Default Ports */ + +/* SSL Port */ +#define S_SEC_DEF_SSL_PORT 3782 + +/* IPC Ports */ +#define S_SEC_DEF_STACK_PORT 10042 +#define S_SEC_DEF_SNAP_PORT 10043 +#define S_SEC_DEF_SNAP_CONTROL_PORT 10044 +#define S_SEC_DEF_SNAP_MONITOR_PORT 10045 + + +/************************************************************************/ +/* Remote address and security info formatting tokens */ + +#define S_SEC_IP_ADDR_DELIM_STR "SSL:" +#define S_SEC_PORT_DELIM_STR "+" +#define S_SEC_PORT_DELIM_CHAR '+' /* same as above but in ' ' */ +#define S_SEC_CIPHER_DELIM_STR "+" +#define S_SEC_CERT_ID_DELIM_STR "," + +#define S_SEC_MAX_IP_ADDR_LEN 20 + +/************************************************************************/ +/* Security Subsystem Error Codes */ + +#define S_SEC_ERR_VALIDITY_TOOSOON 0xA001 /* 40961 */ +#define S_SEC_ERR_VALIDITY_EXPIRED 0xA002 /* 40962 */ +#define S_SEC_ERR_CNAME_TYPE_UNKNOWN 0xA003 /* 40963 */ +#define S_SEC_ERR_CNAME_MISSING 0xA004 /* 40964 */ +#define S_SEC_ERR_CNAME_EXTRA 0xA005 /* 40965 */ +#define S_SEC_ERR_CNAME_MISMATCH 0xA006 /* 40966 */ +#define S_SEC_ERR_TIME_SEAL_INVALID 0xA007 /* 40967 */ +#define S_SEC_ERR_TIME_SEAL_TIME_WINDOW 0xA008 /* 40968 */ +#define S_SEC_ERR_READ_INSTALL_PATH 0xA009 /* 40969 */ +/* DEBUG: these codes are not appearing anywhere */ + +/************************************************************************/ +/* Cipher Suite Selection Defines */ + +#define S_MAX_ALLOWED_CIPHER_SUITES 49 + +/* Masks for Cipher Suite elements */ +#define S_KEYX_MASK 0xff0000 +#define S_CRYPT_MASK 0x00ff00 +#define S_HASH_MASK 0x0000ff + + +/* Key Exchange Algorithms */ +#define S_KEYX_NONE 0x000000 +#define S_KEYX_NULL 0x010000 +#define S_KEYX_RSA 0x020000 +#define S_KEYX_RSA_EX 0x030000 +#define S_KEYX_DH_DSS 0x040000 +#define S_KEYX_DH_DSS_EX 0x050000 +#define S_KEYX_DH_RSA 0x060000 +#define S_KEYX_DH_RSA_EX 0x070000 +#define S_KEYX_DHE_DSS 0x080000 +#define S_KEYX_DHE_DSS_EX 0x090000 +#define S_KEYX_DHE_RSA 0x0A0000 +#define S_KEYX_DHE_RSA_EX 0x0B0000 +#define S_KEYX_DH_ANON 0x0C0000 +#define S_KEYX_DH_ANON_EX 0x0D0000 +#define S_KEYX_FORTEZZA_DMS 0x0E0000 + +/* Encryption Algorithms */ +#define S_CRYPT_NONE 0x000000 +#define S_CRYPT_NULL 0x000100 +#define S_CRYPT_RC4_40 0x000200 +#define S_CRYPT_RC4_56 0x000300 +#define S_CRYPT_RC4_128 0x000400 +#define S_CRYPT_RC2_CBC_40 0x000500 +#define S_CRYPT_IDEA_CBC 0x000600 +#define S_CRYPT_DES40_CBC 0x000700 +#define S_CRYPT_DES_CBC 0x000800 +#define S_CRYPT_3DES_EDE_CBC 0x000900 +#define S_CRYPT_FORTEZZA_CBC 0x000A00 +#define S_CRYPT_AES_128_CBC 0x000B00 +#define S_CRYPT_AES_256_CBC 0x000C00 + +/* Hash Algorithms */ +#define S_HASH_NONE 0x000000 +#define S_HASH_NULL 0x000001 +#define S_HASH_MD5 0x000002 +#define S_HASH_SHA 0x000003 + +/* Cipher Suite Seletion */ +#define S_CIPHER_NOSSL 0x000000 +#define S_CIPHER_ANY 0xFFFFFF + +/* 49 Cipher Suites are defined by SSL 3.0 and TLS 1.0 */ +/* Bit fields: Key Exchange Encryption Hash */ +#define S_CIPHER_NONE (S_KEYX_NONE | S_CRYPT_NONE | S_HASH_NONE) +#define S_CIPHER_010103 (S_KEYX_NULL | S_CRYPT_NULL | S_HASH_SHA) +#define S_CIPHER_020102 (S_KEYX_RSA | S_CRYPT_NULL | S_HASH_MD5) +#define S_CIPHER_020103 (S_KEYX_RSA | S_CRYPT_NULL | S_HASH_SHA) +#define S_CIPHER_020402 (S_KEYX_RSA | S_CRYPT_RC4_128 | S_HASH_MD5) +#define S_CIPHER_020403 (S_KEYX_RSA | S_CRYPT_RC4_128 | S_HASH_SHA) +#define S_CIPHER_020603 (S_KEYX_RSA | S_CRYPT_IDEA_CBC | S_HASH_SHA) +#define S_CIPHER_020803 (S_KEYX_RSA | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_020903 (S_KEYX_RSA | S_CRYPT_3DES_EDE_CBC | S_HASH_SHA) +#define S_CIPHER_020B03 (S_KEYX_RSA | S_CRYPT_AES_128_CBC | S_HASH_SHA) +#define S_CIPHER_020C03 (S_KEYX_RSA | S_CRYPT_AES_256_CBC | S_HASH_SHA) +#define S_CIPHER_030202 (S_KEYX_RSA_EX | S_CRYPT_RC4_40 | S_HASH_MD5) +#define S_CIPHER_030303 (S_KEYX_RSA_EX | S_CRYPT_RC4_56 | S_HASH_SHA) +#define S_CIPHER_030502 (S_KEYX_RSA_EX | S_CRYPT_RC2_CBC_40 | S_HASH_MD5) +#define S_CIPHER_030703 (S_KEYX_RSA_EX | S_CRYPT_DES40_CBC | S_HASH_SHA) +#define S_CIPHER_030803 (S_KEYX_RSA_EX | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_040803 (S_KEYX_DH_DSS | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_040903 (S_KEYX_DH_DSS | S_CRYPT_3DES_EDE_CBC | S_HASH_SHA) +#define S_CIPHER_040B03 (S_KEYX_DH_DSS | S_CRYPT_AES_128_CBC | S_HASH_SHA) +#define S_CIPHER_040C03 (S_KEYX_DH_DSS | S_CRYPT_AES_256_CBC | S_HASH_SHA) +#define S_CIPHER_050703 (S_KEYX_DH_DSS_EX | S_CRYPT_DES40_CBC | S_HASH_SHA) +#define S_CIPHER_060803 (S_KEYX_DH_RSA | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_060903 (S_KEYX_DH_RSA | S_CRYPT_3DES_EDE_CBC | S_HASH_SHA) +#define S_CIPHER_060B03 (S_KEYX_DH_RSA | S_CRYPT_AES_128_CBC | S_HASH_SHA) +#define S_CIPHER_060C03 (S_KEYX_DH_RSA | S_CRYPT_AES_256_CBC | S_HASH_SHA) +#define S_CIPHER_070703 (S_KEYX_DH_RSA_EX | S_CRYPT_DES40_CBC | S_HASH_SHA) +#define S_CIPHER_080403 (S_KEYX_DHE_DSS | S_CRYPT_RC4_128 | S_HASH_SHA) +#define S_CIPHER_080803 (S_KEYX_DHE_DSS | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_080903 (S_KEYX_DHE_DSS | S_CRYPT_3DES_EDE_CBC | S_HASH_SHA) +#define S_CIPHER_090303 (S_KEYX_DHE_DSS_EX | S_CRYPT_RC4_56 | S_HASH_SHA) +#define S_CIPHER_090703 (S_KEYX_DHE_DSS_EX | S_CRYPT_DES40_CBC | S_HASH_SHA) +#define S_CIPHER_090803 (S_KEYX_DHE_DSS_EX | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_080B03 (S_KEYX_DHE_DSS | S_CRYPT_AES_128_CBC | S_HASH_SHA) +#define S_CIPHER_080C03 (S_KEYX_DHE_DSS | S_CRYPT_AES_256_CBC | S_HASH_SHA) +#define S_CIPHER_0A0803 (S_KEYX_DHE_RSA | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_0A0903 (S_KEYX_DHE_RSA | S_CRYPT_3DES_EDE_CBC | S_HASH_SHA) +#define S_CIPHER_0A0B03 (S_KEYX_DHE_RSA | S_CRYPT_AES_128_CBC | S_HASH_SHA) +#define S_CIPHER_0A0C03 (S_KEYX_DHE_RSA | S_CRYPT_AES_256_CBC | S_HASH_SHA) +#define S_CIPHER_0B0703 (S_KEYX_DHE_RSA_EX | S_CRYPT_DES40_CBC | S_HASH_SHA) +#define S_CIPHER_0C0402 (S_KEYX_DH_ANON | S_CRYPT_RC4_128 | S_HASH_MD5) +#define S_CIPHER_0C0803 (S_KEYX_DH_ANON | S_CRYPT_DES_CBC | S_HASH_SHA) +#define S_CIPHER_0C0903 (S_KEYX_DH_ANON | S_CRYPT_3DES_EDE_CBC | S_HASH_SHA) +#define S_CIPHER_0C0B03 (S_KEYX_DH_ANON | S_CRYPT_AES_128_CBC | S_HASH_SHA) +#define S_CIPHER_0C0C03 (S_KEYX_DH_ANON | S_CRYPT_AES_256_CBC | S_HASH_SHA) +#define S_CIPHER_0D0202 (S_KEYX_DH_ANON_EX | S_CRYPT_RC4_40 | S_HASH_MD5) +#define S_CIPHER_0D0703 (S_KEYX_DH_ANON_EX | S_CRYPT_DES40_CBC | S_HASH_SHA) +#define S_CIPHER_0E0103 (S_KEYX_FORTEZZA_DMS | S_CRYPT_NULL | S_HASH_SHA) +#define S_CIPHER_0E0403 (S_KEYX_FORTEZZA_DMS | S_CRYPT_RC4_128 | S_HASH_SHA) +#define S_CIPHER_0E0A03 (S_KEYX_FORTEZZA_DMS | S_CRYPT_FORTEZZA_CBC | S_HASH_SHA) + +/************************************************************************/ +/* Certificate Names */ + +/* nameType defines */ +#define S_CERT_NAME_TYPE_ANY 0 +#define S_CERT_NAME_TYPE_COMMON_NAME 1 +#define S_CERT_NAME_TYPE_COUNTRY 2 +#define S_CERT_NAME_TYPE_STATE_OR_PROVINCE 3 +#define S_CERT_NAME_TYPE_LOCALITY 4 +#define S_CERT_NAME_TYPE_ORGANIZATION 5 +#define S_CERT_NAME_TYPE_EMAIL 6 +#define S_CERT_NAME_TYPE_ORGANIZATIONAL_UNIT 7 + +#define S_CERT_NAME_MAX_LEN 255 + +/* A name in a certificate is a list of names and nane types */ +typedef struct S_CERT_NAME_tag + { + DBL_LNK l; + ST_INT nameType; + ST_CHAR *nameText; + } S_CERT_NAME; + + +/************************************************************************/ +/* Identifying a Certificate */ + +#define S_SERIAL_NUM_NONE -1 + +typedef struct S_CERT_ID_tag + { + /* Note: adding/removing fields to/from this struct will make older */ + /* !!! applications incompatible with new security DLLs. */ + ST_INT serialLen; /* 0 == wildcard */ + ST_UCHAR serialNumber[S_SEC_MAX_SERIAL_LEN]; /* reverse from mmc */ + S_CERT_NAME *issuerCName; /* NULL == wildcard */ + S_CERT_NAME *subjectCName; /* NULL == wildcard */ + } S_CERT_ID; + + +/************************************************************************/ +/* Certificate BLOB, X.509 format */ + +typedef struct S_CERT_BLOB_tag + { + /* Note: adding/removing fields to/from this struct will make older */ + /* !!! applications incompatible with new security DLLs. */ + ST_INT certDataLen; + ST_UCHAR *certData; + } S_CERT_BLOB; + +/************************************************************************/ +/* Signed Time */ + +typedef struct S_SIGNED_TIME_tag + { + /* Note: adding/removing fields to/from this struct will make older */ + /* !!! applications incompatible with new security DLLs. */ + ST_INT signedTimeLen; + ST_UCHAR *signedTimeData; + } S_SIGNED_TIME; + +/************************************************************************/ +/* MACE authentication information */ + +typedef struct S_MACE_INFO_tag + { + ST_INT authType; + union + { + struct + { + S_CERT_BLOB certBlob; + time_t signedTimeT; + + /* UTC NULL-terminated time string to be verified */ + ST_UCHAR clearTime[S_SEC_MAX_SIGNED_TIME_LEN]; + /* UTC time string signed by the sender */ + S_SIGNED_TIME signedTime; + + } certBased; + struct + { + ST_INT placeHolder; + } symmetric; + } u; + } S_MACE_INFO; + + +/************************************************************************/ +/************************************************************************/ +/* Certificate Content Information */ + +typedef struct S_CERT_INFO_tag + { + /* Note: adding/removing fields to/from this struct will make older */ + /* applications incompatible with new security DLLs. */ + ST_INT version; + S_CERT_ID certId; + struct + { + time_t validNotBefore; + time_t validNotAfter; + } validity; + +#if 0 + struct + { + ST_INT publicKeyAlgorithm; + ST_INT algorithmIdentifier; + } algorithms; +#endif + + ST_UCHAR *publicKey; + ST_INT publicKeyLen; + } S_CERT_INFO; + + +/************************************************************************/ +/************************************************************************/ +/* Security Configuration */ +/************************************************************************/ + +/* List of Certificate ID's */ +typedef struct S_CERT_CTRL_tag + { + DBL_LNK l; + ST_CHAR *certName; /* Null if no associated name */ + S_CERT_ID certId; + +/* Rekey Control. These override the global rekey parameters if != 0 */ +/* They apply only to remote certificates */ + ST_UINT32 maxTransactionsPerKey; + ST_UINT32 maxTimePerKey; /* in seconds */ + ST_INT rekeyTimeout; /* In seconds */ + +/* Internal use */ + ST_UINT32 cfgId; /* computed 32-bit CRC on certId */ + /* enabled fields (for matching) */ + } S_CERT_CTRL; + +/************************************************************************/ +/* AR Security Mapping Defines */ + +/* appAuthRequired defines */ +/* These defines come into play only if 'Remote AR Security' is not */ +/* found for an incoming connection */ + +/* 'Remote AR Security' is required; reject all other indications */ +#define S_APP_AUTHREQ_AR_SEC 0 +/* A configured MACE certificate is required */ +#define S_APP_AUTHREQ_MACE 1 +/* A configured MACE certificate is required and encryption is required */ +#define S_APP_AUTHREQ_MACE_ENCRYPTED 2 +/* Encryption is required */ +#define S_APP_AUTHREQ_ENCRYPTED 3 +/* There are no requirements; all connections are acceptable */ +#define S_APP_AUTHREQ_NONE 4 + + + +#define S_AR_AUTH_MODE_AETITLE 0 +#define S_AR_AUTH_MODE_MACE 1 +#define S_AR_AUTH_MODE_SSL 2 +/* For backward compatibility only */ +#define S_AR_AUTH_MODE_NONE S_AR_AUTH_MODE_AETITLE + +/* Note that the Local is used to select the local MACE certificate for */ +/* connections to a remote with arAuthMode == S_AR_AUTH_MODE_MACE */ +typedef struct S_SEC_LOC_AR_tag + { + DBL_LNK l; + ST_CHAR *arName; /* Local or Remote AR Name */ + S_CERT_CTRL *maceCert; /* NULL if none configured */ + +/* User */ + ST_VOID *usr; + } S_SEC_LOC_AR; + +/* Remote AR Security Configuration */ +/* Note that the Remote is used to determine the ACSE authentication */ +/* and encryption to be used for both calling and called connections, */ +/* and is used in identifying the remote for called connections */ +typedef struct S_SEC_REM_AR_tag + { + DBL_LNK l; + ST_CHAR *arName; /* Local or Remote AR Name */ + + /* Authentication */ + ST_INT arAuthMode; + +/* Authentication Certificate: */ +/* arAuthMode == S_AR_AUTH_MODE_MACE : Remote MACE cert */ +/* arAuthMode == S_AR_AUTH_MODE_SSL : Remote SSL cert */ +/* arAuthMode == S_AR_AUTH_MODE_NONE : NULL */ + S_CERT_CTRL *authCert; + +/* Encryption */ + ST_INT encryptMode; + ST_UINT16 sslPort; /* For S_SEC_ENCRYPT_SSL */ + +/* User */ + ST_VOID *usr; + } S_SEC_REM_AR; + +#if defined(_WIN32) +/* Placeholder struct kept only for compatibility purposes with older + * applications. Used in main S_SEC_CFG struct below. + */ +typedef struct + { + ST_INT mutexType; /* GS_MUTEX_UNNAMED (_NAMED) */ + union + { + HANDLE hMutex; /* for named mutex */ + CRITICAL_SECTION cs; /* for unnamed mutex */ + } u; + } ST_MUTEX_SEM_SSEC; +#else +#define ST_MUTEX_SEM_SSEC ST_MUTEX_SEM +#endif + +/************************************************************************/ +/**** Main Configuration Structure ****/ + +#define S_SSL_MAX_LISTEN_PORTS 10 +typedef struct + { + /* Note: adding/removing fields to/from this struct will make older */ + /* !!! applications incompatible with new security DLLs. */ + + /****** General Configuration ******/ + ST_BOOLEAN secureModeEnabled; + + /* Old struct kept around for alignment purposes with old(er) apps */ + ST_MUTEX_SEM_SSEC obsoleteCfgMutex; + + /****** MACE Level Configuration ******/ + /* Time Signature Window */ + ST_UINT32 timeSealWindow; + + /****** Certificate Lists ******/ + /* Remote Certificates and associated AR Names */ + S_CERT_CTRL *sslRemoteCertList; + + /* Local Certificates and associated AR Names */ + S_CERT_CTRL *sslLocalCertList; + + /* Acceptable CA Certificates */ + S_CERT_CTRL *sslTrustedCaCertList; + + /****** SSL Configuration ******/ + /* Local Certificate to be used */ + S_CERT_CTRL *sslLocalCertCtrl; + + /* Listen Port Numbers */ + ST_INT numSslListenPorts; + ST_UINT16 sslListenPorts[S_SSL_MAX_LISTEN_PORTS]; + + /* Allowed Ciphers, ordered by preference */ + ST_INT numAllowedCipherSuites; + ST_INT allowedCipherSuites[S_MAX_ALLOWED_CIPHER_SUITES]; + + /* Flags */ + ST_BOOLEAN certAuthCalling; /* verify that peer certificate is configured */ + ST_BOOLEAN certAuthCalled; /* verify that peer certificate is configured */ + ST_BOOLEAN encryptReqCalling; /* encryption required on calling connection */ + ST_BOOLEAN encryptReqCalled; /* encryption required on called connection */ + + /* Rekey Control */ + ST_UINT32 maxTransactionsPerKey; + ST_UINT32 maxTimePerKey; /* in seconds */ + ST_INT rekeyTimeout; /* In seconds */ + + /* CRL Control */ + ST_INT crlCheckTime; /* In minutes */ + ST_BOOLEAN crlDropExisting; + + /****** Application Configuation */ + ST_INT appAuthRequired; + DIB_MATCH_CTRL dibMatch; + + /* Well Known AR Names */ + S_SEC_LOC_AR *secLocArList; + S_SEC_REM_AR *secRemArList; + + /****** SNAP Configuation */ + ST_UINT16 defCallingSslPort; /* Default SSL Calling Port Number */ + + /* Misc */ + ST_UINT maxCalling; + ST_UINT maxCalled; + + ST_INT cpuAffinity; + + /* Calling connection timeout, used by SNAP. Default 10000ms */ + ST_INT callingConnectTimeout; /* In milliseconds */ + + /****** IPC: SNAP/Stack Ports & IP Addresses */ + ST_CHAR *stackIPAddress; + ST_UINT16 stackListenPort; + + ST_CHAR *snapIPAddress; + ST_UINT16 snapListenPort; + ST_UINT16 snapControlListenPort; + ST_UINT16 snapMonitorListenPort; + + /* SNAP/STACK Connect-to-Ctrl timeout, bidirectional. Default 500ms */ + ST_INT snapStackCtrlTimeout; /* In milliseconds */ + + /****** Security Logging ******/ + ST_INT secEventLogTimeStampMode; + ST_INT secEventLogFileSize; + ST_CHAR *secEventLogFile; + ST_INT diagLogTimeStampMode; + ST_INT diagLogFileSize; + ST_CHAR *diagLogFileName; + ST_UINT secLogMasks; + } S_SEC_CONFIG; + + +/************************************************************************/ +/************************************************************************/ + +#define S_SEC_ENCRYPT_NONE 0 +#define S_SEC_ENCRYPT_SSL 1 +typedef struct S_SEC_ENCRYPT_CTRL_tag + { + ST_INT encryptMode; + union + { + struct + { + ST_UINT16 port; + ST_BOOLEAN sslCertMatched; /* The Subject-to-CertId succeded */ + S_CERT_CTRL *sslCert; /* The matched SSL cert ctrl */ + ST_INT cipherSuite; /* Cipher suite in use */ + } ssl; + } u; + } S_SEC_ENCRYPT_CTRL; + +/* Struct passed back and forth to SUIC */ +typedef struct S_SEC_SPARAMS_tag + { + ACSE_AUTH_INFO *authInfo; + ACSE_AUTH_INFO *partAuthInfo; + S_SEC_ENCRYPT_CTRL *encryptCtrl; + } S_SEC_SPARAMS; + +/************************************************************************/ + +/* Application Level Authentication Check Result */ +typedef struct S_SEC_AUTHCHK_RSLT_tag + { +/* Encryption in use */ + S_SEC_ENCRYPT_CTRL encryptInfo; + +/* Authentication in use */ + ST_INT authPres; + ST_INT mechType; + union + { + struct + { + ST_BOOLEAN timeSealOk; /* Timeseal not reused, in window */ + ST_BOOLEAN maceCertTimeValid; /* Certificate validity times OK */ + ST_BOOLEAN maceCertIssuerOk; /* The issuer is in the OK list */ + ST_BOOLEAN maceCertMatched; /* The Subject-to-CertId succeded */ + S_CERT_CTRL *maceCert; /* The matched MACE cert ctrl */ + } certBased; + struct + { + ST_INT placeHolder; + } symmetric; + struct + { + ST_INT placeHolder2; + } passsword; + } u; + } S_SEC_AUTHCHK_RSLT; + +/************************************************************************/ +/* Look up configured security information by AR Name */ +ST_RET sSecRemArNameToArSec (ST_CHAR *arName, S_SEC_REM_AR **arSecOut); +ST_RET sSecLocArNameToArSec (ST_CHAR *arName, S_SEC_LOC_AR **arSecOut); + +/************************************************************************/ +/* These functions can be used to select and examine SSL level info */ +/* for the selected connection */ +#if defined(MMS_LITE) && !defined(MAP30_ACSE) +/* ssecusr.c functions */ +struct mvl_net_info; /* forward reference */ +ST_RET sSecAssocIndChk (struct mvl_net_info *cc, DIB_MATCH_CTRL *matchCtrl, + S_SEC_REM_AR **arSecOut, S_SEC_AUTHCHK_RSLT *srcChkDest); +ST_RET sSecAssocConfChkEx (struct mvl_net_info *cc, DIB_MATCH_CTRL *matchCtrl, + S_SEC_REM_AR *remArSec, S_SEC_AUTHCHK_RSLT *srcChkDest); +ST_RET sSecAuthChk (struct mvl_net_info *cc, S_SEC_AUTHCHK_RSLT *srcChkDest); +ST_RET sSecGetSecParam (struct mvl_net_info *cc, S_SEC_SPARAMS *secParams); +ST_RET sSecFreeSecParam (ACSE_AUTH_INFO *authInfo); +ST_RET sSecFreePartSecParam (struct mvl_net_info *cc); + +/* For backward compatability */ +#define sSecAssocConfChk(cc,remArSec,secChkDest) sSecAssocConfChkEx(cc,NULL,remArSec,secChkDest) +#else /* !defined(MMS_LITE) || defined(MAP30_ACSE) */ +/* ssecusr.c functions */ +ST_RET sSecAssocIndChk (ST_INT chan, DIB_MATCH_CTRL *matchCtrl, + S_SEC_REM_AR **arSecOut, S_SEC_AUTHCHK_RSLT *srcChkDest); +ST_RET sSecAssocConfChkEx (ST_INT chan, DIB_MATCH_CTRL *matchCtrl, + S_SEC_REM_AR *remArSec, S_SEC_AUTHCHK_RSLT *srcChkDest); +ST_INT sSecAuthChk (ST_INT chan, S_SEC_AUTHCHK_RSLT *srcChkDest); +ST_RET sSecSetSecParam (ST_INT chan, S_SEC_SPARAMS *secParams); +ST_RET sSecGetSecParam (ST_INT chan, S_SEC_SPARAMS *secParams); + +/* For backward compatability */ +#define sSecAssocConfChk(chan,remArSec,secChkDest) sSecAssocConfChkEx(chan,NULL,remArSec,secChkDest) +#endif /* !defined(MMS_LITE) || defined(MAP30_ACSE) */ + + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* Initialize/Terminate */ + +ST_RET sSecUsrStart (S_SEC_CONFIG **secCfgOut); +ST_RET sSecUsrEnd (ST_VOID); +ST_RET sSecStart (S_SEC_CONFIG **secCfg); +ST_RET sSecEnd (ST_VOID); + +/************************************************************************/ +/* Configuration */ + +/* Used by configuration app to get SEC_MAN config information */ +ST_CHAR *secManGetXmlCfg (ST_VOID); +ST_RET secManSetXmlCfg (ST_CHAR *pw, ST_CHAR *xmlCfg); +ST_RET secManExportLocalCerts (ST_CHAR *pw, ST_INT *destFile); + +/* Used by app to reload security components */ +ST_RET sSecUpdate(S_SEC_CONFIG *currCfg, S_SEC_CONFIG *newCfg); + +/************************************************************************/ +/* MACE Authentication */ + +/* Create/Free MACE Authentication Information for a local CertId */ +ST_RET sSecMaceAuthInfoCreate (S_CERT_ID *certId, ACSE_AUTH_INFO *authInfo); + +ST_VOID sSecMaceAuthInfoFree (ACSE_AUTH_INFO *auth_info); + +/* Decode MACE Authentication Information */ +ST_RET sSecMaceAuthInfoDec (ACSE_AUTH_INFO *authInfo, + S_MACE_INFO **maceInfoOut, + S_CERT_INFO **certInfoOut); +ST_VOID sSecFreeCertInfo (S_CERT_INFO *certInfo); + +/************************************************************************/ +/************************************************************************/ +/* Finding things in the Security Configuration */ + +/**** Find configured local CertCtrl for given certName ****/ +ST_RET sSecCertNameToLocCertCtrl (ST_CHAR *certName, S_CERT_CTRL **certCtrlOut); + +/**** Find configured remote CertCtrl for given certName ****/ +ST_RET sSecCertNameToRemCertCtrl (ST_CHAR *certName, S_CERT_CTRL **certCtrlOut); + +/**** Find configured remote CertCtrl for given CertId ****/ +ST_RET sSecCertIdToRemCertCtrl (S_CERT_ID *certId, S_CERT_CTRL **certCtrlOut); + +/**** Find configured remote CertCtrl for given cfgId ****/ +ST_RET sSecCertCfgIdToRemCertCtrl (ST_INT cfgId, S_CERT_CTRL **CertCtrlOut); + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/**** Certificate Blob Handling ****/ + +/* Retrieve local Certificate Blob from Certifcate Store */ +ST_RET sSecGetLocalCert (S_CERT_ID *certId, S_CERT_BLOB *certDataOut); + +/* Decoding a Certificate blob */ +ST_RET sSecCertDec (S_CERT_BLOB *certBlob, S_CERT_INFO **certInfoOut); + +/************************************************************************/ +/**** Signed Time Handling ****/ + +/* Verify a Signed Time signature */ +ST_RET sSecSignedTimeVerify (S_CERT_INFO *remCert, S_SIGNED_TIME *signedTime, ST_UCHAR *clearTime); + +/* Sign a time_t */ +ST_RET sSecSignTimeT (S_CERT_ID *localCert, S_SIGNED_TIME *signedTime, time_t timeToSign); + +/************************************************************************/ +/**** MACE ASN.1 Encode/Decode ****/ + +/* Encode MACE ACSE Authentication */ +ST_RET sSecMaceAsn1Enc (S_MACE_INFO *maceInfo, + ST_CHAR *asn1Buf, ST_INT asn1BufLen, + ST_CHAR **maceAsn1Out, ST_INT *maceAsn1LenOut); + +/* Decode Certificate based ACSE Authentication */ +ST_RET sSecMaceAsn1Dec (ST_CHAR *maceAsn1, ST_INT maceAsn1Len, + S_MACE_INFO **maceInfoOut); + +/************************************************************************/ +/**** Remote Certificate Validity Checking ****/ + +/* Make sure the certificate issuer is OK */ +ST_RET sSecChkIssuer (S_CERT_INFO *certInfo); + +/* Make sure the certificate validity times are OK */ +ST_RET sSecChkValidityTimes (S_CERT_INFO *certInfo); + +/* Validate a MACE time seal */ +ST_RET sSecChkTimeSeal (S_CERT_INFO *remCert, + time_t signedTimeT, + ST_UCHAR *clearTime, + S_SIGNED_TIME *signedTime); + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* Common functions declarations */ + +/**** Compare remote cert issuer names with ones that we trust ****/ +ST_BOOLEAN sSecCmpIssuer (S_CERT_ID *remCert, S_CERT_ID *trustedCert); +/**** Compare two CertIds ****/ +ST_BOOLEAN sSecCmpCertId (S_CERT_ID *certId1, S_CERT_ID *certId2); + +/* Export a certificate to XML */ +#if !defined(_WIN32) +ST_INT ssleCertFileToXml (ST_CHAR *fileName, ST_CHAR *buf, ST_INT bufLen, ST_CHAR *pass); +/* Export a certificate to Text */ +ST_INT ssleCertFileToText (ST_CHAR *fileName, ST_CHAR *buf, ST_INT bufLen, ST_CHAR *pass); +#endif /* !defined(_WIN32) */ + +ST_RET ssleLoadCRLists(ST_VOID *ssl_ctx, ST_BOOLEAN *newCrlOut); + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* secMan Declarations */ +/************************************************************************/ + +/* Set log masks */ +ST_UINT* secManGetDebugSel(ST_VOID); + +/* Start/Stop */ +ST_RET secManStart (S_SEC_CONFIG **secCfg, ST_VOID *secLog); +ST_RET secManEnd (ST_VOID); + +/* Start the SSL Engine in ssec.lib (genssl.c) */ +ST_RET startSSLEngine(S_SEC_CONFIG *sSecCfg, ST_VOID *secLog); +/* Stop the SSL Engine in ssec.lib (genssl.c) */ +ST_RET stopSSLEngine(ST_VOID); +/* Called by SNAP to reload the security configuration (genssl.c) */ +ST_RET sslUpdate(ST_VOID); +/* Called by SNAP-Lite to reload the CRLs (genssl.c) */ +ST_RET updateCRLists (ST_VOID); + +/* Used by SNAP and user apps to get the configuration. + * The release function MUST be called when the app is done using the + * configuration. + */ +ST_RET secManAccessCfg (S_SEC_CONFIG **secCfgOut); +ST_RET secManReleaseCfg (ST_VOID); + +/* Used by the stack to get the configuration */ +ST_RET secManAccessCfgByStack (S_SEC_CONFIG **secCfgOut); + +/* Dynamic Configuration functions */ +ST_BOOLEAN secManChkNewCfgAvail(ST_VOID); +ST_RET secManLoadCfg(S_SEC_CONFIG *secCfgOut); +ST_RET secManUpdateCfg(S_SEC_CONFIG *currCfg, S_SEC_CONFIG *newCfg); +ST_RET secManFreeCfg(S_SEC_CONFIG *secCfg); + +#if !defined(MMS_LITE) || defined(MAP30_ACSE) +#if defined (_WIN32) +/* Called by app or SecCfg to signal change in configuration file */ +__declspec(dllimport) ST_VOID WINAPI secManCfgChange(ST_VOID); +/* __declspec(dllexport) ST_VOID WINAPI secManCfgChange(ST_VOID);*/ +#endif +#else /* MMS_LITE */ +ST_VOID secManCfgChange(ST_VOID); +#endif /* MMS_LITE */ + +#if !defined(MMS_LITE) || defined(MAP30_ACSE) +/* Software Lock access */ +ST_RET secManLckStart(ST_VOID); +ST_VOID secManLckEnd(ST_VOID); +ST_RET secManLckCheck(ST_VOID); +#else +/* MMS_LITE */ +extern ST_CHAR *secManCfgXmlFile; +#endif + +#if !defined(_WIN32) +/* --- For UNIX & LINUX define default path to Certificate Stores --- */ +/* --- under the SISCO_PATH_INSTALL/SISCO_PATH_SECURITY directory --- */ +#define CERT_STORE_LOCAL "certstore/local" +#define CERT_STORE_CA "certstore/ca" +#define CERT_STORE_REMOTE "certstore/remote" + +/* If needed these paths can be changed by app before sSecStart() is called */ +extern ST_CHAR LocalCertStorePath[S_MAX_PATH]; /* defaults to CERT_STORE_LOCAL */ +extern ST_CHAR CACertStorePath[S_MAX_PATH]; /* defaults to CERT_STORE_CA */ + +/* Exported function from libsecpass shared library (provided by the user) */ +ST_RET secPassGetPassword(S_CERT_ID *certId, ST_CHAR *certPass, ST_INT certPassLen); +#endif /* !defined(_WIN32) */ + +/* Logging */ +/* destLog defines */ +#define S_SEC_LOGTYPE_NONE 0 +#define S_SEC_LOGTYPE_DIAG 1 +#define S_SEC_LOGTYPE_SECURITY 2 + +/* eventType defines */ +#define S_SEC_EVENT_NO_CIPHERS 1 +#define S_SEC_EVENT_UNKNOWN_CA 2 +#define S_SEC_EVENT_UNKNOWN_REMOTE 3 +#define S_SEC_EVENT_SSL_FAILURE 4 +#define S_SEC_EVENT_REKEY_FAILURE 5 + +typedef struct S_SEC_EVENT_tag + { + /* Note: adding/removing fields to/from this struct will make older */ + /* !!! applications incompatible with new security DLLs. */ + ST_INT destLog; /* Select Diagnoistic or Security log */ + + /* This section needs work */ + ST_BOOLEAN logSystemEvent; /* Log to System event system */ + ST_INT eventType; + ST_INT8 numArgs; + ST_CHAR *eventArgs[32]; + + ST_BOOLEAN logToSlog; /* Log to SLOG file */ + ST_INT logType; /* Standard SLOG information */ + ST_CHAR *SD_CONST logTypeStr; + ST_CHAR *SD_CONST sourceFile; + ST_INT lineNum; + ST_INT bufLen; + ST_CHAR *buf; + } S_SEC_EVENT; + +/* Logging to Event Viewer via secman.dll */ +ST_VOID secManEventLog (S_SEC_EVENT *secEvent, S_CERT_INFO *cert); + +/**** Output the serial number as a string ****/ +ST_VOID secManPrintSrlNum (S_CERT_ID *certId, ST_CHAR *outBuf, ST_INT outBufLen); + +/* Log configuration to diagnostic log */ +ST_VOID secManLogCfg (ST_VOID); + +/* Clone the log file */ +ST_VOID secManCloneLog (ST_INT logType); + +/************************************************************************/ +/************************************************************************/ +/* Log Macros */ + +/* Log type strings */ +extern SD_CONST ST_CHAR *SD_CONST _sec_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sec_nerr_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sec_flow_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sec_data_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sec_debug_logstr; + +#define SECLOG_ERR0(a) \ + SLOG_0 (sec_debug_sel & SEC_LOG_ERR, _sec_err_logstr, a) +#define SECLOG_ERR1(a,b) \ + SLOG_1 (sec_debug_sel & SEC_LOG_ERR, _sec_err_logstr, a,b) +#define SECLOG_ERR2(a,b,c) \ + SLOG_2 (sec_debug_sel & SEC_LOG_ERR, _sec_err_logstr, a,b,c) +#define SECLOG_ERR3(a,b,c,d) \ + SLOG_3 (sec_debug_sel & SEC_LOG_ERR, _sec_err_logstr, a,b,c,d) + +#define SECLOG_CERR0(a) \ + SLOGC_0 (sec_debug_sel & SEC_LOG_ERR,a) +#define SECLOG_CERR1(a,b) \ + SLOGC_1 (sec_debug_sel & SEC_LOG_ERR,a,b) +#define SECLOG_CERR2(a,b,c) \ + SLOGC_2 (sec_debug_sel & SEC_LOG_ERR,a,b,c) + +#define SECLOG_NERR0(a) \ + SLOG_0 (sec_debug_sel & SEC_LOG_NERR, _sec_nerr_logstr, a) +#define SECLOG_NERR1(a,b) \ + SLOG_1 (sec_debug_sel & SEC_LOG_NERR, _sec_nerr_logstr, a,b) +#define SECLOG_NERR2(a,b,c) \ + SLOG_2 (sec_debug_sel & SEC_LOG_NERR, _sec_nerr_logstr, a,b,c) +#define SECLOG_NERR3(a,b,c,d) \ + SLOG_3 (sec_debug_sel & SEC_LOG_NERR, _sec_nerr_logstr, a,b,c,d) + +#define SECLOG_FLOW0(a) \ + SLOG_0 (sec_debug_sel & SEC_LOG_FLOW, _sec_flow_logstr, a) +#define SECLOG_FLOW1(a,b) \ + SLOG_1 (sec_debug_sel & SEC_LOG_FLOW, _sec_flow_logstr, a,b) +#define SECLOG_FLOW2(a,b,c) \ + SLOG_2 (sec_debug_sel & SEC_LOG_FLOW, _sec_flow_logstr, a,b,c) +#define SECLOG_FLOW3(a,b,c,d) \ + SLOG_3 (sec_debug_sel & SEC_LOG_FLOW, _sec_flow_logstr, a,b,c,d) + +#define SECLOG_CFLOW0(a) \ + SLOGC_0 (sec_debug_sel & SEC_LOG_FLOW,a) +#define SECLOG_CFLOW1(a,b) \ + SLOGC_1 (sec_debug_sel & SEC_LOG_FLOW,a,b) + +#define SECLOG_DEBUG0(a) \ + SLOG_0 (sec_debug_sel & SEC_LOG_DEBUG, _sec_debug_logstr, a) +#define SECLOG_DEBUG1(a,b) \ + SLOG_1 (sec_debug_sel & SEC_LOG_DEBUG, _sec_debug_logstr, a,b) +#define SECLOG_DEBUG2(a,b,c) \ + SLOG_2 (sec_debug_sel & SEC_LOG_DEBUG, _sec_debug_logstr, a,b,c) +#define SECLOG_DEBUG3(a,b,c,d) \ + SLOG_3 (sec_debug_sel & SEC_LOG_DEBUG, _sec_debug_logstr, a,b,c,d) + +#define SECLOG_CDEBUG0(a) \ + SLOGC_0 (sec_debug_sel & SEC_LOG_DEBUG,a) +#define SECLOG_CDEBUG1(a,b) \ + SLOGC_1 (sec_debug_sel & SEC_LOG_DEBUG,a,b) + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* S_SEC_INCLUDED */ +/************************************************************************/ diff --git a/mmslib/inc/ssec_int.h b/mmslib/inc/ssec_int.h new file mode 100644 index 0000000..b8445d4 --- /dev/null +++ b/mmslib/inc/ssec_int.h @@ -0,0 +1,56 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003 - 2007, All Rights Reserved */ +/* */ +/* MODULE NAME : ssec_int.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains internal security functions, defines,... */ +/* that are not exposed to user. */ +/* It also contains function that are passing GEN_SOCK parameter. */ +/* Having these protos in ssec.h caused compile conflicts in */ +/* project using old gensock.h */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/06/07 EJV 02 Chg sSecGetCertId param to ST_UINT32. */ +/* Added few prototypes. */ +/* 08/25/03 EJV 01 Moved protos with GEN_SOCK from ssec.h */ +/************************************************************************/ + +#ifndef SSEC_INT_INCLUDED +#define SSEC_INT_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gensock2.h" + + +/* internal functions for secure socket interface */ +ST_RET setGenSockSSL (GEN_SOCK_CONFIG *sockCfg); +ST_RET sSecGetCipherSuite (GEN_SOCK *pSock, ST_INT *cipherSuiteOut); +ST_RET sSecGetCertId (GEN_SOCK *pSock, ST_UINT32 *cfgIdOut); +ST_RET sSecGetCertCtrl (GEN_SOCK *pSock, S_CERT_CTRL **certCtrlOut); + +ST_RET _secManGetCfg (S_SEC_CONFIG **secCfgOut); + +ST_INT sslGetCipherSuite (GEN_SOCK *pSock); +S_CERT_INFO *sslGetPeerCert (GEN_SOCK *pSock); +ST_VOID sslFreePeerCert (S_CERT_INFO *remCert); + + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* SSEC_INT_INCLUDED */ +/************************************************************************/ diff --git a/mmslib/inc/ssleLog.h b/mmslib/inc/ssleLog.h new file mode 100644 index 0000000..76490b9 --- /dev/null +++ b/mmslib/inc/ssleLog.h @@ -0,0 +1,154 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003 - 2008, All Rights Reserved */ +/* */ +/* MODULE NAME : sslLog.h */ +/* PRODUCT(S) : Sisco MMS Security Toolkit */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* SSL Toolkit logging macros */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/28/08 EJV 24 Merged with non-Marben code. */ +/* 04/08/08 JRB 05 Chg () to (ST_VOID) in prototype. */ +/* 10/20/03 ASK 04 Added ssleGetDebugSel proto. Modlog cleanup. */ +/* 09/03/03 EJV 03 Made ssle_debug_sel ST_UINT */ +/* Moved SSLE_LOG_* masks from sslEngine.h */ +/* 08/21/03 EJV 02 Made ssle_debug_sel extern */ +/* 08/21/02 ASK 01 Created */ +/************************************************************************/ + +#ifndef SSLE_LOG_INCLUDED +#define SSLE_LOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "slog.h" + +/* Log control masks */ +#define SSLE_LOG_ERR 0x00000001 +#define SSLE_LOG_NERR 0x00000002 +#define SSLE_LOG_FLOW 0x00000004 +#define SSLE_LOG_DATA 0x00000008 +#define SSLE_LOG_DEBUG 0x00000010 + +extern ST_UINT ssle_debug_sel; + +/* Function so user can set log masks */ +ST_UINT* ssleGetDebugSel(ST_VOID); +ST_UINT *ssleGetASN1DebugSel(ST_VOID); +/* Function so user can set memory debug flag */ +ST_BOOLEAN *ssleGetMemDebug (ST_VOID); + +/* Internal SSL Toolkit Utility Functions */ +ST_VOID _ssleLogError(ST_ULONG err); + +/* The log macros */ +#define SSLE_LOG_ERR0(a) \ + SLOG_0 (ssle_debug_sel & SSLE_LOG_ERR, "SSLE_LOG_ERR", a) +#define SSLE_LOG_ERR1(a,b) \ + SLOG_1 (ssle_debug_sel & SSLE_LOG_ERR, "SSLE_LOG_ERR", a,b) +#define SSLE_LOG_ERR2(a,b,c) \ + SLOG_2 (ssle_debug_sel & SSLE_LOG_ERR, "SSLE_LOG_ERR", a,b,c) +#define SSLE_LOG_ERR3(a,b,c,d) \ + SLOG_3 (ssle_debug_sel & SSLE_LOG_ERR, "SSLE_LOG_ERR", a,b,c,d) +#define SSLE_LOG_ERR4(a,b,c,d,e) \ + SLOG_4 (ssle_debug_sel & SSLE_LOG_ERR, "SSLE_LOG_ERR", a,b,c,d,e) + +#define SSLE_LOG_NERR0(a) \ + SLOG_0 (ssle_debug_sel & SSLE_LOG_NERR, "SSLE_LOG_NERR", a) +#define SSLE_LOG_NERR1(a,b) \ + SLOG_1 (ssle_debug_sel & SSLE_LOG_NERR, "SSLE_LOG_NERR", a,b) +#define SSLE_LOG_NERR2(a,b,c) \ + SLOG_2 (ssle_debug_sel & SSLE_LOG_NERR, "SSLE_LOG_NERR", a,b,c) +#define SSLE_LOG_NERR3(a,b,c,d) \ + SLOG_3 (ssle_debug_sel & SSLE_LOG_NERR, "SSLE_LOG_NERR", a,b,c,d) +#define SSLE_LOG_NERR4(a,b,c,d,e) \ + SLOG_4 (ssle_debug_sel & SSLE_LOG_NERR, "SSLE_LOG_NERR", a,b,c,d,e) + +#define SSLE_LOG_FLOW0(a) \ + SLOG_0 (ssle_debug_sel & SSLE_LOG_FLOW, "SSLE_LOG_FLOW", a) +#define SSLE_LOG_FLOW1(a,b) \ + SLOG_1 (ssle_debug_sel & SSLE_LOG_FLOW, "SSLE_LOG_FLOW", a,b) +#define SSLE_LOG_FLOW2(a,b,c) \ + SLOG_2 (ssle_debug_sel & SSLE_LOG_FLOW, "SSLE_LOG_FLOW", a,b,c) +#define SSLE_LOG_FLOW3(a,b,c,d) \ + SLOG_3 (ssle_debug_sel & SSLE_LOG_FLOW, "SSLE_LOG_FLOW", a,b,c,d) +#define SSLE_LOG_FLOW4(a,b,c,d,e) \ + SLOG_4 (ssle_debug_sel & SSLE_LOG_FLOW, "SSLE_LOG_FLOW", a,b,c,d,e) + +#define SSLE_LOG_DEBUG0(a) \ + SLOG_0 (ssle_debug_sel & SSLE_LOG_DEBUG, "SSLE_LOG_DEBUG", a) +#define SSLE_LOG_DEBUG1(a,b) \ + SLOG_1 (ssle_debug_sel & SSLE_LOG_DEBUG, "SSLE_LOG_DEBUG", a,b) +#define SSLE_LOG_DEBUG2(a,b,c) \ + SLOG_2 (ssle_debug_sel & SSLE_LOG_DEBUG, "SSLE_LOG_DEBUG", a,b,c) +#define SSLE_LOG_DEBUG3(a,b,c,d) \ + SLOG_3 (ssle_debug_sel & SSLE_LOG_DEBUG, "SSLE_LOG_DEBUG", a,b,c,d) +#define SSLE_LOG_DEBUG4(a,b,c,d,e) \ + SLOG_4 (ssle_debug_sel & SSLE_LOG_DEBUG, "SSLE_LOG_DEBUG", a,b,c,d,e) + +#define SSLE_LOG_DATAH(a,b) \ + SLOGH (ssle_debug_sel & SSLE_LOG_DATA,a,b) + +/* 'C' macros stand for 'Continuation' */ +#define SSLE_LOG_CERR0(a) \ + SLOGC_0 (ssle_debug_sel & SSLE_LOG_ERR, a) +#define SSLE_LOG_CERR1(a,b) \ + SLOGC_1 (ssle_debug_sel & SSLE_LOG_ERR, a,b) +#define SSLE_LOG_CERR2(a,b,c) \ + SLOGC_2 (ssle_debug_sel & SSLE_LOG_ERR, a,b,c) +#define SSLE_LOG_CERR3(a,b,c,d) \ + SLOGC_3 (ssle_debug_sel & SSLE_LOG_ERR, a,b,c,d) +#define SSLE_LOG_CERR4(a,b,c,d,e) \ + SLOGC_4 (ssle_debug_sel & SSLE_LOG_ERR, a,b,c,d,e) + +#define SSLE_LOG_CNERR0(a) \ + SLOGC_0 (ssle_debug_sel & SSLE_LOG_NERR, a) +#define SSLE_LOG_CNERR1(a,b) \ + SLOGC_1 (ssle_debug_sel & SSLE_LOG_NERR, a,b) +#define SSLE_LOG_CNERR2(a,b,c) \ + SLOGC_2 (ssle_debug_sel & SSLE_LOG_NERR, a,b,c) +#define SSLE_LOG_CNERR3(a,b,c,d) \ + SLOGC_3 (ssle_debug_sel & SSLE_LOG_NERR, a,b,c,d) +#define SSLE_LOG_CNERR4(a,b,c,d,e) \ + SLOGC_4 (ssle_debug_sel & SSLE_LOG_NERR, a,b,c,d,e) + +#define SSLE_LOG_CFLOW0(a) \ + SLOGC_0 (ssle_debug_sel & SSLE_LOG_FLOW, a) +#define SSLE_LOG_CFLOW1(a,b) \ + SLOGC_1 (ssle_debug_sel & SSLE_LOG_FLOW, a,b) +#define SSLE_LOG_CFLOW2(a,b,c) \ + SLOGC_2 (ssle_debug_sel & SSLE_LOG_FLOW, a,b,c) +#define SSLE_LOG_CFLOW3(a,b,c,d) \ + SLOGC_3 (ssle_debug_sel & SSLE_LOG_FLOW, a,b,c,d) +#define SSLE_LOG_CFLOW4(a,b,c,d,e) \ + SLOGC_4 (ssle_debug_sel & SSLE_LOG_FLOW, a,b,c,d,e) + +#define SSLE_LOG_CDEBUG0(a) \ + SLOGC_0 (ssle_debug_sel & SSLE_LOG_DEBUG, a) +#define SSLE_LOG_CDEBUG1(a,b) \ + SLOGC_1 (ssle_debug_sel & SSLE_LOG_DEBUG, a,b) +#define SSLE_LOG_CDEBUG2(a,b,c) \ + SLOGC_2 (ssle_debug_sel & SSLE_LOG_DEBUG, a,b,c) +#define SSLE_LOG_CDEBUG3(a,b,c,d) \ + SLOGC_3 (ssle_debug_sel & SSLE_LOG_DEBUG, a,b,c,d) +#define SSLE_LOG_CDEBUG4(a,b,c,d,e) \ + SLOGC_4 (ssle_debug_sel & SSLE_LOG_DEBUG, a,b,c,d,e) + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* SSLE_LOG_INCLUDED */ +/************************************************************************/ diff --git a/mmslib/inc/stdtime.h b/mmslib/inc/stdtime.h new file mode 100644 index 0000000..5cb2504 --- /dev/null +++ b/mmslib/inc/stdtime.h @@ -0,0 +1,1446 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtime.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Header file for Standard Time Management Library Functions */ +/* */ +/* Note: most functions a produce a return-code value STDTIME_RC. */ +/* the return code is zero if successful, otherwise it is a structured */ +/* value in which the low-order 10 bits enumerates an error reason, */ +/* and the upper 20 bits enumerates the high-level and low-level */ +/* functions where the error was detected. */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 04/08/08 JRB 15 Chg () to (ST_VOID) in several prototypes. */ +/* 03/13/08 JRB 14 Chg #error to #warning for STDTIME_UNICODE. */ +/* 02/28/08 JRB 13 Incl "timeb.h" only in "sysincs.h". */ +/* 02/20/08 JRB 12 Chg STDTIME same as FILETIME (simplifies a lot). */ +/* Delete MANY unused functions and definitions. */ +/* Simplify TimeTypeEx, StrucTmEx args. */ +/* 04/03/07 RLH 11 Additional conversion functions to/from FILETIME. */ +/* 03/18/07 RLH 10 Remove tabs from source code inadvertantly added. */ +/* 03/16/07 RLH 09 Normalize struct tm, SYSTEMTIME, and STDTIME_FIELDS */ +/* after rounding is applied; no rounding for formatting */ +/* functions. */ +/* 02/16/07 RLH 08 Clean up minor warnings under Linux */ +/* 01/10/07 RLH 07 Add TruncStdTimeString functions */ +/* 11/29/06 RLH 06 Correction to STDTIME_TIME_T64_ENABLED setting */ +/* 10/18/06 RLH 05 Enhanced capabilities for timezone rules */ +/* 10/27/06 RLH 04 Change STDTIME_RET, STDTIME_IF, STDTIME_IFNOT macros */ +/* 09/13/06 RLH 03 Ensure local time conversions work when TZ not set */ +/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */ +/* 01/18/06 RLH 01 Created */ +/*****************************************************************************/ + +#ifndef _STDTIME_H_7583ECB2_DB3F_48B3_8A97_2D1D2A38C84A_ +#define _STDTIME_H_7583ECB2_DB3F_48B3_8A97_2D1D2A38C84A_ + +#define SECONDS_FROM_1601_TO_1970_HIGH 2 +#define SECONDS_FROM_1601_TO_1970_LOW 0xB6109100 + +#define FILETIME_1970_HIGH 0x019DB1DE +#define FILETIME_1970_LOW 0xD53E8000 + +#undef STDTIME_MSVC6 +#undef STDTIME_MSVC7 +#undef STDTIME_MSVC8 + +#ifdef _MSC_VER + +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE +#endif + + +#if (_MSC_VER >= 1400) +#define STDTIME_MSVC8 +#elif (_MSC_VER >= 1300) +#define STDTIME_MSVC7 +#elif (_MSC_VER >= 1200) +#define STDTIME_MSVC6 +#endif + + +#if 0 + +#if (_MSC_VER >= 1400) +#pragma comment(lib, "stdtimelib.lib") +#elif (_MSC_VER >= 1300) +#pragma comment(lib, "stdtimelib.lib") +#elif (_MSC_VER >= 1200) +#pragma comment(lib, "stdtimelib.lib") +#endif + +#endif /* 0 */ + + +#endif /* _MSC_VER */ + +/* to test for STDTIME library being used */ +#undef STDTIME_DEFINED +#define STDTIME_DEFINED 1 + +/*****************************************************************************/ +/* LIBRARY HEADERS */ +/*****************************************************************************/ + +/* UNICODE or ANSI, but not both */ + +#if defined(STDTIME_UNICODE) && defined(STDTIME_ANSI) +#error Both STDTIME_UNICODE and STDTIME_ANSI defined +#undef STDTIME_UNICODE +#endif + +/* UNICODE or _UNICODE implies STDTIME_UNICODE, but not if ANSI defined */ + +#if (!defined(STDTIME_UNICODE)) && (!defined(STDTIME_ANSI)) +#if defined(UNICODE) || defined(_UNICODE) +#define STDTIME_UNICODE +#endif +#endif + +#if defined(STDTIME_UNICODE) +#pragma message("Warning: STDTIME_UNICODE option no longer supported. Try using ANSI functions mbstowcs and wcstombs.") +#undef STDTIME_UNICODE +#endif + +/* DEBUG: system include should come from "sysincs.h". Fix that later */ +#ifdef _WIN32 +#include +#endif + +#include +#include +#include +#include +#include +#include + +/*****************************************************************************/ +/* with support for gmtime_r and localtime_r if possible */ +/*****************************************************************************/ + +#undef STDTIME_REENTRANT_GMTIME_LOCALTIME + +#undef STDTIME_DEFINED_LINUX__USE_POSIX +#if defined(linux) +#define STDTIME_REENTRANT_GMTIME_LOCALTIME +#ifndef __USE_POSIX +#define __USE_POSIX +#define STDTIME_DEFINED_LINUX__USE_POSIX +#endif +#endif + +#undef STDTIME_DEFINED_SOLARIS_REENTRANT +#if defined(sun) +#define STDTIME_REENTRANT_GMTIME_LOCALTIME +#ifndef _REENTRANT +#define _REENTRANT +#define STDTIME_DEFINED_SOLARIS_REENTRANT +#endif +#endif + +#undef STDTIME_DEFINED_SOLARIS_POSIX_PTHREAD_SEMANTICS +#if defined(sun) +#ifndef _POSIX_PTHREAD_SEMANTICS +#define _POSIX_PTHREAD_SEMANTICS +#define STDTIME_DEFINED_SOLARIS_POSIX_PTHREAD_SEMANTICS +#endif +#endif + +#undef STDTIME_DEFINED_AIX_THREAD_SAFE +#if defined(_AIX) +#define STDTIME_REENTRANT_GMTIME_LOCALTIME +#ifndef _THREAD_SAFE +#define _THREAD_SAFE +#define STDTIME_DEFINED_AIX_THREAD_SAFE +#endif +#endif + +#undef STDTIME_DEFINED_DEC_UNIX_REENTRANT +#if defined(__alpha) && !defined(__VMS) +#define STDTIME_REENTRANT_GMTIME_LOCALTIME +#ifndef _REENTRANT +#define _REENTRANT +#define STDTIME_DEFINED_DEC_UNIX_REENTRANT +#endif +#endif + + +#include + + +#if defined(sun) +struct tm * gmtime_r (const time_t * pTimeT, struct tm * pStructTm); +struct tm * localtime_r (const time_t * pTimeT, struct tm * pStructTm); +#endif + + +/* clean up macro namespace */ + +#ifdef STDTIME_DEFINED_LINUX__USE_POSIX +#undef STDTIME_DEFINED_LINUX__USE_POSIX +#undef __USE_POSIX +#endif + +#ifdef STDTIME_DEFINED_SOLARIS_REENTRANT +#undef STDTIME_DEFINED_SOLARIS_REENTRANT +#undef _REENTRANT +#endif + +#ifdef STDTIME_DEFINED_SOLARIS_POSIX_PTHREAD_SEMANTICS +#undef STDTIME_DEFINED_SOLARIS_POSIX_PTHREAD_SEMANTICS +#undef _POSIX_PTHREAD_SEMANTICS +#endif + +#ifdef STDTIME_DEFINED_DEC_UNIX_REENTRANT +#undef STDTIME_DEFINED_DEC_UNIX_REENTRANT +#undef _REENTRANT +#endif + +#ifdef STDTIME_DEFINED_AIX_THREAD_SAFE +#undef STDTIME_DEFINED_AIX_THREAD_SAFE +#undef _THREAD_SAFE +#endif + + +/*****************************************************************************/ +/* support _T notation on non-Windows platforms */ +/*****************************************************************************/ + +#if (!defined(_T)) && (!defined(__T)) +#ifdef STDTIME_UNICODE +#define __T(x) L##x +#define _T(x) __T(x) +#else +#define __T(x) x +#define _T(x) x +#endif +#endif /* not defined _T and __T */ + +#include "stdtime_config.h" + + +/*****************************************************************************/ +/* determine if "stdtime_timezone_csv.h" file is "merged" or not. */ +/* */ +/* the csv file gets "merged" if there is no comma separating one line */ +/* from the next. a "merged" file is the normal format for a csv data */ +/* file, but when used as part of a C program, the lack of a comma causes */ +/* the last string value on one line to get concatenated by the compiler */ +/* to the first string value on the next line. we need to know if the */ +/* file is "merged" or "unmerged" to know how to 'undo' the merging. */ +/* */ +/* an unmerged file is easier and faster to process, while a merged file */ +/* maintains source compatibility with the original Boost.org timezone */ +/* database file from which it originated. */ +/* */ +/*****************************************************************************/ + +#if defined(STDTIME_MERGED_CSV) && defined(STDTIME_UNMERGED_CSV) +#error Both STDTIME_MERGED_CSV and STDTIME_UNMERGED_CSV defined +#undef STDTIME_UNMERGED_CSV +#endif + +#if !defined(STDTIME_MERGED_CSV) && !defined(STDTIME_UNMERGED_CSV) +#define STDTIME_MERGED_CSV /* default */ +#endif + + +/*****************************************************************************/ +/* determine how GMT is converted to local time, and vice-versa. */ +/* */ +/* using a system API for a definition of what "local" is will be faster, */ +/* but if the SYSTEMTIMEZONE or TZ environment variable does not agree */ +/* with the OS's understanding of what "local" is, there will be a */ +/* conflict. if the time library is likely to be used for a non-local */ +/* time zone, defining STDTIME_LOCAL_USES_TZDB is necessary. */ +/* otherwise, define STDTIME_LOCAL_USES_SYSAPI for speed. */ +/* */ +/*****************************************************************************/ + +#if defined(STDTIME_LOCAL_USES_TZDB) && defined(STDTIME_LOCAL_USES_SYSAPI) +#error Both STDTIME_LOCAL_USES_TZDB and STDTIME_LOCAL_USES_SYSAPI defined +#undef STDTIME_LOCAL_USES_SYSAPI +#endif + +#if !defined(STDTIME_LOCAL_USES_TZDB) && !defined(STDTIME_LOCAL_USES_SYSAPI) +#define STDTIME_LOCAL_USES_SYSAPI /* default */ +#endif + + +/*****************************************************************************/ +/* C++ ONLY ENABLED OR DISABLED */ +/* */ +/* use StdTimeConfig.h to set STDTIME_CPP_ONLY_ENABLED/DISABLED */ +/*****************************************************************************/ + + +#ifdef __cplusplus + +#if defined(STDTIME_CPP_ONLY_ENABLED) && defined(STDTIME_CPP_ONLY_DISABLED) +#error Both STDTIME_CPP_ONLY_ENABLED and STDTIME_CPP_ONLY_DISABLED defined +#undef STDTIME_CPP_ONLY_ENABLED +#endif + +#if !defined(STDTIME_CPP_ONLY_ENABLED) && !defined(STDTIME_CPP_ONLY_DISABLED) +#define STDTIME_CPP_ONLY_ENABLED /* default */ +#endif + +#else /* not __cplusplus */ + +#undef STDTIME_CPP_ONLY_ENABLED +#undef STDTIME_CPP_ONLY_DISABLED +#define STDTIME_CPP_ONLY_DISABLED + +#endif /* __cplusplus */ + + +/* StdTimeW32.h needs the bool definition */ + + +#define STDTIME_BOOL int +#define STDTIME_TRUE 1 +#define STDTIME_FALSE 0 + +typedef int32_t STDTIME_RC; + +/* STDTIME return codes are divided as follows: */ +/* 2 bits unused */ +/* 10 bits = highest level function where error detected */ +/* 10 bits = lowest level function where error detected */ +/* 10 bits = error reason code (nature of problem) */ + + +/* create error code enumeration from enum_stdtime_func.h */ +/* this is done by temporary macro and include file */ + +#define STDTIME_ENUM_FUNC(x) STDTIME_FUNC__##x, + +enum + { + STDTIME_FUNC__0000, /* dummy 0 entry */ +#include "stdtime_enum_func.h" + STDTIME_FUNC__SIZE + }; + +/* temporary macro has served its purpose, so undefine it */ +#undef STDTIME_ENUM_FUNC + + +/* now redefine macro for main purpose, to declare 'rc' and 'func' */ +/* within each function that returns a STDTIME_RC return code. */ + + +#define STDTIME_ENUM_FUNC(x) \ + STDTIME_RC rc; \ + STDTIME_RC func; \ + rc = -1; \ + func = (STDTIME_RC) STDTIME_FUNC__##x; + + +/* create error code enumeration from enum_stdtime_err.h */ +/* this is done by temporary macro and include file */ + +#define STDTIME_ENUM_ERR(x) STDTIME_ERR__##x, + +enum + { + STDTIME_ERR__0000, /* dummy 0 entry */ +#include "stdtime_enum_err.h" + STDTIME_ERR__SIZE + }; + +/* temporary macro has served its purpose, so undefine it */ +#undef STDTIME_ENUM_ERR + + +#define STDTIME_10_BITS 0x3FF +#define STDTIME_20_BITS 0xFFFFF + +#define STDTIME_OK 0 +#define STDTIME_RET(x) return StdTimeRet (func, x) + +#define STDTIME_RET_RC STDTIME_RET(rc) +#define STDTIME_RET_OK return STDTIME_OK + +#define STDTIME_EC(x) ((func << 10) | (STDTIME_ERR__##x)) + +#define STDTIME_RET_EC(x) STDTIME_RET(STDTIME_EC(x)) + +#include "stdtime_quadlib.h" +#include "stdtime_w32.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*****************************************************************************/ +/* TYPES AND STRUCTURES */ +/*****************************************************************************/ + + +#if defined(_MSC_VER) && defined(_WCHAR_T_DEFINED) +typedef wchar_t STDTIME_WCHAR; +#elif defined(sun) && defined(_WCHAR_T) +typedef wchar_t STDTIME_WCHAR; +#else +typedef unsigned short STDTIME_WCHAR; +#endif + +#ifndef STDTIME_TIME_T64_WIN +#if defined(_TIME_T_DEFINED) && defined(_WIN64) +#define STDTIME_TIME_T64_WIN +#endif +#endif + +#ifndef STDTIME_TIME_T64_WIN +#ifdef _TIME64_T_DEFINED +#define STDTIME_TIME_T64_WIN +#endif +#endif + + +#ifndef STDTIME_TIME_T64_ENABLED +#ifdef STDTIME_TIME_T64_WIN +#define STDTIME_TIME_T64_ENABLED +#endif +#endif + + +#ifdef STDTIME_TIME_T64_ENABLED +#ifdef STDTIME_TIME_T64_WIN + +#ifdef _TIME64_T_DEFINED +typedef __time64_t STDTIME_WIN_TIME_T; +#else +typedef time_t STDTIME_WIN_TIME_T; +#endif /* _TIME64_T_DEFINED */ + +#else /* not STDTIME_TIME_T64_WIN */ +typedef QUADLIB_I64N STDTIME_WIN_TIME_T; +#endif /* STDTIME_TIME_T64_WIN */ + + + + +#else /* not STDTIME_TIME_T64_ENABLED */ +typedef time_t STDTIME_WIN_TIME_T; +#endif /* STDTIME_TIME_T64_ENABLED */ + + +#define STDTIME_SCALE_NSEC 100 /* only 1 digit of nsec precision */ +#define STDTIME_PREC_NSEC 10 /* only 1 digit of nsec precision */ + +#define STDTIME_WIN_EPOCH_YEAR 1601 +#define STDTIME_UNIX_EPOCH_YEAR 1970 +#define STDTIME_DST_CUTOFF_YEAR 1945 + +#define STDTIME_YEAR_MIN STDTIME_WIN_EPOCH_YEAR /* base/epoch year */ +#define STDTIME_YEAR_MAX 9999 /* to avoid overflow in STDTIME_STRING */ + +#define STDTIME_INVALID {0,0} +#define STDTIME_FIELDS_INVALID {0,0,0,0,0,0,0,0,0} +#define STDTIME_STRING_INVALID {0} + +#define STDTIME_SPAN_INVALID QUADLIB_I64_MAX + +#define STDTIME_DELTA_DAY_MAX (8400*366) + + +#define STDTIME_DELTA_INVALID { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, \ + 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF } /**/ + + +/* an invalid span exceeds +/- 2,656,281,600,000,000,000 */ +/* which is 8400*366 days in terms of 100-nanosecond intervals */ +/* the pos value in hex is 24DD 020A A768 0000 */ +/* the neg value in hex is DB22 FDF5 5898 0000 */ + +#define STDTIME_SPAN_MAX_HI 0x24DD020A +#define STDTIME_SPAN_MAX_LO 0xA7680000 + +#define STDTIME_SPAN_MIN_HI 0xDB22FDF5 +#define STDTIME_SPAN_MIN_LO 0x58980000 + +#define STDTIME_ERR (-2) +#define STDTIME_LT (-1) +#define STDTIME_EQ 0 +#define STDTIME_GT 1 + +/* Main StdTime structure identical to Windows FILETIME. */ +typedef STDTIME_WIN_FILETIME STDTIME; + +typedef struct + { + int32_t year; + int32_t mon; + int32_t day; + int32_t hour; + int32_t min; + int32_t sec; + int32_t msec; /* milliseconds */ + int32_t usec; /* microseconds */ + int32_t nsec; /* nanoseconds */ + } +STDTIME_FIELDS; + + +typedef struct + { + int32_t day; + int32_t hour; + int32_t min; + int32_t sec; + int32_t msec; + int32_t usec; + int32_t nsec; + } +STDTIME_DELTA; + + +typedef struct + { + QUADLIB_I64 value; + } +STDTIME_SPAN; + + +/* 1 2 3 */ +/* 0123456789012345678901234567890123456 */ +/* STRING format: yyyy-mm-ddThh:mi:ss.fffffff# */ +/* TZO format: +hh:mm:ss# */ +/* 0123456789 */ + +#define STDTIME_STRING_DATE_LEN 10 +#define STDTIME_STRING_TIME_LEN 8 +#define STDTIME_STRING_FRAC_LEN 7 + +#define STDTIME_STRING_DATE_POS 0 +#define STDTIME_STRING_TIME_POS 11 +#define STDTIME_STRING_FRAC_POS 20 + +#define STDTIME_STRING_DLM_D1 4 +#define STDTIME_STRING_DLM_D2 7 +#define STDTIME_STRING_DLM_S1 10 +#define STDTIME_STRING_DLM_T1 13 +#define STDTIME_STRING_DLM_T2 16 +#define STDTIME_STRING_DLM_F1 19 + +#define STDTIME_STRING_LEN 27 +#define STDTIME_TZO_LEN 9 +#define STDTIME_STRING_MAXLEN (STDTIME_STRING_LEN+STDTIME_TZO_LEN) + + +typedef struct + { + char str [STDTIME_TZO_LEN + 1]; + } +STDTIME_TZOA; + +/* embTzo represents an 'embedded' timezone offset, a suffix to the time */ +/* string 'str' in STDTIME_STRINGA and STDTIME_STRINGW. */ +/* embTzo may be a null string, the letter Z or an offset like -05:00 */ + +/* extTzo represents an 'external' timezone offset, created as an output */ +/* value by the STDTIME library. the library creates, but does not */ +/* directly use, the extTzo field. */ + +typedef struct + { + char str [STDTIME_STRING_LEN]; + char embTzo [STDTIME_TZO_LEN + 1]; + STDTIME_TZOA extTzo; /* external TimeZone Offset */ + } +STDTIME_STRINGA; + +#ifdef STDTIME_UNICODE +#else +#define STDTIME_STRING STDTIME_STRINGA +#define STDTIME_TZO STDTIME_TZOA +#endif /* STDTIME_UNICODE */ + +typedef struct + { + STDTIME_WIN_TIME_T t; + } +STDTIME_TIMETYPE; + +#define STDTIME_API_MKTIME mktime + +/* Round/Trunc field selectors */ + +#define STDTIME_FIELD_DAY 0 +#define STDTIME_FIELD_HOUR 1 +#define STDTIME_FIELD_MIN 2 +#define STDTIME_FIELD_SEC 3 +#define STDTIME_FIELD_MSEC 4 +#define STDTIME_FIELD_USEC 5 +#define STDTIME_FIELD_NSEC 6 + + +#define STDTIME_ERRCODE_LEN 27 + +/* an error code has the form 0xNNNNNNNN = HHHH.LLLL.RRRR# */ +/* 0123456789012345678901234567 */ +/* this holds a raw hex RC value, and the RC as subfields */ + +#define STDTIME_ERRMSG_LEN 80 + +typedef struct + { + char errcode [STDTIME_ERRCODE_LEN+1]; + char hilevel [STDTIME_ERRMSG_LEN+1]; + char lolevel [STDTIME_ERRMSG_LEN+1]; + char reason [STDTIME_ERRMSG_LEN+1]; + } +STDTIME_ERRMSGA; + +#define STDTIME_IF(x) ((rc=(x)) == STDTIME_OK) +#define STDTIME_IFNOT(x) ((rc=(x)) != STDTIME_OK) + + +/*** helper function to assemble a STDTIME return code ***********************/ + +STDTIME_RC StdTimeRet ( + const STDTIME_RC /*I*/ func, + const STDTIME_RC /*I*/ ec); + + +/*** StdTime/StdTimeFields conversions ***************************************/ + + +STDTIME_RC StdTimeToStdTimeFields ( + const STDTIME * /*I*/ pStdTime, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + +STDTIME_RC StdTimeFieldsToStdTime ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME * /*O*/ pStdTime); + + +/*** StdTime/external conversions ********************************************/ + + +STDTIME_RC StdTimeToStdTimeStringA ( + const STDTIME * /*I*/ pStdTime, + STDTIME_STRINGA * /*O*/ pStdTimeString); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeToStdTimeString StdTimeToStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** external/StdTime conversions ********************************************/ + + +STDTIME_RC StdTimeStringAToStdTime ( + const STDTIME_STRINGA * /*I*/ pStdTimeString, + STDTIME * /*O*/ pStdTime); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeStringToStdTime StdTimeStringAToStdTime +#endif /* STDTIME_UNICODE */ + + +/*** StdTimeFields/external conversions **************************************/ + + +STDTIME_RC StdTimeFieldsToStdTimeStringA ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_STRINGA * /*O*/ pStdTimeString); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeFieldsToStdTimeString StdTimeFieldsToStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** external/StdTimeFields conversions **************************************/ + + +STDTIME_RC StdTimeStringAToStdTimeFields ( + const STDTIME_STRINGA * /*I*/ pStdTimeString, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeStringToStdTimeFields StdTimeStringAToStdTimeFields +#endif /* STDTIME_UNICODE */ + +/*** StdTime to/from Local ***************************************************/ + + +STDTIME_RC StdTimeToLocalStdTime ( + const STDTIME * /*I*/ pStdTime, + STDTIME * /*O*/ pStdTimeLocal); + +STDTIME_RC LocalStdTimeToStdTime ( + const STDTIME * /*I*/ pStdTimeLocal, + STDTIME * /*O*/ pStdTime); + + +/*** StdTimeFields to/from Local *********************************************/ + + +STDTIME_RC StdTimeFieldsToLocalStdTimeFields ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_FIELDS * /*O*/ pStdTimeFieldsLocal); + +STDTIME_RC LocalStdTimeFieldsToStdTimeFields ( + const STDTIME_FIELDS * /*I*/ pStdTimeFieldsLocal, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + + +/*** StdTimeString to/from Local *********************************************/ + + +STDTIME_RC StdTimeStringAToLocalStdTimeStringA ( + const STDTIME_STRINGA * /*I*/ pStdStdTimeString, + STDTIME_STRINGA * /*O*/ pLocStdTimeString); + +STDTIME_RC LocalStdTimeStringAToStdTimeStringA ( + const STDTIME_STRINGA * /*I*/ pLocStdTimeString, + STDTIME_STRINGA * /*O*/ pStdStdTimeString); + +#define StdTimeStringToLocalStdTimeStringA StdTimeStringAToLocalStdTimeStringA +#define LocalStdTimeStringToStdTimeStringA LocalStdTimeStringAToStdTimeStringA + + +#ifdef STDTIME_UNICODE +#else +#define StdTimeStringToLocalStdTimeString StdTimeStringAToLocalStdTimeStringA +#define LocalStdTimeStringToStdTimeString LocalStdTimeStringAToStdTimeStringA +#endif /* STDTIME_UNICODE */ + +/*** Get (current UTC/GMT time) functions ************************************/ + + +STDTIME_RC GetStdTime ( + STDTIME * /*O*/ pStdTime); + +STDTIME_RC GetStdTimeFields ( + STDTIME_FIELDS * /*O*/ pStdTimeFields); + +STDTIME_RC GetStdTimeStringA ( + STDTIME_STRINGA * /*O*/ pStdTimeString); + +#ifdef STDTIME_UNICODE +#else +#define GetStdTimeString GetStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** GetLocal (current time) functions ***************************************/ + + +STDTIME_RC GetLocalStdTime ( + STDTIME * /*O*/ pStdTime); + +STDTIME_RC GetLocalStdTimeFields ( + STDTIME_FIELDS * /*O*/ pStdTimeFields); + +STDTIME_RC GetLocalStdTimeStringA ( + STDTIME_STRINGA * /*O*/ pStdTimeString); + +#ifdef STDTIME_UNICODE +#else +#define GetLocalStdTimeString GetLocalStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** validation functions ****************************************************/ + + +STDTIME_RC ValidStdTime ( + const STDTIME * /*I*/ pStdTime); + +STDTIME_RC ValidStdTimeFields ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields); + +STDTIME_RC ValidStdTimeStringA ( + const STDTIME_STRINGA * /*I*/ pStdTimeString); + +STDTIME_RC ValidStdTimeDelta ( + const STDTIME_DELTA * /*I*/ pDelta); + +STDTIME_RC ValidStdTimeSpan ( + const STDTIME_SPAN * /*I*/ pSpan); + + +#ifdef STDTIME_UNICODE +#else +#define ValidStdTimeString ValidStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** Format functions ********************************************************/ + + +STDTIME_RC FormatStdTimeA ( + char * /*O*/ pTarget, + size_t /*I*/ nMaxsize, + const char * /*I*/ pFormat, + const STDTIME * /*I*/ pStdTime); + +STDTIME_RC FormatStdTimeFieldsA ( + char * /*O*/ pTarget, + size_t /*I*/ nMaxsize, + const char * /*I*/ pFormat, + const STDTIME_FIELDS * /*I*/ pStdTimeFields); + +STDTIME_RC FormatStdTimeStringA ( + char * /*O*/ pTarget, + size_t /*I*/ nMaxsize, + const char * /*I*/ pFormat, + const STDTIME_STRINGA * /*I*/ pStdTimeString); + +STDTIME_RC TrimStdTimeStringA ( + STDTIME_STRINGA * /*IO*/ pStdTimeString, + int32_t /*I*/ nSize); + +STDTIME_RC TruncStdTimeStringA ( + STDTIME_STRINGA * /*IO*/ pStdTimeString, + int32_t /*I*/ nSize); + +#ifdef STDTIME_UNICODE +#else +#define FormatStdTime FormatStdTimeA +#define FormatStdTimeFields FormatStdTimeFieldsA +#define FormatStdTimeString FormatStdTimeStringA + +#define TrimStdTimeString TrimStdTimeStringA +#define TruncStdTimeString TruncStdTimeStringA + +#endif /* STDTIME_UNICODE */ + + +/*** delimiter functions *****************************************************/ + + +STDTIME_RC SetStdTimeStringDelimitersA ( + const char * /*I*/ pDelimiters); + +STDTIME_RC RepairStdTimeStringA ( + STDTIME_STRINGA * /*O*/ pStdTimeString); + +STDTIME_RC DelimitStdTimeStringA ( + STDTIME_STRINGA * /*O*/ pStdTimeString, + const char * /*I*/ pDelim); + +#ifdef STDTIME_UNICODE +#else +#define SetStdTimeStringDelimiters SetStdTimeStringDelimitersA +#define RepairStdTimeString RepairStdTimeStringA +#define DelimitStdTimeString DelimitStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** AddFraction adjustment function *****************************************/ + + +STDTIME_RC StdTimeFields_AddFraction ( + STDTIME_FIELDS * /*IO*/ pStdTimeFields, + int32_t /*I*/ nMsec, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec); + + +/*** AddSpan functions *******************************************************/ + + +STDTIME_RC StdTime_AddSpan ( + STDTIME * /*IO*/ pStdTime, + const STDTIME_SPAN * /*I*/ pSpan); + +STDTIME_RC StdTimeFields_AddSpan ( + STDTIME_FIELDS * /*IO*/ pStdTimeFields, + const STDTIME_SPAN * /*I*/ pSpan); + +STDTIME_RC StdTimeStringA_AddSpan ( + STDTIME_STRINGA * /*IO*/ pStdTimeString, + const STDTIME_SPAN * /*I*/ pSpan); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeString_AddSpan StdTimeStringA_AddSpan +#endif /* STDTIME_UNICODE */ + + +/*** SubSpan functions *******************************************************/ + + +STDTIME_RC StdTime_SubSpan ( + STDTIME * /*IO*/ pStdTime, + const STDTIME_SPAN * /*I*/ pSpan); + +STDTIME_RC StdTimeFields_SubSpan ( + STDTIME_FIELDS * /*IO*/ pStdTimeFields, + const STDTIME_SPAN * /*I*/ pSpan); + +STDTIME_RC StdTimeStringA_SubSpan ( + STDTIME_STRINGA * /*IO*/ pStdTimeString, + const STDTIME_SPAN * /*I*/ pSpan); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeString_SubSpan StdTimeStringA_SubSpan +#endif /* STDTIME_UNICODE */ + + +/*** GetSpan functions *******************************************************/ + + +STDTIME_RC StdTime_GetSpan ( + const STDTIME * /*I*/ pStdTimeOne, + const STDTIME * /*I*/ pStdTimeTwo, + STDTIME_SPAN * /*O*/ pSpan); + +STDTIME_RC StdTimeFields_GetSpan ( + const STDTIME_FIELDS * /*I*/ pStdTimeFieldsOne, + const STDTIME_FIELDS * /*I*/ pStdTimeFieldsTwo, + STDTIME_SPAN * /*O*/ pSpan); + +STDTIME_RC StdTimeStringA_GetSpan ( + const STDTIME_STRINGA * /*I*/ pStdTimeStringOne, + const STDTIME_STRINGA * /*I*/ pStdTimeStringTwo, + STDTIME_SPAN * /*O*/ pSpan); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeString_GetSpan StdTimeStringA_GetSpan +#endif /* STDTIME_UNICODE */ + + +/*** AddDelta functions ******************************************************/ + +STDTIME_RC StdTime_AddDelta ( + STDTIME * /*IO*/ pStdTime, + const STDTIME_DELTA * /*I*/ pDelta); + +STDTIME_RC StdTimeFields_AddDelta ( + STDTIME_FIELDS * /*IO*/ pStdTimeFields, + const STDTIME_DELTA * /*I*/ pDelta); + +STDTIME_RC StdTimeStringA_AddDelta ( + STDTIME_STRINGA * /*IO*/ pStdTimeString, + const STDTIME_DELTA * /*I*/ pDelta); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeString_AddDelta StdTimeStringA_AddDelta +#endif /* STDTIME_UNICODE */ + + +/*** SubDelta functions ******************************************************/ + + +STDTIME_RC StdTime_SubDelta ( + STDTIME * /*IO*/ pStdTime, + const STDTIME_DELTA * /*I*/ pDelta); + +STDTIME_RC StdTimeFields_SubDelta ( + STDTIME_FIELDS * /*IO*/ pStdTimeFields, + const STDTIME_DELTA * /*I*/ pDelta); + +STDTIME_RC StdTimeStringA_SubDelta ( + STDTIME_STRINGA * /*IO*/ pStdTimeString, + const STDTIME_DELTA * /*I*/ pDelta); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeString_SubDelta StdTimeStringA_SubDelta +#endif /* STDTIME_UNICODE */ + + +/*** GetDelta functions ******************************************************/ + + +STDTIME_RC StdTime_GetDelta ( + const STDTIME * /*I*/ pStdTimeOne, + const STDTIME * /*I*/ pStdTimeTwo, + STDTIME_DELTA * /*O*/ pDelta); + +STDTIME_RC StdTimeFields_GetDelta ( + const STDTIME_FIELDS * /*I*/ pStdTimeFieldsOne, + const STDTIME_FIELDS * /*I*/ pStdTimeFieldsTwo, + STDTIME_DELTA * /*O*/ pDelta); + +STDTIME_RC StdTimeStringA_GetDelta ( + const STDTIME_STRINGA * /*I*/ pStdTimeStringOne, + const STDTIME_STRINGA * /*I*/ pStdTimeStringTwo, + STDTIME_DELTA * /*O*/ pDelta); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeString_GetDelta StdTimeStringA_GetDelta +#endif /* STDTIME_UNICODE */ + + +/*** Delta/Span conversion functions *****************************************/ + + +STDTIME_RC StdTimeDeltaToStdTimeSpan ( + const STDTIME_DELTA * /*I*/ pDelta, + STDTIME_SPAN * /*O*/ pSpan); + +STDTIME_RC StdTimeSpanToStdTimeDelta ( + const STDTIME_SPAN * /*I*/ pSpan, + STDTIME_DELTA * /*O*/ pDelta); + + +/*** Delta/Span sign-related functions ***************************************/ + + +int32_t SgnStdTimeDelta ( + const STDTIME_DELTA * /*I*/ pDelta); + +STDTIME_RC AbsStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta); + +STDTIME_RC NegStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta); + + +int32_t SgnStdTimeSpan ( + const STDTIME_SPAN * /*I*/ pSpan); + +STDTIME_RC AbsStdTimeSpan ( + STDTIME_SPAN * /*IO*/ pSpan); + +STDTIME_RC NegStdTimeSpan ( + STDTIME_SPAN * /*IO*/ pSpan); + + +/*** Compare functions *******************************************************/ + + +int32_t CompareStdTime ( + const STDTIME * /*I*/ pStdTimeOne, + const STDTIME * /*I*/ pStdTimeTwo); + +int32_t CompareStdTimeFields ( + const STDTIME_FIELDS * /*I*/ pStdTimeFieldsOne, + const STDTIME_FIELDS * /*I*/ pStdTimeFieldsTwo); + +int32_t CompareStdTimeStringA ( + const STDTIME_STRINGA * /*I*/ pStdTimeStringOne, + const STDTIME_STRINGA * /*I*/ pStdTimeStringTwo); + +#ifdef STDTIME_UNICODE +#else +#define CompareStdTimeString CompareStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** FileTime functions ******************************************************/ + + + +STDTIME_RC StdTimeToFileTime ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_FILETIME * /*O*/ pFileTime); + +STDTIME_RC FileTimeToStdTime ( + const STDTIME_WIN_FILETIME * /*I*/ pFileTime, + STDTIME * /*O*/ pStdTime); + + + +STDTIME_RC StdTimeFieldsToFileTime ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_FILETIME * /*O*/ pFileTime); + +STDTIME_RC FileTimeToStdTimeFields ( + const STDTIME_WIN_FILETIME * /*I*/ pFileTime, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + + + +STDTIME_RC StdTimeStringAToFileTime ( + const STDTIME_STRINGA * /*I*/ pStdTimeString, + STDTIME_WIN_FILETIME * /*O*/ pFileTime); + +STDTIME_RC FileTimeToStdTimeStringA ( + const STDTIME_WIN_FILETIME * /*I*/ pFileTime, + STDTIME_STRINGA * /*O*/ pStdTimeString); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeStringToFileTime StdTimeStringAToFileTime +#define FileTimeToStdTimeString FileTimeToStdTimeStringA +#endif /* STDTIME_UNICODE */ + + +/*** SystemTimeEx functions **************************************************/ + + +STDTIME_RC StdTimeToSystemTimeEx ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime, + int32_t * /*O*/ pUsec, /* optional */ + int32_t * /*O*/ pNsec); /* optional */ + + +STDTIME_RC SystemTimeExToStdTime ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec, + STDTIME * /*O*/ pStdTime); + + +STDTIME_RC StdTimeFieldsToSystemTimeEx ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime, + int32_t * /*O*/ pUsec, /* optional */ + int32_t * /*O*/ pNsec); /* optional */ + + +STDTIME_RC SystemTimeExToStdTimeFields ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + + +/*** SystemTime functions ****************************************************/ + + +STDTIME_RC StdTimeToSystemTime ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime); + + +STDTIME_RC SystemTimeToStdTime ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + STDTIME * /*O*/ pStdTime); + + +STDTIME_RC StdTimeFieldsToSystemTime ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime); + + +STDTIME_RC SystemTimeToStdTimeFields ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + +#ifdef _WIN32 /* DbTimeStamp functions only for _WIN32 */ +/*** DbTimeStamp functions ***************************************************/ + +/* NOTE: can't include "oledb.h" for DBTIMESTAMP so just define our own struct here.*/ +typedef struct + { + STDTIME_WIN_SHORT year; + STDTIME_WIN_USHORT month; + STDTIME_WIN_USHORT day; + STDTIME_WIN_USHORT hour; + STDTIME_WIN_USHORT minute; + STDTIME_WIN_USHORT second; + STDTIME_WIN_ULONG fraction; + } STDTIME_WIN_DBTIMESTAMP; + +STDTIME_WIN_DBTIMESTAMP StdTimeApiZeroDbTimeStamp (ST_VOID); + +STDTIME_RC StdTimeToDbTimeStamp ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_DBTIMESTAMP * /*O*/ pDbTimeStamp); + +STDTIME_RC DbTimeStampToStdTime ( + const STDTIME_WIN_DBTIMESTAMP * /*I*/ pDbTimeStamp, + STDTIME * /*O*/ pStdTime); + +STDTIME_RC StdTimeFieldsToDbTimeStamp ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_DBTIMESTAMP * /*O*/ pDbTimeStamp); + +STDTIME_RC DbTimeStampToStdTimeFields ( + const STDTIME_WIN_DBTIMESTAMP * /*I*/ pDbTimeStamp, + STDTIME_FIELDS * /*O*/ pStdTimeFields); +#endif /* DbTimeStamp functions only for _WIN32 */ + + +/*** StructTmEx functions ****************************************************/ + + +STDTIME_RC StdTimeToStructTmEx ( + const STDTIME * /*I*/ pStdTime, + struct tm * /*O*/ pStructTm, + int32_t * /*O*/ pNsec); /* optional */ + +STDTIME_RC StructTmExToStdTime ( + const struct tm * /*I*/ pStructTm, + int32_t /*I*/ nNsec, + STDTIME * /*O*/ pStdTime); + +/*** TimeTypeEx functions ****************************************************/ + + +STDTIME_RC StdTimeToTimeTypeEx ( + const STDTIME * /*I*/ pStdTime, + time_t * /*O*/ pTimeT, + int32_t * /*O*/ pNsec); /* optional */ + +STDTIME_RC TimeTypeExToStdTime ( + time_t /*I*/ timet, + int32_t /*I*/ nsec, + STDTIME * /*O*/ pStdTime); + +/*** Constructor-like functions **********************************************/ + + +STDTIME_FIELDS StdTimeFields ( + int32_t /*I*/ year, + int32_t /*I*/ mon, + int32_t /*I*/ day, + int32_t /*I*/ hour, + int32_t /*I*/ min, + int32_t /*I*/ sec, + int32_t /*I*/ msec, + int32_t /*I*/ usec, + int32_t /*I*/ nsec); + + +STDTIME_STRINGA StdTimeStringA ( + const char * /*I*/ str); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeString StdTimeStringA +#endif /* STDTIME_UNICODE */ + + +STDTIME_DELTA StdTimeDelta ( + int32_t /*I*/ day, + int32_t /*I*/ hour, + int32_t /*I*/ min, + int32_t /*I*/ sec, + int32_t /*I*/ msec, + int32_t /*I*/ usec, + int32_t /*I*/ nsec); + + +STDTIME_SPAN StdTimeSpan ( + QUADLIB_I64 /*I*/ value); + + +/*** Initializer functions ***************************************************/ + + +STDTIME ZeroStdTime (ST_VOID); +STDTIME_FIELDS ZeroStdTimeFields (ST_VOID); +STDTIME_DELTA ZeroStdTimeDelta (ST_VOID); +STDTIME_SPAN ZeroStdTimeSpan (ST_VOID); + +STDTIME_STRINGA ZeroStdTimeStringA (ST_VOID); + +STDTIME_TZOA ZeroStdTimeTzoA (ST_VOID); + +STDTIME_ERRMSGA ZeroStdTimeErrMsgA (ST_VOID); + +#ifdef STDTIME_UNICODE +#else +#define ZeroStdTimeString ZeroStdTimeStringA +#define ZeroStdTimeTzo ZeroStdTimeTzoA +#define ZeroStdTimeErrMsg ZeroStdTimeErrMsgA +#endif /* STDTIME_UNICODE */ + +/* initializers for outside types use 'StdTimeApi' prefix */ + +STDTIME_TIMETYPE StdTimeApiZeroTimeType (ST_VOID); +STDTIME_WIN_FILETIME StdTimeApiZeroFileTime (ST_VOID); +STDTIME_WIN_SYSTEMTIME StdTimeApiZeroSystemTime (ST_VOID); +struct tm StdTimeApiZeroStructTm (ST_VOID); + + +/*****************************************************************************/ +/* NORMALIZE, ROUND, TRUNC */ +/*****************************************************************************/ + + +STDTIME_RC NormalizeStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta); + + +STDTIME_RC TruncStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta, + int32_t /*I*/ field); + + +STDTIME_RC RoundStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta, + int32_t /*I*/ field); + + +/*** convenience calendar functions ******************************************/ + + +STDTIME_RC StdTimeGetDayofWeekAndYear ( + int32_t /*I*/ nYear, + int32_t /*I*/ nMon, + int32_t /*I*/ nDayofMon, + int32_t * /*O*/ pDayofWeek, + int32_t * /*O*/ pDayofYear); + + +int32_t StdTimeYearIsLeap ( + int32_t /*I*/ year); + + +int32_t StdTimeDaysInYearMon ( + int32_t /*I*/ year, + int32_t /*I*/ mon); + + +/*** DateEx functions ********************************************************/ + + +STDTIME_RC StdTimeToDateEx ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_DATE * /*O*/ pDate, + int32_t * /*O*/ pMsec, /* optional */ + int32_t * /*O*/ pUsec, /* optional */ + int32_t * /*O*/ pNsec); /* optional */ + + +STDTIME_RC DateExToStdTime ( + const STDTIME_WIN_DATE * /*I*/ pDate, + int32_t /*I*/ nMsec, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec, + STDTIME * /*O*/ pStdTime); + + +STDTIME_RC StdTimeFieldsToDateEx ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_DATE * /*O*/ pDate, + int32_t * /*O*/ pMsec, /* optional */ + int32_t * /*O*/ pUsec, /* optional */ + int32_t * /*O*/ pNsec); /* optional */ + + +STDTIME_RC DateExToStdTimeFields ( + const STDTIME_WIN_DATE * /*I*/ pDate, + int32_t /*I*/ nMsec, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + + +/*** Date functions ***************************************************/ + + +STDTIME_RC StdTimeToDate ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_DATE * /*O*/ pDate); + + +STDTIME_RC DateToStdTime ( + const STDTIME_WIN_DATE * /*I*/ pDate, + STDTIME * /*O*/ pStdTime); + + +STDTIME_RC StdTimeFieldsToDate ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_DATE * /*O*/ pDate); + + +STDTIME_RC DateToStdTimeFields ( + const STDTIME_WIN_DATE * /*I*/ pDate, + STDTIME_FIELDS * /*O*/ pStdTimeFields); + + +/*** timezone-offset support functions ***************************************/ + + +STDTIME_RC StdTimeStringAToTzoA ( + const STDTIME_STRINGA * /*I*/ pStdTimeString, + STDTIME_TZOA * /*O*/ pTzo); + +STDTIME_RC TzoAToStdTimeStringA ( + const STDTIME_TZOA * /*I*/ pTzo, + STDTIME_STRINGA * /*O*/ pStdTimeString); + +STDTIME_RC ValidStdTimeTzoA ( + const STDTIME_TZOA * /*I*/ pTzo); + +STDTIME_RC NormalizeStdTimeTzoA ( + STDTIME_TZOA * /*I*/ pTzo); + +STDTIME_RC GetLocalStdTimeTzoA ( + STDTIME_TZOA * /*O*/ pTzo); + +#define StdTimeStringToTzoA StdTimeStringAToTzoA +#define TzoToStdTimeStringA TzoAToStdTimeStringA + + +#ifdef STDTIME_UNICODE +#else +#define StdTimeStringToTzo StdTimeStringAToTzoA +#define TzoToStdTimeString TzoAToStdTimeStringA +#define ValidStdTimeTzo ValidStdTimeTzoA +#define NormalizeStdTimeTzo NormalizeStdTimeTzoA +#define GetLocalStdTimeTzo GetLocalStdTimeTzoA +#endif /* STDTIME_UNICODE */ + + +/*** error message decoding functions ****************************************/ + + +STDTIME_RC StdTimeRcToErrMsgA ( + const STDTIME_RC /*I*/ stdTimeRc, + STDTIME_ERRMSGA * /*O*/ pErrMsg); + +#ifdef STDTIME_UNICODE +#else +#define StdTimeRcToErrMsg StdTimeRcToErrMsgA +#endif /* STDTIME_UNICODE */ + + +/*** normalization functions; primarily private functions ********************/ + + +STDTIME_RC Rc_NormalizeStdTimeFields ( + STDTIME_FIELDS * pFields); + +STDTIME_RC Rc_StdTime_NormalizeSystemTimeEx ( + STDTIME_WIN_SYSTEMTIME * /*IO*/ pSystemTime, + int32_t * /*IO*/ pUsec, + int32_t * /*IO*/ pNsec); + +STDTIME_RC Rc_StdTime_NormalizeStructTmEx ( + struct tm * /*IO*/ pStructTm, + int32_t * /*IO*/ pMsec, + int32_t * /*IO*/ pUsec, + int32_t * /*IO*/ pNsec); + + +/* Utility functions */ +STDTIME_BOOL Bool_StdTimeGmTimeR ( + time_t * pTimeT, + struct tm * pStructTm); + +/*****************************************************************************/ +/* END */ +/*****************************************************************************/ + + +#ifdef __cplusplus +} +#endif + + +#endif /* _STDTIME_H_7583ECB2_DB3F_48B3_8A97_2D1D2A38C84A_ */ + diff --git a/mmslib/inc/stdtime_config.h b/mmslib/inc/stdtime_config.h new file mode 100644 index 0000000..2be7639 --- /dev/null +++ b/mmslib/inc/stdtime_config.h @@ -0,0 +1,153 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtimeconfig.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Configuration of Standard Time Management Library Functions */ +/* This file is used to set the required symbols to generate a STDTIME */ +/* Library for a desired environment */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 02/22/08 JRB 05 Add glbtypes.h for SD_BYTE_ORDER & del stdtime_endian.h*/ +/* 03/18/07 RLH 04 Add QNX support. */ +/* 01/10/07 RLH 03 Add STDTIME_HPDATE_MSEC_ROUNDED define */ +/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */ +/* 01/18/06 RLH 01 Created */ +/*****************************************************************************/ + + +#ifndef _STDTIME_CONFIG_H_7BF1A3F7_495B_4EEE_A2B3_02D65FDF88B6_ +#define _STDTIME_CONFIG_H_7BF1A3F7_495B_4EEE_A2B3_02D65FDF88B6_ + +#include "glbtypes.h" /* Need this for SD_BYTE_ORDER */ + +#if 0 /* put disabled option inside the #if/#endif block */ + + +#define STDTIME_UNICODE /* default time strings are UNICODE */ +#define STDTIME_UNICODE_SUBSTITUTE_CHAR '\x1A' /* a value instead of '\x1A' */ +#define STDTIME_TIME_T64_ENABLED /* if system time_t is 64 bits */ +#define STDTIME_CPP_ONLY_DISABLED /* if library may be compiled as C */ +#define STDTIME_CPP_ONLY_ENABLED /* if library only compiled as C++ */ +#define STDTIME_MERGED_CSV /* csv has NO commas between records */ +#define STDTIME_LOCAL_USES_SYSAPI /* how to get local time from GMT */ + + +#define STDTIME_ISO_DLM_STR "-T:." /* default STDTIME_STRING delimiters */ +/* STDTIME_ISO_DLM_STR must be exactly 4 Ansi characters */ + + +#define QUADLIB_ENABLED /* if 64-bit math is simulated */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ +#define QUADLIB_NATIVE64_DISABLED /* if compiler has no 64-bit support */ +#define QUADLIB_STATIC static /* to make QUADLIB functions local */ +#define QUADLIB_I64N myI64Type /* explicit 64-bit signed int type */ +#define QUADLIB_U64N myUnsignedI64Type /* explicit 64-bit unsigned int type */ + + +#define STDTIMEW32_STATIC /* makes STDTIMEW32 functions local */ +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on Unix */ +#define STDTIMEW32_USE_GETTIMEOFDAY /* to use gettimeofday() on Unix */ +#define STDTIMEW32_USE_TIMEB /* to use ftime() and timeb on Unix */ + +#endif /* disabled */ + +/* put enabled options after this point */ + +#define STDTIME_TM_ISDST_DEFAULT (-1) /* struct tm_isdst default setting */ + +#define STDTIME_UNMERGED_CSV /* csv HAS commas between records */ + +#undef STDTIME_LOCAL_USES_TZDB /* how to get local time from GMT */ + +#define QUADLIB_NATIVE64_ENABLED /* if compiler has 64-bit support */ +#define STDTIME_HPDATE_MSEC_ROUNDED /* if HpDate msec are rounded */ + +/* include appropriate stdint.h header for target system */ + +#ifdef _AIX +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on Unix */ +#define STDTIMEW32_ENABLED /* enable WIN32 compatibility layer */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ +#include "stdint.h" + +#elif defined(linux) +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on Unix */ +#define STDTIMEW32_ENABLED /* enable WIN32 compatibility layer */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ +#include "stdint.h" + +#elif defined(__ECOS) +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on Unix */ +#define STDTIMEW32_ENABLED /* enable WIN32 compatibility layer */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ +//#include "stdint.h" + +/*renxiaobao add*/ +#elif defined(VXWORKS) +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on Unix */ +#define STDTIMEW32_ENABLED /* enable WIN32 compatibility layer */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ + + + + + + + + + +#elif defined(sun) +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on Unix */ +#define STDTIMEW32_ENABLED /* enable WIN32 compatibility layer */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ +#include + +#elif defined(__alpha) && !defined(__VMS) /* digital unix */ +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on Unix */ +#define STDTIMEW32_ENABLED /* enable WIN32 compatibility layer */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ +#include + +#elif defined(_WIN32) +#define STDTIMEW32_DISABLED /* disable WIN32 compatibility layer */ +#define QUADLIB_DISABLED /* if 64-bit math done in hardware */ +#include "stdtime_stdint.h" + +#elif defined(__QNX__) +#define STDTIMEW32_USE_CLOCKGETTIME /* to use clock_gettime() on QNX */ +#define STDTIMEW32_ENABLED /* enable WIN32 compatibility layer */ +#undef QUADLIB_DISABLED /* if 64-bit math done in hardware */ +#define QUADLIB_ENABLED /* if 64-bit math is simulated */ +#undef QUADLIB_NATIVE64_ENABLED /* if compiler has 64-bit support */ +#define QUADLIB_NATIVE64_DISABLED /* if compiler has no 64-bit support */ + +/* QNX has no stdint.h or equivalent */ +/* bare minimum definitions located here */ + + +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + + +#else + +#define STDTIMEW32_DISABLED /* disable WIN32 compatibility layer */ +#include "stdtime_stdint.h" + +#endif + +#endif /* _STDTIME_CONFIG_H_7BF1A3F7_495B_4EEE_A2B3_02D65FDF88B6_ */ + diff --git a/mmslib/inc/stdtime_endian.h b/mmslib/inc/stdtime_endian.h new file mode 100644 index 0000000..221adb9 --- /dev/null +++ b/mmslib/inc/stdtime_endian.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/* + * Copyright notice reproduced from , from + * which this code was originally taken. + * + * Modified by Caleb Epstein to use with GNU libc and to + * define the BOOST_ENDIAN macro. + */ + +/* + * Modified 2006-02-25 By SISCO, Inc. from Boost source. + * source code simplified, made C compliant, and BOOST_BYTE_ORDER removed + */ + + +#ifndef _STDTIME_ENDIAN_H_9F8D5A2A_B2F9_4F41_A9A0_D2D3912E3082_ +#define _STDTIME_ENDIAN_H_9F8D5A2A_B2F9_4F41_A9A0_D2D3912E3082_ + + +#undef HOST_BIG_ENDIAN +#undef HOST_LITTLE_ENDIAN + +/* GNU libc offers the helpful header which defines __BYTE_ORDER */ + +#ifdef __GLIBC__ +#include + +#if (__BYTE_ORDER == __LITTLE_ENDIAN) /* 1234 */ +#define HOST_LITTLE_ENDIAN +#elif (__BYTE_ORDER == __BIG_ENDIAN) /* 4321 */ +#define HOST_BIG_ENDIAN +#elif (__BYTE_ORDER == __PDP_ENDIAN) +#error PDP_ENDIAN order not supported +#else +#error unknown machine endian order +#endif + + +#elif defined(_MIPSEB) \ + || defined(_POWER) \ + || defined(__hppa) \ + || defined(__powerpc__) \ + || defined(__ppc__) \ + || defined(__s390__) \ + || defined(__sparc) \ + || defined(__sparc__) \ + || defined(sun) \ + || defined(_AIX) \ + || defined(VXWORKS) \ + || defined(__hpux) /**/ +#define HOST_BIG_ENDIAN + + +#elif defined(_M_ALPHA) \ + || defined(_M_IA64) \ + || defined(_M_IX86) \ + || defined(__alpha__) \ + || defined(__i386__) \ + || defined(__ia64) \ + || defined(__ia64__) \ + || defined(MSDOS) \ + || defined(_WIN32) \ + || defined(__LYNX) \ + || defined(__MSDOS__) \ + || defined(__OS2__) \ + || defined(__QNX__) \ + || defined(linux) \ + || (defined(__ALPHA) && defined(__VMS)) \ + || (defined(__alpha) && !defined(__VMS)) /**/ +#define HOST_LITTLE_ENDIAN + + +#else +#error the file host_endian.h needs to be configured for your CPU type +#endif + +#endif /* _STDTIME_ENDIAN_H_9F8D5A2A_B2F9_4F41_A9A0_D2D3912E3082_ */ + diff --git a/mmslib/inc/stdtime_enum_err.h b/mmslib/inc/stdtime_enum_err.h new file mode 100644 index 0000000..34671a2 --- /dev/null +++ b/mmslib/inc/stdtime_enum_err.h @@ -0,0 +1,65 @@ + STDTIME_ENUM_ERR (BTOD_form_code_not_4_or_6) + STDTIME_ENUM_ERR (CComSpan_range_is_invalid) + STDTIME_ENUM_ERR (COleDateTimeSpan_status_is_invalid) + STDTIME_ENUM_ERR (COleDateTimeSpan_status_is_null) + STDTIME_ENUM_ERR (MMS_year_LT_1984) + STDTIME_ENUM_ERR (VARIANT_BYREF_type_not_DATE) + STDTIME_ENUM_ERR (VARIANT_type_not_DATE) + STDTIME_ENUM_ERR (argument_out_of_range) + STDTIME_ENUM_ERR (buffer_size_exceeded) + STDTIME_ENUM_ERR (cannot_determine_local_timezone) + STDTIME_ENUM_ERR (cannot_determine_local_timezone_offset) + STDTIME_ENUM_ERR (cannot_extract_timezone_field) + STDTIME_ENUM_ERR (cannot_find_timezone_entry) + STDTIME_ENUM_ERR (cannot_find_timezone_name) + STDTIME_ENUM_ERR (cannot_open_timezone_file) + STDTIME_ENUM_ERR (conflicting_sign_delta) + STDTIME_ENUM_ERR (data_out_of_range) + STDTIME_ENUM_ERR (day_out_of_range) + STDTIME_ENUM_ERR (failure_in_api_FileTimeToLocalFileTime) + STDTIME_ENUM_ERR (failure_in_api_FileTimeToSystemTime) + STDTIME_ENUM_ERR (failure_in_api_LocalFileTimeToFileTime) + STDTIME_ENUM_ERR (failure_in_api_SetStdTimeStringDelimitersA) + STDTIME_ENUM_ERR (failure_in_api_SetStdTimeStringDelimitersW) + STDTIME_ENUM_ERR (failure_in_api_SgnStdTimeDelta) + STDTIME_ENUM_ERR (failure_in_api_StdTimeGetDayofWeekAndYear) + STDTIME_ENUM_ERR (failure_in_api_StdTimeW32GetDayofWeekAndYear) + STDTIME_ENUM_ERR (failure_in_api_SystemTimeToFileTime) + STDTIME_ENUM_ERR (failure_in_api_strftime) + STDTIME_ENUM_ERR (field_selector_out_of_range) + STDTIME_ENUM_ERR (invalid_FileTime) + STDTIME_ENUM_ERR (invalid_StdTime) + STDTIME_ENUM_ERR (invalid_day) + STDTIME_ENUM_ERR (invalid_delimiter) + STDTIME_ENUM_ERR (invalid_hh_mm) + STDTIME_ENUM_ERR (invalid_hour) + STDTIME_ENUM_ERR (invalid_min) + STDTIME_ENUM_ERR (invalid_mon) + STDTIME_ENUM_ERR (invalid_msec) + STDTIME_ENUM_ERR (invalid_nsec) + STDTIME_ENUM_ERR (invalid_sec) + STDTIME_ENUM_ERR (invalid_sign) + STDTIME_ENUM_ERR (invalid_ss) + STDTIME_ENUM_ERR (invalid_stdtime_rc_value) + STDTIME_ENUM_ERR (invalid_timezone_offset) + STDTIME_ENUM_ERR (invalid_timezone_rule) + STDTIME_ENUM_ERR (invalid_usec) + STDTIME_ENUM_ERR (invalid_year) + STDTIME_ENUM_ERR (length_out_of_range) + STDTIME_ENUM_ERR (missing_timezone_name) + STDTIME_ENUM_ERR (negative_dst_end_time) + STDTIME_ENUM_ERR (negative_dst_start_time) + STDTIME_ENUM_ERR (null_VARIANT_pdate) + STDTIME_ENUM_ERR (null_argument) + STDTIME_ENUM_ERR (overflow_in_delta_day) + STDTIME_ENUM_ERR (overflow_in_delta_hour) + STDTIME_ENUM_ERR (overflow_in_delta_min) + STDTIME_ENUM_ERR (overflow_in_delta_msec) + STDTIME_ENUM_ERR (overflow_in_delta_nsec) + STDTIME_ENUM_ERR (overflow_in_delta_sec) + STDTIME_ENUM_ERR (overflow_in_delta_usec) + STDTIME_ENUM_ERR (span_out_of_range) + STDTIME_ENUM_ERR (time_GT_2038_01_18__19_14_07) + STDTIME_ENUM_ERR (time_LT_1970_01_01) + STDTIME_ENUM_ERR (unexpected_condition) + STDTIME_ENUM_ERR (year_out_of_range) diff --git a/mmslib/inc/stdtime_enum_func.h b/mmslib/inc/stdtime_enum_func.h new file mode 100644 index 0000000..ea9943b --- /dev/null +++ b/mmslib/inc/stdtime_enum_func.h @@ -0,0 +1,425 @@ + STDTIME_ENUM_FUNC (AbsStdTimeDelta) + STDTIME_ENUM_FUNC (AbsStdTimeSpan) + STDTIME_ENUM_FUNC (CComDateExToStdTime) + STDTIME_ENUM_FUNC (CComDateExToStdTimeFields) + STDTIME_ENUM_FUNC (CComDateToStdTime) + STDTIME_ENUM_FUNC (CComDateToStdTimeFields) + STDTIME_ENUM_FUNC (CComSpanExToStdTime) + STDTIME_ENUM_FUNC (CComSpanExToStdTimeDelta) + STDTIME_ENUM_FUNC (CComSpanExToStdTimeFields) + STDTIME_ENUM_FUNC (CComSpanExToStdTimeSpan) + STDTIME_ENUM_FUNC (CComSpanToStdTime) + STDTIME_ENUM_FUNC (CComSpanToStdTimeDelta) + STDTIME_ENUM_FUNC (CComSpanToStdTimeFields) + STDTIME_ENUM_FUNC (CComSpanToStdTimeSpan) + STDTIME_ENUM_FUNC (CFileTimeSpanToStdTime) + STDTIME_ENUM_FUNC (CFileTimeSpanToStdTimeDelta) + STDTIME_ENUM_FUNC (CFileTimeSpanToStdTimeFields) + STDTIME_ENUM_FUNC (CFileTimeSpanToStdTimeSpan) + STDTIME_ENUM_FUNC (CFileTimeToStdTime) + STDTIME_ENUM_FUNC (CFileTimeToStdTimeFields) + STDTIME_ENUM_FUNC (COleDateTimeExToStdTime) + STDTIME_ENUM_FUNC (COleDateTimeExToStdTimeFields) + STDTIME_ENUM_FUNC (COleDateTimeSpanExToStdTime) + STDTIME_ENUM_FUNC (COleDateTimeSpanExToStdTimeDelta) + STDTIME_ENUM_FUNC (COleDateTimeSpanExToStdTimeFields) + STDTIME_ENUM_FUNC (COleDateTimeSpanExToStdTimeSpan) + STDTIME_ENUM_FUNC (COleDateTimeSpanToStdTime) + STDTIME_ENUM_FUNC (COleDateTimeSpanToStdTimeDelta) + STDTIME_ENUM_FUNC (COleDateTimeSpanToStdTimeFields) + STDTIME_ENUM_FUNC (COleDateTimeSpanToStdTimeSpan) + STDTIME_ENUM_FUNC (COleDateTimeToStdTime) + STDTIME_ENUM_FUNC (COleDateTimeToStdTimeFields) + STDTIME_ENUM_FUNC (CTimeExToStdTime) + STDTIME_ENUM_FUNC (CTimeExToStdTimeFields) + STDTIME_ENUM_FUNC (CTimeSpanExToStdTime) + STDTIME_ENUM_FUNC (CTimeSpanExToStdTimeDelta) + STDTIME_ENUM_FUNC (CTimeSpanExToStdTimeFields) + STDTIME_ENUM_FUNC (CTimeSpanExToStdTimeSpan) + STDTIME_ENUM_FUNC (CTimeSpanToStdTime) + STDTIME_ENUM_FUNC (CTimeSpanToStdTimeDelta) + STDTIME_ENUM_FUNC (CTimeSpanToStdTimeFields) + STDTIME_ENUM_FUNC (CTimeSpanToStdTimeSpan) + STDTIME_ENUM_FUNC (CTimeToStdTime) + STDTIME_ENUM_FUNC (CTimeToStdTimeFields) + STDTIME_ENUM_FUNC (DateExToStdTime) + STDTIME_ENUM_FUNC (DateExToStdTimeFields) + STDTIME_ENUM_FUNC (DateToStdTime) + STDTIME_ENUM_FUNC (DateToStdTimeFields) + STDTIME_ENUM_FUNC (DbTimeStampToStdTime) + STDTIME_ENUM_FUNC (DbTimeStampToStdTimeFields) + STDTIME_ENUM_FUNC (DelimitStdTimeStringA) + STDTIME_ENUM_FUNC (DelimitStdTimeStringW) + STDTIME_ENUM_FUNC (FileTimeToStdTime) + STDTIME_ENUM_FUNC (FileTimeToStdTimeFields) + STDTIME_ENUM_FUNC (FileTimeToStdTimeHexStrA) + STDTIME_ENUM_FUNC (FileTimeToStdTimeHexStrW) + STDTIME_ENUM_FUNC (FileTimeToStdTimeStringA) + STDTIME_ENUM_FUNC (FileTimeToStdTimeStringW) + STDTIME_ENUM_FUNC (FormatStdTimeA) + STDTIME_ENUM_FUNC (FormatStdTimeFieldsA) + STDTIME_ENUM_FUNC (FormatStdTimeFieldsW) + STDTIME_ENUM_FUNC (FormatStdTimeHexStrA) + STDTIME_ENUM_FUNC (FormatStdTimeHexStrW) + STDTIME_ENUM_FUNC (FormatStdTimeStringA) + STDTIME_ENUM_FUNC (FormatStdTimeStringW) + STDTIME_ENUM_FUNC (FormatStdTimeW) + STDTIME_ENUM_FUNC (GetLocalStdTime) + STDTIME_ENUM_FUNC (GetLocalStdTimeFields) + STDTIME_ENUM_FUNC (GetLocalStdTimeHexStrA) + STDTIME_ENUM_FUNC (GetLocalStdTimeHexStrW) + STDTIME_ENUM_FUNC (GetLocalStdTimeStringA) + STDTIME_ENUM_FUNC (GetLocalStdTimeStringW) + STDTIME_ENUM_FUNC (GetLocalStdTimeTzoA) + STDTIME_ENUM_FUNC (GetLocalStdTimeTzoW) + STDTIME_ENUM_FUNC (GetStdTime) + STDTIME_ENUM_FUNC (GetStdTimeFields) + STDTIME_ENUM_FUNC (GetStdTimeHexStrA) + STDTIME_ENUM_FUNC (GetStdTimeHexStrW) + STDTIME_ENUM_FUNC (GetStdTimeStringA) + STDTIME_ENUM_FUNC (GetStdTimeStringW) + STDTIME_ENUM_FUNC (GetStdTimeZoneInfo) + STDTIME_ENUM_FUNC (HpCComDateExToStdTime) + STDTIME_ENUM_FUNC (HpCComDateExToStdTimeFields) + STDTIME_ENUM_FUNC (HpCComDateToStdTime) + STDTIME_ENUM_FUNC (HpCComDateToStdTimeFields) + STDTIME_ENUM_FUNC (HpCComSpanExToStdTime) + STDTIME_ENUM_FUNC (HpCComSpanExToStdTimeDelta) + STDTIME_ENUM_FUNC (HpCComSpanExToStdTimeFields) + STDTIME_ENUM_FUNC (HpCComSpanExToStdTimeSpan) + STDTIME_ENUM_FUNC (HpCComSpanToStdTime) + STDTIME_ENUM_FUNC (HpCComSpanToStdTimeDelta) + STDTIME_ENUM_FUNC (HpCComSpanToStdTimeFields) + STDTIME_ENUM_FUNC (HpCComSpanToStdTimeSpan) + STDTIME_ENUM_FUNC (HpCOleDateTimeExToStdTime) + STDTIME_ENUM_FUNC (HpCOleDateTimeExToStdTimeFields) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanExToStdTime) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanExToStdTimeDelta) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanExToStdTimeFields) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanExToStdTimeSpan) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanToStdTime) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanToStdTimeDelta) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanToStdTimeFields) + STDTIME_ENUM_FUNC (HpCOleDateTimeSpanToStdTimeSpan) + STDTIME_ENUM_FUNC (HpCOleDateTimeToStdTime) + STDTIME_ENUM_FUNC (HpCOleDateTimeToStdTimeFields) + STDTIME_ENUM_FUNC (HpDateExToStdTime) + STDTIME_ENUM_FUNC (HpDateExToStdTimeFields) + STDTIME_ENUM_FUNC (HpDateToStdTime) + STDTIME_ENUM_FUNC (HpDateToStdTimeFields) + STDTIME_ENUM_FUNC (IccpTimeStampExToStdTime) + STDTIME_ENUM_FUNC (IccpTimeStampExToStdTimeFields) + STDTIME_ENUM_FUNC (IccpTimeStampToStdTime) + STDTIME_ENUM_FUNC (IccpTimeStampToStdTimeFields) + STDTIME_ENUM_FUNC (LocalStdTimeFieldsToStdTimeFields) + STDTIME_ENUM_FUNC (LocalStdTimeHexStrAToStdTimeHexStrA) + STDTIME_ENUM_FUNC (LocalStdTimeHexStrWToStdTimeHexStrW) + STDTIME_ENUM_FUNC (LocalStdTimeStringAToStdTimeStringA) + STDTIME_ENUM_FUNC (LocalStdTimeStringWToStdTimeStringW) + STDTIME_ENUM_FUNC (LocalStdTimeToStdTime) + STDTIME_ENUM_FUNC (MmsBtodExToStdTime) + STDTIME_ENUM_FUNC (MmsBtodExToStdTimeFields) + STDTIME_ENUM_FUNC (MmsBtodToStdTime) + STDTIME_ENUM_FUNC (MmsBtodToStdTimeFields) + STDTIME_ENUM_FUNC (MmsTimeOfDay4ExToStdTime) + STDTIME_ENUM_FUNC (MmsTimeOfDay4ExToStdTimeFields) + STDTIME_ENUM_FUNC (MmsTimeOfDay4ToStdTime) + STDTIME_ENUM_FUNC (MmsTimeOfDay4ToStdTimeFields) + STDTIME_ENUM_FUNC (MmsTimeOfDay6ExToStdTime) + STDTIME_ENUM_FUNC (MmsTimeOfDay6ExToStdTimeFields) + STDTIME_ENUM_FUNC (MmsTimeOfDay6ToStdTime) + STDTIME_ENUM_FUNC (MmsTimeOfDay6ToStdTimeFields) + STDTIME_ENUM_FUNC (MmsUtcTimeToStdTime) + STDTIME_ENUM_FUNC (MmsUtcTimeToStdTimeFields) + STDTIME_ENUM_FUNC (NegStdTimeDelta) + STDTIME_ENUM_FUNC (NegStdTimeSpan) + STDTIME_ENUM_FUNC (NormalizeStdTimeDelta) + STDTIME_ENUM_FUNC (NormalizeStdTimeTzoA) + STDTIME_ENUM_FUNC (NormalizeStdTimeTzoW) + STDTIME_ENUM_FUNC (Rc_ArgDateExToStdTime) + STDTIME_ENUM_FUNC (Rc_ArgDateExToStdTimeFields) + STDTIME_ENUM_FUNC (Rc_FixStdTimeZoneRules) + STDTIME_ENUM_FUNC (Rc_NormalizeStdTimeFields) + STDTIME_ENUM_FUNC (Rc_ParseStdTimeZoneData) + STDTIME_ENUM_FUNC (Rc_QuadLibI64ToStdTime) + STDTIME_ENUM_FUNC (Rc_StdTimeFieldsToArgDateEx) + STDTIME_ENUM_FUNC (Rc_StdTimeToArgDateEx) + STDTIME_ENUM_FUNC (Rc_StdTimeToQuadLibI64) + STDTIME_ENUM_FUNC (Rc_StdTimeTz_GetRule) + STDTIME_ENUM_FUNC (Rc_StdTimeTz_GetTime) + STDTIME_ENUM_FUNC (Rc_StdTime_DateToVariant) + STDTIME_ENUM_FUNC (Rc_StdTime_FileTimeSplit) + STDTIME_ENUM_FUNC (Rc_StdTime_FileTimeToSystemTimeEx) + STDTIME_ENUM_FUNC (Rc_StdTime_Formatter) + STDTIME_ENUM_FUNC (Rc_StdTime_NormalizeStructTmEx) + STDTIME_ENUM_FUNC (Rc_StdTime_NormalizeSystemTimeEx) + STDTIME_ENUM_FUNC (Rc_StdTime_SystemTimeExToFileTime) + STDTIME_ENUM_FUNC (Rc_StdTime_TimeTBase) + STDTIME_ENUM_FUNC (Rc_StdTime_TimeTypeToFileTime) + STDTIME_ENUM_FUNC (Rc_StdTime_ValidFileTime) + STDTIME_ENUM_FUNC (Rc_StdTime_VariantToDate) + STDTIME_ENUM_FUNC (ReadStdTimeZoneInfo) + STDTIME_ENUM_FUNC (RepairStdTimeStringA) + STDTIME_ENUM_FUNC (RepairStdTimeStringW) + STDTIME_ENUM_FUNC (RoundStdTimeDelta) + STDTIME_ENUM_FUNC (SetStdTimeStringDelimitersA) + STDTIME_ENUM_FUNC (SetStdTimeStringDelimitersW) + STDTIME_ENUM_FUNC (StdTimeApiFileTimeIsDST) + STDTIME_ENUM_FUNC (StdTimeApiFileTimeToZonedFileTime) + STDTIME_ENUM_FUNC (StdTimeApiZonedFileTimeIsDST) + STDTIME_ENUM_FUNC (StdTimeApiZonedFileTimeToFileTime) + STDTIME_ENUM_FUNC (StdTimeDeltaToCComSpan) + STDTIME_ENUM_FUNC (StdTimeDeltaToCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeDeltaToCFileTimeSpan) + STDTIME_ENUM_FUNC (StdTimeDeltaToCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeDeltaToCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeDeltaToCTimeSpan) + STDTIME_ENUM_FUNC (StdTimeDeltaToCTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeDeltaToHpCComSpan) + STDTIME_ENUM_FUNC (StdTimeDeltaToHpCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeDeltaToHpCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeDeltaToHpCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeDeltaToStdTimeSpan) + STDTIME_ENUM_FUNC (StdTimeDelta_AddDelta) + STDTIME_ENUM_FUNC (StdTimeDelta_AddSpan) + STDTIME_ENUM_FUNC (StdTimeDelta_SubDelta) + STDTIME_ENUM_FUNC (StdTimeDelta_SubSpan) + STDTIME_ENUM_FUNC (StdTimeFieldsToCComDate) + STDTIME_ENUM_FUNC (StdTimeFieldsToCComDateEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToCComSpan) + STDTIME_ENUM_FUNC (StdTimeFieldsToCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToCFileTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToCFileTimeSpan) + STDTIME_ENUM_FUNC (StdTimeFieldsToCOleDateTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToCOleDateTimeEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeFieldsToCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToCTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToCTimeEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToCTimeSpan) + STDTIME_ENUM_FUNC (StdTimeFieldsToCTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToDate) + STDTIME_ENUM_FUNC (StdTimeFieldsToDateEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToDbTimeStamp) + STDTIME_ENUM_FUNC (StdTimeFieldsToFileTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCComDate) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCComDateEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCComSpan) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCOleDateTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCOleDateTimeEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpDate) + STDTIME_ENUM_FUNC (StdTimeFieldsToHpDateEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToIccpTimeStamp) + STDTIME_ENUM_FUNC (StdTimeFieldsToIccpTimeStampEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToLocalStdTimeFields) + STDTIME_ENUM_FUNC (StdTimeFieldsToMmsBtod) + STDTIME_ENUM_FUNC (StdTimeFieldsToMmsBtodEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToMmsTimeOfDay4) + STDTIME_ENUM_FUNC (StdTimeFieldsToMmsTimeOfDay4Ex) + STDTIME_ENUM_FUNC (StdTimeFieldsToMmsTimeOfDay6) + STDTIME_ENUM_FUNC (StdTimeFieldsToMmsTimeOfDay6Ex) + STDTIME_ENUM_FUNC (StdTimeFieldsToMmsUtcTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToStdTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToStdTimeHexStrA) + STDTIME_ENUM_FUNC (StdTimeFieldsToStdTimeHexStrW) + STDTIME_ENUM_FUNC (StdTimeFieldsToStdTimeStringA) + STDTIME_ENUM_FUNC (StdTimeFieldsToStdTimeStringW) + STDTIME_ENUM_FUNC (StdTimeFieldsToStructTm) + STDTIME_ENUM_FUNC (StdTimeFieldsToStructTmEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToSystemTime) + STDTIME_ENUM_FUNC (StdTimeFieldsToSystemTimeEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToTimeType) + STDTIME_ENUM_FUNC (StdTimeFieldsToTimeTypeEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToUdate) + STDTIME_ENUM_FUNC (StdTimeFieldsToUdateEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToVariant) + STDTIME_ENUM_FUNC (StdTimeFieldsToVariantEx) + STDTIME_ENUM_FUNC (StdTimeFieldsToZonedStdTimeFields) + STDTIME_ENUM_FUNC (StdTimeFields_AddDelta) + STDTIME_ENUM_FUNC (StdTimeFields_AddFraction) + STDTIME_ENUM_FUNC (StdTimeFields_AddSpan) + STDTIME_ENUM_FUNC (StdTimeFields_GetDelta) + STDTIME_ENUM_FUNC (StdTimeFields_GetSpan) + STDTIME_ENUM_FUNC (StdTimeFields_SubDelta) + STDTIME_ENUM_FUNC (StdTimeFields_SubSpan) + STDTIME_ENUM_FUNC (StdTimeGetDayofWeekAndYear) + STDTIME_ENUM_FUNC (StdTimeHexStrAToFileTime) + STDTIME_ENUM_FUNC (StdTimeHexStrAToLocalStdTimeHexStrA) + STDTIME_ENUM_FUNC (StdTimeHexStrAToStdTime) + STDTIME_ENUM_FUNC (StdTimeHexStrAToStdTimeFields) + STDTIME_ENUM_FUNC (StdTimeHexStrAToStdTimeStringA) + STDTIME_ENUM_FUNC (StdTimeHexStrAToZonedStdTimeHexStrA) + STDTIME_ENUM_FUNC (StdTimeHexStrA_AddDelta) + STDTIME_ENUM_FUNC (StdTimeHexStrA_AddSpan) + STDTIME_ENUM_FUNC (StdTimeHexStrA_GetDelta) + STDTIME_ENUM_FUNC (StdTimeHexStrA_GetSpan) + STDTIME_ENUM_FUNC (StdTimeHexStrA_SubDelta) + STDTIME_ENUM_FUNC (StdTimeHexStrA_SubSpan) + STDTIME_ENUM_FUNC (StdTimeHexStrWToFileTime) + STDTIME_ENUM_FUNC (StdTimeHexStrWToLocalStdTimeHexStrW) + STDTIME_ENUM_FUNC (StdTimeHexStrWToStdTime) + STDTIME_ENUM_FUNC (StdTimeHexStrWToStdTimeFields) + STDTIME_ENUM_FUNC (StdTimeHexStrWToStdTimeStringW) + STDTIME_ENUM_FUNC (StdTimeHexStrWToZonedStdTimeHexStrW) + STDTIME_ENUM_FUNC (StdTimeHexStrW_AddDelta) + STDTIME_ENUM_FUNC (StdTimeHexStrW_AddSpan) + STDTIME_ENUM_FUNC (StdTimeHexStrW_GetDelta) + STDTIME_ENUM_FUNC (StdTimeHexStrW_GetSpan) + STDTIME_ENUM_FUNC (StdTimeHexStrW_SubDelta) + STDTIME_ENUM_FUNC (StdTimeHexStrW_SubSpan) + STDTIME_ENUM_FUNC (StdTimeRcToErrMsgA) + STDTIME_ENUM_FUNC (StdTimeRcToErrMsgW) + STDTIME_ENUM_FUNC (StdTimeSpanToCComSpan) + STDTIME_ENUM_FUNC (StdTimeSpanToCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeSpanToCFileTimeSpan) + STDTIME_ENUM_FUNC (StdTimeSpanToCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeSpanToCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeSpanToCTimeSpan) + STDTIME_ENUM_FUNC (StdTimeSpanToCTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeSpanToHpCComSpan) + STDTIME_ENUM_FUNC (StdTimeSpanToHpCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeSpanToHpCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeSpanToHpCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeSpanToStdTimeDelta) + STDTIME_ENUM_FUNC (StdTimeSpan_AddDelta) + STDTIME_ENUM_FUNC (StdTimeSpan_AddSpan) + STDTIME_ENUM_FUNC (StdTimeSpan_SubDelta) + STDTIME_ENUM_FUNC (StdTimeSpan_SubSpan) + STDTIME_ENUM_FUNC (StdTimeStringAToFileTime) + STDTIME_ENUM_FUNC (StdTimeStringAToLocalStdTimeStringA) + STDTIME_ENUM_FUNC (StdTimeStringAToStdTime) + STDTIME_ENUM_FUNC (StdTimeStringAToStdTimeFields) + STDTIME_ENUM_FUNC (StdTimeStringAToStdTimeHexStrA) + STDTIME_ENUM_FUNC (StdTimeStringAToTzoA) + STDTIME_ENUM_FUNC (StdTimeStringAToZonedStdTimeStringA) + STDTIME_ENUM_FUNC (StdTimeStringA_AddDelta) + STDTIME_ENUM_FUNC (StdTimeStringA_AddSpan) + STDTIME_ENUM_FUNC (StdTimeStringA_GetDelta) + STDTIME_ENUM_FUNC (StdTimeStringA_GetSpan) + STDTIME_ENUM_FUNC (StdTimeStringA_SubDelta) + STDTIME_ENUM_FUNC (StdTimeStringA_SubSpan) + STDTIME_ENUM_FUNC (StdTimeStringWToFileTime) + STDTIME_ENUM_FUNC (StdTimeStringWToLocalStdTimeStringW) + STDTIME_ENUM_FUNC (StdTimeStringWToStdTime) + STDTIME_ENUM_FUNC (StdTimeStringWToStdTimeFields) + STDTIME_ENUM_FUNC (StdTimeStringWToStdTimeHexStrW) + STDTIME_ENUM_FUNC (StdTimeStringWToTzoW) + STDTIME_ENUM_FUNC (StdTimeStringWToZonedStdTimeStringW) + STDTIME_ENUM_FUNC (StdTimeStringW_AddDelta) + STDTIME_ENUM_FUNC (StdTimeStringW_AddSpan) + STDTIME_ENUM_FUNC (StdTimeStringW_GetDelta) + STDTIME_ENUM_FUNC (StdTimeStringW_GetSpan) + STDTIME_ENUM_FUNC (StdTimeStringW_SubDelta) + STDTIME_ENUM_FUNC (StdTimeStringW_SubSpan) + STDTIME_ENUM_FUNC (StdTimeToCComDate) + STDTIME_ENUM_FUNC (StdTimeToCComDateEx) + STDTIME_ENUM_FUNC (StdTimeToCComSpan) + STDTIME_ENUM_FUNC (StdTimeToCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeToCFileTime) + STDTIME_ENUM_FUNC (StdTimeToCFileTimeSpan) + STDTIME_ENUM_FUNC (StdTimeToCOleDateTime) + STDTIME_ENUM_FUNC (StdTimeToCOleDateTimeEx) + STDTIME_ENUM_FUNC (StdTimeToCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeToCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeToCTime) + STDTIME_ENUM_FUNC (StdTimeToCTimeEx) + STDTIME_ENUM_FUNC (StdTimeToCTimeSpan) + STDTIME_ENUM_FUNC (StdTimeToCTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeToDate) + STDTIME_ENUM_FUNC (StdTimeToDateEx) + STDTIME_ENUM_FUNC (StdTimeToDbTimeStamp) + STDTIME_ENUM_FUNC (StdTimeToFileTime) + STDTIME_ENUM_FUNC (StdTimeToHpCComDate) + STDTIME_ENUM_FUNC (StdTimeToHpCComDateEx) + STDTIME_ENUM_FUNC (StdTimeToHpCComSpan) + STDTIME_ENUM_FUNC (StdTimeToHpCComSpanEx) + STDTIME_ENUM_FUNC (StdTimeToHpCOleDateTime) + STDTIME_ENUM_FUNC (StdTimeToHpCOleDateTimeEx) + STDTIME_ENUM_FUNC (StdTimeToHpCOleDateTimeSpan) + STDTIME_ENUM_FUNC (StdTimeToHpCOleDateTimeSpanEx) + STDTIME_ENUM_FUNC (StdTimeToHpDate) + STDTIME_ENUM_FUNC (StdTimeToHpDateEx) + STDTIME_ENUM_FUNC (StdTimeToIccpTimeStamp) + STDTIME_ENUM_FUNC (StdTimeToIccpTimeStampEx) + STDTIME_ENUM_FUNC (StdTimeToLocalStdTime) + STDTIME_ENUM_FUNC (StdTimeToMmsBtod) + STDTIME_ENUM_FUNC (StdTimeToMmsBtodEx) + STDTIME_ENUM_FUNC (StdTimeToMmsTimeOfDay4) + STDTIME_ENUM_FUNC (StdTimeToMmsTimeOfDay4Ex) + STDTIME_ENUM_FUNC (StdTimeToMmsTimeOfDay6) + STDTIME_ENUM_FUNC (StdTimeToMmsTimeOfDay6Ex) + STDTIME_ENUM_FUNC (StdTimeToMmsUtcTime) + STDTIME_ENUM_FUNC (StdTimeToStdTimeField) + STDTIME_ENUM_FUNC (StdTimeToStdTimeHexStrA) + STDTIME_ENUM_FUNC (StdTimeToStdTimeHexStrW) + STDTIME_ENUM_FUNC (StdTimeToStdTimeStringA) + STDTIME_ENUM_FUNC (StdTimeToStdTimeStringW) + STDTIME_ENUM_FUNC (StdTimeToStructTm) + STDTIME_ENUM_FUNC (StdTimeToStructTmEx) + STDTIME_ENUM_FUNC (StdTimeToSystemTime) + STDTIME_ENUM_FUNC (StdTimeToSystemTimeEx) + STDTIME_ENUM_FUNC (StdTimeToTimeType) + STDTIME_ENUM_FUNC (StdTimeToTimeTypeEx) + STDTIME_ENUM_FUNC (StdTimeToUdate) + STDTIME_ENUM_FUNC (StdTimeToUdateEx) + STDTIME_ENUM_FUNC (StdTimeToVariant) + STDTIME_ENUM_FUNC (StdTimeToVariantEx) + STDTIME_ENUM_FUNC (StdTimeToZonedStdTime) + STDTIME_ENUM_FUNC (StdTimeTzTimeToDelta) + STDTIME_ENUM_FUNC (StdTimeW32GetDayofWeekAndYear) + STDTIME_ENUM_FUNC (StdTimeZoneDataToInfo) + STDTIME_ENUM_FUNC (StdTimeZoneDayOfRule) + STDTIME_ENUM_FUNC (StdTime_AddDelta) + STDTIME_ENUM_FUNC (StdTime_AddSpan) + STDTIME_ENUM_FUNC (StdTime_GetDelta) + STDTIME_ENUM_FUNC (StdTime_GetSpan) + STDTIME_ENUM_FUNC (StdTime_SubDelta) + STDTIME_ENUM_FUNC (StdTime_SubSpan) + STDTIME_ENUM_FUNC (StructTmExToStdTime) + STDTIME_ENUM_FUNC (StructTmExToStdTimeFields) + STDTIME_ENUM_FUNC (StructTmToStdTime) + STDTIME_ENUM_FUNC (StructTmToStdTimeFields) + STDTIME_ENUM_FUNC (SystemTimeExToStdTime) + STDTIME_ENUM_FUNC (SystemTimeExToStdTimeFields) + STDTIME_ENUM_FUNC (SystemTimeToStdTime) + STDTIME_ENUM_FUNC (SystemTimeToStdTimeFields) + STDTIME_ENUM_FUNC (TimeTypeExToStdTime) + STDTIME_ENUM_FUNC (TimeTypeExToStdTimeFields) + STDTIME_ENUM_FUNC (TimeTypeToStdTime) + STDTIME_ENUM_FUNC (TimeTypeToStdTimeFields) + STDTIME_ENUM_FUNC (TranslateStdTimeWinZoneName) + STDTIME_ENUM_FUNC (TranslateStdTimeZoneName) + STDTIME_ENUM_FUNC (TrimStdTimeStringA) + STDTIME_ENUM_FUNC (TrimStdTimeStringW) + STDTIME_ENUM_FUNC (TruncStdTimeDelta) + STDTIME_ENUM_FUNC (TruncStdTimeStringA) + STDTIME_ENUM_FUNC (TruncStdTimeStringW) + STDTIME_ENUM_FUNC (TzoAToStdTimeStringA) + STDTIME_ENUM_FUNC (TzoWToStdTimeStringW) + STDTIME_ENUM_FUNC (UdateExToStdTime) + STDTIME_ENUM_FUNC (UdateExToStdTimeFields) + STDTIME_ENUM_FUNC (UdateToStdTime) + STDTIME_ENUM_FUNC (UdateToStdTimeFields) + STDTIME_ENUM_FUNC (ValidStdTime) + STDTIME_ENUM_FUNC (ValidStdTimeDelta) + STDTIME_ENUM_FUNC (ValidStdTimeFields) + STDTIME_ENUM_FUNC (ValidStdTimeHexStrA) + STDTIME_ENUM_FUNC (ValidStdTimeHexStrW) + STDTIME_ENUM_FUNC (ValidStdTimeSpan) + STDTIME_ENUM_FUNC (ValidStdTimeStringA) + STDTIME_ENUM_FUNC (ValidStdTimeStringW) + STDTIME_ENUM_FUNC (ValidStdTimeTzoA) + STDTIME_ENUM_FUNC (ValidStdTimeTzoW) + STDTIME_ENUM_FUNC (VariantExToStdTime) + STDTIME_ENUM_FUNC (VariantExToStdTimeFields) + STDTIME_ENUM_FUNC (VariantToStdTime) + STDTIME_ENUM_FUNC (VariantToStdTimeFields) + STDTIME_ENUM_FUNC (ZonedStdTimeFieldsToStdTimeFields) + STDTIME_ENUM_FUNC (ZonedStdTimeHexStrAToStdTimeHexStrA) + STDTIME_ENUM_FUNC (ZonedStdTimeHexStrWToStdTimeHexStrW) + STDTIME_ENUM_FUNC (ZonedStdTimeStringAToStdTimeStringA) + STDTIME_ENUM_FUNC (ZonedStdTimeStringWToStdTimeStringW) + STDTIME_ENUM_FUNC (ZonedStdTimeToStdTime) diff --git a/mmslib/inc/stdtime_mms_btime.h b/mmslib/inc/stdtime_mms_btime.h new file mode 100644 index 0000000..e1b09c0 --- /dev/null +++ b/mmslib/inc/stdtime_mms_btime.h @@ -0,0 +1,81 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2006 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtime_mms_btime.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Support for MMS Btime4, BTime6 and BTOD conversions to/from STDTIME */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 04/08/08 JRB 03 Chg () to (ST_VOID) in prototype. */ +/* 02/20/08 JRB 02 Add T84_* defines. */ +/* Del TimeOfDay4, Btod, and StdTimeFields functions. */ +/* 10/05/06 RLH 01 Created */ +/*****************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#define T84_HIGHDATETIME 0x01ad63ae /* high word of 1984 FILETIME*/ +#define T84_LOWDATETIME 0xef5a4000 /* low word of 1984 FILETIME*/ + +#if defined(ASN1R_INCLUDED) && defined(MMS_BTOD4) && defined(MMS_BTOD6) +#define STDTIME_MMS_TIMEOFDAY6 MMS_BTIME6 + +#else + +typedef struct + { + int32_t ms; /* milliseconds since midnight */ + int32_t day; /* days since January 1, 1984 */ + } +STDTIME_MMS_TIMEOFDAY6; + +#endif + + + +/*** MmsTimeOfDay4/6 initialization functions ********************************/ + +STDTIME_MMS_TIMEOFDAY6 StdTimeApiZeroMmsTimeOfDay6 (ST_VOID); + +/*** MmsTimeOfDay6Ex functions ***********************************************/ + + +STDTIME_RC StdTimeToMmsTimeOfDay6Ex ( + const STDTIME * /*I*/ pStdTime, + STDTIME_MMS_TIMEOFDAY6 * /*O*/ pMmsTimeOfDay6, + int32_t * /*O*/ pUsec, /* optional */ + int32_t * /*O*/ pNsec); /* optional */ + + +STDTIME_RC MmsTimeOfDay6ExToStdTime ( + const STDTIME_MMS_TIMEOFDAY6 * /*I*/ pMmsTimeOfDay6, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec, + STDTIME * /*O*/ pStdTime); + + +/*** MmsTimeOfDay6 functions *************************************************/ + + +STDTIME_RC StdTimeToMmsTimeOfDay6 ( + const STDTIME * /*I*/ pStdTime, + STDTIME_MMS_TIMEOFDAY6 * /*O*/ pMmsTimeOfDay6); + + +STDTIME_RC MmsTimeOfDay6ToStdTime ( + const STDTIME_MMS_TIMEOFDAY6 * /*I*/ pMmsTimeOfDay6, + STDTIME * /*O*/ pStdTime); + +#ifdef __cplusplus +} +#endif + diff --git a/mmslib/inc/stdtime_mms_utctime.h b/mmslib/inc/stdtime_mms_utctime.h new file mode 100644 index 0000000..1ea703e --- /dev/null +++ b/mmslib/inc/stdtime_mms_utctime.h @@ -0,0 +1,61 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2006 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtime_mms_utctime.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Support for MMS UTC TIME conversions to/from STDTIME */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 04/08/08 JRB 03 Chg () to (ST_VOID) in prototype. */ +/* 02/20/08 JRB 02 Delete StdTimeFields functions. */ +/* 10/05/06 RLH 01 Created */ +/*****************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(ASN1R_INCLUDED) +#define STDTIME_MMS_UTC_TIME MMS_UTC_TIME + +#else + +typedef struct + { + int32_t secs; /* seconds since January 1, 1970 */ + int32_t fraction; /* 24-bit binary fraction of second */ + int32_t qflags; /* 8-bit quality flags */ + } +STDTIME_MMS_UTC_TIME; + +#endif + + +/*** MmsUtcTime initialization function **************************************/ + +STDTIME_MMS_UTC_TIME StdTimeApiZeroMmsUtcTime (ST_VOID); + + +/*** MmsUtcTime functions *************************************************/ + + +STDTIME_RC StdTimeToMmsUtcTime ( + const STDTIME * /*I*/ pStdTime, + STDTIME_MMS_UTC_TIME * /*O*/ pMmsUtcTime); + + +STDTIME_RC MmsUtcTimeToStdTime ( + const STDTIME_MMS_UTC_TIME * /*I*/ pMmsUtcTime, + STDTIME * /*O*/ pStdTime); + +#ifdef __cplusplus +} +#endif + diff --git a/mmslib/inc/stdtime_quadlib.h b/mmslib/inc/stdtime_quadlib.h new file mode 100644 index 0000000..fa45097 --- /dev/null +++ b/mmslib/inc/stdtime_quadlib.h @@ -0,0 +1,1081 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : QuadLib.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* 64-bit Math Simulation Library - header file */ +/* Provided for platforms without native 64-bit support. */ +/* */ +/* When QUADLIB_ENABLED is defined, definitions relevant to the */ +/* simulations library are generated. Otherwise, definitions are */ +/* selected to develop code on 64-bit enabled platforms without going */ +/* through the QuadLib library. */ +/* */ +/* Define QUADLIB_STATIC as 'static' to make the declarations local. */ +/* */ +/* Define QUADLIB_I64N as the native signed 64-bit data type. */ +/* Define QUADLIB_U64N as the native unsigned 64-bit data type. */ +/* If not defined, an assumption is made based on existence of _WIN32. */ +/* */ +/* The include file "host_endian.h" defines the native host endian order. */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 02/22/08 JRB 03 Use SD_BYTE_ORDER like all other SISCO code. */ +/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */ +/* 01/18/06 RLH 01 Created */ +/*****************************************************************************/ + + +#ifndef _STDTIME_QUADLIB_H_B07CB807_8BFC_41B3_872E_EDD251FD6AEB_ +#define _STDTIME_QUADLIB_H_B07CB807_8BFC_41B3_872E_EDD251FD6AEB_ + + +#ifdef __cplusplus +extern "C" { +#endif + +/*****************************************************************************/ +/* ENABLED or DISABLED: SUPPORT FOR 64-BIT EMULATION */ +/* */ +/* use StdTimeConfig.h to set QUADLIB_ENABLED or QUADLIB_DISABLED */ +/*****************************************************************************/ + +#if defined(QUADLIB_ENABLED) && defined(QUADLIB_DISABLED) +#error Both QUADLIB_ENABLED and QUADLIB_DISABLED defined +#undef QUADLIB_ENABLED +#endif + +#if !defined(QUADLIB_ENABLED) && !defined(QUADLIB_DISABLED) +#define QUADLIB_DISABLED /* default */ +#endif + +/*****************************************************************************/ +/* ENABLED or DISABLED: EXISTENCE OF 64-BIT SUPPORT IN COMPILER */ +/* */ +/* use StdTimeConfig.h to set QUADLIB_NATIVE64_ENABLED or */ +/* QUADLIB_NATIVE64_DISABLED */ +/*****************************************************************************/ + +/* these defines are used mainly to avoid compile errors on platforms */ +/* that have no support at all for 64-bit types */ + +#if defined(QUADLIB_NATIVE64_ENABLED) && defined(QUADLIB_NATIVE64_DISABLED) +#error Both QUADLIB_NATIVE64_ENABLED and QUADLIB_NATIVE64_DISABLED defined +#undef QUADLIB_NATIVE64_ENABLED +#undef QUADLIB_NATIVE64_DISABLED +#endif + +#if !defined(QUADLIB_NATIVE64_ENABLED) && !defined(QUADLIB_NATIVE64_DISABLED) +#ifdef _WIN32 +#define QUADLIB_NATIVE64_ENABLED +#else +#define QUADLIB_NATIVE64_DISABLED +#endif +#endif + +/*****************************************************************************/ +/* VALIDATE NATIVE SUPPORT VS. EMULATION SUPPORT */ +/*****************************************************************************/ + +/* either the host must support 64-bit mode or we must emulate it */ +/* otherwise, the code that manages 64-bit FILETIME values will not work */ + +#if defined(QUADLIB_DISABLED) && defined(QUADLIB_NATIVE64_DISABLED) +#error QUADLIB_DISABLED and QUADLIB_NATIVE64_DISABLED, cannot generate code +#endif + + +/*****************************************************************************/ +/* STATIC (LOCAL) FUNCTION QUALIFIER */ +/* */ +/* use StdTimeConfig.h to set QUADLIB_STATIC */ +/*****************************************************************************/ + +#ifndef QUADLIB_STATIC +#define QUADLIB_STATIC +#endif + +/* stdtimeconfig.h includes appropriate stdint.h header for 32/64 bit types */ + +#define QUADLIB_U32_HIGHBIT 0x80000000 + +/*****************************************************************************/ +/* NATIVE 64 BIT TYPES */ +/*****************************************************************************/ + +#ifdef QUADLIB_NATIVE64_ENABLED +#define QUADLIB_I64N int64_t +#define QUADLIB_U64N uint64_t + +#else /* not QUADLIB_NATIVE64_ENABLED */ + +/* host has NO 64-bit data types */ +/* the following defines are just for compatibility */ +/* but lack 64-bit capacity. _WIN32 always supports I64 */ +/* so this is just a non-Windows issue. */ + +#ifndef QUADLIB_I64N +#define QUADLIB_I64N int32_t /* 32-bit */ +#endif + +#ifndef QUADLIB_U64N +#define QUADLIB_U64N uint32_t /* 32-bit */ +#endif + +#endif /* QUADLIB_NATIVE64_ENABLED */ + +/*****************************************************************************/ +/* QUADLIB_I64 - hi/lo member ordering based on ENDIAN definition above */ +/* QUADLIB_U64 has the same representation as QUADLIB_I64 */ +/* two names are used mainly to document the intended usage */ +/*****************************************************************************/ + +/* Make sure SD_BYTE_ORDER is defined (in glbtypes.h) */ +#if !defined(SD_BYTE_ORDER) +#error SD_BYTE_ORDER not defined +#endif +#if (SD_BYTE_ORDER==SD_LITTLE_ENDIAN) + +typedef struct + { + union + { + int32_t i; + uint32_t u; + } lo; + + union + { + int32_t i; + uint32_t u; + } hi; + } + QUADLIB_I64_TYPE; + +#else /* BIG_ENDIAN */ + +typedef struct + { + union + { + int32_t i; + uint32_t u; + } hi; + + union + { + int32_t i; + uint32_t u; + } lo; + } + QUADLIB_I64_TYPE; + +#endif /* BIG_ENDIAN */ + +#define QUADLIB_U64_TYPE QUADLIB_I64_TYPE + +#ifdef QUADLIB_ENABLED + +/* enabled means 64-bit operations are simulated in software */ + +#define QUADLIB_I64 QUADLIB_I64_TYPE +#define QUADLIB_U64 QUADLIB_I64_TYPE +#define QUADLIB_ZERO {0,0} +#define QUADLIB_U64_MAX {0xFFFFFFFF, 0xFFFFFFFF} + +#if (SD_BYTE_ORDER==SD_LITTLE_ENDIAN) + +#define QUADLIB_I64_MAX {0xFFFFFFFF, 0x7FFFFFFF} +#define QUADLIB_I64_MIN {0x00000000, 0x80000000} + +#else /* BIG_ENDIAN */ + +#define QUADLIB_I64_MAX {0x7FFFFFFF, 0xFFFFFFFF} +#define QUADLIB_I64_MIN {0x00000000, 0x00000000} + +#endif /* BIG_ENDIAN */ + +#else /* not QUADLIB_ENABLED */ + +/* use native 64-bit values for a few compatibility functions */ + +#define QUADLIB_I64 QUADLIB_I64N +#define QUADLIB_U64 QUADLIB_U64N +#define QUADLIB_ZERO 0 +#define QUADLIB_U64_MAX (QUADLIB_U64)0xFFFFFFFFFFFFFFFF +#define QUADLIB_I64_MAX (QUADLIB_I64)0x7FFFFFFFFFFFFFFF +#define QUADLIB_I64_MIN (QUADLIB_I64)0x8000000000000000 + +#endif /* QUADLIB_ENABLED */ + + +#ifdef _WCHAR_T_DEFINED +typedef wchar_t QUADLIB_WCHAR; +#else +typedef unsigned short QUADLIB_WCHAR; +#endif + +#define QUADLIB_STRING_LEN 20 + + +typedef struct + { + char str [QUADLIB_STRING_LEN+1]; + } +QUADLIB_STRINGA; + + +typedef struct + { + QUADLIB_WCHAR str [QUADLIB_STRING_LEN+1]; + } +QUADLIB_STRINGW; + + +/*****************************************************************************/ +/* NOT */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_NOT(x) QuadLibI64Not(x) +#define QUADLIB_U64_NOT(x) QuadLibU64Not(x) + +#define QuadLibI64Not(x) QuadLibU64Not(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Not (QUADLIB_U64 x); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_NOT(x) (~x) +#define QUADLIB_U64_NOT(x) (~x) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* AND */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_AND(x,y) QuadLibI64And(x,y) +#define QUADLIB_U64_AND(x,y) QuadLibU64And(x,y) +#define QUADLIB_I64_AND_EQ(x,y) x = QuadLibI64And(x,y) +#define QUADLIB_U64_AND_EQ(x,y) x = QuadLibU64And(x,y) + +#define QUADLIB_I64_ANDNOT(x,y) QuadLibI64AndNot(x,y) +#define QUADLIB_U64_ANDNOT(x,y) QuadLibU64AndNot(x,y) +#define QUADLIB_I64_ANDNOT_EQ(x,y) x = QuadLibI64AndNot(x,y) +#define QUADLIB_U64_ANDNOT_EQ(x,y) x = QuadLibU64AndNot(x,y) + +#define QuadLibI64And(x,y) QuadLibU64And(x,y) +#define QuadLibI64AndNot(x) QuadLibU64AndNot(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64And ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64AndNot ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_AND(x,y) (x & y) +#define QUADLIB_U64_AND(x,y) (x & y) +#define QUADLIB_I64_AND_EQ(x,y) x &= y +#define QUADLIB_U64_AND_EQ(x,y) x &= y + +#define QUADLIB_I64_ANDNOT(x,y) (x & (~y)) +#define QUADLIB_U64_ANDNOT(x,y) (x & (~y)) +#define QUADLIB_I64_ANDNOT_EQ(x,y) x = x & (~y) +#define QUADLIB_U64_ANDNOT_EQ(x,y) x = x & (~y) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* OR */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_OR(x,y) QuadLibI64Or(x,y) +#define QUADLIB_U64_OR(x,y) QuadLibU64Or(x,y) +#define QUADLIB_I64_OR_EQ(x,y) x = QuadLibI64Or(x,y) +#define QUADLIB_U64_OR_EQ(x,y) x = QuadLibU64Or(x,y) + +#define QUADLIB_I64_ORNOT(x,y) QuadLibI64OrNot(x,y) +#define QUADLIB_U64_ORNOT(x,y) QuadLibU64OrNot(x,y) +#define QUADLIB_I64_ORNOT_EQ(x,y) x = QuadLibI64OrNot(x,y) +#define QUADLIB_U64_ORNOT_EQ(x,y) x = QuadLibU64OrNot(x,y) + +#define QuadLibI64Or(x,y) QuadLibU64Or(x,y) +#define QuadLibI64OrNot(x) QuadLibU64OrNot(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Or ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64OrNot ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_OR(x,y) (x | y) +#define QUADLIB_U64_OR(x,y) (x | y) +#define QUADLIB_I64_OR_EQ(x,y) x |= y +#define QUADLIB_U64_OR_EQ(x,y) x |= y + +#define QUADLIB_I64_ORNOT(x,y) (x | (~y)) +#define QUADLIB_U64_ORNOT(x,y) (x | (~y)) +#define QUADLIB_I64_ORNOT_EQ(x,y) x = x | (~y) +#define QUADLIB_U64_ORNOT_EQ(x,y) x = x | (~y) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* XOR */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_XOR(x,y) QuadLibI64Xor(x,y) +#define QUADLIB_U64_XOR(x,y) QuadLibU64Xor(x,y) +#define QUADLIB_I64_XOR_EQ(x,y) x = QuadLibI64Xor(x,y) +#define QUADLIB_U64_XOR_EQ(x,y) x = QuadLibU64Xor(x,y) + +#define QUADLIB_I64_XORNOT(x,y) QuadLibI64XorNot(x,y) +#define QUADLIB_U64_XORNOT(x,y) QuadLibU64XorNot(x,y) +#define QUADLIB_I64_XORNOT_EQ(x,y) x = QuadLibI64XorNot(x,y) +#define QUADLIB_U64_XORNOT_EQ(x,y) x = QuadLibU64XorNot(x,y) + +#define QuadLibI64Xor(x,y) QuadLibU64Xor(x,y) +#define QuadLibI64XorNot(x) QuadLibU64XorNot(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Xor ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64XorNot ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_XOR(x,y) (x ^ y) +#define QUADLIB_U64_XOR(x,y) (x ^ y) +#define QUADLIB_I64_XOR_EQ(x,y) x ^= y +#define QUADLIB_U64_XOR_EQ(x,y) x ^= y + +#define QUADLIB_I64_XORNOT(x,y) (x ^ (~y)) +#define QUADLIB_U64_XORNOT(x,y) (x ^ (~y)) +#define QUADLIB_I64_XORNOT_EQ(x,y) x = x ^ (~y) +#define QUADLIB_U64_XORNOT_EQ(x,y) x = x ^ (~y) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* ADD */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_ADD(x,y) QuadLibI64Add(x,y) +#define QUADLIB_U64_ADD(x,y) QuadLibU64Add(x,y) +#define QUADLIB_I64_ADD_EQ(x,y) x = QuadLibI64Add(x,y) +#define QUADLIB_U64_ADD_EQ(x,y) x = QuadLibU64Add(x,y) + +#define QUADLIB_I64_ADD1(x) QuadLibI64Add1(x) +#define QUADLIB_U64_ADD1(x) QuadLibU64Add1(x) +#define QUADLIB_I64_ADD1_EQ(x) x = QuadLibI64Add1(x) +#define QUADLIB_U64_ADD1_EQ(x) x = QuadLibU64Add1(x) + +#define QuadLibI64Add(x,y) QuadLibU64Add(x,y) +#define QuadLibI64Add1(x) QuadLibU64Add1(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Add ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Add1 ( + QUADLIB_U64 /*I*/ x); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_ADD(x,y) (x + y) +#define QUADLIB_U64_ADD(x,y) (x + y) +#define QUADLIB_I64_ADD_EQ(x,y) x += y +#define QUADLIB_U64_ADD_EQ(x,y) x += y + +#define QUADLIB_I64_ADD1(x) (x + y) +#define QUADLIB_U64_ADD1(x) (x + y) +#define QUADLIB_I64_ADD1_EQ(x) x++ +#define QUADLIB_U64_ADD1_EQ(x) x++ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* SUB */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_SUB(x,y) QuadLibI64Sub(x,y) +#define QUADLIB_U64_SUB(x,y) QuadLibU64Sub(x,y) +#define QUADLIB_I64_SUB_EQ(x,y) x = QuadLibI64Sub(x,y) +#define QUADLIB_U64_SUB_EQ(x,y) x = QuadLibU64Sub(x,y) + +#define QUADLIB_I64_SUB1(x) QuadLibI64Sub1(x) +#define QUADLIB_U64_SUB1(x) QuadLibU64Sub1(x) +#define QUADLIB_I64_SUB1_EQ(x) x = QuadLibI64Sub1(x) +#define QUADLIB_U64_SUB1_EQ(x) x = QuadLibU64Sub1(x) + +#define QuadLibI64Sub(x,y) QuadLibU64Sub(x,y) +#define QuadLibI64Sub1(x) QuadLibU64Sub1(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Sub ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Sub1 ( + QUADLIB_U64 /*I*/ x); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_SUB(x,y) (x - y) +#define QUADLIB_U64_SUB(x,y) (x - y) +#define QUADLIB_I64_SUB_EQ(x,y) x -= y +#define QUADLIB_U64_SUB_EQ(x,y) x -= y + +#define QUADLIB_I64_SUB1(x) (x - y) +#define QUADLIB_U64_SUB1(x) (x - y) +#define QUADLIB_I64_SUB1_EQ(x) x-- +#define QUADLIB_U64_SUB1_EQ(x) x-- + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* NEG */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_NEG(x) QuadLibI64Neg(x) +#define QUADLIB_U64_NEG(x) QuadLibU64Neg(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Neg (QUADLIB_U64 x); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_NEG(x) (-x) +#define QUADLIB_U64_NEG(x) (-x) + +#endif /* QUADLIB_ENABLED */ + +#define QuadLibI64Neg(x) QuadLibU64Neg(x) + +/*****************************************************************************/ +/* ABS */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_ABS(x) QuadLibI64Abs(x) +#define QUADLIB_U64_ABS(x) QuadLibU64Abs(x) + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_ABS(x) ((x) >= 0 ? (x) : -(x)) +#define QUADLIB_U64_ABS(x) ((x) >= 0 ? (x) : -(x)) + +#endif /* QUADLIB_ENABLED */ + +#define QuadLibI64Abs(x) QuadLibU64Abs(x) + +/* quad abs function always defined */ + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Abs (QUADLIB_U64 x); + +/*****************************************************************************/ +/* CMP */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_EQ(x,y) QuadLibI64EQ(x,y) +#define QUADLIB_I64_NE(x,y) QuadLibI64NE(x,y) +#define QUADLIB_I64_GT(x,y) QuadLibI64GT(x,y) +#define QUADLIB_I64_GE(x,y) QuadLibI64GE(x,y) +#define QUADLIB_I64_LT(x,y) QuadLibI64LT(x,y) +#define QUADLIB_I64_LE(x,y) QuadLibI64LE(x,y) + +#define QUADLIB_U64_EQ(x,y) QuadLibU64EQ(x,y) +#define QUADLIB_U64_NE(x,y) QuadLibU64NE(x,y) +#define QUADLIB_U64_GT(x,y) QuadLibU64GT(x,y) +#define QUADLIB_U64_GE(x,y) QuadLibU64GE(x,y) +#define QUADLIB_U64_LT(x,y) QuadLibU64LT(x,y) +#define QUADLIB_U64_LE(x,y) QuadLibU64LE(x,y) + +#define QuadLibI64EQ(x,y) (QuadLibI64Cmp(x,y)==0) +#define QuadLibI64NE(x,y) (QuadLibI64Cmp(x,y)!=0) +#define QuadLibI64GT(x,y) (QuadLibI64Cmp(x,y)> 0) +#define QuadLibI64GE(x,y) (QuadLibI64Cmp(x,y)>=0) +#define QuadLibI64LT(x,y) (QuadLibI64Cmp(x,y)< 0) +#define QuadLibI64LE(x,y) (QuadLibI64Cmp(x,y)<=0) + +#define QuadLibU64EQ(x,y) (QuadLibU64Cmp(x,y)==0) +#define QuadLibU64NE(x,y) (QuadLibU64Cmp(x,y)!=0) +#define QuadLibU64GT(x,y) (QuadLibU64Cmp(x,y)> 0) +#define QuadLibU64GE(x,y) (QuadLibU64Cmp(x,y)>=0) +#define QuadLibU64LT(x,y) (QuadLibU64Cmp(x,y)< 0) +#define QuadLibU64LE(x,y) (QuadLibU64Cmp(x,y)<=0) + +QUADLIB_STATIC int32_t QuadLibU64Cmp ( + /*I*/ QUADLIB_U64 x, + /*I*/ QUADLIB_U64 y); + +QUADLIB_STATIC int32_t QuadLibI64Cmp ( + /*I*/ QUADLIB_I64 x, + /*I*/ QUADLIB_I64 y); + +#define QUADLIB_I64_EQ_0(x) (! QUADLIB_I64_NE_0(x)) +#define QUADLIB_I64_NE_0(x) (QUADLIB_U64_HI(x) | QUADLIB_U64_LO(x)) +#define QUADLIB_I64_GT_0(x) (QUADLIB_I64_GE_0(x) && QUADLIB_I64_NE_0(x)) +#define QUADLIB_I64_GE_0(x) (QUADLIB_I64_HI(x) >= 0) +#define QUADLIB_I64_LT_0(x) (QUADLIB_I64_HI(x) < 0) +#define QUADLIB_I64_LE_0(x) (QUADLIB_I64_LT_0(x) || QUADLIB_I64_EQ_0(x)) + +#define QUADLIB_U64_EQ_0(x) (! QUADLIB_U64_NE_0(x)) +#define QUADLIB_U64_NE_0(x) (QUADLIB_U64_HI(x) | QUADLIB_U64_LO(x)) +#define QUADLIB_U64_GT_0(x) (QUADLIB_U64_GE_0(x) && QUADLIB_U64_NE_0(x)) +#define QUADLIB_U64_GE_0(x) (QUADLIB_U64_HI(x) >= 0) + +#if 0 +#define QUADLIB_U64_LT_0(x) (QUADLIB_U64_HI(x) < 0) +#define QUADLIB_U64_LE_0(x) (QUADLIB_U64_LT_0(x) || QUADLIB_U64_EQ_0(x)) +#endif + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_EQ(x,y) ((x) == (y)) +#define QUADLIB_I64_NE(x,y) ((x) != (y)) +#define QUADLIB_I64_GT(x,y) ((x) > (y)) +#define QUADLIB_I64_GE(x,y) ((x) >= (y)) +#define QUADLIB_I64_LT(x,y) ((x) < (y)) +#define QUADLIB_I64_LE(x,y) ((x) <= (y)) + +#define QUADLIB_U64_EQ(x,y) ((x) == (y)) +#define QUADLIB_U64_NE(x,y) ((x) != (y)) +#define QUADLIB_U64_GT(x,y) ((x) > (y)) +#define QUADLIB_U64_GE(x,y) ((x) >= (y)) +#define QUADLIB_U64_LT(x,y) ((x) < (y)) +#define QUADLIB_U64_LE(x,y) ((x) <= (y)) + +#define QUADLIB_I64_EQ_0(x) ((x) == 0) +#define QUADLIB_I64_NE_0(x) ((x) != 0) +#define QUADLIB_I64_GT_0(x) ((x) > 0) +#define QUADLIB_I64_GE_0(x) ((x) >= 0) +#define QUADLIB_I64_LT_0(x) ((x) < 0) +#define QUADLIB_I64_LE_0(x) ((x) <= 0) + +#define QUADLIB_U64_EQ_0(x) ((x) == 0) +#define QUADLIB_U64_NE_0(x) ((x) != 0) +#define QUADLIB_U64_GT_0(x) ((x) > 0) +#define QUADLIB_U64_GE_0(x) ((x) >= 0) + +#if 0 +#define QUADLIB_U64_LT_0(x) ((x) < 0) +#define QUADLIB_U64_LE_0(x) ((x) <= 0) +#endif + +#endif /* QUADLIB_ENABLED */ + + +/*****************************************************************************/ +/* I32 OVERFLOW CHECK */ +/*****************************************************************************/ + + +#define QUADLIB_I64_NOT_OVERFLOW_I32(x) \ + ( ((QUADLIB_I64_HI(x) == 0) && (QUADLIB_I64_LO(x) >= 0)) \ + || ((QUADLIB_I64_HI(x) == -1) && (QUADLIB_I64_LO(x) < 0)) ) /**/ + + +#define QUADLIB_I64_OVERFLOW_I32(x) (! QUADLIB_I64_NOT_OVERFLOW_I32(x)) + + +#define QUADLIB_U64_NOT_OVERFLOW_I32(x) \ + ((QUADLIB_I64_HI(x) == 0) && (QUADLIB_I64_LO(x) >= 0)) /**/ + + +#define QUADLIB_U64_OVERFLOW_I32(x) (! QUADLIB_U64_NOT_OVERFLOW_I32(x)) + + +#define QUADLIB_I64_OVERFLOW_U32(x) (QUADLIB_I64_HI(x) != 0) +#define QUADLIB_U64_OVERFLOW_U32(x) (QUADLIB_I64_HI(x) != 0) + + +/*****************************************************************************/ +/* SHL */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_SHL(x,n) QuadLibU64SHL(x,n) +#define QUADLIB_U64_SHL(x,n) QuadLibU64SHL(x,n) + +#define QUADLIB_I64_SHL1(x) QuadLibU64SHL1(x) +#define QUADLIB_U64_SHL1(x) QuadLibU64SHL1(x) + +#define QUADLIB_I64_SHL4(x) QuadLibU64SHL4(x) +#define QUADLIB_U64_SHL4(x) QuadLibU64SHL4(x) + +#define QUADLIB_I64_SHL_EQ(x,n) x = QUADLIB_I64_SHL(x,n) +#define QUADLIB_U64_SHL_EQ(x,n) x = QUADLIB_U64_SHL(x,n) + +#define QUADLIB_I64_SHL1_EQ(x) x = QUADLIB_I64_SHL1(x) +#define QUADLIB_U64_SHL1_EQ(x) x = QUADLIB_U64_SHL1(x) + +#define QUADLIB_I64_SHL4_EQ(x) x = QUADLIB_I64_SHL4(x) +#define QUADLIB_U64_SHL4_EQ(x) x = QUADLIB_U64_SHL4(x) + +#define QUADLIB_I64_SHL1_EQ_INLINE(x) QUADLIB_U64_SHL1_EQ_INLINE(x) + + +#define QUADLIB_U64_SHL1_EQ_INLINE(x) \ + { \ + x.hi.u <<= 1; \ + if (x.lo.i < 0) \ + { \ + x.hi.u++; \ + } \ + x.lo.u <<= 1; \ + } /**/ + + +#define QUADLIB_I64_SHL4_EQ_INLINE(x) QUADLIB_U64_SHL4_EQ_INLINE(x) + + +#define QUADLIB_U64_SHL4_EQ_INLINE(x) \ + { \ + x.hi.u = (x.hi.u << 4) | (x.lo.u >> 28); \ + x.lo.u <<= 4; \ + } /**/ + + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHL ( + QUADLIB_U64 /*I*/ value, + int32_t /*I*/ shift); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHL1 ( + QUADLIB_U64 /*I*/ value); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHL4 ( + QUADLIB_U64 /*I*/ value); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_SHL(x,n) ((x) << n) +#define QUADLIB_U64_SHL(x,n) ((x) << n) + +#define QUADLIB_I64_SHL1(x) ((x) << 1) +#define QUADLIB_U64_SHL1(x) ((x) << 1) + +#define QUADLIB_I64_SHL4(x) ((x) << 4) +#define QUADLIB_U64_SHL4(x) ((x) << 4) + +#define QUADLIB_I64_SHL_EQ(x,n) x = ((x) << n) +#define QUADLIB_U64_SHL_EQ(x,n) x = ((x) << n) + +#define QUADLIB_I64_SHL1_EQ(x) x <<= 1 +#define QUADLIB_U64_SHL1_EQ(x) x <<= 1 + +#define QUADLIB_I64_SHL1_EQ_INLINE(x) QUADLIB_I64_SHL1_EQ(x) +#define QUADLIB_U64_SHL1_EQ_INLINE(x) QUADLIB_U64_SHL1_EQ(x) + +#define QUADLIB_I64_SHL4_EQ(x) x <<= 4 +#define QUADLIB_U64_SHL4_EQ(x) x <<= 4 + +#define QUADLIB_I64_SHL4_EQ_INLINE(x) QUADLIB_I64_SHL4_EQ(x) +#define QUADLIB_U64_SHL4_EQ_INLINE(x) QUADLIB_U64_SHL4_EQ(x) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* SHR */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_SHR(x,n) QuadLibI64SHR(x,n) +#define QUADLIB_U64_SHR(x,n) QuadLibU64SHR(x,n) + +#define QUADLIB_I64_SHR1(x) QuadLibI64SHR1(x) +#define QUADLIB_U64_SHR1(x) QuadLibU64SHR1(x) + +#define QUADLIB_I64_SHR4(x) QuadLibI64SHR4(x) +#define QUADLIB_U64_SHR4(x) QuadLibU64SHR4(x) + +#define QUADLIB_I64_SHR_EQ(x,n) x = QUADLIB_I64_SHR(x,n) +#define QUADLIB_U64_SHR_EQ(x,n) x = QUADLIB_U64_SHR(x,n) + +#define QUADLIB_I64_SHR1_EQ(x) x = QUADLIB_I64_SHR1(x) +#define QUADLIB_U64_SHR1_EQ(x) x = QUADLIB_U64_SHR1(x) + +#define QUADLIB_I64_SHR4_EQ(x) x = QUADLIB_I64_SHR4(x) +#define QUADLIB_U64_SHR4_EQ(x) x = QUADLIB_U64_SHR4(x) + + +#define QUADLIB_I64_SHR1_EQ_INLINE(x) \ + { \ + x.lo.u >>= 1; \ + if (x.hi.u & 1) \ + { \ + x.lo.u |= QUADLIB_U32_HIGHBIT; \ + } \ + x.hi.i >>= 1; /* signed */ \ + } /**/ + + +#define QUADLIB_U64_SHR1_EQ_INLINE(x) \ + { \ + x.lo.u >>= 1; \ + if (x.hi.u & 1) \ + { \ + x.lo.u |= QUADLIB_U32_HIGHBIT; \ + } \ + x.hi.u >>= 1; /* unsigned */ \ + } /**/ + + +#define QUADLIB_I64_SHR4_EQ_INLINE(x) \ + { \ + x.lo.u = (x.lo.u >> 4) | (x.hi.u << 28); \ + x.hi.i >>= 4; /* signed */ \ + } /**/ + + +#define QUADLIB_U64_SHR4_EQ_INLINE(x) \ + { \ + x.lo.u = (x.lo.u >> 4) | (x.hi.u << 28); \ + x.hi.u >>= 4; /* unsigned */ \ + } /**/ + + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64SHR ( + QUADLIB_U64 /*I*/ value, + int32_t /*I*/ shift); + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64SHR1 ( + QUADLIB_U64 /*I*/ value); + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64SHR4 ( + QUADLIB_U64 /*I*/ value); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHR ( + QUADLIB_U64 /*I*/ value, + int32_t /*I*/ shift); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHR1 ( + QUADLIB_U64 /*I*/ value); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHR4 ( + QUADLIB_U64 /*I*/ value); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_SHR(x,n) ((QUADLIB_I64)x) >> n +#define QUADLIB_U64_SHR(x,n) ((QUADLIB_U64)x) >> n + +#define QUADLIB_I64_SHR1(x) ((QUADLIB_I64)x) >> 1 +#define QUADLIB_U64_SHR1(x) ((QUADLIB_U64)x) >> 1 + +#define QUADLIB_I64_SHR4(x) ((QUADLIB_I64)x) >> 4 +#define QUADLIB_U64_SHR4(x) ((QUADLIB_U64)x) >> 4 + +#define QUADLIB_I64_SHR_EQ(x,n) x = ((QUADLIB_I64)x) >> n +#define QUADLIB_U64_SHR_EQ(x,n) x = ((QUADLIB_U64)x) >> n + +#define QUADLIB_I64_SHR1_EQ(x) x = ((QUADLIB_I64)x) >> 1 +#define QUADLIB_U64_SHR1_EQ(x) x = ((QUADLIB_U64)x) >> 1 + +#define QUADLIB_I64_SHR4_EQ(x) x = ((QUADLIB_I64)x) >> 4 +#define QUADLIB_U64_SHR4_EQ(x) x = ((QUADLIB_U64)x) >> 4 + +#define QUADLIB_I64_SHR1_EQ_INLINE(x) QUADLIB_I64_SHR1_EQ(x) +#define QUADLIB_U64_SHR1_EQ_INLINE(x) QUADLIB_U64_SHR1_EQ(x) + +#define QUADLIB_I64_SHR4_EQ_INLINE(x) QUADLIB_I64_SHR4_EQ(x) +#define QUADLIB_U64_SHR4_EQ_INLINE(x) QUADLIB_U64_SHR4_EQ(x) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* CONVERT */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_CASTI64N(x) QuadLibI64CastI64N(&x,sizeof(x)) +#define QUADLIB_U64_CASTU64N(x) QuadLibU64CastU64N(&x,sizeof(x)) + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64CastI64N(void * x, size_t n); +QUADLIB_STATIC QUADLIB_U64 QuadLibU64CastU64N(void * x, size_t n); + +#define QUADLIB_I64N_CASTI64(x) QuadLibI64NCastI64(x) +#define QUADLIB_U64N_CASTU64(x) QuadLibU64NCastU64(x) + +QUADLIB_STATIC QUADLIB_I64N QuadLibI64NCastI64(QUADLIB_I64 x); +QUADLIB_STATIC QUADLIB_U64N QuadLibU64NCastU64(QUADLIB_U64 x); + + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_CASTI64N(x) ((QUADLIB_I64)x) +#define QUADLIB_U64_CASTU64N(x) ((QUADLIB_U64)x) +#define QUADLIB_I64N_CASTI64(x) ((QUADLIB_I64N)x) +#define QUADLIB_U64N_CASTU64(x) ((QUADLIB_U64N)x) + +#endif /* QUADLIB_ENABLED */ + + +/*****************************************************************************/ +/* CAST */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_CASTI32(x) QuadLibI64CastI32((int32_t)x) +#define QUADLIB_I64_CASTU32(x) QuadLibI64CastI32((uint32_t)x) + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64CastI32 (int32_t x); + +#define QUADLIB_U64_CASTU32(x) QuadLibU64CastU32((uint32_t)x) +#define QUADLIB_U64_CASTI32(x) QuadLibU64CastU32((int32_t)x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64CastU32 (uint32_t x); + +#define QUADLIB_I32_CASTI64(x) QuadLibI32CastI64(x) +#define QUADLIB_U32_CASTI64(x) ((QUADLIB_U64) QuadLibI32CastI64(x)) + +QUADLIB_STATIC int32_t QuadLibI32CastI64 (QUADLIB_I64 x); + +#define QUADLIB_U32_CASTU64(x) QuadLibU32CastU64(x) +#define QUADLIB_I32_CASTU64(x) ((int32_t) QuadLibU32CastU64(x)) + +QUADLIB_STATIC uint32_t QuadLibU32CastU64 (QUADLIB_U64 x); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_CASTI32(x) ((QUADLIB_I64) (x)) +#define QUADLIB_I64_CASTU32(x) ((QUADLIB_I64) (x)) + +#define QUADLIB_U64_CASTI32(x) ((QUADLIB_U64) (x)) +#define QUADLIB_U64_CASTU32(x) ((QUADLIB_U64) (x)) + +#define QUADLIB_I32_CASTI64(x) ((int32_t) (x)) +#define QUADLIB_I32_CASTU64(x) ((int32_t) (x)) + +#define QUADLIB_U32_CASTI64(x) ((uint32_t) (x)) +#define QUADLIB_U32_CASTU64(x) ((uint32_t) (x)) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* GET/SET */ +/*****************************************************************************/ + +#define QUADLIB_I64_HI(x) (*(QUADLIB_I64_TYPE *)(&x)).hi.i +#define QUADLIB_U64_HI(x) (*(QUADLIB_U64_TYPE *)(&x)).hi.u +#define QUADLIB_I64_LO(x) (*(QUADLIB_I64_TYPE *)(&x)).lo.i +#define QUADLIB_U64_LO(x) (*(QUADLIB_U64_TYPE *)(&x)).lo.u + +#define FILETIME_TO_QUADLIB_I64 FILETIME_TO_QUADLIB_U64 + + +#define FILETIME_TO_QUADLIB_U64(f,q) \ + (*(QUADLIB_U64_TYPE *)(q)).lo.u = (f)->dwLowDateTime; \ + (*(QUADLIB_U64_TYPE *)(q)).hi.u = (f)->dwHighDateTime /**/ + + +#define QUADLIB_I64_TO_FILETIME QUADLIB_U64_TO_FILETIME + + +#define QUADLIB_U64_TO_FILETIME(q,f) \ + (f)->dwLowDateTime = (*(QUADLIB_U64_TYPE *)(q)).lo.u; \ + (f)->dwHighDateTime = (*(QUADLIB_U64_TYPE *)(q)).hi.u /**/ + + +/*****************************************************************************/ +/* MUL */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_MUL(x,y) QuadLibI64Mul(x,y) +#define QUADLIB_U64_MUL(x,y) QuadLibU64Mul(x,y) +#define QUADLIB_I64_MUL_EQ(x,y) x = QuadLibI64Mul(x,y) +#define QUADLIB_U64_MUL_EQ(x,y) x = QuadLibU64Mul(x,y) + +#define QUADLIB_I64_MUL10(x) QuadLibI64Mul10(x) +#define QUADLIB_U64_MUL10(x) QuadLibU64Mul10(x) +#define QUADLIB_I64_MUL10_EQ(x) x = QuadLibI64Mul10(x) +#define QUADLIB_U64_MUL10_EQ(x) x = QuadLibU64Mul10(x) + +#define QuadLibI64Mul(x,y) QuadLibU64Mul(x,y) +#define QuadLibI64Mul10(x) QuadLibU64Mul10(x) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Mul ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Mul10 ( + QUADLIB_U64 /*I*/ x); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_MUL(x,y) (x * y) +#define QUADLIB_U64_MUL(x,y) (x * y) +#define QUADLIB_I64_MUL_EQ(x,y) x *= y +#define QUADLIB_U64_MUL_EQ(x,y) x *= y + +#define QUADLIB_I64_MUL10(x) (x * ((QUADLIB_I64) 10)) +#define QUADLIB_U64_MUL10(x) (x * ((QUADLIB_U64) 10)) +#define QUADLIB_I64_MUL10_EQ(x) x *= ((QUADLIB_I64) 10) +#define QUADLIB_U64_MUL10_EQ(x) x *= ((QUADLIB_U64) 10) + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* STR TO I64/U64 */ +/*****************************************************************************/ + +QUADLIB_STATIC QUADLIB_I64 StrAToQuadLibI64 ( + char * /*I*/ str); + +QUADLIB_STATIC QUADLIB_U64 StrAToQuadLibU64 ( + char * /*I*/ str); + +#ifdef QUADLIB_NATIVE64_ENABLED + +#define QUADLIB_I64_NUM(x) (x) +#define QUADLIB_U64_NUM(x) (x) + +#else /* not QUADLIB_NATIVE64_ENABLED */ + +#define QUADLIB_I64_NUM(x) StrAToQuadLibI64 (#x) +#define QUADLIB_U64_NUM(x) StrAToQuadLibU64 (#x) + +#endif /* QUADLIB_NATIVE64_ENABLED */ + + +/*****************************************************************************/ +/* I64/U64 TO STR */ +/*****************************************************************************/ + + +QUADLIB_STATIC void QuadLibU64ToFixedStrA ( + QUADLIB_U64 /*I*/ qValue, + QUADLIB_STRINGA * /*O*/ pString); + + +QUADLIB_STATIC void QuadLibI64ToFixedStrA ( + QUADLIB_I64 /*I*/ qValue, + QUADLIB_STRINGA * /*O*/ pString); + + +QUADLIB_STATIC void QuadLibU64ToStrA ( + QUADLIB_U64 /*I*/ qValue, + QUADLIB_STRINGA * /*O*/ pString); + + +QUADLIB_STATIC void QuadLibI64ToStrA ( + QUADLIB_I64 /*I*/ qValue, + QUADLIB_STRINGA * /*O*/ pString); + + +/*****************************************************************************/ +/* DIV/MOD */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_I64_DIV(x,y) QuadLibI64Div(x,y) +#define QUADLIB_U64_DIV(x,y) QuadLibU64Div(x,y) +#define QUADLIB_I64_DIV_EQ(x,y) x = QuadLibI64Div(x,y) +#define QUADLIB_U64_DIV_EQ(x,y) x = QuadLibU64Div(x,y) + +#define QUADLIB_I64_MOD(x,y) QuadLibI64Mod(x,y) +#define QUADLIB_U64_MOD(x,y) QuadLibU64Mod(x,y) +#define QUADLIB_I64_MOD_EQ(x,y) x = QuadLibI64Mod(x,y) +#define QUADLIB_U64_MOD_EQ(x,y) x = QuadLibU64Mod(x,y) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64DivMod ( + QUADLIB_U64 u64Dividend, + QUADLIB_U64 u64Divisor, + QUADLIB_U64 *pu64Remainder); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Div ( + QUADLIB_U64 u64Dividend, + QUADLIB_U64 u64Divisor); + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Mod ( + QUADLIB_U64 u64Dividend, + QUADLIB_U64 u64Divisor); + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64DivMod ( + QUADLIB_I64 s64Dividend, + QUADLIB_I64 s64Divisor, + QUADLIB_I64 *ps64Remainder); + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64Div ( + QUADLIB_I64 s64Dividend, + QUADLIB_I64 s64Divisor); + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64Mod ( + QUADLIB_I64 s64Dividend, + QUADLIB_I64 s64Divisor); + +#else /* not QUADLIB_ENABLED */ + +#define QUADLIB_I64_DIV(x,y) (x / y) +#define QUADLIB_U64_DIV(x,y) (x / y) +#define QUADLIB_I64_DIV_EQ(x,y) x /= y +#define QUADLIB_U64_DIV_EQ(x,y) x /= y + +#define QUADLIB_I64_MOD(x,y) (x % y) +#define QUADLIB_U64_MOD(x,y) (x % y) +#define QUADLIB_I64_MOD_EQ(x,y) x %= y +#define QUADLIB_U64_MOD_EQ(x,y) x %= y + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64DivMod ( + QUADLIB_U64 u64Dividend, + QUADLIB_U64 u64Divisor, + QUADLIB_U64 *pu64Remainder); + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64DivMod ( + QUADLIB_I64 s64Dividend, + QUADLIB_I64 s64Divisor, + QUADLIB_I64 *ps64Remainder); + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* END */ +/*****************************************************************************/ + +#ifdef __cplusplus +} +#endif + + +#endif /* _STDTIME_QUADLIB_H_B07CB807_8BFC_41B3_872E_EDD251FD6AEB_ */ + diff --git a/mmslib/inc/stdtime_stdint.h b/mmslib/inc/stdtime_stdint.h new file mode 100644 index 0000000..8aab3e8 --- /dev/null +++ b/mmslib/inc/stdtime_stdint.h @@ -0,0 +1,237 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : stdint.h */ +/* PLATFORM : Microsoft Windows W32 platform */ +/* PRODUCT(S) : general usage */ +/* */ +/* MODULE DESCRIPTION: */ +/* Implementation of C99 standard header file "stdint.h" */ +/* */ +/* Implementation is based on ISO/IEC 9899:1999 TC2 Programming Language C */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */ +/* 02/25/06 RLH 01 Created */ +/*****************************************************************************/ + +/* STDINT.H for Microsoft Windows */ + + +#ifndef _STDTIME_STDINT_H_1BA49070_CC19_4880_8283_69F38C4F8F59_ +#define _STDTIME_STDINT_H_1BA49070_CC19_4880_8283_69F38C4F8F59_ + + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +#if 1 /*defined() */ +/* +// typedef int8_t char; +// typedef int16_t short; +// typedef int32_t int; + +// typedef uint8_t unsigned char; +// typedef uint16_t unsigned short ; +// typedef uint32_t unsigned int; +*/ +/* exact-wide integer types */ + +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; + +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; + +/* minimum-wide integer types */ + +typedef __int8 int_least8_t; +typedef __int16 int_least16_t; +typedef __int32 int_least32_t; +typedef __int64 int_least64_t; + +typedef unsigned __int8 uint_least8_t; +typedef unsigned __int16 uint_least16_t; +typedef unsigned __int32 uint_least32_t; +typedef unsigned __int64 uint_least64_t; + +/* fastest minimum-wide integer types */ + +typedef __int8 int_fast8_t; +typedef __int16 int_fast16_t; +typedef __int32 int_fast32_t; +typedef __int64 int_fast64_t; + +typedef unsigned __int8 uint_fast8_t; +typedef unsigned __int16 uint_fast16_t; +typedef unsigned __int32 uint_fast32_t; +typedef unsigned __int64 uint_fast64_t; + +/* integer types capable of holding object pointers */ + +/* intptr_t, uintptr_t : see stddef.h */ + +/* greatest-width integer types */ + +typedef __int64 intmax_t; +typedef unsigned __int64 uintmax_t; + +#endif +/* macros for limits of exact-width integer types */ +/* only define in C++ if user-requested per C99 standard */ + +#if (!defined(__cplusplus)) || defined(__STDC_LIMIT_MACROS) + +/* fundamental limits : see limits.h */ + +#define INT8_MIN ((int8_t)(SCHAR_MIN)) +#define INT8_MAX ((int8_t)(SCHAR_MAX)) +#define UINT8_MAX ((uint8_t)(UCHAR_MAX)) + +#define INT16_MIN ((int16_t)(SHRT_MIN)) +#define INT16_MAX ((int16_t)(SHRT_MAX)) +#define UINT16_MAX ((uint16_t)(USHRT_MAX)) + +#define INT32_MIN ((int32_t)(INT_MIN)) +#define INT32_MAX ((int32_t)(INT_MAX)) +#define UINT32_MAX ((uint32_t)(UINT_MAX)) + +#define INT64_MIN ((int64_t)(_I64_MIN)) +#define INT64_MAX ((int64_t)(_I64_MAX)) +#define UINT64_MAX ((uint64_t)(_UI64_MAX)) + +/* limits of minimum-width integer types */ + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define UINT_LEAST8_MAX UINT8_MAX + +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define UINT_LEAST16_MAX UINT16_MAX + +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define UINT_LEAST32_MAX UINT32_MAX + +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +/* limits of fastest minimum-width integer types */ + +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define UINT_FAST8_MAX UINT8_MAX + +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define UINT_FAST16_MAX UINT16_MAX + +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST64_MAX UINT64_MAX + +/* limits of greatest-width integer types */ + +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +/* limits of other integer types */ + +#ifndef PTRDIFF_MIN +#ifdef _WIN64 +#define PTRDIFF_MIN INT64_MIN +#else +#define PTRDIFF_MIN INT32_MIN +#endif +#endif + +#ifndef PTRDIFF_MAX +#ifdef _WIN64 +#define PTRDIFF_MAX INT64_MAX +#else +#define PTRDIFF_MAX INT32_MAX +#endif +#endif + +#ifndef SIG_ATOMIC_MIN +#define SIG_ATOMIC_MIN INT32_MIN +#endif + +#ifndef SIG_ATOMIC_MAX +#define SIG_ATOMIC_MAX INT32_MAX +#endif + +#ifndef SIZE_MAX +#ifdef _WIN64 +#define SIZE_MAX UINT64_MAX +#else +#define SIZE_MAX UINT32_MAX +#endif +#endif + +#ifndef WCHAR_MIN +#define WCHAR_MIN ((wchar_t)(0)) +#endif + +#ifndef WCHAR_MAX +#define WCHAR_MAX ((wchar_t)(USHRT_MAX)) +#endif + +#ifndef WINT_MIN +#define WINT_MIN ((wint_t)(0)) +#endif + +#ifndef WINT_MAX +#define WINT_MAX ((wint_t)(USHRT_MAX)) +#endif + +#endif /* (!defined(__cplusplus)) || defined(__STDC_LIMIT_MACROS) */ + + +/* macros for minimum-width integer constants */ +/* only define in C++ if user-requested per C99 standard */ + +#if (!defined(__cplusplus)) || defined(__STDC_CONSTANT_MACROS) + +#define INT8_C(x) (int8_t)(x) +#define INT16_C(x) (int16_t)(x) +#define INT32_C(x) (int32_t)(x) +#define INT64_C(x) (int64_t)(x##i64) + +#define UINT8_C(x) (uint8_t)(x##u) +#define UINT16_C(x) (uint16_t)(x##u) +#define UINT32_C(x) (uint32_t)(x##u) +#define UINT64_C(x) (uint64_t)(x##ui64) + +#define INTMAX_C(x) INT64_C(x) +#define UINTMAX_C(x) UINT64_C(x) + +#endif /* (!defined(__cplusplus)) || defined(__STDC_CONSTANT_MACROS) */ + + +#ifdef __cplusplus +} +#endif + +#endif /* _STDTIME_STDINT_H_1BA49070_CC19_4880_8283_69F38C4F8F59_ */ + diff --git a/mmslib/inc/stdtime_timezone_csv.h b/mmslib/inc/stdtime_timezone_csv.h new file mode 100644 index 0000000..cdf2c26 --- /dev/null +++ b/mmslib/inc/stdtime_timezone_csv.h @@ -0,0 +1,381 @@ +{{"ID;CC","STDABBR","STDNAME","DSTABBR","DSTNAME","GMToffset","DSTadjustment","DSTStartDaterule","Starttime","DSTEnddaterule","Endtime"}}, +{{"Africa/Abidjan;CI","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Accra;GH","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Addis_Ababa;ET","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Algiers;DZ","CET","CET","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Asmera;ER","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Bamako;ML","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Bangui;CF","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Banjul;GM","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Bissau;GW","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Blantyre;MW","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Brazzaville;CG","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Bujumbura;BI","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Cairo;EG","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;5;4","+00:00:00","-1;5;9","+00:00:00"}}, +{{"Africa/Casablanca;MA","WET","WET","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Ceuta;ES","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Africa/Conakry;GN","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Dakar;SN","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Dar_es_Salaam;TZ","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Djibouti;DJ","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Douala;CM","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/El_Aaiun;EH","WET","WET","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Freetown;SL","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Gaborone;BW","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Harare;ZW","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Johannesburg;ZA","SAST","SAST","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Kampala;UG","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Khartoum;SD","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Kigali;RW","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Kinshasa;CF","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Lagos;NG","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Libreville;GA","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Lome;TG","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Luanda;AO","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Lubumbashi;CF","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Lusaka;ZM","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Malabo;GQ","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Maputo;MZ","CAT","CAT","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Maseru;LS","SAST","SAST","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Mbabane;SZ","SAST","SAST","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Mogadishu;SO","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Monrovia;LR","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Nairobi;KE","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Ndjamena;TD","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Niamey;NE","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Nouakchott;MR","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Ouagadougou;BF","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Porto-Novo;BJ","WAT","WAT","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Sao_Tome;ST","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Timbuktu;ML","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Tripoli;LY","EET","EET","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Tunis;TN","CET","CET","","","+01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Africa/Windhoek;NA","WAT","WAT","WAST","WAST","+01:00:00","+01:00:00","1;0;9","+02:00:00","1;0;4","+02:00:00"}}, +{{"America/Adak;US/AK","HAST","HAST","HADT","HADT","-10:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Anchorage;US/AK","AKST","AKST","AKDT","AKDT","-09:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Anguilla;AI","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Antigua;AG","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Araguaina;BR","BRT","BRT","BRST","BRST","-03:00:00","+01:00:00","1;0;11","+00:00:00","-1;0;2","+00:00:00"}}, +{{"America/Aruba;AW","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Asuncion;PY","PYT","PYT","PYST","PYST","-04:00:00","+01:00:00","1;0;10","+00:00:00","1;0;3","+00:00:00"}}, +{{"America/Barbados;BB","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Belem;BR","BRT","BRT","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Belize;BZ","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Boa_Vista;BR","AMT","AMT","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Bogota;CO","COT","COT","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Boise;US/ID","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Buenos_Aires;AR","ART","ART","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Cambridge_Bay;CA/NU","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Cancun;MX","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;5","+02:00:00","-1;0;9","+02:00:00"}}, +{{"America/Caracas;VE","VET","VET","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Catamarca;AR","ART","ART","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Cayenne;GF","GFT","GFT","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Cayman;KY","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Chicago;US/IL","CST","Central Standard Time","CDT","Central Daylight Time","-06:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Chihuahua;MX","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;5","+02:00:00","-1;0;9","+02:00:00"}}, +{{"America/Cordoba;AR","ART","ART","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Costa_Rica;CR","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Cuiaba;BR","AMT","AMT","AMST","AMST","-04:00:00","+01:00:00","1;0;11","+00:00:00","-1;0;2","+00:00:00"}}, +{{"America/Curacao;AN","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Danmarkshavn;GL","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Dawson;CA/YT","PST","PST","PDT","PDT","-08:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Dawson_Creek;CA/BC","MST","MST","","","-07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Denver;US/CO","MST","Mountain Standard Time","MDT","Mountain Daylight Time","-07:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Detroit;US/MI","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Dominica;DM","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Edmonton;CA/AB","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Eirunepe;BR","ACT","ACT","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/El_Salvador;SV","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Fortaleza;BR","BRT","BRT","BRST","BRST","-03:00:00","+01:00:00","1;0;11","+00:00:00","-1;0;2","+00:00:00"}}, +{{"America/Glace_Bay;CA/NS","AST","AST","ADT","ADT","-04:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Godthab;GL","WGT","WGT","WGST","WGST","-03:00:00","+01:00:00","-1;6;3","+22:00:00","-1;6;10","+23:00:00"}}, +{{"America/Goose_Bay;CA/NL","AST","AST","ADT","ADT","-04:00:00","+01:00:00","1;0;4","+00:01:00","-1;0;10","+00:01:00"}}, +{{"America/Grand_Turk;TC","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+00:00:00","-1;0;10","+00:00:00"}}, +{{"America/Grenada;GD","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Guadeloupe;GP","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Guatemala;GT","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Guayaquil;EC","ECT","ECT","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Guyana;GY","GYT","GYT","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Halifax;CA/NS","AST","AST","ADT","ADT","-04:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Havana;CU","CST","CST","CDT","CDT","-05:00:00","+01:00:00","1;0;4","+00:00:00","-1;0;10","+01:00:00"}}, +{{"America/Hermosillo;MX","MST","MST","","","-07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Indiana/Indianapolis;US/IN","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Indiana/Knox;US/IN","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Indiana/Marengo;US/IN","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Indiana/Vevay;US/IN","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Indianapolis;US/IN","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Inuvik;CA/NT","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Iqaluit;CA/NU","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Jamaica;JM","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Jujuy;AR","ART","ART","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Juneau;US/AK","AKST","AKST","AKDT","AKDT","-09:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Kentucky/Louisville;US/KY","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Kentucky/Monticello;US/KY","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/La_Paz;BO","BOT","BOT","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Lima;PE","PET","PET","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Los_Angeles;US/CA","PST","Pacific Standard Time","PDT","Pacific Daylight Time","-08:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Louisville;US/KY","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Maceio;BR","BRT","BRT","BRST","BRST","-03:00:00","+01:00:00","1;0;11","+00:00:00","-1;0;2","+00:00:00"}}, +{{"America/Managua;NI","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Manaus;BR","AMT","AMT","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Martinique;MQ","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Mazatlan;MX","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;5","+02:00:00","-1;0;9","+02:00:00"}}, +{{"America/Mendoza;AR","ART","ART","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Menominee;US/MI","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Merida;MX","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;5","+02:00:00","-1;0;9","+02:00:00"}}, +{{"America/Mexico_City;MX","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Miquelon;PM","PMST","PMST","PMDT","PMDT","-03:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Monterrey;MX","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;5","+02:00:00","-1;0;9","+02:00:00"}}, +{{"America/Montevideo;UY","UYT","UYT","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Montreal;CA/QC","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Montserrat;MS","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Nassau;BS","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/New_York;US/NY","EST","Eastern Standard Time","EDT","Eastern Daylight Time","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Nipigon;CA/ON","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Nome;US/AK","AKST","AKST","AKDT","AKDT","-09:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Noronha;BR","FNT","FNT","","","-02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/North_Dakota/Center;US/ND","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Panama;PA","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Pangnirtung;CA/NU","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Paramaribo;SR","SRT","SRT","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Phoenix;US/AZ","MST","Mountain Standard Time","","","-07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Port-au-Prince;HT","EST","EST","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Port_of_Spain;TT","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Porto_Velho;BR","AMT","AMT","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Puerto_Rico;PR","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Rainy_River;CA/ON","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Rankin_Inlet;CA/NU","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Recife;BR","BRT","BRT","BRST","BRST","-03:00:00","+01:00:00","1;0;11","+00:00:00","-1;0;2","+00:00:00"}}, +{{"America/Regina;CA/SK","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Rio_Branco;BR","ACT","ACT","","","-05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Rosario;AR","ART","ART","","","-03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Santiago;CL","CLT","CLT","CLST","CLST","-04:00:00","+01:00:00","+9;0;10","+00:00:00","+9;0;3","+00:00:00"}}, +{{"America/Santo_Domingo;DO","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Sao_Paulo;BR","BRT","BRT","BRST","BRST","-03:00:00","+01:00:00","1;0;11","+00:00:00","-1;0;2","+00:00:00"}}, +{{"America/Scoresbysund;GL","EGT","EGT","EGST","EGST","-01:00:00","+01:00:00","-1;0;3","+00:00:00","-1;0;10","+01:00:00"}}, +{{"America/Shiprock;US/NM","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/St_Johns;CA/NL","NST","NST","NDT","NDT","-03:30:00","+01:00:00","1;0;4","+00:01:00","-1;0;10","+00:01:00"}}, +{{"America/St_Kitts;KN","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/St_Louis;US/MO","CST","Central Standard Time","CDT","Central Daylight Time","-06:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/St_Lucia;LC","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/St_Thomas;VI","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/St_Vincent;VC","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Swift_Current;CA/SK","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Tegucigalpa;HN","CST","CST","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Thule;GL","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Thunder_Bay;CA/ON","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Tijuana;MX","PST","PST","PDT","PDT","-08:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Toronto;CA/ON","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Tortola;VG","AST","AST","","","-04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"America/Vancouver;CA/BC","PST","PST","PDT","PDT","-08:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Whitehorse;CA/YT","PST","PST","PDT","PDT","-08:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Winnipeg;CA/MB","CST","CST","CDT","CDT","-06:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+03:00:00"}}, +{{"America/Yakutat;US/AK","AKST","AKST","AKDT","AKDT","-09:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"America/Yellowknife;CA/NT","MST","MST","MDT","MDT","-07:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"Antarctica/Casey;AQ","WST","WST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Antarctica/Davis;AQ","DAVT","DAVT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Antarctica/DumontDUrville;AQ","DDUT","DDUT","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Antarctica/Mawson;AQ","MAWT","MAWT","","","+06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Antarctica/McMurdo;AQ","NZST","NZST","NZDT","NZDT","+12:00:00","+01:00:00","1;0;10","+02:00:00","3;0;3","+03:00:00"}}, +{{"Antarctica/Palmer;AQ","CLT","CLT","CLST","CLST","-04:00:00","+01:00:00","2;0;10","+00:00:00","2;0;3","+00:00:00"}}, +{{"Antarctica/South_Pole;AQ","NZST","NZST","NZDT","NZDT","+12:00:00","+01:00:00","1;0;10","+02:00:00","3;0;3","+03:00:00"}}, +{{"Antarctica/Syowa;AQ","SYOT","SYOT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Antarctica/Vostok;AQ","VOST","VOST","","","+06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Arctic/Longyearbyen;SJ","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Aden;YE","AST","AST","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Almaty;KZ","ALMT","ALMT","ALMST","ALMST","+06:00:00","+01:00:00","-1;0;3","+00:00:00","-1;0;10","+00:00:00"}}, +{{"Asia/Amman;JO","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;4;3","+00:00:00","-1;4;9","+01:00:00"}}, +{{"Asia/Anadyr;RU","ANAT","ANAT","ANAST","ANAST","+12:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Aqtau;KZ","AQTT","AQTT","AQTST","AQTST","+04:00:00","+01:00:00","-1;0;3","+00:00:00","-1;0;10","+00:00:00"}}, +{{"Asia/Aqtobe;KZ","AQTT","AQTT","AQTST","AQTST","+05:00:00","+01:00:00","-1;0;3","+00:00:00","-1;0;10","+00:00:00"}}, +{{"Asia/Ashgabat;TM","TMT","TMT","","","+05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Baghdad;IQ","AST","AST","ADT","ADT","+03:00:00","+01:00:00","1;0;4","+03:00:00","1;0;10","+04:00:00"}}, +{{"Asia/Bahrain;BH","AST","AST","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Baku;AZ","AZT","AZT","AZST","AZST","+04:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+01:00:00"}}, +{{"Asia/Bangkok;TH","ICT","ICT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Beirut;LB","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+00:00:00","-1;0;10","+00:00:00"}}, +{{"Asia/Bishkek;KG","KGT","KGT","KGST","KGST","+05:00:00","+01:00:00","-1;0;3","+02:30:00","-1;0;10","+02:30:00"}}, +{{"Asia/Brunei;BN","BNT","BNT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Calcutta;IN","IST","IST","","","+05:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Choibalsan;MN","CHOT","CHOT","","","+09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Chongqing;CN","CST","CST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Colombo;LK","LKT","LKT","","","+06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Damascus;SY","EET","EET","EEST","EEST","+02:00:00","+01:00:00","1;0;4","+00:00:00","1;0;10","+00:00:00"}}, +{{"Asia/Dhaka;BD","BDT","BDT","","","+06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Dili;TP","TPT","TPT","","","+09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Dubai;AE","GST","GST","","","+04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Dushanbe;TJ","TJT","TJT","","","+05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Gaza;PS","EET","EET","EEST","EEST","+02:00:00","+01:00:00","3;5;4","+00:00:00","3;5;10","+00:00:00"}}, +{{"Asia/Harbin;CN","CST","CST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Hong_Kong;HK","HKT","HKT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Hovd;MN","HOVT","HOVT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Irkutsk;RU","IRKT","IRKT","IRKST","IRKST","+08:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Istanbul;TR","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Asia/Jakarta;ID","WIT","WIT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Jayapura;ID","EIT","EIT","","","+09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Jerusalem;IL","IST","IST","IDT","IDT","+02:00:00","+01:00:00","1;0;4","+01:00:00","1;0;10","+01:00:00"}}, +{{"Asia/Kabul;AF","AFT","AFT","","","+04:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Kamchatka;RU","PETT","PETT","PETST","PETST","+12:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Karachi;PK","PKT","PKT","","","+05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Kashgar;CN","CST","CST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Katmandu;NP","NPT","NPT","","","+05:45:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Krasnoyarsk;RU","KRAT","KRAT","KRAST","KRAST","+07:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Kuala_Lumpur;MY","MYT","MYT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Kuching;MY","MYT","MYT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Kuwait;KW","AST","AST","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Macao;MO","CST","CST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Magadan;RU","MAGT","MAGT","MAGST","MAGST","+11:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Manila;PH","PHT","PHT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Muscat;OM","GST","GST","","","+04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Nicosia;EU/CY","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Asia/Novosibirsk;RU","NOVT","NOVT","NOVST","NOVST","+06:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Omsk;RU","OMST","OMST","OMSST","OMSST","+06:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Phnom_Penh;KH","ICT","ICT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Pontianak;ID","WIT","WIT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Pyongyang;KP","KST","KST","","","+09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Qatar;QA","AST","AST","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Rangoon;MM","MMT","MMT","","","+06:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Riyadh;SA","AST","AST","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Saigon;VN","ICT","ICT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Sakhalin;RU","SAKT","SAKT","SAKST","SAKST","+10:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Samarkand;UZ","UZT","UZT","","","+05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Seoul;KR","KST","KST","","","+09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Shanghai;CN","CST","CST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Singapore;SG","SGT","SGT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Taipei;TW","CST","CST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Tashkent;UZ","UZT","UZT","","","+05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Tbilisi;GE","GET","GET","GEST","GEST","+04:00:00","+01:00:00","-1;0;3","+00:00:00","-1;0;10","+00:00:00"}}, +{{"Asia/Tehran;IR","IRT","IRT","","","+03:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Thimphu;BT","BTT","BTT","","","+06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Tokyo;JP","JST","JST","","","+09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Ujung_Pandang;ID","CIT","CIT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Ulaanbaatar;MN","ULAT","ULAT","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Urumqi;CN","CST","CST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Vientiane;LA","ICT","ICT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Asia/Vladivostok;RU","VLAT","VLAT","VLAST","VLAST","+10:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Yakutsk;RU","YAKT","YAKT","YAKST","YAKST","+09:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Yekaterinburg;RU","YEKT","YEKT","YEKST","YEKST","+05:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Asia/Yerevan;AM","AMT","AMT","AMST","AMST","+04:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Atlantic/Azores;PT","AZOT","AZOT","AZOST","AZOST","-01:00:00","+01:00:00","-1;0;3","+00:00:00","-1;0;10","+01:00:00"}}, +{{"Atlantic/Bermuda;BM","AST","AST","ADT","ADT","-04:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}}, +{{"Atlantic/Canary;ES","WET","WET","WEST","WEST","+00:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+02:00:00"}}, +{{"Atlantic/Cape_Verde;CV","CVT","CVT","","","-01:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Atlantic/Faeroe;FO","WET","WET","WEST","WEST","+00:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+02:00:00"}}, +{{"Atlantic/Jan_Mayen;SJ","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Atlantic/Madeira;PT","WET","WET","WEST","WEST","+00:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+02:00:00"}}, +{{"Atlantic/Reykjavik;IS","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Atlantic/South_Georgia;GS","GST","GST","","","-02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Atlantic/St_Helena;SH","GMT","GMT","","","+00:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Atlantic/Stanley;FK","FKT","FKT","FKST","FKST","-04:00:00","+01:00:00","1;0;9","+02:00:00","3;0;4","+02:00:00"}}, +{{"Australia/Adelaide;AU","CST","CST","CST","CST","+09:30:00","+01:00:00","-1;0;10","+02:00:00","-1;0;3","+03:00:00"}}, +{{"Australia/Brisbane;AU","EST","EST","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Australia/Broken_Hill;AU","CST","CST","CST","CST","+09:30:00","+01:00:00","-1;0;10","+02:00:00","-1;0;3","+03:00:00"}}, +{{"Australia/Darwin;AU","CST","CST","","","+09:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Australia/Hobart;AU","EST","EST","EST","EST","+10:00:00","+01:00:00","1;0;10","+02:00:00","-1;0;3","+03:00:00"}}, +{{"Australia/Lindeman;AU","EST","EST","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Australia/Lord_Howe;AU","LHST","LHST","LHST","LHST","+10:30:00","+00:30:00","-1;0;10","+02:00:00","-1;0;3","+02:00:00"}}, +{{"Australia/Melbourne;AU","EST","EST","EST","EST","+10:00:00","+01:00:00","-1;0;10","+02:00:00","-1;0;3","+03:00:00"}}, +{{"Australia/Perth;AU","WST","WST","","","+08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Australia/Sydney;AU","EST","EST","EST","EST","+10:00:00","+01:00:00","-1;0;10","+02:00:00","-1;0;3","+03:00:00"}}, +{{"Europe/Amsterdam;EU/NL","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Andorra;AD","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Athens;EU/GR","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Belfast;IE","GMT","GMT","BST","BST","+00:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+02:00:00"}}, +{{"Europe/Belgrade;CS","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Berlin;EU/DE","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Bratislava;EU/SK","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Brussels;EU/BE","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Bucharest;RO","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Budapest;EU/HU","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Chisinau;MD","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Copenhagen;EU/DK","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Dublin;EU/IE","GMT","GMT","IST","IST","+00:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+02:00:00"}}, +{{"Europe/Gibraltar;GI","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Helsinki;EU/FI","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Istanbul;TR","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Kaliningrad;RU","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Kiev;UA","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Lisbon;EU/PT","WET","WET","WEST","WEST","+00:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+02:00:00"}}, +{{"Europe/Ljubljana;EU/SI","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/London;EU/GB","GMT","GMT","BST","BST","+00:00:00","+01:00:00","-1;0;3","+01:00:00","-1;0;10","+02:00:00"}}, +{{"Europe/Luxembourg;EU/LU","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Madrid;EU/ES","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Malta;EU/MT","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Minsk;BY","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Monaco;MC","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Moscow;RU","MSK","MSK","MSD","MSD","+03:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Nicosia;CY","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Oslo;NO","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Paris;EU/FR","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Prague;EU/CZ","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Riga;EU/LV","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Rome;EU/IT","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Samara;RU","SAMT","SAMT","SAMST","SAMST","+04:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/San_Marino;SM","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Sarajevo;BA","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Simferopol;UA","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Skopje;MK","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Sofia;BG","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Stockholm;EU/SE","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Tallinn;EU/EE","EET","EET","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Europe/Tirane;AL","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Uzhgorod;UA","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Vaduz;LI","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Vatican;VA","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Vienna;EU/AT","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Vilnius;EU/LT","EET","EET","","","+02:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Europe/Warsaw;EU/PL","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Zagreb;HR","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Europe/Zaporozhye;UA","EET","EET","EEST","EEST","+02:00:00","+01:00:00","-1;0;3","+03:00:00","-1;0;10","+04:00:00"}}, +{{"Europe/Zurich;CH","CET","CET","CEST","CEST","+01:00:00","+01:00:00","-1;0;3","+02:00:00","-1;0;10","+03:00:00"}}, +{{"Indian/Antananarivo;MG","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Chagos;IO","IOT","IOT","","","+06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Christmas;CX","CXT","CXT","","","+07:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Cocos;CC","CCT","CCT","","","+06:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Comoro;KM","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Kerguelen;TF","TFT","TFT","","","+05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Mahe;SC","SCT","SCT","","","+04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Maldives;MV","MVT","MVT","","","+05:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Mauritius;MU","MUT","MUT","","","+04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Mayotte;YT","EAT","EAT","","","+03:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Indian/Reunion;RE","RET","RET","","","+04:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Apia;WS","WST","WST","","","-11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Auckland;NZ","NZST","NZST","NZDT","NZDT","+12:00:00","+01:00:00","1;0;10","+02:00:00","3;0;3","+03:00:00"}}, +{{"Pacific/Chatham;NZ","CHAST","CHAST","CHADT","CHADT","+12:45:00","+01:00:00","1;0;10","+02:45:00","3;0;3","+03:45:00"}}, +{{"Pacific/Easter;CL","EAST","EAST","EASST","EASST","-06:00:00","+01:00:00","2;6;10","+22:00:00","2;6;3","+22:00:00"}}, +{{"Pacific/Efate;VU","VUT","VUT","","","+11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Enderbury;KI","PHOT","PHOT","","","+13:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Fakaofo;TK","TKT","TKT","","","-10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Fiji;FJ","FJT","FJT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Funafuti;TV","TVT","TVT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Galapagos;EC","GALT","GALT","","","-06:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Gambier;PF","GAMT","GAMT","","","-09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Guadalcanal;SB","SBT","SBT","","","+11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Guam;GU","ChST","ChST","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Honolulu;US/HI","HST","HST","","","-10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Johnston;UM","HST","HST","","","-10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Kiritimati;KI","LINT","LINT","","","+14:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Kosrae;FM","KOST","KOST","","","+11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Kwajalein;MH","MHT","MHT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Majuro;MH","MHT","MHT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Marquesas;PF","MART","MART","","","-09:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Midway;UM","SST","SST","","","-11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Nauru;NR","NRT","NRT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Niue;NU","NUT","NUT","","","-11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Norfolk;NF","NFT","NFT","","","+11:30:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Noumea;NC","NCT","NCT","","","+11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Pago_Pago;AS","SST","SST","","","-11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Palau;PW","PWT","PWT","","","+09:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Pitcairn;PN","PST","PST","","","-08:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Ponape;FM","PONT","PONT","","","+11:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Port_Moresby;PG","PGT","PGT","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Rarotonga;CK","CKT","CKT","","","-10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Saipan;MP","ChST","ChST","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Tahiti;PF","TAHT","TAHT","","","-10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Tarawa;KI","GILT","GILT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Tongatapu;TO","TOT","TOT","","","+13:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Truk;FM","TRUT","TRUT","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Wake;UM","WAKT","WAKT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Wallis;WF","WFT","WFT","","","+12:00:00","+00:00:00","","","","+00:00:00"}}, +{{"Pacific/Yap;FM","YAPT","YAPT","","","+10:00:00","+00:00:00","","","","+00:00:00"}}, +{{"US/Michigan;US","EST","EST","EDT","EDT","-05:00:00","+01:00:00","1;0;4","+02:00:00","-1;0;10","+02:00:00"}} diff --git a/mmslib/inc/stdtime_tzrules.h b/mmslib/inc/stdtime_tzrules.h new file mode 100644 index 0000000..30548ad --- /dev/null +++ b/mmslib/inc/stdtime_tzrules.h @@ -0,0 +1,58 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtime_tzrules.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Data file to fix historical rules for daylight saving time. */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 06/07/06 RLH 01 Created */ +/*****************************************************************************/ + +/* this data is part of a table of type STDTIME_FIX_TZ_RULES */ +/* the struct defining type STDTIME_FIX_TZ_RULES is in stdtime.h */ +/* entries with region codes must appear before entries without them */ + + + {"US", "IN", 2007, 9999, {2,0,3}, {1, 2,0,0}, {1,0,11}, {1, 2,0,0}}, + {"US", "IN", 1945, 2006, {0,0,0}, {0, 0,0,0}, {0,0,00}, {0, 0,0,0}}, + {"US", "HI", 1945, 9999, {0,0,0}, {0, 0,0,0}, {0,0,00}, {0, 0,0,0}}, + {"US", "AZ", 1945, 9999, {0,0,0}, {0, 0,0,0}, {0,0,00}, {0, 0,0,0}}, + + {"US", "", 2007, 9999, {2,0,3}, {1, 2,0,0}, {1,0,11}, {1, 2,0,0}}, + {"US", "", 1987, 2006, {1,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"US", "", 1976, 1986, {5,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"US", "", 1975, 1975, {5,0,2}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"US", "", 1974, 1974, {1,0,1}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"US", "", 1967, 1973, {5,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"US", "", 1945, 1966, {5,0,4}, {1, 2,0,0}, {5,0, 9}, {1, 2,0,0}}, + + + {"CA", "SK", 1945, 9999, {0,0,0}, {0, 0,0,0}, {0,0,00}, {0, 0,0,0}}, + + /* for now, CA and MX just duplicate US rules */ + + {"CA", "", 2007, 9999, {2,0,3}, {1, 2,0,0}, {1,0,11}, {1, 2,0,0}}, + {"CA", "", 1987, 2006, {1,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"CA", "", 1976, 1986, {5,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"CA", "", 1975, 1975, {5,0,2}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"CA", "", 1974, 1974, {1,0,1}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"CA", "", 1967, 1973, {5,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"CA", "", 1945, 1966, {5,0,4}, {1, 2,0,0}, {5,0, 9}, {1, 2,0,0}}, + + + {"MX", "", 2007, 9999, {2,0,3}, {1, 2,0,0}, {1,0,11}, {1, 2,0,0}}, + {"MX", "", 1987, 2006, {1,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"MX", "", 1976, 1986, {5,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"MX", "", 1975, 1975, {5,0,2}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"MX", "", 1974, 1974, {1,0,1}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"MX", "", 1967, 1973, {5,0,4}, {1, 2,0,0}, {5,0,10}, {1, 2,0,0}}, + {"MX", "", 1945, 1966, {5,0,4}, {1, 2,0,0}, {5,0, 9}, {1, 2,0,0}} /**/ + diff --git a/mmslib/inc/stdtime_w32.h b/mmslib/inc/stdtime_w32.h new file mode 100644 index 0000000..008f58f --- /dev/null +++ b/mmslib/inc/stdtime_w32.h @@ -0,0 +1,353 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtime_w32.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Header file for Standard Time Management Library Win32 Compatibility */ +/* Layer. This header is compiled with STDTIMEW32_ENABLED on Windows to */ +/* generate debugging code or to run emulation on Unix. To run on */ +/* Windows, compile with STDTIMEW32_DISABLED. STDTIMEW32_ENABLED is */ +/* required on Unix/Linux (that is, non-Windows) platforms. */ +/* */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 12/17/07 JRB 04 Del STDTIME_WIN_VARIANT, ..DBTIMESTAMP, ..UDATE */ +/* structs (no longer used). */ +/* 04/03/07 RLH 03 Make UDOT definition compatible with Linux 8.0 */ +/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */ +/* 01/18/06 RLH 01 Created */ +/*****************************************************************************/ + + +#ifndef _STDTIME_W32_H_29560654_4DD5_47A5_9B07_559DA09B36A3_ +#define _STDTIME_W32_H_29560654_4DD5_47A5_9B07_559DA09B36A3_ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*****************************************************************************/ +/* ENABLED or DISABLED */ +/*****************************************************************************/ + +#undef STDTIMEW32_DEBUGGING +#undef STDTIMEW32_UNIX + +#if defined(STDTIMEW32_ENABLED) && defined(STDTIMEW32_DISABLED) +#error Both STDTIMEW32_ENABLED and STDTIMEW32_DISABLED defined +#undef STDTIMEW32_ENABLED +#endif + +#if !defined(STDTIMEW32_ENABLED) && !defined(STDTIMEW32_DISABLED) + +#if defined(STDTIMEW32_USE_CLOCKGETTIME) \ + || defined(STDTIMEW32_USE_GETTIMEOFDAY) \ + || defined(STDTIMEW32_USE_TIMEB) /**/ +#define STDTIMEW32_ENABLED +#else +#define STDTIMEW32_DISABLED +#endif + +#endif + +#if defined(STDTIMEW32_DISABLED) && !defined(_WIN32) +#error StdTime Windows Compatibility Layer disabled on non-Windows platform +#endif + +#if defined(STDTIMEW32_ENABLED) && defined(_WIN32) +#define STDTIMEW32_DEBUGGING +#endif + +#if defined(STDTIMEW32_ENABLED) && !defined(_WIN32) +#define STDTIMEW32_UNIX +#endif + + +/*****************************************************************************/ +/* STATIC (LOCAL) FUNCTION QUALIFIER */ +/*****************************************************************************/ + +#ifndef STDTIMEW32_STATIC +#define STDTIMEW32_STATIC +#endif + + +/*****************************************************************************/ +/* PORTABILITY API NAME DEFINITIONS */ +/*****************************************************************************/ + + +#if defined(STDTIMEW32_USE_CLOCKGETTIME) +#define STDTIME_API_GETSYSTEMTIMEASFILETIME StdTimeW32ClockGetTimeToFileTime + +#elif defined(STDTIMEW32_USE_GETTIMEOFDAY) +#define STDTIME_API_GETSYSTEMTIMEASFILETIME StdTimeW32GetTimeOfDayToFileTime + +#elif defined(STDTIMEW32_USE_TIMEB) +#define STDTIME_API_GETSYSTEMTIMEASFILETIME StdTimeW32TimeBToFileTime + +#else + +#ifdef STDTIMEW32_UNIX +#error No API defined for GetSystemTimeAsFileTime Unix interface +#endif + +#endif /* STDTIMEW32_USE_CLOCKGETTIME */ + + +#ifdef STDTIMEW32_ENABLED +#define STDTIME_API_FILETIMETOLOCALFILETIME StdTimeW32FileTimeToLocalFileTime +#define STDTIME_API_LOCALFILETIMETOFILETIME StdTimeW32LocalFileTimeToFileTime +#else +#define STDTIME_API_FILETIMETOLOCALFILETIME FileTimeToLocalFileTime +#define STDTIME_API_LOCALFILETIMETOFILETIME LocalFileTimeToFileTime +#endif /* STDTIMEW32_ENABLED */ + + +#ifdef STDTIMEW32_ENABLED +#define STDTIME_API_FILETIMETOSYSTEMTIME StdTimeW32FileTimeToSystemTime +#define STDTIME_API_SYSTEMTIMETOFILETIME StdTimeW32SystemTimeToFileTime +#else +#define STDTIME_API_SYSTEMTIMETOFILETIME SystemTimeToFileTime +#define STDTIME_API_FILETIMETOSYSTEMTIME FileTimeToSystemTime +#endif /* STDTIMEW32_ENABLED */ + + +/*****************************************************************************/ +/* BASIC DEFINITIONS */ +/*****************************************************************************/ + + +#define STDTIME_WIN_EPOCH_YEAR 1601 +#define STDTIME_UNIX_EPOCH_YEAR 1970 + +#undef STDTIME_WIN_VT_DATE_DEFINED + +#ifdef _WIN32 + +/* if debugging non-Windows code on Windows, use compatibility typedefs */ + +typedef SHORT STDTIME_WIN_SHORT; +typedef USHORT STDTIME_WIN_USHORT; +typedef WORD STDTIME_WIN_WORD; +typedef DWORD STDTIME_WIN_DWORD; +typedef LONG STDTIME_WIN_LONG; +typedef ULONG STDTIME_WIN_ULONG; +typedef LONGLONG STDTIME_WIN_LONGLONG; +typedef ULONGLONG STDTIME_WIN_ULONGLONG; +typedef BOOL STDTIME_WIN_BOOL; + +#define STDTIME_WIN_TRUE TRUE +#define STDTIME_WIN_FALSE FALSE + + +typedef SYSTEMTIME STDTIME_WIN_SYSTEMTIME; +typedef FILETIME STDTIME_WIN_FILETIME; +typedef LARGE_INTEGER STDTIME_WIN_LARGE_INTEGER; +typedef ULARGE_INTEGER STDTIME_WIN_ULARGE_INTEGER; + +#else /* not _WIN32 */ + +typedef int16_t STDTIME_WIN_SHORT; +typedef uint16_t STDTIME_WIN_USHORT; +typedef uint16_t STDTIME_WIN_WORD; +typedef uint32_t STDTIME_WIN_DWORD; +typedef int32_t STDTIME_WIN_LONG; +typedef uint32_t STDTIME_WIN_ULONG; +typedef QUADLIB_I64 STDTIME_WIN_LONGLONG; +typedef QUADLIB_U64 STDTIME_WIN_ULONGLONG; +typedef int32_t STDTIME_WIN_BOOL; + +#define STDTIME_WIN_TRUE 1 +#define STDTIME_WIN_FALSE 0 + + +#endif /* _WIN32 */ + + +/*****************************************************************************/ +/* SYSTEMTIME structure - compatibility definition */ +/*****************************************************************************/ + +#ifdef STDTIMEW32_UNIX + +typedef struct + { + STDTIME_WIN_WORD wYear; + STDTIME_WIN_WORD wMonth; + STDTIME_WIN_WORD wDayOfWeek; + STDTIME_WIN_WORD wDay; + STDTIME_WIN_WORD wHour; + STDTIME_WIN_WORD wMinute; + STDTIME_WIN_WORD wSecond; + STDTIME_WIN_WORD wMilliseconds; + } STDTIME_WIN_SYSTEMTIME; + +#endif /* STDTIMEW32_UNIX */ + + +/*****************************************************************************/ +/* VT_DATE compatibility definitions */ +/*****************************************************************************/ + +#ifndef STDTIME_WIN_VT_DATE_DEFINED + +typedef uint16_t STDTIME_WIN_VARTYPE; +typedef double STDTIME_WIN_DATE; + +enum STDTIME_WIN_VARENUM + { + STDTIME_WIN_VT_EMPTY = 0, + STDTIME_WIN_VT_DATE = 7, + STDTIME_WIN_VT_BYREF = 0x4000 + }; + +#endif /* STDTIME_WIN_VT_DATE_DEFINED */ + +/*****************************************************************************/ +/* FILETIME structure - compatibility definition */ +/*****************************************************************************/ + +#ifdef STDTIMEW32_UNIX + +typedef struct + { + STDTIME_WIN_DWORD dwLowDateTime; + STDTIME_WIN_DWORD dwHighDateTime; + } STDTIME_WIN_FILETIME; + +#endif /* STDTIMEW32_UNIX */ + +/*****************************************************************************/ +/* LARGE_INTEGER structure - compatibility definition */ +/*****************************************************************************/ + +#ifdef STDTIMEW32_UNIX + +typedef union _STDTIME_WIN_LARGE_INTEGER + { + /* to maximize compatibility, the anonymous struct is omitted */ + /* references to LARGE_INTEGER fields will require 'u' qualifier */ + /* use of the anonymous struct is a non-portable Microsoft extension. */ + + /* the order of LowPart and HighPart should agree with endian */ + /* ordering on the host platform */ + + /* if compiled under I64 compatibility, QuadPart is a QuadLib structure */ + /* QUADLIB_I64 and QUADLIB_U64 are the same type, but have different */ + /* names to document their intended usage */ + + struct + { + STDTIME_WIN_DWORD LowPart; + STDTIME_WIN_LONG HighPart; + } u; + + QUADLIB_I64 QuadPart; + + } STDTIME_WIN_LARGE_INTEGER; + +#endif /* STDTIMEW32_UNIX */ + +/*****************************************************************************/ +/* ULARGE_INTEGER structure - compatibility definition */ +/*****************************************************************************/ + +#ifdef STDTIMEW32_UNIX + +typedef union _STDTIME_WIN_ULARGE_INTEGER + { + /* to maximize compatibility, the anonymous struct is omitted */ + /* references to ULARGE_INTEGER fields will require 'u' qualifier */ + /* use of the anonymous struct is a non-portable Microsoft extension. */ + + /* the order of LowPart and HighPart should agree with endian */ + /* ordering on the host platform */ + + /* if compiled under I64 compatibility, QuadPart is a QuadLib structure */ + /* QUADLIB_I64 and QUADLIB_U64 are the same type, but have different */ + /* names to document their intended usage */ + + struct + { + STDTIME_WIN_DWORD LowPart; + STDTIME_WIN_DWORD HighPart; + } u; + + QUADLIB_U64 QuadPart; + + } STDTIME_WIN_ULARGE_INTEGER; + +#endif /* STDTIMEW32_UNIX */ + + +/*****************************************************************************/ +/* compatibility-layer API functions */ +/*****************************************************************************/ + +#ifndef STDTIME_API_GETSYSTEMTIMEASFILETIME +#define STDTIME_API_GETSYSTEMTIMEASFILETIME GetSystemTimeAsFileTime + +#else +STDTIMEW32_STATIC void STDTIME_API_GETSYSTEMTIMEASFILETIME ( + STDTIME_WIN_FILETIME * /*O*/ pFileTime); +#endif + + +#ifdef STDTIMEW32_ENABLED + + +STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32SystemTimeToFileTime ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + STDTIME_WIN_FILETIME * /*O*/ pFileTime); + + +STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32FileTimeToSystemTime ( + const STDTIME_WIN_FILETIME * /*I*/ pFileTime, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime); + + +STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32FileTimeToLocalFileTime ( + const STDTIME_WIN_FILETIME * /*I*/ pGmtFileTime, + STDTIME_WIN_FILETIME * /*O*/ pLocFileTime); + + +STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32LocalFileTimeToFileTime ( + const STDTIME_WIN_FILETIME * /*I*/ pLocFileTime, + STDTIME_WIN_FILETIME * /*O*/ pGmtFileTime); + + +#endif /* STDTIMEW32_ENABLED */ + + +/*****************************************************************************/ +/* OBTAIN DAY OF WEEK AND DAY OF WEEK */ +/*****************************************************************************/ + +STDTIME_RC StdTimeW32GetDayofWeekAndYear ( + int32_t /*I*/ nYear, + int32_t /*I*/ nMon, + int32_t /*I*/ nDayofMon, + int32_t * /*O*/ pDayofWeek, + int32_t * /*O*/ pDayofYear); + +/*****************************************************************************/ +/* END */ +/*****************************************************************************/ + +#ifdef __cplusplus +} +#endif + + +#endif /* _STDTIME_W32_H_29560654_4DD5_47A5_9B07_559DA09B36A3_ */ + diff --git a/mmslib/inc/stime.h b/mmslib/inc/stime.h new file mode 100644 index 0000000..303d53f --- /dev/null +++ b/mmslib/inc/stime.h @@ -0,0 +1,38 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved */ +/* */ +/* MODULE NAME : stime.h */ +/* PRODUCT(S) : SLOG */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/14/05 EJV 03 Del sGetMsStartTime, sSetMsStartTime */ +/* 11/04/03 JRB 02 Add sMsSleep (replaces gs_sleep). */ +/* 11/05/97 DSF 01 Added sGetSysMsTime () */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +ST_RET stimeInit (ST_VOID); +ST_DOUBLE sGetMsTime (ST_VOID); +ST_DOUBLE sGetSysMsTime (ST_VOID); +ST_VOID sResetMsTime (ST_VOID); +ST_VOID stimeExit (ST_VOID); +ST_VOID sMsSleep (ST_LONG ms); + +#ifdef __cplusplus +} +#endif + diff --git a/mmslib/inc/sx_arb.h b/mmslib/inc/sx_arb.h new file mode 100644 index 0000000..907a8a1 --- /dev/null +++ b/mmslib/inc/sx_arb.h @@ -0,0 +1,119 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999 - 2004, All Rights Reserved */ +/* */ +/* MODULE NAME : sx_arb.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/19/07 JRB 04 Add TEXT_FORMAT_COMMA, sxaTextToLocalEx. */ +/* 10/24/06 JRB 03 Add sxaLocalToText2 proto. */ +/* 12/06/04 JRB 02 Add "sx_defs.h". */ +/* 08/30/04 DSF 01 Module created */ +/************************************************************************/ +/************************************************************************/ + +#ifndef SX_ARB_INCLUDED +#define SX_ARB_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************************************/ + +#include "mms_def2.h" +#include "mms_mp.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "sx_defs.h" /* need SX_ENC_CTRL */ + +ST_RET sxd_decode_rtdata_el (SD_CONST ST_CHAR *elName, + ST_CHAR *xml, ST_INT xmlLen, ST_INT *xmlUsed, + ST_VOID *vdp, SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, ST_BOOLEAN *elPres, + ST_INT sxdXmlStyle, ST_BOOLEAN checkDt); +ST_RET sxd_wr_rtdata (SX_ENC_CTRL *sxEncCtrl, RUNTIME_TYPE *rt, ST_INT numRt, + ST_CHAR *elName, ST_VOID *data, ST_INT sxdXmlStyle, + ST_BOOLEAN encodeDt, ST_BOOLEAN *elPres); + +/************************************************************************/ +/************************************************************************/ +/* Arbitrary data processing, for use in traversing the RUNTIME_TYPE */ + +typedef struct + { + ST_RET (*arrStart) (ST_VOID *usr, RUNTIME_TYPE *rt); + ST_RET (*arrEnd) (ST_VOID *usr, RUNTIME_TYPE *rt); + ST_RET (*strStart) (ST_VOID *usr, RUNTIME_TYPE *rt, SD_CONST RUNTIME_TYPE *rt_head); + ST_RET (*strEnd) (ST_VOID *usr, RUNTIME_TYPE *rt); + ST_RET (*int8) (ST_VOID *usr, ST_INT8 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*int16) (ST_VOID *usr, ST_INT16 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*int32) (ST_VOID *usr, ST_INT32 *data_dest, RUNTIME_TYPE *rt); +#ifdef INT64_SUPPORT + ST_RET (*int64) (ST_VOID *usr, ST_INT64 *data_dest, RUNTIME_TYPE *rt); +#endif + ST_RET (*uint8) (ST_VOID *usr, ST_UINT8 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*uint16) (ST_VOID *usr, ST_UINT16 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*uint32) (ST_VOID *usr, ST_UINT32 *data_dest, RUNTIME_TYPE *rt); +#ifdef INT64_SUPPORT + ST_RET (*uint64) (ST_VOID *usr, ST_UINT64 *data_dest, RUNTIME_TYPE *rt); +#endif + ST_RET (*flt) (ST_VOID *usr, ST_FLOAT *data_dest, RUNTIME_TYPE *rt); + ST_RET (*dbl) (ST_VOID *usr, ST_DOUBLE *data_dest, RUNTIME_TYPE *rt); + ST_RET (*oct) (ST_VOID *usr, ST_UCHAR *data_dest, RUNTIME_TYPE *rt); + ST_RET (*booln) (ST_VOID *usr, ST_BOOLEAN *data_dest, RUNTIME_TYPE *rt); + ST_RET (*bcd1) (ST_VOID *usr, ST_INT8 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*bcd2) (ST_VOID *usr, ST_INT16 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*bcd4) (ST_VOID *usr, ST_INT32 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*bs) (ST_VOID *usr, ST_UCHAR *data_dest, RUNTIME_TYPE *rt); + ST_RET (*vis) (ST_VOID *usr, ST_CHAR *data_dest, RUNTIME_TYPE *rt); + ST_RET (*bt4) (ST_VOID *usr, ST_INT32 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*bt6) (ST_VOID *usr, ST_INT32 *data_dest, RUNTIME_TYPE *rt); + ST_RET (*gt) (ST_VOID *usr, time_t *data_dest, RUNTIME_TYPE *rt); + ST_RET (*utc) (ST_VOID *usr, MMS_UTC_TIME *data_dest, RUNTIME_TYPE *rt); + ST_RET (*utf8) (ST_VOID *usr, ST_UCHAR *data_dest, RUNTIME_TYPE *rt); + } SXD_ARB_DATA_CTRL; + +ST_RET sxd_process_arb_data (ST_CHAR *datptr, SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, ST_VOID *usr, + SXD_ARB_DATA_CTRL *ac, ST_BOOLEAN *elPres); + +ST_RET sxaTextToLocal (ST_CHAR *pSource, ST_VOID *pDest, ST_INT numRt, SD_CONST RUNTIME_TYPE *rtHead); +ST_CHAR *sxaLocalToText (ST_VOID *dataPtr, SD_CONST RUNTIME_TYPE *rtHead, ST_INT numRt); +/* sxaLocalToText2 is thread-safe (does not use global buffer). */ +ST_CHAR *sxaLocalToText2 (ST_VOID *dataPtr, SD_CONST RUNTIME_TYPE *rtHead, ST_INT numRt, + ST_CHAR *textBuf, /* User buffer in which to write text */ + ST_UINT textBufSize); /* size of user buffer */ + +/* Defines to use for textFormat argument of sxaTextToLocalEx. */ +/* DEBUG: currently only ONE format supported (TEXT_FORMAT_COMMA), but */ +/* this should make it easier to add other formats later. */ +#define TEXT_FORMAT_COMMA 1 /* Comma-separated text format */ + /* Each value in the text may */ + /* also be surrounded by "". */ + /* Examples of text: */ + /* "0","1.1","2","3.3","4" */ + /* 0,1.1,2,3.3,4 */ +ST_RET sxaTextToLocalEx ( + ST_CHAR *pSource, /* source text */ + ST_VOID *pDest, /* destination data */ + ST_INT numRt, + SD_CONST RUNTIME_TYPE *rtHead, + ST_INT textFormat); /* text format from which to convert */ + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* SX_ARB_INCLUDED */ diff --git a/mmslib/inc/sx_defs.h b/mmslib/inc/sx_defs.h new file mode 100644 index 0000000..e6ee545 --- /dev/null +++ b/mmslib/inc/sx_defs.h @@ -0,0 +1,611 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999 - 2008, All Rights Reserved */ +/* */ +/* MODULE NAME : sx_defs.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/01/08 EJV 66 Added SX_PARSING_OK, sx_err_str* (for slogs).*/ +/* 01/14/08 MDE 65 Fixed numOcc multithread problem */ +/* 07/30/07 RWM 64 Added numAlloced4 to sx_dec_ctrl */ +/* For early MODLOGS see previous revision of this file on PVCS. */ +/************************************************************************/ + +#ifndef SX_DEFS_INCLUDED +#define SX_DEFS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************************************/ + +#include "glbtypes.h" + +/************************************************************************/ +/* This is the amount of overhead required to ensure no overwrite */ + +#define SX_ENC_BUFFER_OH 20 + +/************************************************************************/ +/* Capacities */ + +#if !defined(SX_MAX_XML_NEST) +#define SX_MAX_XML_NEST 30 +#endif + +#if !defined(SX_MAX_STACK_LEVEL) +#define SX_MAX_STACK_LEVEL 50 +#endif + +#if !defined(SX_MAX_TAG_LEN) +#define SX_MAX_TAG_LEN 100 +#endif + +#if !defined(SX_MAX_ATTRIB) +#define SX_MAX_ATTRIB 20 +#endif + +#if !defined(SX_MAX_ATTR_NAME) +#define SX_MAX_ATTR_NAME 100 +#endif + +#if !defined(SX_MAX_ATTR_VALUE) +#define SX_MAX_ATTR_VALUE 1000 +#endif + +#if !defined(SX_MAX_ELEM_LEN) +#define SX_MAX_ELEM_LEN 2000 +#endif + +#if !defined SX_MAX_ITEMS_PER_TABLE +#define SX_MAX_ITEMS_PER_TABLE 50 +#endif + + +/************************************************************************/ +/* Error codes - stop parsing */ +#define SX_PARSING_OK 0 +#define SX_USER_ERROR 1 +#define SX_STRUCT_NOT_FOUND 2 +#define SX_REQUIRED_TAG_NOT_FOUND 3 +#define SX_DUPLICATE_NOT_ALLOWED 4 +#define SX_EMPTY_TAG_NOT_ALLOWED 5 +#define SX_XML_NEST_TOO_DEEP 6 +#define SX_XML_BUFFER_OVER_MAX 7 +#define SX_XML_MALFORMED 8 +#define SX_FILE_NOT_FOUND 9 +#define SX_END_PARSING 10 /* for partial parsing */ +#define SX_ELEMENT_TBL_TOO_BIG 11 +/* NOTE: when adding more error codes update also the sx_err_str[] in the sx_dec.c */ + +/* Normal errors - continue with parse */ +#define SX_ERR_CONVERT 100 + +#ifdef DEBUG_SISCO +extern ST_CHAR *sx_err_str[]; /* tbl of error strings, used in slogs */ +extern ST_INT sx_err_str_cnt; + +/* macro to get the error string logged */ +#define SX_ERR_STR(errCode) ((errCode < sx_err_str_cnt) ? sx_err_str[errCode] : "UNKNOWN SX ERROR") +#endif /* DEBUG_SISCO */ + +/************************************************************************/ +/************************************************************************/ +/* SX_DURATION */ +/* Duration is an ISO 8601 date/time standard in the following format: */ +/* PnYnMnDTnHnMnS */ +/* where P = period, Y = years, M = months, D = days, T = date/time */ +/* seperator, H = hours, M = minutes, S = seconds. Seconds may be any */ +/* decimal number of arbitrary precision. n represents a number. */ +/* For example: or */ +/* */ +typedef struct sx_duration + { + ST_BOOLEAN negative; /* true = negative duration */ + ST_INT years; /* number of years in duration */ + ST_INT months; /* number of months in duration */ + ST_INT days; /* number of days in duration */ + ST_INT hours; /* number of hours in duration */ + ST_INT minutes; /* number of minutes in duration */ + ST_INT seconds; /* integer part of seconds */ + ST_LONG microseconds; /* decimal part of seconds */ + ST_BOOLEAN inUse; /* easy way to tell if this optional */ + /* attribute is present */ + } SX_DURATION; + +/************************************************************************/ +/************************************************************************/ +/* SX_DATE_TIME */ + +typedef struct sx_date_time + { + time_t dateTime; /* number of local or UTC/GMT/Zule seconds since 1/1/1970 */ + long microseconds; /* decimal fraction or microseconds */ + int tz; /* minutes specified in time zone "+hh:mm or -hh:mm" */ + ST_BOOLEAN useMicroseconds; /* indicates decimal fraction of microseconds is present */ + ST_BOOLEAN useTZ; /* if true "yyyy-mm-ddThh:mm:ss.fffff+/-hh:mm" or */ + /* "yyyy-mm-ddThh:mm:ss+/-hh:mm" or */ + /* "yyyy-mm-ddThh:mm:ss.fffffZ" or */ + /* "yyyy-mm-ddThh:mm:ssZ" */ + /* if false "yyyy-mm-ddThh:mm:ss.fffff or */ + /* "yyyy-mm-ddThh:mm:ss */ + } SX_DATE_TIME; + +/************************************************************************/ +/************************************************************************/ +/* XML <-> Local XML Style Selection */ + +/* Note: Style A must have the value 0 */ +#define SXD_XML_STYLE_A 0 /* Values as attrib, single element/struct */ +#define SXD_XML_STYLE_C 1 /* CDATA value encoding */ +#define SXD_XML_STYLE_V 2 /* Each value has own element, attrib encoded */ + +extern ST_INT sxdDefXmlStyle; /* Note: 0 is style A */ + +/* Examples: */ +/* A: */ +/* A: */ + +/* C: 1248044 */ +/* C: BinFull78Good */ + +/* V: */ +/* V: */ + +/************************************************************************/ +/************************************************************************/ +extern ST_BOOLEAN sxUseSax; +extern ST_BOOLEAN sxUseFormatting; +extern ST_BOOLEAN sxIgnoreNS; +extern ST_BOOLEAN sxLogOverrunAsFlow; + +/* elementFlags defines; bitmasked */ +#define SX_ELF_CSTART 0x0001 +#define SX_ELF_CEND 0x0002 +#define SX_ELF_CSTARTEND 0x0003 + +#define SX_ELF_RPT 0x0008 +#define SX_ELF_OPT 0x0004 +#define SX_ELF_OPTRPT 0x000C + +#define SX_ELF_EMPTYOK 0x0010 + +struct sx_dec_ctrl; /* forward definition */ + +typedef struct sx_element + { + char *tag; + ST_INT elementFlags; + void (*funcPtr)(struct sx_dec_ctrl *sxDecCtrl); + + char *user; + +/* Runtime elements: */ + ST_INT notUsed; + } SX_ELEMENT; + +/************************************************************************/ + +/* defines for string formatting */ +#define CODE_APOS "'" +#define CODE_QUOT """ +#define CODE_AMP "&" +#define CODE_LT "<" +#define CODE_GT ">" + +#define CODE_APOS_LEN (sizeof (CODE_APOS) - 1) +#define CODE_QUOT_LEN (sizeof (CODE_QUOT) - 1) +#define CODE_AMP_LEN (sizeof (CODE_AMP) - 1) +#define CODE_LT_LEN (sizeof (CODE_LT) - 1) +#define CODE_GT_LEN (sizeof (CODE_GT) - 1) + +#define CHAR_APOS '\'' +#define CHAR_QUOT '\"' +#define CHAR_AMP '&' +#define CHAR_LT '<' +#define CHAR_GT '>' + +/************************************************************************/ + +/* defines for 'reason' */ +#define SX_ELEMENT_START 1 +#define SX_ELEMENT_END 2 + + +typedef struct sx_element_tbl_ctrl + { + ST_INT numItems; + SX_ELEMENT *itemTbl; + ST_INT numOccTbl[SX_MAX_ITEMS_PER_TABLE]; + } SX_ELEMENT_TBL_CTRL; + +typedef struct sxe_attr_pair + { + ST_CHAR *name; + ST_CHAR *value; + } SXE_ATTR_PAIR; + +typedef struct sxd_attr_pair + { + ST_CHAR name[SX_MAX_ATTR_NAME]; + ST_CHAR value[SX_MAX_ATTR_VALUE]; + } SXD_ATTR_PAIR; + +typedef struct sx_dec_element_info + { + ST_CHAR tag[SX_MAX_TAG_LEN]; /* start/end */ + ST_CHAR *tagStart; /* tag start pointer */ + /* NOTE: "entityStart" is NOT used if USE_EXPAT defined */ + ST_CHAR *entityStart; /* start (and simple end) */ + ST_UINT attrCount; /* start (and simple end) */ + SXD_ATTR_PAIR attr[SX_MAX_ATTRIB]; /* start (and simple end) */ + /* NOTE: "entityEnd" is NOT used if USE_EXPAT defined */ + ST_CHAR *entityEnd; /* end */ + } SX_DEC_ELEMENT_INFO; + +typedef struct sx_dec_ctrl + { + /* NOTE: the following five params are used ONLY if USE_EXPAT defined */ + ST_VOID *parser; /* save XML_Parser here (cast to (ST_VOID *)) */ + ST_INT skipNestLevel; /* skip tags until back at this nest level */ + ST_INT entityLen; /* len of current entity */ + ST_INT entityBufSize; /* len of entity buffer */ + ST_CHAR *entityBuf; /* ptr to entity buffer */ + +/* XML being decoded */ + ST_CHAR *xmlStart; + ST_INT xmlLen; + + ST_BOOLEAN useFp; + ST_BOOLEAN ignoreNS; + FILE *fp; +/* Decoded element information */ + ST_INT reason; /* SX_ELEMENT_START, SX_ELEMENT_END */ + SX_DEC_ELEMENT_INFO sxDecElInfo; + ST_CHAR elemBuf[SX_MAX_ELEM_LEN+1]; /* tmp buffer for an element */ + +/* Set to != SD_SUCCESS for error */ + ST_RET errCode; /* defined above */ + ST_BOOLEAN termFlag; /* set if you want to terminate decode */ + +/* Set to SD_TRUE to disable numOcc checks */ + ST_BOOLEAN noOccCheck; + +/* Internal use */ + SX_ELEMENT *item; + ST_INT itemStackLevel; + SX_ELEMENT_TBL_CTRL items[SX_MAX_STACK_LEVEL]; + ST_BOOLEAN auto_pop[SX_MAX_STACK_LEVEL]; + + ST_INT xmlNestLevel; + SX_ELEMENT *elTbl[SX_MAX_XML_NEST]; + /* NOTE: "xmlPos" is NOT used if USE_EXPAT defined */ + ST_CHAR *xmlPos; + + ST_INT numAlloced; /* Used to keep track of dynamically allocated message buffers */ + ST_INT numAlloced2; + ST_INT numAlloced3; + ST_INT numAlloced4; + +/* User fields */ + ST_VOID *usr; + ST_VOID *elUser; + ST_VOID *unkElUser; + + /* The initial values for these pointers are passed to the functions */ + /* sx_parse_mt or sx_parseEx_mt. */ + ST_RET (*u_sx_el_start) (struct sx_dec_ctrl *sxDecCtrl, ST_CHAR *tag); + ST_RET (*u_sx_el_end) (struct sx_dec_ctrl *sxDecCtrl, ST_CHAR *tag); + } SX_DEC_CTRL ; + +/************************************************************************/ + +#define SX_PUSH(itemTbl)\ + sx_push (sxDecCtrl, sizeof(itemTbl)/sizeof(SX_ELEMENT), itemTbl, SD_TRUE) + +/* Thread safe versions of XML parsing */ +/* They are using the u_sx_el_xxx defined in the SX_DEC_CTRL) */ +ST_RET sx_parse_mt (ST_LONG lMsgLen, ST_CHAR *xml, ST_INT numItems, + SX_ELEMENT *itemTbl, ST_VOID *usr, + ST_RET (*u_sx_el_start_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag), + ST_RET (*u_sx_el_end_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag)); +ST_RET sx_parseEx_mt (ST_CHAR *fileName, ST_INT numItems, + SX_ELEMENT *itemTbl, ST_VOID *usr, + ST_RET (*u_sx_el_start_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag), + ST_RET (*u_sx_el_end_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag)); +ST_RET sx_parseExx_mt (ST_CHAR *fileName, ST_INT numItems, + SX_ELEMENT *itemTbl, ST_VOID *usr, + ST_RET (*u_sx_el_start_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag), + ST_RET (*u_sx_el_end_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag)); + +ST_VOID sx_push (SX_DEC_CTRL *sxDecCtrl, ST_INT numItems, + SX_ELEMENT *itemTbl, ST_BOOLEAN auto_pop); +ST_VOID sx_pop (SX_DEC_CTRL *sxDecCtrl); + + +ST_RET sx_get_entity (SX_DEC_CTRL *sxDecCtrl, + ST_CHAR *destBuf, ST_INT destLen, + ST_INT *lenOut); +ST_RET sx_get_int (SX_DEC_CTRL *sxDecCtrl, ST_INT *out_ptr); +ST_RET sx_get_float (SX_DEC_CTRL *sxDecCtrl, ST_FLOAT *out_ptr); +ST_RET sx_get_double (SX_DEC_CTRL *sxDecCtrl, ST_DOUBLE *out_ptr); +ST_RET sx_get_uchar (SX_DEC_CTRL *sxDecCtrl, ST_UCHAR *out_ptr); +ST_RET sx_get_int16 (SX_DEC_CTRL *sxDecCtrl, ST_INT16 *out_ptr); +ST_RET sx_get_uint16 (SX_DEC_CTRL *sxDecCtrl, ST_UINT16 *out_ptr); +ST_RET sx_get_int32 (SX_DEC_CTRL *sxDecCtrl, ST_INT32 *out_ptr); +ST_RET sx_get_uint32 (SX_DEC_CTRL *sxDecCtrl, ST_UINT32 *out_ptr); +ST_RET sx_get_uint32_hex (SX_DEC_CTRL *sxDecCtrl, ST_UINT32 *out_ptr); +ST_RET sx_get_long (SX_DEC_CTRL *sxDecCtrl, ST_LONG *out_ptr); +ST_RET sx_get_ulong (SX_DEC_CTRL *sxDecCtrl, ST_ULONG *out_ptr); +ST_RET sx_get_bool (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN *out_ptr); +ST_RET sx_get_duration (SX_DEC_CTRL *sxDecCtrl, SX_DURATION *sxDuration); +ST_RET sx_get_xtime (SX_DEC_CTRL *sxDecCtrl, SX_DATE_TIME *sxDateTime); +ST_RET sx_get_tm (SX_DEC_CTRL *sxDecCtrl, struct tm *out_ptr); +ST_RET sx_get_tm_ex (SX_DEC_CTRL *sxDecCtrl, struct tm *out_ptr, ST_LONG *microseconds); +ST_RET sx_get_time (SX_DEC_CTRL *sxDecCtrl, time_t *out_ptr); +ST_RET sx_get_time_ex (SX_DEC_CTRL *sxDecCtrl, time_t *out_ptr, ST_LONG *microseconds); +ST_RET sx_get_uint (SX_DEC_CTRL *sxDecCtrl, ST_UINT *out_ptr); +ST_RET sx_get_alloc_string (SX_DEC_CTRL *sxDecCtrl, ST_CHAR **strOut); +ST_RET sx_get_string_ptr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR **strOut, ST_INT *lenOut); +ST_RET sx_get_string (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *dest, ST_INT *lenOut); +ST_RET sx_get_string_YesNo (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN *dest, ST_RET errCode); +ST_RET sx_get_string_OnOff_mask (SX_DEC_CTRL *sxDecCtrl, ST_UINT *mask, ST_UINT maskBit, + ST_RET errCode); +ST_RET sx_get_string_OnOff_bool (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN *dest, ST_RET errCode); +ST_VOID sx_format_string_dec (ST_CHAR *dest, ST_CHAR *src); +ST_VOID sx_format_string_enc (ST_CHAR *dest, ST_CHAR *src); +ST_VOID sx_format_nstring_enc (ST_CHAR *dest, ST_CHAR *src, ST_INT len); +ST_RET sx_get_bitstring (SX_DEC_CTRL *sxDecCtrl, ST_INT *dest, ST_INT *lenOut); +ST_RET sx_get_element_contents (SX_DEC_CTRL *sxDecCtrl, + ST_CHAR *destBuf, ST_INT destLen, + ST_INT *lenOut); +ST_RET sx_find_element_contents (SX_DEC_CTRL *sxDecCtrl, + ST_CHAR **elStartOut, ST_INT *lenOut); + +ST_RET sx_get_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *value, ST_CHAR *name); +ST_RET sx_get_attr_ptr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR **ptrOut, ST_CHAR *name); +ST_RET sx_get_bool_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_BOOLEAN *out_ptr); +ST_RET sx_get_int_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_INT *out_ptr); +ST_RET sx_get_float_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_FLOAT *out_ptr); +ST_RET sx_get_double_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_DOUBLE *out_ptr); +ST_RET sx_get_uchar_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UCHAR *out_ptr); +ST_RET sx_get_int16_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_INT16 *out_ptr); +ST_RET sx_get_uint16_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UINT16 *out_ptr); +ST_RET sx_get_int32_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_INT32 *out_ptr); +ST_RET sx_get_uint32_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UINT32 *out_ptr); +ST_RET sx_get_long_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_LONG *out_ptr); +ST_RET sx_get_ulong_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_ULONG *out_ptr); +ST_RET sx_get_uint_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UINT *out_ptr); +ST_RET sx_get_duration_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, SX_DURATION *out_ptr); +ST_RET sx_get_xtime_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, SX_DATE_TIME *out_ptr); +ST_RET sx_get_tm_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, struct tm *out_ptr); + +#define sxd_decode_data_el(elName,xml,xmlLen,xmlUsed,vdp,typeId,elPres,checkDt)\ + _sxd_decode_data_el(elName,xml,xmlLen,xmlUsed,vdp,typeId,elPres,sxdDefXmlStyle,checkDt) + + +ST_RET _sxd_decode_data_el (ST_CHAR *elName, + ST_CHAR *xml, ST_INT xmlLen, ST_INT *xmlUsed, + ST_VOID *vdp, ST_INT typeId, + ST_BOOLEAN *elPres, ST_INT sxdXmlStyle, ST_BOOLEAN checkDt); + +ST_VOID sxStartElement (SX_DEC_CTRL *sxDecCtrl); +ST_VOID sxEndElement (SX_DEC_CTRL *sxDecCtrl); +ST_RET sx_get_value (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *format_string, ST_VOID *out_ptr); +ST_RET sx_get_attr_value (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, + ST_CHAR *format_string, ST_VOID *out_ptr); + +ST_VOID sx_load_characters (ST_CHAR *lineBuf, ST_BOOLEAN *eof, FILE *fp, ST_INT numToRead); + + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +/* max prefix length in SXD_XML_STYLE_A */ +#define SXD_MAX_PREFIX 100 + +typedef struct sx_enc_ctrl + { + ST_INT xmlBufLen; + ST_CHAR *xmlBuf; + ST_CHAR *xmlBufEnd; + + ST_BOOLEAN useFp; + FILE *fp; + + ST_CHAR *nextWritePos; + + ST_INT currNestLevel; + ST_CHAR tags[SX_MAX_STACK_LEVEL][SX_MAX_TAG_LEN+1]; + ST_RET errCode; + + ST_BOOLEAN bUseFormatting; + ST_BOOLEAN bOneLineEl; + + ST_BOOLEAN bUnformattedStrings; + +/* Used for data encoding */ + ST_BOOLEAN encDt; + ST_CHAR *outerElement; + ST_INT sxdXmlStyle; + ST_CHAR sxdPrefix[SXD_MAX_PREFIX+1]; /* only for SXD_XML_STYLE_A */ + ST_INT sxdStructNestLevel; /* only for SXD_XML_STYLE_A */ + + ST_VOID *usr; + } SX_ENC_CTRL; + +/* Macro for getting current encoded length */ +#define SX_ENC_LEN(__sxEncCtrl) ((__sxEncCtrl)->nextWritePos - (__sxEncCtrl)->xmlBuf) + +/************************************************************************/ +/************************************************************************/ + +SX_ENC_CTRL *sx_start_encode (ST_CHAR *xmlBuf, ST_INT xmlBufLen); +SX_ENC_CTRL *sx_start_encodeEx (ST_CHAR *fileName); +ST_VOID sx_end_encode (SX_ENC_CTRL *sxEncCtrl); +ST_VOID sx_init_encode (SX_ENC_CTRL *sxEncCtrl, + ST_CHAR *xmlBuf, ST_INT xmlBufLen); +ST_RET sx_init_encodeEx (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *fileName); + +#define sx_start_element(sxEncCtrl,tag,numAttr,attr)\ + sx_write_element(sxEncCtrl,tag,numAttr,attr,SD_FALSE,SD_FALSE); + +#define sx_write_empty_element(sxEncCtrl,tag,numAttr,attr)\ + sx_write_element(sxEncCtrl,tag,numAttr,attr,SD_FALSE,SD_TRUE); + +ST_VOID sx_end_element (SX_ENC_CTRL *sxEncCtrl); +ST_VOID sx_write_element (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *tag, + ST_INT numAttr, SXE_ATTR_PAIR *attr, + ST_BOOLEAN end, ST_BOOLEAN empty); + +/* Defines for 'no attribute' cases */ +#define sx_wr_string_el(sxEncCtrl,tag,str)\ + sx_wrx_string_el(sxEncCtrl,tag,str,0,NULL) + +#define sx_wr_nstring_el(sxEncCtrl,tag,str,len)\ + sx_wrx_nstring_el(sxEncCtrl,tag,str,len,0,NULL) + +#define sx_wr_int_el(sxEncCtrl,tag,val)\ + sx_wrx_int_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_uint_el(sxEncCtrl,tag,val)\ + sx_wrx_uint_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_ulong_el(sxEncCtrl,tag,val)\ + sx_wrx_ulong_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_uint32_hex_el(sxEncCtrl,tag,val)\ + sx_wrx_uint32_hex_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_float_el(sxEncCtrl,tag,val)\ + sx_wrx_float_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_double_el(sxEncCtrl,tag,val)\ + sx_wrx_double_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_long_el(sxEncCtrl,tag,val)\ + sx_wrx_long_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_bool_el(sxEncCtrl,tag,val)\ + sx_wrx_bool_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_tm_el(sxEncCtrl,tag,val)\ + sx_wrx_tm_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_time_el(sxEncCtrl,tag,val)\ + sx_wrx_time_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_duration_el(sxEncCtrl,tag,val)\ + sx_wrx_duration_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_xtime_el(sxEncCtrl,tag,val)\ + sx_wrx_xtime_el(sxEncCtrl,tag,val,0,NULL) + +#define sx_wr_cdata_el(sxEncCtrl,tag,str, len)\ + sx_wrx_cdata_el(sxEncCtrl,tag,str,len,0,NULL) + +/* Functions to write elements and element contents */ +ST_VOID sx_wr_string (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *str); +ST_VOID sx_wrx_string_el (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *tag, ST_CHAR *str, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_nstring (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *str, ST_INT len); +ST_VOID sx_wrx_nstring_el (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *tag, ST_CHAR *str, ST_INT len, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_bitstring (SX_ENC_CTRL *sxEncCtrl, ST_INT numBits, + ST_UINT8 *bitStr); +ST_VOID sx_wrx_bitstring_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, + ST_INT numBits, ST_UINT8 *bitStr, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_int (SX_ENC_CTRL *sxEncCtrl, ST_INT val); +ST_VOID sx_wrx_int_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_INT val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_uint (SX_ENC_CTRL *sxEncCtrl, ST_UINT val); +ST_VOID sx_wrx_uint_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_UINT val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_ulong (SX_ENC_CTRL *sxEncCtrl, ST_ULONG val); +ST_VOID sx_wrx_ulong_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_ULONG val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_uint32_hex (SX_ENC_CTRL *sxEncCtrl, ST_UINT32 val); +ST_VOID sx_wrx_uint32_hex_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_UINT32 val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_float (SX_ENC_CTRL *sxEncCtrl, ST_FLOAT val); +ST_VOID sx_wrx_float_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_FLOAT val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_double (SX_ENC_CTRL *sxEncCtrl, ST_DOUBLE val); +ST_VOID sx_wrx_double_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_DOUBLE val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_long (SX_ENC_CTRL *sxEncCtrl, ST_LONG val); +ST_VOID sx_wrx_long_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_LONG val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_bool (SX_ENC_CTRL *sxEncCtrl, ST_BOOLEAN val); +ST_VOID sx_wrx_bool_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_BOOLEAN val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_tm (SX_ENC_CTRL *sxEncCtrl, struct tm *val); +ST_VOID sx_wrx_tm_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, struct tm *val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_time (SX_ENC_CTRL *sxEncCtrl, time_t val); +ST_VOID sx_wrx_time_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, time_t val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_duration (SX_ENC_CTRL *sxEncCtrl, SX_DURATION *sxDuration); +ST_VOID sx_wrx_duration_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, SX_DURATION *val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_xtime (SX_ENC_CTRL *sxEncCtrl, SX_DATE_TIME *sxDateTime); +ST_VOID sx_wrx_xtime_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, SX_DATE_TIME *val, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +ST_VOID sx_wr_cdata (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *str, ST_INT len); +ST_VOID sx_wrx_cdata_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, + ST_CHAR *str, ST_INT len, + ST_INT numAttr, SXE_ATTR_PAIR *attr); + +#define sxd_wr_data(ec,typeId,elName,data,encodeDt,elPres)\ + _sxd_wr_data(ec,typeId,elName,data,sxdDefXmlStyle,encodeDt,elPres)\ + +ST_RET _sxd_wr_data (SX_ENC_CTRL *sxEncCtrl, ST_INT typeId, + ST_CHAR *elName, ST_VOID *data, ST_INT sxdXmlStyle, + ST_BOOLEAN encodeDt, ST_BOOLEAN *elPres); + + +ST_VOID sx_add_string (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *_src, + ST_CHAR **writePosIo); +ST_RET sx_add_buf (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *_src, ST_INT _srcLen, + ST_CHAR **writePosIo); +ST_VOID sx_wr_comment (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *str); + +ST_RET XmlStringToDuration (ST_CHAR *src, SX_DURATION *out_ptr); +ST_RET XmlDurationToString (ST_CHAR *buffer, ST_LONG size, SX_DURATION *sxDuration); + +/************************************************************************/ +#ifdef __cplusplus +} +#endif + +#endif /* SX_DEFS_INCLUDED */ + diff --git a/mmslib/inc/sx_log.h b/mmslib/inc/sx_log.h new file mode 100644 index 0000000..36a3670 --- /dev/null +++ b/mmslib/inc/sx_log.h @@ -0,0 +1,337 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999 - 2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : sx_log.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/02/05 EJV 07 Add sx_debug_sel_cfg to save SX masks while */ +/* logging configuration is parsed. */ +/* 05/06/04 DWL 06 Use new "Base" macros SLOG_*, SLOGC_*, SLOGH.*/ +/* 06/06/01 GLB 05 Added SXLOG_CFLOW2 */ +/* 04/26/01 EJV 04 Added/rearranged slog macros for !DEBUG_SISCO*/ +/* 01/25/01 JRB 03 Added SXLOG_ERR2,3 */ +/* 10/30/99 MDE 02 Added SXLOG_NERR3 */ +/* 09/17/99 MDE 01 New */ +/************************************************************************/ + +#ifndef SX_LOG_INCLUDED +#define SX_LOG_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/************************************************************************/ + +#include "slog.h" + +/************************************************************************/ +/* sx_debug_sel bit assignments */ + +#define SX_LOG_DEC 0x0001 +#define SX_LOG_ENC 0x0002 +#define SX_LOG_FLOW 0x0004 +#define SX_LOG_DEBUG 0x0008 +#define SX_LOG_ERR 0x0010 +#define SX_LOG_NERR 0x0020 + +extern ST_UINT sx_debug_sel; +extern ST_UINT sx_debug_sel_cfg; /* saves SX masks while logging configuration is parsed */ + +/* Log type strings */ +extern SD_CONST ST_CHAR *SD_CONST _sx_log_dec_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sx_log_enc_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sx_log_flow_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sx_log_debug_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sx_log_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _sx_log_nerr_logstr; + +/************************************************************************/ +/* Decode log macros */ +#define SXLOG_DEC0(a) \ + SLOG_0 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a) +#define SXLOG_DEC1(a,b) \ + SLOG_1 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b) +#define SXLOG_DEC2(a,b,c) \ + SLOG_2 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b,c) +#define SXLOG_DEC3(a,b,c,d) \ + SLOG_3 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b,c,d) +#define SXLOG_DEC4(a,b,c,d,e) \ + SLOG_4 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b,c,d,e) +#define SXLOG_DEC5(a,b,c,d,e,f) \ + SLOG_5 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b,c,d,e,f) +#define SXLOG_DEC6(a,b,c,d,e,f,g) \ + SLOG_6 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b,c,d,e,f,g) +#define SXLOG_DEC7(a,b,c,d,e,f,g,h) \ + SLOG_7 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b,c,d,e,f,g,h) +#define SXLOG_DEC8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (sx_debug_sel & SX_LOG_DEC,_sx_log_dec_logstr,a,b,c,d,e,f,g,h,i) + +/* Decode continuation log macros */ +#define SXLOG_CDEC0(a) \ + SLOGC_0 (sx_debug_sel & SX_LOG_DEC,a) +#define SXLOG_CDEC1(a,b) \ + SLOGC_1 (sx_debug_sel & SX_LOG_DEC,a,b) +#define SXLOG_CDEC2(a,b,c) \ + SLOGC_2 (sx_debug_sel & SX_LOG_DEC,a,b,c) +#define SXLOG_CDEC3(a,b,c,d) \ + SLOGC_3 (sx_debug_sel & SX_LOG_DEC,a,b,c,d) +#define SXLOG_CDEC4(a,b,c,d,e) \ + SLOGC_4 (sx_debug_sel & SX_LOG_DEC,a,b,c,d,e) +#define SXLOG_CDEC5(a,b,c,d,e,f) \ + SLOGC_5 (sx_debug_sel & SX_LOG_DEC,a,b,c,d,e,f) +#define SXLOG_CDEC6(a,b,c,d,e,f,g) \ + SLOGC_6 (sx_debug_sel & SX_LOG_DEC,a,b,c,d,e,f,g) +#define SXLOG_CDEC7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (sx_debug_sel & SX_LOG_DEC,a,b,c,d,e,f,g,h) +#define SXLOG_CDEC8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (sx_debug_sel & SX_LOG_DEC,a,b,c,d,e,f,g,h,i) + +/* Decode Hex log macro */ +#define SXLOG_DECH(a,b) \ + SLOGH (sx_debug_sel & SX_LOG_DEC,a,b) + +/************************************************************************/ +/* Encode log macros */ +#define SXLOG_ENC0(a) \ + SLOG_0 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a) +#define SXLOG_ENC1(a,b) \ + SLOG_1 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b) +#define SXLOG_ENC2(a,b,c) \ + SLOG_2 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b,c) +#define SXLOG_ENC3(a,b,c,d) \ + SLOG_3 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b,c,d) +#define SXLOG_ENC4(a,b,c,d,e) \ + SLOG_4 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b,c,d,e) +#define SXLOG_ENC5(a,b,c,d,e,f) \ + SLOG_5 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b,c,d,e,f) +#define SXLOG_ENC6(a,b,c,d,e,f,g) \ + SLOG_6 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b,c,d,e,f,g) +#define SXLOG_ENC7(a,b,c,d,e,f,g,h) \ + SLOG_7 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b,c,d,e,f,g,h) +#define SXLOG_ENC8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (sx_debug_sel & SX_LOG_ENC,_sx_log_enc_logstr,a,b,c,d,e,f,g,h,i) + +/* Encode continuation log macros */ +#define SXLOG_CENC0(a) \ + SLOGC_0 (sx_debug_sel & SX_LOG_ENC,a) +#define SXLOG_CENC1(a,b) \ + SLOGC_1 (sx_debug_sel & SX_LOG_ENC,a,b) +#define SXLOG_CENC2(a,b,c) \ + SLOGC_2 (sx_debug_sel & SX_LOG_ENC,a,b,c) +#define SXLOG_CENC3(a,b,c,d) \ + SLOGC_3 (sx_debug_sel & SX_LOG_ENC,a,b,c,d) +#define SXLOG_CENC4(a,b,c,d,e) \ + SLOGC_4 (sx_debug_sel & SX_LOG_ENC,a,b,c,d,e) +#define SXLOG_CENC5(a,b,c,d,e,f) \ + SLOGC_5 (sx_debug_sel & SX_LOG_ENC,a,b,c,d,e,f) +#define SXLOG_CENC6(a,b,c,d,e,f,g) \ + SLOGC_6 (sx_debug_sel & SX_LOG_ENC,a,b,c,d,e,f,g) +#define SXLOG_CENC7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (sx_debug_sel & SX_LOG_ENC,a,b,c,d,e,f,g,h) +#define SXLOG_CENC8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (sx_debug_sel & SX_LOG_ENC,a,b,c,d,e,f,g,h,i) + +/* Encode Hex log macro */ +#define SXLOG_ENCH(a,b) \ + SLOGH (sx_debug_sel & SX_LOG_ENC,a,b) + +/************************************************************************/ +/* Flow log macros */ +#define SXLOG_FLOW0(a) \ + SLOG_0 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a) +#define SXLOG_FLOW1(a,b) \ + SLOG_1 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b) +#define SXLOG_FLOW2(a,b,c) \ + SLOG_2 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b,c) +#define SXLOG_FLOW3(a,b,c,d) \ + SLOG_3 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b,c,d) +#define SXLOG_FLOW4(a,b,c,d,e) \ + SLOG_4 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b,c,d,e) +#define SXLOG_FLOW5(a,b,c,d,e,f) \ + SLOG_5 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b,c,d,e,f) +#define SXLOG_FLOW6(a,b,c,d,e,f,g) \ + SLOG_6 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b,c,d,e,f,g) +#define SXLOG_FLOW7(a,b,c,d,e,f,g,h) \ + SLOG_7 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b,c,d,e,f,g,h) +#define SXLOG_FLOW8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (sx_debug_sel & SX_LOG_FLOW,_sx_log_flow_logstr,a,b,c,d,e,f,g,h,i) + +/* Flow continuation log macros */ +#define SXLOG_CFLOW0(a) \ + SLOGC_0 (sx_debug_sel & SX_LOG_FLOW,a) +#define SXLOG_CFLOW1(a,b) \ + SLOGC_1 (sx_debug_sel & SX_LOG_FLOW,a,b) +#define SXLOG_CFLOW2(a,b,c) \ + SLOGC_2 (sx_debug_sel & SX_LOG_FLOW,a,b,c) +#define SXLOG_CFLOW3(a,b,c,d) \ + SLOGC_3 (sx_debug_sel & SX_LOG_FLOW,a,b,c,d) +#define SXLOG_CFLOW4(a,b,c,d,e) \ + SLOGC_4 (sx_debug_sel & SX_LOG_FLOW,a,b,c,d,e) +#define SXLOG_CFLOW5(a,b,c,d,e,f) \ + SLOGC_5 (sx_debug_sel & SX_LOG_FLOW,a,b,c,d,e,f) +#define SXLOG_CFLOW6(a,b,c,d,e,f,g) \ + SLOGC_6 (sx_debug_sel & SX_LOG_FLOW,a,b,c,d,e,f,g) +#define SXLOG_CFLOW7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (sx_debug_sel & SX_LOG_FLOW,a,b,c,d,e,f,g,h) +#define SXLOG_CFLOW8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (sx_debug_sel & SX_LOG_FLOW,a,b,c,d,e,f,g,h,i) + +/* Flow Hex log macro */ +#define SXLOG_FLOWH(a,b) \ + SLOGH (sx_debug_sel & SX_LOG_FLOW,a,b) + +/************************************************************************/ +/* Debug log macros */ +#define SXLOG_DEBUG0(a) \ + SLOG_0 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a) +#define SXLOG_DEBUG1(a,b) \ + SLOG_1 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b) +#define SXLOG_DEBUG2(a,b,c) \ + SLOG_2 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b,c) +#define SXLOG_DEBUG3(a,b,c,d) \ + SLOG_3 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b,c,d) +#define SXLOG_DEBUG4(a,b,c,d,e) \ + SLOG_4 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b,c,d,e) +#define SXLOG_DEBUG5(a,b,c,d,e,f) \ + SLOG_5 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b,c,d,e,f) +#define SXLOG_DEBUG6(a,b,c,d,e,f,g) \ + SLOG_6 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b,c,d,e,f,g) +#define SXLOG_DEBUG7(a,b,c,d,e,f,g,h) \ + SLOG_7 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b,c,d,e,f,g,h) +#define SXLOG_DEBUG8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (sx_debug_sel & SX_LOG_DEBUG,_sx_log_debug_logstr,a,b,c,d,e,f,g,h,i) + +/* Debug continuation log macros */ +#define SXLOG_CDEBUG0(a) \ + SLOGC_0 (sx_debug_sel & SX_LOG_DEBUG,a) +#define SXLOG_CDEBUG1(a,b) \ + SLOGC_1 (sx_debug_sel & SX_LOG_DEBUG,a,b) +#define SXLOG_CDEBUG2(a,b,c) \ + SLOGC_2 (sx_debug_sel & SX_LOG_DEBUG,a,b,c) +#define SXLOG_CDEBUG3(a,b,c,d) \ + SLOGC_3 (sx_debug_sel & SX_LOG_DEBUG,a,b,c,d) +#define SXLOG_CDEBUG4(a,b,c,d,e) \ + SLOGC_4 (sx_debug_sel & SX_LOG_DEBUG,a,b,c,d,e) +#define SXLOG_CDEBUG5(a,b,c,d,e,f) \ + SLOGC_5 (sx_debug_sel & SX_LOG_DEBUG,a,b,c,d,e,f) +#define SXLOG_CDEBUG6(a,b,c,d,e,f,g) \ + SLOGC_6 (sx_debug_sel & SX_LOG_DEBUG,a,b,c,d,e,f,g) +#define SXLOG_CDEBUG7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (sx_debug_sel & SX_LOG_DEBUG,a,b,c,d,e,f,g,h) +#define SXLOG_CDEBUG8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (sx_debug_sel & SX_LOG_DEBUG,a,b,c,d,e,f,g,h,i) + +/* Debug Hex log macro */ +#define SXLOG_DEBUGH(a,b) \ + SLOGH (sx_debug_sel & SX_LOG_DEBUG,a,b) + +/************************************************************************/ +/* Err log macros */ +#define SXLOG_ERR0(a) \ + SLOG_0 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a) +#define SXLOG_ERR1(a,b) \ + SLOG_1 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b) +#define SXLOG_ERR2(a,b,c) \ + SLOG_2 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b,c) +#define SXLOG_ERR3(a,b,c,d) \ + SLOG_3 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b,c,d) +#define SXLOG_ERR4(a,b,c,d,e) \ + SLOG_4 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b,c,d,e) +#define SXLOG_ERR5(a,b,c,d,e,f) \ + SLOG_5 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b,c,d,e,f) +#define SXLOG_ERR6(a,b,c,d,e,f,g) \ + SLOG_6 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b,c,d,e,f,g) +#define SXLOG_ERR7(a,b,c,d,e,f,g,h) \ + SLOG_7 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b,c,d,e,f,g,h) +#define SXLOG_ERR8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (sx_debug_sel & SX_LOG_ERR,_sx_log_err_logstr,a,b,c,d,e,f,g,h,i) + +/* Err continuation log macros */ +#define SXLOG_CERR0(a) \ + SLOGC_0 (sx_debug_sel & SX_LOG_ERR,a) +#define SXLOG_CERR1(a,b) \ + SLOGC_1 (sx_debug_sel & SX_LOG_ERR,a,b) +#define SXLOG_CERR2(a,b,c) \ + SLOGC_2 (sx_debug_sel & SX_LOG_ERR,a,b,c) +#define SXLOG_CERR3(a,b,c,d) \ + SLOGC_3 (sx_debug_sel & SX_LOG_ERR,a,b,c,d) +#define SXLOG_CERR4(a,b,c,d,e) \ + SLOGC_4 (sx_debug_sel & SX_LOG_ERR,a,b,c,d,e) +#define SXLOG_CERR5(a,b,c,d,e,f) \ + SLOGC_5 (sx_debug_sel & SX_LOG_ERR,a,b,c,d,e,f) +#define SXLOG_CERR6(a,b,c,d,e,f,g) \ + SLOGC_6 (sx_debug_sel & SX_LOG_ERR,a,b,c,d,e,f,g) +#define SXLOG_CERR7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (sx_debug_sel & SX_LOG_ERR,a,b,c,d,e,f,g,h) +#define SXLOG_CERR8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (sx_debug_sel & SX_LOG_ERR,a,b,c,d,e,f,g,h,i) + +/* Err Hex log macro */ +#define SXLOG_ERRH(a,b) \ + SLOGH (sx_debug_sel & SX_LOG_ERR,a,b) + +/************************************************************************/ +/* NErr log macros */ +#define SXLOG_NERR0(a) \ + SLOG_0 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a) +#define SXLOG_NERR1(a,b) \ + SLOG_1 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b) +#define SXLOG_NERR2(a,b,c) \ + SLOG_2 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b,c) +#define SXLOG_NERR3(a,b,c,d) \ + SLOG_3 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b,c,d) +#define SXLOG_NERR4(a,b,c,d,e) \ + SLOG_4 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b,c,d,e) +#define SXLOG_NERR5(a,b,c,d,e,f) \ + SLOG_5 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b,c,d,e,f) +#define SXLOG_NERR6(a,b,c,d,e,f,g) \ + SLOG_6 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b,c,d,e,f,g) +#define SXLOG_NERR7(a,b,c,d,e,f,g,h) \ + SLOG_7 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b,c,d,e,f,g,h) +#define SXLOG_NERR8(a,b,c,d,e,f,g,h,i) \ + SLOG_8 (sx_debug_sel & SX_LOG_NERR,_sx_log_nerr_logstr,a,b,c,d,e,f,g,h,i) + +/* NErr continuation log macros */ +#define SXLOG_CNERR0(a) \ + SLOGC_0 (sx_debug_sel & SX_LOG_NERR,a) +#define SXLOG_CNERR1(a,b) \ + SLOGC_1 (sx_debug_sel & SX_LOG_NERR,a,b) +#define SXLOG_CNERR2(a,b,c) \ + SLOGC_2 (sx_debug_sel & SX_LOG_NERR,a,b,c) +#define SXLOG_CNERR3(a,b,c,d) \ + SLOGC_3 (sx_debug_sel & SX_LOG_NERR,a,b,c,d) +#define SXLOG_CNERR4(a,b,c,d,e) \ + SLOGC_4 (sx_debug_sel & SX_LOG_NERR,a,b,c,d,e) +#define SXLOG_CNERR5(a,b,c,d,e,f) \ + SLOGC_5 (sx_debug_sel & SX_LOG_NERR,a,b,c,d,e,f) +#define SXLOG_CNERR6(a,b,c,d,e,f,g) \ + SLOGC_6 (sx_debug_sel & SX_LOG_NERR,a,b,c,d,e,f,g) +#define SXLOG_CNERR7(a,b,c,d,e,f,g,h) \ + SLOGC_7 (sx_debug_sel & SX_LOG_NERR,a,b,c,d,e,f,g,h) +#define SXLOG_CNERR8(a,b,c,d,e,f,g,h,i) \ + SLOGC_8 (sx_debug_sel & SX_LOG_NERR,a,b,c,d,e,f,g,h,i) + +/* NErr Hex log macro */ +#define SXLOG_NERRH(a,b) \ + SLOGH (sx_debug_sel & SX_LOG_NERR,a,b) +/************************************************************************/ + + +#ifdef __cplusplus +} +#endif + +/************************************************************************/ +#endif /* End of SX_LOG_INCLUDED */ +/************************************************************************/ diff --git a/mmslib/inc/sysincs.h b/mmslib/inc/sysincs.h new file mode 100644 index 0000000..8929593 --- /dev/null +++ b/mmslib/inc/sysincs.h @@ -0,0 +1,459 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2008, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : sysincs.h */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* The purpose of this include file is to bring in include files */ +/* that come with one of the various C compilers. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/27/08 EJV 48 Defined S_MAX_PATH for all systems. */ +/* 01/15/08 EJV 47 Added S_FMT_* helper macros for (s)printf. */ +/* 11/01/07 EJV UNIX, Linux: added define MAX_PATH. */ +/* 02/28/08 JRB 46 Add timeb.h for _WIN32, linux, QNX. */ +/* 10/03/07 JRB 45 Add winsock2.h BEFORE windows.h */ +/* Add #pragma for _WIN32. */ +/* 11/08/06 EJV 44 HP-UX: use */ +/* 07/10/06 EJV 43 Sun: chg inlude to . */ +/* 06/19/06 EJV 42 VXWORKS, QNX: added . */ +/* UNIX, Linux: added . */ +/* 02/28/06 EJV 41 Added pragma to disable warning C4996 (about */ +/* deprecated functions). */ +/* 01/30/06 GLB 33 Integrated porting changes for VMS */ +/* 02/13/06 DSF 39 Migrate to VS.NET 2005 */ +/* 12/16/05 GLB 38 Added "unix.h" for "ftruncate" */ +/* 11/21/05 DSF 37 Do not enforce definition of ASSERT */ +/* 09/28/05 EJV 36 Moved filio.h for sun (from gensock2.c). */ +/* 08/10/05 JRB 35 Fixed a few newline characters. */ +/* 07/15/05 DSF 34 Fixed SASSERT warnings for release builds */ +/* 05/24/05 EJV 33 UNIX, Linux: added include */ +/* 03/18/05 DSF 32 Log asserts */ +/* 12/07/04 JRB 31 Define larger FD_SETSIZE for QNX. */ +/* 09/22/04 EJV 30 Added INADDR_NONE (needed on sun) */ +/* 07/08/04 DSF 29 Fixed SASSERT macro */ +/* 01/26/04 JRB 28 Fix LYNX includes. */ +/* 01/22/04 DSF 27 Added/modified ASSERT macros */ +/* 01/19/04 EJV 26 __hpux 10.20 does not have sys/select.h. */ +/* 12/09/03 JRB 25 Add LYNX support. Add () to max,min macros. */ +/* 10/23/03 JRB 24 Move socket includes to here. */ +/* For _WIN32, add windows.h, process.h */ +/* Del unused CDECL define. */ +/* 04/28/03 DSF 23 Make sure expression inside VERIFY is always */ +/* executed */ +/* 04/15/03 DSF 22 Don't define/undef NDEBUG */ +/* 03/18/03 JRB 21 Fix QNX #ifdef. */ +/* 02/20/03 JRB 20 Del PSOS code. */ +/* 02/17/03 CRM 19 Added "defined(linux)" code. */ +/* 02/17/03 JRB 18 Stop using SYSTEM_SEL define. */ +/* Add conio.h for WIN32. */ +/* Add sys/time.h, sys/select.h for UNIX. */ +/* Add termio.h for UNIX & QNX. */ +/* 02/27/02 EJV 17 Added limits.h to most of systems. */ +/* Check if LONG_MAX and INT_MAX defined. */ +/* 07/27/01 DSF 16 crtdbg.h should only be included if _DEBUG */ +/* is defined */ +/* 03/16/01 DSF 15 Make sure VERIFY is not defined before */ +/* defining it */ +/* 02/02/01 DSF 14 Added asserts */ +/* 01/19/01 EJV 13 Added for SYSTEM_SEL_SYS_5. */ +/* 01/03/01 EJV 12 Added for SYSTEM_SEL_SYS_5. */ +/* 10/13/00 EJV 11 Added for some SYSTEM_SEL_SYS_5. */ +/* 05/05/00 JRB 10 Added "select.h" for some systems. */ +/* 04/20/00 EJV 09 Added stdarg.h for SYSTEM_SEL_SYS_5. */ +/* 02/04/99 JRB 08 Added types.h & stat.h for most systems. */ +/* 07/01/98 JRB 07 Added stdarg.h & ctype.h for some systems. */ +/* 12/29/97 JRB 06 Cleaned up OS2 (include os2.h). More PSOS. */ +/* 12/11/97 JRB 05 Cleaned up PSOS includes. Use SYS_PSOS. */ +/* 12/11/97 JRB 04 Deleted EMBEDDED_6800 includes. */ +/* 10/29/97 EJV 03 Corrected max maro definition */ +/* 10/28/97 EJV 02 Added *.h files specific for SYS_5 */ +/* 08/15/97 EJV 01 Added *.h files specific for SYS_QNX4 */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#ifndef SYSINCS_INCLUDED +#define SYSINCS_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__OS2__) +#define INCL_BASE /* include all OS2 definitions. */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef kbhit /* The OS/2 2.0 version is not what we want */ +#undef kbhit +#endif +#include /* for _beginthread, _endthread */ +#include /* for "kill", etc. */ +/* Sockets related includes */ +#include +#include /* IPPROTO_*, etc. */ +#include /* gethostbyname, etc. */ +#include /* defines FIONBIO */ +#endif /* OS2 */ + +#if defined (_WIN32) +#if !defined (_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE +#endif +#pragma warning(disable : 4996) +#pragma warning(disable : 4786 4800) + +#if defined (_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) +#undef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 +#endif + + + +/* winsock2.h MUST ALWAYS BE BEFORE windows.h to override defs in */ +/* winsock.h (included by windows.h). Any module that includes windows.h*/ +/* before sysincs.h, must also include winsock2.h before windows.h. */ +#include /* must be before windows.h */ +#include +#include /* for _beginthread, _endthread */ +#include /* for ftime, timeb */ +#endif /* defined(_WIN32) */ + +#if defined(_WIN32) || defined(MSDOS) || defined(__MSDOS__) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#if defined(VXWORKS) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for "kill", etc. */ +/* Sockets related includes */ +#include +#include +#include +#include +#include +/*#include */ +#include /* IPPROTO_*, etc. */ +#include /* inet_addr, etc. */ +#include /* TCP_NODELAY, etc. */ +#include +#endif + +#if defined(__QNX__) +/* FD_SETSIZE default is only 32 on QNX. Must define larger value */ +/* here (before any system includes) to allow more TCP connections. */ +#define FD_SETSIZE 600 +#include +#include +#include +#include +#include +#include +#include +#include /* S_IFIFO, S_IRUSR, S_IWUSR, etc. */ +#include +#include +#include /* mknod, etc. */ +#include /* added for "ftruncate" */ +#include /* open, O_RDONLY, O_WRONLY, etc. */ +#include /* execlp, etc. */ +#include +#include +#include +#include +#include +#include /* for "kill", etc. */ +#include /* for ftime, timeb */ +/* Sockets related includes */ +#include +#include /* gethostbyname, etc. */ +#include /* IPPROTO_*, etc. */ +#include /* inet_addr, etc. */ +#include /* TCP_NODELAY, etc. */ +#include +#endif + +/* UNIX or "UNIX-like" systems */ +#if defined(_AIX) || defined(sun) || defined(__hpux) || defined(linux) \ + || (defined(__alpha) && !defined(__VMS)) || defined(__LYNX) +#include /* SHOULD be before any other include files */ +#include +#include +#include +#include +#if (!defined(__LYNX)) +#include +#include +#endif +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#include +#include +#include +#include +#include +#include /* open, O_RDONLY, O_WRONLY, etc. */ +#include +#include + +#if defined(linux) +#include /* for ftime, timeb */ +#endif + +#if defined(__hpux) +#include +#else +#include +#endif + +#if (!defined (__hpux)) && (!defined(__LYNX)) +#include +#endif +#include /* for "kill", etc. */ +#include +#if defined(sun) +#include +#endif +/* Sockets related includes */ +#if defined(__LYNX) +#include +#else +#include +#endif +#include /* gethostbyname, etc. */ +#include /* IPPROTO_*, etc. */ +#include /* for sockaddr_un */ +/* Forward references are supplied to eliminate xlC_r compiler warnings */ +struct ether_addr; /* forward reference */ +struct sockaddr_dl; /* forward reference */ +#include /* inet_addr, etc. */ +#include /* TCP_NODELAY, etc. */ +#ifndef INADDR_NONE +#define INADDR_NONE ((in_addr_t) 0xffffffff) +#endif +#endif /* defined(_AIX) || defined(sun) || defined(__hpux) || defined(linux) ... */ + +#if defined(__ECOS) +#include +#include +#include +#include +#include +#include +#include +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#if defined(__VMS) +#include +#include +#include +#include +#include +#include + +#include /* VMS descriptor stuff */ +#include /* I/O FUNCTION CODE DEFS */ +#include /* LIB$ RTL-routine signatures. */ +#include /* LIB$ RTL-routine signatures. */ +#include /* LIB$ RTL-routine signatures. */ +#include /* SS$_ sys ser return stati <8-) */ +#include /* Sys ser calls */ +#include /* ... */ +#include /* Convert floating-point data type */ +#include /* ... */ +#include /* UNIX style Signal Value Definitions */ +#include +#include +#include + +#include "stdarg.h" +#include "iostream.h" +#include +#include +#include + +#include /* TCP descriptions */ +#include /* internet system Constants and structures. */ +#include /* Network address info. */ +#include /* Network database library info. */ +#include /* TCP/IP socket definitions. */ +#include +#include /* Operations on socket (?) */ + +#define max(a,b) ((a > b) ? a : b) +#define min(a,b) ((a < b) ? a : b) +#endif + +#if (!defined(INT_MAX)) || (!defined(LONG_MAX)) +#error INT_MAX and LONG_MAX must be defined. Usually defined in limits.h +#endif + +#if defined(MAX_PATH) +#define S_MAX_PATH MAX_PATH +#elif defined(PATH_MAX) /* POSIX should have it defined in limits.h */ +#define S_MAX_PATH PATH_MAX +#else +#define S_MAX_PATH 1024 /* default */ +#endif + + /*----------------------------------------------*/ + /* printf, sprintf, sscanf helper macros */ + /*----------------------------------------------*/ + +/* helper macro for 32-bit and 64-bit pointers support */ +/* If pointer "0x%p" format is not supported then something like "0x%x",*/ +/* "0x%lx", or "0x%llx" may be used, depending on the pointer size. */ +#if defined(_WIN32) + #define S_FMT_PTR "0x%p" +#else /* all other systems (e.g. UNIX) */ + #define S_FMT_PTR "0x%p" +#endif /* all other systems (e.g. UNIX) */ + +/* helper macro for time_t */ +#if defined(_WIN32) + #if defined(_USE_32BIT_TIME_T) + #define S_FMT_TIME_T "%d" + #else + #define S_FMT_TIME_T "%I64d" + #endif +#else /* all other systems (e.g. UNIX) */ + #define S_FMT_TIME_T "%d" +#endif /* all other systems (e.g. UNIX) */ + +#ifdef INT64_SUPPORT +#ifdef _WIN32 + #define S_FMT_INT64 "%I64d" + #define S_FMT_UINT64 "%I64u" +#elif defined(_AIX) || defined(__hpux) || defined(linux) || defined(sun) || defined(__LYNX) + #define S_FMT_INT64 "%lld" + #define S_FMT_UINT64 "%llu" +#elif (defined(__alpha) && !defined(__VMS)) + #define S_FMT_INT64 "%ld" + #define S_FMT_UINT64 "%lu" +#else /* all other systems */ + #error Missing S_FMT_INT64 and S_FMT_UINT64 defines for this platform. +#endif /* all other systems */ +#endif /* INT64_SUPPORT */ + +/* helper macro for HANDLE */ +#if defined(_WIN32) + #if (_MSC_VER >= 1300) + #define S_FMT_HANDLE "0x%p" + #define S_FMT_THREAD_HANDLE "0x%p" + #else + #define S_FMT_HANDLE "%d" + #define S_FMT_THREAD_HANDLE "%lu" + #endif +#else /* all other systems (e.g. UNIX) */ + #define S_FMT_THREAD_HANDLE "0x%p" +#endif /* all other systems (e.g. UNIX) */ + + +/************************************************************************/ +/************************************************************************/ +/* Assert stuff */ +/************************************************************************/ +/************************************************************************/ + +#include + +#if defined (_WIN32) && defined (_DEBUG) +#include +#endif + +#if !defined (C_ASSERT) +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#if !defined (ASSERT) +#define ASSERT _ASSERT +#endif + +#if !defined (ASSERTE) +#define ASSERTE _ASSERTE +#endif + +#if !defined (_SASSERT) +#define _SASSERT(e) \ + { \ + int assertResult = (e) ? 1 : 0; \ + if (!assertResult) {SLOGALWAYS3("Assertion failed: '%s', file %s, line %d", #e, __FILE__, __LINE__);} \ + assert (assertResult); \ + } +#endif + +#if !defined (_SASSERTE) +#define _SASSERTE(e) \ + { \ + int assertResult = (e) ? 1 : 0; \ + if (!assertResult) {SLOGALWAYS3("Assertion failed: '%s', file %s, line %d", #e, __FILE__, __LINE__);} \ + assert (assertResult); \ + } +#endif + +#if !defined (SASSERT) +#define SASSERT _SASSERT +#endif + +#if !defined (SASSERTE) +#define SASSERTE _SASSERTE +#endif + +#if !defined (VERIFY) +#if !defined (NDEBUG) +#define VERIFY(e) _SASSERTE(e) +#else +#define VERIFY(e) ((void) (e)) +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/mmslib/inc/time_str.h b/mmslib/inc/time_str.h new file mode 100644 index 0000000..ff9d034 --- /dev/null +++ b/mmslib/inc/time_str.h @@ -0,0 +1,137 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2003, All Rights Reserved */ +/* */ +/* MODULE NAME : time_str.h */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/28/08 JRB 16 Incl "timeb.h" only in "sysincs.h" */ +/* 11/30/06 RLH 15 merge time_str and time_str2 */ +/* 07/13/06 RLH 14 tstrTimeToStringGmt and tstrStringToTimeGmt */ +/* prototypes added */ +/* 03/06/06 RLH 13 add GetTimeAndUsec, tstrTimeToStringGmt, */ +/* tstrStringToTimeGmt */ +/* 07/27/04 DWL 12 Added tstrTmToString (struct tm) */ +/* 07/16/04 DWL 11 Added tstrStringToTm (struct tm) */ +/* 10/30/03 EJV 10 Added dataLen param to UtcValueToXmlString */ +/* 10/15/03 JRB 09 Del _WIN32 ifdef. */ +/* 09/01/03 GLB 08 Added "XmlStringToUtcValue" & */ +/* "UtcValueToXmlString" */ +/* 07/12/02 NAV 07 Add UtcValsToString and UtcStringToVals */ +/* 02/02/01 EJV 06 tstrStringToTime: chg (long *) to (time_t *) */ +/* 07/13/98 NAV 05 Add _cplusplus support */ +/* 10/15/97 NAV 04 Add Btime4 Support Functions */ +/* 10/08/97 NAV 03 Add seconds to TSTR_DEF_TIME_FORMAT */ +/* 09/04/97 NAV 02 Add Btime6 Conversion routines */ +/* 11/08/94 MDE 01 New */ +/************************************************************************/ + +/************************************************************************/ +/* TIME STRING FORM FOR READ DATA */ +/* */ +/* Date{ws}Time */ +/* Time{ws}Date (? should we allow this) */ +/* Time only (uses current time) */ +/* Date only (uses current date) */ +/* */ +/* Date forms : */ +/* 12/01/56 */ +/* 12/01/1956 */ +/* 12-01-56 */ +/* 12-01-1956 */ +/* 12-1-56 */ +/* 12-1-56 */ +/* 26-Aug-1994 */ +/* 26-AUG-1994 */ +/* AUG-26-1993 */ +/* */ +/* Time forms : */ +/* 7:21:43P */ +/* 7:21:43p */ +/* 7:21:43a */ +/* 7:21:43A */ +/* 07:21:43a */ +/* 7:21:43 */ +/* 21:21:43 */ +/* */ +/************************************************************************/ +#include "sx_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* parms that control how a date is parsed in terms of field ordering */ + +#define S_DATE_ORDER_ANY 0 /* check system locale for ordering */ +#define S_DATE_ORDER_MDY 1 /* date ordering is month-day-year */ +#define S_DATE_ORDER_DMY 2 /* date ordering is day-month-year */ +#define S_DATE_ORDER_YMD 3 /* date ordering is year-month-day */ + +/* number of seconds difference between 1984-01-01 and 1970-01-01. */ +/* this amounts to 14 years including 3 leap-year days (1972, 1976 */ +/* and 1980) converted to a number of seconds. 1984 is a leap year */ +/* but the span of dates does not include 1984-02-29, so 1984's */ +/* leap-year day is not counted. */ + +/* S_SECS_DIFF_1984_1970 is used to calculate Btime6 values. */ + +#define S_SECS_DIFF_1984_1970 ((((1984-1970)*365)+3) * 86400) + +#define MAX_TIME_STRING_LEN 256 + +#define TSTR_DEF_TIME_FORMAT "%m-%d-%Y %H:%M:%S" + +extern char *tstrTimeFormat; + +ST_RET tstrTimeToStringGmt (time_t t, char *dest); +ST_RET tstrStringToTimeGmt (char *src, time_t *out); + +ST_RET tstrStringToTime (char *src, time_t *out); +ST_RET tstrStringToTm (char *src, struct tm *out); + +ST_RET tstrTimeToString (time_t t, char *dest); +ST_RET tstrTimeToStringGmt (time_t t, char *dest); + +ST_RET tstrTmToString (struct tm *t, char *dest); +ST_RET tstrTmToStringGmt (struct tm *t, char *dest); + +#define BTIME_DEF_TIME_FORMAT "%m-%d-%Y %H:%M:%S" + +ST_RET Btime6StringToVals (char *src, ST_INT32 *numDays, ST_INT32 *numMSec); +ST_RET Btime6ValsToString (char *dest, ST_INT32 numDays, ST_INT32 numMSec); + +ST_RET Btime4StringToVals (char *src, ST_INT32 *numMSec); +ST_RET Btime4ValsToString (char *dest, ST_INT32 numMSec); + +ST_RET UtcStringToVals (char *src, ST_UINT32 *pSecs, ST_UINT32 *pFraction, + ST_UINT32 *pQflags ); +ST_RET UtcValsToString (char *dest, ST_UINT32 secs, ST_UINT32 fraction, + ST_UINT32 qflags); +ST_RET UtcStringToValues (char *src, ST_UINT32 *pSecs, ST_UINT32 *pFraction); +ST_RET UtcValuesToString (char *dest, ST_UINT32 secs, ST_UINT32 fraction); +ST_RET XmlStringToUtcValue (ST_CHAR *src, SX_DATE_TIME *sxDateTime); +ST_RET UtcValueToXmlString (ST_CHAR *dest, ST_UINT destLen, SX_DATE_TIME *sxDateTime); +ST_DOUBLE CalculateTimeZoneOffset (ST_VOID); +#define UTC_DEF_TIME_FORMAT "%Y-%m-%dT%H:%M:%S" + +#define GET_TIME_AND_USEC_DEFINED 1 +time_t GetTimeAndUsec (long *usec); + +time_t usr_mkgmtime (struct tm * t); + +#ifdef __cplusplus +} /* End of 'C' functions */ + +#endif + diff --git a/mmslib/inc/tp0_sock.h b/mmslib/inc/tp0_sock.h new file mode 100644 index 0000000..5375d8c --- /dev/null +++ b/mmslib/inc/tp0_sock.h @@ -0,0 +1,268 @@ +#ifndef TP0_SOCK_INCLUDED +#define TP0_SOCK_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997 - 2006 All Rights Reserved */ +/* */ +/* MODULE NAME : tp0_sock.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* TP0/RFC1006 header file for "sockets" interface. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/26/06 EJV 30 Ported MMSEASE_MOSI code to HP-UX. */ +/* 06/19/06 EJV 29 Ported MMSEASE_MOSI code to Sun. */ +/* 08/03/05 EJV 28 SOCK_INFO: added rekeyTime */ +/* 07/19/05 EJV 27 Added SOCK_STATE_CONNECT_CANCELLED. */ +/* 06/30/05 EJV 26 SOCK_INFO: added recvCnt (for flow control) */ +/* 06/06/05 EJV 25 MMSEASE_MOSE: few more chgs to RFC1006_IPC* */ +/* 05/25/05 EJV 24 Added ssec.h */ +/* 04/25/05 JRB,EJV 23 Add RFC1006_IPC_MSG, RFC1006_LISTENER_.. defs*/ +/* 05/09/05 EJV 22 SOCK_INFO: added port field. sreadd add arg6.*/ +/* 05/05/05 EJV 21 np_connect_req: added rem_port param. */ +/* 03/08/05 JRB 20 Add RFC1006.. define. */ +/* 02/22/05 JRB 19 slistend,sreadd: chg ret from void to int. */ +/* 02/21/05 JRB 18 Del ioctlsocket define. Use def in gensock2.h*/ +/* 01/14/04 EJV 17 np_data_req: added eot param. */ +/* Added np_get_tx_queue_cnt func. */ +/* 10/23/03 JRB 16 Move all system includes to sysincs.h */ +/* 10/16/03 JRB 15 SOCK_INFO: add genSock. */ +/* 09/11/03 EJV 14 Del winsock.h (windows.h gets right winsock) */ +/* Added encrypt_ctrl arg to np_connect_req(). */ +/* SOCK_INFO: Add DBL_LNK l and encrypt_ctrl. */ +/* 07/16/02 JRB 13 Add arg to sreadd proto. */ +/* 06/20/02 JRB 12 Chg np_connect_req 2nd arg to ulong ipAddr. */ +/* 05/08/02 JRB 11 Chg connect_result to int (to store errno). */ +/* 05/03/02 JRB 10 Add ip_addr to SOCK_INFO to pass to Read task.*/ +/* 02/02/01 EJV 09 _AIX: added forward references for inet.h. */ +/* 01/02/01 EJV 08 Ported to _AIX. */ +/* 08/15/00 EJV 07 WIN32: Del pipe_msg_crit_sec, pipe_msg_count.*/ +/* 05/18/00 JRB 06 Del "select.h". See "sysincs.h". */ +/* Add for VXWORKS. */ +/* Improve "ioctlsocket" macros for non-WIN32. */ +/* 08/13/98 JRB 05 Lint cleanup. */ +/* Add for default system. */ +/* 12/09/97 JRB 04 Added __OS2__ support. */ +/* 11/14/97 JRB 03 Make PIPE_MSG for VXWORKS like _WIN32. */ +/* 11/10/97 JRB 02 Add VXWORKS support. */ +/* 08/01/97 JRB 01 Created (compatible with MMS-EASE 7.0). */ +/************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +#include "gensock2.h" /* need GEN_SOCK definition */ +#include "ssec.h" /* need S_SEC_ENCRYPT_CTRL */ + +/* Include sockets defs appropriate for this platform. */ +#if !defined (_WIN32) +#define closesocket close +#define WSAEWOULDBLOCK EWOULDBLOCK +#define WSAEINPROGRESS EINPROGRESS +#if defined (__OS2__) +#define WSAGetLastError() sock_errno() +#define GetLastError() errno +#else /* !__OS2__ */ +#define WSAGetLastError() errno +#endif /* !__OS2__ */ +#define SOCKET int +#define SOCKADDR struct sockaddr +#define SOCKADDR_IN struct sockaddr_in +#define PSOCKADDR struct sockaddr * +#define HOSTENT struct hostent +#define INVALID_SOCKET (-1) + +#if defined(sun) || defined(__hpux) +#if !defined(AF_LOCAL) +#define AF_LOCAL AF_UNIX +#endif +#endif /* defined(sun) */ + +#endif /* !_WIN32 */ + +/************************************************************************/ +/* Constant definitions. */ +/************************************************************************/ +#define IPPORT_RFC1006 102 +#define RFC1006_HEAD_LEN 4 +#define RFC1006_VERSION 3 /* first byte of TPKT is version*/ +#define INVALID_CONN_ID (-1L) +#define LISTEN_TASK_NAME "slistend" /* "Listen" task exe name*/ +#define READ_TASK_NAME "sreadd" /* "Read" task exe name */ +#define PIPE_TO_MAIN_NAME "/tmp/pipetp0main" +#define PIPE_TO_LISTEN_NAME "/tmp/pipetp0list" + +/************************************************************************/ +/* Variable type definitions. */ +/************************************************************************/ + +/* Defines of possible values for "state" in SOCK_INFO struct. */ +#define SOCK_STATE_ACCEPTED 0 +#define SOCK_STATE_CONNECTING 1 +#define SOCK_STATE_CONNECTED 2 +#define SOCK_STATE_DISCONNECTING 3 +#define SOCK_STATE_CONNECT_CANCELLED 4 +typedef struct + { + DBL_LNK l; /* needed to store this struct on linked list */ + GEN_SOCK *genSock; /* Use with gensock2. Otherwise, use "hSock" */ + SOCKET hSock; + ST_INT state; + ST_LONG user_conn_id; /* Received from user on N-CONNECT.req/rsp */ + ST_UINT32 ip_addr; /* IP addr as long int in network byte order. */ + ST_UINT16 port; /* RFC1006 port, defaults to 102 */ +#if !(defined(_WIN32) || defined (__OS2__)) + pid_t pid_read; /* Save READ process PID */ +#endif + S_SEC_ENCRYPT_CTRL encrypt_ctrl; + ST_UINT recvCnt; /* num of received (queued) data msgs */ + ST_DOUBLE rekeyTime; /* next time to check rekey if we are idle */ + } SOCK_INFO; + + +/* Info to pass to spawned thread. Can only pass 1 arg to thread, so */ +/* make it a structure, and put whatever we need in it. */ +typedef struct + { + SOCK_INFO *sock_info; /* to pass back to main in PIPE_MSG. */ + SOCKET hSock; /* copied from "sock_info" */ + ST_INT state; /* copied from "sock_info" */ + ST_UINT16 max_tpkt_len; /* Max len of RFC1006 TPKT. */ + } THREAD_INFO; + +typedef struct + { + SOCK_INFO *sock_info; + ST_INT connect_result; /* errno (WSAGetLastErr() for Windows)*/ + ST_UINT16 tpkt_len; +#if (defined (_WIN32) || defined (VXWORKS) || defined (__OS2__)) + ST_UCHAR *tpkt_ptr; +#else + ST_UCHAR tpkt_buf [1]; /* Beginning of buffer attached to this struct*/ +#endif + } PIPE_MSG; + +/* Use define for Length of PIPE_MSG without tpkt_buf at end. */ +#define PIPE_MSG_HEAD_LEN (sizeof(PIPE_MSG)-1) + +/************************************************************************/ +/* Global variables. */ +/************************************************************************/ +extern ST_UCHAR *g_tpkt_enc_buf; /* Buffer for encoding TPKTs. */ +extern SOCKET hSockListen; /* listen socket handle */ + +#if defined _WIN32 +extern HANDLE hPipeMainRead; /* read handle for pipe */ +extern HANDLE hPipeMainWrite; /* write handle for pipe */ +extern HANDLE hEventListenGo; +#endif +#if defined (__OS2__) +extern HFILE hPipeMainRead; /* read handle for pipe */ +extern HFILE hPipeMainWrite; /* write handle for pipe */ +extern HEV hEventListenGo; +extern ST_INT pipe_msg_count; +#endif /* __OS2__ */ + +/************************************************************************/ +/* Function Prototypes. */ +/************************************************************************/ +ST_RET np_init (ST_INT max_num_conns); +ST_RET np_end (ST_VOID); +ST_BOOLEAN np_event (ST_VOID); + +SOCK_INFO * np_connect_req (ST_LONG user_conn_id, ST_ULONG ipAddr, ST_UINT16 rem_port, + S_SEC_ENCRYPT_CTRL *encrypt_ctrl); +ST_VOID np_connect_cnf_pos (SOCK_INFO *sock_info, ST_LONG user_conn_id); +/* NOTE: np_connect_ind & np_connect_rsp not needed because user only */ +/* cares about Transport conn. Doesn't need to know about Network conn.*/ + +ST_RET np_data_req (SOCK_INFO *sock_info, ST_INT pdu_len, ST_UCHAR *pdu_ptr, ST_BOOLEAN eot); +ST_VOID np_data_ind (SOCK_INFO *sock_info, ST_UCHAR *pdu_ptr, ST_UINT16 pdu_len); +ST_UINT np_get_tx_queue_cnt (SOCK_INFO *sock_info); + +ST_RET np_disconnect_req (SOCK_INFO *sock_info); +ST_VOID np_disconnect_ind (SOCK_INFO *sock_info); + +ST_RET sockets_init (ST_INT max_num_conns); +ST_VOID sockets_end (ST_VOID); +ST_RET spawn_listen (SOCKET hSock); +ST_RET spawn_read (SOCK_INFO *sock_info); +ST_VOID handle_accepted_conn (SOCK_INFO *sock_info); +ST_VOID handle_connect_success (SOCK_INFO *sock_info); +ST_VOID handle_connect_fail (SOCK_INFO *sock_info); +ST_VOID handle_data (SOCK_INFO *sock_info, ST_UCHAR *tpkt_ptr, ST_UINT16 tpkt_len); +ST_VOID handle_disconnect (SOCK_INFO *sock_info); +SOCK_INFO *sock_info_alloc (SOCKET hSock, ST_INT state, ST_LONG user_conn_id); +ST_VOID sock_info_free (SOCK_INFO *sock_info); + +#if defined (_WIN32) +void ThreadSockListen (void *param); +void ThreadSockRead (void *param); +#endif /* _WIN32 */ +#if defined (__OS2__) +void _Optlink ThreadSockListen (void *param); +void _Optlink ThreadSockRead (void *param); +#endif /* __OS2__ */ + +int slistend (int arg1); +int sreadd (int arg1, int arg2, int arg3, int arg4, int arg5, int arg6); + +/************************************************************************/ +/* Code used by MMSEASE_MOSI. */ +/* Defines, etc. for interfacing to "rfc1006_listener" task. */ +/* Only used on LINUX, but the code should be portable to most UNIX-like*/ +/* systems. */ +/************************************************************************/ + +#if defined(MMSEASE_MOSI) +/* use the same task name and the UNIX domain listen socket name to */ +/* easy associate each other when viewing for example network stats */ +#if defined(linux) || defined(sun) +#define RFC1006_LISTENER_EXE_PATH "/usr/sisco/bin" +#define RFC1006_LISTENER_IPC_PATH "/tmp" +#endif +#if defined(__hpux) +#define RFC1006_LISTENER_EXE_PATH "/opt/sisco/bin" +#define RFC1006_LISTENER_IPC_PATH "/tmp" +#endif +#define RFC1006_LISTENER_NAME "rfc1006listenerd" +#define RFC1006_LISTENER_DOMSOCK "rfc1006listenerd.domsock" +#define RFC1006_LISTENER_LOG "rfc1006listenerd.log" + +#define RFC1006_IPC_MAGIC_NUM 0xBADC +/* defines for "opcode" in RFC1006_IPC_MSG. */ +#define RFC1006_IPC_OP_START 1 /* start RFC1006_LISTENER daemon */ +#define RFC1006_IPC_OP_STOP 2 /* stop RFC1006_LISTENER daemon */ +#define RFC1006_IPC_OP_BIND 3 +#define RFC1006_IPC_OP_UNBIND 4 +#define RFC1006_IPC_OP_CONNECT 5 /* TP0 connect indication */ +#define RFC1006_IPC_OP_SET_LOG 6 /* change RFC1006_LISTENER log masks */ + +typedef struct rfc1006_ipc_msg_tag + { + ST_UINT16 magic; /* always == RFC1006_IPC_MAGIC_NUM */ + ST_UINT16 opcode; /* one of RFC1006_IPC_OP.. values */ + ST_UINT16 data_len; /* length of data following this msg */ + } RFC1006_IPC_MSG; + +extern ST_BOOLEAN use_rfc1006_listener_task; +extern SOCKET domsock_listener; /* domain socket connected to the */ + /* RFC1006_LISTENER task. */ +ST_INT recvwait (SOCKET hSock, ST_VOID *buf, ST_INT numBytes, int flags); +ST_INT sendwait (SOCKET hSock, ST_VOID *buf, ST_INT numBytes, int flags); + +ST_RET setListenerIPCDir (ST_CHAR *dirPath); + +#endif /* defined(MMSEASE_MOSI) */ + +#ifdef __cplusplus +} +#endif + +#endif /* !TP0_SOCK_INCLUDED */ + diff --git a/mmslib/inc/tp4.h b/mmslib/inc/tp4.h new file mode 100644 index 0000000..1c2b1cf --- /dev/null +++ b/mmslib/inc/tp4.h @@ -0,0 +1,363 @@ +#ifndef TP4_INCLUDED +#define TP4_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2005 All Rights Reserved */ +/* */ +/* MODULE NAME : tp4.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* TP4 main header file. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/22/08 JRB 17 Add TPDU_ER structure. */ +/* 03/29/05 EJV 16 MMSEASE_MOSI: added tp0_check_... protos. */ +/* 01/13/04 EJV 15 Changed tp0_send_... funcs to return value. */ +/* 06/27/02 JRB 14 Add tp_dr_reason to TP_CONN. */ +/* 10/25/01 JRB 13 Move replacement func macros to tp4api.h */ +/* 05/07/01 JRB 12 Add loc_tsap, rem_tsap to TP_CONN, TP0_CONN. */ +/* 07/19/99 RKR 11 Modified a macro so this file will install */ +/* 06/08/99 JRB 10 Allow up to 1024 connections by using new */ +/* macros to compute loc_ref_offset & loc_ref. */ +/* 08/13/98 JRB 09 Lint cleanup. */ +/* 08/14/97 JRB 08 Use MAX_TSEL_LEN defined in tp4api.h */ +/* Add max_tpdu_len (negotiated) to TP_CONN. */ +/* Add TP0/RFC1006 support defines & protos. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/21/97 JRB 07 Add tp_free_spdu_all function. */ +/* 02/20/97 EJV 06 Add session_timer to TP_CONN for MOSI implem.*/ +/* 10/04/96 JRB 05 Add global variable max_tpdu_len_enc. */ +/* Chg TPDU_CX param to max_tpdu_len_enc. */ +/* 10/04/96 JRB 04 Chg send_ak_flag to ak_delay. */ +/* 09/09/96 JRB 03 Add send_ak_flag to TP_CONN. */ +/* 09/09/96 JRB 02 Add tp_send_cr, tp_setup_and_send_??, */ +/* tp_send_dt_and_ak & tp_conn_clean prototypes.*/ +/* 07/17/96 JRB 01 Created */ +/************************************************************************/ +#include "tp4api.h" /* need some TP4 user defs. */ +#include "clnp_usr.h" /* TP4 uses CLNP user interface. */ + +#if defined (TP0_ENABLED) +#include "tp0_sock.h" /* TP0/RFC1006 sockets interface defs. */ +#endif /* TP0_ENABLED */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define TP_MAX_CONN_UDATA 32 +#define TP4_EXCEPT() tp4_except (thisFileName, __LINE__) + +/************************************************************************/ +/* The following defines used in computing "loc_ref" (16-bit value): */ +/* TP_CONN_ID_BITS: number of bits to use for conn_id in loc_ref. */ +/* TP_MAX_NUM_CONNS: max number of connections allowed. */ +/* TP_CONN_ID_MASK: mask used to find conn_id in loc_ref. */ +/* TP_LOC_REF_MOD: modulus to use for loc_ref_offset wrap around. */ +/* When loc_ref_offset incremented to this value, */ +/* go back to 1 (not 0 so loc_ref can never be 0). */ +/* TP_CONN_ID_BITS, TP_CONN_ID_MASK, TP_MAX_NUM_CONNS & TP_LOC_REF_MOD */ +/* are all related. If one changes, they must all change. */ +/************************************************************************/ +#define TP_CONN_ID_BITS 10 +#define TP_CONN_ID_MASK 0x3ff /* 0000 0011 1111 1111 binary */ +#define TP_MAX_NUM_CONNS 0x400 /* conn_id = 0 thru 0x3ff */ +/* If 10 bits used for conn_id, 6 bits left for loc_ref_offset, so it */ +/* must wrap around when it reaches 0100 0000 binary (i.e. 0x40). */ +#define TP_LOC_REF_MOD 0x40 /* modulus for 6-bit value */ + +/************************************************************************/ +/* Structure typedefs. */ +/************************************************************************/ + +/* TPDU_CX - Used for CR or CC TPDU info. */ +typedef struct + { + /* NOTE: the following options not supported: */ + /* Transport Expedited Data. */ + /* Non-use of checksum. */ + /* Use of extended format. */ + /* When sending CR, don't request any. */ + /* When sending CC, don't accept any. */ + + ST_UCHAR loc_tsap [1+MAX_TSEL_LEN]; /* Local len & TSAP addr */ + ST_UCHAR rem_tsap [1+MAX_TSEL_LEN]; /* Remote len & TSAP addr */ + ST_UINT16 loc_ref; /* Local Reference for conn. */ + ST_UINT16 rem_ref; /* Remote Reference for conn. */ + ST_UCHAR max_tpdu_len_enc; /* Negotiated Max TPDU len (encoded). */ + ST_UCHAR preferred_class; /* Preferred Transport Class 0-4 */ + ST_UCHAR cdt; /* CDT */ + ST_UCHAR *rem_mac; /* Remote MAC addr */ + ST_UCHAR *rem_nsap; /* Remote len & NSAP addr */ + ST_UINT16 udata_len; /* Length of CR/CC User Data. */ + ST_CHAR udata_buf [TP_MAX_CONN_UDATA]; /* Buffer for CR/CC User Data. */ +#if defined (TP0_ENABLED) + SOCK_INFO *sock_info; /* socket info for TP0 conns only */ +#endif /* TP0_ENABLED */ + } TPDU_CX; + +typedef struct + { + ST_UINT16 loc_ref; /* Local Reference for conn. */ + ST_UINT16 rem_ref; /* Remote Reference for conn. */ + ST_UCHAR reason; /* Reason for disconnect. */ + ST_UCHAR *rem_mac; /* Remote MAC addr */ + ST_UCHAR *rem_nsap; /* Remote len & NSAP addr */ +#if defined (TP0_ENABLED) + SOCK_INFO *sock_info; /* socket info for TP0 conns only */ +#endif /* TP0_ENABLED */ + } TPDU_DR; + +typedef TPDU_DR TPDU_DC; /* Same as DR but ignore "reason". */ + +typedef struct + { + ST_UINT16 dst_ref; /* Dest Reference for conn. */ + ST_UCHAR sn; + ST_UCHAR cdt; + ST_UCHAR *rem_mac; /* Remote MAC addr */ + ST_UCHAR *rem_nsap; /* Remote len & NSAP addr */ + } TPDU_AK; + +typedef struct + { + ST_UINT16 dst_ref; /* Dest Reference for conn. */ + ST_UCHAR sn; /* Sequence #. */ + ST_BOOLEAN eot; /* DT TPDU contains or should contain EOT flag */ + ST_UCHAR *rem_mac; /* Remote MAC addr */ + ST_UCHAR *rem_nsap; /* Remote len & NSAP addr */ + ST_CHAR *udata_ptr; /* Pointer to DT User Data. */ + ST_UINT16 udata_len; /* Length of DT User Data. */ +#if defined (TP0_ENABLED) + SOCK_INFO *sock_info; /* socket info for TP0 conns only */ +#endif /* TP0_ENABLED */ + } TPDU_DT; + +typedef struct + { + ST_UINT16 dst_ref; /* Dest Reference for conn. */ + ST_UCHAR reject_cause; /* reason for error (0-3) */ + ST_UCHAR *invalid_tpdu_ptr; /* Pointer to TPDU hdr that caused reject*/ + ST_UCHAR invalid_tpdu_len; /* Length of TPDU hdr that caused reject*/ + /* NOTE: <= 255 (must fit in 1 byte). */ + ST_UCHAR *rem_mac; /* Remote MAC addr */ + ST_UCHAR *rem_nsap; /* Remote len & NSAP addr */ +#if defined (TP0_ENABLED) + SOCK_INFO *sock_info; /* socket info for TP0 conns only */ +#endif /* TP0_ENABLED */ + } TPDU_ER; + +typedef struct + { + ST_CHAR *spdu_ptr; /* Pointer to SPDU. */ + ST_UINT spdu_len; /* Length of SPDU. */ + ST_UINT offset; /* Offset into SPDU. */ + } SPDU_INFO; + +typedef struct + { + /* NOTE: "state" is first in this struct because it will be */ + /* accessed most often (every time connection made must scan array */ + /* for a TP_CONN with state == TP_STATE_CLOSED). */ + ST_UCHAR state; /* State of connection (initially CLOSED). */ + ST_UCHAR tp_dr_reason; /* reason for disconnect (0 if connected)*/ + ST_UINT16 loc_ref_offset; /* Used to compute loc_ref (see calc_loc_ref)*/ + ST_UINT16 rem_ref; /* Peer's reference # for this connection. */ + ST_UINT16 window_time; /* Window Time */ + ST_UINT16 inact_time; /* Inactivity Time */ + ST_UINT16 retrans_time; /* Retransmission Time */ + ST_UCHAR lower_tx_sn; /* Sequence # for peer's lower window edge. */ + ST_UCHAR adj_rem_cdt; /* Last CDT received from peer. */ + /* Adjusted to stay within our limits. */ + ST_UCHAR next_tx_sn; /* Sequence # for next TPDU to send to peer. */ + ST_UCHAR next_rx_sn; /* Sequence # for next TPDU to receive from peer*/ + TPDU_DT *tpdu_dt_tx; /* ptr to array of "max_rem_cdt" structs */ + /* Allocated by tp4_initialize (). */ + + ST_UCHAR num_spdu_outst; /* # of SPDUs outstanding */ + ST_UCHAR spdu_cnt_qued; /* Count of SPDUs queued. Goes to 0 on overflow */ + ST_UCHAR spdu_cnt_sent; /* Count of SPDUs sent. Goes to 0 on overflow */ + ST_UCHAR spdu_cnt_done; /* Count of SPDUs done. Goes to 0 on overflow */ + SPDU_INFO *spdu_tx; /* ptr to array of "max_spdu_outst" structs */ + SPDU_INFO spdu_rx; /* Struct for one received SPDU */ + ST_BOOLEAN spdu_rx_start; /* Next TPDU rcvd is start of SPDU. */ + /* Save rem_mac & rem_nsap received from CLNP with CR or CC. */ + ST_UCHAR rem_mac [CLNP_MAX_LEN_MAC]; /* Remote MAC addr */ + ST_UCHAR rem_nsap [1+CLNP_MAX_LEN_NSAP]; /* Remote len & NSAP addr */ + ST_UCHAR num_trans; /* (TX ONLY) # of times a TPDU transmitted */ + ST_LONG user_conn_id; /* User's ID for this conn. */ + TPDU_CX tpdu_cx; /* CR or CC Info to Send/Receive. */ + ST_UCHAR ak_delay; /* # of loops to delay sending AK. */ + + ST_UINT16 session_timer; /* Session timer for MOSI implementation */ + ST_UINT16 max_tpdu_len; /* Negotiated TPDU len on this conn. */ + ST_UCHAR loc_tsap [1+MAX_TSEL_LEN]; /* Local len & TSAP addr */ + ST_UCHAR rem_tsap [1+MAX_TSEL_LEN]; /* Remote len & TSAP addr */ + } TP_CONN; + +typedef struct + { + /* NOTE: "state" is first in this struct because it will be */ + /* accessed most often (every time connection made must scan array */ + /* for a TP_CONN with state == TP_STATE_CLOSED). */ + ST_UCHAR state; /* State of connection (initially CLOSED). */ + ST_UINT16 loc_ref_offset; /* Used to compute loc_ref (see calc_loc_ref)*/ + ST_UINT16 rem_ref; /* Peer's reference # for this connection. */ + + SPDU_INFO spdu_rx; /* Struct for one received SPDU */ + ST_BOOLEAN spdu_rx_start; /* Next TPDU rcvd is start of SPDU. */ + ST_LONG user_conn_id; /* User's ID for this conn. */ + TPDU_CX tpdu_cx; /* CR or CC Info to Send/Receive. */ + + ST_UINT16 session_timer; /* Session timer for MOSI implementation */ + ST_UINT16 max_tpdu_len; /* Negotiated TPDU len on this conn. */ +#if defined (TP0_ENABLED) + SOCK_INFO *sock_info; /* socket info for TP0 conns only */ +#endif /* TP0_ENABLED */ + ST_UCHAR loc_tsap [1+MAX_TSEL_LEN]; /* Local len & TSAP addr */ + ST_UCHAR rem_tsap [1+MAX_TSEL_LEN]; /* Remote len & TSAP addr */ + } TP0_CONN; + +/************************************************************************/ +/* Miscellaneous Defines. */ +/************************************************************************/ +#define MODULUS_SN 128 /* Sequence # Modulus (2**7) */ + +/************************************************************************/ +/* Defines for TP4 connection states. */ +/************************************************************************/ +#define TP_STATE_CLOSED 0 +#define TP_STATE_WFCC 1 +#define TP_STATE_WBCL 2 +#define TP_STATE_OPEN 3 +#define TP_STATE_WFTRESP 4 +#define TP_STATE_AKWAIT 5 +#define TP_STATE_CLOSING 6 +#define TP_STATE_WFNC 7 /* for TP0/RFC1006 only */ + +/************************************************************************/ +/* Defines for types of TPDUs. */ +/************************************************************************/ +#define TPDU_TYPE_CR 0 +#define TPDU_TYPE_CC 1 +#define TPDU_TYPE_DR 2 +#define TPDU_TYPE_DC 3 +#define TPDU_TYPE_DT 4 +#define TPDU_TYPE_AK 5 + +/************************************************************************/ +/* Miscellaneous defines. */ +/************************************************************************/ +#define MIN_TP0_CONN_ID 10000 /* min tp_conn_id for TP0 so */ + /* don't overlap with TP4 id's */ + +/* WARNING: We assume TP_MAX_NUM_CONNS <= MIN_TP0_CONN_ID so TP0 conn */ +/* id's can't overlap with TP4 conn id's. */ +/* Let's just make sure this assumption is valid. */ +#if (TP_MAX_NUM_CONNS > MIN_TP0_CONN_ID) +#error TP_MAX_NUM_CONNS > MIN_TP0_CONN_ID. Definitions incompatible. +#endif + +/************************************************************************/ +/* Global variables. */ +/************************************************************************/ +extern TP_CONN *tp_conn_arr; /* ptr to array of "max_num_conns" structs */ +extern ST_LONG only_tp4_bind_id; /* Only one tp4_bind_id. */ +extern ST_LONG only_user_bind_id; /* Only one user_bind_id. */ +extern ST_UCHAR only_loc_tsap []; /* Local len & TSAP addr */ +extern ST_UCHAR max_tpdu_len_enc; /* Binary encoded MAX TPDU len. */ + +extern TP0_CONN *tp0_conn_arr; /* ptr to array of "max_num_conns" structs */ +extern ST_LONG only_tp0_bind_id; /* Only one tp0_bind_id. */ +extern ST_LONG only_tp0_user_bind_id; /* Only one tp0_user_bind_id. */ +extern ST_UCHAR only_tp0_loc_tsap []; /* Local len & TSAP addr */ + +/************************************************************************/ +/* Prototypes */ +/************************************************************************/ +ST_VOID tp_setup_and_send_ak (TP_CONN *tp_conn); +ST_VOID tp_setup_and_send_dr (TP_CONN *tp_conn); + +ST_VOID tp_send_cr (TPDU_CX *tpdu_cr); +ST_VOID tp_send_cc (TPDU_CX *tpdu_cc); +ST_VOID tp_send_dr (TPDU_DR *tpdu_dr); +ST_VOID tp_send_dc (TPDU_DC *tpdu_dc); +ST_VOID tp_send_dt (TPDU_DT *tpdu_dt); +ST_VOID tp_send_ak (TPDU_AK *tpdu_ak); +ST_VOID tp_send_dt_and_ak (TPDU_DT *tpdu_dt, TPDU_AK *tpdu_ak); + +ST_VOID tp_process_cr (TPDU_CX *tpdu_cr_rx); +ST_VOID tp_process_cc (TPDU_CX *tpdu_cc_rx); +ST_VOID tp_process_dr (TPDU_DR *tpdu_dr_rx); +ST_VOID tp_process_dc (TPDU_DC *tpdu_dc_rx); +ST_VOID tp_process_dt (TPDU_DT *tpdu_dt_rx); +ST_VOID tp_process_ak (TPDU_AK *tpdu_ak_rx); +ST_VOID tp_conn_clean (TP_CONN *tp_conn); +ST_VOID tp_free_spdu_all (TP_CONN *tp_conn); + +ST_RET tp0_send_cr (TPDU_CX *tpdu_cr); +ST_RET tp0_send_cc (TPDU_CX *tpdu_cc); +ST_RET tp0_send_dr (TPDU_DR *tpdu_dr); +ST_RET tp0_send_dt (TPDU_DT *tpdu_dt); + +ST_VOID tp0_process_cr (TPDU_CX *tpdu_cr_rx); +ST_VOID tp0_process_cc (TPDU_CX *tpdu_cc_rx); +ST_VOID tp0_process_dr (TPDU_DR *tpdu_dr_rx); +ST_VOID tp0_process_dt (TPDU_DT *tpdu_dt_rx); + +ST_VOID tp0_conn_clean (TP0_CONN *tp_conn); + +#if defined(MMSEASE_MOSI) +ST_RET tp0_check_tsel (ST_UCHAR *tsel, ST_LONG *user_bind_id); +ST_RET tp0_check_bind_id (ST_LONG bind_id, ST_UCHAR **tsel); +#endif + +/************************************************************************/ +/* Macros. */ +/************************************************************************/ + +/*----------------------------------------------------------------------*/ +/* inc_loc_ref_offset */ +/* Increment "loc_ref_offset". When the value reaches TP_LOC_REF_MOD */ +/* (defined above), wrap around back to 1. */ +/* NOTE: We do not wrap to 0, so "loc_ref_offet" will never be 0. */ +/* "loc_ref_offset" is used to compute "loc_ref", so "loc_ref" */ +/* will also never be 0. */ +/* Arg #1: value (i.e. loc_ref_offset) to be incremented */ +/* Example of usage: */ +/* inc_loc_ref_offset (tp_conn->loc_ref_offset); */ +/*----------------------------------------------------------------------*/ +#define inc_loc_ref_offset(value) {\ + if (++(value) >= TP_LOC_REF_MOD) \ + (value) = 1; } /* comment necessary for DDB installation tool */ + +/*----------------------------------------------------------------------*/ +/* calc_loc_ref */ +/* Calculate loc_ref from conn_id and loc_ref_offset. */ +/* IMPORTANT: loc_ref_offset MUST NEVER be 0, so loc_ref will never be 0.*/ +/* This is accomplished by using ONLY the "inc_loc_ref_offset"*/ +/* macro above to change the value of "loc_ref_offset". */ +/*----------------------------------------------------------------------*/ +#define calc_loc_ref(conn_id,loc_ref_offset) \ + ((conn_id) | ((loc_ref_offset) << TP_CONN_ID_BITS)) + +/*----------------------------------------------------------------------*/ +/* calc_conn_id */ +/* Calculate conn_id from loc_ref. */ +/*----------------------------------------------------------------------*/ +#define calc_conn_id(loc_ref) \ + ((loc_ref) & TP_CONN_ID_MASK) + +#ifdef __cplusplus +} +#endif + +#endif /* !TP4_INCLUDED */ + diff --git a/mmslib/inc/tp4_encd.h b/mmslib/inc/tp4_encd.h new file mode 100644 index 0000000..051d46d --- /dev/null +++ b/mmslib/inc/tp4_encd.h @@ -0,0 +1,407 @@ +#ifndef TP4_ENCD_INCLUDED +#define TP4_ENCD_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996 - 2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : tp4_encd.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file defines structures and functions for */ +/* encoding/decoding of class 4 TPDUs. */ +/* */ +/* Note: The following TP options are NOT supported: */ +/* Transport Expedited Data */ +/* Non-use of checksum */ +/* Use of extended format. */ +/* This is reflected in structures and defines below. */ +/* */ +/* For information see the: */ +/* ISO 8073 "Information processing systems - Open Systems */ +/* Interconnections - Connection oriented transport protocol */ +/* specification. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/22/08 JRB 08 tp_decode_ak(_dc,_er): change args. */ +/* Delete tp_decode_rj (not used in TP0 or TP4).*/ +/* 11/01/07 EJV 07 Added comments. */ +/* 05/25/05 EJV 06 Added include tp4.h */ +/* 01/28/99 JRB 05 Move cltp_decode_nsdu proto to ACSE file. */ +/* 12/01/97 JRB 04 CRITICAL: Don't use "sizeof" on structures. */ +/* Caused padding on VXWORKS. */ +/* 08/14/97 JRB 03 Add TP0/RFC1006 support defines & protos. */ +/* Add tp_decode_* protos (were static before). */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 11/22/96 JRB 02 Add TP_PDU_TYPE_UD & cltp_decode_nsdu for CLTP.*/ +/* 06/20/96 EJV 01 Created */ +/************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +#include "tp4.h" + + /* encoding for Transport Protocol class and options */ + +#define TP_CLASS_0 (ST_UCHAR) 0x00 +#define TP_CLASS_1 (ST_UCHAR) 0x10 +#define TP_CLASS_2 (ST_UCHAR) 0x20 +#define TP_CLASS_3 (ST_UCHAR) 0x30 +#define TP_CLASS_4 (ST_UCHAR) 0x40 + +#define TP_OPT_FORMAT_NORMAL (ST_UCHAR) 0x00 +#define TP_OPT_FORMAT_EXTENDED (ST_UCHAR) 0x02 + +#define TP_CLASS_4_NORMAL (ST_UCHAR) (TP_CLASS_4 | TP_OPT_FORMAT_NORMAL) +#define TP_CLASS_4_EXT (ST_UCHAR) (TP_CLASS_4 | TP_OPT_FORMAT_EXTENDED) + +#define TP_CLASS_MASK_OPT (ST_UCHAR) 0xF0 /* for masking opt in ASN1_CLASS_METHOD-OPT in CR */ + + /* encoding for TPDU type code */ + +#define TP_PDU_TYPE_CR (ST_UCHAR) 0xE0 /* 1110 xxxx */ +#define TP_PDU_TYPE_CC (ST_UCHAR) 0xD0 /* 1101 xxxx */ +#define TP_PDU_TYPE_DR (ST_UCHAR) 0x80 /* 1000 0000 */ +#define TP_PDU_TYPE_DC (ST_UCHAR) 0xC0 /* 1100 0000 */ +#define TP_PDU_TYPE_DT (ST_UCHAR) 0xF0 /* 1111 0000 */ +#define TP_PDU_TYPE_ED (ST_UCHAR) 0x10 /* 0001 0000 */ +#define TP_PDU_TYPE_AK (ST_UCHAR) 0x60 /* 0110 zzzz */ +#define TP_PDU_TYPE_EA (ST_UCHAR) 0x20 /* 0010 0000 */ +#define TP_PDU_TYPE_RJ (ST_UCHAR) 0x50 /* 0101 zzzz */ +#define TP_PDU_TYPE_ER (ST_UCHAR) 0x70 /* 0111 0000 */ +#define TP_PDU_TYPE_UD (ST_UCHAR) 0x40 /* 0100 0000 for CLTP */ + +#define TP_PDU_MASK_TYPE (ST_UCHAR) 0x0F /* for masking type to get CDT */ +#define TP_PDU_MASK_CDT (ST_UCHAR) 0xF0 /* for masking CTD to get type */ + +/* encoding for max size of TPDU (parameter in the CR) */ + +#define TP_PDU_MAX_SIZE_65531 (ST_UCHAR) 0x0E /* kluge for TP0/RFC1006 only*/ +#define TP_PDU_MAX_SIZE_8192 (ST_UCHAR) 0x0D +#define TP_PDU_MAX_SIZE_4096 (ST_UCHAR) 0x0C +#define TP_PDU_MAX_SIZE_2048 (ST_UCHAR) 0x0B +#define TP_PDU_MAX_SIZE_1024 (ST_UCHAR) 0x0A +#define TP_PDU_MAX_SIZE_512 (ST_UCHAR) 0x09 +#define TP_PDU_MAX_SIZE_256 (ST_UCHAR) 0x08 +#define TP_PDU_MAX_SIZE_128 (ST_UCHAR) 0x07 + +/* encoding EOT in DT TPDU - bit 8 */ + +#define TP_PDU_EOF (ST_UCHAR) 0x80 + +#define TP_PDU_MASK_EOF (ST_UCHAR) 0x7F /* for masking EOF to get SN (DT)*/ +#define TP_PDU_MASK_SN (ST_UCHAR) 0x80 /* for masking SN to get EOF (DT)*/ + +#define TP_PDU_MASK_BIT8 (ST_UCHAR) 0x7F /* for masking bit 8 to get SN (AK)*/ + +/* encoding for DR reason */ +/* for class 1 - 4 */ +#define TP_DR_NORMAL (ST_UCHAR) 0x80 +#define TP_DR_CONGESTION (ST_UCHAR) 0x81 +#define TP_DR_CLASS_UNSUPPORTED (ST_UCHAR) 0x82 +#define TP_DR_DUPLICATE_SRC_REF (ST_UCHAR) 0x83 +#define TP_DR_INVALID_REF (ST_UCHAR) 0x84 +#define TP_DR_PROT_ERROR (ST_UCHAR) 0x85 +#define TP_DR_REF_OVERFLOW (ST_UCHAR) 0x87 +#define TP_DR_CR_REFUSED (ST_UCHAR) 0x88 +#define TP_DR_HDR_INVALID (ST_UCHAR) 0x8A + +/* for all classes (TP0) */ +#define TP_DR_NO_REASON (ST_UCHAR) 0x00 +#define TP_DR_CONGESTION_AT_TSAP (ST_UCHAR) 0x01 +#define TP_DR_NO_SESSION (ST_UCHAR) 0x02 +#define TP_DR_ADDR_UNKNOWN (ST_UCHAR) 0x03 + + +/* misc defines */ + +#define TP_MAX_CDT (ST_UCHAR) 0x0F + + + + /*----------------------------------------------*/ + /* Encoding and structures for TP parameters */ + /*----------------------------------------------*/ + + /* encoding for TP version */ + +#define TP_VERSION (ST_UCHAR) 0x01 + + /* encoding for the parameter code in CR or CC TPDU variable part */ + +#define TP_PAR_CODE_TSAP_CALLING (ST_UCHAR) 0xC1 +#define TP_PAR_CODE_TSAP_CALLED (ST_UCHAR) 0xC2 +#define TP_PAR_CODE_TPDU_SIZE (ST_UCHAR) 0xC0 +#define TP_PAR_CODE_VERSION (ST_UCHAR) 0xC4 +#define TP_PAR_CODE_ADD_OPTIONS (ST_UCHAR) 0xC6 + + /* encoding for the parameter code in AK TPDU variable part */ + +#define TP_PAR_CODE_AK_SUB_SN (ST_UCHAR) 0x8A +#define TP_PAR_CODE_AK_FLOW_CTRL (ST_UCHAR) 0x8C + + /* encoding for the parameter code in ER TPDU variable part */ + +#define TP_PAR_CODE_ER_INVAL_TPDU (ST_UCHAR) 0xC1 + + /* encoding for the parameter code in variable part (common to */ + /* different TPDU types) */ + +#define TP_PAR_CODE_CHECKSUM (ST_UCHAR) 0xC3 + + + /* encoding for CR TPDU additional options */ + +#define TP_OPT_CHECKSUM_USE (ST_UCHAR) 0x00 +#define TP_OPT_CHECKSUM_NON_USE (ST_UCHAR) 0x02 + +#define TP_OPT_EXPEDITED_NON_USE (ST_UCHAR) 0x00 +#define TP_OPT_EXPEDITED_USE (ST_UCHAR) 0x01 + + +typedef struct + { + ST_UCHAR code; /* parameter code */ + ST_UCHAR len; /* Parameter length */ + ST_UCHAR value [2]; /* parameter value has variable length */ + /* (defined as 2 bytes buffer, the ptr */ + /* will allow us to access any len param*/ + }TP_PAR; + +#define TP_PAR_FIX_LEN 2 + /* define above specifies only the fixed part */ + /* of parameter (code and len) */ + + /* some parameters are fixed in size so we can define them here */ + + /* parameters length in CR or CC */ + +#define TP_PAR_LEN_TPDU_SIZE (TP_PAR_FIX_LEN + 1) +#define TP_PAR_LEN_VERSION (TP_PAR_FIX_LEN + 1) +#define TP_PAR_LEN_ADD_OPTIONS (TP_PAR_FIX_LEN + 1) + + /* parameters length in AK */ + +#define TP_PAR_LEN_AK_SUB_SN (TP_PAR_FIX_LEN + 2) +#define TP_PAR_LEN_AK_FLOW_CTRL (TP_PAR_FIX_LEN + 8) + + /* parameters length (common to different types of TPDU types) */ + +#define TP_PAR_LEN_CHECKSUM (TP_PAR_FIX_LEN + 2) + +/* ! */ +/* NOTE: ! only ST_UCHAR type should be in protocol structs to avoid */ +/* ! packing or problems with sizeof operator. */ +/* ! */ + + + /*----------------------------------------------*/ + /* Struct and defines for CR and CC TPDU */ + /*----------------------------------------------*/ + +typedef struct + { + /* fixed part of header */ + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type_cdt; /* TPDU type and CDT */ + ST_UCHAR dest_ref [2]; /* Remote connection id (set to 0) */ + ST_UCHAR src_ref [2]; /* Local connection id */ + ST_UCHAR class_opt; /* Class and options */ + }TP_FHDR_CX; + +#define TP_FHDR_CX_LEN 7 + + /* for alloc of n_unitdata purposes the max len will be used */ + /* fixed part of header */ + /* local & remote TSAP */ + /* TPDU size parameter */ + /* TP version parameter */ + /* checksum parameter */ + /* additional opt param */ + /* user data (max allowed)*/ + +#define TP_MAX_LEN_CX (TP_FHDR_CX_LEN + \ + 2*(TP_PAR_FIX_LEN + MAX_TSEL_LEN) + \ + TP_PAR_LEN_TPDU_SIZE + \ + TP_PAR_LEN_VERSION + \ + TP_PAR_LEN_CHECKSUM + \ + TP_PAR_LEN_ADD_OPTIONS + \ + TP_MAX_CONN_UDATA) + + /*--------------------------------------*/ + /* Struct and defines for DR TPDU */ + /*--------------------------------------*/ + +typedef struct + { + /* fixed part of header */ + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type; /* TPDU type */ + ST_UCHAR dest_ref [2]; /* Remote connection id (set to 0) */ + ST_UCHAR src_ref [2]; /* Local connection id */ + ST_UCHAR reason; /* Reason code for disconnect */ + }TP_FHDR_DR; + +#define TP_FHDR_DR_LEN 7 + + /* for alloc of n_unitdata the max len will be used. */ + +#define TP_MAX_LEN_DR (TP_FHDR_DR_LEN + TP_PAR_LEN_CHECKSUM) + + /* no additional info parameter or user data in DR */ + + /*--------------------------------------*/ + /* Struct and defines for DC TPDU */ + /*--------------------------------------*/ + +typedef struct + { + /* fixed part of header */ + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type; /* TPDU type */ + ST_UCHAR dest_ref [2]; /* Remote connection id (set to 0) */ + ST_UCHAR src_ref [2]; /* Local connection id */ + }TP_FHDR_DC; + +#define TP_FHDR_DC_LEN 6 + + /* for alloc of n_unitdata the max len will be used. */ + +#define TP_MAX_LEN_DC (TP_FHDR_DC_LEN + TP_PAR_LEN_CHECKSUM) + + + /*--------------------------------------*/ + /* Struct and defines for DT TPDU */ + /*--------------------------------------*/ + +typedef struct + { + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type; /* TPDU type */ + ST_UCHAR dest_ref [2]; /* Remote connection id */ + ST_UCHAR eot_sn; /* EOT flag and sequence number */ + }TP_FHDR_DT; + +#define TP_FHDR_DT_LEN 5 + + /* for alloc of n_unitdata use TP_HEAD_LEN_DT + udata_len */ + +#define TP_HEAD_LEN_DT (ST_UINT16)(TP_FHDR_DT_LEN + TP_PAR_LEN_CHECKSUM) + +/* TP0 DT same as TP4 except doesn't use DST-REF. */ +typedef struct + { + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type; /* TPDU type */ + ST_UCHAR eot_sn; /* EOT flag and sequence number */ + }TP0_FHDR_DT; + +#define TP0_FHDR_DT_LEN 3 +#define TP0_HEAD_LEN_DT (ST_UINT16)(TP0_FHDR_DT_LEN) /* no chksum*/ + + + /*--------------------------------------*/ + /* Struct and defines for AK TPDU */ + /*--------------------------------------*/ + + +typedef struct + { + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type_cdt; /* TPDU type and CDT */ + ST_UCHAR dest_ref [2]; /* Remote connection id */ + ST_UCHAR sn; /* Next expected DT TPDU sequence number*/ + }TP_FHDR_AK; + +#define TP_FHDR_AK_LEN 5 + + /* for alloc of n_unitdata the max len will be used. */ + +#define TP_MAX_LEN_AK (TP_FHDR_AK_LEN + TP_PAR_LEN_CHECKSUM) + + + /*--------------------------------------*/ + /* Struct and defines for RJ TPDU */ + /*--------------------------------------*/ + +typedef struct + { + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type_cdt; /* TPDU type and CDT */ + ST_UCHAR dest_ref [2]; /* Remote connection id */ + ST_UCHAR sn; /* Next expected DT TPDU sequence number*/ + }TP_FHDR_RJ; + +#define TP_FHDR_RJ_LEN 5 + + /* for alloc of n_unitdata the max len will be used. */ + +#define TP_MAX_LEN_RJ TP_FHDR_RJ_LEN + + /*--------------------------------------*/ + /* Struct and defines for ER TPDU */ + /*--------------------------------------*/ + +typedef struct + { + ST_UCHAR hdr_len; /* hdr length (don't count the len byte)*/ + ST_UCHAR type; /* TPDU type */ + ST_UCHAR dest_ref [2]; /* Remote connection id */ + ST_UCHAR reason; /* Code for reject couse */ + }TP_FHDR_ER; + +#define TP_FHDR_ER_LEN 5 + + /* for alloc of n_unitdata the max len will be used. */ + +#define TP_MAX_LEN_ER (TP_FHDR_ER_LEN + TP_PAR_LEN_CHECKSUM) + + + /*----------------------------------------------*/ + /* Function prototypes for encoding/decoding */ + /*----------------------------------------------*/ + +ST_UINT16 tp_encode_cx (ST_UCHAR *enc_buf, TPDU_CX *tpdu_cx, ST_UCHAR pdu_type); +ST_UINT16 tp_encode_dr (ST_UCHAR *enc_buf, TPDU_DR *tpdu_dr); +ST_UINT16 tp_encode_dc (ST_UCHAR *enc_buf, TPDU_DC *tpdu_dc); +ST_UINT16 tp_encode_dt (ST_UCHAR *enc_buf, TPDU_DT *tpdu_dt); +ST_UINT16 tp0_encode_dt (ST_UCHAR *enc_buf, TPDU_DT *tpdu_dt); +ST_UINT16 tp_encode_ak (ST_UCHAR *enc_buf, TPDU_AK *tpdu_ak); + +ST_RET tp_decode_nsdu (N_UNITDATA *n_unitdata); + +ST_UINT16 tp_decode_cx (TPDU_CX *tpdu_cx_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len, ST_UCHAR pdu_type, ST_UCHAR max_tpdu_len_enc); +ST_UINT16 tp_decode_dr (TPDU_DR *tpdu_dr_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len); +ST_UINT16 tp_decode_dc (TPDU_DC *tpdu_dc_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len); +ST_UINT16 tp_decode_dt (TPDU_DT *tpdu_dt_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len); +ST_UINT16 tp0_decode_dt (TPDU_DT *tpdu_dt_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len); +ST_UINT16 tp_decode_ak (TPDU_AK *tpdu_ak_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len); +ST_UINT16 tp_decode_er (TPDU_ER *tpdu_er_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len, + ST_INT tp_class); /* must be 0 or 4 */ + +ST_VOID tp_log_tsdu (ST_VOID *tsdu, ST_UCHAR type, ST_UCHAR mask); + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + + diff --git a/mmslib/inc/tp4_log.h b/mmslib/inc/tp4_log.h new file mode 100644 index 0000000..37694f1 --- /dev/null +++ b/mmslib/inc/tp4_log.h @@ -0,0 +1,228 @@ +#ifndef TP4_LOG_INCLUDED +#define TP4_LOG_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996 - 2008, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : tp4_log.h */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This header file contains logging macros for TP. */ +/* Note: To compile logging functions use the DEBUG_SISCO define */ +/* in the project make file. */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/30/08 EJV 05 Converted to new SLOG macros. */ +/* 05/10/05 EJV 04 Added TP_LOG_ERR3. */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 10/08/98 MDE 02 Migrated to updated SLOG interface */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 06/24/96 EJV 01 Created */ +/************************************************************************/ +#include "slog.h" +#include "tp4api.h" /* NOTE the masks are defined in tp4api.h, */ + /* should we include it here? */ + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************/ +/* Log Control types */ +/****************************************************************/ + +/* defined for TP_LOG.._RIn macros */ +#define TP_REQ (ST_UCHAR) 0 +#define TP_IND (ST_UCHAR) 1 + +#if defined(DEBUG_SISCO) + +extern SD_CONST ST_CHAR *SD_CONST _tp4_err_logstr; +extern SD_CONST ST_CHAR *SD_CONST _tp4_flowup_logstr; +extern SD_CONST ST_CHAR *SD_CONST _tp4_flowdown_logstr; + + /*--------------------------------------------*/ + /* errors logging */ + /*--------------------------------------------*/ + + #define TP_LOG_ERR0(a) SLOG_0 (tp4_debug_sel & TP4_LOG_ERR,_tp4_err_logstr,a) + #define TP_LOG_ERR1(a,b) SLOG_1 (tp4_debug_sel & TP4_LOG_ERR,_tp4_err_logstr,a,b) + #define TP_LOG_ERR2(a,b,c) SLOG_2 (tp4_debug_sel & TP4_LOG_ERR,_tp4_err_logstr,a,b,c) + #define TP_LOG_ERR3(a,b,c,d) SLOG_3 (tp4_debug_sel & TP4_LOG_ERR,_tp4_err_logstr,a,b,c,d) + + /* continuation log */ + + #define TP_LOGC_ERR0(a) SLOGC_0 (tp4_debug_sel & TP4_LOG_ERR,a) + #define TP_LOGC_ERR1(a,b) SLOGC_1 (tp4_debug_sel & TP4_LOG_ERR,a,b) + #define TP_LOGC_ERR2(a,b,c) SLOGC_2 (tp4_debug_sel & TP4_LOG_ERR,a,b,c) + #define TP_LOGC_ERR3(a,b,c,d) SLOGC_2 (tp4_debug_sel & TP4_LOG_ERR,a,b,c) + + /* hex logging */ + + #define TP_LOGH_ERR(a,b) SLOGH (tp4_debug_sel & TP4_LOG_ERR,a,b) + + /*--------------------------------------------*/ + /* Indication logging */ + /*--------------------------------------------*/ + + #define TP_LOG_IND0(a) SLOG_0 (tp4_debug_sel & TP4_LOG_FLOWUP,_tp4_flowup_logstr,a) + #define TP_LOG_IND1(a,b) SLOG_1 (tp4_debug_sel & TP4_LOG_FLOWUP,_tp4_flowup_logstr,a,b) + #define TP_LOG_IND2(a,b,c) SLOG_2 (tp4_debug_sel & TP4_LOG_FLOWUP,_tp4_flowup_logstr,a,b,c) + #define TP_LOG_IND3(a,b,c,d) SLOG_3 (tp4_debug_sel & TP4_LOG_FLOWUP,_tp4_flowup_logstr,a,b,c,d) + #define TP_LOG_IND4(a,b,c,d,e) SLOG_4 (tp4_debug_sel & TP4_LOG_FLOWUP,_tp4_flowup_logstr,a,b,c,d,e) + #define TP_LOG_IND5(a,b,c,d,e,f) SLOG_5 (tp4_debug_sel & TP4_LOG_FLOWUP,_tp4_flowup_logstr,a,b,c,d,e,f) + #define TP_LOG_IND6(a,b,c,d,e,f,g) SLOG_6 (tp4_debug_sel & TP4_LOG_FLOWUP,_tp4_flowup_logstr,a,b,c,d,e,f,g) + + /* continuation log */ + + #define TP_LOGC_IND0(a) SLOGC_0 (tp4_debug_sel & TP4_LOG_FLOWUP,a) + #define TP_LOGC_IND1(a,b) SLOGC_1 (tp4_debug_sel & TP4_LOG_FLOWUP,a,b) + #define TP_LOGC_IND2(a,b,c) SLOGC_2 (tp4_debug_sel & TP4_LOG_FLOWUP,a,b,c) + + /* hex logging */ + + #define TP_LOGH_IND(a,b) SLOGH (tp4_debug_sel & TP4_LOG_FLOWUP,a,b) + + /* continuation hex logging */ + + #define TP_LOGHC_IND(a,b) SLOGH (tp4_debug_sel & TP4_LOG_FLOWUP,a,b) + + /*--------------------------------------------*/ + /* Request logging */ + /*--------------------------------------------*/ + + #define TP_LOG_REQ0(a) SLOG_0 (tp4_debug_sel & TP4_LOG_FLOWDOWN,_tp4_flowdown_logstr,a) + #define TP_LOG_REQ1(a,b) SLOG_1 (tp4_debug_sel & TP4_LOG_FLOWDOWN,_tp4_flowdown_logstr,a,b) + #define TP_LOG_REQ2(a,b,c) SLOG_2 (tp4_debug_sel & TP4_LOG_FLOWDOWN,_tp4_flowdown_logstr,a,b,c) + #define TP_LOG_REQ3(a,b,c,d) SLOG_3 (tp4_debug_sel & TP4_LOG_FLOWDOWN,_tp4_flowdown_logstr,a,b,c,d) + #define TP_LOG_REQ4(a,b,c,d,e) SLOG_4 (tp4_debug_sel & TP4_LOG_FLOWDOWN,_tp4_flowdown_logstr,a,b,c,d,e) + #define TP_LOG_REQ5(a,b,c,d,e,f) SLOG_5 (tp4_debug_sel & TP4_LOG_FLOWDOWN,_tp4_flowdown_logstr,a,b,c,d,e,f) + #define TP_LOG_REQ6(a,b,c,d,e,f,g) SLOG_6 (tp4_debug_sel & TP4_LOG_FLOWDOWN,_tp4_flowdown_logstr,a,b,c,d,e,f,g) + + /* continuation log */ + + #define TP_LOGC_REQ0(a) SLOGC_0 (tp4_debug_sel & TP4_LOG_FLOWDOWN,a) + #define TP_LOGC_REQ1(a,b) SLOGC_1 (tp4_debug_sel & TP4_LOG_FLOWDOWN,a,b) + #define TP_LOGC_REQ2(a,b,c) SLOGC_2 (tp4_debug_sel & TP4_LOG_FLOWDOWN,a,b,c) + + /* hex logging */ + + #define TP_LOGH_REQ(a,b) SLOGH (tp4_debug_sel & TP4_LOG_FLOWDOWN,a,b) + + /* continuation hex logging */ + + #define TP_LOGHC_REQ(a,b) SLOGH (tp4_debug_sel & TP4_LOG_FLOWDOWN,a,b) + + /*--------------------------------------------------------------------*/ + /* macros below are used to log REQ or IND by passing mask to select */ + /* the logging macro (this is handy in log function so the macros */ + /* do not have to repeated in function for REQ and then for IND) */ + /*--------------------------------------------------------------------*/ + + #define TP_LOG_RI0(m,a) {if (m == TP_REQ) {TP_LOG_REQ0(a);} else {TP_LOG_IND0(a)};} + #define TP_LOG_RI1(m,a,b) {if (m == TP_REQ) {TP_LOG_REQ1(a,b);} else {TP_LOG_IND1(a,b);}} + #define TP_LOG_RI2(m,a,b,c) {if (m == TP_REQ) {TP_LOG_REQ2(a,b,c);} else {TP_LOG_IND2(a,b,c);}} + #define TP_LOG_RI3(m,a,b,c,d) {if (m == TP_REQ) {TP_LOG_REQ3(a,b,c,d);} else {TP_LOG_IND3(a,b,c,d);}} + #define TP_LOG_RI4(m,a,b,c,d,e) {if (m == TP_REQ) {TP_LOG_REQ4(a,b,c,d,e);} else {TP_LOG_IND4(a,b,c,d,e);}} + #define TP_LOG_RI5(m,a,b,c,d,e,f) {if (m == TP_REQ) {TP_LOG_REQ5(a,b,c,d,e,f);} else {TP_LOG_IND5(a,b,c,d,e,f);}} + #define TP_LOG_RI6(m,a,b,c,d,e,f,g) {if (m == TP_REQ) {TP_LOG_REQ6(a,b,c,d,e,f,g);} else {TP_LOG_IND6(a,b,c,d,e,f,g);}} + + #define TP_LOGC_RI0(m,a) {if (m == TP_REQ) {TP_LOGC_REQ0(a);} else {TP_LOGC_IND0(a);}} + #define TP_LOGC_RI1(m,a,b) {if (m == TP_REQ) {TP_LOGC_REQ1(a,b);} else {TP_LOGC_IND1(a,b);}} + #define TP_LOGC_RI2(m,a,b,c) {if (m == TP_REQ) {TP_LOGC_REQ2(a,b,c);} else {TP_LOGC_IND2(a,b,c);}} + + #define TP_LOGH_RI(m,a,b) {if (m == TP_REQ) {TP_LOGH_REQ(a,b);} else {TP_LOGH_IND(a,b);}} + #define TP_LOGHC_RI(m,a,b) {if (m == TP_REQ) {TP_LOGHC_REQ(a,b);} else {TP_LOGHC_IND(a,b);}} + + +#else /* macros if DEBUG_SISCO not defined */ + + /*--------------------------------------------*/ + /* errors logging */ + /*--------------------------------------------*/ + + #define TP_LOG_ERR0(a) + #define TP_LOG_ERR1(a,b) + #define TP_LOG_ERR2(a,b,c) + #define TP_LOG_ERR3(a,b,c,d) + + #define TP_LOGC_ERR0(a) + #define TP_LOGC_ERR1(a,b) + #define TP_LOGC_ERR2(a,b,c) + + #define TP_LOGH_ERR(a,b) + #define TP_LOGHC_ERR(a,b) + + /*--------------------------------------------*/ + /* Indication logging */ + /*--------------------------------------------*/ + + #define TP_LOG_IND0(a) + #define TP_LOG_IND1(a,b) + #define TP_LOG_IND2(a,b,c) + #define TP_LOG_IND3(a,b,c,d) + #define TP_LOG_IND4(a,b,c,d,e) + #define TP_LOG_IND5(a,b,c,d,e,f) + #define TP_LOG_IND6(a,b,c,d,e,f,g) + + #define TP_LOGC_IND0(a) + #define TP_LOGC_IND1(a,b) + #define TP_LOGC_IND2(a,b,c) + + #define TP_LOGH_IND(a,b) + #define TP_LOGHC_IND(a,b) + + /*--------------------------------------------*/ + /* Request logging */ + /*--------------------------------------------*/ + + #define TP_LOG_REQ0(a) + #define TP_LOG_REQ1(a,b) + #define TP_LOG_REQ2(a,b,c) + #define TP_LOG_REQ3(a,b,c,d) + #define TP_LOG_REQ4(a,b,c,d,e) + #define TP_LOG_REQ5(a,b,c,d,e,f) + #define TP_LOG_REQ6(a,b,c,d,e,f,g) + + #define TP_LOGC_REQ0(a) + #define TP_LOGC_REQ1(a,b) + #define TP_LOGC_REQ2(a,b,c) + + #define TP_LOGH_REQ(a,b) + #define TP_LOGHC_REQ(a,b) + + /*--------------------------------------------------------------------*/ + /* macros below are used to log REQ or IND by passing mask */ + /*--------------------------------------------------------------------*/ + + #define TP_LOG_RI0(m,a) + #define TP_LOG_RI1(m,a,b) + #define TP_LOG_RI2(m,a,b,c) + #define TP_LOG_RI3(m,a,b,c,d) + #define TP_LOG_RI4(m,a,b,c,d,e) + #define TP_LOG_RI5(m,a,b,c,d,e,f) + #define TP_LOG_RI6(m,a,b,c,d,e,f,g) + + #define TP_LOGC_RI0(m,a) + #define TP_LOGC_RI1(m,a,b) + #define TP_LOGC_RI2(m,a,b,c) + + #define TP_LOGH_RI(m,a,b) + #define TP_LOGHC_RI(m,a,b) + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* end of 'already included' */ + diff --git a/mmslib/inc/tp4api.h b/mmslib/inc/tp4api.h new file mode 100644 index 0000000..48543f3 --- /dev/null +++ b/mmslib/inc/tp4api.h @@ -0,0 +1,333 @@ +#ifndef TP4API_INCLUDED +#define TP4API_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2005 All Rights Reserved */ +/* */ +/* MODULE NAME : tp4api.h */ +/* PRODUCT(S) : TP4 API user include file */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/27/05 JRB 23 Del obsolete DS_INFO, tp4_ds_*, odbc_ds_*. */ +/* 05/05/05 EJV 22 TP0_CFG: added rfc1006_listen_port */ +/* TP4_ADDR added port. */ +/* 04/06/05 EJV 21 MMSEASE_MOSI: use 32 for MAX_TSEL_LEN */ +/* 09/17/04 JRB 20 Chg tp?_connect to ret ST_LONG (i.e. conn_id)*/ +/* 01/14/04 EJV 19 TP0_CFG: added max_spdu_outst. */ +/* 08/25/03 EJV 18 Added encrypt_ctrl arg to tp0_connect(). */ +/* Added param to tp4_connect macro. */ +/* 06/20/02 JRB 17 Replace net_addr with union in TP4_ADDR. */ +/* Chg addr args to tp4_connect_ind. */ +/* Add tp0_convert_ip proto. */ +/* 05/08/02 JRB 16 Add tp0_connect_outstanding_count proto. */ +/* 01/22/02 JRB 15 Add max_conns arg to tp*_initialize. */ +/* 05/10/01 JRB 14 Chg TSEL_LEN from 32 to 4. */ +/* 03/14/01 JRB 13 Add global session_cfg w/ disconnect_timeout.*/ +/* 08/05/99 JRB 12 Add hTcp... extern. */ +/* 06/08/99 JRB 11 Change max_num_conns to ST_UINT16 to allow */ +/* many more connections. */ +/* 01/28/99 JRB 10 Addec cltp_decode_nsdu_fun funct ptr. */ +/* 08/13/98 JRB 09 Lint cleanup. */ +/* 06/18/98 JRB 08 Add TP_TYPE_TPX. */ +/* 03/11/98 JRB 07 Del max_spdu_len from TP0_CFG & TP_CFG. */ +/* Add keepalive to TP0_CFG. */ +/* 09/04/07 JRB 06 Add max_spdu_len arg to tp4_initialize. */ +/* 08/14/97 JRB 05 RFC1006 changes: */ +/* - Add "tp0_*" protos. */ +/* - Add "tp_type" to TP4_ADDR. */ +/* - Add "tp0_cfg" config struct for RFC1006. */ +/* - Chg "tp4_data" arg "data_len" to ST_UINT. */ +/* - Replace tp4_reldata proto with dummy macro.*/ +/* - Chg MAX_TP4_SEL to MAX_TSEL_LEN (ACSE uses)*/ +/* - Chg MAX_NET_ADDR to MAX_IP_ADDR_LEN and */ +/* increase to allow IP hostname. */ +/* 08/04/97 JRB 04 Add max_tpdu_len_enc to TP_CFG (use instead */ +/* of global max_tpdu_len_enc). */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 05/07/97 JRB 03 Added Error codes. */ +/* 02/20/97 EJV 02 Added MOSI support: tp4_session_timer and */ +/* tp4_session_timer_expired. */ +/* 11/14/96 JRB 01 Created for LEAN_T only. */ +/************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ssec.h" /* for S_SEC_ENCRYPT_CTRL */ +#include "clnp_usr.h" /* Need CLNP_MAX_LEN_NSAP define. */ + +/* Defines for Transport type. Used to set "tp_type" in TP4_ADDR. */ +#define TP_TYPE_TCP 0 +#define TP_TYPE_TP4 1 +#define TP_TYPE_TPX 2 /* allow TP4 and TCP at same time. */ + +/****************************************************************/ +/* Structure definitions */ +/****************************************************************/ + +#if defined(MMSEASE_MOSI) +#define MAX_TSEL_LEN 32 +#else +#define MAX_TSEL_LEN 4 /* GOSIP Ver2 recommends len of 2 */ +#endif +#define MAX_IP_ADDR_LEN 80 /* Big enough for IP hostname */ + +typedef struct tagTP4_ADDR + { +#if !defined(REDUCED_STACK) + ST_INT tp_type; /* Type of transport: TP_TYPE_TP4 or TP_TYPE_TCP.*/ + ST_UINT tp4_sel_len; + char tp4_sel[MAX_TSEL_LEN]; + ST_UINT net_addr_len; + union + { /* If TP_TYPE_TP4, use "nsap". If TP_TYPE_TCP, use "ip". */ + ST_UCHAR nsap [CLNP_MAX_LEN_NSAP]; /* NSAP OR */ + ST_ULONG ip; /* IP Addr (network byte order) */ + }netAddr; + ST_UINT16 port; /* remote port, optional param, */ + /* defaults to 102 if not config*/ +#else + ST_UINT16 adlcAddr; +#endif + } TP4_ADDR; + +/****************************************************************/ +/* API prototypes */ +/****************************************************************/ + +ST_RET tp4_initialize (ST_UINT max_conns, ST_UINT max_spdu_len); +ST_RET tp4_terminate (ST_VOID); + +ST_BOOLEAN tp4_event (ST_VOID); + +ST_RET tp4_bind (ST_LONG user_bind_id, TP4_ADDR *tp4_addr, + ST_INT sharable, ST_INT max_conns); +ST_RET tp4_unbind (ST_LONG tp4_bind_id); + +ST_LONG tp4_connect (ST_LONG tp4_bind_id, ST_LONG user_conn_id, + TP4_ADDR *rem_tp4_addr, + ST_INT conndata_len, + char *conndata, + S_SEC_ENCRYPT_CTRL *encrypt_ctrl); /* connection encryption info */ + +ST_RET tp4_accept (ST_LONG tp4_conn_id, ST_LONG user_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp4_disconnect (ST_LONG tp4_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp4_data (ST_LONG tp4_conn_id, + ST_INT eot, + ST_UINT data_len, + char *data); +ST_RET tp4_expdata (ST_LONG tp4_conn_id, + ST_UINT data_len, + char *data); + +/* The "tp4_reldata" function is not needed in this TP4 implementation, */ +/* so define "tp4_reldata" macro which does nothing. */ +#define tp4_reldata(databuf) + +/* Function for MOSI implementation: */ +ST_RET tp4_session_timer (ST_LONG tp_conn_id, ST_BOOLEAN start); + +ST_RET tp0_initialize (ST_UINT max_conns, ST_UINT max_spdu_len); +ST_RET tp0_terminate (ST_VOID); + +ST_BOOLEAN tp0_event (ST_VOID); + +ST_RET tp0_bind (ST_LONG user_bind_id, TP4_ADDR *tp4_addr, + ST_INT sharable, ST_INT max_conns); +ST_RET tp0_unbind (ST_LONG tp4_bind_id); + +ST_LONG tp0_connect (ST_LONG tp4_bind_id, ST_LONG user_conn_id, + TP4_ADDR *rem_tp4_addr, + ST_INT conndata_len, + char *conndata, + S_SEC_ENCRYPT_CTRL *encrypt_ctrl); +ST_INT tp0_connect_outstanding_count (TP4_ADDR *tp4Addr); +ST_RET tp0_accept (ST_LONG tp4_conn_id, ST_LONG user_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp0_disconnect (ST_LONG tp4_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp0_data (ST_LONG tp4_conn_id, + ST_INT eot, + ST_UINT data_len, + char *data); + +/* Function for MOSI implementation: */ +ST_RET tp0_session_timer (ST_LONG tp_conn_id, ST_BOOLEAN start); + +/****************************************************************/ +/* Event callback function prototypes */ +/****************************************************************/ + +ST_VOID tp4_bind_cnf (ST_LONG user_bind_id, ST_LONG tp4_bind_id, ST_RET result); +ST_VOID tp4_unbind_cnf (ST_LONG user_bind_id); + +ST_VOID tp4_connect_ind (ST_LONG user_bind_id, ST_LONG tp4_conn_id, + ST_UCHAR *loc_tsap, ST_UCHAR *rem_tsap, + ST_UCHAR *rem_nsap, ST_ULONG rem_ip, + ST_INT conndata_len, char *conndata); +ST_VOID tp4_connect_cnf (ST_LONG user_conn_id, ST_LONG tp4_conn_id, + ST_INT conndata_len, char *conndata); +ST_VOID tp4_disconnect_ind (ST_LONG user_conn_id, ST_INT reason, + ST_INT conndata_len, char *conndata); +ST_VOID tp4_data_ind (ST_LONG user_conn_id, ST_INT eot, + ST_UINT data_len, char *data); +ST_VOID tp4_expdata_ind (ST_LONG user_conn_id, + ST_UINT data_len, char *data); + +/* Function for MOSI implementation: */ +ST_VOID tp4_session_timer_expired (ST_LONG user_conn_id); + + +/****************************************************************/ +/* Log Control */ +/****************************************************************/ + +#define TP4_LOG_ERR 0x00000001 +#define TP4_LOG_FLOWUP 0x00000002 +#define TP4_LOG_FLOWDOWN 0x00000004 + +extern ST_UINT tp4_debug_sel; + +/****************************************************************/ +/* Error Codes */ +/****************************************************************/ + +#define TP4E_SHMALLOC 0x1201 +#define TP4E_BADCONN 0x1202 +#define TP4E_QUEUE_FULL 0x1203 +#define TP4E_CONN_STATE 0x1204 +#define TP4E_INVAL_TPDU_LEN 0x1205 +#define TP4E_INVAL_REM_CDT 0x1206 +#define TP4E_INVAL_LOC_CDT 0x1207 +#define TP4E_INVAL_SPDU_OUTST 0x1208 +#define TP4E_INVAL_NUM_CONNS 0x1209 +#define TP4E_INVAL_SPDU_LEN 0x120A +#define TP4E_INVAL_WINDOW_TIME 0x120B +#define TP4E_INVAL_INACT_TIME 0x120C +#define TP4E_INVAL_RETRANS_TIME 0x120D +#define TP4E_INVAL_MAX_TRANS 0x120E +#define TP4E_MALLOC 0x120F +#define TP4E_INVAL_TSEL 0x1210 +#define TP4E_TOO_MANY_BINDS 0x1211 + + +/************************************************************************/ +/* Global Configuration Structure Typedef. */ +/************************************************************************/ +typedef struct + { + ST_UINT16 max_tpdu_len; /* max len of TPDU. Base on SNPDU size.*/ + /* Use to allocate TPDU buffers. */ + ST_UCHAR max_tpdu_len_enc; /* Binary encoded MAX TPDU len. Computed*/ + /* from max_tpdu_len by tp4_initialize. */ + ST_UCHAR max_rem_cdt; /* Max credits we can handle. */ + /* Will allocate this many TPDU_DT */ + /* structs. */ + /* CRITICAL: MUST BE POWER OF 2. */ + ST_UCHAR loc_cdt; /* CDT value we will ALWAYS send in ACK */ + /* We only accept in-sequence TPDUs so */ + /* only purpose of this is to */ + /* allow peer to send ahead. */ + ST_UCHAR max_spdu_outst; /* Max # of SPDUs outstanding per conn. */ + /* Will allocate this many SPDU_INFO */ + /* structs for transmit queue. */ + /* CRITICAL: MUST BE POWER OF 2. */ + ST_UINT16 max_num_conns; /* Max # Connections */ + ST_UINT16 window_time; /* Window Time */ + ST_UINT16 inact_time; /* Inactivity Time */ + ST_UINT16 retrans_time; /* Retransmission Time */ + ST_UCHAR max_trans; /* Max # of transmissions of a TPDU */ + ST_UCHAR ak_delay; /* # of loops to delay sending AK. */ + } TP_CFG; + +typedef struct + { + ST_UINT16 max_tpdu_len; /* max len of TPDU. Base on SNPDU size.*/ + /* Use to allocate TPDU buffers. */ + ST_UCHAR max_tpdu_len_enc; /* Binary encoded MAX TPDU len. Computed*/ + /* from max_tpdu_len by tp0_initialize. */ + ST_UINT max_spdu_outst; /* Max # of SPDUs outstanding per conn. */ + /* that can be queued on the gensock2 */ + ST_UINT16 max_num_conns; /* Max # Connections */ + ST_BOOLEAN keepalive; /* Use KEEPALIVE option on Sockets? */ + ST_UINT16 rfc1006_listen_port;/* RFC1006 listen port, optional param, */ + /* will default to 102 if not configured*/ + } TP0_CFG; /* For TP0/RFC1006 only. */ + +typedef struct + { + ST_UINT16 disconnect_timeout; /* time to wait for T-disconnect. */ + } SESSION_CFG; + +/************************************************************************/ +/* Global Configuration Structure */ +/* This structure must be filled in by user BEFORE tp4_initialize (). */ +/* It MUST NOT change after tp4_initialize (). */ +/************************************************************************/ +extern TP_CFG tp_cfg; +extern TP0_CFG tp0_cfg; /* For TP0/RFC1006 only. */ +extern SESSION_CFG session_cfg; + +/************************************************************************/ +/* Global Variables */ +/************************************************************************/ +/* CLTP decode function pointer. */ +extern ST_VOID (*cltp_decode_nsdu_fun) (N_UNITDATA *n_unitdata); + +/************************************************************************/ +/* Additional Prototypes for LEAN_T only. */ +/************************************************************************/ + +ST_VOID tp4_except (ST_CHAR *filename, ST_INT line); +ST_VOID tp4_timer_tick (ST_VOID); +ST_RET tp4_config (ST_VOID); +ST_VOID tp4_init_timer (ST_VOID); +ST_VOID tp4_check_timer (ST_VOID); +ST_INT tp4_buffers_avail (ST_LONG tp4_conn_id); + +ST_VOID tp0_timer_tick (ST_VOID); +ST_INT tp0_buffers_avail (ST_LONG tp4_conn_id); +ST_ULONG tp0_convert_ip (ST_CHAR *hostname); + +/************************************************************************/ +/* Event semaphore to indicate TCP events. */ +/************************************************************************/ +extern ST_EVENT_SEM hTcpEvent; + +/************************************************************************/ +/* Replacement function macros. If no TP4, call TP0 functions. */ +/************************************************************************/ +#if !defined (TP4_ENABLED) +#define tp4_initialize(a,b) tp0_initialize(a,b) +#define tp4_terminate() tp0_terminate() +#define tp4_event() tp0_event() +#define tp4_bind(a,b,c,d) tp0_bind(a,b,c,d) +#define tp4_unbind(a) tp0_unbind(a) +#define tp4_connect(a,b,c,d,e,f) tp0_connect(a,b,c,d,e,f) +#define tp4_accept(a,b,c,d) tp0_accept(a,b,c,d) +#define tp4_disconnect(a,b,c) tp0_disconnect(a,b,c) +#define tp4_data(a,b,c,d) tp0_data(a,b,c,d) +#define tp4_session_timer(a,b) tp0_session_timer(a,b) +#define tp4_timer_tick() tp0_timer_tick() +#define tp4_buffers_avail(a) tp0_buffers_avail(a) +#endif /* !defined (TP4_ENABLED) */ + +#ifdef __cplusplus +} +#endif +#endif /* !TP4API_INCLUDED */ diff --git a/mmslib/inc/tp4api.h.bak b/mmslib/inc/tp4api.h.bak new file mode 100644 index 0000000..73cf08f --- /dev/null +++ b/mmslib/inc/tp4api.h.bak @@ -0,0 +1,333 @@ +#ifndef TP4API_INCLUDED +#define TP4API_INCLUDED +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2005 All Rights Reserved */ +/* */ +/* MODULE NAME : tp4api.h */ +/* PRODUCT(S) : TP4 API user include file */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/27/05 JRB 23 Del obsolete DS_INFO, tp4_ds_*, odbc_ds_*. */ +/* 05/05/05 EJV 22 TP0_CFG: added rfc1006_listen_port */ +/* TP4_ADDR added port. */ +/* 04/06/05 EJV 21 MMSEASE_MOSI: use 32 for MAX_TSEL_LEN */ +/* 09/17/04 JRB 20 Chg tp?_connect to ret ST_LONG (i.e. conn_id)*/ +/* 01/14/04 EJV 19 TP0_CFG: added max_spdu_outst. */ +/* 08/25/03 EJV 18 Added encrypt_ctrl arg to tp0_connect(). */ +/* Added param to tp4_connect macro. */ +/* 06/20/02 JRB 17 Replace net_addr with union in TP4_ADDR. */ +/* Chg addr args to tp4_connect_ind. */ +/* Add tp0_convert_ip proto. */ +/* 05/08/02 JRB 16 Add tp0_connect_outstanding_count proto. */ +/* 01/22/02 JRB 15 Add max_conns arg to tp*_initialize. */ +/* 05/10/01 JRB 14 Chg TSEL_LEN from 32 to 4. */ +/* 03/14/01 JRB 13 Add global session_cfg w/ disconnect_timeout.*/ +/* 08/05/99 JRB 12 Add hTcp... extern. */ +/* 06/08/99 JRB 11 Change max_num_conns to ST_UINT16 to allow */ +/* many more connections. */ +/* 01/28/99 JRB 10 Addec cltp_decode_nsdu_fun funct ptr. */ +/* 08/13/98 JRB 09 Lint cleanup. */ +/* 06/18/98 JRB 08 Add TP_TYPE_TPX. */ +/* 03/11/98 JRB 07 Del max_spdu_len from TP0_CFG & TP_CFG. */ +/* Add keepalive to TP0_CFG. */ +/* 09/04/07 JRB 06 Add max_spdu_len arg to tp4_initialize. */ +/* 08/14/97 JRB 05 RFC1006 changes: */ +/* - Add "tp0_*" protos. */ +/* - Add "tp_type" to TP4_ADDR. */ +/* - Add "tp0_cfg" config struct for RFC1006. */ +/* - Chg "tp4_data" arg "data_len" to ST_UINT. */ +/* - Replace tp4_reldata proto with dummy macro.*/ +/* - Chg MAX_TP4_SEL to MAX_TSEL_LEN (ACSE uses)*/ +/* - Chg MAX_NET_ADDR to MAX_IP_ADDR_LEN and */ +/* increase to allow IP hostname. */ +/* 08/04/97 JRB 04 Add max_tpdu_len_enc to TP_CFG (use instead */ +/* of global max_tpdu_len_enc). */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 05/07/97 JRB 03 Added Error codes. */ +/* 02/20/97 EJV 02 Added MOSI support: tp4_session_timer and */ +/* tp4_session_timer_expired. */ +/* 11/14/96 JRB 01 Created for LEAN_T only. */ +/************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ssec.h" /* for S_SEC_ENCRYPT_CTRL */ +#include "clnp_usr.h" /* Need CLNP_MAX_LEN_NSAP define. */ + +/* Defines for Transport type. Used to set "tp_type" in TP4_ADDR. */ +#define TP_TYPE_TCP 0 +#define TP_TYPE_TP4 1 +#define TP_TYPE_TPX 2 /* allow TP4 and TCP at same time. */ + +/****************************************************************/ +/* Structure definitions */ +/****************************************************************/ + +#if defined(MMSEASE_MOSI) +#define MAX_TSEL_LEN 32 +#else +#define MAX_TSEL_LEN 4 /* GOSIP Ver2 recommends len of 2 */ +#endif +#define MAX_IP_ADDR_LEN 80 /* Big enough for IP hostname */ + +typedef struct tagTP4_ADDR + { +#if !defined(REDUCED_STACK) + ST_INT tp_type; /* Type of transport: TP_TYPE_TP4 or TP_TYPE_TCP.*/ + ST_UINT tp4_sel_len; + char tp4_sel[MAX_TSEL_LEN]; + ST_UINT net_addr_len; + union + { /* If TP_TYPE_TP4, use "nsap". If TP_TYPE_TCP, use "ip". */ + ST_UCHAR nsap [CLNP_MAX_LEN_NSAP]; /* NSAP OR */ + ST_ULONG ip; /* IP Addr (network byte order) */ + }netAddr; + ST_UINT16 port; /* remote port, optional param, */ + /* defaults to 102 if not config*/ +#else + ST_UINT16 adlcAddr; +#endif + } TP4_ADDR; + +/****************************************************************/ +/* API prototypes */ +/****************************************************************/ + +ST_RET tp4_initialize (ST_UINT max_conns, ST_UINT max_spdu_len); +ST_RET tp4_terminate (ST_VOID); + +ST_BOOLEAN tp4_event (ST_VOID); + +ST_RET tp4_bind (ST_LONG user_bind_id, TP4_ADDR *tp4_addr, + ST_INT sharable, ST_INT max_conns); +ST_RET tp4_unbind (ST_LONG tp4_bind_id); + +ST_LONG tp4_connect (ST_LONG tp4_bind_id, ST_LONG user_conn_id, + TP4_ADDR *rem_tp4_addr, + ST_INT conndata_len, + char *conndata, + S_SEC_ENCRYPT_CTRL *encrypt_ctrl); /* connection encryption info */ + +ST_RET tp4_accept (ST_LONG tp4_conn_id, ST_LONG user_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp4_disconnect (ST_LONG tp4_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp4_data (ST_LONG tp4_conn_id, + ST_INT eot, + ST_UINT data_len, + char *data); +ST_RET tp4_expdata (ST_LONG tp4_conn_id, + ST_UINT data_len, + char *data); + +/* The "tp4_reldata" function is not needed in this TP4 implementation, */ +/* so define "tp4_reldata" macro which does nothing. */ +#define tp4_reldata(databuf) + +/* Function for MOSI implementation: */ +ST_RET tp4_session_timer (ST_LONG tp_conn_id, ST_BOOLEAN start); + +ST_RET tp0_initialize (ST_UINT max_conns, ST_UINT max_spdu_len); +ST_RET tp0_terminate (ST_VOID); + +ST_BOOLEAN tp0_event (ST_VOID); + +ST_RET tp0_bind (ST_LONG user_bind_id, TP4_ADDR *tp4_addr, + ST_INT sharable, ST_INT max_conns); +ST_RET tp0_unbind (ST_LONG tp4_bind_id); + +ST_LONG tp0_connect (ST_LONG tp4_bind_id, ST_LONG user_conn_id, + TP4_ADDR *rem_tp4_addr, + ST_INT conndata_len, + char *conndata, + S_SEC_ENCRYPT_CTRL *encrypt_ctrl); +ST_INT tp0_connect_outstanding_count (TP4_ADDR *tp4Addr); +ST_RET tp0_accept (ST_LONG tp4_conn_id, ST_LONG user_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp0_disconnect (ST_LONG tp4_conn_id, + ST_INT conndata_len, + char *conndata); +ST_RET tp0_data (ST_LONG tp4_conn_id, + ST_INT eot, + ST_UINT data_len, + char *data); + +/* Function for MOSI implementation: */ +ST_RET tp0_session_timer (ST_LONG tp_conn_id, ST_BOOLEAN start); + +/****************************************************************/ +/* Event callback function prototypes */ +/****************************************************************/ + +ST_VOID tp4_bind_cnf (ST_LONG user_bind_id, ST_LONG tp4_bind_id, ST_RET result); +ST_VOID tp4_unbind_cnf (ST_LONG user_bind_id); + +/*ST_VOID tp4_connect_ind (ST_LONG user_bind_id, ST_LONG tp4_conn_id, + ST_UCHAR *loc_tsap, ST_UCHAR *rem_tsap, + ST_UCHAR *rem_nsap, ST_ULONG rem_ip, + ST_INT conndata_len, char *conndata);*/ +ST_VOID tp4_connect_cnf (ST_LONG user_conn_id, ST_LONG tp4_conn_id, + ST_INT conndata_len, char *conndata); +ST_VOID tp4_disconnect_ind (ST_LONG user_conn_id, ST_INT reason, + ST_INT conndata_len, char *conndata); +ST_VOID tp4_data_ind (ST_LONG user_conn_id, ST_INT eot, + ST_UINT data_len, char *data); +ST_VOID tp4_expdata_ind (ST_LONG user_conn_id, + ST_UINT data_len, char *data); + +/* Function for MOSI implementation: */ +ST_VOID tp4_session_timer_expired (ST_LONG user_conn_id); + + +/****************************************************************/ +/* Log Control */ +/****************************************************************/ + +#define TP4_LOG_ERR 0x00000001 +#define TP4_LOG_FLOWUP 0x00000002 +#define TP4_LOG_FLOWDOWN 0x00000004 + +extern ST_UINT tp4_debug_sel; + +/****************************************************************/ +/* Error Codes */ +/****************************************************************/ + +#define TP4E_SHMALLOC 0x1201 +#define TP4E_BADCONN 0x1202 +#define TP4E_QUEUE_FULL 0x1203 +#define TP4E_CONN_STATE 0x1204 +#define TP4E_INVAL_TPDU_LEN 0x1205 +#define TP4E_INVAL_REM_CDT 0x1206 +#define TP4E_INVAL_LOC_CDT 0x1207 +#define TP4E_INVAL_SPDU_OUTST 0x1208 +#define TP4E_INVAL_NUM_CONNS 0x1209 +#define TP4E_INVAL_SPDU_LEN 0x120A +#define TP4E_INVAL_WINDOW_TIME 0x120B +#define TP4E_INVAL_INACT_TIME 0x120C +#define TP4E_INVAL_RETRANS_TIME 0x120D +#define TP4E_INVAL_MAX_TRANS 0x120E +#define TP4E_MALLOC 0x120F +#define TP4E_INVAL_TSEL 0x1210 +#define TP4E_TOO_MANY_BINDS 0x1211 + + +/************************************************************************/ +/* Global Configuration Structure Typedef. */ +/************************************************************************/ +typedef struct + { + ST_UINT16 max_tpdu_len; /* max len of TPDU. Base on SNPDU size.*/ + /* Use to allocate TPDU buffers. */ + ST_UCHAR max_tpdu_len_enc; /* Binary encoded MAX TPDU len. Computed*/ + /* from max_tpdu_len by tp4_initialize. */ + ST_UCHAR max_rem_cdt; /* Max credits we can handle. */ + /* Will allocate this many TPDU_DT */ + /* structs. */ + /* CRITICAL: MUST BE POWER OF 2. */ + ST_UCHAR loc_cdt; /* CDT value we will ALWAYS send in ACK */ + /* We only accept in-sequence TPDUs so */ + /* only purpose of this is to */ + /* allow peer to send ahead. */ + ST_UCHAR max_spdu_outst; /* Max # of SPDUs outstanding per conn. */ + /* Will allocate this many SPDU_INFO */ + /* structs for transmit queue. */ + /* CRITICAL: MUST BE POWER OF 2. */ + ST_UINT16 max_num_conns; /* Max # Connections */ + ST_UINT16 window_time; /* Window Time */ + ST_UINT16 inact_time; /* Inactivity Time */ + ST_UINT16 retrans_time; /* Retransmission Time */ + ST_UCHAR max_trans; /* Max # of transmissions of a TPDU */ + ST_UCHAR ak_delay; /* # of loops to delay sending AK. */ + } TP_CFG; + +typedef struct + { + ST_UINT16 max_tpdu_len; /* max len of TPDU. Base on SNPDU size.*/ + /* Use to allocate TPDU buffers. */ + ST_UCHAR max_tpdu_len_enc; /* Binary encoded MAX TPDU len. Computed*/ + /* from max_tpdu_len by tp0_initialize. */ + ST_UINT max_spdu_outst; /* Max # of SPDUs outstanding per conn. */ + /* that can be queued on the gensock2 */ + ST_UINT16 max_num_conns; /* Max # Connections */ + ST_BOOLEAN keepalive; /* Use KEEPALIVE option on Sockets? */ + ST_UINT16 rfc1006_listen_port;/* RFC1006 listen port, optional param, */ + /* will default to 102 if not configured*/ + } TP0_CFG; /* For TP0/RFC1006 only. */ + +typedef struct + { + ST_UINT16 disconnect_timeout; /* time to wait for T-disconnect. */ + } SESSION_CFG; + +/************************************************************************/ +/* Global Configuration Structure */ +/* This structure must be filled in by user BEFORE tp4_initialize (). */ +/* It MUST NOT change after tp4_initialize (). */ +/************************************************************************/ +extern TP_CFG tp_cfg; +extern TP0_CFG tp0_cfg; /* For TP0/RFC1006 only. */ +extern SESSION_CFG session_cfg; + +/************************************************************************/ +/* Global Variables */ +/************************************************************************/ +/* CLTP decode function pointer. */ +extern ST_VOID (*cltp_decode_nsdu_fun) (N_UNITDATA *n_unitdata); + +/************************************************************************/ +/* Additional Prototypes for LEAN_T only. */ +/************************************************************************/ + +ST_VOID tp4_except (ST_CHAR *filename, ST_INT line); +ST_VOID tp4_timer_tick (ST_VOID); +ST_RET tp4_config (ST_VOID); +ST_VOID tp4_init_timer (ST_VOID); +ST_VOID tp4_check_timer (ST_VOID); +ST_INT tp4_buffers_avail (ST_LONG tp4_conn_id); + +ST_VOID tp0_timer_tick (ST_VOID); +ST_INT tp0_buffers_avail (ST_LONG tp4_conn_id); +ST_ULONG tp0_convert_ip (ST_CHAR *hostname); + +/************************************************************************/ +/* Event semaphore to indicate TCP events. */ +/************************************************************************/ +extern ST_EVENT_SEM hTcpEvent; + +/************************************************************************/ +/* Replacement function macros. If no TP4, call TP0 functions. */ +/************************************************************************/ +#if !defined (TP4_ENABLED) +#define tp4_initialize(a,b) tp0_initialize(a,b) +#define tp4_terminate() tp0_terminate() +#define tp4_event() tp0_event() +#define tp4_bind(a,b,c,d) tp0_bind(a,b,c,d) +#define tp4_unbind(a) tp0_unbind(a) +#define tp4_connect(a,b,c,d,e,f) tp0_connect(a,b,c,d,e,f) +#define tp4_accept(a,b,c,d) tp0_accept(a,b,c,d) +#define tp4_disconnect(a,b,c) tp0_disconnect(a,b,c) +#define tp4_data(a,b,c,d) tp0_data(a,b,c,d) +#define tp4_session_timer(a,b) tp0_session_timer(a,b) +#define tp4_timer_tick() tp0_timer_tick() +#define tp4_buffers_avail(a) tp0_buffers_avail(a) +#endif /* !defined (TP4_ENABLED) */ + +#ifdef __cplusplus +} +#endif +#endif /* !TP4API_INCLUDED */ diff --git a/mmslib/mem/mem_chks.c b/mmslib/mem/mem_chks.c new file mode 100644 index 0000000..5c16df2 --- /dev/null +++ b/mmslib/mem/mem_chks.c @@ -0,0 +1,1837 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986-2008 All Rights Reserved */ +/* */ +/* MODULE NAME : mem_chks.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains enhanced memory allocation functions */ +/* for performing various integrity checks */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/04/08 EJV 56 _nd_chk_* corr: del ++/-- chk_curr_mem_count;*/ +/* (was not protected in multithreaded apps). */ +/* m_mem_debug: init to SD_TRUE for lib products*/ +/* 10/04/07 MDE 55 Tweaked LOGCFG_VALUE_GROUP/LOGCFGX_VALUE_MAP */ +/* 01/15/07 EJV 54 Chg S_LOCK_RESOURCES to S_LOCK_UTIL_RESOURCES*/ +/* 10/25/06 MDE 53 Removed msjexhnd.h include */ +/* 08/23/06 DSF 52 Call to ExpInit () no longer needed */ +/* 08/09/06 JRB 51 Log error if m_mem_debug changed after startup*/ +/* 07/14/06 DSF 50 Ported to VS2005 compiler */ +/* 03/01/06 EJV 49 Moved mem_chk.h outside define. */ +/* 02/28/06 RLH 48 avoid duplicate definition of #define */ +/* 01/30/06 GLB 47 Integrated porting changes for VMS */ +/* 10/13/05 EJV 46 dyn_mem_ptr_status2: combined 2 slogs. */ +/* 05/11/05 MDE 45 Minor logging */ +/* 05/23/05 EJV 44 Add memLogMaskMapCtrl & memDebugMapCtrl */ +/* for parsing logcfg.xml */ +/* 05/11/05 MDE 43 Now do list check for chk_calloc too */ +/* 03/10/04 EJV 42 Use '%lu' and typecast to (ST_ULONG) for */ +/* ST_UINT32 logging. */ +/* 02/06/04 EJV 42 Added dyn_mem_ptr_status2. */ +/* Use '%u' when logging memory statistics. */ +/* 06/06/03 JRB 41 Use S_LOCK_RESOURCES (new util mutex). */ +/* 04/08/03 DSF 40 1) No need to lock common resources in nd_ */ +/* functions or when checking if we've been */ +/* initialized */ +/* 2) Use Microsoft CRT Debug calls when */ +/* MEMCHK_WIN32_CRT_DEBUG is defined and */ +/* m_mem_crt_debug is set */ +/* 03/06/02 JRB 39 Add S_UNLOCK.. before ret in chk_alloc_ptr. */ +/* 02/11/02 DSF 38 Add a call to ExpInit () */ +/* 10/18/01 JRB 37 Eliminate warning. Fix *_memerr_fun calls. */ +/* 10/10/01 JRB 36 Del unused valid_string function. */ +/* 09/19/01 JRB 35 Add NULL ptr check in dyn_mem_ptr_status. */ +/* 08/29/01 EJV 34 mem_report: prevented stack overflow. */ +/* 08/20/01 JRB 33 If !DEBUG_SISCO, chk_* macros call nd_chk_*. */ +/* If DEBUG_SISCO, chk_* macros call x_chk_*. */ +/* nd_* functions use CHK_DYN_MEM_NODE_NDEBUG */ +/* Globals calling_file/line deleted (see args).*/ +/* Del (x_)chk_free_wipe functions. */ +/* 08/20/01 JRB 32 Del m_pad_string_len (use m_num_pad_bytes) */ +/* 08/20/01 JRB 31 Default m_find_node_enable=FALSE (faster). */ +/* Ignore m_track_prev_free (not effective). */ +/* 08/16/01 JRB 30 Delete SAVE_CALLING_ADDRESS code for DOS. */ +/* 04/02/01 JRB 29 ALWAYS call init_mem_chk automatically (not */ +/* depending on DEBUG_SISCO or m_mem_debug). */ +/* Fix previous chg to save m_mem_debug value. */ +/* 03/27/01 GLB 28 Added MEMCHK_WIN32_CRT_DEBUG */ +/* 03/03/01 GLB 27 save m_mem_debug in m_mem_debug_saved */ +/* 02/23/01 DSF 26 m_mem_debug should not be initialized to TRUE*/ +/* 01/30/01 DSF 25 Added WIN32 Debug CRT memory checks */ +/* 04/28/00 JRB 24 Lint cleanup. */ +/* 04/19/00 JRB 23 Del SD_CONST from def_realloc_err arg. */ +/* Fix "uninitialized" warnings in chk_realloc. */ +/* 10/13/99 RKR 22 Cast file to a ST_CHAR *, fixed a prototype */ +/* 09/13/99 MDE 21 Added SD_CONST modifiers */ +/* 09/07/99 MDE 20 Minor optimization for calloc (1, x) */ +/* 04/14/99 MDE 19 Cleaned up system dependency stuff a bit */ +/* 04/14/99 MDE 18 Fixed 'chk_strdup' file/line */ +/* 03/05/98 MDE 17 Added 'chk_strdup' */ +/* 02/23/99 RKR 16 fixed the redefinition of new_mem_node */ +/* 02/15/99 DSF 15 fixed a bug in the new chk_calloc() routine -*/ +/* don't fill allocated buffer */ +/* 02/09/99 DSF 14 chk_calloc () now makes direct calls to */ +/* RTL calloc () - faster */ +/* 02/02/99 JRB 13 Add "()" in free calls in chk_free: */ +/* helps some "free" macros work. */ +/* Don't init chk_debug_en in declaration: */ +/* some compilers put it in ROM (unchangable). */ +/* Don't use obsolete MEMCHK_ERR_PRINT. */ +/* 12/08/98 MDE 12 Added 'ST_BOOLEAN m_auto_hw_log' */ +/* 10/09/98 MDE 11 Changed 'MEMLOG_CHERR' usage per new macros */ +/* 10/08/98 MDE 10 Migrated to updated SLOG interface */ +/* 09/21/98 MDE 09 Minor lint cleanup */ +/* 06/15/98 MDE 08 Changes to allow compile under C++ */ +/* 01/30/98 EJV 07 Added typecating (ST_VOID **) in list funcs. */ +/* 10/14/97 DSF 06 m_bad_ptr_val is now a pointer */ +/* 10/13/97 DSF 05 Initialize chk_debug_en = MEM_LOG_ERR */ +/* 09/16/97 DSF 04 chk_debug_en is UINT */ +/* 06/19/97 RKR 03 Changed return code from MEM_PTR_CHK_ERROR2 */ +/* 05/27/97 DSF 02 Minor bug fix */ +/* 05/20/97 RKR 01 Changed default of m_mem_debug to SD_TRUE */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "mem_chk.h" + +#define MEM_CHK /* used in mem_chk.h */ +#include "memlog.h" +#include "gen_list.h" +#include + +/* WIN32 CRT Debug used for all but MMS-EASE Lite users */ +/* MMS-EASE Lite users can define in project if desired ... */ +#if defined (_WIN32) && defined (_DEBUG) && !defined(MMS_LITE) +#ifndef MEMCHK_WIN32_CRT_DEBUG +#define MEMCHK_WIN32_CRT_DEBUG +#endif +#endif + +#if defined(MEMCHK_WIN32_CRT_DEBUG) +#include +int mem_report (int reportType, char *userMessage, int *retVal); +ST_BOOLEAN m_mem_crt_debug; +#endif + +/************************************************************************/ +/************************************************************************/ +/* These should be defined on the compiler command line */ +/* #define DEBUG */ +/* #define NO_REALLOC_SMALLER */ + +#if (((defined(MSDOS) || defined(__MSDOS__)) && !defined(_WIN32)) && !defined(_WINDOWS)) +#define MSOFT_HEAP_CHECK +#endif + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* These functions (with leading '_') are EXACTLY the same as the */ +/* "nd_chk_*" functions, but they are static so they can only be */ +/* called by the "x_chk_*" functions within this module, and */ +/* only if DEBUG_SISCO is defined. */ +/* This prevents the user from mixing debug and non-debug calling code. */ +/* If this module is compiled with DEBUG_SISCO defined, then ALL user */ +/* code must be compiled with DEBUG_SISCO defined, and the user code */ +/* will call "x_chk_*". */ +/* If this module is compiled with DEBUG_SISCO !defined, then ALL user*/ +/* code must be compiled with DEBUG_SISCO !defined, and the user code */ +/* will call "nd_chk_*". */ +/************************************************************************/ +#ifdef DEBUG_SISCO +static ST_VOID *_nd_chk_malloc (ST_UINT size); +static ST_VOID *_nd_chk_calloc (ST_UINT num, ST_UINT size); +static ST_VOID *_nd_chk_realloc (ST_VOID *ptr, ST_UINT size); +static ST_VOID _nd_chk_free (ST_VOID *del_mem_ptr); +#endif + +/************************************************************************/ +/************************************************************************/ +/* DEBUG related defines & variables (leave declared for both versions) */ + +ST_BOOLEAN m_mem_debug = SD_TRUE; +#ifdef DEBUG_SISCO +static ST_BOOLEAN m_mem_debug_saved; +#endif +ST_VOID *m_bad_ptr_val; + +/* Use 4 bytes (default) at the end of each buffer for overwrite detect */ +/* Default value used will be 0xDEADBEEF */ +ST_CHAR *m_pad_string; +ST_INT m_num_pad_bytes; + +/* Use this to fill malloc'ed and freed memory with garbage */ +ST_UCHAR m_fill_byte; +ST_BOOLEAN m_fill_en; + +/* This variable used to enable MSOFT heap check calls on every alloc */ +/* and free call. */ +ST_BOOLEAN m_heap_check_enable; + +/* This variable used to enable list validation and overwrite checking */ +/* on every alloc and free call. */ +ST_BOOLEAN m_check_list_enable; + +/* Set this variable SD_FALSE to speed up the debug version. When SD_TRUE, it */ +/* enables searching the memory list for the element before accessing */ +/* the memory during chk_realloc and chk_free calls */ +ST_BOOLEAN m_find_node_enable; + +/* This variable will cause chk_realloc to not realloc when the new */ +/* size is smaller than the old size */ +ST_BOOLEAN m_no_realloc_smaller; + +/* Dump memory table whenever high water mark is advanced */ +ST_BOOLEAN m_auto_hw_log; + +ST_BOOLEAN m_track_prev_free; /* NOT USED. Only for backward compat. */ + +/* Bit masked logging control variable */ +ST_UINT chk_debug_en; + +#ifdef DEBUG_SISCO +SD_CONST ST_CHAR *SD_CONST _mem_log_err_logstr = "MEM_LOG_ERR"; +SD_CONST ST_CHAR *SD_CONST _mem_log_calloc_logstr = "MEM_LOG_CALLOC"; +SD_CONST ST_CHAR *SD_CONST _mem_log_malloc_logstr = "MEM_LOG_MALLOC"; +SD_CONST ST_CHAR *SD_CONST _mem_log_realloc_logstr = "MEM_LOG_REALLOC"; +SD_CONST ST_CHAR *SD_CONST _mem_log_free_logstr = "MEM_LOG_FREE"; +SD_CONST ST_CHAR *SD_CONST _mem_log_nerr_logstr = "MEM_LOG_NERR"; +SD_CONST ST_CHAR *SD_CONST _mem_log_dump_logstr = "MEM_LOG_DUMP"; +LOGCFGX_VALUE_MAP memLogMaskMaps[] = + { + {"MEM_LOG_ERR", MEM_LOG_ERR, &chk_debug_en, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Error"}, + {"MEM_LOG_CALLOC", MEM_LOG_CALLOC, &chk_debug_en, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Calloc"}, + {"MEM_LOG_MALLOC", MEM_LOG_MALLOC, &chk_debug_en, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Malloc"}, + {"MEM_LOG_REALLOC", MEM_LOG_REALLOC,&chk_debug_en, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Realloc"}, + {"MEM_LOG_FREE", MEM_LOG_FREE, &chk_debug_en, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Free"} + }; + +LOGCFG_VALUE_GROUP memLogMaskMapCtrl = + { + {NULL,NULL}, + "MemLogMasks", /* Parent Tag */ + sizeof(memLogMaskMaps)/sizeof(LOGCFGX_VALUE_MAP), + memLogMaskMaps + }; + +LOGCFGX_VALUE_MAP memDebugMaps[] = + { +/* Memory debugging */ + {"MemFillEnable", 0, &m_fill_en, _LOGCFG_DATATYPE_BOOLEAN}, + {"MemHeapCheck", 0, &m_heap_check_enable, _LOGCFG_DATATYPE_BOOLEAN}, + {"MemCheckList", 0, &m_check_list_enable, _LOGCFG_DATATYPE_BOOLEAN}, + {"MemFindNode", 0, &m_find_node_enable, _LOGCFG_DATATYPE_BOOLEAN}, + {"MemNoReallocSmaller", 0, &m_no_realloc_smaller, _LOGCFG_DATATYPE_BOOLEAN}, + + /* Old names */ + {"CheckListEnable", 0, &m_check_list_enable, _LOGCFG_DATATYPE_BOOLEAN}, + {"FindNodeEnable", 0, &m_find_node_enable, _LOGCFG_DATATYPE_BOOLEAN}, + {"NoReallocSmaller", 0, &m_no_realloc_smaller, _LOGCFG_DATATYPE_BOOLEAN} + }; + +LOGCFG_VALUE_GROUP memDebugMapCtrl = + { + {NULL,NULL}, + "MemAllocDbgCtrl", /* Parent Tag */ + sizeof(memDebugMaps)/sizeof(LOGCFGX_VALUE_MAP), + memDebugMaps + }; +#endif /* DEBUG_SISCO */ + +/* Declarations for functions and array of structures used to keep track*/ +/* of allocated memory. */ +ST_UINT32 chk_curr_mem_count; +ST_UINT32 chk_max_dyn_mem_ptrs; +ST_UINT32 chk_max_mem_allocated; +ST_UINT32 chk_curr_mem_size; + +/* This function pointer can be set to select a function to be called */ +/* in case of memory error. */ +ST_VOID (*mem_chk_err)(ST_VOID); + +/************************************************************************/ +/* Internal variables */ + +/* Memory block header, used for DEBUG to track all allocated memory */ + +#if defined(DEBUG_SISCO) +typedef struct chk_dyn_mem_node + { + DBL_LNK chk_mem_node_link; + ST_INT chk_alloc_mem_size; + ST_VOID *chk_alloc_mem_ptr; + ST_CHAR *file; /* File && line that allocated the memory */ + ST_INT line; + ST_UINT16 overwrite_prev_detected; /* flag to indicate that */ + /* overwrite previously detected */ + SD_END_STRUCT + } CHK_DYN_MEM_NODE; + +static CHK_DYN_MEM_NODE *head_dyn_mem_list; + +#endif /* DEBUG_SISCO */ + +/* nd_* functions use CHK_DYN_MEM_NODE_NDEBUG. This saves overhead if */ +/* !DEBUG_SISCO or if !m_mem_debug. */ +typedef struct chk_dyn_mem_node_ndebug + { + ST_INT chk_alloc_mem_size; + SD_END_STRUCT + } CHK_DYN_MEM_NODE_NDEBUG; + +/* The 'mem_chk' tools must be initialized before being used, esp. */ +/* in DEBUG mode, or we may write or flush a NULL stream */ +static ST_INT mem_chk_initialized; + +/************************************************************************/ +/* DEBUG internal variables and functions */ +#ifdef DEBUG_SISCO + +/* padding variables */ +static ST_UINT mem_overhead; + +static ST_RET check_overwrite (CHK_DYN_MEM_NODE *ptr); +static ST_VOID set_overwrite_value (CHK_DYN_MEM_NODE *ptr); + +#endif + +/************************************************************************/ +/* Internal functions */ + +static ST_VOID *def_malloc_err (ST_UINT size); +static ST_VOID *def_calloc_err (ST_UINT num, ST_UINT size); +static ST_VOID *def_realloc_err (ST_VOID *old, ST_UINT size); +static ST_VOID mem_fat_err (ST_VOID); + +/************************************************************************/ +/************************************************************************/ +/* def_xxx_err */ +/* default fatal error service functions - just return */ +/************************************************************************/ + +static ST_VOID *def_malloc_err (ST_UINT size) + { + mem_fat_err (); + return (NULL); + } + +static ST_VOID *def_calloc_err (ST_UINT num, ST_UINT size) + { + mem_fat_err (); + return (NULL); + } + +static ST_VOID *def_realloc_err (ST_VOID *old, ST_UINT size) + { + mem_fat_err (); + return (NULL); + } + +static ST_VOID mem_fat_err () + { +#ifdef DEBUG_SISCO + + if (m_mem_debug_saved) + { + MEMLOG_ERR0 ("Fatal Memory Allocation Error"); + MEMLOG_CERR1 ("Current number of allocated buffers : %lu", + (ST_ULONG) chk_curr_mem_count); + MEMLOG_CERR1 ("Current amount of memory allocated : %lu", + (ST_ULONG) chk_curr_mem_size); + MEMLOG_CERR1 ("Maximum number of pointers allocated : %lu", + (ST_ULONG) chk_max_dyn_mem_ptrs); + MEMLOG_CERR1 ("Maximum amount of memory allocated : %lu", + (ST_ULONG) chk_max_mem_allocated); + MEMLOG_PAUSEERR (""); + + if (mem_chk_err) + (*mem_chk_err)(); + + dyn_mem_ptr_status (); + } +#endif /* no debug, do nothing. Can't printf because may be windowing. */ + + exit (255); /* the default action includes exit! */ + } + +/************************************************************************/ +/* fatal error service function pointers, used for unrecoverable errors */ + +ST_VOID *(*m_memerr_fun)(ST_UINT size); +ST_VOID *(*c_memerr_fun)(ST_UINT num, ST_UINT size); +ST_VOID *(*r_memerr_fun)(ST_VOID *ptr, ST_UINT size); + +/************************************************************************/ +/* init_mem_chk */ +/************************************************************************/ + +ST_VOID init_mem_chk () + { + + if (mem_chk_initialized) + { /* do not allow reinitialize */ + return; + } + + S_LOCK_UTIL_RESOURCES (); + +#if defined(MEMCHK_WIN32_CRT_DEBUG) + if (m_mem_crt_debug) + m_mem_debug = SD_TRUE; +#endif + +#ifdef DEBUG_SISCO + + /* Save the current value of "m_mem_debug" to control debugging. */ + /* If it is changed later, it has no impact. */ + /* This prevents crashes caused by changing allocation mode in the */ + /* middle of a program. */ + + m_mem_debug_saved = m_mem_debug; + + chk_debug_en |= MEM_LOG_ERR; + + if (m_bad_ptr_val == NULL) + m_bad_ptr_val = (ST_VOID *) -1; + if (m_pad_string == NULL) + m_pad_string = "\336\255\276\357"; /* 0xDEADBEEF */ + if (m_num_pad_bytes == 0) + m_num_pad_bytes = 4; + if (m_fill_byte == 0) + m_fill_byte = (ST_UCHAR) 0xCC; + +/* Calculate the debug memory overhead */ + mem_overhead = sizeof (CHK_DYN_MEM_NODE) + m_num_pad_bytes; + +#if defined(MEMCHK_WIN32_CRT_DEBUG) +/* hook a debug report function */ + + _CrtSetReportHook (mem_report); + + { + int tmpFlag = _CrtSetDbgFlag (_CRTDBG_REPORT_FLAG); + tmpFlag |= _CRTDBG_LEAK_CHECK_DF; + + if (m_heap_check_enable) + tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF; + +/* Set the new state for the flag */ + _CrtSetDbgFlag (tmpFlag); + } + +#endif + +#endif + + if (!m_memerr_fun) + m_memerr_fun = def_malloc_err; + if (!c_memerr_fun) + c_memerr_fun = def_calloc_err; + if (!r_memerr_fun) + r_memerr_fun = def_realloc_err; + mem_chk_initialized = SD_TRUE; + S_UNLOCK_UTIL_RESOURCES (); + } + +#if defined(MEMCHK_WIN32_CRT_DEBUG) +/************************************************************************/ +/* mem_report */ +/* Called by CRT Library to report a memory condition. */ +/************************************************************************/ + +int mem_report (int reportType, char *userMessage, int *retVal) + { +static int fileCreated = SD_FALSE; +static HANDLE hFile = INVALID_HANDLE_VALUE; +DWORD bytesWritten; + + *retVal = 0; + + if (hFile != INVALID_HANDLE_VALUE) + { + /* if file already open that means that we are called again */ + /* from the fprintf() below, */ + /* exit to prevent stack overflow in fprintf when _HEAPBADNODE err */ + return FALSE; + } + + hFile = CreateFile("MemReport.log", GENERIC_WRITE, + FILE_SHARE_WRITE, NULL, fileCreated ? OPEN_ALWAYS : CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + fileCreated = SD_TRUE; + + SetFilePointer (hFile, 0, NULL, FILE_END); + WriteFile(hFile, userMessage, strlen (userMessage), &bytesWritten, NULL); + + CloseHandle (hFile); + hFile = INVALID_HANDLE_VALUE; + + return FALSE; + } + +#endif + + +/************************************************************************/ +/* x_chk_malloc */ +/* get memory via malloc, check for error condition */ +/* if error, invoke the fatal error function via pointer */ +/************************************************************************/ + +#if defined(DEBUG_SISCO) +ST_VOID *x_chk_malloc (ST_UINT size, + SD_CONST ST_CHAR *SD_CONST calling_file, + SD_CONST ST_INT calling_line) + { +CHK_DYN_MEM_NODE *new_mem_node; + +/* Verify mem_check tools have been initialized, do it if not */ + if (!mem_chk_initialized) + init_mem_chk (); + + if (m_mem_debug_saved != m_mem_debug) + { + MEMLOG_ERR1 ("ERROR: m_mem_debug flag changed to '%d' after first allocation. Not allowed so ignored.", + m_mem_debug); + m_mem_debug = m_mem_debug_saved; /* change it back so err logged only once*/ + } + + if (m_mem_debug_saved) + { + S_LOCK_UTIL_RESOURCES (); + +/* Do linked list && overwrite checks, if enabled */ + if (m_check_list_enable) + check_mem_list (); + +/* Perform heap validation, if enabled and the system supports it */ +#if defined(DEBUG_SISCO) && defined (MSOFT_HEAP_CHECK) + if (m_heap_check_enable) + msoft_heap_check (0); /* do not print the heap! */ +#endif + +/* It is not OK to malloc a buffer of size 0 - check for this */ + if (!size) + { + MEMLOG_ERR0 ("Attempting to malloc with size == 0"); + MEMLOG_CALLSTACK (NULL); + if (mem_chk_err) + (*mem_chk_err)(); + size++; + } + +/* Allocate the buffer using the standard 'malloc' call */ + +#if defined(MEMCHK_WIN32_CRT_DEBUG) + if (m_mem_crt_debug) + new_mem_node = (CHK_DYN_MEM_NODE *) _malloc_dbg (size + mem_overhead, _NORMAL_BLOCK, + calling_file, calling_line); + else + new_mem_node = (CHK_DYN_MEM_NODE *) malloc (size + mem_overhead); +#else + new_mem_node = (CHK_DYN_MEM_NODE *) malloc (size + mem_overhead); +#endif + + if (new_mem_node == NULL) + { /* see if we can call a function to get some memory back*/ + if (!(new_mem_node = (CHK_DYN_MEM_NODE *) + (*m_memerr_fun)(size + mem_overhead))) + { + MEMLOG_ERR0 ("WARNING : Returning NULL Pointer"); + MEMLOG_CALLSTACK (NULL); + if (mem_chk_err) + (*mem_chk_err)(); + + S_UNLOCK_UTIL_RESOURCES (); + return (NULL); /* if we can't get any back we return a NULL */ + } + } + +/* Set up the memory control block header */ + new_mem_node -> chk_alloc_mem_size = size; + new_mem_node -> chk_alloc_mem_ptr = (ST_VOID *)(new_mem_node+1); + +/* Fill memory with garbage */ + if (m_fill_en) + memset (new_mem_node -> chk_alloc_mem_ptr, m_fill_byte, size); + +/* Save file and line numbers */ + new_mem_node->file = (ST_CHAR *)calling_file; + new_mem_node->line = calling_line; + +/* Set the overwrite detect value at the end of the buffer */ + set_overwrite_value (new_mem_node); + +/* Now add this element to the allocation control list */ + list_add_first ((ST_VOID **)&head_dyn_mem_list, new_mem_node); + +/* Update memory allocation statistics parameters */ + chk_curr_mem_count++; + chk_curr_mem_size += size; + if (chk_curr_mem_count > chk_max_dyn_mem_ptrs) + chk_max_dyn_mem_ptrs = chk_curr_mem_count; + if (chk_curr_mem_size > chk_max_mem_allocated) + { + chk_max_mem_allocated = chk_curr_mem_size; + if (m_auto_hw_log) + dyn_mem_ptr_status (); + } +/* log allocation info, if enabled */ + MEMLOG_MALLOC2 ("chk_malloc : size = %05u, ptr = %08lx" + ,size, (ST_VOID *)(new_mem_node+1)); + if (calling_line != -1) + { + MEMLOG_CMALLOC2 ("File : %s, Line %d",calling_file, calling_line); + } + +/* return the user pointer */ + S_UNLOCK_UTIL_RESOURCES (); + return ((ST_VOID *)(new_mem_node+1)); + } + else /* !m_mem_debug_saved */ + return (_nd_chk_malloc (size)); + } +#endif /* DEBUG_SISCO */ + +/************************************************************************/ +/* nd_chk_malloc */ +/* This function is called if (!DEBUG_SISCO) OR (!m_mem_debug_saved). */ +/************************************************************************/ +#ifdef DEBUG_SISCO /* Use "static" for DEBUG, so user can't call. */ +static ST_VOID *_nd_chk_malloc (ST_UINT size) +#else +ST_VOID *nd_chk_malloc (ST_UINT size) +#endif + { +CHK_DYN_MEM_NODE_NDEBUG *new_mem_node; + +/* Verify mem_check tools have been initialized, do it if not */ + if (!mem_chk_initialized) + init_mem_chk (); + + new_mem_node = + (CHK_DYN_MEM_NODE_NDEBUG *) malloc (size + sizeof(CHK_DYN_MEM_NODE_NDEBUG)); + if (new_mem_node == NULL) + { /* malloc failed. Try err_fun to get mem*/ + new_mem_node = (CHK_DYN_MEM_NODE_NDEBUG *) + (*m_memerr_fun)(size + sizeof(CHK_DYN_MEM_NODE_NDEBUG)); + if (!new_mem_node) + { + return (NULL); /* can't get any back, so return NULL */ + } + } + new_mem_node -> chk_alloc_mem_size = size; + return ((ST_VOID *)(new_mem_node+1)); + } + +/************************************************************************/ +/* x_chk_calloc */ +/* get memory via calloc, check for error condition */ +/* if error, invoke the fatal error function via pointer */ +/************************************************************************/ + +#if defined(DEBUG_SISCO) +ST_VOID *x_chk_calloc (ST_UINT num, + ST_UINT size, + SD_CONST ST_CHAR *SD_CONST calling_file, + SD_CONST ST_INT calling_line) + { +CHK_DYN_MEM_NODE *new_mem_node; +ST_INT buf_size; + +/* Verify mem_check tools have been initialized, do it if not */ + if (!mem_chk_initialized) + init_mem_chk (); + + if (m_mem_debug_saved) + { + S_LOCK_UTIL_RESOURCES (); + +/* Do linked list && overwrite checks, if enabled */ + if (m_check_list_enable) + check_mem_list (); + +/* It is not OK to calloc a buffer of size 0 - check for this */ + if (!size) + { + MEMLOG_ERR0 ("Attempting to calloc with size == 0"); + MEMLOG_CALLSTACK (NULL); + if (mem_chk_err) + (*mem_chk_err)(); + size++; + } + if (!num) + { + MEMLOG_ERR0 ("Attempting to calloc with num == 0"); + MEMLOG_CALLSTACK (NULL); + if (mem_chk_err) + (*mem_chk_err)(); + num++; + } + +/* Calculate the size required ... Save a multiply? */ + if (num == 1) + buf_size = size; + else if (size == 1) + buf_size = num; + else + buf_size = num * size; + +/* get the buffer */ +#if defined(MEMCHK_WIN32_CRT_DEBUG) + if (m_mem_crt_debug) + new_mem_node = (CHK_DYN_MEM_NODE *) _calloc_dbg (1, buf_size + mem_overhead, _NORMAL_BLOCK, + calling_file, calling_line); + else + new_mem_node = (CHK_DYN_MEM_NODE *) calloc (1, buf_size + mem_overhead); +#else + new_mem_node = (CHK_DYN_MEM_NODE *) calloc (1, buf_size + mem_overhead); +#endif + +/* verify NULL not returned */ + if (!new_mem_node) + { + MEMLOG_ERR0 ("WARNING : Returning NULL Pointer"); + MEMLOG_CERR5 ("Parameters: num:%d size: %d file:%s line:%d %s", + num, size, calling_file, calling_line, ""); + MEMLOG_CALLSTACK (NULL); + if (mem_chk_err) + (*mem_chk_err)(); + S_UNLOCK_UTIL_RESOURCES (); + return (NULL); + } + +/* Set up the memory control block header */ + new_mem_node -> chk_alloc_mem_size = buf_size; + new_mem_node -> chk_alloc_mem_ptr = (ST_VOID *)(new_mem_node+1); + +/* Save file and line numbers */ + new_mem_node->file = (ST_CHAR *)calling_file; + new_mem_node->line = calling_line; + +/* Set the overwrite detect value at the end of the buffer */ + set_overwrite_value (new_mem_node); + +/* Now add this element to the allocation control list */ + list_add_first ((ST_VOID **)&head_dyn_mem_list, new_mem_node); + +/* Update memory allocation statistics parameters */ + chk_curr_mem_count++; + chk_curr_mem_size += buf_size; + if (chk_curr_mem_count > chk_max_dyn_mem_ptrs) + chk_max_dyn_mem_ptrs = chk_curr_mem_count; + if (chk_curr_mem_size > chk_max_mem_allocated) + { + chk_max_mem_allocated = chk_curr_mem_size; + if (m_auto_hw_log) + dyn_mem_ptr_status (); + } + +/* log allocation info, if enabled */ + MEMLOG_CALLOC3 ("chk_calloc : num = %05u, size = %05u Ptr = %08lx",num,size,new_mem_node+1); + if (calling_line != -1) + { + MEMLOG_CCALLOC2 ("File : %s, Line %d",calling_file, calling_line); + } + +/* return the user pointer */ + S_UNLOCK_UTIL_RESOURCES (); + return ((ST_VOID *)(new_mem_node+1)); + } + else /* !m_mem_debug_saved */ + return (_nd_chk_calloc (num, size)); + } +#endif /* DEBUG_SISCO */ + +/************************************************************************/ +/* nd_chk_calloc */ +/* This function is called if (!DEBUG_SISCO) OR (!m_mem_debug_saved). */ +/************************************************************************/ +#ifdef DEBUG_SISCO /* Use "static" for DEBUG, so user can't call. */ +static ST_VOID *_nd_chk_calloc (ST_UINT num, ST_UINT size) +#else +ST_VOID *nd_chk_calloc (ST_UINT num, ST_UINT size) +#endif + { +CHK_DYN_MEM_NODE_NDEBUG *new_mem_node; +ST_INT buf_size; + +/* Verify mem_check tools have been initialized, do it if not */ + if (!mem_chk_initialized) + init_mem_chk (); + + buf_size = num * size; /* chk_malloc adds overhead */ + new_mem_node = + (CHK_DYN_MEM_NODE_NDEBUG *) calloc (1, buf_size + sizeof(CHK_DYN_MEM_NODE_NDEBUG)); + if (new_mem_node == NULL) + { /* calloc failed. Try err_fun to get mem*/ + new_mem_node = (CHK_DYN_MEM_NODE_NDEBUG *) + (*c_memerr_fun)(1, buf_size + sizeof(CHK_DYN_MEM_NODE_NDEBUG)); + if (!new_mem_node) + { + return (NULL); /* can't get any back, so return NULL */ + } + } + new_mem_node -> chk_alloc_mem_size = buf_size; + return ((ST_VOID *)(new_mem_node+1)); + } + +/************************************************************************/ +/* x_chk_realloc */ +/* get memory via calloc, check for error condition */ +/* if error, invoke the fatal error function via pointer */ +/************************************************************************/ + +#if defined(DEBUG_SISCO) +ST_VOID *x_chk_realloc (ST_VOID *ptr, + ST_UINT size, + SD_CONST ST_CHAR *SD_CONST calling_file, + SD_CONST ST_INT calling_line) + { +CHK_DYN_MEM_NODE *old_mem_node, *new_mem_node; +ST_VOID *old_mem_ptr; +ST_UINT old_mem_size; +ST_BOOLEAN no_realloc; + +/* Verify mem_check tools have been initialized, do it if not */ + if (!mem_chk_initialized) + init_mem_chk (); + + if (m_mem_debug_saved) + { + S_LOCK_UTIL_RESOURCES (); +/* Do linked list && overwrite checks, if enabled */ + if (m_check_list_enable) + check_mem_list (); + +/* Perform heap validation, if enabled and the system supports it */ +#if defined(DEBUG_SISCO) && defined (MSOFT_HEAP_CHECK) + if (m_heap_check_enable) + msoft_heap_check (0); /* do not print the heap! */ +#endif + +/* It is not OK to pass in a NULL pointer, check for this */ + if (!ptr) + { + MEMLOG_ERR2 ("File : %s, Line %d", + calling_file, calling_line); + MEMLOG_CERR0 ("Attempting to realloc NULL pointer"); + MEMLOG_CALLSTACK (NULL); + MEMLOG_PAUSEERR (""); + if (mem_chk_err) + (*mem_chk_err)(); + S_UNLOCK_UTIL_RESOURCES (); + return (NULL); + } + +/* It is not OK to re-alloc a buffer of size 0 - check for this */ + if (!size) + { + MEMLOG_ERR0 ( "Attempting to realloc with size = 0"); + MEMLOG_CALLSTACK (NULL); + if (mem_chk_err) + (*mem_chk_err)(); + size++; + } + +/* Get the pointer to the control information */ + old_mem_node = ((CHK_DYN_MEM_NODE *)ptr)-1; + +/* Verify that this node is on the list before accessing it */ + if (m_find_node_enable == SD_TRUE) + { + if (list_find_node (head_dyn_mem_list, old_mem_node) != SD_SUCCESS) + { + goto MEM_REALLOC_ERROR; + } + } + +/* extract information from memory block header */ + old_mem_ptr = old_mem_node -> chk_alloc_mem_ptr; + old_mem_size = old_mem_node -> chk_alloc_mem_size; + + if (old_mem_ptr != ptr) /* verify that the ptr passed in matches */ + { +MEM_REALLOC_ERROR : + MEMLOG_ERR2 ("\n File : %s, Line %d", + calling_file, calling_line); + MEMLOG_CERR1 ( + "Invalid realloc (%08lx)",ptr); + + MEMLOG_CALLSTACK (NULL); + MEMLOG_PAUSEERR (""); + if (mem_chk_err) + (*mem_chk_err)(); + S_UNLOCK_UTIL_RESOURCES (); + return (ptr); /* just hope realloc was for smaller */ + } + +/* Update memory allocation statistics parameters */ + chk_curr_mem_count--; /* update the node count*/ + chk_curr_mem_size -= old_mem_size; /* update the mem size */ + + +/* Check for 'no realloc smaller' option */ +/* This is controlled either by compile time define or by variable */ +/* If new size is less than old size, just don't use the system realloc */ + + no_realloc = SD_FALSE; + +#if defined(NO_REALLOC_SMALLER) + if (size <= (ST_UINT) old_mem_node -> chk_alloc_mem_size) + { + no_realloc = SD_TRUE; + } +#else + if (m_no_realloc_smaller) + { + if (size <= (ST_UINT) old_mem_node -> chk_alloc_mem_size) + { + no_realloc = SD_TRUE; + } + } +#endif + + if (no_realloc) + new_mem_node = old_mem_node; /* Use original buffer. */ + else + { +/* invalidate the old block */ + old_mem_node->chk_alloc_mem_ptr = NULL; + +/* remove the old memory block from the mem_chk system */ + list_unlink ((ST_VOID **)&head_dyn_mem_list, old_mem_node); /* unlink the old node */ + +/* Use the system realloc to get the new pointer */ +#if defined(MEMCHK_WIN32_CRT_DEBUG) + if (m_mem_crt_debug) + new_mem_node = (CHK_DYN_MEM_NODE *) + _realloc_dbg ((ST_VOID *) old_mem_node, size + mem_overhead, _NORMAL_BLOCK, + calling_file, calling_line); + else + new_mem_node = (CHK_DYN_MEM_NODE *) + realloc ((ST_VOID *) old_mem_node, size + mem_overhead); +#else + new_mem_node = (CHK_DYN_MEM_NODE *) + realloc ((ST_VOID *) old_mem_node, size + mem_overhead); +#endif + + if (new_mem_node == NULL) + { + if (!(new_mem_node = (CHK_DYN_MEM_NODE *) + (*r_memerr_fun)((ST_VOID *) old_mem_node, + size + mem_overhead))) + { + MEMLOG_ERR0 ("WARNING : Returning NULL Pointer"); + MEMLOG_CALLSTACK (NULL); + if (mem_chk_err) + (*mem_chk_err)(); + S_UNLOCK_UTIL_RESOURCES (); + return( NULL ); /* if we can't get any back we return a NULL */ + } + } + +/* Now add this element to the allocation control list */ + list_add_first ((ST_VOID **)&head_dyn_mem_list, new_mem_node); + } + +/* Now we have a new memory block, initialize the mem_chk header and */ +/* put on the active list */ + new_mem_node -> chk_alloc_mem_size = size;/* update the header */ + new_mem_node -> chk_alloc_mem_ptr = (ST_VOID *)(new_mem_node+1); + + new_mem_node->file = (ST_CHAR *)calling_file; + new_mem_node->line = calling_line; + +/* Initialize the overwrite value */ + set_overwrite_value (new_mem_node); + +/* Update memory allocation statistics parameters */ + chk_curr_mem_size += size; /* add the new size */ + chk_curr_mem_count++; /* update the node count*/ + if (chk_curr_mem_size > chk_max_mem_allocated) + { + chk_max_mem_allocated = chk_curr_mem_size; + if (m_auto_hw_log) + dyn_mem_ptr_status (); + } +/* log allocation info, if enabled */ + MEMLOG_REALLOC3 ("chk_realloc : ptr = %08lx, size = %05u, ptr = %08lx", + ptr,size, (ST_VOID *)(new_mem_node+1)); + if (calling_line != -1) + { + MEMLOG_CREALLOC2 ("File : %s. Line %d", + calling_file, + calling_line); + } + S_UNLOCK_UTIL_RESOURCES (); + return ((ST_VOID *)(new_mem_node+1)); + } + else /* !m_mem_debug_saved */ + return (_nd_chk_realloc (ptr, size)); + } +#endif /* DEBUG_SISCO */ + +/************************************************************************/ +/* nd_chk_realloc */ +/* This function is called if (!DEBUG_SISCO) OR (!m_mem_debug_saved). */ +/************************************************************************/ +#ifdef DEBUG_SISCO /* Use "static" for DEBUG, so user can't call. */ +static ST_VOID *_nd_chk_realloc (ST_VOID *ptr, ST_UINT size) +#else +ST_VOID *nd_chk_realloc (ST_VOID *ptr, ST_UINT size) +#endif + { +CHK_DYN_MEM_NODE_NDEBUG *old_mem_node; +CHK_DYN_MEM_NODE_NDEBUG *new_mem_node; +ST_BOOLEAN no_realloc; + +/* Verify mem_check tools have been initialized, do it if not */ + if (!mem_chk_initialized) + init_mem_chk (); + +/* Get the pointer to the control information */ + old_mem_node = ((CHK_DYN_MEM_NODE_NDEBUG *)ptr)-1; + +/* Check for 'no realloc smaller' option */ +/* This is controlled either by compile time define or by variable */ +/* If new size is less than old size, just don't use the system realloc */ + + no_realloc = SD_FALSE; + +#if defined(NO_REALLOC_SMALLER) + if (size <= (ST_UINT) old_mem_node -> chk_alloc_mem_size) + { + no_realloc = SD_TRUE; + } +#else + if (m_no_realloc_smaller) + { + if (size <= (ST_UINT) old_mem_node -> chk_alloc_mem_size) + { + no_realloc = SD_TRUE; + } + } +#endif + + if (no_realloc) + new_mem_node = old_mem_node; /* Use original buffer. */ + else + { +/* Use the system realloc to get the new pointer */ + if ((new_mem_node = (CHK_DYN_MEM_NODE_NDEBUG *) + realloc ((ST_VOID *) old_mem_node, + size + sizeof (CHK_DYN_MEM_NODE_NDEBUG))) == NULL) + { + if (!(new_mem_node = + (CHK_DYN_MEM_NODE_NDEBUG *) (*r_memerr_fun)((ST_VOID *) old_mem_node, + size + sizeof (CHK_DYN_MEM_NODE_NDEBUG)))) + { + return( NULL ); /* if we can't get any back we return a NULL */ + } + } + } + + new_mem_node -> chk_alloc_mem_size = size; /* update the header */ + return ((ST_VOID *)(new_mem_node+1)); + } + +/************************************************************************/ +/* x_chk_free */ +/************************************************************************/ + +#if defined(DEBUG_SISCO) +ST_VOID x_chk_free (ST_VOID *del_mem_ptr, + SD_CONST ST_CHAR *SD_CONST calling_file, + SD_CONST ST_INT calling_line) + { +CHK_DYN_MEM_NODE *chk_mem_node; + +/* Verify mem_check tools have been initialized, do it if not */ + if (!mem_chk_initialized) + init_mem_chk (); + + if (m_mem_debug_saved) + { + S_LOCK_UTIL_RESOURCES (); + +/* Do linked list && overwrite checks, if enabled */ + if (m_check_list_enable) + check_mem_list (); /* check linked list. Works for all systems. */ + +/* Perform heap validation, if enabled and the system supports it */ +#if defined(DEBUG_SISCO) && defined (MSOFT_HEAP_CHECK) + if (m_heap_check_enable) + msoft_heap_check (0); /* do not print the heap! */ +#endif + +/* log allocation info, if enabled */ + MEMLOG_FREE1 ("chk_free : ptr = %08lx",del_mem_ptr); + + if (calling_line != -1) + { + MEMLOG_CFREE2 ("File : %s. Line %d", + calling_file, + calling_line); + } + +/* verify that a non-NULL pointer was passed in */ + if (!del_mem_ptr) + { + goto MEM_FREE_ERROR; + } + +/* Get the pointer to the control information */ + chk_mem_node = ((CHK_DYN_MEM_NODE *)del_mem_ptr)-1; + +/* Verify that this node is on the list before accessing it */ + if (m_find_node_enable == SD_TRUE) + { + if (list_find_node (head_dyn_mem_list, chk_mem_node) != SD_SUCCESS) + { + goto MEM_FREE_ERROR; + } + } + +/* verify that the pointer matches the expected pointer */ + if (chk_mem_node->chk_alloc_mem_ptr == del_mem_ptr) + { + if (check_overwrite (chk_mem_node)) + { + MEMLOG_ERR0 ("Memory overwrite at end of buffer detected"); + MEMLOG_CERR5 ( + "Node = %lx, Prev = %lx, Next = %lx, Len = %u, Curr = %lx", + chk_mem_node, + chk_mem_node->chk_mem_node_link.prev, + chk_mem_node->chk_mem_node_link.next, + chk_mem_node->chk_alloc_mem_size, + chk_mem_node->chk_alloc_mem_ptr); + MEMLOG_CHERR (chk_mem_node->chk_alloc_mem_size + + sizeof (CHK_DYN_MEM_NODE) + + m_num_pad_bytes, chk_mem_node); + +/* Take care of this memory block */ + chk_mem_node->chk_alloc_mem_ptr = NULL; /* invalidate the block */ + chk_curr_mem_size -= chk_mem_node -> chk_alloc_mem_size; + chk_curr_mem_count--; + list_unlink ((ST_VOID **)&head_dyn_mem_list, chk_mem_node); + + MEMLOG_CERR2 ("Pointer was allocated at file: %s, line %d ", + chk_mem_node->file,chk_mem_node->line); + goto MEM_FREE_ERROR2; /* print the call stack */ + } + else /* This is a good free, do it! */ + { + chk_mem_node->chk_alloc_mem_ptr = NULL; /* invalidate the block */ + chk_curr_mem_size -= chk_mem_node -> chk_alloc_mem_size; + chk_curr_mem_count--; + list_unlink ((ST_VOID **)&head_dyn_mem_list, chk_mem_node); + +/* Fill memory with garbage before freeing it */ +#ifdef MEM_FILL_CONTROL + if (m_fill_en) + memset (chk_mem_node, m_fill_byte, + chk_mem_node->chk_alloc_mem_size + + sizeof (CHK_DYN_MEM_NODE)); +#else + if (m_fill_en) + memset ((ST_CHAR *) chk_mem_node + sizeof (CHK_DYN_MEM_NODE), + m_fill_byte, + chk_mem_node->chk_alloc_mem_size); +#endif + +#if defined(MEMCHK_WIN32_CRT_DEBUG) + if (m_mem_crt_debug) + _free_dbg ((ST_VOID *)chk_mem_node, _NORMAL_BLOCK); + else + free ((ST_VOID *)chk_mem_node); +#else + free ((ST_VOID *)chk_mem_node); +#endif + } + } /* end if pointer matched expected */ + else /* Whoops, free error */ + { + if (chk_debug_en & MEM_LOG_ERR) + { +MEM_FREE_ERROR : + + MEMLOG_ERR1 ( + "Invalid Free (%08lx)",del_mem_ptr); + +MEM_FREE_ERROR2 : + MEMLOG_CERR2 ("Free call made from file : %s, Line %d ", + calling_file, + calling_line); + } + MEMLOG_CALLSTACK (NULL); + MEMLOG_PAUSEERR (""); + if (mem_chk_err) + (*mem_chk_err)(); + } + +/* Do linked list && overwrite checks, if enabled */ + if (m_check_list_enable) + check_mem_list (); /* check linked list. Works for all systems. */ + +/* Perform heap validation, if enabled and the system supports it */ +#if defined(DEBUG_SISCO) && defined (MSOFT_HEAP_CHECK) + if (m_heap_check_enable) + msoft_heap_check (0); /* do not print the heap! */ +#endif + S_UNLOCK_UTIL_RESOURCES (); + } + else /* !m_mem_debug_saved */ + _nd_chk_free (del_mem_ptr); + } +#endif /* DEBUG_SISCO */ + + +/************************************************************************/ +/* nd_chk_free */ +/* This function is called if (!DEBUG_SISCO) OR (!m_mem_debug_saved). */ +/************************************************************************/ +#ifdef DEBUG_SISCO /* Use "static" for DEBUG, so user can't call. */ +static ST_VOID _nd_chk_free (ST_VOID *del_mem_ptr) +#else +ST_VOID nd_chk_free (ST_VOID *del_mem_ptr) +#endif + { +/* Verify mem_check tools have been initialized, do it if not */ + if (!mem_chk_initialized) + init_mem_chk (); + + /* Extra () helps some "free" macros work. */ + free ((((CHK_DYN_MEM_NODE_NDEBUG *)del_mem_ptr)-1)); + } + +#if defined(DEBUG_SISCO) +/************************************************************************/ +/* x_chk_strdup */ +/************************************************************************/ + +ST_CHAR *x_chk_strdup (ST_CHAR *str, + SD_CONST ST_CHAR *SD_CONST file, + SD_CONST ST_INT line) + { +ST_CHAR *new_str; + + new_str = (ST_CHAR *) x_chk_malloc (strlen (str) + 1, file, line); + strcpy (new_str, str); + return (new_str); + } + +#else /* !DEBUG_SISCO */ +/************************************************************************/ +/* nd_chk_strdup */ +/************************************************************************/ + +ST_CHAR *nd_chk_strdup (ST_CHAR *str) + { +ST_CHAR *new_str; + + new_str = (ST_CHAR *) nd_chk_malloc (strlen (str) + 1); + strcpy (new_str, str); + return (new_str); + } +#endif /* !DEBUG_SISCO */ + +/***************************************************************************/ +/***************************************************************************/ +/* dyn_mem_ptr_status */ +/***************************************************************************/ + +ST_VOID dyn_mem_ptr_status () + { +#ifdef DEBUG_SISCO + dyn_mem_ptr_status2 (NULL); +#endif + } + +/***************************************************************************/ +/* dyn_mem_ptr_status2 */ +/* This function will log all nodes up to marker_ptr node and return */ +/* count of logged nodes. If market_ptr is NULL the function will log all */ +/* memory nodes. */ +/***************************************************************************/ + +ST_UINT dyn_mem_ptr_status2 (ST_VOID *marker_ptr) + { + ST_UINT logged_count = 0; +#ifdef DEBUG_SISCO + CHK_DYN_MEM_NODE *chk_mem_node; + ST_UINT32 count = 1; + ST_INT line = 1; + + if (m_mem_debug_saved) + { + S_LOCK_UTIL_RESOURCES (); + chk_mem_node = head_dyn_mem_list; + MEMLOG_LF (); + if (marker_ptr) + { + MEMLOG_DUMP0 ("DYNAMIC MEMORY POINTER TABLE ABOVE MARKER\n" + "----------------------------------------- "); + } + else + { + MEMLOG_DUMP0 ("DYNAMIC MEMORY POINTER TABLE\n" + "---------------------------- "); + } + while (count <= chk_curr_mem_count) + { + if (chk_mem_node == NULL) + { + MEMLOG_CDUMP0 ("Dump halted due to NULL pointer. Table corrupted."); + break; /* Break out of loop. */ + } + if (marker_ptr && chk_mem_node->chk_alloc_mem_ptr == marker_ptr) + break; + ++logged_count; +#if defined(MEMCHK_WIN32_CRT_DEBUG) + { + int req_num = -1; + _CrtIsMemoryBlock(chk_mem_node, + chk_mem_node->chk_alloc_mem_size + mem_overhead, + &req_num, NULL, NULL); + MEMLOG_CDUMP5 ("Ptr %08lx Size % 5u File : %-12s #%04d {%04d}", + chk_mem_node -> chk_alloc_mem_ptr, + chk_mem_node -> chk_alloc_mem_size, + chk_mem_node->file, + chk_mem_node->line, + req_num); + } +#else + MEMLOG_CDUMP4 ("Ptr %08lx Size % 5u File : %-12s #%04d", + chk_mem_node -> chk_alloc_mem_ptr, + chk_mem_node -> chk_alloc_mem_size, + chk_mem_node->file, + chk_mem_node->line); +#endif + + chk_mem_node = (CHK_DYN_MEM_NODE *) + chk_mem_node -> chk_mem_node_link.next; + count++; + + line++; + if (line > 10) + { + MEMLOG_PAUSE ("---- More Follows Press any key ----"); + line = 1; + } + } + MEMLOG_CDUMP0 ("---- END OF MEMORY POINTER TABLE ----------"); + + MEMLOG_CDUMP1 ("Total number of allocated pointers: %lu", + (ST_ULONG) chk_curr_mem_count); + MEMLOG_CDUMP1 ("Total amount of memory allocated: %lu bytes ", + (ST_ULONG) chk_curr_mem_size); + MEMLOG_CDUMP1 ("Maximum number of pointers allocated: %lu", + (ST_ULONG) chk_max_dyn_mem_ptrs); + MEMLOG_CDUMP1 ("Maximum amount of memory allocated: %lu bytes", + (ST_ULONG) chk_max_mem_allocated); + MEMLOG_PAUSE (""); + S_UNLOCK_UTIL_RESOURCES (); + } +#endif /* end of DEBUG_SISCO */ + return (logged_count); + } + +/***************************************************************************/ +/* dyn_mem_ptr_statistics */ +/***************************************************************************/ + +ST_VOID dyn_mem_ptr_statistics (ST_BOOLEAN log_to_screen) + { +#ifdef DEBUG_SISCO + CHK_DYN_MEM_NODE *chk_mem_node; + ST_UINT32 count = 1; + + if (m_mem_debug_saved) + { + S_LOCK_UTIL_RESOURCES (); + chk_mem_node = head_dyn_mem_list; + if ( log_to_screen == SD_TRUE ) + { +#ifndef _WINDOWS + printf("\nDYNAMIC MEMORY POINTER TABLE "); + printf("\n----------------------------- "); +#endif + } + else + { + MEMLOG_LF (); + MEMLOG_DUMP0 ("DYNAMIC MEMORY POINTER TABLE "); + MEMLOG_CDUMP0 ("----------------------------- "); + } + while (count <= chk_curr_mem_count) + { + chk_mem_node = (CHK_DYN_MEM_NODE *) + chk_mem_node -> chk_mem_node_link.next; + count++; + } + + if ( log_to_screen == SD_TRUE ) + { +#if !defined(_WINDOWS) || defined(_WIN32) + printf ("\nTotal number of allocated pointers: %lu", + (ST_ULONG) chk_curr_mem_count); + printf ("\nTotal amount of memory allocated: %lu bytes ", + (ST_ULONG) chk_curr_mem_size); + printf ("\nMaximum number of pointers allocated: %lu", + (ST_ULONG) chk_max_dyn_mem_ptrs); + printf ("\nMaximum amount of memory allocated: %lu bytes", + (ST_ULONG) chk_max_mem_allocated); +#endif + } + else + { + MEMLOG_CDUMP1 ("Total number of allocated pointers: %lu", + (ST_ULONG) chk_curr_mem_count); + MEMLOG_CDUMP1 ("Total amount of memory allocated: %lu bytes ", + (ST_ULONG) chk_curr_mem_size); + MEMLOG_CDUMP1 ("Maximum number of pointers allocated: %lu", + (ST_ULONG) chk_max_dyn_mem_ptrs); + MEMLOG_CDUMP1 ("Maximum amount of memory allocated: %lu bytes", + (ST_ULONG) chk_max_mem_allocated); + MEMLOG_PAUSE (""); + } + S_UNLOCK_UTIL_RESOURCES (); + return; + } +#endif /* end of DEBUG_SISCO */ + } + +/************************************************************************/ +/************************************************************************/ +/* chk_hp */ +/* Perform system specific heap validation */ +/************************************************************************/ + +ST_RET chk_hp (ST_INT16 prt_mask, ST_CHAR *file, ST_INT line) + { +ST_RET ret; + + ret = SD_SUCCESS; + +#if defined(DEBUG_SISCO) && defined (MSOFT_HEAP_CHECK) + S_LOCK_UTIL_RESOURCES (); + if (ret = msoft_heap_check (prt_mask)) + { + MEMLOG_ERR2 ("\nFILE : %s, LINE %d",file,line); + if (mem_chk_err) + (*mem_chk_err)(); + } + S_UNLOCK_UTIL_RESOURCES (); +#endif + + return (ret); + } + +/************************************************************************/ +/* msoft_heap_check */ +/* Perform Microsoft specific heap validation */ +/* Also sets all unused heap to 0x55 */ +/************************************************************************/ + +ST_RET msoft_heap_check (ST_INT16 prt_mask) + { +#if defined(DEBUG_SISCO) && defined (MSOFT_HEAP_CHECK) +struct _heapinfo entry; +ST_INT i; +ST_INT ret; +ST_BOOLEAN error; +ST_INT32 total_size; +ST_INT num_ptrs; + + S_LOCK_UTIL_RESOURCES (); + entry._pentry = NULL; /* start at the top of the list */ + error = SD_FALSE; + total_size = 0; + num_ptrs = 0; + for (i = 0; SD_TRUE; ++i) + { + ret = _heapwalk (&entry); + switch (ret) + { + case _HEAPBADPTR : + MEMLOG_ERR0 ("BAD HEAP : POINTER OUTSIDE HEAP"); + error = SD_TRUE; + break; + case _HEAPBADBEGIN : + MEMLOG_ERR0 ("BAD HEAP : INITIAL ENTRY"); + error = SD_TRUE; + break; + case _HEAPBADNODE : + MEMLOG_ERR0 ("BAD HEAP : BAD NODE "); + error = SD_TRUE; + break; + } + + if (prt_mask & DEBUG_HEAP_ENTRY) + { + if (ret == _HEAPEMPTY) + { + MEMLOG_DUMP0 ("Heap Empty"); + } + else if (ret == _HEAPEND) + { + MEMLOG_DUMP0 ("End Of Heap"); + } + else + { + MEMLOG_CDUMP1 (" Heap Entry %d :",i); + MEMLOG_CDUMP1 (" Pointer : %08lX",entry._pentry); + MEMLOG_CDUMP1 (" Size (decimal) : %d",entry._size); + MEMLOG_CDUMP1 (" Use Flag : %s", + entry._useflag == _USEDENTRY ? "USED" : "FREE"); + num_ptrs++; + total_size += entry._size; + } + + MEMLOG_PAUSE ("Hit any key to continue - "); + } + + if (ret == _HEAPEND || ret == _HEAPEMPTY || error) + break; + } + + if (prt_mask & DEBUG_HEAP_SUM) + { + MEMLOG_DUMP1 ("Total # Pointers : %d",num_ptrs); + MEMLOG_CDUMP1 ("Total memory malloc'd : %ld",total_size); + MEMLOG_PAUSE ("Hit any key to continue - "); + } + + _heapset ('\x55'); /* write all unused memory with 55's */ + + S_UNLOCK_UTIL_RESOURCES (); + return (SD_FALSE); +#elif defined(DEBUG_SISCO) && defined(MEMCHK_WIN32_CRT_DEBUG) + return _CrtCheckMemory () ? SD_FALSE : SD_TRUE; +#else + return (SD_FALSE); +#endif + } + + + +/************************************************************************/ +/************************************************************************/ +/* chk_alloc_ptr */ +/************************************************************************/ + +ST_RET chk_alloc_ptr (ST_VOID *mem_ptr) + { +#ifdef DEBUG_SISCO +CHK_DYN_MEM_NODE *chk_mem_node; + + if (m_mem_debug_saved) + { + S_LOCK_UTIL_RESOURCES (); +/* verify that a non-NULL pointer was passed in */ + if (!mem_ptr) + { + if (chk_debug_en & MEM_LOG_ERR) + { + MEMLOG_ERR0 ("NULL pointer in chk_alloc_ptr"); + goto MEM_PTR_CHK_ERROR; + } + S_UNLOCK_UTIL_RESOURCES (); + return(SD_FAILURE); + } + +/* verify that the pointer matches the expected pointer */ + chk_mem_node = ((CHK_DYN_MEM_NODE *)mem_ptr)-1; + +/* Verify that this node is on the list before accessing it */ + if (list_find_node (head_dyn_mem_list, chk_mem_node) != SD_SUCCESS) + { + if (chk_debug_en & MEM_LOG_ERR) + { + MEMLOG_ERR0 (" chk_alloc_ptr - pointer not on list"); + goto MEM_PTR_CHK_ERROR; + } + S_UNLOCK_UTIL_RESOURCES (); + return(SD_FAILURE); + } + + if (chk_mem_node->chk_alloc_mem_ptr == mem_ptr) + { + if (chk_mem_node->overwrite_prev_detected == SD_FALSE) + { + if (check_overwrite (chk_mem_node)) + { + MEMLOG_ERR0 ("Memory overwrite at end of buffer detected"); + chk_mem_node->overwrite_prev_detected=SD_TRUE; + MEMLOG_CERR5 ( + "Node = %lx, Prev = %lx, Next = %lx, Len = %u, Curr = %lx", + chk_mem_node, + chk_mem_node->chk_mem_node_link.prev, + chk_mem_node->chk_mem_node_link.next, + chk_mem_node->chk_alloc_mem_size, + chk_mem_node->chk_alloc_mem_ptr); + MEMLOG_CERR2 ("Pointer was allocated at file: %s, line %d ", + chk_mem_node->file,chk_mem_node->line); + MEMLOG_CHERR (chk_mem_node->chk_alloc_mem_size + + sizeof (CHK_DYN_MEM_NODE) + + m_num_pad_bytes, chk_mem_node); + goto MEM_PTR_CHK_ERROR2; + } + } /* end if overwrite not detected for this node */ + +#if defined(MEMCHK_WIN32_CRT_DEBUG) + if (_CrtIsMemoryBlock (chk_mem_node, chk_mem_node->chk_alloc_mem_size + mem_overhead, + NULL, NULL, NULL) == FALSE) + { + MEMLOG_ERR0 ("Buffer not a valid memory block"); + MEMLOG_CERR5 ( + "Node = %lx, Prev = %lx, Next = %lx, Len = %u, Curr = %lx", + chk_mem_node, + chk_mem_node->chk_mem_node_link.prev, + chk_mem_node->chk_mem_node_link.next, + chk_mem_node->chk_alloc_mem_size, + chk_mem_node->chk_alloc_mem_ptr); + MEMLOG_CERR2 ("Pointer was allocated at file: %s, line %d ", + chk_mem_node->file,chk_mem_node->line); + MEMLOG_CHERR (chk_mem_node->chk_alloc_mem_size + + sizeof (CHK_DYN_MEM_NODE) + + m_num_pad_bytes, chk_mem_node); + goto MEM_PTR_CHK_ERROR2; + } +#endif + } + else /* Pointer does not match header */ + { +MEM_PTR_CHK_ERROR : + + MEMLOG_ERR1 ("Pointer Does Not Exist (%08lx)",mem_ptr); + +MEM_PTR_CHK_ERROR2 : + MEMLOG_CALLSTACK (NULL); + MEMLOG_PAUSEERR (""); + if (mem_chk_err) + (*mem_chk_err)(); + S_UNLOCK_UTIL_RESOURCES (); + return(SD_FAILURE); + } + S_UNLOCK_UTIL_RESOURCES (); + } +#endif + return(SD_SUCCESS); + } + + +/************************************************************************/ +/* check_mem_list */ +/************************************************************************/ + +ST_VOID check_mem_list () + { +#ifdef DEBUG_SISCO +CHK_DYN_MEM_NODE *node; +CHK_DYN_MEM_NODE *prev; +CHK_DYN_MEM_NODE *next; +ST_INT len; +ST_VOID *curr; +ST_UINT32 j; + + if (m_mem_debug_saved) + { + S_LOCK_UTIL_RESOURCES (); + if ((node = head_dyn_mem_list) == NULL) + { + S_UNLOCK_UTIL_RESOURCES (); + return; /* list empty. Nothing to check */ + } + for (j = 0; j < chk_max_dyn_mem_ptrs; j++) + { + /* should break out when j = chk_curr_mem_count */ + prev = (CHK_DYN_MEM_NODE *) node->chk_mem_node_link.prev; + next = (CHK_DYN_MEM_NODE *) node->chk_mem_node_link.next; + len = node->chk_alloc_mem_size; + curr = node->chk_alloc_mem_ptr; + + /* check ptr to this node */ + if (curr != (ST_VOID *) (node + 1)) + { + MEMLOG_ERR1 ("Current node pointer corrupted on node #%d", j); + MEMLOG_CERR5 ( + "Node = %lx, Prev = %lx, Next = %lx, Len = %u, Curr = %lx", + node, prev, next, len, curr); + MEMLOG_CALLSTACK (NULL); + MEMLOG_PAUSEERR (""); + if (mem_chk_err) + (*mem_chk_err)(); + } + + /* check link list ptrs */ + if (node != (CHK_DYN_MEM_NODE *) next->chk_mem_node_link.prev) + { + MEMLOG_ERR1 ("\nLinked list corrupted at node #%d", j); + MEMLOG_CERR6 ( + "Node=%lx, Prev=%lx, Next=%lx, Len=%5u, Curr=%lx, Next node's prev=%lx", + node, prev, next, len, curr, next->chk_mem_node_link.prev); + MEMLOG_CALLSTACK (NULL); + MEMLOG_PAUSEERR (""); + if (mem_chk_err) + (*mem_chk_err)(); + } + + /* Check for buffer overwrite */ + if (check_overwrite (node)) + { + if(node->overwrite_prev_detected==SD_FALSE) + { + MEMLOG_ERR0 ("Memory overwrite at end of buffer detected"); + MEMLOG_CERR5 ( + "Node = %lx, Prev = %lx, Next = %lx, Len = %u, Curr = %lx", + node, prev, next, len, curr); + MEMLOG_CERR2 ("Pointer was allocated at file: %s, line %d ", + node->file,node->line); + MEMLOG_CHERR (node->chk_alloc_mem_size + + sizeof (CHK_DYN_MEM_NODE) + + m_num_pad_bytes, node); + MEMLOG_CALLSTACK (NULL); + MEMLOG_PAUSEERR (""); + if (mem_chk_err) + (*mem_chk_err)(); + node->overwrite_prev_detected=SD_TRUE; + } + } +#if defined(MEMCHK_WIN32_CRT_DEBUG) + else + { + if (_CrtIsMemoryBlock (node, node->chk_alloc_mem_size + mem_overhead, + NULL, NULL, NULL) == FALSE) + { + MEMLOG_ERR0 ("Buffer not a valid memory block"); + MEMLOG_CERR5 ( + "Node = %lx, Prev = %lx, Next = %lx, Len = %u, Curr = %lx", + node, + node->chk_mem_node_link.prev, + node->chk_mem_node_link.next, + node->chk_alloc_mem_size, + node->chk_alloc_mem_ptr); + MEMLOG_CERR2 ("Pointer was allocated at file: %s, line %d ", + node->file,node->line); + MEMLOG_CHERR (node->chk_alloc_mem_size + + sizeof (CHK_DYN_MEM_NODE) + + m_num_pad_bytes, node); + } + } +#endif + + if (next == head_dyn_mem_list) /* is this last node on list? */ + break; + + node = next; /* point to next node in linked list */ + } /* end "for" */ + + if (j >= chk_max_dyn_mem_ptrs) + { + MEMLOG_ERR1 ( + "Last node (Node #%d) does not point back to first.", j - 1); + MEMLOG_CALLSTACK (NULL); + MEMLOG_PAUSEERR (""); + if (mem_chk_err) + (*mem_chk_err)(); + } + else if (j + 1 != chk_curr_mem_count) + { + MEMLOG_CERR0 ("Linked list current count corrupted."); + MEMLOG_CERR2 ("Count = %lu, Should be = %lu.", + (ST_ULONG) chk_curr_mem_count, (ST_ULONG) (j + 1)); + MEMLOG_CALLSTACK (NULL); + MEMLOG_PAUSEERR (""); + if (mem_chk_err) + (*mem_chk_err)(); + } + S_UNLOCK_UTIL_RESOURCES (); + return; + } +#endif /* DEBUG_SISCO */ + } + +/************************************************************************/ +/* check_overwrite */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +static ST_RET check_overwrite (CHK_DYN_MEM_NODE *node) + { +ST_CHAR *bptr; +ST_CHAR *eptr; +ST_INT i; + +/* Get a pointer to the byte after the user's data */ + bptr = (ST_CHAR *) (node +1); + bptr += node->chk_alloc_mem_size; + eptr = bptr + m_num_pad_bytes; + +/* Verify the signature */ + i = 0; + while (bptr < eptr) + { + if (*(bptr++) != m_pad_string[i]) + return (SD_TRUE); /* Overwrite detected, return the error */ + + if (++i >= m_num_pad_bytes) /* if we have wrapped the string */ + i = 0; + } + +/* All is OK with the end of this buffer */ + return (SD_FALSE); + } +#endif + +/************************************************************************/ +/* set_overwrite_value */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +static ST_VOID set_overwrite_value (CHK_DYN_MEM_NODE *node) + { +ST_CHAR *bptr; +ST_CHAR *eptr; +ST_INT i; + +/* Get a pointer to the byte after the user's data */ + bptr = (ST_CHAR *)(node+1); + bptr += node->chk_alloc_mem_size; + eptr = bptr + m_num_pad_bytes; + +/* Set the signature */ + i = 0; + while (bptr < eptr) + { + *(bptr++) = m_pad_string[i]; + if (++i >= m_num_pad_bytes) /* if we have wrapped the string */ + i = 0; + } + + node->overwrite_prev_detected=SD_FALSE; + } +#endif + + diff --git a/mmslib/mmsl/mms_adl.c b/mmslib/mmsl/mms_adl.c new file mode 100644 index 0000000..7dcaf88 --- /dev/null +++ b/mmslib/mmsl/mms_adl.c @@ -0,0 +1,1346 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 1997, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_adl.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Function to convert ADL (Alternate Access Definition Language) into */ +/* alternate access structure */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/09/06 JRB 07 Added ms_adl_to_asn1_2. */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 06/15/98 MDE 05 Changes to allow compile under C++ */ +/* 02/20/98 MDE 04 Minor variable initialization changes */ +/* 12/29/97 MDE 03 Corrected LOCK/UNLOCK problems */ +/* 12/10/97 MDE 02 Added logging for invalid sel_type */ +/* 05/21/97 IKE 01 Used '[' instead of ':' for nesting for an */ +/* array of structures */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" + +/************************************************************************/ + +#define MAX_NESTING_LEVEL 50 +#define MAX_NUM_AA 100 + +#define AA_STACK_EMPTY(a) (!((a)->brace_number)) /* is stack empty*/ +#define AA_STACK_FULL(a) ((a)->brace_number == MAX_NESTING_LEVEL) + +#define L_ANGLE_BRACKET '<' +#define R_ANGLE_BRACKET '>' +#define L_BRACE '[' +#define R_BRACE ']' +#define COMMA ',' +#define COLON ':' +#define ASTERISK '*' +#define NULL_CHARACTER '\0' + +#define ARRAY_ACCESS 0 +#define STRUCTURE_ACCESS 1 +#define L_BRACE_PARSE 2 +#define R_BRACE_PARSE 3 +#define COMMA_PARSE 4 +#define COLON_PARSE 5 +#define FINISH_PARSE 6 + +/* The following data structure is used to keep track of information */ +/* needed to handle ADL string internally. */ + +struct adl_info + { + ST_BOOLEAN comp_name_exists; /* is it a named alternate acces exist ? */ + ST_INT named_index; /* where exactly is the index of the name ? */ + ST_CHAR comp_name[MAX_IDENT_LEN+1]; /* what is the name of the component?*/ + ST_INT nest_count[MAX_NESTING_LEVEL]; /* nesting level per brace */ + ST_INT comp_count[MAX_NESTING_LEVEL]; /* comp nesting level */ + ST_INT brace_number; + ST_INT access_state; /* what to be parsed next ? */ + ST_BOOLEAN started_with_structure_access;/*start could be array or struct*/ + ST_BOOLEAN named_comp_allowed; /* are named components allowed ? */ + ST_BOOLEAN left_brace_allowed; /* is left brace allowed ? */ + }; +typedef struct adl_info ADL_INFO; + + +/************************************************************************/ +/* static variables used in this module */ +/************************************************************************/ + +SD_CONST static ST_CHAR seps[] = " []<>\t\n:,"; +SD_CONST static ST_CHAR ch_seps[] = "[]<>:,"; + +/************************************************************************/ +/* Internal functions for this module */ +/************************************************************************/ +static ST_RET get_alternate_access (ST_CHAR *pString, + ALT_ACCESS *alt_acc, + ADL_INFO *info); +static ST_RET get_structure_access (ST_CHAR **ppString, + ALT_ACCESS *alt_acc, + ADL_INFO *info); +static ST_RET get_array_access (ST_CHAR **ppString, + ALT_ACCESS *alt_acc, + ADL_INFO *info); +static ST_RET process_r_brace (ST_CHAR **ppString, + ALT_ACCESS *alt_acc, + ADL_INFO *info); +static ST_RET process_comma (ST_CHAR **ppString, + ALT_ACCESS *alt_acc, + ADL_INFO *info); +static ST_RET process_l_brace (ST_CHAR **ppString,ADL_INFO *info); +static ST_RET process_colon (ST_CHAR **ppString,ADL_INFO *info); +static ST_RET end_of_parsing (ALT_ACCESS *alt_acc,ADL_INFO *info); +static ST_RET get_named_component (ST_CHAR **ppString,ST_CHAR *token); +static ST_RET get_index_identifier (ST_CHAR **ppString,ALT_ACCESS *alt_acc); +static ST_RET get_sel_type (ST_CHAR **ppString,ST_INT type); +static ST_VOID copy_component_name (ALT_ACCESS *alt_acc,ADL_INFO *info); +static ST_RET isnumber (ST_CHAR *pString); +static ST_RET is_iso_identifier (ST_CHAR *pString); +static ST_VOID point_to_next_character (ST_INT length,ST_CHAR **ppString); +static ST_RET token_copy (ST_CHAR *token,ST_CHAR *pString,ST_INT max_token_length); +static ST_RET traverse_array (ALT_ACCESS *, ST_INT, ST_CHAR *,ST_INT); +static ST_RET get_alt_acc (ALT_ACCESS *); +static ST_RET separator_copy (ST_CHAR *adl,ST_INT *i,ST_CHAR separator, ST_INT max_adl_len); +static ST_RET comp_copy (ST_CHAR *adl,ST_INT *i,ST_CHAR *comp, ST_INT max_adl_len); + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* ms_adl_to_aa */ +/* Function to parse ADL (Alternate Access Definition Language) and */ +/* put into alternate structure */ +/* Input : adl_str User allocates and frees it */ +/* Output : alt_acc User allocate and frees it */ +/* Output : alt_acc->aa : This function allocates and user frees it */ +/* The grammar of ADL is as follows */ +/* */ +/* ::= | */ +/* ::= | */ +/* */ +/* ::= */ +/* ::= | */ +/* */ +/* ::= | */ +/* ::="["{}"]"*/ +/* | "["{}"]" */ +/* ::= ISO Identifier */ +/* ::= "<"">" */ +/* ::= | | */ +/* ::= */ +/* ::= */ +/* ::= */ +/* ::= | */ +/* ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"*/ +/* ::= "*" */ +/* ::= "," */ +/* ::= ":" */ +/************************************************************************/ + +ST_RET ms_adl_to_aa (ST_CHAR *adl_str,ALT_ACCESS *alt_acc) + { +ST_RET ret_value; +ST_CHAR *string; +ST_INT str_length; +ADL_INFO *info; + + S_LOCK_COMMON_RESOURCES (); + +/* initialize local variables */ + ret_value = MVE_INVALID_ADL; + str_length = strlen (adl_str); + string = (ST_CHAR *) chk_calloc (1,str_length+1); + info = (ADL_INFO *) chk_calloc (1,sizeof (ADL_INFO)); + +/* initialize alt_acc */ + alt_acc->num_aa = 0; + alt_acc->aa = (ALT_ACC_EL *) chk_calloc (MAX_NUM_AA,sizeof (ALT_ACC_EL)); + +/* make the duplicate copy of the adl_string and use it in the function */ +/* calls in case any function corrupts the string */ + strcpy (string,adl_str); + +/* initialize some state control variables */ + info->comp_name_exists = SD_FALSE; + info->named_comp_allowed = SD_FALSE; + info->left_brace_allowed = SD_TRUE; + +/* start parsing */ + ret_value = get_alternate_access (string,alt_acc,info); + +/* free what we allocated in this function */ + chk_free (info); + chk_free (string); + if (ret_value != SD_SUCCESS) + chk_free (alt_acc->aa); + +/* Take care of housekeeping */ + if (ret_value == SD_SUCCESS) + { + /* Log the alternate access, if selected */ + if (mms_debug_sel & MMS_LOG_AA) + ms_log_alt_access (alt_acc); + /* save the high water mark */ + if (alt_acc->num_aa > m_hw_dec_aa) + m_hw_dec_aa = alt_acc->num_aa; + } + S_UNLOCK_COMMON_RESOURCES (); + return (ret_value); + } + +/************************************************************************/ +/* ms_aa_to_adl */ +/* Function to extract information from alternate access structure and */ +/* make ADL string as output */ +/* Input : alt_acc user allocates and frees it */ +/* Output : adl_str : user is responsible and frees it */ +/************************************************************************/ +ST_RET ms_aa_to_adl (ALT_ACCESS *alt_acc, ST_CHAR *adl_str,ST_INT max_adl_len) + { +ST_INT num_of_els; +ST_RET ret; + + S_LOCK_COMMON_RESOURCES (); + num_of_els = get_alt_acc (alt_acc); + if (num_of_els == 0) + ret = MVE_INVALID_ADL; + else + ret = traverse_array (alt_acc, num_of_els, adl_str,max_adl_len); + + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +/************************************************************************/ +/* get_alternate_access */ +/* This function parses the passed string pString sequentially. While */ +/* parsing, this function works on state basis and calls the appropriate*/ +/* function on the basis. The called functions set the next state */ +/************************************************************************/ + +static ST_RET get_alternate_access (ST_CHAR *pString, + ALT_ACCESS *alt_acc, + ADL_INFO *info) + { +ST_INT ret_value; +ST_BOOLEAN all_done; + + ret_value = SD_SUCCESS; + all_done = SD_FALSE; + point_to_next_character (0,&pString); + if (*pString == L_BRACE) + { + info->brace_number++; + info->access_state = ARRAY_ACCESS; + info->started_with_structure_access = SD_FALSE; + point_to_next_character (1,&pString); + } + else + { + info->access_state = STRUCTURE_ACCESS; + info->started_with_structure_access = SD_TRUE; + } + + while ((all_done==SD_FALSE) && (ret_value == SD_SUCCESS)) + { + switch (info->access_state) + { + case STRUCTURE_ACCESS : + ret_value = get_structure_access (&pString,alt_acc,info); + break; + + case ARRAY_ACCESS : + ret_value = get_array_access (&pString,alt_acc,info); + break; + + case L_BRACE_PARSE : + ret_value = process_l_brace (&pString,info); + break; + + case R_BRACE_PARSE : + ret_value = process_r_brace (&pString,alt_acc,info); + break; + + case COMMA_PARSE : + ret_value = process_comma (&pString,alt_acc,info); + break; + + case COLON_PARSE : + ret_value = process_colon (&pString,info); + break; + + case FINISH_PARSE : + ret_value = end_of_parsing (alt_acc,info); + all_done = SD_TRUE; + break; + + default: + MLOG_NERR1("Unexpected %s",pString); + ret_value = MVE_INVALID_ADL; + break; + + } + } + + if (ret_value != SD_SUCCESS) + return (MVE_INVALID_ADL); + +/* Stack should be empty because all braces should be matched by now */ + if (info->brace_number) + { + MLOG_NERR0("Braces not matched"); + return (MVE_INVALID_ADL); + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* get_structure_access */ +/* This function expects the syntax like comp1 or comp1 in the */ +/* beginning. It parses until the component ,checks the next character */ +/* and sets the next state */ +/************************************************************************/ + +static ST_RET get_structure_access (ST_CHAR **ppString, + ALT_ACCESS *alt_acc, + ADL_INFO *info) + { +ST_CHAR token[MAX_IDENT_LEN+1]; +ST_INT token_length; +ST_RET ret_value; +ST_CHAR *pString; +ALT_ACC_EL *aa; + + ret_value = SD_SUCCESS; + pString = *ppString; + aa = alt_acc->aa+alt_acc->num_aa; + if (*pString == L_ANGLE_BRACKET) /* alternate access has a name */ + { + if (info->comp_name_exists == SD_TRUE) /* name already defined */ + { + MLOG_NERR1("component name is allowed only once.Error at %s",pString); + return (MVE_INVALID_ADL); + } + info->comp_name_exists = SD_TRUE; + if (get_named_component (&pString,info->comp_name) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + if (!(token_length = token_copy (token,pString,MAX_IDENT_LEN))) + { + MLOG_NERR1("Expected component at %s",pString); + return (MVE_INVALID_ADL); + } + if (is_iso_identifier (token) == SD_FALSE) + { + MLOG_NERR1("Component %s is not a valid identifier",token); + return (MVE_INVALID_ADL); + } +/* set the aa pointer to the current structure to be filled in */ + aa = alt_acc->aa+alt_acc->num_aa; + +/* start filling the structure */ + aa->comp_name_pres = info->comp_name_exists; + if (aa->comp_name_pres) + strcpy (aa->comp_name,info->comp_name); + strcpy (aa->u.component,token); + aa->sel_type = get_sel_type (&pString,AA_COMP); + + if ((info->comp_name_exists == SD_TRUE) && (aa->sel_type == AA_COMP || aa->sel_type == AA_COMP_NEST)) + info->named_index = alt_acc->num_aa; + if (++alt_acc->num_aa > MAX_NUM_AA) + { + MLOG_NERR0("Number of elements in the structure exceeded the limit"); + return (MVE_INVALID_ADL); + } + point_to_next_character (token_length,&pString); + +/* Setting the next access state */ + switch (*pString) + { + case L_BRACE : + info->access_state = L_BRACE_PARSE; + break; + + case R_BRACE : + info->access_state = R_BRACE_PARSE; + break; + + case COMMA : + info->access_state = COMMA_PARSE; + break; + + case NULL_CHARACTER : + info->access_state = FINISH_PARSE; + break; + + default : + MLOG_NERR1("Unexpected %s",pString); + ret_value = MVE_INVALID_ADL; + info->access_state = -1; + break; + } +/* update argumet with the current position of the pointer to string */ + *ppString = pString; + return (ret_value); + } + +/************************************************************************/ +/* get_array_access */ +/* This function expects the syntax like 2:comp1 or 2[3 or 2,3 in the */ +/* beginning. It parses to get the index identifier, checks the next */ +/* character and sets the next state */ +/************************************************************************/ + +static ST_RET get_array_access (ST_CHAR **ppString, + ALT_ACCESS *alt_acc, + ADL_INFO *info) + { +ST_CHAR *pString; +ST_RET ret_value; + + ret_value = SD_SUCCESS; + pString = *ppString; + if (info->left_brace_allowed == SD_FALSE) + { + MLOG_NERR1("Syntax error at %s",pString); + return (MVE_INVALID_ADL); + } + if (get_index_identifier (&pString,alt_acc) != SD_SUCCESS) + return (MVE_INVALID_ADL); + if (++alt_acc->num_aa > MAX_NUM_AA) + { + MLOG_NERR0("Number of elements in the structure exceeded the limit"); + return (MVE_INVALID_ADL); + } +/* Setting the next access state */ + + switch (*pString) + { + case L_BRACE : + info->access_state = L_BRACE_PARSE; + break; + + case R_BRACE : + info->access_state = R_BRACE_PARSE; + break; + + case COLON : + info->access_state = COLON_PARSE; + break; + + default : + MLOG_NERR1("Unexpected %s",pString); + ret_value = MVE_INVALID_ADL; + info->access_state = -1; + break; + } +/* update argumet with the current position of the pointer to string */ + *ppString = pString; + return (ret_value); + } + +/************************************************************************/ +/* process_l_brace */ +/* If the left brace is encountered then we expect array access.We also */ +/* keep track of nesting associated with this brace */ +/************************************************************************/ + +static ST_RET process_l_brace (ST_CHAR **ppString,ADL_INFO *info) + { +ST_CHAR *pString; + + pString = *ppString; + if (AA_STACK_FULL (info)) + { + MLOG_NERR0("Nesting Level exceeded"); + return (MVE_INVALID_ADL); + } +/* we are nesting one level now associated with this brace */ + info -> nest_count[info->brace_number++] = 1; + point_to_next_character (1,&pString); + if (isdigit (*pString) || (*pString == ASTERISK)) + info->access_state = ARRAY_ACCESS; + else + info->access_state = STRUCTURE_ACCESS; + *ppString = pString; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* process_r_brace */ +/* Right brace is used to end the array access. This function removes */ +/* the right brace from the passed string, checks the next character */ +/* and sets the next state */ +/************************************************************************/ + +static ST_RET process_r_brace (ST_CHAR **ppString, + ALT_ACCESS *alt_acc, + ADL_INFO *info) + { +ST_CHAR *pString; +ST_RET ret_value; +ST_INT i; +ST_INT brace_number; +ALT_ACC_EL *aa; + + ret_value = SD_SUCCESS; + aa = alt_acc->aa+alt_acc->num_aa; + pString = *ppString; + + info->left_brace_allowed = SD_FALSE; + if (AA_STACK_EMPTY (info)) + { + MLOG_NERR1("Syntax Error due to right brace at %s",pString); + return (MVE_INVALID_ADL); + } + brace_number = -- info->brace_number; + for (i=0;inest_count[brace_number];i++,aa++) + { + aa->sel_type = AA_END_NEST; + if (++alt_acc->num_aa > MAX_NUM_AA) + { + MLOG_NERR0("Number of elements in the structure exceeded the limit"); + return (MVE_INVALID_ADL); + } + } + point_to_next_character (1,&pString); + switch (*pString) + { + case R_BRACE : + info->access_state = R_BRACE_PARSE; + break; + + case COMMA : + /* comma is used to separate between different alternate accesses */ + /* it is invalid between between two array accesses like [2],[3] */ + if ((info->started_with_structure_access == SD_TRUE) || (info->brace_number)) + { + info->access_state = COMMA_PARSE; + } + else + { + info->access_state = -1; + MLOG_NERR1("Comma invalid at %s",pString); + ret_value = MVE_INVALID_ADL; + } + break; + + case NULL_CHARACTER : + info->access_state = FINISH_PARSE; + break; + + default : + info->access_state = -1; + MLOG_NERR1("Unexpected %s",pString); + ret_value = MVE_INVALID_ADL; + break; + } + *ppString = pString; + return (ret_value); + } + +/************************************************************************/ +/* process_comma */ +/* If the comma is encountered then we expect structure access */ +/************************************************************************/ + +static ST_RET process_comma (ST_CHAR **ppString, + ALT_ACCESS *alt_acc, + ADL_INFO *info) + { + info->named_comp_allowed = SD_TRUE; + info->access_state = STRUCTURE_ACCESS; + info->left_brace_allowed = SD_TRUE; +/* it is time to copy the name of the alternate access if there is any */ + if (info->comp_name_exists) + copy_component_name (alt_acc,info); + point_to_next_character (1,ppString); + if (**ppString == NULL_CHARACTER) + { + MLOG_NERR0("Comma unexpected at the end"); + return (MVE_INVALID_ADL); + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/* process_colon */ +/* Colon means array index is nested with structure elements so we */ +/* increment the nesting level of the brace before colon by one */ +/************************************************************************/ + +static ST_RET process_colon (ST_CHAR **ppString,ADL_INFO *info) + { +ST_RET brace_number; + + if (AA_STACK_EMPTY (info)) + { + MLOG_NERR1("Syntax Error due to colon at %s",*ppString); + return (MVE_INVALID_ADL); + } + brace_number = info->brace_number - 1; + info -> nest_count[brace_number] ++; + info->access_state = STRUCTURE_ACCESS; + point_to_next_character (1,ppString); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* end_of_parsing */ +/* At the end of parsing it checks if the name of the alternate access */ +/* needs to be copied into the structure */ +/************************************************************************/ + +static ST_RET end_of_parsing (ALT_ACCESS *alt_acc,ADL_INFO *info) + { +ALT_ACC_EL *aa; + + aa = alt_acc->aa+alt_acc->num_aa; + if ((info->comp_name_exists) && (info->named_comp_allowed)) + copy_component_name (alt_acc,info); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* get_named_component */ +/* This function extracts "name1" from the syntax and points */ +/* to first non white space character after ">" */ +/************************************************************************/ + +static ST_RET get_named_component (ST_CHAR **ppString,ST_CHAR *token) + { +ST_INT token_length; +ST_CHAR *pString; + + pString = *ppString; + point_to_next_character (1,&pString); + if (!(token_length = token_copy (token,pString,MAX_IDENT_LEN))) + { + MLOG_NERR1("Expected name for the Alternate Access at %s",pString); + return (MVE_INVALID_ADL); + } + if (is_iso_identifier (token) == SD_FALSE) + { + MLOG_NERR1("not a valid ISO identifier %s",token); + return (MVE_INVALID_ADL); + } + point_to_next_character (token_length,&pString); + if (*pString != R_ANGLE_BRACKET)/* expect R_ANGLE_BRACKET */ + { + MLOG_NERR1("Right Angle Bracket expected at %s",pString); + return (MVE_INVALID_ADL); + } + point_to_next_character (1,&pString); /* remove white spaces between R_ANGLE_BRACKET*/ + *ppString = pString; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* get_index_identifier */ +/* This function is called by the function get_array_access */ +/* Index Identifier could be one of these three types */ +/* */ +/* ::= */ +/* ::= "*" */ +/* where , and are decimal numbers */ +/************************************************************************/ + +static ST_RET get_index_identifier (ST_CHAR **ppString,ALT_ACCESS *alt_acc) + { +ST_CHAR *pString; +ST_INT token_length; +ST_CHAR token[MAX_IDENT_LEN+1]; +ALT_ACC_EL *aa; + + aa = alt_acc->aa+alt_acc->num_aa; + pString = *ppString; + if (!(token_length = token_copy (token,pString,MAX_IDENT_LEN))) + { + MLOG_NERR1("Expected an index after [ at %s",pString); + return (MVE_INVALID_ADL); + } + point_to_next_character (token_length,&pString); + switch (*pString) + { + case L_BRACE : + case R_BRACE : + case COLON : + if ((*token == ASTERISK) && (token_length == 1)) + { + aa->sel_type = get_sel_type (&pString,AA_ALL); + } + else + { + if (isnumber (token) == SD_FALSE) + { + MLOG_NERR1("Expected a number or '*' at %s",token); + return (MVE_INVALID_ADL); + } + aa->u.index = atol (token); + aa->sel_type = get_sel_type (&pString,AA_INDEX); + } + break; + + case COMMA : + if (isnumber (token) == SD_FALSE) + { + MLOG_NERR1("Expected a number at %s",token); + return (MVE_INVALID_ADL); + } + aa->u.ir.low_index = atol (token); + point_to_next_character (1,&pString); + if (!(token_length = token_copy (token,pString,MAX_IDENT_LEN+1))) + { + MLOG_NERR1("Expected an index at %s",pString); + return (MVE_INVALID_ADL); + } + point_to_next_character (token_length,&pString); + if ((*pString != L_BRACE) && (*pString != R_BRACE) + && (*pString != COLON)) + { + MLOG_NERR2("Unexpected character %c at %s", *pString,pString); + MLOG_NERR0("Expected characters []:"); + return (MVE_INVALID_ADL); + } + if (isnumber (token) == SD_FALSE) + { + MLOG_NERR1("Expected a number at %s",token); + return (MVE_INVALID_ADL); + } + aa->u.ir.num_elmnts = atol (token); + aa->sel_type = get_sel_type (&pString,AA_INDEX_RANGE); + break; + + default : + MLOG_NERR2("Unexpected character %c at %s ",*pString,pString); + MLOG_NERR0("Expected characters : [],:"); + return (MVE_INVALID_ADL); + break; + } + *ppString = pString; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* get_sel_type */ +/* This function determines sel_type for Alternate Access if it nested */ +/* or not depending on the next separator. If type is nested it */ +/* increments a static variable nesting_count which is used to fill the */ +/* structure with sel_type of AA_END_NEST at the end of parsing. If type*/ +/* is not nested, it returns the passed type. This function does not */ +/* alter the passed string */ +/************************************************************************/ + +static ST_RET get_sel_type (ST_CHAR **ppString, ST_INT type) + { +ST_CHAR *next_separator; + + next_separator = strpbrk (*ppString,ch_seps); + if (!next_separator) + return (type); + + switch (type) + { + case AA_COMP : + if (*next_separator == L_BRACE) + type = AA_COMP_NEST; + break; + + case AA_INDEX : + if ((*next_separator == L_BRACE) || (*next_separator == COLON)) + type = AA_INDEX_NEST; + break; + + case AA_INDEX_RANGE : + if ((*next_separator == L_BRACE) || (*next_separator == COLON)) + type = AA_INDEX_RANGE_NEST; + break; + + case AA_ALL : + if ((*next_separator == L_BRACE) || (*next_separator == COLON)) + type = AA_ALL_NEST; + break; + } + return (type); + } + +/************************************************************************/ +/* copy_component_name */ +/* This function copies the name of the alternate access to the */ +/* structure at the right place */ +/************************************************************************/ + +static ST_VOID copy_component_name (ALT_ACCESS *alt_acc,ADL_INFO *info) + { +ALT_ACC_EL *aa; + aa = alt_acc -> aa + info->named_index; + strcpy (aa->comp_name,info->comp_name); + aa->comp_name_pres = SD_TRUE; + info->comp_name_exists = SD_FALSE; + } + +/************************************************************************/ +/* isnumber */ +/* This function checks if the passed string contains only digits */ +/************************************************************************/ + +static ST_RET isnumber (ST_CHAR *pString) + { + while (*pString) + { + if (isdigit (*pString++)==0) + return (SD_FALSE); + } + return (SD_TRUE); + } + +/************************************************************************/ +/* is_iso_identifier */ +/* This function checks the health of ISO identifier. ISO identifier */ +/* can not start with a number and it can have alphanumeric characters */ +/* underscore '_' and dollar sign '$' */ +/************************************************************************/ + +static ST_RET is_iso_identifier (ST_CHAR *pString) + { + if (isdigit (*pString)) /* the first letter may not be a digit */ + return (SD_FALSE); + while (*pString) + { + if ((!(isalnum (*pString))) && + (!(*pString == '_')) && + (!(*pString == '$'))) + return (SD_FALSE); + pString++; + } + return (SD_TRUE); + } + +/************************************************************************/ +/* point_to_next_character */ +/* This function wacks all the white spaces and pointer will be */ +/* pointing to the next character in the string or null character if */ +/* there are no more characters in the string */ +/************************************************************************/ + +static ST_VOID point_to_next_character (ST_INT length,ST_CHAR **ppString) + { + *ppString += length; + while (isspace (**ppString)) + (*ppString)++; + } + +/************************************************************************/ +/* token_copy */ +/* This funtion gets the token from the string and returns the strlen */ +/************************************************************************/ + +static ST_RET token_copy (ST_CHAR *token,ST_CHAR *pString,ST_INT max_token_length) + { +ST_INT counter; + + counter = 0; + while ((strchr (seps,*pString)==NULL) && (counter < max_token_length)) + { + *token++ = *pString++; + counter++; + } + *token = '\0'; + return (counter); + } + +/************************************************************************/ +/* get_alt_acc */ +/* This function is called by ms_adl_to_string */ +/************************************************************************/ +static ST_RET get_alt_acc (ALT_ACCESS *alt_acc) + { +ALT_ACC_EL *aa; +ST_INT el_count; +ST_INT error; +ST_INT index_count; /*keep track of nesting */ +ST_INT comp_nest_count[MAX_NESTING_LEVEL]; +ST_INT x; + + error = SD_FALSE; + x = -1; + index_count = 0; + aa = alt_acc->aa; + for (el_count = 0; el_count < alt_acc->num_aa; ++el_count, ++aa) + { + switch (aa->sel_type) + { + case AA_COMP_NEST : + index_count++; + comp_nest_count[++x] = index_count; + case AA_COMP : + break; + + case AA_INDEX_NEST : + index_count++; + case AA_INDEX : + break; + + case AA_INDEX_RANGE_NEST : + index_count++; + case AA_INDEX_RANGE : + break; + + case AA_ALL_NEST : + index_count++; + case AA_ALL : + break; + case AA_END_NEST : + if (index_count == comp_nest_count[x] && x >= 0) + comp_nest_count[x--] = 0; + index_count--; + break; + + default : /* should not be any other tag */ + MLOG_NERR0("Bad sel_type"); + error = SD_TRUE; + break; + } + if (error) + break; + } + + if (!error && el_count && !index_count) + { + alt_acc->num_aa = el_count; + return (el_count); + } + return (0); + } + +/************************************************************************/ +/* traverse_array */ +/* Interprets each element of AA structure and puts correct ADL syntax */ +/* into an array. This function is called through aa_to_adl. */ +/************************************************************************/ +static ST_RET traverse_array (ALT_ACCESS *alt_acc, + ST_INT count, + ST_CHAR *adl, + ST_INT max_adl_len) + { +ADL_INFO info; +ALT_ACC_EL *aa; +ST_INT loop_count; +ST_INT temp_count; +ST_INT prev_sel_type; /* Initialize to meaningless value */ +ST_INT lbrace_count; +ST_INT rbrace_count; +ST_INT x; +ST_INT y; +ST_INT len, len2; +ST_INT i; +ST_CHAR ch[MAX_IDENT_LEN]; /* Max length for unsigned long integer */ +ST_CHAR *pCount; +ST_CHAR *temp_ptr; + + prev_sel_type = 99; /* Initialize to meaningless value */ + x = -1; + y = 0; + i = 0; + + pCount = adl; + temp_ptr = adl; + memset (&info, 0, sizeof (ADL_INFO)); + aa = alt_acc->aa; + info.nest_count[0] = 0; + info.comp_count[0] = 0; + + switch (aa->sel_type) + { + case AA_INDEX : + case AA_INDEX_RANGE : + case AA_ALL : + case AA_ALL_NEST : + case AA_INDEX_NEST : + case AA_INDEX_RANGE_NEST : + info.access_state = ARRAY_ACCESS; + info.started_with_structure_access = SD_FALSE; + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + break; + default: + info.access_state = STRUCTURE_ACCESS; + info.started_with_structure_access = SD_TRUE; + break; + } + + for (loop_count = 0; loop_count < count; loop_count++, aa++) + { + switch (aa->sel_type) + { + case AA_COMP: + if ((prev_sel_type == AA_COMP) && (info.nest_count[0])) + { + i--; + if (separator_copy (adl, &i, COMMA, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + else if ((prev_sel_type == AA_END_NEST) || (prev_sel_type == AA_COMP)) + { + if (separator_copy (adl, &i, COMMA, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + if ((prev_sel_type == AA_INDEX_RANGE_NEST) || (prev_sel_type == AA_INDEX_NEST)) + { + i--; + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + else if ((prev_sel_type == AA_INDEX) || (prev_sel_type == AA_INDEX_RANGE) + || (prev_sel_type == AA_ALL_NEST)) + { + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + if (prev_sel_type == AA_COMP_NEST) + { + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + if ((aa->comp_name_pres) && (!info.comp_count[0])) + { + if (separator_copy (adl, &i, L_ANGLE_BRACKET, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + if (comp_copy (adl, &i, aa->comp_name, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + if (separator_copy (adl, &i, R_ANGLE_BRACKET, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + if (comp_copy (adl, &i, aa->u.component, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + len = strlen (aa->u.component); + len2 = strlen (aa->comp_name); + if (adl[i - len - 1] == L_BRACE || prev_sel_type == AA_COMP_NEST || + (aa->comp_name_pres && adl[i - len - len2 - 3] == L_BRACE)) + if (separator_copy (adl, &i, R_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + + info.comp_name_exists = SD_TRUE; + prev_sel_type = AA_COMP; + break; + + case AA_COMP_NEST: + if (prev_sel_type == AA_END_NEST) + { + if (separator_copy (adl, &i, COMMA, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + + if ((prev_sel_type == AA_INDEX_NEST) && adl[i - 1] == R_BRACE) + { + i--; + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + else if ((prev_sel_type == AA_INDEX_NEST) || (prev_sel_type == AA_INDEX_RANGE_NEST) + || (prev_sel_type == AA_ALL_NEST)) + { + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + + if (prev_sel_type == AA_COMP) + { + if (separator_copy (adl, &i, COMMA, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + + if (prev_sel_type == AA_COMP_NEST) + { + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + + if ((aa->comp_name_pres) && (!info.comp_count[0])) + { + if (separator_copy (adl, &i, L_ANGLE_BRACKET, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + if (comp_copy (adl, &i, aa->comp_name, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + if (separator_copy (adl, &i, R_ANGLE_BRACKET, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + if (comp_copy (adl, &i, aa->u.component, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + info.comp_name_exists = SD_TRUE; + prev_sel_type = AA_COMP_NEST; + info.nest_count[y] = AA_COMP_NEST; + info.comp_count[++x] = info.nest_count[y++]; + break; + + + case AA_INDEX_NEST: + info.nest_count[y++] = AA_INDEX_NEST; + if (prev_sel_type == AA_END_NEST) + { + if (separator_copy (adl, &i, COMMA, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + + if ((prev_sel_type == AA_INDEX_RANGE_NEST) || (prev_sel_type == AA_COMP_NEST) || + (prev_sel_type == AA_ALL_NEST)) + { + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + + if (prev_sel_type == AA_INDEX_NEST) + { + i--; + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + sprintf (ch, "%lu", aa->u.index); + if (strlen (ch) > MAX_IDENT_LEN) + return (MVE_INVALID_ADL); + if (comp_copy (adl, &i, ch, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + if (separator_copy (adl, &i, R_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + prev_sel_type = AA_INDEX_NEST; + break; + + case AA_INDEX: + if (prev_sel_type == AA_END_NEST) + { + if (separator_copy (adl, &i, COMMA, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + + if (prev_sel_type == AA_INDEX_RANGE_NEST) + { + --i; + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + if ((prev_sel_type == AA_COMP_NEST) ||(prev_sel_type == AA_ALL_NEST)) + { + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + + if (prev_sel_type == AA_INDEX_NEST) + { + i--; + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + sprintf (ch, "%lu", aa->u.index); + if (strlen (ch) > MAX_IDENT_LEN) + return (MVE_INVALID_ADL); + if (comp_copy (adl, &i, ch, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + if (separator_copy (adl, &i, R_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + prev_sel_type = AA_INDEX_NEST; + break; + + case AA_INDEX_RANGE_NEST: + info.nest_count[y++] = AA_INDEX_RANGE_NEST; + case AA_INDEX_RANGE: + if (prev_sel_type == AA_INDEX_NEST) + { + i--; + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + if (prev_sel_type == AA_END_NEST) + { + if (separator_copy (adl, &i, COMMA, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + if (prev_sel_type == AA_COMP_NEST) + { + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + if (prev_sel_type == AA_INDEX_RANGE_NEST) + { + i--; + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + sprintf (ch, "%lu", aa->u.ir.low_index); + if (strlen (ch) > MAX_IDENT_LEN) + return (MVE_INVALID_ADL); + if (comp_copy (adl, &i, ch, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + if (separator_copy (adl, &i, COMMA, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + sprintf (ch, "%lu", aa->u.ir.num_elmnts); + if (strlen (ch) > MAX_IDENT_LEN) + return (MVE_INVALID_ADL); + if (comp_copy (adl, &i, ch, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + if (separator_copy (adl, &i, R_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + prev_sel_type = AA_INDEX_RANGE_NEST; + break; + + case AA_ALL_NEST: + info.nest_count[y++] = AA_ALL_NEST; + case AA_ALL: + if (prev_sel_type == AA_END_NEST) + { + if (separator_copy (adl, &i, COMMA, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + if ((prev_sel_type == AA_COMP_NEST) || (prev_sel_type == AA_ALL_NEST)) + { + if (separator_copy (adl, &i, L_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + } + + if (separator_copy (adl, &i, ASTERISK, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + prev_sel_type = AA_ALL_NEST; + break; + + case AA_END_NEST: + if ((prev_sel_type != AA_END_NEST) && (adl[i - 1] == R_BRACE)) + { + i--; + adl[i] = 0; + } + y--; + if (info.nest_count[y] == info.comp_count[x] && x >= 0) + info.comp_count[x--] = 0; + + lbrace_count = rbrace_count = 0; + + if (separator_copy (adl, &i, R_BRACE, max_adl_len) != SD_SUCCESS) + return (MVE_INVALID_ADL); + + if (y == 0) + { + for (temp_count = 0; (temp_count <= (&adl[i] - temp_ptr)) && + (*pCount != 0); temp_count++, pCount++) + { + if (*pCount == L_BRACE) + lbrace_count++; + if (*pCount == R_BRACE) + rbrace_count++; + } + } + + adl[i] = 0; + prev_sel_type = AA_END_NEST; + break; + default: + MLOG_NERR1("Invalid sel_type : %d", aa->sel_type); + return (MVE_INVALID_ADL); + break; + } + } + + pCount = adl; + lbrace_count = rbrace_count = 0; + + for (temp_count = 0; (temp_count <= i) && (*pCount != 0); temp_count++, pCount++) + { + if (*pCount == L_BRACE) + lbrace_count++; + if (*pCount == R_BRACE) + rbrace_count++; + } + rbrace_count = lbrace_count - rbrace_count; + for (temp_count = 0; temp_count < rbrace_count; temp_count++) + { + *pCount = R_BRACE; + pCount++; + } + *pCount = 0; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* separator_copy */ +/* This function takes start of string pointer, current string pointer */ +/* the string we want to copy and max len allowed, Before we copy str */ +/* into adl[*i] we validate for the overrun */ +/************************************************************************/ +static ST_RET separator_copy (ST_CHAR *adl,ST_INT *i,ST_CHAR sep, ST_INT max_adl_len) + { + if (*i + 1 >= max_adl_len) + return (SD_FAILURE); + adl[*i] = sep; + *i += 1; + adl[*i] = 0; /* Insure end of string is recognized */ + return (SD_SUCCESS); + } +/************************************************************************/ + +/************************************************************************/ +static ST_RET comp_copy (ST_CHAR *adl,ST_INT *i,ST_CHAR *comp, ST_INT max_adl_len) + { +ST_INT comp_len; + + comp_len = strlen (comp); + if (*i + comp_len + 1 >= max_adl_len) + return (SD_FAILURE); + strcpy (&adl[*i], comp); + *i += comp_len; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* ms_adl_to_asn1_2 */ +/* Function to parse ADL (Alternate Access Definition Language) and */ +/* generate the ASN.1 encoding of the Alternate Access Definition. */ +/* NOTE: Suffix (_2) is just to avoid naming conflict with older funct. */ +/* NOTE: this function is thread-safe as long as the encode buffer */ +/* passed as arg (buf_ptr) is not being used by another thread. */ +/************************************************************************/ +ST_RET ms_adl_to_asn1_2 (ST_CHAR *pAdl, /* ADL string to be encoded */ + ST_UCHAR *buf_ptr, /* buffer in which to encode */ + ST_INT buf_len, /* buffer length */ + ST_UCHAR **asn1_ptr_out, /* ptr to ptr to encoded data */ + ST_INT *asn1_len_out) /* ptr to encoded length */ + { +ALT_ACCESS stAltAcc; +ST_RET retcode; + + /* First, convert from ADL string to ALT_ACCESS structure. */ + /* NOTE: if successful, this allocates "stAltAcc.aa". Be sure to free it.*/ + retcode = ms_adl_to_aa(pAdl, &stAltAcc); /* get ALT_ACCESS */ + if (retcode == SD_SUCCESS) + { + /* Next, convert from ALT_ACCESS structure to ASN.1 encoding. */ + retcode = ms_aa_to_asn1_2 (&stAltAcc, buf_ptr, buf_len, + asn1_ptr_out, asn1_len_out); + chk_free (stAltAcc.aa); /* free array allocated by ms_adl_to_aa */ + } + return (retcode); + } diff --git a/mmslib/mmsl/mms_alta.c b/mmslib/mmsl/mms_alta.c new file mode 100644 index 0000000..aac2358 --- /dev/null +++ b/mmslib/mmsl/mms_alta.c @@ -0,0 +1,934 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2006, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_alta.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Function to decode ASN.1 type definitions into Runtime typedefs */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/09/06 JRB 20 Add ms_aa_to_asn1_2. */ +/* 02/22/05 JRB 19 Make "sp" local to avoid VXWORKS conflict. */ +/* 02/06/02 JRB 18 Move ms_mk_rt_aa* to new mms_rtaa.c. */ +/* 12/20/01 JRB 17 Converted to use ASN1R (re-entrant ASN1) */ +/* 11/15/01 EJV 16 Added support for new MMS type UtcTime: */ +/* find_named_comp: added case for RT_UTC_TIME; */ +/* _ms_log_runtime_aa: add case for RT_UTC_TIME;*/ +/* 09/26/00 JRB 15 Add SD_CONST on ms_mk_rt_aa* */ +/* 07/28/00 JRB 14 Use ms_comp_name_find for everyone. */ +/* 07/13/00 JRB 13 Use new ms_comp_name_find for MMS LITE. */ +/* 04/28/00 JRB 12 Lint cleanup */ +/* 09/13/99 RKR 11 Respaced a macro for the install utility */ +/* 09/13/99 MDE 10 Added SD_CONST modifiers */ +/* 07/30/99 MDE 09 Replaced CSTR_DONE_FUN macro use */ +/* 09/21/98 MDE 08 Minor lint cleanup */ +/* 09/10/98 MDE 07 Changes to work better with MMS-LITE */ +/* 06/15/98 MDE 06 Changes to allow compile under C++ */ +/* 03/12/98 MDE 05 '_ms_m_get_rt_info' use change */ +/* 03/11/98 MDE 04 Removed NEST_RT_TYPES */ +/* 02/10/98 MDE 03 No longer use runtime type 'loops' element */ +/* rearranged for MMS-LITE (MMS_ALTA_DATA) */ +/* 12/29/97 MDE 02 Corrected LOCK/UNLOCK problems */ +/* 06/09/97 MDE 01 Modified Runtime Type handling */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ + +static ST_RET wr_altAcc (ASN1_ENC_CTXT *aCtx, ALT_ACC_EL **aap, ALT_ACC_EL *last_aa); +static ST_RET wr_altAccSel (ASN1_ENC_CTXT *aCtx, ALT_ACC_EL **aap, ALT_ACC_EL *last_aa); +static ALT_ACC_EL *find_start_aa_nest (ALT_ACC_EL *aa, ALT_ACC_EL *last_aa); +static ST_VOID alt_acc_seq_start (ASN1_DEC_CTXT *aCtx); +static ST_VOID alt_acc_seq_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID add_alt_acc_tags (ASN1_DEC_CTXT *aCtx); +static ST_VOID named_start (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_component_name (ASN1_DEC_CTXT *aCtx); +static ST_VOID named_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_acc_comp (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_acc_index (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_acc_index_range (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_acc_ir_low (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_acc_ir_num (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_acc_ir_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_acc_all (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_alt_acc (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_alt_acc_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_alt_acc_comp (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_alt_acc_index (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_alt_acc_index_range (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_alt_acc_ir_low (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_alt_acc_ir_num (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_alt_acc_ir_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID sel_alt_acc_all (ASN1_DEC_CTXT *aCtx); +static ST_VOID alt_acc_dec_done_ok (ASN1_DEC_CTXT *aCtx); +static ST_VOID inc_dest_aa (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/************************************************************************/ +/* Static internal variables, used during decode */ + +static ALT_ACC_EL *dest_aa; +static ALT_ACC_EL *end_dest_aa; + +/************************************************************************/ +/************************************************************************/ +/* ms_asn1_to_aa */ +/* Convert an ASN.1 encoded AA to an array of 'ALT_ACC_EL' */ +/* Allocates an array of 'm_max_dec_aa' elements, using chk_calloc, */ +/* does not realloc to correct size. */ +/************************************************************************/ + + +ST_RET ms_asn1_to_aa (ST_UCHAR *asn1ptr, ST_INT asn1len, ALT_ACCESS *alt_acc_out) + { +ALT_ACC_EL *dest_aa_head; +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean. */ + + S_LOCK_COMMON_RESOURCES (); + +/* Allocate the output AA array */ + dest_aa = (ALT_ACC_EL *) chk_calloc (m_max_dec_aa, sizeof (ALT_ACC_EL)); + end_dest_aa = dest_aa + (m_max_dec_aa -1); + dest_aa_head = dest_aa; + +/* Set up ASN.1 decode tools */ + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* select tag method */ + aCtx->asn1r_decode_done_fun = asn1r_done_err;/* not legal to be done at this time */ + aCtx->asn1r_err_fun = NULL; + +/* We are using an alternate entry point into the ASN.1 decode, where */ +/* the outer tag is not required. */ + + add_alt_acc_tags (aCtx); + aCtx->asn1r_c_done_fun[0] = NULL; + aCtx->asn1r_decode_done_fun = alt_acc_dec_done_ok; + asn1r_decode_asn1_seq (aCtx, asn1ptr, asn1len); /* decode ASN.1 'Data' entity */ + + if (aCtx->asn1r_pdu_dec_err != NO_DECODE_ERR) /* check for sucess or return error */ + { + chk_free (dest_aa_head); + MLOG_NERR0 ("ASN.1 to AA Decode Error"); + S_UNLOCK_COMMON_RESOURCES (); + return (MVE_DATA_CONVERT); + } + + alt_acc_out->aa = dest_aa_head; + alt_acc_out->num_aa = dest_aa - dest_aa_head; + +/* Log the alternate access, if selected */ + if (mms_debug_sel & MMS_LOG_AA) + ms_log_alt_access (alt_acc_out); + +/* save the high water mark */ + if (alt_acc_out->num_aa > m_hw_dec_aa) + m_hw_dec_aa = alt_acc_out->num_aa; + + S_UNLOCK_COMMON_RESOURCES (); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* alt_acc_seq_start */ +/* This function is called whe the outer UNI SEQ constructor of the */ +/* AlternateAcess is found. Used only for continuing the decode for a */ +/* nested AA spec, as the outer constructor is stripped */ +/************************************************************************/ + +static ST_VOID alt_acc_seq_start (ASN1_DEC_CTXT *aCtx) + { + add_alt_acc_tags (aCtx); + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = alt_acc_seq_cstr_done; + } + + +/************************************************************************/ +/* alt_acc_seq_cstr_done */ +/************************************************************************/ + +static ST_VOID alt_acc_seq_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("alt_acc_seq_cstr_done"); + } + +/************************************************************************/ +/************************************************************************/ +/* add_alt_acc_tags */ +/* Add appropriate tags for the outer 'AlternateAccess' */ +/************************************************************************/ + +static ST_VOID add_alt_acc_tags (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, sel_alt_acc); + ASN1R_TAG_ADD (aCtx, CTX, 1, sel_acc_comp); + ASN1R_TAG_ADD (aCtx, CTX, 2, sel_acc_index); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, sel_acc_index_range); + ASN1R_TAG_ADD (aCtx, CTX, 4, sel_acc_all); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, named_start); + } + +/************************************************************************/ +/* named_start */ +/* Constructor for the 'named' element of the 'AlternateAccess' */ +/************************************************************************/ + +static ST_VOID named_start (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("named_start"); + ASN1R_TAG_ADD (aCtx, CTX, 0, get_component_name); + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = named_cstr_done; + } + +/************************************************************************/ +/* get_component_name */ +/* The 'componentName' element of the 'named' element */ +/************************************************************************/ + +static ST_VOID get_component_name (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_component_name"); + if (asn1r_get_identifier (aCtx, dest_aa->comp_name)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + dest_aa->comp_name_pres = SD_TRUE; + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, sel_alt_acc); + ASN1R_TAG_ADD (aCtx, CTX, 1, sel_acc_comp); + ASN1R_TAG_ADD (aCtx, CTX, 2, sel_acc_index); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, sel_acc_index_range); + ASN1R_TAG_ADD (aCtx, CTX, 4, sel_acc_all); + } + } + +/************************************************************************/ +/* named_cstr_done */ +/* End of 'named' constructor */ +/************************************************************************/ + +static ST_VOID named_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("named_cstr_done"); + add_alt_acc_tags (aCtx); + } + + +/************************************************************************/ +/* sel_acc_comp */ +/* The 'component' of the 'selectAccess' has been encountered */ +/************************************************************************/ + +static ST_VOID sel_acc_comp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_acc_comp"); + if (asn1r_get_identifier (aCtx, dest_aa->u.component)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + dest_aa->sel_type = AA_COMP; + inc_dest_aa (aCtx); + add_alt_acc_tags (aCtx); + } + } + +/************************************************************************/ +/* sel_acc_index */ +/* The 'index' of the 'selectAccess' has been encountered */ +/************************************************************************/ + +static ST_VOID sel_acc_index (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_acc_index"); + if (asn1r_get_u32 (aCtx, &dest_aa->u.index)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + dest_aa->sel_type = AA_INDEX; + inc_dest_aa (aCtx); + add_alt_acc_tags (aCtx); + } + } + +/************************************************************************/ +/* sel_acc_index_range */ +/* The 'indexRange' of the 'selectAccess' has been encountered */ +/************************************************************************/ + +static ST_VOID sel_acc_index_range (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_acc_index_range"); + + dest_aa->sel_type = AA_INDEX_RANGE; + ASN1R_TAG_ADD (aCtx, CTX,0, sel_acc_ir_low); + } + + +/************************************************************************/ +/* sel_acc_ir_low */ +/* The 'low_index' of the 'indexRange' has been encountered */ +/************************************************************************/ + +static ST_VOID sel_acc_ir_low (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_acc_ir_low"); + if (asn1r_get_u32 (aCtx, &dest_aa->u.ir.low_index)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + ASN1R_TAG_ADD (aCtx, CTX, 1, sel_acc_ir_num); + } + } + +/************************************************************************/ +/* sel_acc_ir_num */ +/* The 'numberOfElements' of the 'indexRange' has been encountered */ +/************************************************************************/ + +static ST_VOID sel_acc_ir_num (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_acc_ir_num"); + if (asn1r_get_u32 (aCtx, &dest_aa->u.ir.num_elmnts)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = sel_acc_ir_cstr_done; + } + } + +/************************************************************************/ +/* sel_acc_ir_cstr_done */ +/* End of the 'indexRange' constructor */ +/************************************************************************/ + +static ST_VOID sel_acc_ir_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_acc_ir_cstr_done"); + inc_dest_aa (aCtx); + add_alt_acc_tags (aCtx); + } + + +/************************************************************************/ +/* sel_acc_all */ +/* The 'allElements' of the 'selectAccess' has been encountered */ +/************************************************************************/ + +static ST_VOID sel_acc_all (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_acc_all"); + dest_aa->sel_type = AA_ALL; + inc_dest_aa (aCtx); + add_alt_acc_tags (aCtx); + } + + +/************************************************************************/ +/************************************************************************/ +/* sel_alt_acc */ +/* The 'selectAlternateAccess' constructor has been encountered */ +/************************************************************************/ + +static ST_VOID sel_alt_acc (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_alt_acc"); + + ASN1R_TAG_ADD (aCtx, CTX, 0, sel_alt_acc_comp); + ASN1R_TAG_ADD (aCtx, CTX, 1, sel_alt_acc_index); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, sel_alt_acc_index_range); + ASN1R_TAG_ADD (aCtx, CTX, 3, sel_alt_acc_all); + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = sel_alt_acc_cstr_done; + } + + +/************************************************************************/ +/* sel_alt_acc_cstr_done */ +/* End of the 'selectAlternateAccess' constructor */ +/************************************************************************/ + +static ST_VOID sel_alt_acc_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_alt_acc_cstr_done"); + dest_aa->sel_type = AA_END_NEST; + inc_dest_aa (aCtx); + add_alt_acc_tags (aCtx); + } + +/************************************************************************/ +/* sel_alt_acc_comp */ +/* The 'component' of the 'selectAlternateAccesss' has been encountered */ +/************************************************************************/ + +static ST_VOID sel_alt_acc_comp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_alt_acc_comp"); + if (asn1r_get_identifier (aCtx, dest_aa->u.component)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + dest_aa->sel_type = AA_COMP_NEST; + inc_dest_aa (aCtx); + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, alt_acc_seq_start); + } + } + +/************************************************************************/ +/* sel_alt_acc_index */ +/* The 'index' of the 'selectAlternateAccesss' has been encountered */ +/************************************************************************/ + +static ST_VOID sel_alt_acc_index (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_alt_acc_index"); + if (asn1r_get_u32 (aCtx, &dest_aa->u.index)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + dest_aa->sel_type = AA_INDEX_NEST; + inc_dest_aa (aCtx); + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, alt_acc_seq_start); + } + } + +/************************************************************************/ +/* sel_alt_acc_index_range */ +/* The 'indexRange' of 'selectAlternateAccesss' has been encountered */ +/************************************************************************/ + +static ST_VOID sel_alt_acc_index_range (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_alt_acc_index_range"); + dest_aa->sel_type = AA_INDEX_RANGE_NEST; + ASN1R_TAG_ADD (aCtx, CTX,0, sel_alt_acc_ir_low); + } + + +/************************************************************************/ +/* sel_alt_acc_ir_low */ +/* The 'low_index' of the 'indexRange' has been encountered */ +/************************************************************************/ + +static ST_VOID sel_alt_acc_ir_low (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_alt_acc_ir_low"); + if (asn1r_get_u32 (aCtx, &dest_aa->u.ir.low_index)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + ASN1R_TAG_ADD (aCtx, CTX, 1, sel_alt_acc_ir_num); + } + } + +/************************************************************************/ +/* sel_alt_acc_ir_num */ +/* The 'numberOfElements' of the 'indexRange' has been encountered */ +/************************************************************************/ + +static ST_VOID sel_alt_acc_ir_num (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_alt_acc_ir_num"); + if (asn1r_get_u32 (aCtx, &dest_aa->u.ir.num_elmnts)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = sel_alt_acc_ir_cstr_done; + } + } + +/************************************************************************/ +/* sel_alt_acc_ir_cstr_done */ +/* End of the 'indexRange' constructor */ +/************************************************************************/ + +static ST_VOID sel_alt_acc_ir_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_alt_acc_ir_cstr_done"); + inc_dest_aa (aCtx); + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, alt_acc_seq_start); + } + + +/************************************************************************/ +/* sel_alt_acc_all */ +/* The 'allElements' of 'selectAlternateAccesss' has been encountered */ +/************************************************************************/ + +static ST_VOID sel_alt_acc_all (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sel_alt_acc_all"); + dest_aa->sel_type = AA_ALL_NEST; + inc_dest_aa (aCtx); + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, alt_acc_seq_start); + } + + +/************************************************************************/ +/* inc_dest_aa */ +/* Increment the destination AA pointer, verify no overrun */ +/************************************************************************/ + +static ST_VOID inc_dest_aa (ASN1_DEC_CTXT *aCtx) + { + if (++dest_aa > end_dest_aa) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + } + +/************************************************************************/ +/* alt_acc_dec_done_ok */ +/* 'decode done fun' for the ASN.1 to AA decode */ +/************************************************************************/ + +static ST_VOID alt_acc_dec_done_ok (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("alt_dec_done_ok"); + } + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* ms_aa_to_asn1 */ +/* Encode Alternate Access, assume that the encode tools have been */ +/* initalized */ +/* NOTE: The higher level function "ms_aa_to_asn1_2" is more convenient.*/ +/* Call this directly only if "AA" encode is in the middle of a */ +/* larger encode. */ +/************************************************************************/ + +static ST_INT encodeDone; + +ST_RET ms_aa_to_asn1 (ASN1_ENC_CTXT *aCtx, ALT_ACCESS *alt_acc) + { +ALT_ACC_EL *aa; +ALT_ACC_EL *last_aa; +ST_RET ret; + + S_LOCK_COMMON_RESOURCES (); + aa = alt_acc->aa; + last_aa = aa; /* save pointer to aa[0] */ + aa += (alt_acc->num_aa-1); /* go from bottom to top */ + +/* Write the AlternateAccess 'Seq Of Choice' elements until we have */ +/* gone through all AA elements */ + ret = SD_SUCCESS; + encodeDone = SD_FALSE; + while (!encodeDone && ret == SD_SUCCESS) + { + if (aa == last_aa) + encodeDone = SD_TRUE; + ret = wr_altAcc (aCtx, &aa, last_aa); + } + +/* Verify no asn.1 encode buffer overrun */ + if (aCtx->asn1r_encode_overrun) + { + MLOG_NERR0 ("AA to ASN.1 : buffer overrun"); + ret = ME_ASN1_ENCODE_OVERRUN; + } + + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +/************************************************************************/ +/* wr_altAcc */ +/************************************************************************/ + +/* NOTE : This function is entered recursively to encode parts of the */ +/* AlternateAccess */ + +static ST_RET wr_altAcc (ASN1_ENC_CTXT *aCtx, ALT_ACC_EL **aap, ALT_ACC_EL *last_aa) + { +ALT_ACC_EL *aa; +ALT_ACC_EL *aa_start_nest; +ST_RET ret; + +/* get a working pointer */ + aa = *aap; + +/* Write the AlternateAccess sequence of choice element */ + +/* First need to see if this is the start of a named component, so */ +/* we can start the constructor if so */ + +/* If this is a nested AA element, need to find the start element */ + if (aa->sel_type == AA_END_NEST) + { + aa_start_nest = find_start_aa_nest (aa, last_aa); + if (!aa_start_nest) + { + MLOG_NERR0 ("AA to ASN.1 : Bad AA"); + return (MVE_AA_SELECT); + } + + if (aa_start_nest->comp_name_pres) + asn1r_strt_constr (aCtx); /* Start 'named' seq cstr */ + } + else /* not the start of a nested */ + { + if (aa->comp_name_pres) + asn1r_strt_constr (aCtx); /* Start 'named' seq cstr */ + } + +/* OK, if this was a named component, the constructor has been started */ +/* Go ahead and write the AlternateAccessSelection element */ + + ret = wr_altAccSel (aCtx, &aa, last_aa); /* write the altAccSel */ + + *aap = aa; + return (ret); + } + + +/************************************************************************/ +/* wr_altAccSel */ +/************************************************************************/ + +/* NOTE : This function is entered recursively to encode parts of the */ +/* AlternateAccess */ + +static ST_RET wr_altAccSel (ASN1_ENC_CTXT *aCtx, ALT_ACC_EL **aap, ALT_ACC_EL *last_aa) + { +ALT_ACC_EL *aa; +ALT_ACC_EL *aa_start_nest; +ST_RET ret; + + ret = SD_SUCCESS; + aa = *aap; /* get working pointer */ + switch (aa->sel_type) + { + case AA_COMP : + asn1r_wr_vstr (aCtx, aa->u.component); + asn1r_fin_prim (aCtx, 1,CTX); + break; + + case AA_INDEX : + asn1r_wr_u32 (aCtx, aa->u.index); + asn1r_fin_prim (aCtx, 2,CTX); + break; + + case AA_INDEX_RANGE : + asn1r_strt_constr (aCtx); + asn1r_wr_u32 (aCtx, aa->u.ir.num_elmnts); + asn1r_fin_prim (aCtx, 1,CTX); + asn1r_wr_u32 (aCtx, aa->u.ir.low_index); + asn1r_fin_prim (aCtx, 0,CTX); + asn1r_fin_constr (aCtx, 3,CTX,DEF); + break; + + case AA_ALL : + asn1r_fin_prim (aCtx, 4,CTX); + break; + + case AA_END_NEST : + + /* First we need to find the NEST START element so that we can */ + /* encode all elements on this level before returning, so that we */ + /* can add the outer constructor */ + + aa_start_nest = find_start_aa_nest (aa, last_aa); + if (!aa_start_nest) + { + MLOG_NERR0 ("AA to ASN.1 : Bad AA"); + return (MVE_AA_SELECT); + } + + asn1r_strt_constr (aCtx); /* Start SelectAlternateAccess constructor */ + asn1r_strt_constr (aCtx); /* Start outer AlternateAccess constructor */ + --aa; /* Begin with next element */ + while (aa != aa_start_nest) + { + ret = wr_altAcc (aCtx, &aa, last_aa); /* wr_altAcc will decrement aa */ + if (aa == last_aa) + encodeDone = SD_TRUE; + + if (ret != SD_SUCCESS) + return (ret); + } + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* Outer AlternateAccess cstr */ + + /* Now write the accessSelection */ + switch (aa->sel_type) + { + case AA_COMP_NEST : + asn1r_wr_vstr (aCtx, aa->u.component); + asn1r_fin_prim (aCtx, 0,CTX); + break; + + case AA_INDEX_NEST : + asn1r_wr_u32 (aCtx, aa->u.index); + asn1r_fin_prim (aCtx, 1,CTX); + break; + + case AA_INDEX_RANGE_NEST : + asn1r_strt_constr (aCtx); + asn1r_wr_u32 (aCtx, aa->u.ir.num_elmnts); + asn1r_fin_prim (aCtx, 1,CTX); + asn1r_wr_u32 (aCtx, aa->u.ir.low_index); + asn1r_fin_prim (aCtx, 0,CTX); + asn1r_fin_constr (aCtx, 2,CTX,DEF); + break; + + case AA_ALL_NEST : + asn1r_fin_prim (aCtx, 3,CTX); + break; + } + + /* Finish the accessSelection constructor */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); + break; + + /* These should never be encountered at this level */ + case AA_COMP_NEST : + case AA_INDEX_NEST : + case AA_INDEX_RANGE_NEST : + case AA_ALL_NEST : + default : + MLOG_NERR0 ("AA to ASN.1 : Bad AA sel_type value"); + return SD_FAILURE; + break; + } + + +/* For the elements that are not 'end nest', add the 'named' element */ +/* as required */ + + if (aa->sel_type != AA_END_NEST) + { + if (aa->comp_name_pres) + { + asn1r_wr_vstr (aCtx, aa->comp_name); /* Write the name */ + asn1r_fin_prim (aCtx, 0,CTX); + asn1r_fin_constr (aCtx, 5,CTX,DEF); /* Finish the 'named' cstr */ + } + } + + if (aa > last_aa) + --aa; + *aap = aa; + return (ret); + } + + +/************************************************************************/ +/* find_start_aa_nest */ +/************************************************************************/ + +static ALT_ACC_EL *find_start_aa_nest (ALT_ACC_EL *aa, + ALT_ACC_EL *last_aa) + { +ALT_ACC_EL *aa2; +ST_INT nest; + + aa2 = aa-1; /* Start with the element above */ + nest = 0; /* keep track of nesting level */ + while (SD_TRUE) + { + if (aa2->sel_type == AA_COMP_NEST || + aa2->sel_type == AA_INDEX_NEST || + aa2->sel_type == AA_INDEX_RANGE_NEST || + aa2->sel_type == AA_ALL_NEST) + { + if (nest == 0) /* we found the matching start nest */ + break; + + --nest; /* point to the next above element */ + if (nest < 0) /* sanity check - users make this tbl */ + { + return (NULL); + } + } + else /* not a start nest element, check to */ + { /* see if we are nesting further */ + if (aa2->sel_type == AA_END_NEST) + nest++; + } + + /* OK, we did not find the start element for the end nest, look */ + /* some more */ + if (aa2 == last_aa) /* sanity check - users make this tbl */ + { + MLOG_NERR0 ("AA to ASN.1 : Bad AA"); + return (NULL); + } + --aa2; + } + return (aa2); + } + +/************************************************************************/ +/* ms_log_alt_access */ +/************************************************************************/ + +ST_VOID ms_log_alt_access (ALT_ACCESS *alt_acc) + { +#ifdef DEBUG_SISCO +ALT_ACC_EL *aa; +ST_INT num_aa; +ST_INT i; +ST_INT indent; +/* Use these strings to keep logging aligned and indented as desired */ +#define MAX_INDENT 5 +SD_CONST ST_CHAR *sp[MAX_INDENT] = + { + " ", + " ", + " ", + " ", + " ", + }; +SD_CONST ST_CHAR *sp2[MAX_INDENT] = + { + " ", + " ", + " ", + " ", + "", + }; + + S_LOCK_COMMON_RESOURCES (); + aa = alt_acc->aa; + num_aa = alt_acc->num_aa; + indent = 0; + MLOG_ALWAYS1 ("Alternate Access : %d elements", num_aa); + + for (i = 0; i < num_aa; ++i, ++aa) + { + if (aa->comp_name_pres) + { + MLOG_CALWAYS3 ("%sNamed %s: %s", + sp[indent], + sp2[indent], + aa->comp_name); + } + + switch (aa->sel_type) + { + case AA_COMP : + MLOG_CALWAYS3 ("%sComp %s: %s", + sp[indent], + sp2[indent], + aa->u.component); + break; + case AA_INDEX : + MLOG_CALWAYS3 ("%sIndex %s: %ld", + sp[indent], + sp2[indent], + aa->u.index); + if (--indent < 0) + indent++; + break; + case AA_INDEX_RANGE : + MLOG_CALWAYS4 ("%sIndex Range%s: Low = %ld, Num = %ld", + sp[indent], + sp2[indent], + aa->u.ir.low_index, + aa->u.ir.num_elmnts); + if (--indent < 0) + indent++; + break; + case AA_ALL : + MLOG_CALWAYS2 ("%sAll %s:", + sp[indent], + sp2[indent]); + if (--indent < 0) + indent++; + break; + case AA_ALL_NEST : + MLOG_CALWAYS2 ("%sAll Nest %s:", + sp[indent], + sp2[indent]); + if (++indent >= MAX_INDENT) + indent--; + break; + case AA_COMP_NEST : + MLOG_CALWAYS3 ("%sComp Nest %s: %s", + sp[indent], + sp2[indent], + aa->u.component); + if (++indent >= MAX_INDENT) + indent--; + break; + case AA_INDEX_NEST : + MLOG_CALWAYS3 ("%sIndex Nest %s: %ld", + sp[indent], + sp2[indent], + aa->u.index); + if (++indent >= MAX_INDENT) + indent--; + break; + case AA_INDEX_RANGE_NEST : + MLOG_CALWAYS4 ("%sRange Nest %s: Low = %ld, Num = %ld", + sp[indent], + sp2[indent], + aa->u.ir.low_index, + aa->u.ir.num_elmnts); + if (++indent >= MAX_INDENT) + indent--; + break; + case AA_END_NEST : + MLOG_CALWAYS2 ("%sEnd Nest %s:", + sp[indent], + sp2[indent]); + if (--indent < 0) + indent++; + break; + + default : /* should not be any other tag */ + MLOG_CALWAYS1 (" **** UNKNOWN ELEMENT %02d ",i); + break; + } + } + S_UNLOCK_COMMON_RESOURCES (); +#endif + } + +/************************************************************************/ +/* ms_aa_to_asn1_2 */ +/************************************************************************/ +ST_RET ms_aa_to_asn1_2 (ALT_ACCESS *alt_acc, /* info to be encoded */ + ST_UCHAR *buf_ptr, /* buffer in which to encode */ + ST_INT buf_len, /* buffer length */ + ST_UCHAR **asn1_ptr_out, /* ptr to ptr to encoded data */ + ST_INT *asn1_len_out) /* ptr to encoded length */ + { +ASN1_ENC_CTXT aCtx; +ST_RET retcode; + + asn1r_strt_asn1_bld (&aCtx, buf_ptr, buf_len); /* start build*/ + retcode = ms_aa_to_asn1 (&aCtx, alt_acc); + if (retcode == SD_SUCCESS) + { + *asn1_ptr_out = ASN1_ENC_PTR(&aCtx); + *asn1_len_out = ASN1_ENC_LEN(&aCtx); + } + return (retcode); + } diff --git a/mmslib/mmsl/mms_aref.c b/mmslib/mmsl/mms_aref.c new file mode 100644 index 0000000..ff7c238 --- /dev/null +++ b/mmslib/mmsl/mms_aref.c @@ -0,0 +1,390 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_aref.c */ +/* PRODUCT(S) : MMS-EASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains functions for encoding and decoding and the */ +/* general manipulation of Application References. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/04/05 EJV 07 MMSEASE: needs suicscse.h. */ +/* 02/28/05 EJV 05 Elim Linux warnings in if (a=b) */ +/* 03/28/05 JRB 05 Del suicacse header. */ +/* 03/11/04 GLB 04 Cleaned up "thisFileName" */ +/* 12/20/01 JRB 03 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 07/29/97 DSF 01 Moved some of this functionality to SUIC */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" + +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pcon.h" +#include "asn1defs.h" +#ifndef MMS_LITE +#include "suicacse.h" +#endif + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) && defined(S_MT_SUPPORT) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +static APP_REF *ar_fill_ptr; + +static ST_VOID ap_title_strt (ASN1_DEC_CTXT *aCtx); +static ST_VOID ap_invoke_strt (ASN1_DEC_CTXT *aCtx); +static ST_VOID ae_qual_strt (ASN1_DEC_CTXT *aCtx); +static ST_VOID ae_invoke_strt (ASN1_DEC_CTXT *aCtx); +static ST_VOID ar_ref_asn1_decode_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID ae_invoke_get (ASN1_DEC_CTXT *aCtx); +static ST_VOID ae_qual_cnstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID ae_qual_get (ASN1_DEC_CTXT *aCtx); +static ST_VOID ap_invoke_cnstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID ap_invoke_get (ASN1_DEC_CTXT *aCtx); +static ST_VOID ap_cnstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID ap_title_get (ASN1_DEC_CTXT *aCtx); +static ST_VOID ar_cnstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID ar_ref_strt (ASN1_DEC_CTXT *aCtx); + +/**************************************************************************/ +/* ms_appref_to_asn1 */ +/* Function to convert from an intermediate for of an ApplicationReference*/ +/* to ASN.1. Function only supports FORM_2 of and ApplicationReference */ +/**************************************************************************/ + +ST_RET ms_appref_to_asn1 (APP_REF *ar_ref_ptr, ST_UCHAR *build_buf_ptr, + ST_INT build_buf_len, ST_UCHAR **ret_ptr, + ST_INT *ret_len) + { +ST_INT ret_val; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + S_LOCK_COMMON_RESOURCES (); + if (ar_ref_ptr->form == APP_REF_FORM2) + { + asn1r_strt_asn1_bld (aCtx, build_buf_ptr,build_buf_len); + asn1r_strt_constr (aCtx); + + if (ar_ref_ptr->ae_invoke_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_i32 (aCtx, ar_ref_ptr->ae_invoke); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, 3,CTX,DEF); + } + + if (ar_ref_ptr->ae_qual_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_i32 (aCtx, ar_ref_ptr->ae_qual.form_2); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, 2,CTX,DEF); + } + + if (ar_ref_ptr->ap_invoke_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_i32 (aCtx, ar_ref_ptr->ap_invoke); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, 1,CTX,DEF); + } + + if ((ar_ref_ptr->ap_title.form_2.num_comps) && + (ar_ref_ptr->ap_title_pres)) + { + asn1r_strt_constr (aCtx); + asn1r_wr_objid (aCtx, &ar_ref_ptr->ap_title.form_2.comps[0], + ar_ref_ptr->ap_title.form_2.num_comps); + asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI); + asn1r_fin_constr (aCtx, 0,CTX,DEF); + } + + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); + + *ret_ptr = aCtx->asn1r_field_ptr+1; + *ret_len = (&build_buf_ptr[build_buf_len] - aCtx->asn1r_field_ptr -1) & 0xffff; + ret_val = SD_SUCCESS; + } + else /* not form 2 */ + ret_val = MVE_BAD_APP_REF_FORM; + +/* Check for encode overrun */ + if (aCtx->asn1r_encode_overrun) + ret_val = ME_ASN1_ENCODE_OVERRUN; + + S_UNLOCK_COMMON_RESOURCES (); + return (ret_val); + } + + +/************************************************************************/ +/* DECODE FUNCTIONS FOR APPLICATION REFERENCE */ +/* ms_asn1_to_appref */ +/* Function to convert an ASN.1 encoded ApplicationReference to an */ +/* intermediate form. These decode functions only support FORM_2 */ +/************************************************************************/ + +ST_RET ms_asn1_to_appref (APP_REF *ar_ref_ptr, ST_UCHAR *buf_ptr, ST_INT buf_len) + { +ST_RET ret; +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean. */ + S_LOCK_COMMON_RESOURCES (); + ar_fill_ptr = ar_ref_ptr; + if (*buf_ptr == (CONSTR | SEQ_CODE)) + ar_fill_ptr->form = APP_REF_FORM2; + else + ar_fill_ptr->form = APP_REF_FORM1; + ar_fill_ptr->ap_title.form_2.num_comps = 0; + ar_fill_ptr->ap_invoke_pres = SD_FALSE; + ar_fill_ptr->ae_qual_pres = SD_FALSE; + ar_fill_ptr->ae_invoke_pres = SD_FALSE; + + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,ar_ref_strt); + aCtx->asn1r_decode_done_fun = asn1r_done_err; + aCtx->asn1r_err_fun = NULL; + asn1r_decode_asn1 (aCtx, buf_ptr,buf_len); + + if (aCtx->asn1r_pdu_dec_err == NO_DECODE_ERR) + ret = SD_SUCCESS; + else + ret = SD_FAILURE; + + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + + +static ST_VOID ar_ref_strt (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,ap_title_strt); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,ap_invoke_strt); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,ae_qual_strt); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,3,ae_invoke_strt); + aCtx->asn1r_decode_done_fun = ar_ref_asn1_decode_done; + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = ar_cnstr_done; + } + +static ST_VOID ar_cnstr_done (ASN1_DEC_CTXT *aCtx) + { + } + +static ST_VOID ap_title_strt (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, UNI,OBJ_ID_CODE,ap_title_get); + aCtx->asn1r_decode_done_fun = asn1r_done_err; + } + +static ST_VOID ap_title_get (ASN1_DEC_CTXT *aCtx) + { + + asn1r_get_objid (aCtx, &ar_fill_ptr->ap_title.form_2.comps[0], + &ar_fill_ptr->ap_title.form_2.num_comps); + if (ar_fill_ptr->ap_title.form_2.num_comps) + ar_fill_ptr->ap_title_pres = SD_TRUE; + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = ap_cnstr_done; + } + +static ST_VOID ap_cnstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,ap_invoke_strt); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,ae_qual_strt); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,3,ae_invoke_strt); + aCtx->asn1r_decode_done_fun = ar_ref_asn1_decode_done; + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = ar_cnstr_done; + } + +static ST_VOID ap_invoke_strt (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,ap_invoke_get); + aCtx->asn1r_decode_done_fun = asn1r_done_err; + } + +static ST_VOID ap_invoke_get (ASN1_DEC_CTXT *aCtx) + { + + if (!asn1r_get_i32 (aCtx, &ar_fill_ptr->ap_invoke)) + ar_fill_ptr->ap_invoke_pres = SD_TRUE; + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = ap_invoke_cnstr_done; + } + +static ST_VOID ap_invoke_cnstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,ae_qual_strt); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,3,ae_invoke_strt); + aCtx->asn1r_decode_done_fun = ar_ref_asn1_decode_done; + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = ar_cnstr_done; + } + +static ST_VOID ae_qual_strt (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,ae_qual_get); + aCtx->asn1r_decode_done_fun = asn1r_done_err; + } + +static ST_VOID ae_qual_get (ASN1_DEC_CTXT *aCtx) + { + + if (!asn1r_get_i32 (aCtx, &ar_fill_ptr->ae_qual.form_2)) + ar_fill_ptr->ae_qual_pres = SD_TRUE; + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = ae_qual_cnstr_done; + } + +static ST_VOID ae_qual_cnstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,3,ae_invoke_strt); + aCtx->asn1r_decode_done_fun = ar_ref_asn1_decode_done; + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = ar_cnstr_done; + } + +static ST_VOID ae_invoke_strt (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,ae_invoke_get); + aCtx->asn1r_decode_done_fun = asn1r_done_err; + } + +static ST_VOID ae_invoke_get (ASN1_DEC_CTXT *aCtx) + { + + if (!asn1r_get_i32 (aCtx, &ar_fill_ptr->ae_invoke)) + ar_fill_ptr->ae_invoke_pres = SD_TRUE; + aCtx->asn1r_decode_done_fun = ar_ref_asn1_decode_done; + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = ar_cnstr_done; + } + +static ST_VOID ar_ref_asn1_decode_done (ASN1_DEC_CTXT *aCtx) + { + } + +/************************************************************************/ +#ifndef MMS_LITE +/************************************************************************/ + +/************************************************************************/ +/* ms_arname_to_asn1 */ +/* Function to convert from an arname to the ASN.1 encoded equivalent of*/ +/* the ApplicationReference that corresponds to it. Returns SD_SUCCESS or */ +/* ERROR CODE. */ +/************************************************************************/ + +ST_RET ms_arname_to_asn1 (ST_CHAR *arname, ST_UCHAR *buf_ptr, + ST_INT buf_len, ST_UCHAR **ret_ptr_addr, + ST_INT *ret_len_addr) + { +ST_RET ret_val; +APP_REF *app_ref_ptr; + + S_LOCK_COMMON_RESOURCES (); + ret_val = MVE_DATA_CONVERT; + if (!(ret_val = ms_arname_to_appref (arname, &app_ref_ptr))) + { + ret_val = ms_appref_to_asn1(app_ref_ptr, buf_ptr, buf_len, + ret_ptr_addr, ret_len_addr); + } + S_UNLOCK_COMMON_RESOURCES (); + return (ret_val); + } + +/************************************************************************/ +/* ms_asn1_to_arname */ +/* Function to convert from an ASN.1 encoded application reference to */ +/* the arname that corresponds to it. Return SD_SUCCESS or ERROR CODE. */ +/************************************************************************/ + +ST_RET ms_asn1_to_arname (ST_CHAR *arname, ST_UCHAR *asn1_ptr, ST_INT asn1_len) + { +ST_RET ret_val; +APP_REF app_reference; + + S_LOCK_COMMON_RESOURCES (); + ret_val = MVE_ASN1_DECODE_ERR; + if (!(ret_val = ms_asn1_to_appref (&app_reference, asn1_ptr, asn1_len))) + { + ret_val = ms_appref_to_arname (arname, &app_reference); + } + S_UNLOCK_COMMON_RESOURCES (); + return (ret_val); + } + +/************************************************************************/ +/* ms_arname_to_appref */ +/* Function to convert from the C representation of an arname to the C */ +/* representation of an ApplicationReference. Returns SD_SUCCESS or */ +/* ERROR CODE. */ +/************************************************************************/ + +ST_RET ms_arname_to_appref (ST_CHAR *arname, APP_REF **appref_ptr_addr) + { +ST_RET ret_val; + + S_LOCK_COMMON_RESOURCES (); + ret_val = MVE_DATA_CONVERT; + if (arname) + { + if ((*appref_ptr_addr = s_find_proc (arname)) != NULL) + ret_val = SD_SUCCESS; + } + else + *appref_ptr_addr = NULL; + S_UNLOCK_COMMON_RESOURCES (); + return (ret_val); + } + +/************************************************************************/ +/* ms_appref_to_arname */ +/* Function to convert from the C representation of an ApplicationRef. */ +/* to the C representation of an arname. Returns SD_SUCCESS or ERROR CODE.*/ +/* The argument arname has to be a pointer to a place big enough to */ +/* hold the arname (MAX_AR_LEN+1). */ +/************************************************************************/ + +ST_RET ms_appref_to_arname (ST_CHAR *arname, APP_REF *appref_addr) + { +ST_RET ret; + + S_LOCK_COMMON_RESOURCES (); + ret = MVE_DATA_CONVERT; + if (arname && appref_addr) + { /* match the AE-Qualifier */ + if (s_find_arname (appref_addr, appref_addr->ae_qual_pres, arname)) + ret = SD_SUCCESS; + } + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +/************************************************************************/ +#endif /* end ifndef MMS_LITE */ +/************************************************************************/ diff --git a/mmslib/mmsl/mms_ced.c b/mmslib/mmsl/mms_ced.c new file mode 100644 index 0000000..678c07b --- /dev/null +++ b/mmslib/mmsl/mms_ced.c @@ -0,0 +1,265 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_ced.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains common primitive encode/decode functions. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/22/02 JRB 05 Add _ms_fin_pdu & _ms_fin_pdu_log (these */ +/* replace functionality of _ms_fin_pdu_debug). */ +/* Use new "asn1r_buf_end" instead of globals. */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 04/28/00 JRB 03 Lint cleanup */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 03/23/99 MDE 01 Changes to decode buffer allocation scheme */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "asn1defs.h" + +/************************************************************************/ +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/************************************************************************/ +/* COMPANION STANDARD INFO DECODE FUNCTIONS */ +/************************************************************************/ + +#ifdef CS_SUPPORT +static ST_VOID mms_cs_start (ASN1_DEC_CTXT *aCtx); +static ST_VOID mms_cs_cstr_done (ASN1_DEC_CTXT *aCtx); +#endif + +/************************************************************************/ +/************************************************************************/ +/* _ms_set_cs_check */ +/* This function is used to check for CS info after rest of PDU has */ +/* been decoded. */ +/************************************************************************/ + +ST_VOID _ms_set_cs_check (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_done_fun = _mms_dec_done_ok; + _ms_set_cs_check2 (aCtx); + } + +/************************************************************************/ +/* _ms_set_cs_check2 */ +/* use this function to avoid setting the aCtx->asn1r_decode_done_fun */ +/************************************************************************/ + +ST_VOID _ms_set_cs_check2 (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* need to use TAG method */ + +#ifdef CS_SUPPORT +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS only */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,79,mms_cs_start); /* need to check for CS */ +#else + if (mmsl_version) /* IS only */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,79,mms_cs_start); /* need to check for CS */ +#endif +#endif + /* in case this is cstr done */ + if (!aCtx->asn1r_msg_level) + aCtx->asn1r_c_done_fun[1] = NULL; /* OK for all to be complete */ + else /* need to go through all upper levels */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = _ms_set_cs_check2; + } + + +#ifdef CS_SUPPORT +/************************************************************************/ +/* mms_cs_start */ +/************************************************************************/ + +static ST_VOID mms_cs_start (ASN1_DEC_CTXT *aCtx) + { + _mmsdec_rslt->cs.cs_ptr = aCtx->asn1r_field_ptr; /* start of CS info */ + asn1r_set_all_cstr_done (aCtx); /* clear up all cstr done's */ + asn1r_parse_cstr_contents (aCtx, mms_cs_cstr_done); /* verify ASN.1 */ + } + +/************************************************************************/ +/* mms_cs_cstr_done */ +/************************************************************************/ + +static ST_VOID mms_cs_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _mmsdec_rslt->cs.cs_pres = SD_TRUE; /* CS info was OK */ + _mmsdec_rslt->cs.cs_len = aCtx->asn1r_field_ptr - _mmsdec_rslt->cs.cs_ptr; + aCtx->asn1r_decode_done = SD_TRUE; + } +#endif + +/************************************************************************/ +/************************************************************************/ +/* EXTERNAL decode functions */ +/************************************************************************/ +/************************************************************************/ +/* _ms_chk_for_extern */ +/************************************************************************/ +/* This function is called when adding tags when an EXTERNAL may be */ +/* encountered. Pass in the destination and the constructor done fun */ +/* Currently do not parse EXTERNAL itself, allow user to do this. */ + +static ST_VOID (*ext_done_fun)(ASN1_DEC_CTXT *aCtx); + +static ST_VOID ext_seq_start (ASN1_DEC_CTXT *aCtx); + +static ST_INT *ext_len_ptr; /* save in case EXTERNAL found */ +static ST_UCHAR **ext_buf_ptr_ptr; + +ST_VOID _ms_chk_for_extern (ASN1_DEC_CTXT *aCtx, ST_INT *len_ptr, ST_UCHAR **buf_ptr_ptr, + ST_VOID (*done_fun)(ASN1_DEC_CTXT *aCtx)) + { + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,EXTERN_CODE,ext_seq_start); /* get the EXT seq*/ + ext_done_fun = done_fun; + ext_len_ptr = len_ptr; + ext_buf_ptr_ptr = buf_ptr_ptr; + } + +/************************************************************************/ +/* ext_seq_start */ +/* External encountered */ +/************************************************************************/ + +static ST_VOID ext_seq_start (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("ext_seq_start"); + +/* save pointer and length of the external data element */ + *ext_len_ptr = aCtx->asn1r_elmnt_len + (aCtx->asn1r_field_ptr - aCtx->asn1r_field_start); + *ext_buf_ptr_ptr = aCtx->asn1r_field_start; + + asn1r_parse_cstr_contents (aCtx, ext_done_fun); + } + + +/************************************************************************/ +/************************************************************************/ +/* GENERAL DECODE FUNCTIONS */ +/************************************************************************/ +/* mms_req_not_supp */ +/************************************************************************/ + +ST_VOID mms_req_not_supp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("mms_req_not_supp"); + + if (_mmsdec_rslt->op == MMSOP_INFO_RPT || + _mmsdec_rslt->op == MMSOP_USTATUS || + _mmsdec_rslt->op == MMSOP_EVENT_NOT) + asn1r_set_dec_err (aCtx, UNCONF_UNREC_SERV); + else + asn1r_set_dec_err (aCtx, REQ_UNREC_SERV); + } + +/************************************************************************/ +/* mms_rsp_not_supp */ +/************************************************************************/ + +ST_VOID mms_rsp_not_supp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("mms_rsp_not_supp "); + + asn1r_set_dec_err (aCtx, RESP_UNREC_SERV); + } + +/************************************************************************/ +/************************************************************************/ +/* _mms_null_pdu_dec */ +/* This function is called from MMSDEC when the opcode for a NULL PDU */ +/* is being decoded. */ +/************************************************************************/ + +ST_VOID _mms_null_pdu_dec (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Decoding Null PDU (examine opcode for service)"); + + _ms_set_cs_check (aCtx); /* check to see of CS info pres */ + } + +/************************************************************************/ +/* _mms_dec_done_ok */ +/* general decode done function, used for most primitive decodes */ +/************************************************************************/ + +ST_VOID _mms_dec_done_ok (ASN1_DEC_CTXT *aCtx) + { + _mmsdec_rslt->data_pres = _mms_dec_info_pres; /* write data pres flag */ + _mmsdec_rslt->data_ptr = _mms_dec_info; /* write pointer */ + } + +/************************************************************************/ +/* _mms_dec_buf_free */ +/* error decoding the request: free allocated storage. */ +/************************************************************************/ + +ST_VOID _mms_dec_buf_free (ASN1_DEC_CTXT *aCtx, ST_RET err) + { + (*m_free_os_fun)(_mms_dec_info); + } + +/************************************************************************/ +/* _ms_fin_pdu */ +/* User passes ptr to PDU len pPduLen, this function sets (*pPduLen). */ +/* RETURNS: pointer to MMS PDU */ +/************************************************************************/ + +ST_UCHAR *_ms_fin_pdu (ASN1_ENC_CTXT *aCtx, ST_INT type, ST_INT *pPduLen) + { + asn1r_fin_constr (aCtx, (ST_INT16)type, CTX,DEF); + *pPduLen = aCtx->asn1r_buf_end - aCtx->asn1r_field_ptr; + return (aCtx->asn1r_field_ptr + 1); + } + +#ifdef DEBUG_SISCO +/************************************************************************/ +/* _ms_fin_pdu_log */ +/* Write complete MMS PDU to log. */ +/************************************************************************/ + +ST_VOID _ms_fin_pdu_log (ST_INT type, ST_CHAR *msg_ptr, + ST_UCHAR *pduPtr, ST_INT pduLen) + { +/* Do PDU Encode logging */ + if (type == MMSRESP) + { + MLOG_ENC2 ("%s Response built : len = %d",msg_ptr, pduLen); + } + else + { + MLOG_ENC2 ("%s Request built : len = %d",msg_ptr, pduLen); + } + MLOG_ENCH (pduLen,pduPtr); + + return; + } +#endif /* DEBUG_SISCO */ + diff --git a/mmslib/mmsl/mms_ced3.c b/mmslib/mmsl/mms_ced3.c new file mode 100644 index 0000000..d2afe65 --- /dev/null +++ b/mmslib/mmsl/mms_ced3.c @@ -0,0 +1,223 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_ced3.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains common primitive encode/decode functions */ +/* particular to getting and writing object names. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/02/03 MDE 04 Added log for invalid object name tag */ +/* 12/20/01 JRB 03 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 06/09/97 MDE 01 Fixed object name decode for COMPACT */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" + +#include "sysincs.h" + +#include "mmsdefs.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ + +static ST_VOID objname_get_item_id (ASN1_DEC_CTXT *aCtx); +static ST_VOID objname_get_domain_id (ASN1_DEC_CTXT *aCtx); +static ST_VOID objname_get_vmd_spec (ASN1_DEC_CTXT *aCtx); +static ST_VOID objname_dom_spec_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID objname_dom_spec_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID objname_get_aa_spec (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/* global structures & functions */ +/************************************************************************/ + +static ST_VOID (*get_mms_objname_done) (ASN1_DEC_CTXT *aCtx); + +static OBJECT_NAME *obj_ptr; + +static ST_RET _error_code; + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_mms_objname */ +/* Function to get an MMS object name from the received message. */ +/************************************************************************/ + +ST_VOID _ms_get_mms_objname (ASN1_DEC_CTXT *aCtx, OBJECT_NAME *data_ptr, ST_VOID (*done_fun) (ASN1_DEC_CTXT *aCtx)) + { + /* set decode error for request or response */ + if (_mmsdec_rslt->type == MMSRESP) + _error_code = RESP_BAD_VALUE; + else + _error_code = REQ_BAD_VALUE; + + obj_ptr = data_ptr; + get_mms_objname_done = done_fun; + + ASN1R_TAG_ADD (aCtx, CTX, 0, objname_get_vmd_spec); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, objname_dom_spec_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 2, objname_get_aa_spec); + } + +/************************************************************************/ +/* objname_get_vmd_spec */ +/* vmd-specific name was encountered. */ +/************************************************************************/ + +static ST_VOID objname_get_vmd_spec (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("objname_get_vmd_spec"); + + obj_ptr->object_tag = VMD_SPEC; /* set tag to vmd specific */ + +#if defined(USE_COMPACT_MMS_STRUCTS) + obj_ptr->obj_name.vmd_spec = (ST_CHAR *) (aCtx->asn1r_field_ptr - 1); +#endif + /* read name from message */ + if (asn1r_get_identifier (aCtx, obj_ptr->obj_name.vmd_spec)) + asn1r_set_dec_err (aCtx, _error_code); + + (*get_mms_objname_done) (aCtx); /* all done, call user set fun */ + } + +/************************************************************************/ +/* objname_dom_spec_cstr */ +/* domain specific constructor was encountered. */ +/************************************************************************/ + +static ST_VOID objname_dom_spec_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("objname_dom_spec_cstr"); + + obj_ptr->object_tag = DOM_SPEC; /* set tag to domain specific */ + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, objname_get_domain_id); + } + +/************************************************************************/ +/* objname_get_domain_id */ +/* domain id was encountered. */ +/************************************************************************/ + +static ST_VOID objname_get_domain_id (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("objname_get_domain_id"); + +#if defined(USE_COMPACT_MMS_STRUCTS) + obj_ptr->domain_id = (ST_CHAR *) (aCtx->asn1r_field_ptr - 1); +#endif + /* read name from message */ + if (asn1r_get_identifier (aCtx, obj_ptr->domain_id)) + asn1r_set_dec_err (aCtx, _error_code); + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, objname_get_item_id); + } + +/************************************************************************/ +/* objname_get_item_id */ +/* item id was encountered. */ +/************************************************************************/ + +static ST_VOID objname_get_item_id (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("objname_get_item_id"); + +#if defined(USE_COMPACT_MMS_STRUCTS) + obj_ptr->obj_name.item_id = (ST_CHAR *) (aCtx->asn1r_field_ptr - 1); +#endif + /* read name from message */ + if (asn1r_get_identifier (aCtx, obj_ptr->obj_name.item_id)) + asn1r_set_dec_err (aCtx, _error_code); + /* set constructor done fun */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = objname_dom_spec_cstr_done; + } + +/************************************************************************/ +/* objname_dom_spec_cstr_done */ +/* domain specific constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID objname_dom_spec_cstr_done (ASN1_DEC_CTXT *aCtx) + { + (*get_mms_objname_done) (aCtx); /* all done, call user set fun */ + } + +/************************************************************************/ +/* objname_get_aa_spec */ +/* aa-specific name was encountered. */ +/************************************************************************/ + +static ST_VOID objname_get_aa_spec (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("objname_get_aa_spec"); + + obj_ptr->object_tag = AA_SPEC; /* set tag to aa specific */ + +#if defined(USE_COMPACT_MMS_STRUCTS) + obj_ptr->obj_name.aa_spec = (ST_CHAR *) (aCtx->asn1r_field_ptr - 1); +#endif + /* read name from message */ + if (asn1r_get_identifier (aCtx, obj_ptr->obj_name.aa_spec)) + asn1r_set_dec_err (aCtx, _error_code); + + (*get_mms_objname_done) (aCtx); /* all done, call user set fun */ + } + +/************************************************************************/ +/************************************************************************/ +/* _ms_wr_mms_objname */ +/* Function to write an MMS object name to the message. */ +/************************************************************************/ + +ST_VOID _ms_wr_mms_objname (ASN1_ENC_CTXT *aCtx, OBJECT_NAME *data_ptr) + { + switch (data_ptr->object_tag) + { + case (VMD_SPEC) : /* write the vmd specific name */ + asn1r_wr_vstr (aCtx, data_ptr->obj_name.vmd_spec); + asn1r_fin_prim (aCtx, 0, CTX); /* context tag 0 */ + break; + + case (DOM_SPEC) : /* write domain specific name */ + asn1r_strt_constr (aCtx); + asn1r_wr_vstr (aCtx, data_ptr->obj_name.item_id); + asn1r_fin_prim (aCtx, VISTR_CODE, UNI); /* universal string */ + asn1r_wr_vstr (aCtx, data_ptr->domain_id); + asn1r_fin_prim (aCtx, VISTR_CODE, UNI); /* universal string */ + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* context tag 1 */ + break; + + case (AA_SPEC) : /* write the aa specific name */ + asn1r_wr_vstr (aCtx, data_ptr->obj_name.aa_spec); + asn1r_fin_prim (aCtx, 2,CTX); /* context tag 2 */ + break; + + default: + MLOG_NERR1 ("Invalid object_tag: %d", data_ptr->object_tag); + break; + } + } + diff --git a/mmslib/mmsl/mms_ced4.c b/mmslib/mmsl/mms_ced4.c new file mode 100644 index 0000000..773c7af --- /dev/null +++ b/mmslib/mmsl/mms_ced4.c @@ -0,0 +1,936 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_ced4.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains common primitive encode/decode functions */ +/* particular to getting and writing variables. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/09/09 JRB 04 Allow any value for DataAccessError. */ +/* 03/11/04 GLB 03 Remove "thisFileName" */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 01 Added SD_CONST modifiers */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +static ST_VOID va_spec_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID va_spec_vlist_list_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID va_spec_vlist_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID va_vlist_alt_acc_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID va_vlist_alt_acc_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID va_vlist_useq_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID va_vlist_var_spec_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID va_vlist_useq_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID va_var_spec_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID var_spec_type_spec (ASN1_DEC_CTXT *aCtx); +static ST_VOID var_spec_objname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID var_spec_address_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID var_spec_var_descr_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID var_spec_scat_acc_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID var_spec_get_null (ASN1_DEC_CTXT *aCtx); +static ST_VOID alt_access_get_aa_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID scat_access_get_sa_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID type_spec_get_tspec_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID vdata_get_data_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID access_rslt_get_data_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID access_rslt_cstr_parse (ASN1_DEC_CTXT *aCtx, ST_UINT16 id); +static ST_VOID access_rslt_get_result (ASN1_DEC_CTXT *aCtx, ST_UINT16 id); +static ST_VOID address_unc_addr_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID address_get_num_addr (ASN1_DEC_CTXT *aCtx); +static ST_VOID address_get_sym_addr (ASN1_DEC_CTXT *aCtx); +static ST_VOID address_get_unc_addr (ASN1_DEC_CTXT *aCtx); +static ST_VOID address_unc_addr_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID (*get_va_address_done) (ASN1_DEC_CTXT *aCtx); +static ST_VOID (*get_va_access_rslt_done) (ASN1_DEC_CTXT *aCtx); +static ST_VOID (*get_va_data_done) (ASN1_DEC_CTXT *aCtx); +static ST_VOID (*get_va_type_spec_done) (ASN1_DEC_CTXT *aCtx); +static ST_VOID (*get_va_scat_access_done) (ASN1_DEC_CTXT *aCtx); +static ST_VOID (*get_va_alt_access_done) (ASN1_DEC_CTXT *aCtx); +static ST_VOID (*get_va_var_spec_done) (ASN1_DEC_CTXT *aCtx); +static ST_VOID (*get_va_spec_done) (ASN1_DEC_CTXT *aCtx); +static ST_VOID var_spec_cstr_get_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID va_spec_done (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/* global structures & functions */ +/************************************************************************/ + +static VAR_ACC_ADDR *addr_ptr; +static ACCESS_RESULT *acc_rslt_ptr; +static VAR_ACC_DATA *vdata_ptr; +static VAR_ACC_TSPEC *tspec_ptr; +static SCATTERED_ACCESS *scat_acc_ptr; +static ALTERNATE_ACCESS *alt_acc_ptr; +static VARIABLE_SPEC *var_spec_ptr; +static VARIABLE_LIST *var_list_ptr; +static VAR_ACC_SPEC *va_spec_ptr; +static VARIABLE_LIST *va_spec_vlist_ptr; + +static ST_INT *NUM_OF_VARS; +static ST_INT MAX_VARS; +static ST_RET ERROR_CODE; +static ST_INT save_dec_method; + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_va_address */ +/* Function to get a variable access address from the received message. */ +/************************************************************************/ + +ST_VOID _ms_get_va_address (ASN1_DEC_CTXT *aCtx, VAR_ACC_ADDR *data_ptr, ST_VOID (*done_fun) (ASN1_DEC_CTXT *aCtx)) + { + + /* set decode error for request or response */ + if (_mmsdec_rslt->type == MMSRESP) + ERROR_CODE = RESP_BAD_VALUE; + else + ERROR_CODE = REQ_BAD_VALUE; + + addr_ptr = data_ptr; + get_va_address_done = done_fun; + + ASN1R_TAG_ADD (aCtx, CTX, 0, address_get_num_addr); + ASN1R_TAG_ADD (aCtx, CTX, 1, address_get_sym_addr); + ASN1R_TAG_ADD (aCtx, CTX, 2, address_get_unc_addr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, address_unc_addr_cstr); + } + +/************************************************************************/ +/* address_get_num_addr */ +/* numeric address was encountered. */ +/************************************************************************/ + +static ST_VOID address_get_num_addr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_num_addr"); + + addr_ptr->addr_tag = 0; /* set tag to numeric address */ + + /* read numeric address */ + if (asn1r_get_u32 (aCtx, &addr_ptr->addr.num_addr)) + asn1r_set_dec_err (aCtx, ERROR_CODE); + + (*get_va_address_done) (aCtx); /* all done, call user set fun */ + } + +/************************************************************************/ +/* address_get_sym_addr */ +/* symbolic address was encountered. */ +/************************************************************************/ + +static ST_VOID address_get_sym_addr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("address_get_sym_addr"); + + addr_ptr->addr_tag = 1; /* set tag to symbolic address */ + + /* decode symbolic address onto itself, shifted by 1 ST_CHAR */ + addr_ptr->addr.sym_addr = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + /* read symbolic address */ + if (asn1r_get_vstr (aCtx, addr_ptr->addr.sym_addr)) + asn1r_set_dec_err (aCtx, ERROR_CODE); + + (*get_va_address_done) (aCtx); /* all done, call user set fun */ + } + +/************************************************************************/ +/* address_get_unc_addr */ +/* unconstrained address primitive was encountered. */ +/************************************************************************/ + +static ST_VOID address_get_unc_addr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("address_get_unc_addr"); + + addr_ptr->addr_tag = 2; /* set tag to unconstrained */ + + /* decode unconstrained address onto itself, shifted by 1 ST_CHAR */ + addr_ptr->addr.unc_addr.unc_ptr = aCtx->asn1r_field_ptr - 1; + /* read unconstrained address */ + if (asn1r_get_octstr (aCtx, addr_ptr->addr.unc_addr.unc_ptr)) + asn1r_set_dec_err (aCtx, ERROR_CODE); + /* save the address length */ + addr_ptr->addr.unc_addr.unc_len = aCtx->asn1r_octetcount; + + (*get_va_address_done) (aCtx); /* all done, call user set fun */ + } + +/************************************************************************/ +/* address_unc_addr_cstr */ +/* unconstrained address constructor was encountered. */ +/************************************************************************/ + +static ST_VOID address_unc_addr_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("address_unc_addr_cstr"); + + addr_ptr->addr_tag = 2; /* set tag to unconstrained */ + + /* decode unconstrained address onto itself, shifted by 1 ST_CHAR */ + addr_ptr->addr.unc_addr.unc_ptr = aCtx->asn1r_field_ptr - 1; + + /* set up where to go when done decoding cstr */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = address_unc_addr_cstr_done; + + /* read unconstrained address from message */ + asn1r_get_octstr_cstr (aCtx, _mmsdec_msglen, addr_ptr->addr.unc_addr.unc_ptr); + } + +/************************************************************************/ +/* address_unc_addr_cstr_done */ +/* unconstrained address constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID address_unc_addr_cstr_done (ASN1_DEC_CTXT *aCtx) + { + /* save the address length */ + addr_ptr->addr.unc_addr.unc_len = aCtx->asn1r_octetcount; + + (*get_va_address_done) (aCtx); /* all done, call user set fun */ + } + + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_va_access_rslt */ +/* Function to get a variable access access result from the received */ +/* message. */ +/************************************************************************/ + +ST_VOID _ms_get_va_access_rslt (ASN1_DEC_CTXT *aCtx, ACCESS_RESULT *data_ptr, + ST_VOID (*done_fun) (ASN1_DEC_CTXT *aCtx)) + { + /* set decode error for request or response */ + if (_mmsdec_rslt->type == MMSRESP) + ERROR_CODE = RESP_BAD_VALUE; + else + ERROR_CODE = REQ_BAD_VALUE; + + acc_rslt_ptr = data_ptr; + get_va_access_rslt_done = done_fun; + + acc_rslt_ptr->va_data.data = aCtx->asn1r_field_ptr; /* set data pointer */ + + save_dec_method = aCtx->asn1r_decode_method; + aCtx->asn1r_decode_method = ASN1_CLASS_METHOD; + + aCtx->asn1r_c_id_fun = access_rslt_get_result; /* decode access result */ + aCtx->asn1r_u_id_fun = asn1r_class_err; /* no universals */ + aCtx->asn1r_a_id_fun = asn1r_class_err; /* no applications */ + aCtx->asn1r_p_id_fun = asn1r_class_err; /* no privates */ + } + +/************************************************************************/ +/* access_rslt_get_result */ +/* get access result. */ +/************************************************************************/ + +static ST_VOID access_rslt_get_result (ASN1_DEC_CTXT *aCtx, ST_UINT16 id) + { + MLOG_CDEC0 ("access_rslt_get_result"); + + if (aCtx->asn1r_constr_elmnt) + { /* constructor, success */ + acc_rslt_ptr->acc_rslt_tag = ACC_RSLT_SUCCESS; + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = access_rslt_get_data_done; + aCtx->asn1r_c_id_fun = access_rslt_cstr_parse; /* decode access result */ + } + else + { /* primitive */ + if (id != 0) + { /* success */ + acc_rslt_ptr->acc_rslt_tag = ACC_RSLT_SUCCESS; + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; /* move past data element */ + access_rslt_get_data_done (aCtx); + } + else + { /* failure */ + acc_rslt_ptr->acc_rslt_tag = ACC_RSLT_FAILURE; + /* read data access error */ + if (asn1r_get_i16 (aCtx, &acc_rslt_ptr->failure)) + asn1r_set_dec_err (aCtx, ERROR_CODE); + /* NOTE: DataAccessError should be [0-11] but allow any val here. */ + + aCtx->asn1r_decode_method = save_dec_method; /* restore original dec method */ + (*get_va_access_rslt_done) (aCtx); /* all done, call user set fun */ + } + } + } + +/************************************************************************/ +/* access_rslt_cstr_parse */ +/* in the middle of a result constructor, just accept the elements */ +/************************************************************************/ + +static ST_VOID access_rslt_cstr_parse (ASN1_DEC_CTXT *aCtx, ST_UINT16 id) + { + MLOG_CDEC0 ("access_rslt_cstr_parse"); + + if (!aCtx->asn1r_constr_elmnt) /* if primitive, need to move */ + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; /* aCtx->asn1r_field_ptr */ + else /* if cstr, need to set cstr */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = NULL; /* done function == safe */ + } + +/************************************************************************/ +/* access_rslt_get_data_done */ +/* variable data has been obtianed. */ +/************************************************************************/ + +static ST_VOID access_rslt_get_data_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("access_rslt_get_data_done"); + /* set the variable data length */ + acc_rslt_ptr->va_data.len = + aCtx->asn1r_field_ptr - acc_rslt_ptr->va_data.data; + + aCtx->asn1r_decode_method = save_dec_method; /* restore original dec method */ + + (*get_va_access_rslt_done) (aCtx); /* all done, call user set fun */ + } + + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_va_data */ +/* Function to get a variable access data from the received message. */ +/************************************************************************/ + +ST_VOID _ms_get_va_data (ASN1_DEC_CTXT *aCtx, VAR_ACC_DATA *data_ptr, ST_VOID (*done_fun) (ASN1_DEC_CTXT *aCtx)) + { + + vdata_ptr = data_ptr; + get_va_data_done = done_fun; + + vdata_ptr->data = aCtx->asn1r_field_ptr; /* set data pointer */ + + asn1r_parse_next (aCtx, vdata_get_data_done); /* parse entire element */ + } + +/************************************************************************/ +/* vdata_get_data_done */ +/* variable data has been parsed. */ +/************************************************************************/ + +static ST_VOID vdata_get_data_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("vdata_get_data_done"); + /* set the variable data length */ + vdata_ptr->len = aCtx->asn1r_field_ptr - vdata_ptr->data; + + (*get_va_data_done) (aCtx); /* all done, call user set fun */ + } + + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_va_type_spec */ +/* Function to get a variable access type specification from the */ +/* received message. */ +/************************************************************************/ + +ST_VOID _ms_get_va_type_spec (ASN1_DEC_CTXT *aCtx, VAR_ACC_TSPEC *data_ptr, + ST_VOID (*done_fun) (ASN1_DEC_CTXT *aCtx)) + { + + tspec_ptr = data_ptr; + get_va_type_spec_done = done_fun; + + tspec_ptr->data = aCtx->asn1r_field_ptr; /* set data pointer */ + + asn1r_parse_next (aCtx, type_spec_get_tspec_done); /* parse entire element */ + } + +/************************************************************************/ +/* type_spec_get_tspec_done */ +/* valid type specification was encountered. */ +/************************************************************************/ + +static ST_VOID type_spec_get_tspec_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("type_spec_get_tspec_done"); + /* set type specification len */ + tspec_ptr->len = aCtx->asn1r_field_ptr - tspec_ptr->data; + + (*get_va_type_spec_done) (aCtx); /* all done, call user set fun */ + } + + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_va_scat_access */ +/* Function to get a variable access scattered access from the received */ +/* message. */ +/************************************************************************/ + +ST_VOID _ms_get_va_scat_access (ASN1_DEC_CTXT *aCtx, SCATTERED_ACCESS *data_ptr, + ST_VOID (*done_fun) (ASN1_DEC_CTXT *aCtx)) + { + + scat_acc_ptr = data_ptr; + get_va_scat_access_done = done_fun; + + scat_acc_ptr->data = aCtx->asn1r_field_ptr; /* set data pointer */ + + asn1r_parse_next (aCtx, scat_access_get_sa_done); /* parse entire element */ + } + +/************************************************************************/ +/* scat_access_get_sa_done */ +/* scattered access universal sequence constructor was encountered. */ +/************************************************************************/ + +static ST_VOID scat_access_get_sa_done (ASN1_DEC_CTXT *aCtx) + { + /* set scattered access len */ + scat_acc_ptr->len = aCtx->asn1r_field_ptr - scat_acc_ptr->data; + + (*get_va_scat_access_done) (aCtx); /* all done, call user set fun */ + } + + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_va_alt_access */ +/* Function to get a variable access alternate access from the received */ +/* message. */ +/************************************************************************/ + +ST_VOID _ms_get_va_alt_access (ASN1_DEC_CTXT *aCtx, ALTERNATE_ACCESS *data_ptr, + ST_VOID (*done_fun) (ASN1_DEC_CTXT *aCtx)) + { + MLOG_CDEC0 ("_ms_get_va_alt_access"); + + alt_acc_ptr = data_ptr; + get_va_alt_access_done = done_fun; + + alt_acc_ptr->data = aCtx->asn1r_field_ptr; /* set data pointer */ + + asn1r_parse_cstr_contents (aCtx, alt_access_get_aa_done); /* parse entire element */ + } + +/************************************************************************/ +/* alt_access_get_aa_done */ +/* scattered access was encountered. */ +/************************************************************************/ + +static ST_VOID alt_access_get_aa_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("alt_access_get_aa_done"); + /* set type specification len */ + alt_acc_ptr->len = aCtx->asn1r_field_ptr - alt_acc_ptr->data; + + (*get_va_alt_access_done) (aCtx); /* all done, call user set fun */ + } + + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_va_var_spec */ +/* Function to get a variable access variable specification from the */ +/* received message. */ +/************************************************************************/ + +ST_VOID _ms_get_va_var_spec (ASN1_DEC_CTXT *aCtx, VARIABLE_SPEC *data_ptr, + ST_VOID (*done_fun) (ASN1_DEC_CTXT *aCtx)) + { + /* set decode error for request or response */ + if (_mmsdec_rslt->type == MMSRESP) + ERROR_CODE = RESP_BAD_VALUE; + else + ERROR_CODE = REQ_BAD_VALUE; + + var_spec_ptr = data_ptr; + get_va_var_spec_done = done_fun; + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, var_spec_objname_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, var_spec_address_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, var_spec_var_descr_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, var_spec_scat_acc_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 4, var_spec_get_null); + } + +/************************************************************************/ +/* var_spec_objname_cstr */ +/* variable specification object name constructor was encountered. */ +/************************************************************************/ + +static ST_VOID var_spec_objname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("var_spec_objname_cstr"); + + var_spec_ptr->var_spec_tag = 0; /* set tag to name */ + + _ms_get_mms_objname (aCtx, &var_spec_ptr->vs.name, var_spec_cstr_get_done); + } + +/************************************************************************/ +/* var_spec_address_cstr */ +/* variable specification address was encountered. */ +/************************************************************************/ + +static ST_VOID var_spec_address_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("var_spec_address_cstr"); + + var_spec_ptr->var_spec_tag = 1; /* set tag to address */ + + _ms_get_va_address (aCtx, &var_spec_ptr->vs.address, var_spec_cstr_get_done); + } + +/************************************************************************/ +/* var_spec_var_descr_cstr */ +/* variable specification variable description constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID var_spec_var_descr_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("var_spec_var_descr_cstr"); + + var_spec_ptr->var_spec_tag = 2; /* set tag to variable descr */ + + _ms_get_va_address (aCtx, &var_spec_ptr->vs.var_descr.address, var_spec_type_spec); + } + +/************************************************************************/ +/* var_spec_type_spec */ +/* variable specification address is done, get the type specification. */ +/************************************************************************/ + +static ST_VOID var_spec_type_spec (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("var_spec_type_spec"); + + _ms_get_va_type_spec (aCtx, &var_spec_ptr->vs.var_descr.type, var_spec_cstr_get_done); + } + +/************************************************************************/ +/* var_spec_scat_acc_cstr */ +/* variable specification scattered access constructor was encountered. */ +/************************************************************************/ + +static ST_VOID var_spec_scat_acc_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("var_spec_scat_acc_cstr"); + + var_spec_ptr->var_spec_tag = 3; /* set tag to scattered access */ + + _ms_get_va_scat_access (aCtx, &var_spec_ptr->vs.sa_descr, var_spec_cstr_get_done); + } + +/************************************************************************/ +/* var_spec_get_null */ +/* variable specification null was encountered. */ +/************************************************************************/ + +static ST_VOID var_spec_get_null (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("var_spec_get_null"); + + var_spec_ptr->var_spec_tag = 4; /* set tag to variable descr */ + + if (aCtx->asn1r_elmnt_len != 0) + { + asn1r_set_dec_err (aCtx, ERROR_CODE); + return; + } + + (*get_va_var_spec_done) (aCtx); /* all done, call user set fun */ + } + +/************************************************************************/ +/* var_spec_cstr_get_done */ +/* variable specification object name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID var_spec_cstr_get_done (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = va_var_spec_done; + } + +/************************************************************************/ +/* va_var_spec_done */ +/* variable specification has been obtained, return to set-up function. */ +/************************************************************************/ + +static ST_VOID va_var_spec_done (ASN1_DEC_CTXT *aCtx) + { + (*get_va_var_spec_done) (aCtx); /* all done, call user set fun */ + } + + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_va_var_list */ +/* Function to get a variable access variable list from the received */ +/* message. */ +/************************************************************************/ + +ST_VOID _ms_get_va_var_list (ASN1_DEC_CTXT *aCtx, VARIABLE_LIST *data_ptr, ST_INT *num_of_vars, + ST_INT max_vars, ST_VOID (*done_fun) (ASN1_DEC_CTXT *aCtx)) + { + /* set decode error for request or response */ + if (_mmsdec_rslt->type == MMSRESP) + ERROR_CODE = RESP_BAD_VALUE; + else + ERROR_CODE = REQ_BAD_VALUE; + + var_list_ptr = data_ptr; + NUM_OF_VARS = num_of_vars; + MAX_VARS = max_vars; + *NUM_OF_VARS = 0; /* initialize # of variables */ + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, va_vlist_useq_cstr); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = done_fun; /* can be empty list */ + } + +/************************************************************************/ +/* va_vlist_useq_cstr */ +/* variable access variable list universal sequence was encountered. */ +/************************************************************************/ + +static ST_VOID va_vlist_useq_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("va_vlist_useq_cstr"); + + (*NUM_OF_VARS)++; /* increment # of variables */ + if (*NUM_OF_VARS > MAX_VARS) + asn1r_set_dec_err (aCtx, ERROR_CODE); + + var_list_ptr->alt_access_pres = SD_FALSE; + + _ms_get_va_var_spec (aCtx, &var_list_ptr->var_spec, va_vlist_var_spec_done); + } + +/************************************************************************/ +/* va_vlist_var_spec_done */ +/* variable access variable specification done, get alternate access. */ +/************************************************************************/ + +static ST_VOID va_vlist_var_spec_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("va_vlist_var_spec_done"); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, va_vlist_alt_acc_cstr); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = va_vlist_useq_cstr_done; + } + +/************************************************************************/ +/* va_vlist_alt_acc_cstr */ +/* variable access variable list alternate access constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID va_vlist_alt_acc_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("va_vlist_alt_acc_cstr"); + + var_list_ptr->alt_access_pres = SD_TRUE; /* set alternate access present */ + + _ms_get_va_alt_access (aCtx, &var_list_ptr->alt_access, va_vlist_alt_acc_done); + } + +/************************************************************************/ +/* va_vlist_alt_acc_done */ +/* variable specification alternate access has been obtained. */ +/************************************************************************/ + +static ST_VOID va_vlist_alt_acc_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("va_vlist_alt_acc_done"); + } + + +/************************************************************************/ +/* va_vlist_useq_cstr_done */ +/* variable access variable list universal sequence constructor done */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID va_vlist_useq_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("va_vlist_useq_cstr_done"); + var_list_ptr++; /* point to where next will go */ + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, va_vlist_useq_cstr); + } + + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_va_spec */ +/* Function to get a variable access specification from the received */ +/* message. */ +/************************************************************************/ + +ST_VOID _ms_get_va_spec (ASN1_DEC_CTXT *aCtx, VAR_ACC_SPEC *data_ptr, ST_INT max_vars, + ST_VOID (*done_fun) (ASN1_DEC_CTXT *aCtx)) + { + + /* set decode error for request or response */ + if (_mmsdec_rslt->type == MMSRESP) + ERROR_CODE = RESP_BAD_VALUE; + else + ERROR_CODE = REQ_BAD_VALUE; + + va_spec_ptr = data_ptr; + va_spec_vlist_ptr = (VARIABLE_LIST *) (va_spec_ptr + 1); + MAX_VARS = max_vars; + get_va_spec_done = done_fun; + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, va_spec_vlist_list_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, va_spec_vlist_name_cstr); + } + +/************************************************************************/ +/* va_spec_vlist_list_cstr */ +/* variable access specification list of variables constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID va_spec_vlist_list_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("va_spec_vlist_list_cstr"); + + va_spec_ptr->var_acc_tag = 0; /* set tag to list of variables */ + + _ms_get_va_var_list (aCtx, va_spec_vlist_ptr, &va_spec_ptr->num_of_variables, + MAX_VARS, va_spec_done); + } + +/************************************************************************/ +/* va_spec_vlist_name_cstr */ +/* variable access specification variable list name constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID va_spec_vlist_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("va_spec_vlist_name_cstr"); + + va_spec_ptr->var_acc_tag = 1; /* set tag to var list name */ + + _ms_get_mms_objname (aCtx, &va_spec_ptr->vl_name, va_spec_objname_done); + } + +/************************************************************************/ +/* va_spec_objname_done */ +/* variable access specification variable list object name is complete. */ +/************************************************************************/ + +static ST_VOID va_spec_objname_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = va_spec_done; + } + +/************************************************************************/ +/* va_spec_done */ +/* variable access specification has been obtained, return to set-up */ +/* function. */ +/************************************************************************/ + +static ST_VOID va_spec_done (ASN1_DEC_CTXT *aCtx) + { + (*get_va_spec_done) (aCtx); /* all done, call user set fun */ + } + +/************************************************************************/ +/************************************************************************/ +/* _ms_wr_va_address */ +/* Function to write a variable access address to the message. */ +/************************************************************************/ + +ST_VOID _ms_wr_va_address (ASN1_ENC_CTXT *aCtx, VAR_ACC_ADDR *data_ptr) + { + switch (data_ptr->addr_tag) + { + case (0) : /* write the numeric address */ + asn1r_wr_u32 (aCtx, data_ptr->addr.num_addr); + asn1r_fin_prim (aCtx, 0, CTX); /* context tag 0 */ + break; + + case (1) : /* write the symbolic address */ + asn1r_wr_vstr (aCtx, data_ptr->addr.sym_addr); + asn1r_fin_prim (aCtx, 1,CTX); /* context tag 1 */ + break; + + case (2) : /* write the unconstrained addr */ + asn1r_wr_octstr (aCtx, data_ptr->addr.unc_addr.unc_ptr, + data_ptr->addr.unc_addr.unc_len); + asn1r_fin_prim (aCtx, 2,CTX); /* context tag 2 */ + break; + } + } + +/************************************************************************/ +/* _ms_wr_va_access_rslt */ +/* Function to write a variable access access result to the message. */ +/************************************************************************/ + +ST_VOID _ms_wr_va_access_rslt (ASN1_ENC_CTXT *aCtx, ACCESS_RESULT *data_ptr) + { + if (data_ptr->acc_rslt_tag == ACC_RSLT_SUCCESS) + _ms_wr_va_data (aCtx, &data_ptr->va_data); /* success, write data */ + else + { /* failure, write failure value */ + asn1r_wr_i16 (aCtx, data_ptr->failure); + asn1r_fin_prim (aCtx, 0, CTX); /* context tag 0 */ + } + } + +/************************************************************************/ +/* _ms_wr_va_data */ +/* Function to write a variable access data to the message. */ +/************************************************************************/ + +ST_VOID _ms_wr_va_data (ASN1_ENC_CTXT *aCtx, VAR_ACC_DATA *data_ptr) + { + asn1r_wr_delmnt (aCtx, data_ptr->data, data_ptr->len); + } + +/************************************************************************/ +/* _ms_wr_va_type_spec */ +/* Function to write a variable access type specification to the */ +/* message. */ +/************************************************************************/ + +ST_VOID _ms_wr_va_type_spec (ASN1_ENC_CTXT *aCtx, VAR_ACC_TSPEC *data_ptr) + { + asn1r_wr_delmnt (aCtx, data_ptr->data, data_ptr->len); + } + +/************************************************************************/ +/* _ms_wr_va_scat_access */ +/* Function to write a variable access scattered access to the message. */ +/************************************************************************/ + +ST_VOID _ms_wr_va_scat_access (ASN1_ENC_CTXT *aCtx, SCATTERED_ACCESS *data_ptr) + { + asn1r_wr_delmnt (aCtx, data_ptr->data, data_ptr->len); + } + +/************************************************************************/ +/* _ms_wr_va_alt_access */ +/* Function to write a variable access alternate access to the message. */ +/************************************************************************/ + +ST_VOID _ms_wr_va_alt_access (ASN1_ENC_CTXT *aCtx, ALTERNATE_ACCESS *data_ptr) + { + asn1r_wr_delmnt (aCtx, data_ptr->data, data_ptr->len); + } + +/************************************************************************/ +/* _ms_wr_va_var_spec */ +/* Function to write a variable access variable specification to the */ +/* message. */ +/************************************************************************/ + +ST_VOID _ms_wr_va_var_spec (ASN1_ENC_CTXT *aCtx, VARIABLE_SPEC *data_ptr) + { + switch (data_ptr->var_spec_tag) + { + case 0 : + asn1r_strt_constr (aCtx); + _ms_wr_mms_objname (aCtx, &data_ptr->vs.name); + asn1r_fin_constr (aCtx, 0, CTX, DEF); + break; + + case 1 : + asn1r_strt_constr (aCtx); + _ms_wr_va_address (aCtx, &data_ptr->vs.address); + asn1r_fin_constr (aCtx, 1, CTX, DEF); + break; + + case 2 : + asn1r_strt_constr (aCtx); + _ms_wr_va_type_spec (aCtx, &data_ptr->vs.var_descr.type); + _ms_wr_va_address (aCtx, &data_ptr->vs.var_descr.address); + asn1r_fin_constr (aCtx, 2, CTX, DEF); + break; + + case 3 : + asn1r_strt_constr (aCtx); + _ms_wr_va_scat_access (aCtx, &data_ptr->vs.sa_descr); + asn1r_fin_constr (aCtx, 3, CTX, DEF); + break; + + case 4 : + asn1r_fin_prim (aCtx, 4, CTX); + break; + } + } + +/************************************************************************/ +/* _ms_wr_va_var_list */ +/* Function to write a variable access variable list to the message. */ +/************************************************************************/ + +ST_VOID _ms_wr_va_var_list (ASN1_ENC_CTXT *aCtx, VARIABLE_LIST *data_ptr, ST_INT num_of_vars) + { +VARIABLE_LIST *vl_ptr; +ST_INT i; + + vl_ptr = data_ptr; + vl_ptr += num_of_vars - 1; /* point to last in the list */ + for (i = 0; i < num_of_vars; i++) + { + asn1r_strt_constr (aCtx); /* start universal sequece cstr */ + if (vl_ptr->alt_access_pres) + { + asn1r_strt_constr (aCtx); /* start context tag 5 cstr */ + _ms_wr_va_alt_access (aCtx, &vl_ptr->alt_access); + asn1r_fin_constr (aCtx, 5, CTX, DEF); + } + _ms_wr_va_var_spec (aCtx, &vl_ptr->var_spec); + asn1r_fin_constr (aCtx, SEQ_CODE, UNI, DEF); + vl_ptr--; /* point to previous var name */ + } + } + +/************************************************************************/ +/* _ms_wr_va_spec */ +/* Function to write a variable access specification to the message. */ +/************************************************************************/ + +ST_VOID _ms_wr_va_spec (ASN1_ENC_CTXT *aCtx, VAR_ACC_SPEC *data_ptr) + { +VARIABLE_LIST *vl_ptr; + + if (data_ptr->var_acc_tag == 1) + { + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + _ms_wr_mms_objname (aCtx, &data_ptr->vl_name); + asn1r_fin_constr (aCtx, 1, CTX, DEF); + } + else + { + vl_ptr = (VARIABLE_LIST *) (data_ptr + 1); + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + _ms_wr_va_var_list (aCtx, vl_ptr, data_ptr->num_of_variables); + asn1r_fin_constr (aCtx, 0, CTX, DEF); + } + } diff --git a/mmslib/mmsl/mms_ced5.c b/mmslib/mmsl/mms_ced5.c new file mode 100644 index 0000000..6a3ccf2 --- /dev/null +++ b/mmslib/mmsl/mms_ced5.c @@ -0,0 +1,77 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_ced5.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains common primitive encode/decode functions */ +/* particular application references. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 03 Remove "thisFileName" */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 01 Added SD_CONST modifiers */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "asn1defs.h" + +/************************************************************************/ + +static ST_VOID app_ref_get_seq (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/* global structures & functions */ +/************************************************************************/ + +static ST_VOID (*get_mms_app_ref_done) (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_mms_app_ref */ +/* Function to get an Application Reference from the received message. */ +/* Takes two destination element pointers because of op-specific struct */ +/* differences. */ +/************************************************************************/ + +ST_VOID _ms_get_mms_app_ref (ASN1_DEC_CTXT *aCtx, ST_UCHAR **ptr_ptr, ST_INT *len_ptr, + ST_VOID (*done_fun) (ASN1_DEC_CTXT *aCtx)) + { + + get_mms_app_ref_done = done_fun; + + *ptr_ptr = aCtx->asn1r_field_ptr; /* save pointer */ + *len_ptr = aCtx->asn1r_elmnt_len; /* save length of data */ + + ASN1R_TAG_ADD (aCtx, UNI|CONSTR, SEQ_CODE, app_ref_get_seq); + } + +/************************************************************************/ +/* app_ref_get_seq */ +/* Sequence was encountered, contents are 4 optional ASN.1 ANY's. */ +/************************************************************************/ + +static ST_VOID app_ref_get_seq (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("app_ref_get_seq"); + if (aCtx->asn1r_elmnt_len) /* if any contents, parse them */ + asn1r_parse_cstr_contents (aCtx, get_mms_app_ref_done); + else /* no contents, call user done function */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = get_mms_app_ref_done; + } + diff --git a/mmslib/mmsl/mms_ced6.c b/mmslib/mmsl/mms_ced6.c new file mode 100644 index 0000000..b5d6fd8 --- /dev/null +++ b/mmslib/mmsl/mms_ced6.c @@ -0,0 +1,151 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_ced6.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains common primitive encode/decode functions */ +/* particular event time */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 04 Remove "thisFileName" */ +/* 12/20/01 JRB 03 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 08/15/97 MDE 01 BTOD handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "asn1defs.h" + +/************************************************************************/ +static ST_VOID evtime_get_time_of_day (ASN1_DEC_CTXT *aCtx); +static ST_VOID evtime_get_time_seq_id (ASN1_DEC_CTXT *aCtx); +static ST_VOID (*get_mms_evtime_done) (ASN1_DEC_CTXT *aCtx); +static ST_VOID evtime_get_undefined (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/* global structures & functions */ +/************************************************************************/ + +static EVENT_TIME *ev_time_ptr; + +static ST_RET _error_code; + + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_mms_evtime */ +/* Function to get an Event Time from the received message. */ +/************************************************************************/ + +ST_VOID _ms_get_mms_evtime (ASN1_DEC_CTXT *aCtx, EVENT_TIME *data_ptr, ST_VOID (*done_fun) (ASN1_DEC_CTXT *aCtx)) + { + /* set decode error for request or response */ + if (_mmsdec_rslt->type == MMSRESP) + _error_code = RESP_BAD_VALUE; + else + _error_code = REQ_BAD_VALUE; + + ev_time_ptr = data_ptr; + get_mms_evtime_done = done_fun; + + ASN1R_TAG_ADD (aCtx, CTX, 0, evtime_get_time_of_day); + ASN1R_TAG_ADD (aCtx, CTX, 1, evtime_get_time_seq_id); +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + ASN1R_TAG_ADD (aCtx, CTX, 2, evtime_get_undefined); + } + +/************************************************************************/ +/* evtime_get_time_of_day */ +/* time of day was encountered. */ +/************************************************************************/ + +static ST_VOID evtime_get_time_of_day (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evtime_get_time_of_day"); + + ev_time_ptr->evtime_tag = 0; /* set tag to time of day */ + + /* read time from message */ + if (asn1r_get_btod (aCtx, &ev_time_ptr->evtime.time_of_day)) + asn1r_set_dec_err (aCtx, _error_code); + + (*get_mms_evtime_done) (aCtx); /* all done, call user set fun */ + } + +/************************************************************************/ +/* evtime_get_time_seq_id */ +/* time sequence identifier was encountered. */ +/************************************************************************/ + +static ST_VOID evtime_get_time_seq_id (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evtime_get_time_seq_id"); + + ev_time_ptr->evtime_tag = 1; /* set tag to time seq id */ + + /* read time from message */ + if (asn1r_get_u32 (aCtx, &ev_time_ptr->evtime.time_seq_id)) + asn1r_set_dec_err (aCtx, _error_code); + + (*get_mms_evtime_done) (aCtx); /* all done, call user set fun */ + } + +/************************************************************************/ +/* evtime_get_undefined */ +/* undefined was encountered. */ +/************************************************************************/ + +static ST_VOID evtime_get_undefined (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evtime_get_undefined"); + + ev_time_ptr->evtime_tag = 2; /* set tag to undefined */ + + (*get_mms_evtime_done) (aCtx); /* all done, call user set fun */ + } + + +/************************************************************************/ +/************************************************************************/ +/* _ms_wr_mms_evtime */ +/* Function to write an Event Time to the message. */ +/************************************************************************/ + +ST_VOID _ms_wr_mms_evtime (ASN1_ENC_CTXT *aCtx, EVENT_TIME *data_ptr) + { + if (data_ptr->evtime_tag == 0) + { /* write the time of day */ + asn1r_wr_btod (aCtx, &data_ptr->evtime.time_of_day); + asn1r_fin_prim (aCtx, 0, CTX); /* context tag 0 */ + } + else if (data_ptr->evtime_tag == 1) + { /* write time sequence id */ + asn1r_wr_u32 (aCtx, data_ptr->evtime.time_seq_id); + asn1r_fin_prim (aCtx, 1, CTX); /* context tag 1 */ + } + else + { /* IS - write undefined (null) */ + asn1r_fin_prim (aCtx, 2, CTX); /* context tag 2 */ + } + } + diff --git a/mmslib/mmsl/mms_ced7.c b/mmslib/mmsl/mms_ced7.c new file mode 100644 index 0000000..c6ca125 --- /dev/null +++ b/mmslib/mmsl/mms_ced7.c @@ -0,0 +1,543 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_ced7.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains common primitive encode/decode functions */ +/* particular to getting and writing a list of modifiers. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 08/28/03 EJV 04 Corr spelling for 'receive'. */ +/* 03/31/03 JRB 03 asn1r_get_bitstr: add max_bits arg. */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 01 Added SD_CONST modifiers */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "asn1defs.h" + + +#ifdef MOD_SUPPORT +/************************************************************************/ +/************************************************************************/ +/* global structures & functions */ +/************************************************************************/ + +static ST_VOID modlist_attach_to_ec (ASN1_DEC_CTXT *aCtx); +static ST_VOID modlist_attach_to_sem (ASN1_DEC_CTXT *aCtx); +static ST_VOID modlist_modifier_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID modlist_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID atsem_get_priority (ASN1_DEC_CTXT *aCtx); +static ST_VOID atsem_get_acc_delay (ASN1_DEC_CTXT *aCtx); +static ST_VOID atsem_get_ctrl_timeout (ASN1_DEC_CTXT *aCtx); +static ST_VOID atsem_get_abrt_timeout (ASN1_DEC_CTXT *aCtx); +static ST_VOID atsem_get_rel_conn_lost (ASN1_DEC_CTXT *aCtx); +static ST_VOID atec_get_ct_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID atsem_get_named_token (ASN1_DEC_CTXT *aCtx); +static ST_VOID atsem_sem_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID atsem_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID atsem_sem_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID atec_get_acc_delay (ASN1_DEC_CTXT *aCtx); +static ST_VOID atec_get_ct_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID atec_get_ct_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID atec_ecname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID atec_ecname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID atec_ecname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID atec_eename_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID atec_eename_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID atec_eename_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID (*get_mms_modlist_done) (ASN1_DEC_CTXT *aCtx); + + +static MODIFIER *mod_ptr; +static ST_INT *NUM_OF_MODS; +static ST_INT MAX_MODS; +static ST_RET ERROR_CODE; + + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_mms_modlist */ +/* Function to get an MMS list of modifiers from the received message. */ +/************************************************************************/ + +ST_VOID _ms_get_mms_modlist (ASN1_DEC_CTXT *aCtx, MODIFIER *data_ptr, ST_INT *num_ptr, + ST_INT max_mods, ST_VOID (*done_fun) (ASN1_DEC_CTXT *ac)) + { + /* set decode error for request or response */ + if (_mmsdec_rslt->type == MMSRESP) + ERROR_CODE = RESP_BAD_VALUE; + else + ERROR_CODE = REQ_BAD_VALUE; + + mod_ptr = data_ptr; + NUM_OF_MODS = num_ptr; + MAX_MODS = max_mods; + get_mms_modlist_done = done_fun; + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, modlist_attach_to_ec); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, modlist_attach_to_sem); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = modlist_done; + } + +/************************************************************************/ +/************************************************************************/ +/* modlist_attach_to_ec */ +/* decoding list of modifiers: attach to event condition modifier cstr */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID modlist_attach_to_ec (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("modlist_attach_to_ec"); + + (*NUM_OF_MODS)++; /* increment # of modifiers */ + if (*NUM_OF_MODS > MAX_MODS) + asn1r_set_dec_err (aCtx, ERROR_CODE); + + mod_ptr->modifier_tag = 0; /* set tag to attach to ec */ + + ASN1R_TAG_ADD (aCtx, CTX |CONSTR, 0, atec_eename_cstr); + } + +/************************************************************************/ +/* atec_eename_cstr */ +/* decoding attach to event condition modifier: event enrollment name */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID atec_eename_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("atec_eename_cstr"); + + _ms_get_mms_objname (aCtx,&mod_ptr->mod.atec.evenroll_name, atec_eename_done); + } + +/************************************************************************/ +/* atec_eename_done */ +/* decoding attach to event condition modifier: event enrollment name */ +/* has been obtained. */ +/************************************************************************/ + +static ST_VOID atec_eename_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = atec_eename_cstr_done; + } + +/************************************************************************/ +/* atec_eename_cstr_done */ +/* decoding attach to event condition modifier: event enrollment name */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID atec_eename_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX |CONSTR, 1, atec_ecname_cstr); + } + +/************************************************************************/ +/* atec_ecname_cstr */ +/* decoding attach to event condition modifier: event condition name */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID atec_ecname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("atec_ecname_cstr"); + + _ms_get_mms_objname (aCtx, &mod_ptr->mod.atec.evcon_name, atec_ecname_done); + } + +/************************************************************************/ +/* atec_ecname_done */ +/* decoding attach to event condition modifier: event condition name */ +/* has been obtained. */ +/************************************************************************/ + +static ST_VOID atec_ecname_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = atec_ecname_cstr_done; + } + +/************************************************************************/ +/* atec_ecname_cstr_done */ +/* decoding attach to event condition modifier: event condition name */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID atec_ecname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX, 2,atec_get_ct_prim); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,atec_get_ct_cstr); + } + +/************************************************************************/ +/* atec_get_ct_prim */ +/* decoding attach to event condition modifier: causing transitions */ +/* primitive was encountered. */ +/************************************************************************/ + +static ST_VOID atec_get_ct_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("atec_get_ct_prim"); + if (!asn1r_get_bitstr (aCtx, &mod_ptr->mod.atec.causing_transitions, 7)) + atec_get_ct_done (aCtx); /* set up for the next data element */ + else + asn1r_set_dec_err (aCtx, ERROR_CODE); + } + +/************************************************************************/ +/* atec_get_ct_cstr */ +/* decoding attach to event condition modifier: causing transitions */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID atec_get_ct_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("atec_get_ct_cstr"); + + /* set up bitstring cstr done function */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = atec_get_ct_done; + + asn1r_get_bitstr_cstr (aCtx, 7,&mod_ptr->mod.atec.causing_transitions); + } + +/************************************************************************/ +/* atec_get_ct_done */ +/* decoding attach to event condition modifier: causing transitions */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID atec_get_ct_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("atec_get_ct_done"); + + /* Check aCtx->asn1r_bitcount for correct # of bits */ + if (aCtx->asn1r_bitcount != 7) /* should be 7 bits */ + asn1r_set_dec_err (aCtx, ERROR_CODE); + else /* now get acceptable delay */ + { + ASN1R_TAG_ADD (aCtx, CTX,3,atec_get_acc_delay); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = modlist_modifier_done; + } + } + +/************************************************************************/ +/* atec_get_acc_delay */ +/* decoding attach to event condition modifier: decode acceptable delay */ +/************************************************************************/ + +static ST_VOID atec_get_acc_delay (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("atec_get_acc_dela"); + + mod_ptr->mod.atec.acc_delay_pres = SD_TRUE; /* accept delay present */ + + /* read acceptable delay from message */ + if (asn1r_get_u32 (aCtx, &(mod_ptr->mod.atec.acc_delay))) + asn1r_set_dec_err (aCtx, ERROR_CODE); + } + +/************************************************************************/ +/************************************************************************/ +/* modlist_attach_to_sem */ +/* decoding list of modifiers: attach to semaphore modifier constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID modlist_attach_to_sem (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("modlist_attach_to_sem"); + + (*NUM_OF_MODS)++; /* increment # of modifiers */ + if (*NUM_OF_MODS > MAX_MODS) + asn1r_set_dec_err (aCtx, ERROR_CODE); + + mod_ptr->modifier_tag = 1; /* set tag to attach to sem */ + + ASN1R_TAG_ADD (aCtx, CTX |CONSTR, 0, atsem_sem_name_cstr); + } + +/************************************************************************/ +/* atsem_sem_name_cstr */ +/* decoding attach to semaphore modifier: semaphore name constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID atsem_sem_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("atsem_sem_name_cstr"); + + mod_ptr->mod.atsem.priority = MMS_NORM_PRIORITY; + mod_ptr->mod.atsem.rel_conn_lost = SD_TRUE; + + _ms_get_mms_objname (aCtx, &mod_ptr->mod.atsem.sem_name, atsem_objname_done); + } + +/************************************************************************/ +/* atsem_objname_done */ +/* decoding attach to semaphore modifier: semaphore name has been */ +/* obtained. */ +/************************************************************************/ + +static ST_VOID atsem_objname_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = atsem_sem_name_cstr_done; + } + +/************************************************************************/ +/* atsem_sem_name_cstr_done */ +/* decoding attach to semaphore modifier: semaphore name constructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID atsem_sem_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, atsem_get_named_token); + ASN1R_TAG_ADD (aCtx, CTX, 2, atsem_get_priority ); + ASN1R_TAG_ADD (aCtx, CTX, 3, atsem_get_acc_delay ); + ASN1R_TAG_ADD (aCtx, CTX, 4, atsem_get_ctrl_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 5, atsem_get_abrt_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 6, atsem_get_rel_conn_lost); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = modlist_modifier_done; + } + +/************************************************************************/ +/* atsem_get_named_token */ +/* decoding attach to semaphore modifier: named token name was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID atsem_get_named_token (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("atsem_get_named_token"); + + mod_ptr->mod.atsem.named_token_pres = SD_TRUE; /* named token present */ + + /* read named token from received message */ + if (asn1r_get_identifier (aCtx, mod_ptr->mod.atsem.named_token)) + asn1r_set_dec_err (aCtx, ERROR_CODE); + + ASN1R_TAG_ADD (aCtx, CTX, 2, atsem_get_priority ); + ASN1R_TAG_ADD (aCtx, CTX, 3, atsem_get_acc_delay ); + ASN1R_TAG_ADD (aCtx, CTX, 4, atsem_get_ctrl_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 5, atsem_get_abrt_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 6, atsem_get_rel_conn_lost); + } + +/************************************************************************/ +/* atsem_get_priority */ +/* decoding attach to semaphore modifier: decode the priority. */ +/************************************************************************/ + +static ST_VOID atsem_get_priority (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("atsem_get_priorit"); + /* read priority from received message */ + if (asn1r_get_u8 (aCtx, &(mod_ptr->mod.atsem.priority))) + asn1r_set_dec_err (aCtx, ERROR_CODE); + + ASN1R_TAG_ADD (aCtx, CTX, 3, atsem_get_acc_delay ); + ASN1R_TAG_ADD (aCtx, CTX, 4, atsem_get_ctrl_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 5, atsem_get_abrt_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 6, atsem_get_rel_conn_lost); + } + +/************************************************************************/ +/* atsem_get_acc_delay */ +/* decoding attach to semaphore modifier: decode acceptable delay */ +/************************************************************************/ + +static ST_VOID atsem_get_acc_delay (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("atsem_get_acc_dela"); + + mod_ptr->mod.atsem.acc_delay_pres = SD_TRUE; /* accept delay present */ + + /* read acceptable delay from message */ + if (asn1r_get_u32 (aCtx, &(mod_ptr->mod.atsem.acc_delay))) + asn1r_set_dec_err (aCtx, ERROR_CODE); + + ASN1R_TAG_ADD (aCtx, CTX, 4, atsem_get_ctrl_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 5, atsem_get_abrt_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 6, atsem_get_rel_conn_lost); + } + +/************************************************************************/ +/* atsem_get_ctrl_timeout */ +/* decoding attach to semaphore modifier: decode control timeout. */ +/************************************************************************/ + +static ST_VOID atsem_get_ctrl_timeout (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("atsem_get_ctrl_timeou"); + + mod_ptr->mod.atsem.ctrl_timeout_pres = SD_TRUE; /* ctrl timeout pres */ + + /* read control timeout from message */ + if (asn1r_get_u32 (aCtx, &(mod_ptr->mod.atsem.ctrl_timeout))) + asn1r_set_dec_err (aCtx, ERROR_CODE); + + ASN1R_TAG_ADD (aCtx, CTX, 5, atsem_get_abrt_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 6, atsem_get_rel_conn_lost); + } + +/************************************************************************/ +/* atsem_get_abrt_timeout */ +/* decoding attach to semaphore modifier: decode abort timeout. */ +/************************************************************************/ + +static ST_VOID atsem_get_abrt_timeout (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("atsem_get_abrt_timeout"); + + mod_ptr->mod.atsem.abrt_on_timeout_pres = SD_TRUE; + + if (asn1r_get_bool (aCtx, &(mod_ptr->mod.atsem.abrt_on_timeout))) + asn1r_set_dec_err (aCtx, ERROR_CODE); + + ASN1R_TAG_ADD (aCtx, CTX, 6, atsem_get_rel_conn_lost); + } + +/************************************************************************/ +/* atsem_get_rel_conn_lost */ +/* decoding attach to semaphore modifier: decode relinquish if */ +/* connection lost. */ +/************************************************************************/ + +static ST_VOID atsem_get_rel_conn_lost (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("atsem_get_rel_conn_lost"); + + if (asn1r_get_bool (aCtx, &(mod_ptr->mod.atsem.rel_conn_lost))) + asn1r_set_dec_err (aCtx, ERROR_CODE); + } + +/************************************************************************/ +/* modlist_modifier_done */ +/* decoding attach to semaphore modifier: modifier constructor done */ +/* was encountered */ +/************************************************************************/ + +static ST_VOID modlist_modifier_done (ASN1_DEC_CTXT *aCtx) + { + mod_ptr++; /* point to where next will go */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, modlist_attach_to_ec); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, modlist_attach_to_sem); + } + +/************************************************************************/ +/* modlist_done */ +/* decoding list of modifiers: list is done */ +/************************************************************************/ + +static ST_VOID modlist_done (ASN1_DEC_CTXT *aCtx) + { + (*get_mms_modlist_done) (aCtx); /* all done, call user set fun */ + } + + +/************************************************************************/ +/************************************************************************/ +/* _ms_wr_mms_modlist */ +/* Function to write an MMS list of modifiers to the message. */ +/************************************************************************/ + +ST_VOID _ms_wr_mms_modlist (ASN1_ENC_CTXT *aCtx, MODIFIER *data_ptr, ST_INT num_of_mods) + { +MODIFIER *modPtr; +ST_INT i; + + modPtr = data_ptr; + modPtr += num_of_mods - 1; /* point to last in the list */ + + for (i = 0; i < num_of_mods; i++) + { + asn1r_strt_constr (aCtx); /* start ctx tag 0 or 1 cstr */ + switch (modPtr->modifier_tag) + { + case (0) : /* write attach to event cond */ + if (modPtr->mod.atec.acc_delay_pres) + { + asn1r_wr_u32 (aCtx, modPtr->mod.atec.acc_delay); + asn1r_fin_prim (aCtx, 3, CTX); + } + + asn1r_wr_bitstr (aCtx, &modPtr->mod.atec.causing_transitions, 7); + asn1r_fin_prim (aCtx, 2, CTX); + + asn1r_strt_constr (aCtx); + _ms_wr_mms_objname (aCtx, &modPtr->mod.atec.evcon_name); + asn1r_fin_constr (aCtx, 1, CTX, DEF); + + asn1r_strt_constr (aCtx); + _ms_wr_mms_objname (aCtx, &modPtr->mod.atec.evenroll_name); + asn1r_fin_constr (aCtx, 0, CTX, DEF); + break; + + case (1) : /* write attach to semaphore */ + asn1r_wr_bool (aCtx, modPtr->mod.atsem.rel_conn_lost); + asn1r_fin_prim (aCtx, 6, CTX); + + if (modPtr->mod.atsem.abrt_on_timeout_pres) + { + asn1r_wr_bool (aCtx, modPtr->mod.atsem.abrt_on_timeout); + asn1r_fin_prim (aCtx, 5, CTX); + } + + if (modPtr->mod.atsem.ctrl_timeout_pres) + { + asn1r_wr_u32 (aCtx, modPtr->mod.atsem.ctrl_timeout); + asn1r_fin_prim (aCtx, 4, CTX); + } + + if (modPtr->mod.atsem.acc_delay_pres) + { + asn1r_wr_u32 (aCtx, modPtr->mod.atsem.acc_delay); + asn1r_fin_prim (aCtx, 3, CTX); + } + + if (modPtr->mod.atsem.priority != MMS_NORM_PRIORITY) + { + asn1r_wr_u8 (aCtx, modPtr->mod.atsem.priority); + asn1r_fin_prim (aCtx, 2, CTX); + } + + if (modPtr->mod.atsem.named_token_pres) + { + asn1r_wr_vstr (aCtx, modPtr->mod.atsem.named_token); + asn1r_fin_prim (aCtx, 1, CTX); + } + + asn1r_strt_constr (aCtx); + _ms_wr_mms_objname (aCtx, &modPtr->mod.atsem.sem_name); + asn1r_fin_constr (aCtx, 0, CTX, DEF); + break; + } + asn1r_fin_constr (aCtx, (ST_UINT16) modPtr->modifier_tag, CTX, DEF); + modPtr--; /* point to previous modifier */ + } + } +#endif diff --git a/mmslib/mmsl/mms_err.c b/mmslib/mmsl/mms_err.c new file mode 100644 index 0000000..7ca4486 --- /dev/null +++ b/mmslib/mmsl/mms_err.c @@ -0,0 +1,775 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2007, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_err.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the MMS error functions for decoding */ +/* & encoding the error response PDUs : */ +/* confirmed-ErrorPDU */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/01/07 EJV 08 Rem obsolete LLC30... code. */ +/* 04/05/02 MDE 07 Added MLOG logging */ +/* 01/23/02 JRB 06 Fix "Response built" msg (was missing header)*/ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pcon.h" +#include "asn1defs.h" +#include "mloguser.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* variables global to the decode : */ + +static ERR_INFO *err_info_ptr; + + +#ifdef MOD_SUPPORT +static ST_VOID err_mod_pos (ASN1_DEC_CTXT *aCtx); +#endif +static ST_VOID err_rsp2 (ASN1_DEC_CTXT *aCtx); +static ST_VOID err_class (ASN1_DEC_CTXT *aCtx); +static ST_VOID err_get_cac (ASN1_DEC_CTXT *aCtx); +#ifdef CS_SUPPORT +static ST_VOID err_get_cs (ASN1_DEC_CTXT *aCtx); +static ST_VOID err_cs_done (ASN1_DEC_CTXT *aCtx); +#endif +static ST_VOID err_class_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID err_get_add_code (ASN1_DEC_CTXT *aCtx); +static ST_VOID err_get_add_descr (ASN1_DEC_CTXT *aCtx); +static ST_VOID err_add_ssi_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID err_get_add_ssi_i16 (ASN1_DEC_CTXT *aCtx); +static ST_VOID err_get_add_ssi_u32 (ASN1_DEC_CTXT *aCtx); +static ST_VOID err_get_dee_obj_name (ASN1_DEC_CTXT *aCtx); +static ST_VOID err_dee_obj_name_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID err_get_add_serv_err (ASN1_DEC_CTXT *aCtx); +static ST_VOID err_adtnl_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID err_ssi_done (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/************************************************************************/ +/* mms_err_invoke_fun */ +/* This function is called from mmsdec.c when invoke ID is expected */ +/* in a CONFIRMED or CANCEL ERROR PDU. */ +/************************************************************************/ + +ST_VOID mms_err_invoke_fun (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code) + { +ST_INT pdutype; + + pdutype = _mmsdec_rslt->type; + if (aCtx->asn1r_constr_elmnt || id_code != 0) + { + asn1r_set_dec_err (aCtx, PDU_INVALID); /* wrong code or constructed int*/ + return; + } + if (asn1r_get_u32 (aCtx, &_mmsdec_rslt->id)) + { + if (pdutype == MMSCANERR) + asn1r_set_dec_err (aCtx, CANERR_INVAL_INVOKE); /* not a valid integer contents */ + else + asn1r_set_dec_err (aCtx, ERR_INVAL_INVOKE); /* not a valid integer contents */ + return; + } + + _mmsdec_rslt->dec_level = 2; /* set flag that Invoke ID is OK */ + + MLOG_CDEC1 ("Invoke ID present, = %ld",_mmsdec_rslt->id); + err_info_ptr = (ERR_INFO *) _m_get_dec_buf (aCtx, sizeof (ERR_INFO)); + if (pdutype == MMSCANERR) /* Cancel Error PDU, next must */ + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,1,err_rsp2); /* be context tag 1 cstr */ + else + { /* Confirmed Error PDU, next */ +#ifdef MOD_SUPPORT + ASN1R_TAG_ADD (aCtx, CTX ,1,err_mod_pos); /* Context tag 1 (opt) */ +#endif + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,err_rsp2); /* Context tag 2 cstr */ + } + } + +#ifdef MOD_SUPPORT +/************************************************************************/ +/* err_mod_pos */ +/* This function is called when a modifier position is detected in a */ +/* confirmed_request_error PDU. The only thing which may follow is a */ +/* service error description. */ +/************************************************************************/ + +static ST_VOID err_mod_pos (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("err_mod_pos"); + + if (asn1r_get_i32 (aCtx, &(err_info_ptr->adtnl.mod_pos))) /* read mod position */ + asn1r_set_dec_err (aCtx, ERR_UNSPECIFIED); + err_info_ptr -> adtnl.mod_pos_pres = SD_TRUE; + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,2,err_rsp2); /* Context tag 2 cstr */ + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* mms_err_rsp */ +/* This function is called from mmsdec.c when an Error Response PDU is */ +/* being decoded for initiate or conclude error ONLY */ +/* When this is called directly, we need to allocate the buffer */ +/************************************************************************/ + +ST_VOID mms_err_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("mms_err_rsp"); + + err_info_ptr = (ERR_INFO *) _m_get_dec_buf (aCtx, sizeof (ERR_INFO)); + aCtx->asn1r_err_fun = _mms_dec_buf_free; + err_rsp2 (aCtx); /* set tags */ + } + + +/************************************************************************/ +/************************************************************************/ +/* _mms_get_service_err */ +/* This function is called from rs_termd.c when IS is used and the */ +/* 'discarded' parameter is send (service error) -or- from rs_evnot.c */ +/* when the action result is failure. */ +/************************************************************************/ + +ST_VOID _mms_get_service_err (ASN1_DEC_CTXT *aCtx, ERR_INFO *err_ptr) + { + err_info_ptr = err_ptr; /* use caller's storage */ + err_rsp2 (aCtx); /* set tags */ + } + + +/************************************************************************/ +/************************************************************************/ +/* err_rsp2 */ +/* This function is called when an Error Response PDU is being decoded */ +/* for confirmed error. */ +/************************************************************************/ + +static ST_VOID err_rsp2 (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("err_rsp2"); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,err_class); + } + +/************************************************************************/ +/* err_class */ +/* This function is invoked when the ServiceError is being decoded, and */ +/* the errorClass choice is encountered. */ +/************************************************************************/ + +static ST_VOID err_class (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("err_class"); + + ASN1R_TAG_ADD (aCtx, CTX, 0, err_get_cac); + ASN1R_TAG_ADD (aCtx, CTX, 1, err_get_cac); + ASN1R_TAG_ADD (aCtx, CTX, 2, err_get_cac); + ASN1R_TAG_ADD (aCtx, CTX, 3, err_get_cac); + ASN1R_TAG_ADD (aCtx, CTX, 4, err_get_cac); + ASN1R_TAG_ADD (aCtx, CTX, 5, err_get_cac); + ASN1R_TAG_ADD (aCtx, CTX, 6, err_get_cac); + ASN1R_TAG_ADD (aCtx, CTX, 7, err_get_cac); + ASN1R_TAG_ADD (aCtx, CTX, 8, err_get_cac); + ASN1R_TAG_ADD (aCtx, CTX, 9, err_get_cac); + ASN1R_TAG_ADD (aCtx, CTX,10, err_get_cac); + ASN1R_TAG_ADD (aCtx, CTX,11, err_get_cac); + ASN1R_TAG_ADD (aCtx, CTX,12, err_get_cac); +#ifdef CS_SUPPORT +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,13, err_get_cs); /* CS error */ +#endif + } + +/************************************************************************/ +/* err_get_cac */ +/* error response is being decoded: context tagged error class has */ +/* been encountered, get the error class and error code. */ +/************************************************************************/ + +static ST_VOID err_get_cac (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("err_get_cac"); + + err_info_ptr->eclass = aCtx->asn1r_elmnt_id; /* save the error class */ + + if (asn1r_get_i16 (aCtx, &(err_info_ptr->code))) /* read the error code */ + asn1r_set_dec_err (aCtx, ERR_UNSPECIFIED); + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = err_class_cstr_done; /* choice cstr done */ + } + +#ifdef CS_SUPPORT +/************************************************************************/ +/* err_get_cs */ +/* error response is being decoded: context tagged error class 13 has */ +/* been encountered, get the CS service error. */ +/************************************************************************/ + +static ST_VOID err_get_cs (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("err_get_cs"); + + err_info_ptr->adtnl.ss_error_data= aCtx->asn1r_field_ptr; /* save ptr to field */ + err_info_ptr->adtnl.ss_error_len = aCtx->asn1r_elmnt_len; /* save len of field */ + asn1r_parse_next (aCtx, err_cs_done); /* parse the contents */ + } + +/************************************************************************/ +/* err_cs_done */ +/* Companion Standard service error has been parsed OK. */ +/************************************************************************/ + +static ST_VOID err_cs_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = err_class_cstr_done; /* choice cstr done */ + } +#endif + +/************************************************************************/ +/* err_class_cstr_done */ +/* errorClass constructor (choice) is complete */ +/* set up to get additional (optional) information */ +/************************************************************************/ + +static ST_VOID err_class_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("err_class_cstr_done"); + + /* add tags for optional information */ + ASN1R_TAG_ADD (aCtx, CTX, 1, err_get_add_code); + ASN1R_TAG_ADD (aCtx, CTX, 2, err_get_add_descr); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 3, err_add_ssi_cstr); + + aCtx->asn1r_decode_done_fun = _mms_dec_done_ok; + + if ((_mmsdec_rslt->type == MMSREQ) || /* terminate download request */ + (_mmsdec_rslt->type == MMSUNREQ)) /* or Event Notification */ + /* Terminate Download req or Event Notification unconfirmed */ + /* request is being decoded, decode can be done, but check for */ + /* companion standard information. */ + _ms_set_cs_check (aCtx); + else + asn1r_set_all_cstr_done (aCtx); /* clear all cstr done funtions */ + } + +/************************************************************************/ +/* err_get_add_code */ +/* error response is being decoded: additional error code has been */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID err_get_add_code (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("err_get_add_code"); + + err_info_ptr->adtnl.info_pres = SD_TRUE; /* set info present */ + err_info_ptr->adtnl.code_pres = SD_TRUE; /* set code present */ + + /* read the additional error code */ + if (asn1r_get_i32 (aCtx, &(err_info_ptr->adtnl.code))) + asn1r_set_dec_err (aCtx, ERR_UNSPECIFIED); + + ASN1R_TAG_ADD (aCtx, CTX, 2, err_get_add_descr); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 3, err_add_ssi_cstr); + + if ((_mmsdec_rslt->type == MMSREQ) || /* terminate download request */ + (_mmsdec_rslt->type == MMSUNREQ)) /* or Event Notification */ + /* Terminate Download req or Event Notification unconfirmed */ + /* request is being decoded, decode can be done, but check for */ + /* companion standard information. */ + _ms_set_cs_check (aCtx); + else + asn1r_set_all_cstr_done (aCtx); /* clear all cstr done funtions */ + } + +/************************************************************************/ +/* err_get_add_descr */ +/* error response is being decoded: additional error description has */ +/* been encountered. */ +/************************************************************************/ + +static ST_VOID err_get_add_descr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("err_get_add_descr"); + + err_info_ptr->adtnl.info_pres = SD_TRUE; /* set info present */ + err_info_ptr->adtnl.descr_pres = SD_TRUE; /* set descr present */ + + /* read the additional error description */ +/* copy error description back onto itself shifted by one character */ + err_info_ptr->adtnl.descr = (ST_CHAR *)aCtx->asn1r_field_ptr -1; + if (asn1r_get_vstr (aCtx, err_info_ptr->adtnl.descr)) + asn1r_set_dec_err (aCtx, ERR_UNSPECIFIED); + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 3, err_add_ssi_cstr); + + if ((_mmsdec_rslt->type == MMSREQ) || /* terminate download request */ + (_mmsdec_rslt->type == MMSUNREQ)) /* or Event Notification */ + /* Terminate Download req or Event Notification unconfirmed */ + /* request is being decoded, decode can be done, but check for */ + /* companion standard information. */ + _ms_set_cs_check (aCtx); + else + asn1r_set_all_cstr_done (aCtx); /* clear all cstr done funtions */ + } + +/************************************************************************/ +/* err_add_ssi_cstr */ +/* error response is being decoded: additional service specific error */ +/* information constructor has been encountered. */ +/************************************************************************/ + +static ST_VOID err_add_ssi_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("err_get_ssi_cstr"); + + /* add tags for all choices */ + ASN1R_TAG_ADD (aCtx, CTX, 0, err_get_add_ssi_i16); + ASN1R_TAG_ADD (aCtx, CTX, 1, err_get_add_ssi_i16); + ASN1R_TAG_ADD (aCtx, CTX, 2, err_get_add_ssi_i16); + ASN1R_TAG_ADD (aCtx, CTX, 3, err_get_add_ssi_i16); + ASN1R_TAG_ADD (aCtx, CTX, 4, err_get_add_ssi_i16); + ASN1R_TAG_ADD (aCtx, CTX, 5, err_get_add_ssi_u32); + ASN1R_TAG_ADD (aCtx, CTX, 6, err_get_add_ssi_u32); + ASN1R_TAG_ADD (aCtx, CTX, 7, err_get_add_ssi_u32); +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + { + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 8, err_get_dee_obj_name); /* def ev enroll*/ + ASN1R_TAG_ADD (aCtx, CTX, 9, err_get_add_ssi_i16); /* file rename */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,10, err_get_add_serv_err); /* adtnl service*/ + } + else + { + ASN1R_TAG_ADD (aCtx, CTX, 8, err_get_add_ssi_i16); /* file rename */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 9, err_get_add_serv_err); /* adtnl service*/ + } + } + +/************************************************************************/ +/* err_get_add_ssi_i16 */ +/* error response is being decoded: additional service specific error */ +/* information has been encountered for obtain file, start, stop, */ +/* resume, reset or file rename. */ +/************************************************************************/ + +static ST_VOID err_get_add_ssi_i16 (ASN1_DEC_CTXT *aCtx) + { +ST_INT16 ssi_error; + + MLOG_CDEC0 ("err_get_add_ssi_i16"); + + err_info_ptr->adtnl.info_pres = SD_TRUE; /* set info present indicator */ + err_info_ptr->adtnl.ssi_pres = SD_TRUE; /* set additional service pres */ + + err_info_ptr->adtnl.service = aCtx->asn1r_elmnt_id; /* save the service id */ + + /* read the additional service error */ + if (asn1r_get_i16 (aCtx, &ssi_error)) + asn1r_set_dec_err (aCtx, ERR_UNSPECIFIED); + else + err_info_ptr->adtnl.ss_error_val = (ST_UINT32) ssi_error; + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = err_ssi_done; + } + +/************************************************************************/ +/* err_get_add_ssi_u32 */ +/* error response is being decoded: additional service specific error */ +/* information has been encountered for delete varaible access, delete */ +/* named variable list or delete named type. */ +/************************************************************************/ + +static ST_VOID err_get_add_ssi_u32 (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("err_get_add_ssi_u32"); + + err_info_ptr->adtnl.info_pres = SD_TRUE; /* set info present indicator */ + err_info_ptr->adtnl.ssi_pres = SD_TRUE; /* set additional service pres */ + + err_info_ptr->adtnl.service = aCtx->asn1r_elmnt_id; /* save the service id */ + + /* read the additional service error */ + if (asn1r_get_u32 (aCtx, &(err_info_ptr->adtnl.ss_error_val))) + asn1r_set_dec_err (aCtx, ERR_UNSPECIFIED); + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = err_ssi_done; + } + +/************************************************************************/ +/* err_get_dee_obj_name */ +/* error response is being decoded: additional service specific error */ +/* information has been encountered for define event enrollment error */ +/* get the object name. */ +/************************************************************************/ + +static ST_VOID err_get_dee_obj_name (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("err_get_dee_obj_name"); + + err_info_ptr->adtnl.info_pres = SD_TRUE; /* set info present indicator */ + err_info_ptr->adtnl.ssi_pres = SD_TRUE; /* set additional service pres */ + + err_info_ptr->adtnl.service = aCtx->asn1r_elmnt_id; /* save the service id */ + + /* read the object name */ + _ms_get_mms_objname (aCtx, &err_info_ptr->adtnl.ss_error_oname, + err_dee_obj_name_done); + } + +/************************************************************************/ +/* err_dee_obj_name_done */ +/* define event enrollment error is being decoded: object name has */ +/* been obtained. */ +/************************************************************************/ + +static ST_VOID err_dee_obj_name_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("err_dee_obj_name_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = err_adtnl_done; + } + +/************************************************************************/ +/* err_get_add_serv_err */ +/* error response is being decoded: additional service specific error */ +/* information has been encountered for additional service error. */ +/************************************************************************/ + +static ST_VOID err_get_add_serv_err (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("err_get_add_serv_err"); + + err_info_ptr->adtnl.info_pres = SD_TRUE; /* set info present indicator */ + err_info_ptr->adtnl.ssi_pres = SD_TRUE; /* set additional service pres */ + + err_info_ptr->adtnl.service = aCtx->asn1r_elmnt_id; /* save the service id */ + + /* Companion Standard additional service error */ + err_info_ptr->adtnl.ss_error_data = aCtx->asn1r_field_ptr; /* save ptr to field */ + err_info_ptr->adtnl.ss_error_len = aCtx->asn1r_elmnt_len; /* save len of field */ + asn1r_parse_next (aCtx, err_adtnl_done); /* parse contents */ + } + +/************************************************************************/ +/* err_adtnl_done */ +/* IS: define event enrollment, object name has been obtained -OR- */ +/* Companion Standard ANY has been parsed OK. Message is now done. */ +/************************************************************************/ + +static ST_VOID err_adtnl_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = err_ssi_done; + } + +/************************************************************************/ +/* err_ssi_done */ +/* Service specific info constructor done */ +/************************************************************************/ + +static ST_VOID err_ssi_done (ASN1_DEC_CTXT *aCtx) + { + if ((_mmsdec_rslt->type == MMSREQ) || /* terminate download request */ + (_mmsdec_rslt->type == MMSUNREQ)) /* or Event Notification */ + /* Terminate Download req or Event Notification unconfirmed */ + /* request is being decoded, decode can be done, but check for */ + /* companion standard information. */ + _ms_set_cs_check (aCtx); + else + aCtx->asn1r_decode_done = SD_TRUE; /* just terminate the parse */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_err_resp */ +/* Create and send a general error response */ +/************************************************************************/ + +ST_RET mp_err_resp (MMSREQ_IND *indptr, ST_INT16 class, ST_INT16 code) + { +ST_UCHAR *msg_ptr; /* pointer to start of message */ +ST_INT msg_len; /* length of message built */ +ST_RET ret; /* function return value */ +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + S_LOCK_COMMON_RESOURCES (); + if (!(ret = _ms_check_ind_actv (indptr))) + { + msg_ptr = _ms_mk_err_resp (aCtx, m_build_buf,mms_max_msgsize,indptr->op,indptr->id, + class,code); + msg_len = M_BUILD_BUF_END - msg_ptr; + + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + ret = ME_ASN1_ENCODE_OVERRUN; + else + ret = _mms_send_data (indptr->chan, msg_len, msg_ptr, + indptr->context, indptr->add_addr_info); + + /* If a response logging function is installed, call it */ + if (!ret && m_log_error_resp_fun && (mms_debug_sel & MMS_LOG_RESP)) + (*m_log_error_resp_fun) (indptr, class, code); + + _ms_ind_serve_done (indptr); + } + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_err_resp */ +/* Create and send a general error response */ +/* Initiate, Conclude, Confirmed Service */ +/************************************************************************/ + +ST_RET mpl_err_resp (ST_INT opcode, ST_UINT32 invoke, + ST_INT16 err_class, ST_INT16 code) + { +ST_INT ret; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; +ERR_INFO err_info; + + S_LOCK_COMMON_RESOURCES (); + mmsl_msg_start = _ms_mk_err_resp (aCtx, mmsl_enc_buf,mmsl_enc_buf_size,opcode,invoke, + err_class,code); + mmsl_msg_len = (mmsl_enc_buf + mmsl_enc_buf_size) - mmsl_msg_start; + + if (!aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + ret = SD_SUCCESS; + else + ret = ME_ASN1_ENCODE_OVERRUN; + + if ((mms_debug_sel & MMS_LOG_RESP) && ret == SD_SUCCESS && ml_log_error_resp_fun) + { + memset (&err_info, 0, sizeof (err_info)); + err_info.code = code; + err_info.eclass = err_class; + (*ml_log_error_resp_fun) (invoke, &err_info); + } + + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_err_resp */ +/* This function is called to build a general error response. */ +/* adtnl_err_info is a global variable containing additional error */ +/* information. */ +/************************************************************************/ + +ST_UCHAR *_ms_mk_err_resp (ASN1_ENC_CTXT *aCtx, ST_UCHAR *buf_ptr, ST_INT buf_len, ST_INT op, + ST_UINT32 id, ST_INT16 err_class, ST_INT16 code) + { +ST_INT pdu_type; /* PDU type to go in error PDU. */ +#ifdef DEBUG_SISCO +ST_UCHAR *msg_start; /* These variables used for */ +ST_INT msg_len; /* debug print only */ +#endif + + asn1r_strt_asn1_bld (aCtx, buf_ptr,buf_len); /* init the ASN.1 tools */ + _ms_wr_service_err (aCtx, err_class,code,&adtnl_err_info); + +/* Write SEQUENCE header and invoke id, if this opcode is NOT initiate */ +/* or conclude. */ + if ((op == MMSOP_INITIATE) || (op == MMSOP_CONCLUDE)) + ; + else + { /* Finish the serviceError sequence. */ + if (op == MMSOP_CANCEL) + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* context tag 1 for cancel */ + else + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* context 2 for confirmed err */ + +#ifdef MOD_SUPPORT + if (adtnl_err_info.mod_pos_pres) /* send the modifier position */ + { + asn1r_wr_u32 (aCtx, adtnl_err_info.mod_pos); + asn1r_fin_prim (aCtx, 1,CTX); + adtnl_err_info.mod_pos_pres = SD_FALSE; + } +#endif + + asn1r_wr_u32 (aCtx, id); /* Write the invoke ID. */ + asn1r_fin_prim (aCtx, 0,CTX); /* conf and cancl both use CTX 0 tag */ + } + + /* Reset add'l info structure to empty */ + adtnl_err_info.info_pres = SD_FALSE; + + switch (op) + { + case MMSOP_INITIATE : + pdu_type = MMSINITERR; + break; + case MMSOP_CONCLUDE : + pdu_type = MMSCNCLERR; + break; + case MMSOP_CANCEL : + pdu_type = MMSCANERR; + break; + default: + pdu_type = MMSERROR; + } + +#ifdef DEBUG_SISCO + asn1r_fin_constr (aCtx, (ST_UINT16) pdu_type,CTX,DEF); + msg_start = aCtx->asn1r_field_ptr + 1; + msg_len = (buf_ptr + buf_len) - msg_start; + MLOG_ENC1 ("ERROR Response built : len = %d ",msg_len); + MLOG_ENCH (msg_len,msg_start); + MLOG_PAUSEENC (NULL); + return (msg_start); +#else + asn1r_fin_constr (aCtx, (ST_UINT16) pdu_type,CTX,DEF); + return (aCtx->asn1r_field_ptr + 1); +#endif + } + + +/************************************************************************/ +/************************************************************************/ +/* wr_service_err */ +/************************************************************************/ + +ST_VOID _ms_wr_service_err (ASN1_ENC_CTXT *aCtx, ST_INT16 err_class, ST_INT16 code, + ADTNL_ERR_RESP_INFO *adtnl_info) + { +ST_INT16 ssi_error; + + asn1r_strt_constr (aCtx); /* start sequence constructor */ + if (adtnl_info->info_pres) + { /* write additional info if present */ + if (adtnl_info->ssi_pres) + { /* write the service specific info */ + asn1r_strt_constr (aCtx); + switch (adtnl_info->service) + { + case 0 : /* obtain file */ + case 1 : /* start */ + case 2 : /* stop */ + case 3 : /* resume */ + case 4 : /* reset */ + ssi_error = (ST_INT16) adtnl_info->ss_error_val; + asn1r_wr_i16 (aCtx, ssi_error); + asn1r_fin_prim (aCtx, adtnl_info->service,CTX); + break; + + case 5 : /* delete variable access */ + case 6 : /* delete named variable list */ + case 7 : /* delete named type */ + asn1r_wr_u32 (aCtx, adtnl_info->ss_error_val); + asn1r_fin_prim (aCtx, adtnl_info->service,CTX); + break; + + case 8 : +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + { /* IS, define event enrollment */ + asn1r_strt_constr (aCtx); + _ms_wr_mms_objname (aCtx, &adtnl_info->ss_error_oname); + asn1r_fin_constr (aCtx, 8,CTX,DEF); + } + else + { /* DIS, file rename */ + ssi_error = (ST_INT16) adtnl_info->ss_error_val; + asn1r_wr_i16 (aCtx, ssi_error); + asn1r_fin_prim (aCtx, adtnl_info->service,CTX); + } + break; + + case 9 : +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + { /* IS, file rename */ + ssi_error = (ST_INT16) adtnl_info->ss_error_val; + asn1r_wr_i16 (aCtx, ssi_error); + asn1r_fin_prim (aCtx, adtnl_info->service,CTX); + } + else + { /* DIS, additional service err */ + asn1r_strt_constr (aCtx); + asn1r_wr_delmnt (aCtx, adtnl_info->ss_error_data,adtnl_info->ss_error_len); + asn1r_fin_constr (aCtx, 9,CTX,DEF); + } + break; + + default: /* IS, additional service error */ + asn1r_strt_constr (aCtx); + asn1r_wr_delmnt (aCtx, adtnl_info->ss_error_data,adtnl_info->ss_error_len); + asn1r_fin_constr (aCtx, 10,CTX,DEF); + } + asn1r_fin_constr (aCtx, 3,CTX,DEF); + } + + if (adtnl_info->descr_pres) + { /* write the additional description */ + asn1r_wr_vstr (aCtx, adtnl_info->descr); + asn1r_fin_prim (aCtx, 2,CTX); + } + if (adtnl_info->code_pres) + { /* write the service specific info */ + asn1r_wr_i32 (aCtx, adtnl_info->code); + asn1r_fin_prim (aCtx, 1,CTX); + } + adtnl_info->info_pres = SD_FALSE; + } + + asn1r_strt_constr (aCtx); /* start choice constructor */ + asn1r_wr_i16 (aCtx, code); /* write the value */ + asn1r_fin_prim (aCtx, err_class,CTX); /* finish the contents */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context 0 cstr */ + } + diff --git a/mmslib/mmsl/mms_err2.c b/mmslib/mmsl/mms_err2.c new file mode 100644 index 0000000..61a4464 --- /dev/null +++ b/mmslib/mmsl/mms_err2.c @@ -0,0 +1,110 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 1997, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_err2.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the MMS error functions for decoding */ +/* & encoding the error response PDUs : */ +/* initiate-ErrorPDU */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/09/05 EJV 06 Fixed thisFileName for MMS-EASE */ +/* 03/17/04 RKR 05 Changed thisFileName */ +/* 03/11/04 GLB 04 Remove "thisFileName" */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pcon.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) && !defined(MMS_LITE) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +#ifndef MMS_LITE + +#include "mms_vcon.h" + +/************************************************************************/ +/* mp_init_err */ +/* Create and send an initiate error response */ +/************************************************************************/ + +ST_RET mp_init_err (MMSREQ_IND *indptr, ST_INT16 class, ST_INT16 code) + { +INIT_INFO *init_req; +INIT_INFO *init_resp; +CS_INIT_INFO *cs_init_resp; +ST_INT size; +ST_INT i; +ST_INT ret; + + S_LOCK_COMMON_RESOURCES (); + init_req = (INIT_INFO *) indptr->req_info_ptr; + +/* Allocate the INITIATE response info, make big enough for all CS init */ + size = sizeof (INIT_INFO) + + (MAX_INIT_CONTEXTS * sizeof (CS_INIT_INFO)); + init_resp = (INIT_INFO *) chk_calloc (1, size); + cs_init_resp = (CS_INIT_INFO *) (init_resp+1); + + if (!(ret = _ms_check_ind_actv (indptr))) + { + if (init_req->mms_p_context_pres) + { + init_resp->rslt.accept_context = SD_FALSE; + init_resp->rslt.err_info_pres = SD_TRUE; + init_resp->rslt.err.eclass = class; + init_resp->rslt.err.code = code; + } + + for (i = 0; i < init_req->num_cs_init; ++i, ++cs_init_resp) + { + cs_init_resp->rslt.accept_context = SD_FALSE; + cs_init_resp->rslt.err_info_pres = SD_TRUE; + cs_init_resp->rslt.err.eclass = class; + cs_init_resp->rslt.err.code = code; + } /* for each CS context */ + + mv_chk_init_resp_param (indptr,init_resp); + ret = mp_init_resp (indptr,init_resp); + } + + chk_free (init_resp); + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +#else +/************************************************************************/ +/* mpl_init_err */ +/* Create an initiate error response */ +/************************************************************************/ + +ST_RET mpl_init_err (ST_INT16 err_class, ST_INT16 code) + { + return (mpl_err_resp (MMSOP_INITIATE,0L,err_class,code)); + } +#endif diff --git a/mmslib/mmsl/mms_err3.c b/mmslib/mmsl/mms_err3.c new file mode 100644 index 0000000..1d88e4a --- /dev/null +++ b/mmslib/mmsl/mms_err3.c @@ -0,0 +1,75 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2007, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_err3.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the MMS error functions for decoding */ +/* & encoding the error response PDUs : */ +/* conclude-ErrorPDU */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/01/07 EJV 06 Rem obsolete LLC30... code. */ +/* 03/09/05 EJV 05 Fixed thisFileName for MMS-EASE */ +/* 03/17/04 RKR 04 Changed thisFileName */ +/* 03/11/04 GLB 03 Remove "thisFileName" */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pcon.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) && !defined(MMS_LITE) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +#ifndef MMS_LITE +/************************************************************************/ +/* mp_conclude_err */ +/************************************************************************/ + +ST_RET mp_conclude_err (MMSREQ_IND *indptr, ST_INT16 class, ST_INT16 code) + { +ST_RET ret; + + S_LOCK_COMMON_RESOURCES (); + mms_chan_info[indptr->chan].ctxt.chan_state &= ~M_CONCL_URESP_WAIT; + ret = mp_err_resp (indptr,class,code); + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +#else +/************************************************************************/ +/* mpl_conclude_err */ +/************************************************************************/ + +ST_RET mpl_conclude_err (ST_INT16 err_class, ST_INT16 code) + { + return (mpl_err_resp (MMSOP_CONCLUDE,0L,err_class,code)); + } + +#endif + + diff --git a/mmslib/mmsl/mms_err4.c b/mmslib/mmsl/mms_err4.c new file mode 100644 index 0000000..a38a6e6 --- /dev/null +++ b/mmslib/mmsl/mms_err4.c @@ -0,0 +1,96 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2007, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_err4.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the MMS error functions for decoding */ +/* & encoding the error response PDUs : */ +/* cancel-ErrorPDU */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/01/07 EJV 07 Rem obsolete LLC30... code. */ +/* 08/09/05 EJV 06 MMS_LITE does not need thisFileName. */ +/* 03/17/04 RKR 05 Changed thisFileName */ +/* 03/11/04 GLB 04 Remove "thisFileName" */ +/* 12/20/01 JRB 03 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pcon.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) && (defined(S_MT_SUPPORT) && !defined(MMS_LITE)) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +#ifndef MMS_LITE +/************************************************************************/ +/* mp_cancel_err */ +/* Create and send a cancel error response */ +/************************************************************************/ + +ST_RET mp_cancel_err (MMSREQ_IND *indptr, ST_INT16 err_class, ST_INT16 code) + { +ST_UCHAR *msg_ptr; /* pointer to start of message */ +ST_INT msg_len; /* length of message built */ +ST_RET ret; /* function return value */ +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + S_LOCK_COMMON_RESOURCES (); + if (!(ret = _ms_check_ind_actv (indptr))) + { + if (indptr->cancl_state != CANCELING) + { + S_UNLOCK_COMMON_RESOURCES (); + return (MVE_CANCEL_STATE); + } + msg_ptr = _ms_mk_err_resp (aCtx, m_build_buf,mms_max_msgsize,MMSOP_CANCEL,indptr->id, + err_class,code); + msg_len = M_BUILD_BUF_END - msg_ptr; /* find length */ + + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + ret = ME_ASN1_ENCODE_OVERRUN; + else + ret = _mms_send_data (indptr->chan, msg_len, msg_ptr, + indptr->context, indptr->add_addr_info); + } + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +#else +/************************************************************************/ +/* mpl_cancel_err */ +/* Create a cancel error response */ +/************************************************************************/ + +ST_RET mpl_cancel_err (ST_UINT32 invoke, ST_INT16 err_class, ST_INT16 code) + { + return (mpl_err_resp (MMSOP_CANCEL,invoke,err_class,code)); + } + +#endif diff --git a/mmslib/mmsl/mms_rej.c b/mmslib/mmsl/mms_rej.c new file mode 100644 index 0000000..991bc80 --- /dev/null +++ b/mmslib/mmsl/mms_rej.c @@ -0,0 +1,281 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_rej.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the functions to decode/encode a reject */ +/* operation. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Cleaned up "thisFileName" */ +/* 01/18/02 JRB 05 Fix encoding if !DEBUG_SISCO (use new fcts */ +/* _ms_fin_pdu & _ms_fin_pdu_log. */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pcon.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) && defined(S_MT_SUPPORT) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ + +static REJECT_RESP_INFO *rej_info_ptr; + +static ST_VOID rej_get_problem (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code); + + +/************************************************************************/ +/************************************************************************/ +/* mms_reject */ +/* Reject PDU is being decoded, and this is a context-specific element. */ +/* It should be an integer. */ +/************************************************************************/ + +ST_VOID mms_reject (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code) + { + MLOG_CDEC0 ("mms_reject"); + + if (aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, PDU_INVALID); + return; + } + + rej_info_ptr = (REJECT_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (REJECT_RESP_INFO)); + aCtx->asn1r_decode_method = ASN1_CLASS_METHOD; + rej_info_ptr -> detected_here = SD_FALSE; /* reject detected remotely */ + rej_info_ptr -> pdu_type = UNKNOWNTYPE; /* in this case, no pdu type */ + + if (!id_code) /* if this is invoke id - */ + { + if (asn1r_get_u32 (aCtx, &rej_info_ptr -> invoke)) /* read invoke id */ + asn1r_set_dec_err (aCtx, PDU_INVALID); + else + { + rej_info_ptr -> invoke_known = SD_TRUE; /* set flag */ + _mmsdec_rslt -> dec_level = 2; + _mmsdec_rslt -> id = rej_info_ptr -> invoke; /* store invoke ID */ + aCtx->asn1r_c_id_fun = rej_get_problem; + } + } + else + { + rej_info_ptr -> invoke_known = SD_FALSE; /* clear */ + rej_get_problem (aCtx, id_code); /* call rejectreason fun direct */ + } + } + +/************************************************************************/ +/* rej_get_problem */ +/* Reject PDU is being decoded, and this is a context-specific element. */ +/* It should be an integer in which the tag is the error class and the */ +/* value is the error code. */ +/************************************************************************/ + +static ST_VOID rej_get_problem (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code) + { + MLOG_CDEC0 ("rej_get_problem"); + + if (aCtx->asn1r_constr_elmnt || id_code < 1 || id_code > 11 || aCtx->asn1r_elmnt_len > 1) + { /* better not be constructor */ + asn1r_set_dec_err (aCtx, PDU_INVALID); /* better be context tagged 1-4 */ + return; /* max value = 8 */ + } + +/* Information looks OK; extract it. */ + + rej_info_ptr -> rej_class = id_code; + asn1r_get_i16 (aCtx, &rej_info_ptr -> rej_code); /* get the problem value */ + + aCtx->asn1r_decode_done_fun = _mms_dec_done_ok; /* all done now */ + aCtx->asn1r_decode_done = SD_TRUE; + } + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_reject_resp */ +/* Sends reject message. Returns integer value indicating success */ +/* (value = 0) or failure (value <> 0) to send the reject message. */ +/************************************************************************/ + +ST_RET mp_reject_resp (ST_INT chan, REJECT_RESP_INFO *info_ptr) + { +ST_UCHAR *msg_ptr; +ST_INT msg_len; +LLP_ADDR_INFO add_llp_info; +ST_RET ret; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + S_LOCK_COMMON_RESOURCES (); + msg_ptr = _ms_mk_reject (aCtx, m_build_buf,mms_max_msgsize,info_ptr); + msg_len = M_BUILD_BUF_END - msg_ptr; /* find length */ + + add_llp_info.i.LLC.use_rem_addr = SD_FALSE; + add_llp_info.i.LLC.send_type = REJECT_PDU; + add_llp_info.i.LLC.req_ptr = (ST_CHAR *)NULL; + +/* Check for encode overrun */ + if (aCtx->asn1r_encode_overrun) + ret = ME_ASN1_ENCODE_OVERRUN; + else + ret = _mms_send_data (chan, msg_len, msg_ptr, P_context_sel[chan], &add_llp_info); + + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_reject_resp */ +/* Sends reject message. Returns integer value indicating success */ +/* (value = 0) or failure (value <> 0) to send the reject message. */ +/************************************************************************/ + +ST_RET mpl_reject_resp (REJECT_RESP_INFO *info_ptr) + { +ST_RET ret; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + S_LOCK_COMMON_RESOURCES (); + mmsl_msg_start = _ms_mk_reject (aCtx, mmsl_enc_buf,mmsl_enc_buf_size,info_ptr); + /* find length */ + mmsl_msg_len = (mmsl_enc_buf + mmsl_enc_buf_size) - mmsl_msg_start; + + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + ret = ME_ASN1_ENCODE_OVERRUN; + else + ret = SD_SUCCESS; + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } +#endif + +/************************************************************************/ +/* _ms_mk_reject */ +/* Construct a reject PDU. */ +/************************************************************************/ + +ST_UCHAR *_ms_mk_reject (ASN1_ENC_CTXT *aCtx, ST_UCHAR *msg_ptr, ST_INT buf_len, + REJECT_RESP_INFO *info_ptr) + { +ST_UCHAR *pduStart; +ST_INT pduLen; + + asn1r_strt_asn1_bld (aCtx, msg_ptr,buf_len); /* init the ASN.1 tools */ + + asn1r_wr_i16 (aCtx, info_ptr -> rej_code); + asn1r_fin_prim (aCtx, info_ptr -> rej_class,CTX); + +#ifndef MMS_LITE + if (info_ptr->invoke_known && info_ptr->invoke <= MAX_INVOKE) +#else + if (info_ptr->invoke_known) +#endif + { + asn1r_wr_u32 (aCtx, info_ptr -> invoke); /* if the invoke ID is known & */ + asn1r_fin_prim (aCtx, 0,CTX); /* is not artificial, write it */ + } + + pduStart = _ms_fin_pdu (aCtx, MMSREJECT, &pduLen); +#ifdef DEBUG_SISCO + _ms_fin_pdu_log (MMSREJECT, "REJECT", pduStart, pduLen); +#endif + + return (pduStart); + } + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* _ms_reject_resp */ +/* Function to reject an MMS confirmed response pdu, given the request */ +/* control structure. This must be a valid response, parsed OK. */ +/* Called by the user or virtual machine after the confirm is matched. */ +/************************************************************************/ + +ST_VOID _ms_reject_resp (MMSREQ_PEND *reqptr, ST_INT16 code) + { +REJECT_RESP_INFO info; /* reject input info structure */ + + info.detected_here = SD_TRUE; /* parse error detected locally */ + + info.invoke_known = SD_TRUE; + info.invoke = reqptr->id; + + info.pdu_type = MMSRESP; /* confirmed response */ + info.rej_code = code; /* include error code */ + info.rej_class = 2; /* invalid response class */ + + if (mp_reject_resp (reqptr->chan,&info)) /* send the reject pdu */ + (*u_mmsexcept_ind_fun)(reqptr->chan,MX_REJECT); + (*u_reject_ind_fun) (reqptr->chan,&info); + } + +/************************************************************************/ +/* mp_reject_ind */ +/************************************************************************/ + +ST_RET mp_reject_ind (MMSREQ_IND *req_ptr, REJECT_RESP_INFO *info_ptr) + { +ST_RET ret; /* function return value */ + + S_LOCK_COMMON_RESOURCES (); + if (!(ret = _ms_check_ind_actv (req_ptr))) + { + if (!(ret = mp_reject_resp (req_ptr->chan, info_ptr))) + _ms_ind_serve_done (req_ptr); + } + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +/************************************************************************/ +/* mp_reject_conf */ +/************************************************************************/ + +ST_RET mp_reject_conf (MMSREQ_PEND *req_ptr, REJECT_RESP_INFO *info_ptr) + { +ST_RET ret; /* function return value */ + + S_LOCK_COMMON_RESOURCES (); + if (!(ret = _ms_check_req_actv (req_ptr))) + { + ret = mp_reject_resp (req_ptr->chan, info_ptr); + } + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +#endif diff --git a/mmslib/mmsl/mms_rtaa.c b/mmslib/mmsl/mms_rtaa.c new file mode 100644 index 0000000..d80447b --- /dev/null +++ b/mmslib/mmsl/mms_rtaa.c @@ -0,0 +1,1222 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_rtaa.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Function to decode ASN.1 type definitions into Runtime typedefs */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _ms_mk_rt_aa_all */ +/* _ms_mk_rt_aa */ +/* _ms_get_rtaa_data_size */ +/* _ms_log_runtime_aa */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/27/05 MDE 06 if m_max_rt_aa_cltr == 0 calc required size */ +/* 05/11/05 MDE 05 Added _ms_calc_rt_aa_size */ +/* 02/22/05 JRB 04 Make "sp" local to avoid VXWORKS conflict. */ +/* 04/02/03 JRB 03 Add UTF8string support (see RT_UTF8_STRING). */ +/* 03/04/02 JRB 02 Add more "SD_CONST RUNTIME_TYPE *". */ +/* Make sure str_end_rtaa, arr_end_rtaa init'd. */ +/* 02/06/02 JRB 01 New. Code from mms_alta.c moved here. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ + +#define COPY_RTAA(dest,src) { dest->rt = src->rt;\ + dest->offset_to_data = src->offset_to_data; } + +/************************************************************************/ +/************************************************************************/ +/* This code is required for handling real alternate access data */ +/* conversion via mmsdataa, and for using the ARB DATA handlers. */ + +/************************************************************************/ +/************************************************************************/ +/* Runtime AA (RTAA) Handling */ +/************************************************************************/ +/************************************************************************/ +static ST_VOID _ms_calc_rt_aa_size (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + ST_INT *num_aa_out); + +static ST_RET get_struct_comps (AA_APPLY_CTRL *aa_app, RT_AA_CTRL *w_rtaa); +static ST_RET get_arr_elmnts (AA_APPLY_CTRL *aa_app, RT_AA_CTRL *w_rtaa); +static ST_INT count_num_comp (AA_APPLY_CTRL *aa_app, + ALT_ACC_EL *aa, + ST_INT *count_out); + +static RT_AA_CTRL *find_end_rtaa (AA_APPLY_CTRL *aa_app, + RT_AA_CTRL *start_rtaa); + +static RT_AA_CTRL *find_named_comp (AA_APPLY_CTRL *aa_app, + ST_CHAR *name, + RT_AA_CTRL *w_rtaa); + +static ST_RET get_component_elmnts (AA_APPLY_CTRL *aa_app, + RT_AA_CTRL *rtaa); + +static RT_AA_CTRL *find_arr_el (AA_APPLY_CTRL *aa_app, + RT_AA_CTRL *w_rtaa, + ST_INT el_index); +static ST_VOID ms_rtaa_el_size_calc (RT_AA_CTRL *runtime_aa, ST_INT num_rt_aa); + +static ST_INT arr_loop_level; +static ST_INT *arr_loops; + +/************************************************************************/ +/* Create a RTAA with all elements for the specified RT type */ +/* This table is allocated via chk_calloc, and is sized for the max */ +/* possible AA size. If desired, this may be realloc'd to the correct */ +/* size by the caller. */ + +ST_RET _ms_mk_rt_aa_all (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + RT_AA_CTRL **rt_aa_out, ST_INT *num_aa_out) + { +RT_AA_CTRL *rtaa; +ST_INT data_offset; +SD_CONST RUNTIME_TYPE *rt_end; +SD_CONST RUNTIME_TYPE *rt; +ST_INT arr_loop_buf[ASN1_MAX_LEVEL]; +ST_INT _max_rt_aa_ctrl; + + S_LOCK_COMMON_RESOURCES (); + + arr_loop_level = 0; + arr_loops = arr_loop_buf; + +/* Allocate the output array for max size */ + _max_rt_aa_ctrl = m_max_rt_aa_ctrl; + if (_max_rt_aa_ctrl == 0) + _ms_calc_rt_aa_size (rt_head, rt_num, &_max_rt_aa_ctrl); + + rtaa = (RT_AA_CTRL *) chk_calloc (_max_rt_aa_ctrl, sizeof (RT_AA_CTRL)); + *rt_aa_out = rtaa; + *num_aa_out = 0; + + rt = rt_head; /* set runtime ptr */ + rt_end = rt_head + rt_num; /* end block */ + data_offset = 0; + +/* Traverse the RT type as though we were doing a ASN.1 to LOCAL, and */ +/* set the RTAA RT pointer and offset as each element is encountered. */ + + while (rt < rt_end) + { + if (rt->el_tag == RT_ARR_END) /* treat case of array ending */ + { + if (--arr_loops[arr_loop_level] > 0) /* if need to do next ar elmnt */ + { + rt -= rt->u.arr.num_rt_blks; /* mv rt to start of arr */ + continue; + } + else + --arr_loop_level; + } + + (*num_aa_out)++; /* Count this one */ + rtaa->rt = rt; /* Set the RT pointer */ + rtaa->offset_to_data = data_offset; /* Set the offset */ + data_offset += rt->el_size; /* Offset for next */ + + if (rt->el_tag == RT_ARR_START) /* Set up array looping */ + { + ++arr_loop_level; + arr_loops[arr_loop_level] = rt->u.arr.num_elmnts; + } + + rtaa++; /* point to next runtime AA element */ + rt++; /* point to next runtime element */ + } + +/* Post process to calculate the 'rtaa->el_size' values (for packed */ +/* local representation). */ + ms_rtaa_el_size_calc (*rt_aa_out, *num_aa_out); + + if (mms_debug_sel & MMS_LOG_RTAA) + _ms_log_runtime_aa (*rt_aa_out, *num_aa_out); + +/* save the high water mark */ + if (*num_aa_out > m_hw_rt_aa_ctrl) + m_hw_rt_aa_ctrl = *num_aa_out; + + S_UNLOCK_COMMON_RESOURCES (); + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* _ms_calc_rt_aa_size */ +/************************************************************************/ + +static ST_VOID _ms_calc_rt_aa_size (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + ST_INT *num_aa_out) + { +SD_CONST RUNTIME_TYPE *rt_end; +SD_CONST RUNTIME_TYPE *rt; +ST_INT arr_loop_buf[ASN1_MAX_LEVEL]; +ST_INT num_aa; + + S_LOCK_COMMON_RESOURCES (); + arr_loop_level = 0; + arr_loops = arr_loop_buf; + + num_aa = 0; + rt = rt_head; /* set runtime ptr */ + rt_end = rt_head + rt_num; /* end block */ + +/* Traverse the RT type as though we were doing a ASN.1 to LOCAL, and */ +/* count the RTAA elements */ + while (rt < rt_end) + { + if (rt->el_tag == RT_ARR_END) /* treat case of array ending */ + { + if (--arr_loops[arr_loop_level] > 0) /* if need to do next ar elmnt */ + { + rt -= rt->u.arr.num_rt_blks; /* mv rt to start of arr */ + continue; + } + else + --arr_loop_level; + } + ++num_aa; /* Count this one */ + + if (rt->el_tag == RT_ARR_START) /* Set up array looping */ + { + ++arr_loop_level; + arr_loops[arr_loop_level] = rt->u.arr.num_elmnts; + } + rt++; /* point to next runtime element */ + } + *num_aa_out = num_aa; + S_UNLOCK_COMMON_RESOURCES (); + } + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* Create a RTAA with elements selected by a AA for the specified RT */ +/* type */ +/* This table is allocated via chk_calloc, and is sized for the max */ +/* possible AA size. If desired, this may be realloc'd to the correct */ +/* size by the caller. */ + +ST_RET _ms_mk_rt_aa (SD_CONST RUNTIME_TYPE *rt, ST_INT rt_num, + ALT_ACCESS *alt_acc, + RT_AA_CTRL **rt_aa_out, ST_INT *num_aa_out) + { +ALT_ACC_EL *aa; +ST_INT num_aa; +ST_RET ret; +ST_INT num_all_rtaa; +RT_AA_CTRL *all_rtaa; +RT_AA_CTRL *rtaa; +AA_APPLY_CTRL aa_app_ctrl; +ST_UINT32 mms_log_mask_save; +ST_INT _max_rt_aa_ctrl; + + S_LOCK_COMMON_RESOURCES (); + + aa = alt_acc->aa; + num_aa = alt_acc->num_aa; + +/* Make the 'all' rtaa - has all elements expanded, with offsets. */ +/* This is used with the AA to select the elements for the new RTAA */ + +/* Don't allow logging of the 'all' runtime aa table */ + mms_log_mask_save = mms_debug_sel; + mms_debug_sel &= ~MMS_LOG_RTAA; + ret = _ms_mk_rt_aa_all (rt, rt_num, &all_rtaa, &num_all_rtaa); + mms_debug_sel = mms_log_mask_save; + + if (ret) + { + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +/* Allocate the output (new) RT AA table */ + _max_rt_aa_ctrl = m_max_rt_aa_ctrl; + if (_max_rt_aa_ctrl == 0) + _ms_calc_rt_aa_size (rt, rt_num, &_max_rt_aa_ctrl); + + rtaa = (RT_AA_CTRL *) chk_calloc (_max_rt_aa_ctrl, sizeof (RT_AA_CTRL)); + *rt_aa_out = rtaa; + *num_aa_out = 0; + +/* Initialize the AA process control structure components */ + +/* Alternate Access */ + aa_app_ctrl.num_aa = num_aa; + aa_app_ctrl.aa_head = aa; + aa_app_ctrl.aa_end = aa + num_aa - 1; + aa_app_ctrl.curr_aa = aa; + +/* Default RTAA */ + aa_app_ctrl.num_all_rtaa = num_all_rtaa; + aa_app_ctrl.all_rtaa_head = all_rtaa; + aa_app_ctrl.all_rtaa_end = all_rtaa + (num_all_rtaa -1); + +/* New RTAA */ + aa_app_ctrl.num_rtaa = 0; + aa_app_ctrl.rtaa_head = rtaa; + aa_app_ctrl.curr_rtaa = rtaa; + +/* Nest Level */ + aa_app_ctrl.nest = 0; + +/* Get the appropriate rt_aa_ctrl elements */ +/* Start by getting the first nest level elements, based on the RT. */ +/* Note that these functions will call recursively to get handle */ +/* further nest levels */ + + if (rt->el_tag == RT_ARR_START) + { + ret = get_arr_elmnts (&aa_app_ctrl, all_rtaa); + } + else if (rt->el_tag == RT_STR_START) + { + ret = get_struct_comps (&aa_app_ctrl, all_rtaa); + } + else + { + MLOG_NERR0 ("Runtime Type must be a Structure or Array for AA"); + ret = MVE_RT_TYPE; + } + +/* If successful, set the output AA count and log if enabled */ + if (ret == SD_SUCCESS) + { + *num_aa_out = aa_app_ctrl.num_rtaa; + +/* Post process to calculate the 'rtaa->el_size' values (for packed */ +/* local representation). */ + ms_rtaa_el_size_calc (*rt_aa_out, *num_aa_out); + + if (mms_debug_sel & MMS_LOG_RTAA) + _ms_log_runtime_aa (*rt_aa_out, *num_aa_out); + +/* save the high water mark */ + if (*num_aa_out > m_hw_rt_aa_ctrl) + m_hw_rt_aa_ctrl = *num_aa_out; + } + else + { + chk_free (rtaa); /* If error, need to free the RTAA */ + } + + chk_free (all_rtaa); /* we are done with the 'all' RTAA */ + S_UNLOCK_COMMON_RESOURCES (); + + return (ret); + } + +/************************************************************************/ +/* We are working on a structure level, and need to copy the selected */ +/* RTAA components for this nest level. This function can be called */ +/* recursively as further nesting levels are encountered. */ +/* The 'w_rtaa' parameter is the 'working' RTAA, and is used to select */ +/* the scope (nest) for the operation */ + +static ST_RET get_struct_comps (AA_APPLY_CTRL *aa_app, RT_AA_CTRL *w_rtaa) + { +ST_RET ret; +RT_AA_CTRL *o_rtaa; +ALT_ACC_EL *aa; +ST_INT num_str_comp; +RT_AA_CTRL *start_rtaa; +RT_AA_CTRL *str_end_rtaa = NULL; +ST_BOOLEAN done; + +/* get working pointers */ + aa = aa_app->curr_aa; /* Current AA */ + o_rtaa = aa_app->curr_rtaa; /* Output RTAA */ + +/* Check to see if we need to have the outer structure */ +/* We need this if there are more than 1 named components selected */ + + if (count_num_comp (aa_app, aa, &num_str_comp)) + return (MVE_AA_SELECT); + + if (num_str_comp != 1) + { + str_end_rtaa = find_end_rtaa (aa_app, w_rtaa); + if (!str_end_rtaa) + return (MVE_AA_SELECT); + + /* Write the start component of the output rtaa */ + COPY_RTAA (o_rtaa,w_rtaa); + aa_app->num_rtaa++; + aa_app->curr_rtaa++; + } + +/* Get all selected named components */ + ret = SD_SUCCESS; + done = SD_FALSE; + while (!done && ret == SD_SUCCESS) + { + aa = aa_app->curr_aa; /* get current AA pointer */ + o_rtaa = aa_app->curr_rtaa; /* get the output RTAA pointer */ + + /* This AA sel type can be a named component (w/wo further nesting) */ + /* or a 'end nest' element. */ + switch (aa->sel_type) + { + case AA_COMP : + /* This AA selects a entire named component. Just find the */ + /* component name in the ALL RTAA and copy it's RTAA elements */ + + start_rtaa = find_named_comp (aa_app, aa->u.component, w_rtaa); + if (!start_rtaa) + { + return (MVE_AA_SELECT); + } + ret = get_component_elmnts (aa_app, start_rtaa); + ++aa_app->curr_aa; + break; + + case AA_COMP_NEST : + /* This AA selects a named component, with further selection. */ + /* Find the component name in the ALL RTAA and call recursively */ + /* to get the components. */ + + /* This component must be a structure or an array, so that we */ + /* need to call recursively to get the selected RT AA elements */ + + start_rtaa = find_named_comp (aa_app, aa->u.component, w_rtaa); + if (!start_rtaa) + return (MVE_AA_SELECT); + + ++aa_app->nest; /* Increment the nest level */ + /* Point to the next AA */ + if (aa_app->curr_aa < aa_app->aa_end) + ++aa_app->curr_aa; + else + { + MLOG_NERR0 ("AA table too small"); + return (MVE_AA_SELECT); + } + + /* Based on the RT type, get the next level with the scope */ + /* defined by the start RTAA. */ + if (start_rtaa->rt->el_tag == RT_ARR_START) + { + ret = get_arr_elmnts (aa_app, start_rtaa); + } + else if (start_rtaa->rt->el_tag == RT_STR_START) + { + ret = get_struct_comps (aa_app, start_rtaa); + } + else + { + MLOG_NERR0 ("Incorrect RT Type for further nesting"); + return (MVE_RT_TYPE); + } + --aa_app->nest; /* Decrement the nest level */ + + /* curr_aa should now point to our END_NEST, consume it */ + if (aa_app->curr_aa->sel_type != AA_END_NEST) + { + MLOG_NERR0 ("Required AA_END_NEST not present"); + return (MVE_AA_SELECT); + } + else /* Consume the AA_END_NEST */ + ++aa_app->curr_aa; + break; + + case AA_END_NEST : + done = SD_TRUE; /* This level is complete */ + break; + + case AA_ALL : + case AA_ALL_NEST : + case AA_INDEX_NEST : + case AA_INDEX_RANGE_NEST : + case AA_INDEX : + case AA_INDEX_RANGE : + MLOG_NERR0 ("Incorrect AA sel_type for structure component selection"); + return (MVE_AA_SELECT); + break; + + default : + MLOG_NERR0 ("Invalid AA sel_type"); + return (MVE_AA_SELECT); + break; + } + + /* Prepare to look at next AA, if this was not the last */ + if (aa_app->curr_aa > aa_app->aa_end) + done = SD_TRUE; + } /* End while getting named components at this level */ + + +/* Don't continue if an error was detected */ + if (ret) + return (ret); + + +/* Now copy the structure end element if required */ + if (num_str_comp != 1) + { + o_rtaa = aa_app->curr_rtaa; + COPY_RTAA (o_rtaa, str_end_rtaa); + aa_app->num_rtaa++; + aa_app->curr_rtaa++; + } + + return (ret); + } + +/************************************************************************/ +/* We are working on a array selection, and need to copy the selected */ +/* RTAA components for this selection. This function can be called */ +/* recusively as further nesting levels are encountered. */ +/* The 'w_rtaa' parameter is the 'working' RTAA, and is used to select */ +/* the scope (nest) for the operation */ + + +static ST_RET get_arr_elmnts (AA_APPLY_CTRL *aa_app, RT_AA_CTRL *w_rtaa) + { +ST_RET ret; +ST_INT i; +RT_AA_CTRL *el_rtaa; +RT_AA_CTRL *o_rtaa; +RT_AA_CTRL *arr_end_rtaa = NULL; +ST_INT nest; +ALT_ACC_EL *aa; +ST_INT num_el; +ST_INT start_el; +ST_INT curr_el; + + + ret = SD_SUCCESS; + +/* get working pointers */ + aa = aa_app->curr_aa; /* Current AA */ + o_rtaa = aa_app->curr_rtaa; /* Output RTAA */ + + /* This AA sel type must be one of the array selection types, */ + /* (w/wo further nesting) */ + + /* Start by determining the number of elements and the start element */ + switch (aa->sel_type) + { + case AA_INDEX : + case AA_INDEX_NEST : + num_el = 1; + start_el = (ST_INT) aa->u.index; + break; + + case AA_INDEX_RANGE : + case AA_INDEX_RANGE_NEST : + num_el = (ST_INT) aa->u.ir.num_elmnts; + start_el = (ST_INT) aa->u.ir.low_index; + if (!num_el && !start_el) + { + num_el = w_rtaa->rt->u.arr.num_elmnts; + start_el = 0; + } + break; + + case AA_ALL : + case AA_ALL_NEST : + num_el = w_rtaa->rt->u.arr.num_elmnts; + start_el = 0; + break; + + case AA_COMP : + case AA_COMP_NEST : + MLOG_NERR0 ("Invalid AA Type"); + return (MVE_AA_SELECT); + break; + + default : + MLOG_NERR0 ("Bad AA Type"); + return (MVE_AA_SELECT); + break; + } + +/* num_el is the number of elements to get, start_el is the base index */ +/* w_rtaa points to the start of the array in the default RTAA */ + +/* Determine whether the array elements have further AA select ... */ + if (aa->sel_type == AA_INDEX_NEST || + aa->sel_type == AA_INDEX_RANGE_NEST || + aa->sel_type == AA_ALL_NEST) + { + nest = SD_TRUE; + } + else + nest = SD_FALSE; + + +/* Check to see if we need to have the outer array */ +/* We need this if there are more than 1 element selected */ + + if (num_el != 1) + { + arr_end_rtaa = find_end_rtaa (aa_app, w_rtaa); + if (!arr_end_rtaa) + return (MVE_AA_SELECT); + + /* Write the start component of the output rtaa */ + COPY_RTAA (o_rtaa,w_rtaa); + aa_app->num_rtaa++; + aa_app->curr_rtaa++; + } + +/* Now we work through the array elements, getting them one at a time */ + curr_el = start_el; + for (i = 0; i < num_el && ret == SD_SUCCESS; ++i, ++curr_el) + { + aa_app->curr_aa = aa; /* Restore the working AA position */ + o_rtaa = aa_app->curr_rtaa; /* Output RTAA */ + + /* Move the working RTAA pointer to the next element to be selected */ + el_rtaa = find_arr_el (aa_app, w_rtaa, curr_el); + if (!el_rtaa) + return (MVE_AA_SELECT); + + /* If further selection is to take place, do it */ + if (nest) + { + /* Set up working parameters for the nest level of nesting */ + if (aa_app->curr_aa < aa_app->aa_end) + ++aa_app->curr_aa; + else + { + MLOG_NERR0 ("AA table too small"); + return (MVE_AA_SELECT); + } + ++aa_app->nest; /* Increment the nest level */ + + if (el_rtaa->rt->el_tag == RT_ARR_START) + { + ret = get_arr_elmnts (aa_app, el_rtaa); + } + else if (el_rtaa->rt->el_tag == RT_STR_START) + { + ret = get_struct_comps (aa_app, el_rtaa); + } + else /* Whoops, internal error */ + { + MLOG_NERR0 ("Bad RT Type for further AA selection"); + return (MVE_RT_TYPE); + } + --aa_app->nest; /* Decrement the nest level */ + } + else /* No further selection, copy the compoment */ + { + ret = get_component_elmnts (aa_app, el_rtaa); + } + } /* end for each selected element */ + + +/* Now copy the array end element if required */ + if (ret == SD_SUCCESS && num_el != 1) + { + o_rtaa = aa_app->curr_rtaa; + COPY_RTAA (o_rtaa, arr_end_rtaa); + aa_app->num_rtaa++; + aa_app->curr_rtaa++; + } + + if (nest) + { + /* curr_aa should now point to our END_NEST, consume it */ + if (aa_app->curr_aa->sel_type != AA_END_NEST) + { + MLOG_NERR0 ("Required AA_END_NEST not present"); + ret = MVE_AA_SELECT; + } + else /* Consume the AA_END_NEST */ + ++aa_app->curr_aa; + } + else + ++aa_app->curr_aa; /* Point to the next AA */ + + return (ret); + } + +/************************************************************************/ +/************************************************************************/ +/* Given the array or structure start RTAA pointer, return a pointer to */ +/* the corresponding end element */ + +static RT_AA_CTRL *find_end_rtaa (AA_APPLY_CTRL *aa_app, + RT_AA_CTRL *start_rtaa) + { +SD_CONST RUNTIME_TYPE *start_rt; +SD_CONST RUNTIME_TYPE *end_rt; +ST_INT num_rt; +RT_AA_CTRL *rtaa; + + start_rt = start_rtaa->rt; + if (start_rt->el_tag == RT_ARR_START) + { + num_rt = start_rt->u.arr.num_rt_blks; + } + else if (start_rt->el_tag == RT_STR_START) + { + num_rt = start_rt->u.str.num_rt_blks; + } + else + { + MLOG_NERR0 ("Bad RT Type"); + return (NULL); + } + + end_rt = start_rt + (num_rt + 1); + +/* Just a trivial sanity check */ + if (end_rt->el_tag != RT_ARR_END && + end_rt->el_tag != RT_STR_END) + { + MLOG_NERR0 ("Bad RT Type"); + return (NULL); + } + +/* Now find the RTAA that has a reference to the end structure */ +/* within this scope (we hope!) */ + + for (rtaa = start_rtaa; rtaa <= aa_app->all_rtaa_end; ++rtaa) + { + if (rtaa->rt == end_rt) + return (rtaa); + } + + MLOG_NERR0 ("End RT Not Found"); + return (NULL); + } + +/************************************************************************/ +/* Copy the current RTAA element, including any sub-elements */ + +static ST_RET get_component_elmnts (AA_APPLY_CTRL *aa_app, RT_AA_CTRL *rtaa) + { +RT_AA_CTRL *last_rtaa; +RT_AA_CTRL *dest_rtaa; + + if (rtaa->rt->el_tag == RT_ARR_START || + rtaa->rt->el_tag == RT_STR_START) + { + last_rtaa = find_end_rtaa (aa_app, rtaa); + if (!last_rtaa) + return (MVE_AA_SELECT); + } + else /* Simple element, just copy one */ + last_rtaa = rtaa; + + dest_rtaa = aa_app->curr_rtaa; + while (rtaa <= last_rtaa) + { + COPY_RTAA (dest_rtaa, rtaa); + aa_app->num_rtaa++; + aa_app->curr_rtaa++; + ++dest_rtaa; + ++rtaa; + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* Count the number of named components selected at this level */ +/* by the alternate access select */ + +static ST_INT count_num_comp (AA_APPLY_CTRL *aa_app, + ALT_ACC_EL *aa, + ST_INT *count_out) + { +ST_INT count; +ST_INT nest; +ST_INT done; + + done = SD_FALSE; + nest = 0; + count = 0; + while (done == SD_FALSE) + { + switch (aa->sel_type) + { + case AA_COMP : + if (nest == 0) + ++count; + break; + + case AA_COMP_NEST : + if (nest == 0) + ++count; + nest++; + break; + + case AA_INDEX : + case AA_INDEX_RANGE : + case AA_ALL : + break; + + case AA_INDEX_NEST : + case AA_INDEX_RANGE_NEST : + case AA_ALL_NEST : + nest++; + break; + + case AA_END_NEST : + if (--nest < 0) + done = SD_TRUE; + break; + + default : + MLOG_NERR0 ("Bad AA Type"); + return (MVE_AA_SELECT); + break; + } + + if (aa >= aa_app->aa_end) /* If we are done (level 0 only) */ + done = SD_TRUE; + + aa++; /* Point to next */ + } + + *count_out = count; + return (SD_SUCCESS); + } + + +/************************************************************************/ +/* Given a RTAA pointer, find a named component at the current nest */ +/* The 'w_rtaa' parameter is the 'working' RTAA, and is used to select */ +/* the scope (nest) for the operation */ + +static RT_AA_CTRL *find_named_comp (AA_APPLY_CTRL *aa_app, + ST_CHAR *name, + RT_AA_CTRL *w_rtaa) + { +ST_INT nest; +ST_INT err; + + if (w_rtaa->rt->el_tag != RT_STR_START) + { + MLOG_NERR0 ("Bad RT Type - must be structure start"); + return (NULL); + } + w_rtaa++; + + nest = 0; + err = SD_FALSE; + while (!err) + { + if (nest == 0 && + !strcmp (name, ms_comp_name_find (w_rtaa->rt))) + { + return (w_rtaa); + } + switch (w_rtaa->rt->el_tag) + { + case RT_ARR_START : + case RT_STR_START : + nest++; + break; + + case RT_STR_END : + case RT_ARR_END : + if (--nest < 0) + break; + break; + + case RT_BOOL : + case RT_BIT_STRING : + case RT_INTEGER : + case RT_UNSIGNED : + case RT_FLOATING_POINT : + case RT_OCTET_STRING : + case RT_VISIBLE_STRING : + case RT_GENERAL_TIME : + case RT_BINARY_TIME : + case RT_BCD : + case RT_UTC_TIME : + case RT_BOOLEANARRAY : + case RT_UTF8_STRING : + break; + + default : + err = SD_TRUE; + MLOG_NERR0 ("Bad RT Type"); + break; + } + + w_rtaa++; + if (w_rtaa >= aa_app->all_rtaa_end) + break; + } + + MLOG_NERR1 ("AA Named component (%s) not found", name); + return (NULL); + } + + +/************************************************************************/ +/************************************************************************/ +/* Given a 'working' RTAA pointer to the RT_ARR_START element and the */ +/* element index, return a pointer to the start RTAA for the element */ +/* The 'w_rtaa' parameter is the 'working' RTAA, and is used to select */ +/* the scope (nest) for the operation */ + +static RT_AA_CTRL *find_arr_el (AA_APPLY_CTRL *aa_app, + RT_AA_CTRL *w_rtaa, + ST_INT el_index) + { +RT_AA_CTRL *ret_rtaa; +SD_CONST RUNTIME_TYPE *arr_rt; +SD_CONST RUNTIME_TYPE *start_rt; +ST_INT el; + + arr_rt = w_rtaa->rt; + if (arr_rt->el_tag != RT_ARR_START) + { + MLOG_NERR0 ("RTAA is not RT_ARR_START"); + return (NULL); + } + if (el_index >= arr_rt->u.arr.num_elmnts) + { + MLOG_NERR0 ("Index out of range"); + return (NULL); + } + +/* Now we need to locate the el_index'th element. To do this, we first */ +/* get a pointer to the 0'th element's first RT block, then search for */ +/* the el_index'th occurance of the RT within the RTAA */ + + w_rtaa++; /* 0'th element */ + start_rt = w_rtaa->rt; /* Start RT block */ + el = 0; + while (w_rtaa <= aa_app->all_rtaa_end) /* while still in RTAA */ + { + if (w_rtaa->rt == start_rt) /* if start of an element */ + { + if (el == el_index) /* if selected element */ + return (w_rtaa); /* we found it */ + else + ++el; /* maybe next time */ + } + w_rtaa++; /* look at next RTAA */ + } + + ret_rtaa = (w_rtaa+1) + (el_index * arr_rt->u.arr.num_rt_blks); + return (ret_rtaa); + } + + +/************************************************************************/ +/* ms_rtaa_el_size_calc */ +/************************************************************************/ + +/* Given a RTAA table, calculate the 'el_size' for each element. This */ +/* is done by using the alignment control table, and is used only for */ +/* encoding/decoding AA data that is 'packed' in local memory. */ + +static ST_VOID ms_rtaa_el_size_calc (RT_AA_CTRL *runtime_aa, + ST_INT num_rt_aa) + { +ST_INT ellen; +SD_CONST RUNTIME_TYPE *rt; +RT_AA_CTRL *rtaa_above; +ST_INT curr_offset; +ST_INT pad; +ST_INT algn; +ST_INT i; + + curr_offset = 0; /* Offset from start of data */ + rtaa_above = NULL; + for (i = 0; i < num_rt_aa; ++i, ++runtime_aa) + { + rt = runtime_aa->rt; + + /* Get 'algnment index' and size of the element (excluding padding) */ + _ms_m_get_rt_info (rt, &algn, &ellen); + + /* Set the base element size, before padding */ + runtime_aa->el_size = ellen; + + /* Check to see if padding on the element above is required for */ + /* alignment for this element, add it if so. */ + /* Increment the offset until no bits are set that shouldn't be */ + pad = 0; + while (curr_offset & algn) + { + curr_offset++; + pad++; + } + + if (pad) + { + if (!rtaa_above) /* First element better not require alignment */ + { + MLOG_ERR0 ("Alignment table error"); + } + else /* add pad to element above */ + rtaa_above->el_size += pad; + } + + /* Save the pointer to the previous RT element (not this one's name) */ + rtaa_above = runtime_aa; + + /* Point past the current element */ + curr_offset += ellen; + } + } + +/************************************************************************/ +/* _ms_get_rtaa_data_size */ +/************************************************************************/ + +ST_INT _ms_get_rtaa_data_size (RT_AA_CTRL *runtime_aa, + ST_INT num_rt_aa) + { +ST_INT i; +ST_INT size; + + size = 0; + for (i = 0; i < num_rt_aa; ++i, ++runtime_aa) + size += runtime_aa->el_size; + return (size); + } + +/************************************************************************/ +/************************************************************************/ +/* LOGGING FUNCTIONS */ +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* _ms_log_runtime_aa */ +/************************************************************************/ + +ST_VOID _ms_log_runtime_aa (RT_AA_CTRL *rt_aa, ST_INT num_aa) + { +#ifdef DEBUG_SISCO +SD_CONST RUNTIME_TYPE *rt; + +ST_INT i; +ST_INT indent; +SD_CONST ST_CHAR *comp_name; +/* Use these strings to keep logging aligned and indented as desired */ +#define MAX_INDENT 5 +SD_CONST ST_CHAR *sp[MAX_INDENT] = + { + " ", + " ", + " ", + " ", + " ", + }; +SD_CONST ST_CHAR *sp2[MAX_INDENT] = + { + " ", + " ", + " ", + " ", + "", + }; + + S_LOCK_COMMON_RESOURCES (); + indent = 0; + MLOG_ALWAYS1 ("RTAA : %d elements", num_aa); + + for (i = 0; i < num_aa; ++i, rt_aa++) + { + rt = rt_aa->rt; + comp_name = ms_comp_name_find (rt); + if (strlen (comp_name)) + { + MLOG_CALWAYS3 ("%sNamed comp %s: %s", + sp[indent], + sp2[indent], + comp_name); + } + + switch (rt->el_tag) + { + case RT_ARR_START : + MLOG_CALWAYS5 ("%sArray start %s: size %02d, %02d elmnts, %02d rt", + sp[indent], + sp2[indent], + rt_aa->el_size, + rt->u.arr.num_elmnts, + rt->u.arr.num_rt_blks); + if (++indent >= MAX_INDENT) + indent--; + break; + + case RT_ARR_END : + if (--indent < 0) + indent++; + MLOG_CALWAYS5 ("%sArray end %s: size %02d, %02d elmnts, %02d rt", + sp[indent], + sp2[indent], + rt_aa->el_size, + rt->u.arr.num_elmnts, + rt->u.arr.num_rt_blks); + break; + + case RT_STR_START : + MLOG_CALWAYS3 ("%sStruct start%s: size %02d", + sp[indent], + sp2[indent], + rt_aa->el_size); + if (++indent >= MAX_INDENT) + indent--; + break; + + case RT_STR_END : + if (--indent < 0) + indent++; + MLOG_CALWAYS3 ("%sStruct end %s: size %02d", + sp[indent], + sp2[indent], + rt_aa->el_size); + break; + + case RT_BOOL : + MLOG_CALWAYS5 ("%sBoolean %s: size %02d, precision %02d, offset %d", + sp[indent], + sp2[indent], + rt_aa->el_size, + rt->u.p.el_len, + rt_aa->offset_to_data); + break; + + case RT_BIT_STRING : + MLOG_CALWAYS5 ("%sBitstring %s: size %02d, precision %02d, offset %d", + sp[indent], + sp2[indent], + rt_aa->el_size, + rt->u.p.el_len, + rt_aa->offset_to_data); + break; + + case RT_INTEGER : + MLOG_CALWAYS5 ("%sInteger %s: size %02d, precision %02d, offset %d", + sp[indent], + sp2[indent], + rt_aa->el_size, + rt->u.p.el_len, + rt_aa->offset_to_data); + break; + + case RT_UNSIGNED : + MLOG_CALWAYS5 ("%sUnsigned %s: size %02d, precision %02d, offset %d", + sp[indent], + sp2[indent], + rt_aa->el_size, + rt->u.p.el_len, + rt_aa->offset_to_data); + break; + + case RT_FLOATING_POINT : + MLOG_CALWAYS5 ("%sFloat %s: size %02d, precision %02d, offset %d", + sp[indent], + sp2[indent], + rt_aa->el_size, + rt->u.p.el_len, + rt_aa->offset_to_data); + break; + + case RT_OCTET_STRING : + MLOG_CALWAYS5 ("%sOctet Str %s: size %02d, precision %02d, offset %d", + sp[indent], + sp2[indent], + rt_aa->el_size, + rt->u.p.el_len, + rt_aa->offset_to_data); + break; + + case RT_VISIBLE_STRING : + MLOG_CALWAYS5 ("%sVisible Str %s: size %02d, precision %02d, offset %d", + sp[indent], + sp2[indent], + rt_aa->el_size, + rt->u.p.el_len, + rt_aa->offset_to_data); + break; + + case RT_GENERAL_TIME : + MLOG_CALWAYS5 ("%sGen Time %s: size %02d, precision %02d, offset %d", + sp[indent], + sp2[indent], + rt_aa->el_size, + rt->u.p.el_len, + rt_aa->offset_to_data); + break; + + case RT_BINARY_TIME : + MLOG_CALWAYS5 ("%sBin Time %s: size %02d, precision %02d, offset %d", + sp[indent], + sp2[indent], + rt_aa->el_size, + rt->u.p.el_len, + rt_aa->offset_to_data); + break; + + case RT_BCD : + MLOG_CALWAYS5 ("%sBCD %s: size %02d, precision %02d, offset %d", + sp[indent], + sp2[indent], + rt_aa->el_size, + rt->u.p.el_len, + rt_aa->offset_to_data); + break; + + case RT_UTC_TIME : + MLOG_CALWAYS5 ("%sUtc Time %s: size %02d, precision %02d, offset %d", + sp[indent], + sp2[indent], + rt_aa->el_size, + rt->u.p.el_len, + rt_aa->offset_to_data); + break; + + case RT_UTF8_STRING : + MLOG_CALWAYS5 ("%sUTF8 Str %s: size %02d, precision %02d, offset %d", + sp[indent], + sp2[indent], + rt_aa->el_size, + rt->u.p.el_len, + rt_aa->offset_to_data); + break; + + default : /* should not be any other tag */ + MLOG_CALWAYS1 (" **** UNKNOWN ELEMENT %02d ",i); + break; + } + } + S_UNLOCK_COMMON_RESOURCES (); + +#endif + } + diff --git a/mmslib/mmsl/mms_tdef.c b/mmslib/mmsl/mms_tdef.c new file mode 100644 index 0000000..0727bc3 --- /dev/null +++ b/mmslib/mmsl/mms_tdef.c @@ -0,0 +1,3265 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2006, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_tdef.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Function to decode ASN.1 type definitions into Runtime typedefs */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* ms_runtime_create */ +/* ms_runtime_destroy */ +/* ms_is_rt_prim */ +/* ms_rt_el_tag_text */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/06/07 JRB 59 Chg ms_rt_bld_* to avoid realloc (reduces */ +/* max memory usage and fragmentation). */ +/* 04/17/07 JRB 58 ms_get_blocked_length: set also prim_count. */ +/* 02/02/07 JRB 57 Fix log message in ms_rt_bld_chk_state. */ +/* 10/30/06 JRB 56 Add ms_rt_bld_* functions. */ +/* 03/22/06 EJV 55 Chg RT_GENERAL_TIME to use time_t len & algn.*/ +/* 01/30/06 GLB 54 Integrated porting changes for VMS */ +/* 08/01/05 JRB 53 Avoid risky cast to remove const. */ +/* 04/07/05 MDE 52 Changed ERR log to NERR */ +/* 03/10/05 JRB 51 Add ms_rt_el_tag_text funct. */ +/* 02/23/05 JRB 50 ms_is_rt_prim: add SD_CONST to arg. */ +/* 02/21/05 JRB 49 Del m_struct_* for Lite, created by FOUNDRY. */ +/* Del asserts checking m_struct_*. */ +/* 01/27/05 JRB 48 Move m_lite_data.. extern to mms_vvar.h. */ +/* Init m_data_algn_tbl=NULL if FOUNDRY. */ +/* Add ; to one more MLOG* call. */ +/* 11/02/04 JRB 47 For MMS_LITE, use m_lite_data_algn_tbl */ +/* generated by Foundry for target platform. */ +/* 11/01/04 JRB 46 Add ; on MLOG* calls to work with new macros.*/ +/* 06/29/04 JRB 45 str_done: chk for empty structure. */ +/* 12/09/03 JRB 44 Add LYNX support. */ +/* 11/07/03 JRB 43 Fix misleading log message when decode done. */ +/* 10/13/03 EJV 42 Removed defined(__VAX). */ +/* 06/05/03 JRB 41 type_name_cstr_done: copy component names */ +/* for USE_RT_TYPE_2. */ +/* 04/28/03 JRB 40 Eliminate compiler warnings. */ +/* 04/28/03 JRB 39 Add UTF8string support (see RT_UTF8_STRING). */ +/* 03/13/03 JRB 38 u_ml_get_rt_type: chg from "func ptr" to func.*/ +/* 02/20/03 JRB 37 get_str_comp_name ret err if name index */ +/* can't be found for USE_RT_TYPE_3. */ +/* type_name_cstr_done save & restore comp name */ +/* for USE_RT_TYPE_2/USE_RT_TYPE_3. */ +/* 02/20/03 JRB 36 Del PSOS code. */ +/* 01/20/03 CRM 35 Added "defined(linux)" code. */ +/* 01/03/03 JRB 34 Move arr_loop* globals to locals in ms_get.. */ +/* 12/31/02 MDE 33 Eliminate use of m_calc_rt_size global. */ +/* 12/26/02 JRB 32 Add ms_asn1_to_runtime_x for backward compat.*/ +/* 12/16/02 JRB 31 Add ms_is_rt_prim funct. */ +/* 11/11/02 JRB 30 Chg ms_runtime_create/destroy args. */ +/* Make ms_asn1_to_runtime static, must call */ +/* ms_runtime_create instead. */ +/* Use DEC_INFO struct to avoid global vars. */ +/* Pass aCtx to ms_asn1_to_runtime & pass */ +/* DEC_INFO in aCtx->usr_info[0]. */ +/* 04/16/02 MDE 29 Now set name index for named struct elements */ +/* 03/04/02 JRB 28 Add more "SD_CONST RUNTIME_TYPE *". */ +/* 12/20/01 JRB 27 Converted to use ASN1R (re-entrant ASN1) */ +/* 11/14/01 EJV 26 Added support for new MMS type UtcTime: */ +/* Added fun get_utc_time_el; */ +/* set_type_tags: added code for tag 17; */ +/* _ms_m_get_rt_info: added case for RT_UTC_TIME*/ +/* _ms_log_runtime: added case for RT_UTC_TIME; */ +/* 10/18/01 JRB 25 Eliminate warning. */ +/* 08/29/00 JRB 24 Del ms_comp_name_find function. Use macro. */ +/* 07/28/00 JRB 23 Simplify RT_TYPE ifdefs. */ +/* Fix SD_CONST usage & lint warnings. */ +/* Make ms_type_nam* static. Only used here. */ +/* 07/13/00 JRB 22 Add ms_runtime_create, ms_runtime_destroy, */ +/* ms_comp_name_find. */ +/* 06/29/00 JRB 21 Make ms_asn1_to_runtime work for MMS LITE. */ +/* Must def USE_RT_TYPE_2 to save comp names. */ +/* 09/13/99 MDE 20 Added SD_CONST modifiers */ +/* 04/14/99 MDE 19 Removed unnecessary include files */ +/* 02/23/99 JRB 18 MMS_LITE: "m_data_algn.. = m_def_data_algn.."*/ +/* Don't need packed for backward compatibility.*/ +/* 09/10/98 MDE 17 Changes to work better with MMS-LITE */ +/* 08/21/98 EJV 16 __hpux STRSTRT_ALGN set from 3 to 0, and */ +/* 07/23/98 RKR 15 OPEN_VMS STRSTRT_ALGN set from 3 to 0 */ +/* 06/26/98 EJV 14 m_def_data_algn_tbl only for __alpha DECUNIX.*/ +/* 06/03/98 MDE 13 Corrected structure end alignment handling */ +/* 03/23/98 MDE 12 Tweaks to structure alignment */ +/* 03/12/98 MDE 11 Worked on structure alignment */ +/* 02/10/98 MDE 10 Runtime type changes for LITE */ +/* 11/04/97 DSF 09 Fixed alignment table for WIN32 */ +/* 10/30/97 MDE 08 Minor logging change */ +/* 09/29/97 MDE 07 Minor logging change */ +/* 08/27/97 MDE 06 Fixed problem with log runtime w/numrt = 0 */ +/* 08/15/97 MDE 05 BTOD handling changes */ +/* 08/04/97 MDE 04 Minor cleanup */ +/* 06/19/97 MDE 03 Added 64 bit integer support */ +/* 06/09/97 MDE 02 Fixed MMS-LITE compile problems, other minor */ +/* 04/08/97 MDE 01 Fixed 'RT Table too small prob w/named types */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" + +#include "sysincs.h" +#include "glbsem.h" +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "asn1defs.h" +#if defined(MMS_LITE) +#include "mvl_defs.h" +#endif + +/************************************************************************/ +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/************************************************************************/ + +#ifdef MMS_LITE +ST_VOID (*u_rt_type_process) (SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt); +#endif + +static ST_VOID _ms_log_runtime (ST_INT indent, SD_CONST RUNTIME_TYPE *rt, + ST_INT num_rt); + +static ST_VOID _do_padding (RUNTIME_TYPE *padDest, + ST_INT *curr_offset, + ST_INT algn); +static ST_VOID _get_struct_start_align (SD_CONST RUNTIME_TYPE *rt, + ST_INT *algn_out, + ST_INT *ellen_out); +static ST_VOID _get_struct_end_align (SD_CONST RUNTIME_TYPE *rt, + ST_INT *algn_out, + ST_INT *ellen_out); +static ST_VOID _get_arr_start_align (SD_CONST RUNTIME_TYPE *rt, + ST_INT *algn_out, + ST_INT *ellen_out); + +/************************************************************************/ + +static ST_VOID str_comp_seq_start (ASN1_DEC_CTXT *aCtx); /* CTX 1 CSTR - seq of comp */ +static ST_VOID get_num_arr_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID array_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID arr_el_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_arr_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID float_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_float_exp (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_float_fract (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_str_packed (ASN1_DEC_CTXT *aCtx); /* CTX 0 BOOL - packed */ +static ST_VOID get_arr_packed (ASN1_DEC_CTXT *aCtx); +static ST_VOID type_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID type_name_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_named_type (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_array_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_struct_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_bool_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_bitstr_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_int_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_uint_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_float_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_octstr_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_vstr_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_gtime_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_btime_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_bcd_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_utc_time_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_utf8_el (ASN1_DEC_CTXT *aCtx); +static ST_VOID set_type_tags (ASN1_DEC_CTXT *aCtx); +static ST_VOID td_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID td_err (ASN1_DEC_CTXT *aCtx, ST_RET err); + +/************************************************************************/ +/************************************************************************/ +/* Variables and definitions used in this module */ + +static RUNTIME_TYPE *rt_ptr; /* current runtime element */ + +static ST_INT rt_count; /* total elements in runtime table */ + /* (also index) */ +static ST_INT rt_limit; /* max # runtime elements */ + + +/* defines used during decode for various types of errors */ +#define PDU_ERR 2 +#define LENGTH_ERR 3 +#define UNSUPPORTED 4 +#define UNKNOWN_TYPENAME 5 +#define RUNTIME_LIMIT 6 + +static ST_INT arr_index[ASN1_MAX_LEVEL]; /* index to array element start */ +static RUNTIME_TYPE *struct_tracking[ASN1_MAX_LEVEL]; + +static OBJECT_NAME type_name; /* temp storage */ + + +/************************************************************************/ +/* ms_asn1_to_runtime */ +/************************************************************************/ + +static ST_INT _ms_asn1_to_runtime (ASN1_DEC_CTXT *aCtx, + ST_UCHAR *asn1ptr, ST_UINT asn1len, + RUNTIME_TYPE *rt_table, ST_INT rt_len) + { +MMSDEC_INFO dummy_rslt; +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; + + S_LOCK_COMMON_RESOURCES (); + + _mmsdec_rslt = &dummy_rslt; /* give _ms_get_mms_objname a place to point */ + /* to */ + rt_ptr = rt_table; /* initialize the element pointer */ + decInfo->rt_start = rt_table;/* initialize the element pointer */ + rt_limit = rt_len; /* save the limit */ + + rt_count = 0; /* set element count = 0 */ + +#if defined(USE_RT_TYPE_2) + decInfo->comp_name_used = 0; + decInfo->comp_name_ptr = decInfo->comp_name_buf; +#endif + + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; + + aCtx->asn1r_decode_done_fun = td_done; /* set up done function */ + aCtx->asn1r_err_fun = td_err; /* set up error detected fun */ + + set_type_tags (aCtx); /* setup the legal tags */ + + asn1r_decode_asn1 (aCtx, asn1ptr,asn1len); /* do message decode and */ + +/* If decode was OK and we are producing a real RT table, need to set */ +/* the data element sizes. */ + if (rt_count && !decInfo->calc_only) + { + ms_rt_size_calc (rt_table,rt_count); + +/* Also log the runtime type, if selected */ + if (mms_debug_sel & MMS_LOG_RT) + ms_log_runtime (rt_table, rt_count); + } + + S_UNLOCK_COMMON_RESOURCES (); + return (rt_count); /* return # elements used */ + } + + +/************************************************************************/ +/* set_type_tags */ +/* setup tags for main TypeSpecfication decode */ +/************************************************************************/ + +static ST_VOID set_type_tags (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,get_named_type); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_array_el); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_struct_el); + ASN1R_TAG_ADD (aCtx, CTX,3,get_bool_el); + ASN1R_TAG_ADD (aCtx, CTX,4,get_bitstr_el); + ASN1R_TAG_ADD (aCtx, CTX,5,get_int_el); + ASN1R_TAG_ADD (aCtx, CTX,6,get_uint_el); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,7,get_float_el); + ASN1R_TAG_ADD (aCtx, CTX,9,get_octstr_el); + ASN1R_TAG_ADD (aCtx, CTX,10,get_vstr_el); + ASN1R_TAG_ADD (aCtx, CTX,11,get_gtime_el); + ASN1R_TAG_ADD (aCtx, CTX,12,get_btime_el); + ASN1R_TAG_ADD (aCtx, CTX,13,get_bcd_el); + ASN1R_TAG_ADD (aCtx, CTX,17,get_utc_time_el); + ASN1R_TAG_ADD (aCtx, CTX,RT_UTF8_STRING,get_utf8_el); + } + +/************************************************************************/ +/* rt_ptr_inc */ +/* move the rt_ptr to next element and inc count. Checks vs limit. */ +/************************************************************************/ + +static ST_VOID rt_ptr_inc (ASN1_DEC_CTXT *aCtx) + { + if (++rt_count >= rt_limit) /* move the runtime pointer */ + { + MLOG_CDEC0 ("decode_done"); + aCtx->asn1r_decode_done = SD_TRUE; + } + else + rt_ptr++; /* point to next runtime element */ + } + +/************************************************************************/ +/************************************************************************/ +/* TypeSpecification element get start functions */ +/************************************************************************/ +/************************************************************************/ +/* get_named_type */ +/* named type element, check if in database, copy if so. */ +/************************************************************************/ + + +static ST_VOID get_named_type (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_named_type"); + +/* execute 'type_name_done' when type name has been extracted */ + _ms_get_mms_objname (aCtx, &type_name,type_name_done); + } + +/************************************************************************/ +/* type_name_done */ +/* The type_name objectName has been read, and is now in 'type_name' */ +/* That means that the type_name constructor now can be complete. */ +/************************************************************************/ + +static ST_VOID type_name_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("type_name_done"); + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = type_name_cstr_done; + } + + +/************************************************************************/ +/* get_array_el */ +/* array element, setup to get array parameters. */ +/************************************************************************/ + +static ST_VOID get_array_el (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; + + MLOG_CDEC0 ("get_array_el"); + + if (!decInfo->calc_only) + rt_ptr->el_tag = RT_ARR_START; /* write the tag */ + + arr_index[aCtx->asn1r_msg_level] = rt_count; /* save index to this element */ + + ASN1R_TAG_ADD (aCtx, CTX,0,get_arr_packed);/* set up to get next items */ + ASN1R_TAG_ADD (aCtx, CTX,1,get_num_arr_el); + } + +/************************************************************************/ +/* get_struct_el */ +/* structure element, setup to get struct parameters. */ +/************************************************************************/ + +static ST_VOID get_struct_el (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; + + MLOG_CDEC0 ("get_struct_el"); + + if (++rt_count >= rt_limit) + { + MLOG_NERR0 ("ASN.1 to RT Error : RT Table too small"); + asn1r_set_dec_err (aCtx, RUNTIME_LIMIT); + } + else + { + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_STR_START; /* write the tag */ + struct_tracking[aCtx->asn1r_msg_level] = rt_ptr; + rt_ptr++; /* point to next runtime element*/ + } + } + + ASN1R_TAG_ADD (aCtx, CTX,0,get_str_packed); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,str_comp_seq_start); + } + +/************************************************************************/ +/* Simple type get functions */ +/************************************************************************/ +/************************************************************************/ +/* get_bool_el */ +/* boolean element encountered. */ +/************************************************************************/ + +static ST_VOID get_bool_el (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; + + MLOG_CDEC0 ("get_bool_el"); + + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_BOOL; /* set data type tag */ + rt_ptr->u.p.el_len = 1; /* set max data length */ + } + rt_ptr_inc (aCtx); /* move rt ptr, inc count */ + } + +/************************************************************************/ +/* get_bitstr_el */ +/* bitstring element encountered. */ +/************************************************************************/ + +static ST_VOID get_bitstr_el (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; +ST_INT32 size; + + MLOG_CDEC0 ("get_bitstr_el"); + + if (asn1r_get_i32 (aCtx, &size)) + asn1r_set_dec_err (aCtx, PDU_ERR); /* too long */ + else + { + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_BIT_STRING; /* set data type tag */ + rt_ptr->u.p.el_len = (ST_INT) size; /* save size */ + if (rt_ptr->u.p.el_len != (ST_INT) size) /* make sure OK cast */ + { + MLOG_NERR0 ("Bitstring size too big"); + asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE */ + } + } + rt_ptr_inc (aCtx); /* move rt ptr, inc count */ + } + } +/************************************************************************/ +/* get_int_el */ +/* integer element encountered. */ +/************************************************************************/ + +static ST_VOID get_int_el (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; +ST_UCHAR size; + + MLOG_CDEC0 ("get_int_el"); + + if (asn1r_get_u8 (aCtx, &size) || size %8) /* read integer */ + asn1r_set_dec_err (aCtx, LENGTH_ERR); /* if too long or not byte size */ + else + { + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_INTEGER; /* set data type tag */ + rt_ptr->u.p.el_len = 1; /* set max data length */ + + rt_ptr->u.p.el_len = (ST_INT) size/8; /* looks OK so far */ + + if ((rt_ptr->u.p.el_len != sizeof (ST_CHAR) && + rt_ptr->u.p.el_len != sizeof (ST_INT16) && + rt_ptr->u.p.el_len != sizeof (ST_INT) && /*** decunix use 1,2,4,8 bytes ***/ +#ifdef INT64_SUPPORT + rt_ptr->u.p.el_len != sizeof (ST_INT64) && +#endif + rt_ptr->u.p.el_len != sizeof (ST_INT32)) || + size % 8) + { + MLOG_NERR0 ("Integer length not supported"); + asn1r_set_dec_err (aCtx, UNSUPPORTED); /* not standard size int */ + } + } + rt_ptr_inc (aCtx); /* move rt ptr, inc count */ + } + } + +/************************************************************************/ +/* get_uint_el */ +/* unsigned element encountered. */ +/************************************************************************/ + +static ST_VOID get_uint_el (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; +ST_UCHAR size; + + MLOG_CDEC0 ("get_uint_el"); + + if (asn1r_get_u8 (aCtx, &size) || size %8) /* read integer */ + asn1r_set_dec_err (aCtx, LENGTH_ERR); /* if too long or not byte size */ + else + { + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_UNSIGNED; /* set data type tag */ + rt_ptr->u.p.el_len = (ST_INT) size/8; /* looks OK so far */ + if ((rt_ptr->u.p.el_len != sizeof (ST_CHAR) && + rt_ptr->u.p.el_len != sizeof (ST_INT16) && + rt_ptr->u.p.el_len != sizeof (ST_INT) && /*** decunix use 1,2,4,8 bytes ***/ +#ifdef INT64_SUPPORT + rt_ptr->u.p.el_len != sizeof (ST_INT64) && +#endif + rt_ptr->u.p.el_len != sizeof (ST_INT32)) || + size % 8) + { + MLOG_NERR0 ("Integer length not supported"); + asn1r_set_dec_err (aCtx, UNSUPPORTED); /* not standard size int */ + } + } + rt_ptr_inc (aCtx); /* move rt ptr, inc count */ + } + } + +/************************************************************************/ +/************************************************************************/ +/* get_float_el */ +/* float element encountered. */ +/************************************************************************/ + +static ST_UCHAR float_f; +static ST_UCHAR float_e; + +static ST_VOID get_float_el (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_float_el"); + + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,get_float_fract); + } + +/************************************************************************/ +/* get_float_fract */ +/* float element fractional positions (unsigned 8) encountered */ +/************************************************************************/ + +static ST_VOID get_float_fract (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_float_fract"); + + if (asn1r_get_u8 (aCtx, &float_f)) + asn1r_set_dec_err (aCtx, UNSUPPORTED); + else + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,get_float_exp); + } + +/************************************************************************/ +/* get_float_exp */ +/* float element fractional positions (unsigned 8) encountered */ +/************************************************************************/ + + +static ST_VOID get_float_exp (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; + + MLOG_CDEC0 ("get_float_exp"); + + if (asn1r_get_u8 (aCtx, &float_e)) + asn1r_set_dec_err (aCtx, UNSUPPORTED); + else + { /* IEEE 754 Single */ + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_FLOATING_POINT; /* set data type tag */ + +/* Since DIS & IS differ on the values used to represent floating point */ +/* types, allow either. */ + + if ((float_f == SNGL_FRACT || float_f == SNGL_WHOLE) && + float_e == SNGL_EXP) + rt_ptr->u.p.el_len = 4; /* single precision */ + else + { /* IEEE 754 Double */ + if ((float_f == DOUBL_FRACT || float_f == DOUBL_WHOLE) && + float_e == DOUBL_EXP) + rt_ptr->u.p.el_len = 8; /* double precision */ + else + { + MLOG_NERR0 ("Float format not supported"); + asn1r_set_dec_err (aCtx, UNSUPPORTED); /* not standard size int */ + } + } + } + } +/* Float element constructor can now be done */ + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = float_cstr_done; + } + +/************************************************************************/ +/* float_cstr_done */ +/* float element cstr done function, allow type decode to continue */ +/************************************************************************/ + +static ST_VOID float_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("float_cstr_done"); + rt_ptr_inc (aCtx); /* move rt ptr, inc count */ + } + + +/************************************************************************/ +/* get_octstr_el */ +/* octet string element encountered. */ +/************************************************************************/ + +static ST_VOID get_octstr_el (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; +ST_INT32 size; + + MLOG_CDEC0 ("get_octstr_el"); + + if (asn1r_get_i32 (aCtx, &size)) + asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE */ + else + { + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_OCTET_STRING; /* set data type tag */ + rt_ptr->u.p.el_len = (ST_INT) size; /* save precision */ + if (rt_ptr->u.p.el_len != (ST_INT) size) /* make sure OK cast */ + { + MLOG_NERR0 ("Octet string too big"); + asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE */ + } + } + rt_ptr_inc (aCtx); /* move rt ptr, inc count */ + } + } + +/************************************************************************/ +/* get_vstr_el */ +/* visible string element encountered. */ +/************************************************************************/ + +static ST_VOID get_vstr_el (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; +ST_INT32 size; + + MLOG_CDEC0 ("get_vstr_el"); + + if (asn1r_get_i32 (aCtx, &size)) + asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE */ + else + { + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_VISIBLE_STRING; /* set data type tag */ + rt_ptr->u.p.el_len = (ST_INT) size; /* save precision */ + if (rt_ptr->u.p.el_len != (ST_INT) size) /* make sure OK cast */ + { + MLOG_NERR0 ("Vis string too big"); + asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE */ + } + } + rt_ptr_inc (aCtx); /* move rt ptr, inc count */ + } + } + +/************************************************************************/ +/* get_gtime_el */ +/* generalized time element encountered. */ +/************************************************************************/ + +static ST_VOID get_gtime_el (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; + + MLOG_CDEC0 ("get_gtime_el"); + + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_GENERAL_TIME; /* set data type tag */ + rt_ptr->u.p.el_len = sizeof(time_t);/* gen time precision */ + } + rt_ptr_inc (aCtx); /* move rt ptr, inc count */ + } + +/************************************************************************/ +/* get_btime_el */ +/* binary time element encountered. */ +/************************************************************************/ + +static ST_VOID get_btime_el (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; +ST_BOOLEAN dateFlag; + + MLOG_CDEC0 ("get_btime_el"); + + if (asn1r_get_bool (aCtx, &dateFlag)) /* get the 4/6 flag */ + asn1r_set_dec_err (aCtx, PDU_ERR); + else + { + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_BINARY_TIME; /* set data type tag */ + if (dateFlag) /* if date included */ + rt_ptr->u.p.el_len = 6; /* expect 6 bytes */ + else /* no date */ + rt_ptr->u.p.el_len = 4; /* expect 4 bytes */ + } + rt_ptr_inc (aCtx); /* move rt ptr, inc count */ + } + } + +/************************************************************************/ +/* get_bcd_el */ +/* bcd element encountered. */ +/************************************************************************/ + +static ST_VOID get_bcd_el (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; +ST_UCHAR size; + + MLOG_CDEC0 ("get_bcd_el"); + + if (asn1r_get_u8 (aCtx, &size)) /* get the precision */ + asn1r_set_dec_err (aCtx, PDU_ERR); /* too long */ + else /* find # bytes */ + { + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_BCD; /* set data type tag */ + rt_ptr->u.p.el_len = (ST_INT) size;/* save precision */ + if (size > 8) + { + MLOG_NERR0 ("BCD size too big"); + asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE */ + } + } + } + rt_ptr_inc (aCtx); /* move rt ptr, inc count */ + } + +/************************************************************************/ +/* get_utc_time_el */ +/* UTC Time element encountered. */ +/************************************************************************/ + +static ST_VOID get_utc_time_el (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; + + MLOG_CDEC0 ("get_utc_time_el"); + + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_UTC_TIME; /* set data type tag */ + rt_ptr->u.p.el_len = 8; /* expect 8 bytes */ + } + rt_ptr_inc (aCtx); /* move rt ptr, inc count */ + } + + +/************************************************************************/ +/* get_utf8_el */ +/* Unicode UTF8string element encountered. */ +/************************************************************************/ + +static ST_VOID get_utf8_el (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; +ST_INT32 size; + + MLOG_CDEC0 ("get_utf8_el"); + + if (asn1r_get_i32 (aCtx, &size)) + asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE*/ + else + { + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_UTF8_STRING; /* set data type tag */ + rt_ptr->u.p.el_len = (ST_RTINT) size; /* save size */ + if (rt_ptr->u.p.el_len != size) + { /* lost precision in cast*/ + MLOG_NERR0 ("Unicode UTF8 string too long"); + asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE*/ + } + } + rt_ptr_inc (aCtx); /* move rt ptr, inc count */ + } + } + +/************************************************************************/ +/************************************************************************/ +/* STRUCTURE COMPONENT DECODE */ +/************************************************************************/ +/* function declarations used in structure parsing */ + +static ST_VOID get_str_comp_seq (ASN1_DEC_CTXT *aCtx); /* UNI seq - comp */ +static ST_VOID get_str_comp_name (ASN1_DEC_CTXT *aCtx); /* CTX 0 comp ID */ +static ST_VOID get_str_comp_type (ASN1_DEC_CTXT *aCtx); /* CTX 1 CSTR - typedef */ +static ST_VOID str_comp_type_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID str_comp_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID str_comp_seq_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID str_done (ASN1_DEC_CTXT *aCtx); /* main struct cstr done */ + +/************************************************************************/ +/* get_str_packed */ +/************************************************************************/ + +static ST_VOID get_str_packed (ASN1_DEC_CTXT *aCtx) + { +#if !defined(USE_RT_TYPE_2) && !defined(USE_RT_TYPE_3) +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; +#endif +ST_UCHAR m_packed; + + MLOG_CDEC0 ("get_str_packed"); + + if (asn1r_get_u8 (aCtx, &m_packed)) /* get the boolean value */ + asn1r_set_dec_err (aCtx, PDU_ERR); /* too long */ + else + { +#if !defined(USE_RT_TYPE_2) && !defined(USE_RT_TYPE_3) + if (!decInfo->calc_only) + rt_ptr->u.str.packd = m_packed; +#endif + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,str_comp_seq_start); + } + } + +/************************************************************************/ +/* str_comp_seq_start */ +/* This is a 'seq' component , of the main struct 'seq of' */ +/* Next is an optional 'packed' or the components sequence */ +/************************************************************************/ + +static ST_VOID str_comp_seq_start (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("str_comp_seq_start"); + + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,get_str_comp_seq); + } + +/************************************************************************/ +/* get_str_comp_seq */ +/* This is a 'seq' component , of the main struct 'seq of' */ +/* Next is an optional 'packed' or the components sequence */ +/************************************************************************/ + +static ST_VOID get_str_comp_seq (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_str_comp_seq"); + + ASN1R_TAG_ADD (aCtx, CTX,0,get_str_comp_name); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_str_comp_type); + } + + +/************************************************************************/ +/* get_str_comp_name */ +/* structure component name here */ +/* NOTE: USE_RT_TYPE_2 must be defined or this function will not save */ +/* component names (needs rt_ptr->comp_name_ptr). */ +/************************************************************************/ + +#if defined(USE_RT_TYPE_3) +static ST_INT _mvl_rt_name_to_index (ST_CHAR *name) + { +ST_INT i; + + for (i = 0; i < numMvlRtNames; ++i) + { + if (!strcmp (mvlRtNames[i], name)) + return (i); + } + return (-1); + } +#endif + + +static ST_VOID get_str_comp_name (ASN1_DEC_CTXT *aCtx) + { +ST_CHAR name[MAX_IDENT_LEN+1]; /* for component name element */ +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; +#if defined(USE_RT_TYPE_2) +ST_INT name_len; +#endif + + MLOG_CDEC0 ("get_str_comp_name"); + + if (asn1r_get_identifier (aCtx, name)) /* read the identifier */ + asn1r_set_dec_err (aCtx, PDU_ERR); /* too long */ + else + { +#ifdef USE_RT_TYPE_2 + name_len = strlen (name) + 1; /* make space for NULL */ + decInfo->comp_name_used += name_len;/* compute total len BEFORE copy*/ + if (!decInfo->calc_only) + { + if (decInfo->comp_name_ptr && + decInfo->comp_name_used <= decInfo->comp_name_size) /* enough space?*/ + { + strcpy (decInfo->comp_name_ptr, name); + rt_ptr->comp_name_ptr = decInfo->comp_name_ptr; /* Store name ptr*/ + decInfo->comp_name_ptr += name_len; + } + else + { /* Buffer too small. Should never happen. */ + MLOG_ERR0 ("ASN.1 to RT Error : Component name buffer overflow."); + asn1r_set_dec_err (aCtx, RUNTIME_LIMIT); + return; + } + } +#elif defined(USE_RT_TYPE_3) + if (!decInfo->calc_only) + { + rt_ptr->name_index = _mvl_rt_name_to_index (name); + if (rt_ptr->name_index < 0) + { + MLOG_NERR1 ("ASN.1 to RT Error : Component name '%s'cannot be converted to index", name); + asn1r_set_dec_err (aCtx, UNKNOWN_TYPENAME); + return; + } + } +#else /* Default */ + if (!decInfo->calc_only) + strcpy (rt_ptr->name, name); +#endif /* Default */ + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_str_comp_type); /* need to get type next */ + } + } + + +/************************************************************************/ +/* get_str_comp_type */ +/* structure component, is a type definition */ +/* This constructor contains the type_definition element */ +/************************************************************************/ + +static ST_VOID get_str_comp_type (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_str_comp_type"); + + set_type_tags (aCtx); /* set up to get the type spec. */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = str_comp_type_done; + } + +/************************************************************************/ +/* str_comp_type_done */ +/* structure component typedef constructor complete */ +/* This just means that is is OK for this component to be done. */ +/************************************************************************/ + +static ST_VOID str_comp_type_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("str_comp_type_done"); + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = str_comp_done; + } + +/************************************************************************/ +/* str_comp_done */ +/* structure component constructor complete */ +/* set up to get the next */ +/************************************************************************/ + +static ST_VOID str_comp_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("str_comp_done"); + + /* setup to get next struct component */ + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,get_str_comp_seq); + +/* since a struct comp has been read, OK for this seq to be done */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = str_comp_seq_done; + } + +/************************************************************************/ +/* str_comp_seq_done */ +/* structure component seq complete */ +/* set up to get the next seq, or could be done with this seq */ +/************************************************************************/ + +static ST_VOID str_comp_seq_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("str_comp_seq_done"); + +/* since a struct comp has been read, OK for this seq to be done */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = str_done; /* ok for this struct to be done */ + } + +/************************************************************************/ +/* str_done */ +/* structure complete */ +/* set up to get the next element */ +/************************************************************************/ + +static ST_VOID str_done (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; +RUNTIME_TYPE *start_rt_blk; +ST_INT num_rt; + + MLOG_CDEC0 ("str_done"); + + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_STR_END; /* write the tag */ + +/* calculate where the corresponding STR_START elment is */ + start_rt_blk = struct_tracking[aCtx->asn1r_msg_level+1]; + +/* Set num_rt, for use in AA processing */ + num_rt = (rt_ptr - start_rt_blk - 1); + +/* If everything else working correctly, this error should never occur. */ + if (num_rt <= 0) + { + MLOG_ERR0 ("ASN.1 to RT Error : Structure empty."); + asn1r_set_dec_err (aCtx, LENGTH_ERR); + } + + start_rt_blk->u.str.num_rt_blks = num_rt; + rt_ptr->u.str.num_rt_blks = num_rt; + +#if !defined(USE_RT_TYPE_2) && !defined(USE_RT_TYPE_3) +/* copy the packed flag from the start block to the end block */ + rt_ptr->u.str.packd = start_rt_blk->u.str.packd; +#endif + } + rt_ptr_inc (aCtx); /* move rt ptr, inc count */ + } + + +/************************************************************************/ +/************************************************************************/ +/* ARRAY COMPONENT DECODE */ +/************************************************************************/ +/* get_arr_packed */ +/* packed flag received here, just ignore for now */ +/************************************************************************/ + +static ST_VOID get_arr_packed (ASN1_DEC_CTXT *aCtx) + { +#if !defined(USE_RT_TYPE_2) && !defined(USE_RT_TYPE_3) +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; +#endif +ST_UCHAR m_packed; + + MLOG_CDEC0 ("get_arr_packed"); + + if (asn1r_get_u8 (aCtx, &m_packed)) /* get the boolean value */ + asn1r_set_dec_err (aCtx, PDU_ERR); /* too long */ + else + { +#if !defined(USE_RT_TYPE_2) && !defined(USE_RT_TYPE_3) + if (!decInfo->calc_only) + rt_ptr->u.arr.packd = m_packed; +#endif + ASN1R_TAG_ADD (aCtx, CTX,1,get_num_arr_el); /* next must be number of elmnts*/ + } + } + +/************************************************************************/ +/* get_num_arr_el */ +/* number of array elements */ +/************************************************************************/ + +static ST_VOID get_num_arr_el (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; +ST_UINT32 num; + + MLOG_CDEC0 ("get_num_arr_el"); + + if (asn1r_get_u32 (aCtx, &num)) /* get the number of elements */ + asn1r_set_dec_err (aCtx, PDU_ERR); /* too long */ + else + { + if (!decInfo->calc_only) + { + rt_ptr->u.arr.num_elmnts = (ST_INT) num; + if (rt_ptr->u.arr.num_elmnts != (ST_INT) num) /* verify cast */ + { + MLOG_NERR0 ("Array size too big"); + asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long */ + } + } + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_arr_el); /* need to get type next */ + + if (++rt_count >= rt_limit) /* check runtime table limit */ + { + MLOG_NERR0 ("ASN.1 to RT Error : RT Table too small"); + asn1r_set_dec_err (aCtx, RUNTIME_LIMIT); + } + else + rt_ptr++; /* move rt ptr to next element */ + } + } + +/************************************************************************/ +/* get_arr_el */ +/* structure component, is a type definition */ +/* This constructor contains the type_definition element */ +/************************************************************************/ + +static ST_VOID get_arr_el (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_arr_el"); + + set_type_tags (aCtx); /* set up to get the type spec. */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = arr_el_cstr_done; + } + +/************************************************************************/ +/* arr_el_cstr_done */ +/* array element constructor complete */ +/* This means that the array sequence is complete */ +/************************************************************************/ + +static ST_VOID arr_el_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("arr_el_cstr_done"); + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = array_done; /* set done function for array */ + } + +/************************************************************************/ +/* array_done */ +/* array constructor complete */ +/* calculate the # rt blocks is each element, update start/end of array */ +/************************************************************************/ + +static ST_VOID array_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT num_rt; +RUNTIME_TYPE *start_rt_blk; +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; + + MLOG_CDEC0 ("array_done"); + + if (!decInfo->calc_only) + { + rt_ptr->el_tag = RT_ARR_END; /* write the tag */ + +/* calculate and write rt count for end, start blocks */ + start_rt_blk = decInfo->rt_start + arr_index[aCtx->asn1r_msg_level+1]; + num_rt = rt_count - arr_index[aCtx->asn1r_msg_level+1] -1; /* rt_count not inc'd yet*/ + + rt_ptr->u.arr.num_rt_blks = num_rt; + start_rt_blk->u.arr.num_rt_blks = num_rt; + +/* copy the element count from the start block to the end block */ + rt_ptr->u.arr.num_elmnts = start_rt_blk->u.arr.num_elmnts; + } + rt_ptr_inc (aCtx); /* move rt ptr, inc count */ + } + + +/************************************************************************/ +/************************************************************************/ +/* NAMED TYPE */ +/************************************************************************/ +/* type_name_cstr_done */ +/* type_name constructor complete */ +/* need to find in local database, copy the runtime elements */ +/************************************************************************/ + +static ST_VOID type_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0]; +RUNTIME_TYPE *sub_rt_head; /* ptr to first rt in sub-type */ +ST_INT sub_rt_num; /* num of rt in sub-type */ +#if !defined(MMS_LITE) +NAMED_TYPE *tptr; +#endif + +#if defined (USE_RT_TYPE_2) +ST_CHAR *name_ptr_save; +ST_INT j; +ST_INT comp_name_len; +#elif defined(USE_RT_TYPE_3) +ST_RTINT name_index_save; +#else +ST_CHAR name_save[MAX_IDENT_LEN+1]; +#endif + + MLOG_CDEC0 ("type_name_cstr_done"); + +#if !defined(MMS_LITE) + tptr = ms_find_named_type_obj (&type_name,0); + if (!tptr) + { + MLOG_NERR1 ("Named type %s not found", type_name.obj_name.vmd_spec); + asn1r_set_dec_err (aCtx, UNKNOWN_TYPENAME); + return; + } + sub_rt_num = tptr->rt_num; + sub_rt_head = tptr->rt_head; +#else + /* This function finds previously defined types. The default function */ + /* should be in the library, but user may replace it with customized funct.*/ + if (u_ml_get_rt_type (aCtx, &type_name, &sub_rt_head, &sub_rt_num) != SD_SUCCESS) + { + MLOG_NERR1 ("Named type %s not found", type_name.obj_name.vmd_spec); + asn1r_set_dec_err (aCtx, UNKNOWN_TYPENAME); + return; + } + +#endif + +/* OK, we have a pointer to the referenced runtime type and the number */ +/* of elements. We can either insert the referenced table into the */ +/* new one, OR we can just add a reference. */ + + if ((rt_count += sub_rt_num) > rt_limit) + { + MLOG_NERR0 ("ASN.1 to RT Error : RT Table too small"); + asn1r_set_dec_err (aCtx, RUNTIME_LIMIT); + return; + } + if (decInfo->calc_only) + { +#if defined(USE_RT_TYPE_2) /* make room to copy comp names from sub-type*/ + for (j = 0; j < sub_rt_num; ++j) + { + if (sub_rt_head[j].comp_name_ptr) + decInfo->comp_name_used += (strlen (sub_rt_head[j].comp_name_ptr) + 1); + } +#endif + } + else + { +#if defined(USE_RT_TYPE_2) + name_ptr_save = rt_ptr->comp_name_ptr; +#elif defined(USE_RT_TYPE_3) + name_index_save = rt_ptr->name_index; +#else + strcpy (name_save, rt_ptr->name); +#endif + + /* Copy array of RUNTIME_TYPE structs. */ + memcpy ((ST_CHAR *)rt_ptr,(ST_CHAR *)sub_rt_head, sizeof(RUNTIME_TYPE)*sub_rt_num); + +#if defined(USE_RT_TYPE_2) + /* Copy component names from sub-type into new type. */ + /* Must update comp_name_ptr in each rt. */ + for (j = 0; j < sub_rt_num; ++j) + { + if (sub_rt_head[j].comp_name_ptr) + { + /* check for buffer space BEFORE strcpy. */ + comp_name_len = (strlen(sub_rt_head[j].comp_name_ptr) + 1); + decInfo->comp_name_used += comp_name_len; + if (decInfo->comp_name_used <= decInfo->comp_name_size) /* enough space?*/ + { + strcpy (decInfo->comp_name_ptr, sub_rt_head[j].comp_name_ptr); + rt_ptr[j].comp_name_ptr = decInfo->comp_name_ptr; + decInfo->comp_name_ptr += comp_name_len; + } + else + { /* Buffer too small. Should never happen. */ + MLOG_ERR0 ("ASN.1 to RT Error : Component name buffer overflow."); + asn1r_set_dec_err (aCtx, RUNTIME_LIMIT); + return; + } + } + } + rt_ptr->comp_name_ptr = name_ptr_save; +#elif defined(USE_RT_TYPE_3) + rt_ptr->name_index = name_index_save; +#else + strcpy (rt_ptr->name, name_save); +#endif + rt_ptr += sub_rt_num; /* chg global rt_ptr to point after inserted sub-type*/ + } + } + + +/************************************************************************/ +/************************************************************************/ +/* DECODE DONE FUNCTIONS */ +/************************************************************************/ +/* td_done */ +/************************************************************************/ + + +static ST_VOID td_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("td_done"); + } + +/************************************************************************/ +/* td_err */ +/************************************************************************/ + +static ST_VOID td_err (ASN1_DEC_CTXT *aCtx, ST_RET err) + { + MLOG_CDEC0 ("td_err"); + + rt_count = 0; /* error, set count = 0 */ + mms_op_err = aCtx->asn1r_pdu_dec_err; /* save error code */ + } + +/************************************************************************/ +/* DATA ALIGNMENT TABLE DEFINITIONS */ +/************************************************************************/ + +/* This is the 'packed' data alignment table, which is used to emulate */ +/* the alignment used by previous versions of the data conversion */ +/* functions. */ + +SD_CONST ST_INT m_packed_data_algn_tbl[NUM_ALGN_TYPES] = + { + 0x0000, /* ARRSTRT_ALGN 00 */ + 0x0000, /* ARREND_ALGN 01 */ + 0x0000, /* STRSTRT_ALGN 02 */ + 0x0000, /* STREND_ALGN 03 */ + 0x0000, /* INT8_ALGN 04 */ + 0x0000, /* INT16_ALGN 05 */ + 0x0000, /* INT32_ALGN 06 */ + 0x0000, /* INT64_ALGN 07 */ + 0x0000, /* FLOAT_ALGN 08 */ + 0x0000, /* DOUBLE_ALGN 09 */ + 0x0000, /* OCT_ALGN 10 */ + 0x0000, /* BOOL_ALGN 11 */ + 0x0000, /* BCD1_ALGN 12 */ + 0x0000, /* BCD2_ALGN 13 */ + 0x0000, /* BCD4_ALGN 14 */ + 0x0000, /* BIT_ALGN 15 */ + 0x0000 /* VIS_ALGN 16 */ + }; + +/* CRITICAL: this global variable "m_data_algn_tbl" must be set before */ +/* any types are created. */ +#ifdef MMS_LITE +#if defined(FOUNDRY) +/* For some strange reason on "linux", the linker tries to get this */ +/* module again from the library (causing duplicates) if */ +/* m_data_algn_tbl is not initialized here. */ +SD_CONST ST_INT *m_data_algn_tbl=NULL; /* Foundry sets it as needed */ +#else +/* Use m_lite_data_algn_tbl generated by Foundry for target platform. */ +/* This assures that Foundry types & dynamic types have same alignment. */ +SD_CONST ST_INT *m_data_algn_tbl = m_lite_data_algn_tbl; +#endif +#else /* !MMS_LITE */ +/* Should use "m_def_data_algn_tbl" for all systems, but must */ +/* default to "m_packed_data_algn_tbl" for backward compatiblity with */ +/* very old MMS-EASE products. */ +#if !defined(NO_GLB_VAR_INIT) +SD_CONST ST_INT *m_data_algn_tbl = m_packed_data_algn_tbl; +#endif +#endif /* !MMS_LITE */ + +/* Here is where we create the 'default' alignment tables. These should */ +/* allow natural access to components. */ + +/* This data alignment table provides word alignment per the following */ +/* simple rule : */ +/* Align on the smaller of the size of the data type OR 2 bytes. */ +/* To do this we set the low bit for every type that is greater than */ +/* or equal to 2 bytes in size. */ + +#if !defined(MMS_LITE) /* m_def_data_algn_tbl NOT used for MMS_LITE */ +#if defined(MSDOS) + +#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST +#define M_STREND_MODE M_STREND_MODE_LARGEST + +SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] = + { + 0x0000, /* ARRSTRT_ALGN 00 */ + 0x0000, /* ARREND_ALGN 01 */ + 0x0000, /* STRSTRT_ALGN 02 */ + 0x0000, /* STREND_ALGN 03 */ + 0x0000, /* INT8_ALGN 04 */ + 0x0001, /* INT16_ALGN 05 */ + 0x0001, /* INT32_ALGN 06 */ + 0x0001, /* INT64_ALGN 07 */ + 0x0001, /* FLOAT_ALGN 08 */ + 0x0001, /* DOUBLE_ALGN 09 */ + 0x0000, /* OCT_ALGN 10 */ + 0x0000, /* BOOL_ALGN 11 */ + 0x0000, /* BCD1_ALGN 12 */ + 0x0001, /* BCD2_ALGN 13 */ + 0x0001, /* BCD4_ALGN 14 */ + 0x0000, /* BIT_ALGN 15 */ + 0x0000 /* VIS_ALGN 16 */ + }; +#endif + +/* This data alignment table provides word alignment per the following */ +/* simple rule : */ +/* Align on the smaller of the size of the data type OR 4 bytes. */ +/* To do this we set the low bit for every type that is equal to 2 */ +/* bytes in size, and the low two bits for every type that is greater */ +/* than or equal to 4 bytes in size. */ + +#if 0 + +#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST +#define M_STREND_MODE M_STREND_MODE_LARGEST + +SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] = + { + 0x0000, /* ARRSTRT_ALGN 00 */ + 0x0000, /* ARREND_ALGN 01 */ + 0x0000, /* STRSTRT_ALGN 02 */ + 0x0000, /* STREND_ALGN 03 */ + 0x0000, /* INT8_ALGN 04 */ + 0x0001, /* INT16_ALGN 05 */ + 0x0003, /* INT32_ALGN 06 */ + 0x0007, /* INT64_ALGN 07 */ + 0x0003, /* FLOAT_ALGN 08 */ + 0x0003, /* DOUBLE_ALGN 09 */ + 0x0000, /* OCT_ALGN 10 */ + 0x0000, /* BOOL_ALGN 11 */ + 0x0000, /* BCD1_ALGN 12 */ + 0x0000, /* BCD2_ALGN 13 */ + 0x0001, /* BCD4_ALGN 14 */ + 0x0000, /* BIT_ALGN 15 */ + 0x0000 /* VIS_ALGN 16 */ + }; +#endif + +#ifdef _AIX + +#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST +#define M_STREND_MODE M_STREND_MODE_LARGEST + +SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] = + { + 0x0000, /* ARRSTRT_ALGN 00 */ + 0x0000, /* ARREND_ALGN 01 */ + 0x0000, /* STRSTRT_ALGN 02 */ + 0x0000, /* STREND_ALGN 03 */ + 0x0000, /* INT8_ALGN 04 */ + 0x0001, /* INT16_ALGN 05 */ + 0x0003, /* INT32_ALGN 06 */ + 0x0007, /* INT64_ALGN 07 */ + 0x0003, /* FLOAT_ALGN 08 */ + 0x0003, /* DOUBLE_ALGN 09 */ + 0x0000, /* OCT_ALGN 10 */ + 0x0000, /* BOOL_ALGN 11 */ + 0x0000, /* BCD1_ALGN 12 */ + 0x0001, /* BCD2_ALGN 13 */ + 0x0003, /* BCD4_ALGN 14 */ + 0x0000, /* BIT_ALGN 15 */ + 0x0000 /* VIS_ALGN 16 */ + }; +#endif + +#if defined (__hpux) + +#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST +#define M_STREND_MODE M_STREND_MODE_LARGEST + +SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] = + { + 0x0000, /* ARRSTRT_ALGN 00 */ + 0x0000, /* ARREND_ALGN 01 */ + 0x0000, /* STRSTRT_ALGN 02 */ + 0x0000, /* STREND_ALGN 03 */ + 0x0000, /* INT8_ALGN 04 */ + 0x0001, /* INT16_ALGN 05 */ + 0x0003, /* INT32_ALGN 06 */ + 0x0007, /* INT64_ALGN 07 */ + 0x0003, /* FLOAT_ALGN 08 */ + 0x0007, /* DOUBLE_ALGN 09 */ + 0x0000, /* OCT_ALGN 10 */ + 0x0000, /* BOOL_ALGN 11 */ + 0x0000, /* BCD1_ALGN 12 */ + 0x0001, /* BCD2_ALGN 13 */ + 0x0003, /* BCD4_ALGN 14 */ + 0x0000, /* BIT_ALGN 15 */ + 0x0000 /* VIS_ALGN 16 */ + }; +#endif + +#ifdef __OS2__ + +#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST +#define M_STREND_MODE M_STREND_MODE_LARGEST + +SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] = + { + 0x0000, /* ARRSTRT_ALGN 00 */ + 0x0000, /* ARREND_ALGN 01 */ + 0x0000, /* STRSTRT_ALGN 02 */ + 0x0000, /* STREND_ALGN 03 */ + 0x0000, /* INT8_ALGN 04 */ + 0x0001, /* INT16_ALGN 05 */ + 0x0003, /* INT32_ALGN 06 */ + 0x0007, /* INT64_ALGN 07 */ + 0x0003, /* FLOAT_ALGN 08 */ + 0x0003, /* DOUBLE_ALGN 09 */ + 0x0000, /* OCT_ALGN 10 */ + 0x0000, /* BOOL_ALGN 11 */ + 0x0000, /* BCD1_ALGN 12 */ + 0x0001, /* BCD2_ALGN 13 */ + 0x0003, /* BCD4_ALGN 14 */ + 0x0000, /* BIT_ALGN 15 */ + 0x0000 /* VIS_ALGN 16 */ + }; +#endif + +#ifdef sun + +#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST +#define M_STREND_MODE M_STREND_MODE_LARGEST + +SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] = + { + 0x0000, /* ARRSTRT_ALGN 00 */ + 0x0000, /* ARREND_ALGN 01 */ + 0x0000, /* STRSTRT_ALGN 02 */ + 0x0000, /* STREND_ALGN 03 */ + 0x0000, /* INT8_ALGN 04 */ + 0x0001, /* INT16_ALGN 05 */ + 0x0003, /* INT32_ALGN 06 */ + 0x0007, /* INT64_ALGN 07 */ + 0x0003, /* FLOAT_ALGN 08 */ + 0x0007, /* DOUBLE_ALGN 09 */ + 0x0000, /* OCT_ALGN 10 */ + 0x0000, /* BOOL_ALGN 11 */ + 0x0000, /* BCD1_ALGN 12 */ + 0x0001, /* BCD2_ALGN 13 */ + 0x0003, /* BCD4_ALGN 14 */ + 0x0000, /* BIT_ALGN 15 */ + 0x0000 /* VIS_ALGN 16 */ + }; +#endif + +#if (defined(__ALPHA) && defined(__VMS)) + +#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST +#define M_STREND_MODE M_STREND_MODE_LARGEST + +SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] = + { + 0x0000, /* ARRSTRT_ALGN 00 */ + 0x0000, /* ARREND_ALGN 01 */ + 0x0000, /* STRSTRT_ALGN 02 */ + 0x0000, /* STREND_ALGN 03 */ + 0x0000, /* INT8_ALGN 04 */ + 0x0001, /* INT16_ALGN 05 */ + 0x0003, /* INT32_ALGN 06 */ + 0x0007, /* INT64_ALGN 07 */ + 0x0003, /* FLOAT_ALGN 08 */ + 0x0007, /* DOUBLE_ALGN 09 */ + 0x0000, /* OCT_ALGN 10 */ + 0x0000, /* BOOL_ALGN 11 */ + 0x0000, /* BCD1_ALGN 12 */ + 0x0001, /* BCD2_ALGN 13 */ + 0x0003, /* BCD4_ALGN 14 */ + 0x0000, /* BIT_ALGN 15 */ + 0x0000 /* VIS_ALGN 16 */ + }; +#endif + +#if defined(__alpha) && !defined(__VMS) + +#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST +#define M_STREND_MODE M_STREND_MODE_LARGEST + +SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] = + { + 0x0000, /* ARRSTRT_ALGN 00 */ + 0x0000, /* ARREND_ALGN 01 */ + 0x0000, /* STRSTRT_ALGN 02 */ + 0x0000, /* STREND_ALGN 03 */ + 0x0000, /* INT8_ALGN 04 */ + 0x0001, /* INT16_ALGN 05 */ + 0x0003, /* INT32_ALGN 06 */ + 0x0007, /* INT64_ALGN 07 */ + 0x0003, /* FLOAT_ALGN 08 */ + 0x0007, /* DOUBLE_ALGN 09 */ + 0x0000, /* OCT_ALGN 10 */ + 0x0000, /* BOOL_ALGN 11 */ + 0x0000, /* BCD1_ALGN 12 */ + 0x0001, /* BCD2_ALGN 13 */ + 0x0003, /* BCD4_ALGN 14 */ + 0x0000, /* BIT_ALGN 15 */ + 0x0000 /* VIS_ALGN 16 */ + }; +#endif + +#ifdef _WIN32 + +#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST +#define M_STREND_MODE M_STREND_MODE_LARGEST + +SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] = + { + 0x0000, /* ARRSTRT_ALGN 00 */ + 0x0000, /* ARREND_ALGN 01 */ + 0x0000, /* STRSTRT_ALGN 02 */ + 0x0000, /* STREND_ALGN 03 */ + 0x0000, /* INT8_ALGN 04 */ + 0x0001, /* INT16_ALGN 05 */ + 0x0003, /* INT32_ALGN 06 */ + 0x0007, /* INT64_ALGN 07 */ + 0x0003, /* FLOAT_ALGN 08 */ + 0x0007, /* DOUBLE_ALGN 09 */ + 0x0000, /* OCT_ALGN 10 */ + 0x0000, /* BOOL_ALGN 11 */ + 0x0000, /* BCD1_ALGN 12 */ + 0x0001, /* BCD2_ALGN 13 */ + 0x0003, /* BCD4_ALGN 14 */ + 0x0000, /* BIT_ALGN 15 */ + 0x0000 /* VIS_ALGN 16 */ + }; +#endif + +#ifdef VXWORKS + +#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST +#define M_STREND_MODE M_STREND_MODE_LARGEST + +SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] = + { + 0x0000, /* ARRSTRT_ALGN 00 */ + 0x0000, /* ARREND_ALGN 01 */ + 0x0000, /* STRSTRT_ALGN 02 */ + 0x0000, /* STREND_ALGN 03 */ + 0x0000, /* INT8_ALGN 04 */ + 0x0001, /* INT16_ALGN 05 */ + 0x0001, /* INT32_ALGN 06 */ + 0x0001, /* INT64_ALGN 07 */ + 0x0001, /* FLOAT_ALGN 08 */ + 0x0001, /* DOUBLE_ALGN 09 */ + 0x0000, /* OCT_ALGN 10 */ + 0x0000, /* BOOL_ALGN 11 */ + 0x0000, /* BCD1_ALGN 12 */ + 0x0001, /* BCD2_ALGN 13 */ + 0x0001, /* BCD4_ALGN 14 */ + 0x0000, /* BIT_ALGN 15 */ + 0x0000 /* VIS_ALGN 16 */ + }; +#endif + +#if defined (__QNX__) /* packed */ + +#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST +#define M_STREND_MODE M_STREND_MODE_LARGEST + +SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] = + { + 0x0000, /* ARRSTRT_ALGN 00 */ + 0x0000, /* ARREND_ALGN 01 */ + 0x0000, /* STRSTRT_ALGN 02 */ + 0x0000, /* STREND_ALGN 03 */ + 0x0000, /* INT8_ALGN 04 */ + 0x0000, /* INT16_ALGN 05 */ + 0x0000, /* INT32_ALGN 06 */ + 0x0000, /* INT64_ALGN 07 */ + 0x0000, /* FLOAT_ALGN 08 */ + 0x0000, /* DOUBLE_ALGN 09 */ + 0x0000, /* OCT_ALGN 10 */ + 0x0000, /* BOOL_ALGN 11 */ + 0x0000, /* BCD1_ALGN 12 */ + 0x0000, /* BCD2_ALGN 13 */ + 0x0000, /* BCD4_ALGN 14 */ + 0x0000, /* BIT_ALGN 15 */ + 0x0000 /* VIS_ALGN 16 */ + }; +#endif /* __QNX__ */ + +#if defined(linux) +#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST +#define M_STREND_MODE M_STREND_MODE_LARGEST + + +SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] = + { + 0x0000, /* ARRSTRT_ALGN 00 */ + 0x0000, /* ARREND_ALGN 01 */ + 0x0000, /* STRSTRT_ALGN 02 */ + 0x0000, /* STREND_ALGN 03 */ + 0x0000, /* INT8_ALGN 04 */ + 0x0001, /* INT16_ALGN 05 */ + 0x0003, /* INT32_ALGN 06 */ + 0x0003, /* INT64_ALGN 07 */ + 0x0003, /* FLOAT_ALGN 08 */ + 0x0003, /* DOUBLE_ALGN 09 */ + 0x0000, /* OCT_ALGN 10 */ + 0x0000, /* BOOL_ALGN 11 */ + 0x0000, /* BCD1_ALGN 12 */ + 0x0001, /* BCD2_ALGN 13 */ + 0x0003, /* BCD4_ALGN 14 */ + 0x0000, /* BIT_ALGN 15 */ + 0x0000 /* VIS_ALGN 16 */ + }; +#endif /* linux */ + +#if defined (__LYNX) + +#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST +#define M_STREND_MODE M_STREND_MODE_LARGEST + +SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] = + { + 0x0000, /* ARRSTRT_ALGN 00 */ + 0x0000, /* ARREND_ALGN 01 */ + 0x0000, /* STRSTRT_ALGN 02 */ + 0x0000, /* STREND_ALGN 03 */ + 0x0000, /* INT8_ALGN 04 */ + 0x0001, /* INT16_ALGN 05 */ + 0x0003, /* INT32_ALGN 06 */ + 0x0003, /* INT64_ALGN 07 */ + 0x0003, /* FLOAT_ALGN 08 */ + 0x0003, /* DOUBLE_ALGN 09 */ + 0x0000, /* OCT_ALGN 10 */ + 0x0000, /* BOOL_ALGN 11 */ + 0x0000, /* BCD1_ALGN 12 */ + 0x0001, /* BCD2_ALGN 13 */ + 0x0003, /* BCD4_ALGN 14 */ + 0x0000, /* BIT_ALGN 15 */ + 0x0000 /* VIS_ALGN 16 */ + }; +#endif /* __LYNX */ +#endif /* !defined(MMS_LITE) */ + + + +/************************************************************************/ +/************************************************************************/ +/* ms_rt_size_calc */ +/************************************************************************/ +/* */ +/* ****** PRIMITIVE elements alignment is well known. */ +/* Element above == primitive : Add padding to element above. */ +/* { */ +/* prim yy << pad */ +/* prim xx */ +/* } */ +/* Element above == struct end : Add padding to struct end above. */ +/* { */ +/* struct yy */ +/* { */ +/* ... */ +/* } << pad */ +/* prim xx */ +/* } */ +/* Element above == arr end : Add padding to array end above. */ +/* { */ +/* arr yy[zz]; */ +/* arr_end << pad */ +/* prim xx */ +/* } */ +/* */ +/* ****** STRUCTURE START elements alignment is derived from elements */ +/* Element above == primitive : Add padding to element above. */ +/* { */ +/* prim yy */ +/* struct << pad */ +/* { */ +/* ... */ +/* } xx */ +/* } */ +/* Element above == struct end : Add padding to struct end above. */ +/* { */ +/* struct yy */ +/* { */ +/* ... */ +/* } */ +/* struct << pad */ +/* { */ +/* ... */ +/* } xx */ +/* } */ +/* Element above == arr end : Add padding to array end above. */ +/* { */ +/* arr yy[zz]; */ +/* struct << pad */ +/* { */ +/* ... */ +/* } xx */ +/* } */ +/* */ +/* ****** ARRAY START elements alignment is derived from element */ +/* Element above == primitive : Add padding to element above. */ +/* { */ +/* prim yy << pad */ +/* arr xx[zz]; */ +/* } */ +/* Element above == struct end : Add padding to struct end above. */ +/* { */ +/* struct yy */ +/* { */ +/* ... */ +/* } << pad */ +/* arr xx[zz]; */ +/* } */ +/* Element above == arr end : Add padding to array end above. */ +/* { */ +/* arr yy[zz]; */ +/* arr_end << pad */ +/* arr xx[zz]; */ +/* } */ +/* */ +/* STRUCTURE SIZE PADDING - struct end */ +/* struct */ +/* { */ +/* xx */ +/* yy << Pad for structure size */ +/* } */ +/* */ +/* ARRAYS OF STRUCTURES - array of structure end */ +/* struct ss */ +/* { */ +/* xx */ +/* yy */ +/* } << Pad to accomadate ss and xx alignment requirements */ +/* [xx]; */ +/* */ +/* */ + +#if !defined(MMS_LITE) +/* NOTE: For MMS_LITE, these variables are created by Foundry and placed*/ +/* in the Foundry output 'c' file. */ +ST_INT m_struct_start_algn_mode = M_STRSTART_MODE; +ST_INT m_struct_end_algn_mode = M_STREND_MODE; +#endif + +ST_VOID ms_rt_size_calc (RUNTIME_TYPE *rt_head, ST_INT rt_num) + { +ST_INT ellen; +RUNTIME_TYPE *arr1_rt; +RUNTIME_TYPE *rt; +RUNTIME_TYPE *rt_end; +RUNTIME_TYPE *rt_pad_dest; +ST_INT curr_offset; +ST_INT algn; +ST_INT arr_level; +ST_INT arr_start_offset[ASN1_MAX_LEVEL]; +ST_INT arr_element_size; + + S_LOCK_COMMON_RESOURCES (); + + rt = rt_head; /* set runtime ptr */ + rt_end = rt_head + rt_num; /* end block */ + + arr_level = 0; + curr_offset = 0; /* Offset from start of data */ + + rt_pad_dest = NULL; + while (rt < rt_end) + { + if (rt->el_tag == RT_ARR_END) + { + /* Special handling for an array of structures */ + /* We need to check if the structure end needs to be padded */ + arr1_rt = rt - rt->u.arr.num_rt_blks; + if (arr1_rt->el_tag == RT_STR_START) + { + _get_struct_start_align (arr1_rt, &algn, &ellen); + _do_padding (rt_pad_dest, &curr_offset, algn); + } + + /* Now we need to multiply the size of this array element by the */ + /* number of elements in the array */ + --arr_level; + arr_element_size = curr_offset - arr_start_offset[arr_level]; + curr_offset += (arr_element_size * (rt->u.arr.num_elmnts-1)); + } + + /* Get the current RT element's alignment requirements and do any */ + /* required padding on the element above us. */ + _ms_m_get_rt_info (rt, &algn, &ellen); + _do_padding (rt_pad_dest, &curr_offset, algn); + + /* If we are starting an array, we must remember the start offset */ + if (rt->el_tag == RT_ARR_START) + { + arr_start_offset[arr_level] = curr_offset; + ++arr_level; + } + + /* Set the current element's nominal memory requirements */ + rt->el_size = ellen; + + /* Set the offset for the next element */ + curr_offset += ellen; + + /* Usually we pad the element directly above us ... */ + rt_pad_dest = rt; + rt++; + } + +/* We are all done with adjusting padding for our type. */ +/* Get the offset past the last element, for encoding */ + rt_head->offset_to_last = ms_get_blocked_length (rt_head,rt_num); + +/* Let the user have a shot at the runtime type if they want to */ + if (u_rt_type_process) + (*u_rt_type_process) (rt_head, rt_num); + + S_UNLOCK_COMMON_RESOURCES (); + } + +/************************************************************************/ +/* _ms_m_get_rt_info */ +/************************************************************************/ +/* WARNING: Recursive routine */ + +ST_RET _ms_m_get_rt_info (SD_CONST RUNTIME_TYPE *rt, ST_INT *algn_out, + ST_INT *ellen_out) + { +ST_INT algn_index = NUM_ALGN_TYPES; /* init to ILLEGAL value */ +ST_INT ellen; + + switch (rt->el_tag) + { + case RT_STR_START : /* structure starting */ + _get_struct_start_align (rt, algn_out, ellen_out); + return (SD_SUCCESS); + break; + + case RT_STR_END : /* structure done */ + _get_struct_end_align (rt, algn_out, ellen_out); + return (SD_SUCCESS); + break; + + case RT_ARR_START : /* array starting */ + _get_arr_start_align (rt, algn_out, ellen_out); + return (SD_SUCCESS); + break; + + case RT_ARR_END : /* array done */ + ellen = 0; + algn_index = ARREND_ALGN; + break; + + case RT_GENERAL_TIME : /* generalized time */ + ellen = sizeof(time_t); + algn_index = GENERAL_TIME_ALGN; + break; + + case RT_BINARY_TIME : /* binary time is one or 2 ST_INT32 */ + if (rt->u.p.el_len == 6) + ellen = 2 * sizeof(ST_INT32); + else + ellen = sizeof(ST_INT32); + algn_index = INT32_ALGN; + break; + + case RT_UTC_TIME : /* UTC Time is 3 ST_UINT32 in struct */ + ellen = sizeof (MMS_UTC_TIME); /* 3 * sizeof(ST_UINT32); */ + algn_index = INT32_ALGN; + break; + + case RT_INTEGER : /* integer */ + case RT_UNSIGNED : /* integer */ + ellen = rt->u.p.el_len; /* # bytes used */ + switch (ellen) + { + case 1 : + algn_index = INT8_ALGN; + break; + + case 2 : + algn_index = INT16_ALGN; + break; + + case 4 : + algn_index = INT32_ALGN; + break; + +#ifdef INT64_SUPPORT + case 8 : + algn_index = INT64_ALGN; + break; +#endif + } + break; + + case RT_FLOATING_POINT : /* float */ + ellen = rt->u.p.el_len; /* # bytes used */ + if (ellen == 4) + algn_index = FLOAT_ALGN; + else + algn_index = DOUBLE_ALGN; + break; + + case RT_OCTET_STRING : /* octet string */ + ellen = abs (rt->u.p.el_len); /* max # bytes used */ + if (rt->u.p.el_len < 0) /* if variable, allow for size */ + { + algn_index = INT16_ALGN; + ellen += sizeof (ST_INT16); + } + else + algn_index = OCT_ALGN; + break; + + case RT_BOOL : /* boolean */ + ellen = rt->u.p.el_len; /* # bytes used */ + algn_index = BOOL_ALGN; + break; + + case RT_BCD : /* bcd */ + if (rt->u.p.el_len <= 2) + { + ellen = 1; + algn_index = BCD1_ALGN; + } + else if (rt->u.p.el_len <= 4) + { + ellen = 2; + algn_index = BCD2_ALGN; + } + else + { + ellen = 4; + algn_index = BCD4_ALGN; + } + break; + + case RT_BIT_STRING : /* bit string */ + ellen = abs (rt->u.p.el_len)/8; /* # bytes used */ + if (rt->u.p.el_len % 8) /* if not a multiple of 8 */ + ellen++; /* add one to take spare bits */ + + if (rt->u.p.el_len < 0) /* if variable, allow for size */ + { + algn_index = INT16_ALGN; + ellen += sizeof (ST_INT16); + } + else + algn_index = BIT_ALGN; + break; + + case RT_VISIBLE_STRING : /* visible string */ + ellen = abs (rt->u.p.el_len) + 1; /* # bytes used */ + algn_index = VIS_ALGN; + break; + + case RT_UTF8_STRING : /* Unicode UTF8 string */ +#if (UNICODE_LOCAL_FORMAT==UNICODE_UTF8) + ellen = abs(rt->u.p.el_len)*4 + 1;/* # bytes (4 bytes per char + NULL)*/ + algn_index = VIS_ALGN; /* Same alignment as visible string*/ +#else /* assume UNICODE_UTF16 */ + ellen = abs(rt->u.p.el_len)*2 + 2;/* # bytes (2 bytes per char + 2 byte NULL)*/ + algn_index = INT16_ALGN; +#endif + break; + + default : /* should not be any other tag */ + MLOG_NERR0 ("Bad el_tag in RT"); + return (SD_FAILURE); + break; + } + + if (algn_index == NUM_ALGN_TYPES) /* ILLEGAL value */ + { + MLOG_ERR0 ("algn_index never set"); /* THIS SHOULD NEVER HAPPEN */ + return (SD_FAILURE); + } + + *algn_out = m_data_algn_tbl[algn_index]; + *ellen_out = ellen; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _get_struct_start_align */ +/************************************************************************/ +/* WARNING: Recursive routine */ + +static ST_VOID _get_struct_start_align (SD_CONST RUNTIME_TYPE *rt, + ST_INT *algn_out, + ST_INT *ellen_out) + { +ST_INT i; +ST_INT curr_algn; +ST_INT algn; +ST_INT ellen; +ST_INT num_rt; + + algn = m_data_algn_tbl[STRSTRT_ALGN]; + num_rt = rt->u.str.num_rt_blks; + ++rt; /* Point to first structure member */ + if (m_struct_start_algn_mode == M_STRSTART_MODE_LARGEST) + { + for (i = 0; i < num_rt; ++i, ++rt) + { + _ms_m_get_rt_info (rt, &curr_algn, &ellen); + if (curr_algn > algn) + algn = curr_algn; + } + } + else if (m_struct_start_algn_mode == M_STRSTART_MODE_FIRST) + _ms_m_get_rt_info (rt, &algn, &ellen); + + + *algn_out = algn; + *ellen_out = 0; + } + +/************************************************************************/ +/* _get_struct_end_align */ +/************************************************************************/ +/* WARNING: Recursive routine */ + +static ST_VOID _get_struct_end_align (SD_CONST RUNTIME_TYPE *rt, + ST_INT *algn_out, + ST_INT *ellen_out) + { +ST_INT i; +ST_INT algn; +ST_INT curr_algn; +ST_INT ellen; +ST_INT num_rt; + + num_rt = rt->u.str.num_rt_blks; + rt -= rt->u.str.num_rt_blks; + algn = m_data_algn_tbl[STREND_ALGN]; + if (m_struct_end_algn_mode == M_STREND_MODE_LARGEST) + { + for (i = 0; i < num_rt; ++i, ++rt) + { + _ms_m_get_rt_info (rt, &curr_algn, &ellen); + if (curr_algn > algn) + algn = curr_algn; + } + } + + *algn_out = algn; + *ellen_out = 0; + } + +/************************************************************************/ +/* _get_arr_start_align */ +/************************************************************************/ +/* WARNING: Recursive routine */ + +static ST_VOID _get_arr_start_align (SD_CONST RUNTIME_TYPE *rt, + ST_INT *algn_out, + ST_INT *ellen_out) + { +ST_INT i; +ST_INT algn; +ST_INT ellen; +ST_INT num_rt; + + algn = m_data_algn_tbl[ARRSTRT_ALGN]; + num_rt = rt->u.arr.num_rt_blks; + ++rt; + for (i = 0; i < num_rt; ++i, ++rt) + { + if (rt->el_tag != RT_ARR_START) + { + _ms_m_get_rt_info (rt, &algn, &ellen); + break; + } + } + *algn_out = algn; + *ellen_out = 0; + } + +/************************************************************************/ +/* _do_padding */ +/************************************************************************/ + +static ST_VOID _do_padding (RUNTIME_TYPE *padDest, + ST_INT *curr_offset, + ST_INT algn) + { +ST_INT pad; + +/*Increment the offset until no bits are set that shouldn't be */ + pad = 0; + while ((*curr_offset) & algn) + { + (*curr_offset)++; + pad++; + } + + /* If pad bytes are needed, add to the end struct element */ + if (pad) + { + if (!padDest) + { + MLOG_ERR0 ("Alignment table error"); + } + else + padDest->el_size += pad; + } + } + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* ms_get_blocked_len */ +/* Function to return the size of buffer required for blocked data for */ +/* the data type selected. This is used when type definitions come over */ +/* the wire, and in general, when a type is created. */ +/************************************************************************/ + +#ifndef MMS_LITE + +ST_INT ms_get_blocked_len (NAMED_TYPE *tptr) + { + return (ms_get_blocked_length (tptr->rt_head,tptr->rt_num)); + } + +#endif + +/************************************************************************/ +/* ms_get_blocked_length */ +/* If MMS_LITE, this function also sets rt_head->mvluTypeInfo.prim_count*/ +/************************************************************************/ + +ST_INT ms_get_blocked_length (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num) + { +ST_INT total_size; +SD_CONST RUNTIME_TYPE *rt; /* current runtime element */ +SD_CONST RUNTIME_TYPE *rt_end; +ST_INT arr_loop_buf[ASN1_MAX_LEVEL]; +ST_INT arr_loop_level; +ST_INT *arr_loops; +ST_RTINT prim_count; + + S_LOCK_COMMON_RESOURCES (); + arr_loop_level = 0; + arr_loops = arr_loop_buf; + + rt = rt_head; /* set runtime ptr */ + rt_end = rt_head + rt_num; /* end block */ + total_size = 0; + prim_count = 0; /* initialize */ + + while (rt < rt_end) + { + if (rt->el_tag == RT_ARR_START) /* Set up array looping */ + { + ++arr_loop_level; + arr_loops[arr_loop_level] = rt->u.arr.num_elmnts; + } + + if (rt->el_tag == RT_ARR_END) /* treat case of array ending */ + { + if (--arr_loops[arr_loop_level] > 0) /* if need to do next ar elmnt */ + { + rt -= rt->u.arr.num_rt_blks; /* mv rt to start of arr */ + continue; + } + --arr_loop_level; + } + + total_size += rt->el_size; + if (ms_is_rt_prim (rt)) + prim_count++; + rt++; /* point to next runtime element*/ + } + +#if defined(MMS_LITE) + rt_head->mvluTypeInfo.prim_count = prim_count; +#endif + S_UNLOCK_COMMON_RESOURCES (); + return (total_size); + } + + +/************************************************************************/ +/* ms_log_runtime */ +/************************************************************************/ +/* list the elements in a runtime type def table */ + + +#define MAX_INDENT 5 + +ST_VOID ms_log_runtime (SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt) + { + _ms_log_runtime (0, rt, num_rt); + } + + +static ST_VOID _ms_log_runtime (ST_INT indent, SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt) + { +#if defined(DEBUG_SISCO) + +ST_INT i; +const ST_CHAR *comp_name; +ST_CHAR *sp[MAX_INDENT] = + { + " ", + " ", + " ", + " ", + " ", + }; +ST_CHAR *sp2[MAX_INDENT] = + { + " ", + " ", + " ", + " ", + "", + }; + + S_LOCK_COMMON_RESOURCES (); + + if (num_rt == 0) + { + MLOG_ALWAYS0 ("Runtime Type : 0 elements"); + } + else if (indent == 0) + { + MLOG_ALWAYS2 ("Runtime Type : %d elements, Offset past last : %d", + num_rt, rt->offset_to_last); + } + + for (i = 0; i < num_rt; ++i, rt++) + { + comp_name = ms_comp_name_find (rt); + if (strlen (comp_name)) + { + MLOG_CALWAYS3 ("%sNamed comp %s: %s", + sp[indent], + sp2[indent], + comp_name); + } + + switch (rt->el_tag) + { + case RT_ARR_START : + MLOG_CALWAYS5 ("%sArray start %s: size %02d, %02d elmnts, %02d rt", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.arr.num_elmnts, + rt->u.arr.num_rt_blks); + if (++indent >= MAX_INDENT) + indent--; + break; + + case RT_ARR_END : + if (--indent < 0) + indent++; + MLOG_CALWAYS5 ("%sArray end %s: size %02d, %02d elmnts, %02d rt", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.arr.num_elmnts, + rt->u.arr.num_rt_blks); + break; + + case RT_STR_START : + MLOG_CALWAYS4 ("%sStruct start%s: size %02d, %02d rt", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.str.num_rt_blks); + if (++indent >= MAX_INDENT) + indent--; + break; + + case RT_STR_END : + if (--indent < 0) + indent++; + MLOG_CALWAYS3 ("%sStruct end %s: size %02d", + sp[indent], + sp2[indent], + rt->el_size); + break; + + case RT_BOOL : + MLOG_CALWAYS4 ("%sBoolean %s: size %02d, precision %02d", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.p.el_len); + break; + + case RT_BIT_STRING : + MLOG_CALWAYS4 ("%sBitstring %s: size %02d, precision %02d", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.p.el_len); + break; + + case RT_INTEGER : + MLOG_CALWAYS4 ("%sInteger %s: size %02d, precision %02d", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.p.el_len); + break; + + case RT_UNSIGNED : + MLOG_CALWAYS4 ("%sUnsigned %s: size %02d, precision %02d", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.p.el_len); + break; + + case RT_FLOATING_POINT : + MLOG_CALWAYS4 ("%sFloat %s: size %02d, precision %02d", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.p.el_len); + break; + + case RT_OCTET_STRING : + MLOG_CALWAYS4 ("%sOctet Str %s: size %02d, precision %02d", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.p.el_len); + break; + + case RT_VISIBLE_STRING : + MLOG_CALWAYS4 ("%sVisible Str %s: size %02d, precision %02d", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.p.el_len); + break; + + case RT_GENERAL_TIME : + MLOG_CALWAYS4 ("%sGen Time %s: size %02d, precision %02d", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.p.el_len); + break; + + case RT_BINARY_TIME : + MLOG_CALWAYS4 ("%sBin Time %s: size %02d, precision %02d", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.p.el_len); + break; + + case RT_BCD : + MLOG_CALWAYS4 ("%sBCD %s: size %02d, precision %02d", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.p.el_len); + break; + + case RT_UTC_TIME : + MLOG_CALWAYS4 ("%sUTC Time %s: size %02d, precision %02d", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.p.el_len); + break; + + case RT_UTF8_STRING : + MLOG_CALWAYS4 ("%sUTF8string %s: size %02d, precision %02d", + sp[indent], + sp2[indent], + rt->el_size, + rt->u.p.el_len); + break; + + default : /* should not be any other tag */ + MLOG_CALWAYS1 (" **** UNKNOWN ELEMENT %02d ",i); + break; + } + } + + S_UNLOCK_COMMON_RESOURCES (); + +#endif + } + +/************************************************************************/ +/* ms_runtime_create */ +/* This function parses an ASN.1 type definition, and creates a Runtime */ +/* Type Table from it. It allocates memory for the table and fills it in.*/ +/* The table should be destroyed by calling "ms_runtime_destroy". */ +/************************************************************************/ +RUNTIME_CTRL *ms_runtime_create (ST_UCHAR *asn1_data, + ST_UINT asn1_len, + ST_INT max_num_rt) + { +RUNTIME_CTRL *rt_ctrl = NULL; /* assume failure */ +ST_INT num_rt; /* num entries in RUNTIME_TYPE array */ +ASN1_DEC_CTXT aCtx; /* Main decode struct */ +ASN1_TO_RT_DEC_INFO decInfo; /* temporary storage for extra decode info. */ +ST_UCHAR *asn1_tmp; /* temporary copy of asn1_data. */ + + assert (m_data_algn_tbl != NULL); /* ptr MUST be set before now. */ + + /* First decode only to compute "num_rt" (RUNTIME_TYPE array NOT alloc'd)*/ + memset (&aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean.*/ + aCtx.usr_info[0] = &decInfo; /* save ptr to decInfo in context. */ + + /* set global variables to parse the type for size */ + decInfo.calc_only = SD_TRUE; /* flag to calculate num rt blocks*/ + + /* If USE_COMPACT_MMS_STRUCTS defined & ObjectNames included in ASN.1,*/ + /* (maybe other cases) the ASN1 buffer gets corrupted by decode. */ + /* Copy to tmp buffer & use tmp buffer on 1st decode. */ + asn1_tmp = (ST_UCHAR *) chk_calloc (1, asn1_len); + memcpy (asn1_tmp, asn1_data, asn1_len); + num_rt = _ms_asn1_to_runtime (&aCtx, asn1_tmp, asn1_len, NULL, max_num_rt); + chk_free (asn1_tmp); /* done with temporary copy */ + + /* Second decode to alloc & init array of RUNTIME_TYPE structs. */ + if (num_rt) + { + memset (&aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean.*/ + aCtx.usr_info[0] = &decInfo; /* save ptr to decInfo in context.*/ + /* Allocate RUNTIME_CTRL struct plus array of RUNTIME_TYPE structs. */ + rt_ctrl = (RUNTIME_CTRL *) chk_calloc (1, sizeof (RUNTIME_CTRL) + num_rt * sizeof (RUNTIME_TYPE)); + rt_ctrl->rt_first = (RUNTIME_TYPE *)(rt_ctrl + 1); + + /* parse the type encoding a second time to get an RT TYPE */ + decInfo.calc_only = SD_FALSE; +#if defined(USE_RT_TYPE_2) + decInfo.comp_name_size = decInfo.comp_name_used; /* Save running count.*/ + if (decInfo.comp_name_size) + decInfo.comp_name_buf = (ST_CHAR *) chk_calloc (1, decInfo.comp_name_size); + else + decInfo.comp_name_buf = NULL; /* There is no buffer. */ +#endif /* USE_RT_TYPE_2 */ + rt_ctrl->rt_num = _ms_asn1_to_runtime (&aCtx, asn1_data, asn1_len, rt_ctrl->rt_first, num_rt); + if (rt_ctrl->rt_num == 0) + { /* 2nd decode failed. Should almost NEVER happen. Cleanup. */ +#if defined(USE_RT_TYPE_2) + if (decInfo.comp_name_buf) + chk_free (decInfo.comp_name_buf); +#endif + chk_free (rt_ctrl); + rt_ctrl = NULL; + } + } + /* rt_first & rt_num should now be set in rt_ctrl */ + return (rt_ctrl); + } + +/************************************************************************/ +/* ms_runtime_destroy */ +/* This function frees up all the memory for a Runtime Type Table */ +/* created by "ms_runtime_create". */ +/* It should not be called until all references to the Rumtime Type */ +/* (i.e. Variable associations, etc.) have been destroyed. */ +/************************************************************************/ +ST_VOID ms_runtime_destroy (RUNTIME_CTRL *rt_ctrl) + { +#if defined(USE_RT_TYPE_2) +RUNTIME_TYPE *rt_table = rt_ctrl->rt_first; +ST_INT j; + /* Component names only saved if USE_RT_TYPE_2 defined. Must free them.*/ + /* Find the first non-NULL comp_name_ptr. This should be the pointer */ + /* to the buffer allocated for "component names". Free the buffer. */ + for (j=0; j < rt_ctrl->rt_num; j++) + { + if (rt_table[j].comp_name_ptr != 0) + { + chk_free (rt_table[j].comp_name_ptr); /* Free the buffer of names*/ + break; + } + } +#endif /* USE_RT_TYPE_2 */ + + /* Free the table. */ + chk_free (rt_ctrl); + } + +/************************************************************************/ +/* ms_is_rt_prim */ +/************************************************************************/ +ST_BOOLEAN ms_is_rt_prim (SD_CONST RUNTIME_TYPE *rt) + { + switch (rt->el_tag) + { + case RT_BOOL : + case RT_BIT_STRING : + case RT_INTEGER : + case RT_UNSIGNED : + case RT_FLOATING_POINT : + case RT_OCTET_STRING : + case RT_VISIBLE_STRING : + case RT_GENERAL_TIME : + case RT_BINARY_TIME : + case RT_BCD : + case RT_BOOLEANARRAY : + case RT_UTC_TIME : + case RT_UTF8_STRING : + return (SD_TRUE); + break; + } + return (SD_FALSE); + } + +/************************************************************************/ +/* ms_rt_el_tag_text */ +/* Gets "el_tag" from RUNTIME_TYPE struct and converts is to text. */ +/************************************************************************/ +ST_CHAR *ms_rt_el_tag_text (SD_CONST RUNTIME_TYPE *rt_type) + { +ST_CHAR *el_tag_text; + + switch (rt_type->el_tag) + { + case RT_ARR_START: el_tag_text="RT_ARR_START"; break; + case RT_STR_START: el_tag_text="RT_STR_START"; break; + case RT_BOOL: el_tag_text="RT_BOOL"; break; + case RT_BIT_STRING: el_tag_text="RT_BIT_STRING"; break; + case RT_INTEGER: el_tag_text="RT_INTEGER"; break; + case RT_UNSIGNED: el_tag_text="RT_UNSIGNED"; break; + case RT_FLOATING_POINT: el_tag_text="RT_FLOATING_POINT"; break; + case RT_OCTET_STRING: el_tag_text="RT_OCTET_STRING"; break; + case RT_VISIBLE_STRING: el_tag_text="RT_VISIBLE_STRING"; break; + case RT_GENERAL_TIME: el_tag_text="RT_GENERAL_TIME"; break; + case RT_BINARY_TIME: el_tag_text="RT_BINARY_TIME"; break; + case RT_BCD: el_tag_text="RT_BCD"; break; + case RT_BOOLEANARRAY: el_tag_text="RT_BOOLEANARRAY"; break; + case RT_UTC_TIME: el_tag_text="RT_UTC_TIME"; break; + case RT_UTF8_STRING: el_tag_text="RT_UTF8_STRING"; break; + case RT_STR_END: el_tag_text="RT_STR_END"; break; + case RT_ARR_END: el_tag_text="RT_ARR_END"; break; + default: el_tag_text="RT_UNSUPPORTED"; break; /* should never happen*/ + } + return (el_tag_text); + } + +/************************************************************************/ +/* ms_asn1_to_runtime_x */ +/* For backward compatibility only. Does NOT work with USE_RT_TYPE_2. */ +/* New programs should use ms_runtime_create. */ +/************************************************************************/ + +#if !defined(MMS_LITE) +ST_INT ms_asn1_to_runtime_x (ST_UCHAR *asn1_data, ST_UINT asn1_len, + RUNTIME_TYPE *rt_table, ST_INT rt_len, + ST_BOOLEAN calc_only) + { +ST_INT rt_num; /* num entries in RUNTIME_TYPE array */ +ASN1_DEC_CTXT aCtx; /* Main decode struct */ +ASN1_TO_RT_DEC_INFO decInfo; /* temporary storage for extra decode info. */ + + memset (&aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean.*/ + aCtx.usr_info[0] = &decInfo; /* save ptr to decInfo in context.*/ + decInfo.calc_only = calc_only; + + rt_num = _ms_asn1_to_runtime (&aCtx, asn1_data, asn1_len, rt_table, rt_len); + + /* rt_first & rt_num should now be set in rt_ctrl */ + return (rt_num); + } + +#endif /* !MMS_LITE */ + +#if defined(USE_RT_TYPE_2) +/* Currently, the ms_rt_bld*" functions work only if USE_RT_TYPE_2 */ +/* defined. Fix to work with other options, or eliminate them. */ + +/************************************************************************/ +/* ms_rt_bld_set_name */ +/* Copy the comp_name into the buffer and set the comp_name_ptr in the */ +/* current RUNTIME_TYPE pointing to it. */ +/************************************************************************/ +static ST_VOID ms_rt_bld_set_name (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name) + { + if (comp_name) + { + ctxt->rt_type->comp_name_ptr = ctxt->comp_name_buf + (ctxt->rt_ctrl->rt_num * (MAX_IDENT_LEN + 1)); + strcpy (ctxt->rt_type->comp_name_ptr, comp_name); + } + } +/************************************************************************/ +/* ms_rt_bld_compress */ +/* NOTE: don't need to save pointer to component name buffer allocated */ +/* here. This buf is freed in "ms_runtime_destroy" by using the */ +/* "comp_name_ptr" of the first RUNTIME_TYPE. */ +/************************************************************************/ +static ST_VOID ms_rt_bld_compress (RUNTIME_BUILD_CTXT *ctxt) + { +RUNTIME_CTRL *rt_ctrl = ctxt->rt_ctrl; +RUNTIME_TYPE *rt_type; +ST_CHAR *compressed_buf;/* allocated buf to store all component names. */ +ST_CHAR *cur_ptr; /* ptr to current position in buffer. */ +ST_INT j; +size_t total_len; + + /* Compute total len of all component names (including 1 byte NULL terminator).*/ + for (j = 0, rt_type = rt_ctrl->rt_first, total_len = 0; j< rt_ctrl->rt_num; j++, rt_type++) + { + if (rt_type->comp_name_ptr) + total_len += (strlen(rt_type->comp_name_ptr) + 1); + } + /* Allocate new buffer. Copy all component names to new buffer */ + /* and update each component name pointer. */ + compressed_buf = chk_malloc (total_len); + for (j = 0, rt_type = rt_ctrl->rt_first, cur_ptr = compressed_buf; + j< rt_ctrl->rt_num; + j++, rt_type++) + { + if (rt_type->comp_name_ptr) + { + strcpy (cur_ptr, rt_type->comp_name_ptr); + rt_type->comp_name_ptr = cur_ptr; + cur_ptr += (strlen(rt_type->comp_name_ptr) + 1); + } + } + assert (cur_ptr == compressed_buf + total_len); /* make sure we counted right*/ + /* Done with old buffer, so free it, and set pointer back to NULL. */ + chk_free (ctxt->comp_name_buf); + ctxt->comp_name_buf = NULL; + } + +/************************************************************************/ +/* ms_rt_bld_start */ +/* Start building a type. */ +/* If max_rt_num == 0: */ +/* Start computing the number of RUNTIME_TYPE elements */ +/* by setting "do_count=SD_TRUE" (used by all lower ms_rt_bld* functs).*/ +/* Call ms_rt_bld_get_count when build is done to get the count. */ +/* DO NOT need to call ..bld_finish or ..bld_cancel when build is done.*/ +/* If max_rt_num != 0: */ +/* Alloc that number of RUNTIME_TYPE elements and prepare to fill them in.*/ +/* MUST call ..bld_finish or ..bld_cancel to clean up when build is done.*/ +/************************************************************************/ +ST_VOID ms_rt_bld_start (RUNTIME_BUILD_CTXT *rt_ctxt, ST_INT max_rt_num) + { +RUNTIME_CTRL *rt_ctrl; + + if (max_rt_num==0) + { /* set up to compute number of RUNTIME_TYPE */ + /* NOTE: this memset effectively sets these paramters as we want: */ + /* rt_ctxt->curr_count = 0 (lower functions increment it). */ + /* rt_ctxt->rt_ctrl = NULL (must not write to it). */ + memset (rt_ctxt, 0, sizeof (RUNTIME_BUILD_CTXT)); /* start clean */ + rt_ctxt->do_count = SD_TRUE; + return; + } + + /* Allocate RUNTIME_CTRL struct plus array of RUNTIME_TYPE structs. */ + rt_ctrl = (RUNTIME_CTRL *) chk_calloc (1, sizeof (RUNTIME_CTRL) + max_rt_num * sizeof (RUNTIME_TYPE)); + rt_ctrl->rt_first = (RUNTIME_TYPE *)(rt_ctrl + 1); + /* NOTE: rt_ctrl->rt_num = 0 now. Incremented as types added. */ + + /* Initialize the runtime build context structure. */ + /* NOTE: this memset effectively sets these paramters as we want: */ + /* rt_ctxt->nest_level = 0; */ + /* rt_ctxt->errcode = SD_SUCCESS; */ + /* rt_ctxt->do_count = SD_FALSE; */ + memset (rt_ctxt, 0, sizeof (RUNTIME_BUILD_CTXT)); /* start clean */ + rt_ctxt->rt_ctrl = rt_ctrl; + rt_ctxt->rt_type = rt_ctrl->rt_first; /* point to first. This ptr */ + /* incremented as types added */ + rt_ctxt->max_rt_type = rt_ctrl->rt_first + max_rt_num; + /* Allocate buffer to store component names. Compress it later using */ + /* ms_rt_bld_compress. */ + rt_ctxt->comp_name_buf = chk_calloc (max_rt_num , (MAX_IDENT_LEN+1)); + memset (rt_ctxt->nest_start_ptr, 0, sizeof (rt_ctxt->nest_start_ptr)); + } +/************************************************************************/ +/************************************************************************/ +ST_VOID ms_rt_bld_cancel (RUNTIME_BUILD_CTXT *rt_ctxt) + { + if (rt_ctxt->do_count) + return; /* no cleanup necessary */ + + if (rt_ctxt->comp_name_buf) + { + chk_free (rt_ctxt->comp_name_buf); + rt_ctxt->comp_name_buf = NULL; + } + chk_free (rt_ctxt->rt_ctrl); + } +/************************************************************************/ +/************************************************************************/ +ST_VOID ms_rt_bld_finish (RUNTIME_BUILD_CTXT *rt_ctxt) + { + if (rt_ctxt->do_count) + return; /* no cleanup necessary */ + + /* This assert verifies rt_num & rt_type incremented/decremented correctly.*/ + assert (&rt_ctxt->rt_ctrl->rt_first[rt_ctxt->rt_ctrl->rt_num] == rt_ctxt->rt_type); + ms_rt_bld_compress (rt_ctxt); + + /* CRITICAL: this funct sets "el_size" in every RUNTIME_TYPE.*/ + ms_rt_size_calc (rt_ctxt->rt_ctrl->rt_first, rt_ctxt->rt_ctrl->rt_num); + } + +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_remove_last (RUNTIME_BUILD_CTXT *ctxt) + { +RUNTIME_TYPE *rt_type; + + if (ctxt->do_count) + { + assert (ctxt->curr_count > 0); /* this should never be called otherwise*/ + ctxt->curr_count--; + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + + if (ctxt->rt_ctrl->rt_num > 0) + { + ctxt->rt_ctrl->rt_num--; + ctxt->rt_type--; /* always decrement this & rt_num at same time*/ + rt_type = ctxt->rt_type; + /* If removing STR_START or ARR_START must adjust nest level*/ + if (rt_type->el_tag==RT_STR_START || rt_type->el_tag== RT_ARR_START) + ctxt->nest_level--; + memset (rt_type, 0, sizeof (RUNTIME_TYPE)); /* clean struct */ + return (SD_SUCCESS); + } + else + return (SD_FAILURE); /* already empty. Nothing to remove.*/ + } +/************************************************************************/ +/* Check if state is valid to add another type. */ +/* CRITICAL: DO NOT use when (ctxt->do_count==SD_TRUE). */ +/************************************************************************/ +ST_RET ms_rt_bld_chk_state (RUNTIME_BUILD_CTXT *ctxt) + { + if (ctxt->errcode) + return (ctxt->errcode); /* err already set. Just return it. */ + + if (ctxt->rt_type >= ctxt->max_rt_type) + { + /* NOTE: if this error occurs, try calling ms_rt_bld_start with larger num*/ + /* NOTE: we want to log the "max_rt_num" passed to "ms_rt_bld_start"*/ + /* but we didn't save it, so use pointer arithmetic to compute it.*/ + MLOG_ERR1 ("Error building type. Exceeds max number of elements '%d'", + ctxt->max_rt_type - ctxt->rt_ctrl->rt_first); + ctxt->errcode = SD_FAILURE; /* set flag so all subsequent calls fail too.*/ + return (SD_FAILURE); + } + return (SD_SUCCESS); + } +/************************************************************************/ +/* Get current count. */ +/* CRITICAL: maximum count may be slightly more than current count */ +/* because RT_STR_START or RT_ARR_START may be temporarily added, then */ +/* removed later if they are empty (see ms_rt_bld_remove_last). */ +/************************************************************************/ +ST_INT ms_rt_bld_get_count (RUNTIME_BUILD_CTXT *ctxt) + { + if (ctxt->do_count) + return (ctxt->curr_count); + else + return (ctxt->rt_ctrl->rt_num); /* usually same as curr_count, */ + /* but may be different on error*/ + } +/************************************************************************/ +/* Get maximum count. */ +/* CRITICAL: maximum count may be slightly more than current count */ +/* because RT_STR_START or RT_ARR_START may be temporarily added, then */ +/* removed later if they are empty (see ms_rt_bld_remove_last). */ +/************************************************************************/ +ST_INT ms_rt_bld_get_max_count (RUNTIME_BUILD_CTXT *ctxt) + { + assert (ctxt->do_count!=SD_FALSE); /* only valid if do_count is TRUE.*/ + return (ctxt->max_count); + } +/************************************************************************/ +/* Increment the count and adjust the max count, if necessary. */ +/************************************************************************/ +static ST_VOID inc_count (RUNTIME_BUILD_CTXT *ctxt) + { + ctxt->curr_count++; + if (ctxt->curr_count > ctxt->max_count) + ctxt->max_count = ctxt->curr_count; /* update max */ + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_str_start (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + rt_type->el_tag = RT_STR_START; + ms_rt_bld_set_name (ctxt, comp_name); + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + assert (ctxt->nest_level < ASN1_MAX_LEVEL); + ctxt->nest_start_ptr[ctxt->nest_level++] = rt_type; + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_str_end (RUNTIME_BUILD_CTXT *ctxt) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_INT num_rt; +RUNTIME_TYPE *rt_start; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + if (--ctxt->nest_level < 0) + { + MLOG_ERR0 ("STR_END does not have corresponding STR_START"); + ctxt->errcode = SD_FAILURE; /* DEBUG: use different errcode?*/ + return (ctxt->errcode); + } + rt_start = ctxt->nest_start_ptr[ctxt->nest_level]; + if (rt_start->el_tag != RT_STR_START) + { + MLOG_ERR0 ("STR_END does not have corresponding STR_START"); + ctxt->errcode = SD_FAILURE; /* DEBUG: use different errcode?*/ + return (ctxt->errcode); + } + num_rt = (rt_type - rt_start - 1); + rt_start->u.str.num_rt_blks = num_rt; + rt_type->u.str.num_rt_blks = num_rt; + rt_type->el_tag = RT_STR_END; + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_arr_start (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT array_count) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + rt_type->el_tag = RT_ARR_START; + ms_rt_bld_set_name (ctxt, comp_name); + rt_type->u.arr.num_elmnts = array_count; + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + ctxt->nest_start_ptr[ctxt->nest_level++] = rt_type; + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_arr_end (RUNTIME_BUILD_CTXT *ctxt) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_INT num_rt; +RUNTIME_TYPE *rt_start; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + if (--ctxt->nest_level < 0) + { + MLOG_ERR0 ("ARR_END does not have corresponding ARR_START"); + ctxt->errcode = SD_FAILURE; /* DEBUG: use different errcode?*/ + return (ctxt->errcode); + } + rt_start = ctxt->nest_start_ptr[ctxt->nest_level]; + if (rt_start->el_tag != RT_ARR_START) + { + MLOG_ERR0 ("ARR_END does not have corresponding ARR_START"); + ctxt->errcode = SD_FAILURE; /* DEBUG: use different errcode?*/ + return (ctxt->errcode); + } + num_rt = (rt_type - rt_start - 1); + rt_type->u.arr.num_rt_blks = num_rt; + rt_start->u.arr.num_rt_blks = num_rt; + +/* copy the element count from the start block to the end block */ + rt_type->u.arr.num_elmnts = rt_start->u.arr.num_elmnts; + + rt_type->el_tag = RT_ARR_END; + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_bool (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + rt_type->el_tag = RT_BOOL; + rt_type->u.p.el_len = 1; + ms_rt_bld_set_name (ctxt, comp_name); + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_int (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + rt_type->el_tag = RT_INTEGER; + rt_type->u.p.el_len = el_len; + ms_rt_bld_set_name (ctxt, comp_name); + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_uint (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + rt_type->el_tag = RT_UNSIGNED; + rt_type->u.p.el_len = el_len; + ms_rt_bld_set_name (ctxt, comp_name); + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_float (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + rt_type->el_tag = RT_FLOATING_POINT; + rt_type->u.p.el_len = el_len; + ms_rt_bld_set_name (ctxt, comp_name); + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_bstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + rt_type->el_tag = RT_BIT_STRING; + rt_type->u.p.el_len = el_len; + ms_rt_bld_set_name (ctxt, comp_name); + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_bvstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + rt_type->el_tag = RT_BIT_STRING; + rt_type->u.p.el_len = -el_len; + ms_rt_bld_set_name (ctxt, comp_name); + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_vstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + rt_type->el_tag = RT_VISIBLE_STRING; + rt_type->u.p.el_len = -el_len; + ms_rt_bld_set_name (ctxt, comp_name); + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_utctime (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + rt_type->el_tag = RT_UTC_TIME; + rt_type->u.p.el_len = 8; + ms_rt_bld_set_name (ctxt, comp_name); + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_btime6 (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + rt_type->el_tag = RT_BINARY_TIME; + rt_type->u.p.el_len = 6; + ms_rt_bld_set_name (ctxt, comp_name); + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_ostring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + rt_type->el_tag = RT_OCTET_STRING; + rt_type->u.p.el_len = el_len; + ms_rt_bld_set_name (ctxt, comp_name); + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_ovstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + rt_type->el_tag = RT_OCTET_STRING; + rt_type->u.p.el_len = -el_len; + ms_rt_bld_set_name (ctxt, comp_name); + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +/************************************************************************/ +/************************************************************************/ +ST_RET ms_rt_bld_add_utf8vstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + rt_type->el_tag = RT_UTF8_STRING; + rt_type->u.p.el_len = -el_len; + ms_rt_bld_set_name (ctxt, comp_name); + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +/************************************************************************/ +/* Use info from caller's RUNTIME_TYPE struct. */ +/************************************************************************/ +ST_RET ms_rt_bld_add_special (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, RUNTIME_TYPE *special) + { +RUNTIME_TYPE *rt_type = ctxt->rt_type; +ST_RET ret; + if (ctxt->do_count) + { + inc_count (ctxt); + return (SD_SUCCESS); /* just counting, nothing else to do */ + } + if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS) + return (ret); + + /* NOTE: only need el_tag & el_len */ + rt_type->el_tag = special->el_tag; + rt_type->u.p.el_len = special->u.p.el_len; + ms_rt_bld_set_name (ctxt, comp_name); + ctxt->rt_ctrl->rt_num++; + ctxt->rt_type++; /* always increment this & rt_num at same time*/ + return (SD_SUCCESS); + } +#endif /* defined(USE_RT_TYPE_2) */ diff --git a/mmslib/mmsl/mmscancl.c b/mmslib/mmsl/mmscancl.c new file mode 100644 index 0000000..99a672f --- /dev/null +++ b/mmslib/mmsl/mmscancl.c @@ -0,0 +1,73 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmscancl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the common function to encode a conclude */ +/* operation. Note that the cancel request and the cancel */ +/* response are the same. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 01 Added SD_CONST modifiers */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* _ms_mk_cancel */ +/* Construct a cancel response or request PDU. */ +/************************************************************************/ + +ST_UCHAR *_ms_mk_cancel (ASN1_ENC_CTXT *aCtx, ST_BOOLEAN request, ST_UCHAR *msg_ptr, ST_INT buf_len, ST_UINT32 id) + { +ST_UCHAR *msg_start; +#ifdef DEBUG_SISCO +ST_INT msg_len; /* Used for debug print only */ +#endif + + asn1r_strt_asn1_bld (aCtx, msg_ptr,buf_len); /* init the ASN.1 tools */ + + asn1r_wr_u32 (aCtx, id); /* write the invoke id */ + +/* Finish the PDU with the correct context tag. */ + if (request) + asn1r_fin_prim (aCtx, MMSCANREQ,CTX); + else + asn1r_fin_prim (aCtx, MMSCANRESP,CTX); + + msg_start = aCtx->asn1r_field_ptr + 1; +#ifdef DEBUG_SISCO + msg_len = (msg_ptr + buf_len) - msg_start; + MLOG_ENC1 ("CANCEL response built, len = %d", msg_len); + MLOG_ENCH (msg_len,msg_start); + MLOG_PAUSEENC (NULL); +#endif + + return (msg_start); + } diff --git a/mmslib/mmsl/mmsconcl.c b/mmslib/mmsl/mmsconcl.c new file mode 100644 index 0000000..0cfb145 --- /dev/null +++ b/mmslib/mmsl/mmsconcl.c @@ -0,0 +1,76 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsconcl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the common function to encode a conclude */ +/* operation. Note that the conclude request and the conclude */ +/* response are the same. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 01 Added SD_CONST modifiers */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_conclude */ +/* Function to construct a conclude message in selected buffer. */ +/* This may be used for either request or response by selecting the */ +/* PDU type desired. Pass a pointer to the end of the build buffer. */ +/* Returns a pointer to the first byte of the decoded message. */ +/************************************************************************/ + +ST_UCHAR *_ms_mk_conclude (ASN1_ENC_CTXT *aCtx, ST_UCHAR *buf_ptr, ST_INT buf_len, ST_INT pdutype) + { +#ifdef DEBUG_SISCO +ST_UCHAR *msg_start; /* These variables used for */ +ST_INT msg_len; /* debug print only */ +#endif + + asn1r_strt_asn1_bld (aCtx, buf_ptr,buf_len); /* init the ASN.1 tools */ + +/* The only data element is a context-tagged NULL. */ + +#ifdef DEBUG_SISCO + asn1r_fin_prim (aCtx, (ST_UINT16) pdutype, CTX); + msg_start = aCtx->asn1r_field_ptr + 1; + msg_len = (buf_ptr + buf_len) - msg_start; + MLOG_ENC2 ("CONCLUDE %s built, len = %d", + pdutype == MMSCNCLREQ ? "request" : "response", + msg_len); + MLOG_ENCH (msg_len,msg_start); + MLOG_PAUSEENC (NULL); + return (msg_start); +#else + asn1r_fin_prim (aCtx, (ST_UINT16) pdutype,CTX); + return (aCtx->asn1r_field_ptr + 1); +#endif + } diff --git a/mmslib/mmsl/mmsdata.c b/mmslib/mmsl/mmsdata.c new file mode 100644 index 0000000..585dc24 --- /dev/null +++ b/mmslib/mmsl/mmsdata.c @@ -0,0 +1,1758 @@ +/***********************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2008, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsdata.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the functions employed by the virtual */ +/* machine for translating ASN.1 data (from the MMS 'Data' */ +/* production) to local data, and vice versa. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/26/09 JRB 31 Avoid moving constructed bstr, ostr data. */ +/* Del undocumented BAD_DATA, INTERNAL errcodes.*/ +/* 07/21/09 JRB 30 Chk new asn1r_bitstr_truncated flag. */ +/* 06/25/09 MDE 29 Fixed octet string overwrite hole */ +/* 05/01/08 JRB 28 ms_asn1_to_local: return error from decoder. */ +/* 04/09/08 JRB 27 wr_prim_dat: fail if BVstring, OVstring len<0*/ +/* 01/29/08 EJV 26 Use S_FMT_PTR macro to log pointers. */ +/* 08/09/06 JRB 25 Add ms_local_to_asn1_2. */ +/* Log TDL & data if wr_prim_dat fails. */ +/* 03/22/06 EJV 24 RT_GENERAL_TIME: cast datptr to (time_t *). */ +/* 10/29/04 JRB 23 Use ms_is_rt_prim, safer than el_tag range chk*/ +/* 01/20/04 MDE 22 Changed some MLOG_ERR to MLOG_NERR */ +/* 01/14/04 JRB 21 ms_local_to_asn1: stop encoding if */ +/* asn1r_encode_overrun flag is set. */ +/* 10/13/03 JRB 20 asn1r_magic error: Chg assert to err return. */ +/* 04/14/03 JRB 19 Eliminate compiler warnings. */ +/* 03/31/03 JRB 18 Add UTF8string support (see RT_UTF8_STRING). */ +/* Use new RT_MAX_PRIM_TAG in range chk. */ +/* asn1r_get_bitstr: add max_bits arg. */ +/* 12/12/02 JRB 17 Verify aCtx using asn1r_magic. */ +/* 07/12/02 JRB 16 Log Local Data Type (TDL) & maybe ASN.1 data */ +/* if conversion fails. */ +/* 01/23/02 JRB 15 Simplify use of usr_info (fixes QNX compile) */ +/* 12/06/01 JRB 14 Convert to use ASN1R (re-entrant ASN1). */ +/* Add ASN1_DEC_CTXT arg to ms_loc*_to_asn1. */ +/* Add function ms_local_to_asn1_easy. */ +/* On decode, replace globals with ..usr_info[].*/ +/* Use macros to access usr_info[], more readable.*/ +/* Pass datptr,rt_ptr as args to wr_prim_dat. */ +/* Delete all locks, functions now thread-safe. */ +/* 11/14/01 EJV 13 Added support for new MMS type UtcTime: */ +/* added get_utc_time_prim func; */ +/* ms_local_to_asn1: replaced RT_BOOLEANARRAY */ +/* with RT_UTC_TIME in range check; */ +/* wr_prim_dat: added case for RT_UTC_TIME; */ +/* 09/22/00 DSF 12 Truncate extended prim bitstrings */ +/* 09/13/99 MDE 11 Added SD_CONST modifiers */ +/* 03/11/98 MDE 10 Removed NEST_RT_TYPES */ +/* 02/10/98 MDE 09 No longer use runtime type 'loops' element */ +/* 12/10/97 MDE 08 Cast for call to get_i8 */ +/* 09/05/97 MDE 07 Minor logging changes */ +/* 08/15/97 MDE 06 BTOD handling changes */ +/* 08/14/97 MDE 05 Fixed get_bcd_prim (ST_CHAR -> ST_INT8) */ +/* 07/02/97 MDE 04 Check for ASN.1 encode overrun */ +/* 06/19/97 MDE 03 Added 64 bit integer support */ +/* 06/10/97 MDE 02 Removed stub functions (AA, AA Data) */ +/* 06/09/97 MDE 01 Modified Runtime Type handling */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" + +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "asn1defs.h" +#if defined(_S_TEST_PROBES) +#include "stestprb.h" +#endif + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* DEC_INFO - structure to store temporary decode information. */ +/************************************************************************/ +typedef struct + { + ST_INT arr_loop_level; + ST_INT *arr_loops; + SD_CONST RUNTIME_TYPE *rt_ptr; /* current RUNTIME_TYPE struct */ + SD_CONST RUNTIME_TYPE *rt_end; /* last RUNTIME_TYPE struct */ + ST_CHAR *datptr; /* decoded data destination */ + } DEC_INFO; + +/************************************************************************/ +/* Local functions for ASN1 decode. */ +/************************************************************************/ +static ST_VOID assign_tags (ASN1_DEC_CTXT *aCtx); +static ST_RET wr_prim_dat (ASN1_ENC_CTXT *aCtx, ST_CHAR *datptr, SD_CONST RUNTIME_TYPE *rt_ptr); +static ST_VOID get_bstr_cstr (ASN1_DEC_CTXT *aCtx); /* for constructed bitstrings */ +static ST_VOID bs_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_ostr_cstr (ASN1_DEC_CTXT *aCtx); /* for constructed octetstrings */ +static ST_VOID os_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_bool_prim (ASN1_DEC_CTXT *aCtx); /* for boolean primitives */ +static ST_VOID get_bitstr_prim (ASN1_DEC_CTXT *aCtx); /* for bitstring primitives */ +static ST_VOID get_int_prim (ASN1_DEC_CTXT *aCtx); /* for integer primitives */ +static ST_VOID get_uint_prim (ASN1_DEC_CTXT *aCtx); /* for unsigned integers */ +static ST_VOID get_float_prim (ASN1_DEC_CTXT *aCtx); /* for float primitives */ +static ST_VOID get_octstr_prim (ASN1_DEC_CTXT *aCtx); /* for octet string primitives */ +static ST_VOID get_vstr_prim (ASN1_DEC_CTXT *aCtx); /* for visible string primitives*/ +static ST_VOID get_gtime_prim (ASN1_DEC_CTXT *aCtx); /* for generalized time */ +static ST_VOID get_btime_prim (ASN1_DEC_CTXT *aCtx); /* for binary time primitives */ +static ST_VOID get_utc_time_prim (ASN1_DEC_CTXT *aCtx); /* for UTC time primitives */ +static ST_VOID get_bcd_prim (ASN1_DEC_CTXT *aCtx); /* for binary coded decimal */ +static ST_VOID get_utf8_prim (ASN1_DEC_CTXT *aCtx); /* for Unicode UTF8string */ +static ST_VOID arr_start (ASN1_DEC_CTXT *aCtx); +static ST_VOID str_start (ASN1_DEC_CTXT *aCtx); +static ST_VOID arr_done_fun (ASN1_DEC_CTXT *aCtx); +static ST_VOID str_done_fun (ASN1_DEC_CTXT *aCtx); +static ST_VOID data_asn1_decode_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID data_dec_err (ASN1_DEC_CTXT *aCtx,ST_RET); /* for type definition error */ + +static ST_VOID _log_data_type (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num); + +#if defined(_S_TEST_PROBES) + +static ST_RET _wr_constructed_bitstring (ASN1_ENC_CTXT *aCtx, ST_CHAR *datptr, + SD_CONST RUNTIME_TYPE *rt_ptr); + +static ST_RET _wr_constructed_octetstring (ASN1_ENC_CTXT *aCtx, ST_CHAR *datptr, + SD_CONST RUNTIME_TYPE *rt_ptr); + +#endif + +/************************************************************************/ +/* ms_asn1_to_locl */ +/* Function to convert an MMS ASN.1 'Data' entity into local blocked */ +/* data. Uses the ASN1DE decode tools to check the received data */ +/* against the expected data for the selected type using the runtime */ +/* type table for that type. Returns 0 if the decode is OK, else an */ +/* error code. */ +/************************************************************************/ + +#ifndef MMS_LITE + +ST_RET ms_asn1_to_locl (NAMED_TYPE *tptr, ST_UCHAR *asn1ptr, + ST_INT asn1len, ST_CHAR *dptr) + { + if (!tptr->rt_num) /* check to make sure some components */ + { + MLOG_NERR0 ("Named type has no runtime elements"); + return (MVE_RT_TYPE); /* 0 length typedef is error */ + } + return (ms_asn1_to_local (tptr->rt_head,tptr->rt_num, + asn1ptr,asn1len,dptr)); + } + +#endif + +/************************************************************************/ +/* ms_asn1_to_local */ +/************************************************************************/ + +ST_RET ms_asn1_to_local (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + ST_UCHAR *asn1ptr, ST_INT asn1len, ST_CHAR *dptr) + { +ST_RET ret; +ST_INT arr_loop_buf[ASN1_MAX_LEVEL]; +ASN1_DEC_CTXT aCtx; +DEC_INFO decInfo; /* temporary storage for decode info. */ + + /* Set initial values in decInfo. */ + decInfo.arr_loop_level = 0; + decInfo.arr_loops = arr_loop_buf; + decInfo.rt_ptr = rt_head; /* point to head rt_block */ + decInfo.rt_end = decInfo.rt_ptr + rt_num; /* done when pointer is here*/ + decInfo.datptr = dptr; /* datptr is the running dest pointer. */ + + /* Initialize the decode context "aCtx" and call "asn1r_decode_asn1". */ + memset (&aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean.*/ + aCtx.usr_info[0] = &decInfo; /* save ptr to decInfo in context. */ + aCtx.asn1r_decode_method = ASN1_TAG_METHOD; /* select tag method */ + aCtx.asn1r_decode_done_fun = asn1r_done_err;/* not legal to be done at this time */ + aCtx.asn1r_err_fun = data_dec_err; /* parse error => call to data_dec_err */ + + assign_tags (&aCtx); /* set up tags allowed by 1st rt_block */ + asn1r_decode_asn1 (&aCtx,asn1ptr,asn1len);/* decode entire ASN.1 'Data' entity */ + + if (aCtx.asn1r_pdu_dec_err == NO_DECODE_ERR)/* check for sucess or return error */ + ret = SD_SUCCESS; + else + { + MLOG_NERR0 ("ASN.1 to Local data conversion error. ASN.1 data to convert:"); + if (mms_debug_sel & MMS_LOG_NERR) + { /* use ALWAYSH but only if NERR enabled*/ + MLOG_ALWAYSH (asn1len, asn1ptr); + } + /* Conversion failed, try to log the type used for the conversion. */ + _log_data_type (rt_head, rt_num); + + ret = aCtx.asn1r_pdu_dec_err; /* Just return ASN.1 decode error*/ + } + + return (ret); + } + +/************************************************************************/ +/* assign_tags */ +/* Function to assign tags to the ASN1DE tools based on what's expected */ +/* in the runtime_type definition table. At the beginning of the 'Data'*/ +/* entity, a DataAccessError type is allowed. WARNING: This function */ +/* requires that the current rt_block NOT be an end-of-array or end-of- */ +/* structure rt_block. If so, it will return an error. */ +/************************************************************************/ + +static ST_VOID assign_tags (ASN1_DEC_CTXT *aCtx) + { +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + if (decInfo->rt_ptr < decInfo->rt_end) /* if elements to look at */ + { + if (decInfo->rt_ptr->el_tag == RT_ARR_END) /* treat case of array ending*/ + { + if (--decInfo->arr_loops[decInfo->arr_loop_level] > 0) /* if need to do next ar elmnt */ + decInfo->rt_ptr -= decInfo->rt_ptr->u.arr.num_rt_blks; /* mv rtPtr to start of arr */ + else + --decInfo->arr_loop_level; + } + + switch (decInfo->rt_ptr->el_tag) + { + case RT_ARR_START : + ASN1R_TAG_ADD (aCtx,CTX|CONSTR,1,arr_start); /* expecting an array cstr */ + break; + + case RT_STR_START : + ASN1R_TAG_ADD (aCtx,CTX|CONSTR,2,str_start); /* expecting an struct cstr */ + break; + + case RT_BOOL : + ASN1R_TAG_ADD (aCtx,CTX,3,get_bool_prim); + break; + + case RT_BIT_STRING : + ASN1R_TAG_ADD (aCtx,CTX,4,get_bitstr_prim); + ASN1R_TAG_ADD (aCtx,CTX|CONSTR,4,get_bstr_cstr); + break; + + case RT_INTEGER : + ASN1R_TAG_ADD (aCtx,CTX,5,get_int_prim); + break; + + case RT_UNSIGNED : + ASN1R_TAG_ADD (aCtx,CTX,6,get_uint_prim); + break; + +#ifdef FLOAT_DATA_SUPPORT + case RT_FLOATING_POINT : + ASN1R_TAG_ADD (aCtx,CTX,7,get_float_prim); + break; +#endif + + case RT_OCTET_STRING : + ASN1R_TAG_ADD (aCtx,CTX,9,get_octstr_prim); + ASN1R_TAG_ADD (aCtx,CTX|CONSTR,9,get_ostr_cstr); + break; + + case RT_VISIBLE_STRING : + ASN1R_TAG_ADD (aCtx,CTX,10,get_vstr_prim); + break; + +#ifdef TIME_DATA_SUPPORT + case RT_GENERAL_TIME : + ASN1R_TAG_ADD (aCtx,CTX,11,get_gtime_prim); + break; +#endif + +#ifdef BTOD_DATA_SUPPORT + case RT_BINARY_TIME : + ASN1R_TAG_ADD (aCtx,CTX,12,get_btime_prim); + break; +#endif + + case RT_BCD : + ASN1R_TAG_ADD (aCtx,CTX,13,get_bcd_prim); + break; + + case RT_UTC_TIME : + ASN1R_TAG_ADD (aCtx,CTX,17,get_utc_time_prim); + break; + + case RT_UTF8_STRING : + ASN1R_TAG_ADD (aCtx,CTX,RT_UTF8_STRING,get_utf8_prim); + break; + + case RT_ARR_END : /* array done */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = arr_done_fun; /* the arr cstr must be done*/ + break; + + case RT_STR_END : /* structure done */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = str_done_fun; /* the str cstr must be done*/ + break; + + default : /* should not be any other tag */ + MLOG_NERR0 ("Bad tag in runtime type"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + return; + break; + } + } + else /* no more elements to do */ + { + aCtx->asn1r_decode_done = SD_TRUE; /* terminate decode */ + aCtx->asn1r_decode_done_fun = data_asn1_decode_done; /* ok to be done now */ + } + } +/****************************************************************** +Function name: +Author: YDF +Version: V1.00 +Date: 2008-5-14 +Description: 改进例程中的ms_asn1_to_local函数 +Input Parameter: NULL +Return Parameter: NULL +Modify History: + + ydf 2008-05-014 首次版本创建 +*******************************************************************/ +static ST_VOID assign_tags_new (ASN1_DEC_CTXT *aCtx); +ST_RET ms_asn1_to_local_new (ST_UCHAR tag, ST_INT16 size,ST_INT rt_num, + ST_UCHAR *asn1ptr, ST_INT asn1len, ST_CHAR *dptr) +{ +ST_RET ret; +ST_INT arr_loop_buf[ASN1_MAX_LEVEL]; +ASN1_DEC_CTXT aCtx; +DEC_INFO decInfo; /* temporary storage for decode info. */ +RUNTIME_TYPE rt_head; + + rt_head.el_tag=tag; + rt_head.el_size=size; + /* Set initial values in decInfo. */ + decInfo.arr_loop_level = 0; + decInfo.arr_loops = arr_loop_buf; + decInfo.rt_ptr = &rt_head; /* point to head rt_block */ + decInfo.rt_end = decInfo.rt_ptr + rt_num; /* done when pointer is here*/ + decInfo.datptr = dptr; /* datptr is the running dest pointer. */ + + /* Initialize the decode context "aCtx" and call "asn1r_decode_asn1". */ + memset (&aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean.*/ + aCtx.usr_info[0] = &decInfo; /* save ptr to decInfo in context. */ + aCtx.asn1r_decode_method = ASN1_TAG_METHOD; /* select tag method */ + aCtx.asn1r_decode_done_fun = asn1r_done_err;/* not legal to be done at this time */ + aCtx.asn1r_err_fun = data_dec_err; /* parse error => call to data_dec_err */ + + assign_tags_new (&aCtx); /* set up tags allowed by 1st rt_block */ + asn1r_decode_asn1 (&aCtx,asn1ptr,asn1len);/* decode entire ASN.1 'Data' entity */ + + if (aCtx.asn1r_pdu_dec_err == NO_DECODE_ERR)/* check for sucess or return error */ + ret = SD_SUCCESS; + else + { + /* MLOG_NERR0 ("ASN.1 to Local data conversion error. ASN.1 data to convert:"); + if (mms_debug_sel & MMS_LOG_NERR) + { use ALWAYSH but only if NERR enabled + MLOG_ALWAYSH (asn1len, asn1ptr); + }*/ + /* Conversion failed, try to log the type used for the conversion. + _log_data_type (rt_head, rt_num); ydf add */ + + ret = MVE_DATA_CONVERT; + } + + return (ret); +} + + +/***************************************************************** +Function name: +Author: YDF +Version: V1.00 +Date: 2008-5-14 +Description: 改进例程中的assign_tags函数 +Input Parameter: NULL +Return Parameter: NULL +Modify History: + + ydf 2008-05-014 首次版本创建 +*******************************************************************/ +static ST_VOID assign_tags_new (ASN1_DEC_CTXT *aCtx) + { + DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + if (decInfo->rt_ptr < decInfo->rt_end) /* if elements to look at */ + { +/* printk("decInfo->rt_ptr->el_tag = %x ", decInfo->rt_ptr->el_tag);*/ + switch (decInfo->rt_ptr->el_tag) + { + case RT_ARR_START : + ASN1R_TAG_ADD (aCtx,CTX|CONSTR,1,arr_start); /* expecting an array cstr */ + break; + + case RT_STR_START : + ASN1R_TAG_ADD (aCtx,CTX|CONSTR,2,str_start); /* expecting an struct cstr */ + break; + + case RT_BOOL : + ASN1R_TAG_ADD (aCtx,CTX,3,get_bool_prim); + break; + + case RT_BIT_STRING : + ASN1R_TAG_ADD (aCtx,CTX,4,get_bitstr_prim); + ASN1R_TAG_ADD (aCtx,CTX|CONSTR,4,get_bstr_cstr); + break; + + case RT_INTEGER : + ASN1R_TAG_ADD (aCtx,CTX,5,get_int_prim); + break; + + case RT_UNSIGNED : + ASN1R_TAG_ADD (aCtx,CTX,6,get_uint_prim); + break; + +#ifdef FLOAT_DATA_SUPPORT + case RT_FLOATING_POINT : + ASN1R_TAG_ADD (aCtx,CTX,7,get_float_prim); + break; +#endif + + case RT_OCTET_STRING : + ASN1R_TAG_ADD (aCtx,CTX,9,get_octstr_prim); + ASN1R_TAG_ADD (aCtx,CTX|CONSTR,9,get_ostr_cstr); + break; + + case RT_VISIBLE_STRING : + ASN1R_TAG_ADD (aCtx,CTX,10,get_vstr_prim); + break; + +#ifdef TIME_DATA_SUPPORT + case RT_GENERAL_TIME : + ASN1R_TAG_ADD (aCtx,CTX,11,get_gtime_prim); + break; +#endif + +#ifdef BTOD_DATA_SUPPORT + case RT_BINARY_TIME : + ASN1R_TAG_ADD (aCtx,CTX,12,get_btime_prim); + break; +#endif + + case RT_BCD : + ASN1R_TAG_ADD (aCtx,CTX,13,get_bcd_prim); + break; + + case RT_UTC_TIME : + ASN1R_TAG_ADD (aCtx,CTX,17,get_utc_time_prim); + break; + + case RT_UTF8_STRING : + ASN1R_TAG_ADD (aCtx,CTX,RT_UTF8_STRING,get_utf8_prim); + break; + + case RT_ARR_END : /* array done */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = arr_done_fun; /* the arr cstr must be done*/ + break; + + case RT_STR_END : /* structure done */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = str_done_fun; /* the str cstr must be done*/ + break; + + default : /* should not be any other tag */ + /* MLOG_NERR0 ("Bad tag in runtime type"); + asn1r_set_dec_err (aCtx,INTERNAL);*/ + return; + break; + } + } + else /* no more elements to do */ + { + aCtx->asn1r_decode_done = SD_TRUE; /* terminate decode */ + aCtx->asn1r_decode_done_fun = data_asn1_decode_done; /* ok to be done now */ + } + } + +/************************************************************************/ +/* arr_start */ +/* This is the function called when an array cstr is starting */ +/************************************************************************/ + +static ST_VOID arr_start (ASN1_DEC_CTXT *aCtx) + { +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + MLOG_CDEC0 ("arr_start"); + +/* initialize the loop counter for the array */ + + ++decInfo->arr_loop_level; + decInfo->arr_loops[decInfo->arr_loop_level] = decInfo->rt_ptr->u.arr.num_elmnts; + + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); /* setup to get next element */ + } + + +/************************************************************************/ +/* arr_done_fun */ +/* This is the cstr done function called when an array cstr is done */ +/************************************************************************/ + +static ST_VOID arr_done_fun (ASN1_DEC_CTXT *aCtx) + { +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + MLOG_CDEC0 ("arr_done_fun"); + + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); /* setup to get next element */ + } + + +/************************************************************************/ +/* str_start */ +/* This is the function called when an struct cstr is starting */ +/************************************************************************/ + +static ST_VOID str_start (ASN1_DEC_CTXT *aCtx) + { +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + MLOG_CDEC0 ("str_start"); + + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); /* setup to get next element */ + } + +/************************************************************************/ +/* str_done_fun */ +/* This is the cstr done function called when an struct cstr is done */ +/************************************************************************/ + +static ST_VOID str_done_fun (ASN1_DEC_CTXT *aCtx) + { +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + MLOG_CDEC0 ("str_done_fun"); + + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); /* setup to get next element */ + } + + +/************************************************************************/ +/* get_bstr_cstr */ +/* State function to extract a boolean value from an asn1 data element. */ +/************************************************************************/ + +static ST_VOID get_bstr_cstr (ASN1_DEC_CTXT *aCtx) + { +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + MLOG_CDEC0 ("get_bstr_cstr"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = bs_cstr_done; + + /* Pass different data pointer for fixed len or variable len bitstring.*/ + if (decInfo->rt_ptr->u.p.el_len >=0) /* fixed length */ + asn1r_get_bitstr_cstr (aCtx,abs (decInfo->rt_ptr->u.p.el_len), (ST_UCHAR *) decInfo->datptr); + else /* variable length */ + asn1r_get_bitstr_cstr (aCtx,abs (decInfo->rt_ptr->u.p.el_len), (ST_UCHAR *) decInfo->datptr + sizeof (ST_INT16)); + } + +/************************************************************************/ +/* bs_cstr_done */ +/* This function is called when an bit string constructor is */ +/* completed OK. Need to reset the decode state machine. */ +/************************************************************************/ + +static ST_VOID bs_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT abs_len; +ST_INT abs_count; +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + + abs_count = abs (decInfo->rt_ptr->u.p.el_len); + abs_len = (abs_count+7) / 8; + +/* determine whether octect string is fixed or variable length */ + + if (decInfo->rt_ptr->u.p.el_len >=0) /* fixed length */ + { + if (aCtx->asn1r_bitstr_truncated || aCtx->asn1r_bitcount != abs_count) + { + MLOG_NERR0 ("Fixed length bit string mismatch"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + return; + } + } + else /* variable length bit string */ + { + /* Set length. */ + *((ST_INT16 *)decInfo->datptr) = (ST_INT16) aCtx->asn1r_bitcount; + } + + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); /* Assign tags for next data elt*/ + } + + +/************************************************************************/ +/* get_ostr_cstr */ +/* State function to extract an octet string from an asn1 data element. */ +/************************************************************************/ + +static ST_VOID get_ostr_cstr (ASN1_DEC_CTXT *aCtx) + { +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + MLOG_CDEC0 ("get_ostr_cstr"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = os_cstr_done; + + /* Pass different data pointer for fixed len or variable len octetstring.*/ + if (decInfo->rt_ptr->u.p.el_len >=0) /* fixed length */ + asn1r_get_octstr_cstr (aCtx,abs (decInfo->rt_ptr->u.p.el_len), (ST_UCHAR *) decInfo->datptr); + else /* variable length */ + asn1r_get_octstr_cstr (aCtx,abs (decInfo->rt_ptr->u.p.el_len), (ST_UCHAR *) decInfo->datptr + sizeof (ST_INT16)); + } + +/************************************************************************/ +/* os_cstr_done */ +/* This function is called when an octet string constructor is */ +/* completed OK. Need to reset the decode state machine. */ +/************************************************************************/ + +static ST_VOID os_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT abs_len; +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + + abs_len = abs (decInfo->rt_ptr->u.p.el_len); + +/* determine whether octect string is fixed or variable length */ + + if (decInfo->rt_ptr->u.p.el_len >=0) /* fixed length */ + { + if (aCtx->asn1r_octetcount != abs_len) + { + MLOG_NERR0 ("Fixed length octet string mismatch"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + return; + } + } + else /* variable length octet string */ + { + /* Set length. */ + *((ST_INT16 *)decInfo->datptr) = (ST_INT16) aCtx->asn1r_octetcount; + } + + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); /* Assign tags for next data elt*/ + } + + +/************************************************************************/ +/* get_bool_prim */ +/* State function to extract a boolean prim from an asn1 data element. */ +/************************************************************************/ + +static ST_VOID get_bool_prim (ASN1_DEC_CTXT *aCtx) + { +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + MLOG_CDEC0 ("get_bool_prim"); + + if (asn1r_get_bool (aCtx,(ST_UCHAR *)decInfo->datptr)) /* Get the boolean length */ + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); /* checked by get function */ + + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); /* continue the parse */ + } + +/************************************************************************/ +/* get_bitstr_prim */ +/* State function to extract an bitstring prim from an asn1 data element*/ +/************************************************************************/ + +static ST_VOID get_bitstr_prim (ASN1_DEC_CTXT *aCtx) + { +ST_INT abs_len; +ST_INT abs_count; +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + + MLOG_CDEC0 ("get_bitstr_prim"); + + abs_count = abs (decInfo->rt_ptr->u.p.el_len); + abs_len = CALC_BIT_LEN (abs_count); + +/* determine whether bitstring is fixed or variable length */ + if (decInfo->rt_ptr->u.p.el_len >= 0) + { + if (asn1r_get_bitstr (aCtx,(ST_UCHAR *)decInfo->datptr, abs_count)) + { + MLOG_CDEC0 ("Bitstring decode failed"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + } + else if (aCtx->asn1r_bitstr_truncated || aCtx->asn1r_bitcount != abs_count) + { + /* For 'fixed length' bitstr, length must match expected length. */ + /* If bitstr truncated, this implies length DID NOT match. */ + MLOG_CDEC0 ("Bitstring length incorrect"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + } + } + else /* variable length octet string */ + { + if (asn1r_get_bitstr (aCtx,(ST_UCHAR *)decInfo->datptr + sizeof (ST_INT16), abs_count)) + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + else + { + *((ST_INT16 *)decInfo->datptr) = (ST_INT16) aCtx->asn1r_bitcount; + } + } + + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* get_int_prim */ +/* State function to extract an integer prim from an asn1 data element. */ +/************************************************************************/ + +static ST_VOID get_int_prim (ASN1_DEC_CTXT *aCtx) + { +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + MLOG_CDEC0 ("get_int_prim"); + + switch (decInfo->rt_ptr -> u.p.el_len) /* determine length */ + { + case 1 : /* one byte int */ + if (asn1r_get_i8 (aCtx,(ST_INT8 *)decInfo->datptr)) /* write a single byte */ + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + break; + + case 2 : /* two byte int */ + if (asn1r_get_i16 (aCtx,(ST_INT16 *)decInfo->datptr)) /* read 16 bit integer */ + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + break; + + case 4 : /* four byte integer */ + if (asn1r_get_i32 (aCtx,(ST_INT32 *)decInfo->datptr))/* read 4 bytes*/ + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + break; + +#ifdef INT64_SUPPORT + case 8 : /* eight byte integer */ + if (asn1r_get_i64 (aCtx,(ST_INT64 *)decInfo->datptr))/* read 8 bytes*/ + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + break; +#endif + + default : + MLOG_NERR0 ("Invalid integer size in RT"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); /* no other lengths are valid*/ + return; + } + + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* get_uint_prim */ +/* State function to extract an unsigned integer prim from an asn1 data */ +/* element. */ +/************************************************************************/ + +static ST_VOID get_uint_prim (ASN1_DEC_CTXT *aCtx) + { +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + MLOG_CDEC0 ("get_uint_prim"); + + switch (decInfo->rt_ptr -> u.p.el_len) /* determine length */ + { + case 1 : /* one byte int */ + if (asn1r_get_u8 (aCtx,(ST_UCHAR *)decInfo->datptr)) /* write a single byte */ + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + break; + + case 2 : /* two byte int */ + if (asn1r_get_u16 (aCtx,(ST_UINT16 *)decInfo->datptr)) /* read 16 bit integer */ + { + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + } + break; + + case 4 : /* four byte integer */ + if (asn1r_get_u32 (aCtx,(ST_UINT32 *)decInfo->datptr))/* read 4 bytes*/ + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + break; + +#ifdef INT64_SUPPORT + case 8 : /* eight byte integer */ + if (asn1r_get_u64 (aCtx,(ST_UINT64 *)decInfo->datptr))/* read 8 bytes*/ + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + break; +#endif + + default : + MLOG_NERR0 ("Invalid integer size in RT"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); /* no other lengths are valid*/ + return; + } + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* get_float_prim */ +/* State function to extract a floating point primitive from an asn1 */ +/* data element. */ +/************************************************************************/ + +#ifdef FLOAT_DATA_SUPPORT + +static ST_VOID get_float_prim (ASN1_DEC_CTXT *aCtx) + { +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + MLOG_CDEC0 ("get_float_prim"); + + if (decInfo->rt_ptr -> u.p.el_len == 8) + { + if (asn1r_get_double (aCtx,(ST_DOUBLE *)decInfo->datptr)) + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + } + else if (decInfo->rt_ptr -> u.p.el_len == 4) + { + if (asn1r_get_float (aCtx,(ST_FLOAT *)decInfo->datptr)) + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + } + else + { + MLOG_NERR0 ("Bad float size in RT"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + return; + } + + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); + } + +#endif + +/************************************************************************/ +/* get_octstr_prim */ +/* State function to extract an octet string primitive from an asn1 */ +/* data element. */ +/************************************************************************/ + +static ST_VOID get_octstr_prim (ASN1_DEC_CTXT *aCtx) + { +ST_INT abs_len; +ST_INT var_len; /* variable length octetstring decoded length */ +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + + MLOG_CDEC0 ("get_octstr_prim"); + + abs_len = abs (decInfo->rt_ptr->u.p.el_len); + + if (decInfo->rt_ptr->u.p.el_len >= 0) /* fixed length */ + { + if (asn1r_get_octstr_fixlen (aCtx,(ST_UCHAR *) decInfo->datptr, abs_len)) + { + MLOG_NERR0 ("Fixed length octet string decode error"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + return; + } + } + else /* variable length */ + { + if (asn1r_get_octstr_varlen (aCtx,(ST_UCHAR *) decInfo->datptr + sizeof (ST_INT16), abs_len, &var_len)) + { + MLOG_NERR0 ("Variable length octet string decode error"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + return; + } + else + { + *((ST_INT16 *)decInfo->datptr) = (ST_INT16) var_len; + } + } + + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* get_vstr_prim */ +/* State function to extract a visible string primitive from an asn1 */ +/* data element. */ +/************************************************************************/ + +static ST_VOID get_vstr_prim (ASN1_DEC_CTXT *aCtx) + { +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + MLOG_CDEC0 ("get_vstr_prim"); + +/* When the u.p.el_len is positive the v-string is of fixed length */ +/* meaning that the aCtx->asn1r_elmnt_len has to be equal. It is ok for the */ +/* u.p.el_len to be negative. When this is encountered it means that */ +/* the v_string is of variable length, the aCtx->asn1r_elmnt_len has to be <= */ +/* u.p.el_len to be valid. */ + + if (((decInfo->rt_ptr -> u.p.el_len > 0) && + (aCtx->asn1r_elmnt_len != decInfo->rt_ptr->u.p.el_len)) || + (aCtx->asn1r_elmnt_len > abs (decInfo->rt_ptr -> u.p.el_len)) || + (asn1r_get_vstr (aCtx,decInfo->datptr))) + { + MLOG_NERR0 ("Vstring size or content problem"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + return; + } + /* v-strings are null term'd */ + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* get_utf8_prim */ +/* State function to extract a Unicode UTF8string primitive from an */ +/* ASN.1 data element. */ +/************************************************************************/ + +static ST_VOID get_utf8_prim (ASN1_DEC_CTXT *aCtx) + { +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + MLOG_CDEC0 ("get_utf8_prim"); + +/* If "el_len" is positive, the string is "fixed length" and this is the + * number of characters. + * If "el_len" is negative, the string is "variable length" and + * "abs(el_len)" is the "maximum" number of characters. + * Pass "el_len" to the ASN.1 function and it will take care of all len chks. + */ + + if (asn1r_get_utf8 (aCtx,decInfo->datptr,decInfo->rt_ptr->u.p.el_len)) + { + MLOG_NERR0 ("Unicode UTF8(V)string decode error"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + return; + } + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* get_gtime_prim */ +/* State function to extract a generalized time primitive from an asn1 */ +/* data element. */ +/************************************************************************/ + +#ifdef TIME_DATA_SUPPORT + +static ST_VOID get_gtime_prim (ASN1_DEC_CTXT *aCtx) + { +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + MLOG_CDEC0 ("get_gtime_prim"); + + if (asn1r_get_time (aCtx,(time_t *)decInfo->datptr)) + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); + } + +#endif + +/************************************************************************/ +/* get_btime_prim */ +/* State function to extract a binary time primitive from an asn1 data */ +/* element. */ +/************************************************************************/ + +#ifdef BTOD_DATA_SUPPORT + +static ST_VOID get_btime_prim (ASN1_DEC_CTXT *aCtx) + { +MMS_BTOD btod_data; +ST_INT32 *i32_ptr; +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + + MLOG_CDEC0 ("get_btime_prim"); + + if (asn1r_get_btod (aCtx,&btod_data)) + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + else if (btod_data.form != decInfo->rt_ptr->u.p.el_len) + { + MLOG_NERR0 ("BTOD form mismatch"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + return; + } + else + { + i32_ptr = (ST_INT32 *) decInfo->datptr; + *i32_ptr = btod_data.ms; + if (btod_data.form == MMS_BTOD6) + { + ++i32_ptr; + *i32_ptr = btod_data.day; + } + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); + } + } + +#endif + +/************************************************************************/ +/* get_bcd_prim */ +/* State function to extract a binary coded decimal primitive from an */ +/* asn1 data element. */ +/************************************************************************/ + +static ST_VOID get_bcd_prim (ASN1_DEC_CTXT *aCtx) + { +ST_INT32 range; +ST_INT8 btemp; +ST_INT16 stemp; +ST_INT32 ltemp; +ST_INT i; +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + + range = 0; + + MLOG_CDEC0 ("get_bcd_prim"); + +/* we have to calculate the legal range of digits this bcd type will */ +/* fit in. */ + + for (i = 0; i < decInfo->rt_ptr->u.p.el_len; i++) + range = (range * 10) + 9; + + if (decInfo->rt_ptr -> u.p.el_len <= 2) /* determine length */ + { + if (asn1r_get_i8 (aCtx,&btemp)) /* get a two nibble value */ + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + if ((btemp > (ST_CHAR)range) || /* is it in range */ + (btemp < 0)) + { + MLOG_NERR0 ("BCD value out of range"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + return; + } + else + memcpy (decInfo->datptr, &btemp, sizeof (ST_CHAR)); /* copy good data*/ + } + else if (decInfo->rt_ptr -> u.p.el_len <= 4) + { + if (asn1r_get_i16 (aCtx,&stemp)) /* read 4 nibble BCD */ + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + if ((stemp > (ST_INT16) range) || (stemp < 0)) + { + MLOG_NERR0 ("BCD value out of range"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + return; + } + else + memcpy (decInfo->datptr, &stemp, sizeof (ST_INT16)); /* copy good data */ + } + else if (decInfo->rt_ptr -> u.p.el_len <= 8) + { + if (asn1r_get_i32 (aCtx,<emp)) /* read 4 bytes */ + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + if ((ltemp > range) || (ltemp < 0)) + { + MLOG_NERR0 ("BCD value out of range"); + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + return; + } + else + memcpy (decInfo->datptr, <emp, sizeof (ST_INT32)); /* copy good data*/ + } + else + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); /* no other lengths are valid*/ + + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* get_utc_time_prim */ +/* State function to extract a UTC time primitive from an asn1 data */ +/* element. */ +/************************************************************************/ + +static ST_VOID get_utc_time_prim (ASN1_DEC_CTXT *aCtx) + { +MMS_UTC_TIME utc_time; +DEC_INFO *decInfo = (DEC_INFO *) aCtx->usr_info[0]; /* get saved ptr*/ + + MLOG_CDEC0 ("get_utc_time_prim"); + + if (asn1r_get_utc_time (aCtx, &utc_time)) + asn1r_set_dec_err (aCtx,MVE_DATA_CONVERT); + else + /* just copy the whole struct */ + memcpy (decInfo->datptr, (ST_CHAR *)&utc_time, sizeof (MMS_UTC_TIME)); + + decInfo->datptr += decInfo->rt_ptr->el_size; /* Adjust data pointer */ + decInfo->rt_ptr++; /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* data_asn1_decode_done */ +/* Function called when the end of the ASN.1 'Data' entity is */ +/* detected. Checks this against the runtime type table. */ +/************************************************************************/ + +static ST_VOID data_asn1_decode_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("data_asn1_decode_done"); + } + +/************************************************************************/ +/* data_dec_err */ +/* Function called when an invalid tag is encountered in the ASN.1 */ +/* 'Data' entity. Stops the parse with a fatal error. */ +/************************************************************************/ + +static ST_VOID data_dec_err (ASN1_DEC_CTXT *aCtx, ST_RET err) + { + MLOG_CDEC1 ("data_dec_err %d", err); + /* NOTE: error already set. DO NOT call asn1r_set_dec_err. */ + /* DO NOT set (aCtx->asn1r_pdu_dec_err). */ + } + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* Block data to ASN.1 data section */ +/* Assumes that the ASN.1 tools have been initialized. */ +/************************************************************************/ +/************************************************************************/ +/* ms_locl_to_asn1 */ +/* Construct a 'data' element (ASN.1) from blocked data. */ +/* The user passes a pointer to the blocked data and the type def, */ +/* and the number of elements in the type definition table. */ +/* */ +/* Assume the build tools have been initialized, use ASN.1 build tools */ +/************************************************************************/ + +#ifndef MMS_LITE + +ST_RET ms_locl_to_asn1 (ASN1_ENC_CTXT *aCtx, NAMED_TYPE *tptr, ST_CHAR *dptr) + { + if (!tptr->rt_num) /* if len == 0 */ + { + MLOG_NERR0 ("Named type has no runtime elements"); + return (MVE_RT_TYPE); /* 0 length typedef is error */ + } + + return (ms_local_to_asn1 (aCtx, tptr->rt_head,tptr->rt_num, dptr)); + } + +#endif + +/************************************************************************/ +/* ms_local_to_asn1 */ +/* This function is most convenient when data is encoded in the */ +/* middle of a larger encode. */ +/* If data is encoded by itself, ms_local_to_asn1_2 is more */ +/* efficient and much easier to use. */ +/************************************************************************/ +//extern int flag_jou_asn1_endian;//lnk编译删除,原å‰ç½®ç¨‹åºæœªä½¿ç”¨ + +//void jou_endian_2(char *pval);//lnk编译删除,原å‰ç½®ç¨‹åºæœªä½¿ç”¨ +//void jou_endian_4(char *pval);//lnk编译删除,原å‰ç½®ç¨‹åºæœªä½¿ç”¨ + +ST_RET ms_local_to_asn1 (ASN1_ENC_CTXT *aCtx, + SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, + ST_CHAR *dptr) + { +ST_INT done; +ST_RET ret_val; +ST_INT arr_loop_buf[ASN1_MAX_LEVEL]; +ST_CHAR *datptr; +SD_CONST RUNTIME_TYPE *rt_ptr; +SD_CONST RUNTIME_TYPE *rt_end; +ST_INT arr_loop_level; +ST_INT *arr_loops; + +/* Make sure that "asn1r_strt_asn1_bld" was called for this context. */ + if (aCtx->asn1r_magic != ASN1_ENC_MAGIC_NUMBER) + { + MLOG_ERR0 ("ASN1_ENC_CTXT not initialized. MUST call 'asn1r_strt_asn1_bld' first."); + return (MVE_ASN1_ENCODE_ERR); + } + + arr_loop_level = 0; + arr_loops = arr_loop_buf; + + rt_ptr = rt_head + rt_num -1; /* point to bottom rt element */ + rt_end = rt_head; /* head is end */ + +/* Set working data pointer to point below last data element */ + datptr = dptr + rt_head->offset_to_last; + + done = SD_FALSE; + ret_val = SD_SUCCESS; + while (!done && !ret_val && !aCtx->asn1r_encode_overrun) /* while not done*/ + { + if (ms_is_rt_prim (rt_ptr)) /* is this a primitive element? */ + { + datptr -= rt_ptr->el_size; /* Point to data for this element */ + + + //if(flag_jou_asn1_endian) + if(0)//lnk编译修改,原å‰ç½®ç¨‹åºæœªä½¿ç”¨ + { + if(rt_ptr->el_tag==RT_BIT_STRING) + { + jou_endian_2((char *)&datptr[0]); + jou_endian_2((char *)&datptr[2]); + } + if(rt_ptr->el_tag==RT_FLOATING_POINT) + { + jou_endian_4((char *)datptr); + } + if(rt_ptr->el_tag==RT_INTEGER) + { + if(rt_ptr -> u.p.el_len==2) jou_endian_2((char *)&datptr[0]); + if(rt_ptr -> u.p.el_len==4) jou_endian_4((char *)&datptr[0]); + } + if(rt_ptr->el_tag==RT_UTC_TIME) + { + jou_endian_4((char *)&datptr[0]); + jou_endian_4((char *)&datptr[4]); + } + } + ret_val = wr_prim_dat (aCtx, datptr, rt_ptr); /* Write the primitive data*/ + } + else /* not a primitive element */ + { + switch (rt_ptr->el_tag) + { + case RT_ARR_END : /* array end, start constructor */ + /* initialize loop count */ + ++arr_loop_level; + arr_loops[arr_loop_level] = rt_ptr->u.arr.num_elmnts; + asn1r_strt_constr (aCtx); + datptr -= rt_ptr->el_size; /* Point to data element above */ + break; + + case RT_ARR_START : /* array start */ + /* if more loops, move ptr back */ + if (--arr_loops[arr_loop_level] > 0) /* if need to do next ar elmnt */ + { + rt_ptr += rt_ptr->u.arr.num_rt_blks; + continue; /* Back to loop bottom */ + } + else + { + --arr_loop_level; + asn1r_fin_constr (aCtx,1,CTX,DEF); /* array done, fin the cstr*/ + datptr -= rt_ptr->el_size; + } + break; + + case RT_STR_END : /* array end, start constructor */ + asn1r_strt_constr (aCtx); + datptr -= rt_ptr->el_size; + break; + + case RT_STR_START : + asn1r_fin_constr (aCtx,2,CTX,DEF); /* struct done, fin the cstr*/ + datptr -= rt_ptr->el_size; + break; + + default : /* unknown typedef tag */ + MLOG_NERR0 ("Unknown RT type tag"); + ret_val = MVE_RT_TYPE; + } + } /* end if not primitive element */ + +/* All tags (EXCEPT array start when loopback) come here. */ + +/* Move the rt_ptr to the next element, check for done */ + if (rt_ptr == rt_end) /* If this was last element */ + done = SD_TRUE; + else + --rt_ptr; /* move pointer to next */ + } + + + if (ret_val == SD_SUCCESS) + { + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + ret_val = ME_ASN1_ENCODE_OVERRUN; + } + + /* If conversion failed, log the type used for the conversion. */ + if (ret_val) + { + MLOG_NERR1 ("Local to ASN.1 data conversion error = 0x%X", ret_val); + _log_data_type (rt_head, rt_num); + } + + return (ret_val); + } + +/************************************************************************/ +/* wr_prim_dat */ +/* Write a primitive data element from the user data to the message */ +/* under construction. */ +/************************************************************************/ + +static ST_RET wr_prim_dat (ASN1_ENC_CTXT *aCtx, ST_CHAR *datptr, SD_CONST RUNTIME_TYPE *rt_ptr) + { +ST_RET ret_val; +ST_INT16 len; +MMS_BTOD btod_data; +ST_INT32 *i32_ptr; + + ret_val = SD_SUCCESS; + +/* use the runtime type def table element and type to select storage */ + + switch (rt_ptr->el_tag) + { + case RT_BOOL : /* boolean */ + asn1r_wr_bool (aCtx,*((ST_UCHAR *)datptr)); /* write a single byte*/ + break; + + case RT_BIT_STRING : +#if defined(_S_TEST_PROBES) + if (_sTestProbeEnabledS("MmsConstructedBitstrings")) + { + ret_val = _wr_constructed_bitstring (aCtx, datptr, rt_ptr); + goto _CONSTRUCTED_BSOS_WRITTEN; + } +#endif + + if (rt_ptr->u.p.el_len >= 0) + asn1r_wr_bitstr (aCtx,(ST_UCHAR *)datptr,rt_ptr->u.p.el_len); /* bits */ + else + { /* variable length bitstring */ + len = *((ST_INT16 *)datptr); + if (len < 0 || len > abs(rt_ptr->u.p.el_len)) + { + MLOG_NERR1 ("Invalid variable length bitstring length: %d", + (ST_INT) len); + ret_val = MVE_RT_TYPE; + } + else + asn1r_wr_bitstr (aCtx,(ST_UCHAR *) (datptr + sizeof(ST_INT16)), len); + } + break; + + case RT_INTEGER : + switch (rt_ptr -> u.p.el_len) /* determine length */ + { + case 1 : /* one byte int */ + asn1r_wr_i8 (aCtx,*datptr); /* write a single byte */ + break; + + case 2 : /* two byte int */ + asn1r_wr_i16 (aCtx,*((ST_INT16 *)datptr)); + break; + + case 4 : /* four byte integer */ + asn1r_wr_i32 (aCtx,*((ST_INT32 *) datptr)); + break; + +#ifdef INT64_SUPPORT + case 8 : /* eight byte integer */ + asn1r_wr_i64 (aCtx,*((ST_INT64 *) datptr)); + break; +#endif + + default : + MLOG_NERR0 ("Invalid integer length"); + ret_val = MVE_RT_TYPE; + } + break; + + case RT_UNSIGNED : + switch (rt_ptr -> u.p.el_len) /* determine length */ + { + case 1 : /* one byte unsigned int */ + asn1r_wr_u8 (aCtx,*((ST_UCHAR *)datptr)); + break; + + case 2 : /* two byte unsigned int */ + asn1r_wr_u16 (aCtx,*((ST_UINT16 *) datptr)); + break; + + case 4 : /* four byte unsigned integer */ + asn1r_wr_u32 (aCtx,*((ST_UINT32 *) datptr)); + break; + +#ifdef INT64_SUPPORT + case 8 : /* eight byte unsigned integer */ + asn1r_wr_u64 (aCtx,*((ST_UINT64 *) datptr)); + break; +#endif + + default : + MLOG_NERR0 ("Invalid integer length"); + ret_val = MVE_RT_TYPE; + } + break; + +#ifdef FLOAT_DATA_SUPPORT + case RT_FLOATING_POINT : + if (rt_ptr -> u.p.el_len != sizeof (ST_FLOAT)) + asn1r_wr_double (aCtx,*((ST_DOUBLE *)datptr)); + else + asn1r_wr_float (aCtx,*((ST_FLOAT *)datptr)); + break; +#endif + + case RT_OCTET_STRING : +#if defined(_S_TEST_PROBES) + if (_sTestProbeEnabledS("MmsConstructedOctetstrings")) + { + ret_val = _wr_constructed_octetstring (aCtx, datptr, rt_ptr); + goto _CONSTRUCTED_BSOS_WRITTEN; + } +#endif + + if (rt_ptr->u.p.el_len >= 0) + asn1r_wr_octstr (aCtx,(ST_UCHAR *)datptr, rt_ptr->u.p.el_len); + else + { /* variable length octetstring */ + len = *((ST_INT16 *)datptr); + if (len < 0 || len > abs(rt_ptr->u.p.el_len)) + { + MLOG_NERR1 ("Invalid variable length octetstring length: %d", + (ST_INT) len); + ret_val = MVE_RT_TYPE; + } + else + asn1r_wr_octstr (aCtx,(ST_UCHAR *) (datptr + sizeof(ST_INT16)), len); + } + break; + + case RT_VISIBLE_STRING : + if (((rt_ptr -> u.p.el_len > 0) && + (strlen (datptr) != (ST_UINT) rt_ptr->u.p.el_len)) || + (strlen (datptr) > (ST_UINT) abs (rt_ptr->u.p.el_len))) + { + MLOG_ENC0 ("Data is illegal for VISIBLE_STRING type."); + ret_val = MVE_ASN1_ENCODE_ERR; /* say data is illegal for type */ + } + else + asn1r_wr_vstr (aCtx,datptr); + break; + +#ifdef TIME_DATA_SUPPORT + case RT_GENERAL_TIME : + asn1r_wr_time (aCtx,*((time_t *)datptr)); + break; +#endif + +#ifdef BTOD_DATA_SUPPORT + case RT_BINARY_TIME : + i32_ptr = (ST_INT32 *) datptr; + btod_data.ms = *i32_ptr; + if (rt_ptr->u.p.el_len == 6) + { + btod_data.form = MMS_BTOD6; + ++i32_ptr; + btod_data.day = *i32_ptr; + } + else + btod_data.form = MMS_BTOD4; + + asn1r_wr_btod (aCtx,&btod_data); + break; +#endif + +/* The u.p.el_len for BCD indicates the number of digits in the value. */ +/* Digits are represented as [0..9] requiring one nibble of storage */ +/* each. Because all BCD values are sent over the wire as integers and */ +/* the C programming language has no native BCD type, BCD values are */ +/* handled by MMS-EASE as integers. */ + + case RT_BCD: + if (rt_ptr->u.p.el_len <= 2) + asn1r_wr_i8 (aCtx,*datptr); /* write a single byte */ + else if (rt_ptr->u.p.el_len <= 4) + asn1r_wr_i16 (aCtx,*((ST_INT16 *)datptr)); + else + asn1r_wr_i32 (aCtx,*((ST_INT32 *) datptr)); + break; + + case RT_UTC_TIME : + { + MMS_UTC_TIME *utc_time = (MMS_UTC_TIME *) datptr; + asn1r_wr_utc_time (aCtx,utc_time); + } + break; + + case RT_UTF8_STRING : + /* asn1r_wr_utf8 returns SD_SUCCESS or error code, so chk return */ + if (asn1r_wr_utf8 (aCtx,datptr,rt_ptr->u.p.el_len)) + { + MLOG_NERR1 ("Data or len is illegal for UTF8(V)string%d.", + abs(rt_ptr->u.p.el_len)); + ret_val = MVE_ASN1_ENCODE_ERR; /* say data is illegal for type */ + } + break; + + default : + MLOG_NERR0 ("Bad RT tag"); + ret_val = MVE_RT_TYPE; + } + + asn1r_fin_prim (aCtx,rt_ptr->el_tag,CTX); /* finish the primitive */ + +#if defined(_S_TEST_PROBES) +_CONSTRUCTED_BSOS_WRITTEN: +#endif + + if (ret_val) + { + ST_CHAR tmp_tdl [MAX_IDENT_LEN+1]; + MLOG_ERR0 ("Local data could not be converted to ASN.1"); + if (ms_runtime_to_tdl (rt_ptr, 1, tmp_tdl, MAX_IDENT_LEN) > 0) + MLOG_CERR1 ("Data type TDL=%s", tmp_tdl); + else + MLOG_CERR1 ("Data type tag=%d", rt_ptr->el_tag); + MLOG_CERR0 ("Local Data:"); + MLOG_ERRH (rt_ptr->el_size, datptr); + } + return (ret_val); + } + +/************************************************************************/ +/************************************************************************/ + +#if defined(_S_TEST_PROBES) + +static ST_RET _wr_constructed_bitstring (ASN1_ENC_CTXT *aCtx, ST_CHAR *datptr, + SD_CONST RUNTIME_TYPE *rt_ptr) + { +ST_INT16 len; +ST_INT16 el_len; +ST_INT j; +ST_INT extra_bits; +ST_INT numbytes; +ST_UCHAR *bitstr_data; +static ST_BOOLEAN firstTime = SD_TRUE; + + if (firstTime) + { + SLOGALWAYS0 ("TEST: Using constructed bitstrings"); + firstTime = SD_FALSE; + } + + + el_len = rt_ptr->u.p.el_len; + if (el_len > 8 || (el_len < 0 && *(ST_INT16*)datptr > 8)) + { /* bitstring longer than 8 bits */ + if (el_len < 0) + { + bitstr_data = datptr + 2; /* point after ST_INT16 len */ + len = *(ST_INT16 *)datptr; + } + else + { + bitstr_data = datptr; + len = el_len; + } + extra_bits = len % 8; + numbytes = len / 8; + + asn1r_strt_constr (aCtx); + asn1r_strt_constr (aCtx); /* nested constr. Should be ignored.*/ +#if 0 /* DEBUG: enable this to send 1 garbage bit after last real segment.*/ + /* Should cause truncation for "variable length" bitstr */ + /* (error for "fixed length" bitstr). */ + asn1r_wr_bitstr (aCtx, bitstr_data, 1); /* write 1 bit bitstr*/ + asn1r_fin_prim (aCtx,BITS_CODE,UNI); +#endif + /* encoding backward, so loop backward through bits.*/ + if (extra_bits) + { + asn1r_wr_bitstr (aCtx, bitstr_data+numbytes, extra_bits); + /* NOTE: Tag is UNI class.*/ + asn1r_fin_prim (aCtx,BITS_CODE,UNI); + } + for (j = numbytes-1; j >= 0; j--) + { + asn1r_wr_bitstr (aCtx, bitstr_data+j, 8); /* write 8 bit bitstr*/ + asn1r_fin_prim (aCtx,BITS_CODE,UNI); /* finish the primitive */ + } +#if 0 /* DEBUG: enable this to send 1 garbage bit before first real segment.*/ + /* Should cause decode error. First segment must be multiple of 8 bits*/ + asn1r_wr_bitstr (aCtx, &onebit, 1); /* write 1 bit bitstr*/ + asn1r_fin_prim (aCtx,BITS_CODE,UNI); +#endif + asn1r_fin_constr (aCtx, BITS_CODE, UNI,DEF); /* nested constr. Should be ignored.*/ + asn1r_fin_constr (aCtx, RT_BIT_STRING, CTX,DEF); /* finish the constructor*/ + } + else + { + asn1r_wr_bitstr (aCtx,(ST_UCHAR *)datptr,rt_ptr->u.p.el_len); /* bits */ + asn1r_fin_prim (aCtx, RT_BIT_STRING, CTX); /* finish the primitive */ + } + return (SD_SUCCESS); + } + +/************************************************************************/ + +static ST_RET _wr_constructed_octetstring (ASN1_ENC_CTXT *aCtx, ST_CHAR *datptr, + SD_CONST RUNTIME_TYPE *rt_ptr) + { +ST_INT16 len; +ST_INT j; +static ST_BOOLEAN firstTime = SD_TRUE; + + if (firstTime) + { + SLOGALWAYS0 ("TEST: Using constructed octetstrings"); + firstTime = SD_FALSE; + } + + len = rt_ptr->u.p.el_len; + if (len < 0) + { + len = *(ST_INT16 *)datptr; + datptr += 2; /* point after ST_INT16 len */ + } + + asn1r_strt_constr (aCtx); + asn1r_strt_constr (aCtx); /* nested constr. Should be ignored.*/ + /* encoding backward, so loop backward through bytes.*/ + for (j = len-1; j >= 0; j--) + { + asn1r_wr_octstr (aCtx, &datptr[j], 1); /* write 1 byte*/ + /* NOTE: all prim octstr inside constructed octstr, must be UNI.*/ + asn1r_fin_prim (aCtx,OCT_CODE,UNI); /* finish the primitive */ + } + asn1r_fin_constr (aCtx,OCT_CODE, UNI,DEF); /* nested constr. Should be ignored.*/ + asn1r_fin_constr (aCtx,RT_OCTET_STRING,CTX,DEF); /* finish the constructor*/ + return (SD_SUCCESS); + } + +#endif + +/************************************************************************/ +/* ms_local_to_asn1_easy */ +/* If a data encode is NOT part of a bigger encode, */ +/* this function is more efficient and easier to use. */ +/* NOTE: ms_local_to_asn1_2 is almost the same but its arguments are */ +/* more consistent with other encoding functions. */ +/************************************************************************/ +ST_UCHAR *ms_local_to_asn1_easy (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + ST_CHAR *dptr, + ST_UCHAR *asn1Buf, + ST_INT asn1BufLen, + ST_INT *asn1LenOut) + { +ST_RET ret_val; +ASN1_ENC_CTXT aCtx; +ST_UCHAR *asn1Start = NULL; /* ptr to start of ASN1 encoded data */ + /* init to NULL (i.e. failure) */ + + asn1r_strt_asn1_bld (&aCtx, asn1Buf, asn1BufLen); + + /* encode everything using new context. */ + ret_val = ms_local_to_asn1 (&aCtx, rt_head, rt_num, dptr); + + /* When the ASN.1 encode is complete, 'asn1_field_ptr' points 1 byte */ + /* ahead of the start of the message. The ASN.1 message is built from */ + /* back to front, so the length = (ptr to end) - (ptr to start) */ + if (ret_val == SD_SUCCESS) + { + asn1Start = aCtx.asn1r_field_ptr+1; + *asn1LenOut = (asn1Buf + asn1BufLen) - asn1Start; + } + return (asn1Start); /* ptr to start (or NULL on error) */ + } + +/************************************************************************/ +/* ms_local_to_asn1_2 */ +/* If a data encode is NOT part of a bigger encode, */ +/* this function is easier to use. */ +/************************************************************************/ +ST_RET ms_local_to_asn1_2 (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + ST_CHAR *dptr, /* local data to encode */ + ST_UCHAR *buf_ptr, /* buffer in which to encode */ + ST_INT buf_len, /* buffer length */ + ST_UCHAR **asn1_ptr_out, /* ptr to ptr to encoded data */ + ST_INT *asn1_len_out) /* ptr to encoded length */ + { +ST_RET ret_val; +ASN1_ENC_CTXT aCtx; + + asn1r_strt_asn1_bld (&aCtx, buf_ptr, buf_len); + + /* encode everything using new context. */ + ret_val = ms_local_to_asn1 (&aCtx, rt_head, rt_num, dptr); + + if (ret_val == SD_SUCCESS) + { + /* Set output parameters (ptr & len). */ + *asn1_ptr_out = ASN1_ENC_PTR(&aCtx); + *asn1_len_out = ASN1_ENC_LEN(&aCtx); + } + return (ret_val); + } + +/************************************************************************/ +/* _log_data_type */ +/* Log the data type (as TDL so average user can read it). */ +/************************************************************************/ +static ST_VOID _log_data_type (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num) + { +/*ST_CHAR tdl_buf [500];*/ +ST_CHAR tdl_buf [500]; +ST_INT tdl_len; + + tdl_len = sizeof (tdl_buf); /* init to max allowed tdl len */ + tdl_len = ms_runtime_to_tdl (rt_head, rt_num, tdl_buf, tdl_len); + + if (tdl_len != 0) /* conversion to tdl succeeded */ + { + MLOG_CALWAYS1 ("Local Data Type TDL: %s", tdl_buf); /* should be CERR1?*/ + } + else + { /* conversion failed. Just log what we can. */ + MLOG_CALWAYS2 ("Local Runtime Type Array ptr = " S_FMT_PTR ", Num Entries = %d", + rt_head, rt_num); + } + } + diff --git a/mmslib/mmsl/mmsdatat.c b/mmslib/mmsl/mmsdatat.c new file mode 100644 index 0000000..a2ebf26 --- /dev/null +++ b/mmslib/mmsl/mmsdatat.c @@ -0,0 +1,1231 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997 - 2006, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsdatat.c */ +/* PRODUCT(S) : none */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the functions employed by the virtual */ +/* machine for parsing an ASN.1 data string and creating the */ +/* run-time type specification from it. */ +/* Adapted from mmsdata.c */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/17/08 JRB 19 Del m_use_long_ints flag & assume smallest */ +/* integer is 4 bytes. */ +/* 02/19/07 JRB 18 Add error log message. */ +/* 03/22/06 EJV 17 Changed RT_GENERAL_TIME st_size and el_len to*/ +/* sizeof(time_t) (VS 2005 has 64-bit time_t).*/ +/* 01/30/06 GLB 16 Integrated porting changes for VMS */ +/* 10/27/03 JRB 15 Assume all UTF8strings are variable-length. */ +/* Add code to adjust len for array of UTF8str..*/ +/* 10/16/03 MDE 14 Fixed leak for data conversion error */ +/* 05/08/03 JRB 13 Fix TAG_ADD for "array" of RT_UTF8_STRING. */ +/* 04/02/03 JRB 12 Add UTF8string support (see RT_UTF8_STRING). */ +/* 12/20/01 JRB 11 Converted to use ASN1R (re-entrant ASN1) */ +/* 11/15/01 EJV 10 Added support for new MMS type UtcTime. */ +/* 10/06/00 MDE 09 Now set asn1_decode_method */ +/* 04/20/00 JRB 08 Undo last chg, fix mms_vvar.h instead. Lint. */ +/* 10/13/99 RKR 07 Added SD_CONST to function headers */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 06/03/98 MDE 05 Allow for 0 length variable length items */ +/* 03/12/98 MDE 04 Fixed 'loops' change - whoops! */ +/* 02/10/98 MDE 03 No longer use runtime type 'loops' element */ +/* 08/15/97 MDE 02 BTOD handling changes */ +/* 07/03/97 MDE 01 Fixed problem w/structures */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" + +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "asn1defs.h" +#include "mem_chk.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ + +static ST_VOID assign_tags (ASN1_DEC_CTXT *aCtx); +static int init_new_RT (ASN1_DEC_CTXT *aCtx, ST_UCHAR tag, ST_INT el_len); +#if 0 /* Constructed bitstrings and octetstrings not supported */ +static ST_VOID get_bstr_cstr (ASN1_DEC_CTXT *aCtx); /* for constructed bitstrings */ +static ST_VOID get_ostr_cstr (ASN1_DEC_CTXT *aCtx); /* for constructed octetstrings */ +static ST_VOID bs_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID os_cstr_done (ASN1_DEC_CTXT *aCtx); +#endif +static ST_VOID get_bool_prim (ASN1_DEC_CTXT *aCtx); /* for boolean primitives */ +static ST_VOID get_bitstr_prim (ASN1_DEC_CTXT *aCtx); /* for bitstring primitives */ +static ST_VOID get_int_prim (ASN1_DEC_CTXT *aCtx); /* for integer primitives */ +static ST_VOID get_uint_prim (ASN1_DEC_CTXT *aCtx); /* for unsigned integers */ +static ST_VOID get_float_prim (ASN1_DEC_CTXT *aCtx); /* for float primitives */ +static ST_VOID get_octstr_prim (ASN1_DEC_CTXT *aCtx); /* for octet string primitives */ +static ST_VOID get_vstr_prim (ASN1_DEC_CTXT *aCtx); /* for visible string primitives*/ +static ST_VOID get_gtime_prim (ASN1_DEC_CTXT *aCtx); /* for generalized time */ +static ST_VOID get_btime_prim (ASN1_DEC_CTXT *aCtx); /* for binary time primitives */ +static ST_VOID get_bcd_prim (ASN1_DEC_CTXT *aCtx); /* for binary coded decimal */ +static ST_VOID get_utc_time_prim (ASN1_DEC_CTXT *aCtx); /* for UTC time primitives */ +static ST_VOID get_utf8_prim (ASN1_DEC_CTXT *aCtx); /* for UTF8string primitives */ +static ST_VOID arr_start (ASN1_DEC_CTXT *aCtx); +static ST_VOID str_start (ASN1_DEC_CTXT *aCtx); +static ST_VOID arr_done_fun (ASN1_DEC_CTXT *aCtx); +static ST_VOID str_done_fun (ASN1_DEC_CTXT *aCtx); +static ST_VOID err_clean_fun (ASN1_DEC_CTXT *aCtx, ST_RET err_code); + + +typedef enum { UNDEF, STRUCT, ARRAY } ConstrType; /* Constructor types */ + + +static RUNTIME_TYPE *rt_base; /* Base ptr for runtime array */ +static RUNTIME_TYPE *cur_rt; /* Current runtime element ptr */ +static RUNTIME_TYPE *nxt_un_rt; /* Next unused RT el in buffer */ +static RUNTIME_TYPE *rt_EOB_ptr; /* One past end of RT buffer. */ +static int local_alloc_flag; + /* Block pointer for arrs & structs */ +static RUNTIME_TYPE *rt_blk_start[ASN1_MAX_LEVEL]; +static ConstrType constr_type[ASN1_MAX_LEVEL]; /* Cstr type */ +static ST_INT arr_loop_level; +static ST_INT *arr_loops; + +/* The following defines specify the various error codes that are used */ +/* in ms_asn1_to_locl and its subordinate functions. These are in ad- */ +/* dition to the error codes that can be generated by ASN1DE internally,*/ +/* and both translate into return values that are one greater than the */ +/* error codes themselves. */ + +#define BAD_DATA 100 /* Data not consistent with */ + /* type specification. */ +#define INTERNAL 101 /* Type specif'n bad, not data. */ + +/************************************************************************/ +/************************************************************************/ + +ST_RET ms_asn1_data_to_locl (ST_UCHAR *asn1_data, + ST_INT asn1_data_len, + ST_VOID **data_dest, + ST_INT *data_dest_len, + RUNTIME_TYPE **rt, + ST_INT *t_len) + { +ST_RET rc; +RUNTIME_TYPE *rt_in; + + /* First, build runtime from data string */ + rt_in = *rt; + rc = ms_asn1_data_to_runtime (rt, t_len, asn1_data, asn1_data_len); + if (rc != SD_SUCCESS) + return (rc); + +/* verify that the supplied data buffer is big enough */ + if (*data_dest && *data_dest_len < (*rt)->offset_to_last) + { + if (!rt_in) /* RT table was chk_calloc'd */ + chk_free (*rt); + + return (MVE_DATA_SPACE); + } + + if (!*data_dest) + { + *data_dest_len = (*rt)->offset_to_last; + + /* Variable length items can have a data length of 0 */ + if (*data_dest_len) + { + *data_dest = chk_calloc (1, (*rt)->offset_to_last); + + /* OK, go ahead and do the data conversion */ + rc = ms_asn1_to_local (*rt, *t_len, asn1_data, asn1_data_len, (ST_CHAR *) *data_dest); + if (rc) + { + chk_free (*data_dest); + if (!rt_in) /* RT table was chk_calloc'd */ + chk_free (*rt); + } + } + else + *data_dest = chk_calloc (1, 1); + } + else /* OK, go ahead and do the data conversion */ + { + + rc = ms_asn1_to_local (*rt, *t_len, asn1_data, asn1_data_len, (ST_CHAR *) *data_dest); + if (rc && !rt_in) /* Error and RT table was chk_calloc'd */ + chk_free (*rt); + } + return (rc); + } + + +/************************************************************************/ +/* ms_asn1_data_to_runtime */ +/* Creates a run-time data defn table from the input ASN.1 data string. */ +/* Input parameters: */ +/* RUNTIME_TYPE **tptr Pointer^2 to runtime buffer. */ +/* ST_INT *t_len Length of runtime buffer, in runtime elements. */ +/* ST_UCHAR *asn1ptr Pointer to input ASN.1 string */ +/* ST_INT asn1len Length of ASN.1 string, in bytes. */ +/* Returns: SD_SUCCESS, SD_FAILURE or INTERNAL. If SD_FAILURE, aCtx->asn1r_pdu_dec_err */ +/* has the specific error code. */ +/* Output globals: aCtx->asn1r_decode_done_fun */ +/* Static variables set: rt_base, rt_EOB_ptr, cur_rt, nxt_un_rt */ +/************************************************************************/ + + +ST_RET ms_asn1_data_to_runtime (RUNTIME_TYPE **tptr, + ST_INT *t_len, + ST_UCHAR *asn1ptr, + ST_INT asn1_len) + { +ST_RET ret; +ST_INT arr_loop_buf[ASN1_MAX_LEVEL]; +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean. */ + + local_alloc_flag = SD_FALSE; + if (tptr == NULL) /* What? Parameter error, fix that. */ + { + return (MVE_RT_TYPE); + } + + S_LOCK_COMMON_RESOURCES (); + arr_loop_level = 0; + arr_loops = arr_loop_buf; + if (*tptr != NULL) + { /* Type buffer already allocated, use it. */ + rt_base = *tptr; /* Init pointer to runtime buffer. */ + if (*t_len <= 0) /* Check size. */ + { + S_UNLOCK_COMMON_RESOURCES (); + return (MVE_RT_TYPE); /* Parameter error. */ + } + else + rt_EOB_ptr = rt_base + *t_len; /* Init end-of-buffer pointer */ + } + else /* Allocate a default-size buffer here. */ + { + rt_base = (RUNTIME_TYPE *) chk_calloc (m_rt_type_limit, sizeof (RUNTIME_TYPE)); + rt_EOB_ptr = rt_base + m_rt_type_limit; + local_alloc_flag = SD_TRUE; + } + + cur_rt = nxt_un_rt = rt_base; + rt_blk_start[0] = rt_base; /* Starting block for level 0 is first block. */ + constr_type[0] = UNDEF; /* Constructed type initializes to UNDEF. */ + /* These variables are used by the tag routines */ + /* to build the runtime type table. */ + + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; + assign_tags (aCtx); /* Assign tags. First type can be anything. */ + + aCtx->asn1r_decode_done_fun = NULL; + aCtx->asn1r_err_fun = err_clean_fun; + + asn1r_decode_asn1 (aCtx, asn1ptr, asn1_len); /* Build the type table. */ + + *tptr = rt_base; /* Local buffer de-allocated on error. */ + if (rt_base != NULL) /* Check for error to prevent doing */ + { /* arithmetic with NULL pointers. */ + *t_len = nxt_un_rt - rt_base; + ms_rt_size_calc (rt_base, *t_len); /* Fix up element offsets in table */ + } + else + *t_len = 0; + + ret = (aCtx->asn1r_pdu_dec_err == NO_DECODE_ERR) ? SD_SUCCESS : MVE_DATA_TO_RT ; + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +/************************************************************************/ +/* assign_tags */ +/* Function to assign tags to the ASN1DE tools based on what's expected */ +/* in the runtime_type definition table. At the beginning of the 'Data'*/ +/* entity, a DataAccessError type is allowed. WARNING: This function */ +/* requires that the current rt_block NOT be an end-of-array or end-of- */ +/* structure rt_block. If so, it will return an error. */ +/************************************************************************/ + +static ST_VOID assign_tags (ASN1_DEC_CTXT *aCtx) + { /* There are two possible cases here: */ + /* 1.) We are parsing through terra incognita and don't know */ + /* what to expect (yet). All possible tags are legal. */ + /* Set up to build type definitions for what we find. */ + /* 2.) We are parsing through the 2nd or later element of an */ + /* array and know what tag we should get next. If the */ + /* array is a sub-array of an enveloping array, we will */ + /* have an element count for it; check that too. Verify */ + /* tags against what we expect to see. */ + + if (cur_rt < nxt_un_rt) /* if this is the 2nd or later element */ + { /* of an array & types are defined, */ + if (cur_rt->el_tag == RT_ARR_END) /* treat case of array ending */ + { /* Only possible if we've seen this array before as */ + /* an element of an enveloping array, otherwise */ + /* there would be no RT_ARR_END runtime record yet. */ + if (--arr_loops[arr_loop_level] > 0) /* if need to do next ar elmnt */ + cur_rt -= cur_rt->u.arr.num_rt_blks; + } /* mv cur_rt to start of arr */ + + switch (cur_rt->el_tag) + { + case RT_ARR_START : + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,arr_start); /* expecting an array cstr */ + break; + + case RT_STR_START : + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,str_start); /* expecting a struct cstr */ + break; + + case RT_BOOL : + ASN1R_TAG_ADD (aCtx, CTX,3,get_bool_prim); + break; + + case RT_BIT_STRING : + ASN1R_TAG_ADD (aCtx, CTX,4,get_bitstr_prim); +#if 0 /* Constructed bitstrings and octetstrings not supported */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,4,get_bstr_cstr); +#endif + break; + + case RT_INTEGER : + ASN1R_TAG_ADD (aCtx, CTX,5,get_int_prim); + break; + + case RT_UNSIGNED : + ASN1R_TAG_ADD (aCtx, CTX,6,get_uint_prim); + break; + +#ifdef FLOAT_DATA_SUPPORT + case RT_FLOATING_POINT : + ASN1R_TAG_ADD (aCtx, CTX,7,get_float_prim); + break; +#endif + + case RT_OCTET_STRING : + ASN1R_TAG_ADD (aCtx, CTX,9,get_octstr_prim); +#if 0 /* Constructed bitstrings and octetstrings not supported */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,9,get_ostr_cstr); +#endif + break; + + case RT_VISIBLE_STRING : + ASN1R_TAG_ADD (aCtx, CTX,10,get_vstr_prim); + break; + +#ifdef TIME_DATA_SUPPORT + case RT_GENERAL_TIME : + ASN1R_TAG_ADD (aCtx, CTX,11,get_gtime_prim); + break; +#endif + +#ifdef BTOD_DATA_SUPPORT + case RT_BINARY_TIME : + ASN1R_TAG_ADD (aCtx, CTX,12,get_btime_prim); + break; +#endif + + case RT_BCD : + ASN1R_TAG_ADD (aCtx, CTX,13,get_bcd_prim); + break; + + case RT_UTC_TIME : + ASN1R_TAG_ADD (aCtx, CTX,17,get_utc_time_prim); + break; + + case RT_UTF8_STRING : + ASN1R_TAG_ADD (aCtx, CTX,RT_UTF8_STRING,get_utf8_prim); + break; + + case RT_ARR_END : /* array done */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = arr_done_fun; /* the arr cstr must be done*/ + break; + + case RT_STR_END : /* structure done */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = str_done_fun; /* the str cstr must be done*/ + break; + + default : /* should not be any other tag */ + MLOG_ERR0 ("Bad tag in runtime type"); + asn1r_set_dec_err (aCtx, INTERNAL); + return; + break; + } + } + else /* In terra incognita, next element can be anything */ + { + /* Allow for any type of data in the data string. */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,arr_start); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,str_start); + ASN1R_TAG_ADD (aCtx, CTX,3,get_bool_prim); + ASN1R_TAG_ADD (aCtx, CTX,4,get_bitstr_prim); +#if 0 /* Constructed bitstrings and octetstrings not supported */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,4,get_bstr_cstr); +#endif + ASN1R_TAG_ADD (aCtx, CTX,5,get_int_prim); + ASN1R_TAG_ADD (aCtx, CTX,6,get_uint_prim); + ASN1R_TAG_ADD (aCtx, CTX,7,get_float_prim); + ASN1R_TAG_ADD (aCtx, CTX,9,get_octstr_prim); +#if 0 /* Constructed bitstrings and octetstrings not supported */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,9,get_ostr_cstr); +#endif + ASN1R_TAG_ADD (aCtx, CTX,10,get_vstr_prim); + ASN1R_TAG_ADD (aCtx, CTX,11,get_gtime_prim); + ASN1R_TAG_ADD (aCtx, CTX,12,get_btime_prim); + ASN1R_TAG_ADD (aCtx, CTX,13,get_bcd_prim); + ASN1R_TAG_ADD (aCtx, CTX,17,get_utc_time_prim); + ASN1R_TAG_ADD (aCtx, CTX,RT_UTF8_STRING,get_utf8_prim); + } + } + + + +/************************************************************************/ +/* init_new_RT */ +/* This is the function called to check to see if a new RT table entry */ +/* is required and available, and initializes it if so. */ +/* Parameters: */ +/* tag Tag value for the field type. */ +/* el_len Element length, in its own units. 0 for constructed */ +/* types. Units are bytes except for bitstrings (length */ +/* given in bits). */ +/* Globals input: */ +/* cur_rt, nxt_un_rt, rt_EOB_ptr */ +/* Globals output: */ +/* nxt_un_rt */ +/* Returns: */ +/* 0 if OK, 1 if error (table overflow). */ +/************************************************************************/ + +static int init_new_RT (ASN1_DEC_CTXT *aCtx, ST_UCHAR tag, ST_INT el_len) + { +ST_BOOLEAN prim; +ST_INT st_size; + + prim = SD_TRUE; + switch (tag) /* Calc storage size based on element fundamentals */ + { + case RT_BOOL: /* Size must be 1, so ignore it. */ + st_size = 1; + break; + + case RT_BIT_STRING: /* el_len was converted to bits */ + st_size = CALC_BIT_LEN (el_len); /* Calculate byte count. */ + break; + + case RT_INTEGER: /* Size is in bytes. */ + case RT_UNSIGNED: + st_size = el_len; /* already conditioned (1,2,4) */ + break; + + case RT_BCD: /* always put into ST_INT32 */ + st_size = 4; + el_len = 8; /* assume type is 8 BCD digits */ + break; + + case RT_FLOATING_POINT: + /* Decrement el_len because it's used for storage size later */ + st_size = (--el_len == 4) ? sizeof (float) : sizeof (double); + break; + + case RT_OCTET_STRING: /* Size is in bytes. */ + st_size = el_len; /* No terminating null */ + break; /* If variable length, size will */ + /* be increased by sizeof (ST_INT16) */ + + case RT_VISIBLE_STRING: /* Size is in bytes. */ + st_size = el_len+1; /* Add space for terminating null */ + break; /* No increase for variable length */ + + case RT_GENERAL_TIME: /* Generalized time */ + st_size = sizeof (time_t); + el_len = sizeof (time_t); + break; + + case RT_BINARY_TIME: /* Binary time */ + if (el_len == 6) + st_size = 2 * sizeof (ST_INT32); + else + st_size = sizeof (ST_INT32); + break; + + case RT_UTC_TIME: /* UTC time */ + st_size = sizeof (MMS_UTC_TIME); /* 3 * sizeof (ST_UINT32); */ + break; + + case RT_UTF8_STRING: /* Unicode UTF8string */ +#if (UNICODE_LOCAL_FORMAT==UNICODE_UTF8) + st_size = abs(el_len)*4 + 1; /* # bytes (4 bytes per char + NULL)*/ +#else /* assume UNICODE_UTF16 */ + st_size = abs(el_len)*2 + 2; /* # bytes (2 bytes per char + 2 byte NULL)*/ +#endif + break; + + default: + prim = SD_FALSE; /* Not a primitive element. */ + st_size = 0; + break; + } + + if (cur_rt == nxt_un_rt) /* If this element is not already defined, */ + { /* We need to use another el, do ovrfl check */ + if (nxt_un_rt == rt_EOB_ptr) /* Check against EOB pointer. */ + { + asn1r_set_dec_err (aCtx, MX_MEMORY_ALLOC); /* Table is full, declare error & return */ + MLOG_ERR1 ("Exceeded %d limit on number of elements in RUNTIME_TYPE array", rt_EOB_ptr - rt_base); + return SD_FAILURE; /* Error value. */ + } + ++nxt_un_rt; /* Used one more element. */ + /* Clear the new element. */ + memset ((char *)cur_rt, 0, sizeof (RUNTIME_TYPE)); + cur_rt->el_tag = tag; /* Set the tag value. */ + cur_rt->el_size = st_size; /* Set storage size */ + if (prim) + { + if (tag == RT_BCD) + cur_rt->u.p.el_len = 8; + else + cur_rt->u.p.el_len = el_len; /* Set initial data size for prim */ + } + if (tag == RT_ARR_START) + cur_rt->u.arr.num_rt_blks = -1; /* Flag unfinished constructor */ + else if (tag == RT_STR_START) + cur_rt->u.str.num_rt_blks = -1; /* Flag unfinished constructor */ + + return SD_SUCCESS; /* New element, done. */ + } + + /* The following code executes if this is an element of an array. */ + /* It adjusts sizes if necessary. For example, if the second Vstring */ + /* in an array is longer than the first, the el_len and el_size are */ + /* increased to handle it. */ + + /* This is an "old" element. Check data sizes */ + /* and update as required. Check for variable */ + switch (tag) /* length issues in byte and bit strings. */ + { + case RT_BIT_STRING: /* Size is in bits */ + if (cur_rt->u.p.el_len < 0) /* Is variable */ + { /* Re-size if necessary */ + if (-cur_rt->u.p.el_len < el_len) /* New one is bigger */ + { + cur_rt->u.p.el_len = -el_len; /* Set new length */ + cur_rt->el_size = st_size + sizeof (ST_INT16); + } + } + else if (cur_rt->u.p.el_len != el_len) /* Different length */ + { /* Make variable length */ + if (cur_rt->u.p.el_len > el_len) /* Size for biggest seen */ + el_len = cur_rt->u.p.el_len; + + cur_rt->u.p.el_len = -el_len; + cur_rt->el_size = CALC_BIT_LEN (el_len) + sizeof (ST_INT16); + } + break; + + case RT_INTEGER: /* Size is in bytes. */ + case RT_UNSIGNED: + if (st_size > cur_rt->el_size) /* If this one is bigger, */ + { /* set both storage size */ + cur_rt->el_size = /* and element length. */ + cur_rt->u.p.el_len = st_size; + } + break; + + case RT_OCTET_STRING: /* Size is in bytes. */ + if (cur_rt->u.p.el_len < 0) /* Variable size */ + { + if (-cur_rt->u.p.el_len < el_len) /* New one is longer */ + { + cur_rt->u.p.el_len = -el_len; /* Bump size up */ + cur_rt->el_size = el_len + sizeof (ST_INT16); + } + } + else if (cur_rt->u.p.el_len != el_len) /* Different size */ + { + if (-cur_rt->u.p.el_len > el_len) /* If old is bigger, */ + el_len = -cur_rt->u.p.el_len; /* keep it, otherwise */ + cur_rt->u.p.el_len = -el_len; /* use this size. */ + cur_rt->el_size = el_len + sizeof (ST_INT16); + } + break; + + case RT_VISIBLE_STRING: /* Size is in bytes. */ + if (cur_rt->u.p.el_len < 0) /* Variable len */ + { + if (cur_rt->u.p.el_len > -el_len) /* New one is bigger. */ + cur_rt->u.p.el_len = -el_len; + } + else if (cur_rt->u.p.el_len != el_len) /* Length different */ + { /* Make variable length */ + if (cur_rt->u.p.el_len > el_len) + el_len = cur_rt->u.p.el_len; + cur_rt->u.p.el_len = -el_len; + } + cur_rt->el_size = abs (cur_rt->u.p.el_len) + 1; + break; + + case RT_UTF8_STRING: /* Unicode UTF8string */ + /* If new len > old len, force string to be "variable-len" & increase len.*/ + if (abs(el_len) > abs(cur_rt->u.p.el_len)) /* New one is bigger. */ + { + cur_rt->u.p.el_len = -abs(el_len); /* increase len */ + /* adjust el_size */ +#if (UNICODE_LOCAL_FORMAT==UNICODE_UTF8) + cur_rt->el_size = abs(cur_rt->u.p.el_len)*4 + 1; /* # bytes (4 bytes per char + NULL)*/ +#else /* assume UNICODE_UTF16 */ + cur_rt->el_size = abs(cur_rt->u.p.el_len)*2 + 2; /* # bytes (2 bytes per char + 2 byte NULL)*/ +#endif + } + break; + + default: /* Other types are fixed length */ + break; + } + + return SD_SUCCESS; /* All OK. */ + } + + + +/************************************************************************/ +/* next_rt_index */ +/* Sets cur_rt to the correct value for the next data element in */ +/* the parse. If the current message level is an unfinished array, */ +/* it increments the u.arr.num_elmnts member of the header. */ +/* Parameters: None. */ +/* Globals input: cur_rt, nxt_un_rt, constr_type[] */ +/* Globals output: cur_rt */ +/* Other variables changed: cur_rt->u.arr.num_elmnts */ +/************************************************************************/ + +static ST_VOID next_rt_index (ASN1_DEC_CTXT *aCtx) + { + if (++cur_rt < nxt_un_rt) /* Next RT element already defined? */ + return; /* Return, done. */ + /* The current message level isn't complete yet. Check type. */ + if (constr_type[aCtx->asn1r_msg_level] == ARRAY) /* This is an unfinished array. */ + { + cur_rt = rt_blk_start[aCtx->asn1r_msg_level]; /* Loop back to array start */ + cur_rt->u.arr.num_elmnts++; /* Inc # of elements. */ + ++cur_rt; /* Point to contents. */ + } + /* Done. No loopback is required for structures, only arrays. */ + } + + + +/************************************************************************/ +/* arr_start */ +/* This is the function called when an array cstr is starting */ +/************************************************************************/ + +static ST_VOID arr_start (ASN1_DEC_CTXT *aCtx) + { +/* initialize the loop counter for the array */ + MLOG_CDEC0 ("pars_arr_start"); + + if (init_new_RT (aCtx, RT_ARR_START, 0)) /* Return if error. */ + return; + /* Check to see if the end-contructor for this array */ + /* has been encountered before. */ + + ++arr_loop_level; + if (cur_rt->u.arr.num_rt_blks == -1) + { + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = arr_done_fun; /* Init now if new array */ + } + else /* We've seen this array before as an element of a larger array. We */ + /* know the size. Initialize the loop count in the RT_ARR_END block. */ + { + arr_loops[arr_loop_level] = cur_rt->u.arr.num_elmnts; + } + + + rt_blk_start[aCtx->asn1r_msg_level] = cur_rt; /* Point to initial element */ + constr_type[aCtx->asn1r_msg_level] = ARRAY; + cur_rt++; /* Increment index (no loopback) */ + assign_tags (aCtx); /* Assign tags for next data element. */ + } + + +/************************************************************************/ +/* arr_done_fun */ +/* This is the cstr done function called when an array cstr is done */ +/* Note: aCtx->asn1r_msg_level is one less than the value given to array_start (). */ +/************************************************************************/ + +static ST_VOID arr_done_fun (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("pars_arr_done_fun"); + + if (rt_blk_start[aCtx->asn1r_msg_level+1]->u.arr.num_rt_blks == -1) + { /* Unfinished array, build RT_ARR_END record. */ + cur_rt = nxt_un_rt; /* Point to one past end */ + if (init_new_RT (aCtx, RT_ARR_END, 0)) /* Init a new RT block */ + return; + + cur_rt->u.arr.num_rt_blks = /* Calc RT block count for array. */ + rt_blk_start[aCtx->asn1r_msg_level+1]->u.arr.num_rt_blks = + (cur_rt - rt_blk_start[aCtx->asn1r_msg_level+1] - 1);/* Copy count back to start. */ + + cur_rt->u.arr.num_elmnts = /* Copy element count to */ + rt_blk_start[aCtx->asn1r_msg_level+1]->u.arr.num_elmnts;/* end-array element.*/ + } + else + { /* This is the end of a finished array. */ + if (arr_loops[arr_loop_level]) /* Loop count down to 0? */ + { + MLOG_NERR0 ("Malformed array data"); + asn1r_set_dec_err (aCtx, BAD_DATA); /* If not exactly 0, error. */ + } + } + --arr_loop_level; + + next_rt_index (aCtx); + assign_tags (aCtx); /* setup to get next element */ + } + +/************************************************************************/ +/* str_start */ +/* This is the function called when a struct cstr is starting */ +/************************************************************************/ + +static ST_VOID str_start (ASN1_DEC_CTXT *aCtx) + { + + if (init_new_RT (aCtx, RT_STR_START, 0)) + return; + + if (cur_rt->u.str.num_rt_blks == -1) + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = str_done_fun; /* Init now if new struct */ + + rt_blk_start[aCtx->asn1r_msg_level] = cur_rt; /* Point to initial element */ + constr_type[aCtx->asn1r_msg_level] = STRUCT; + cur_rt++; /* point to next runtime element always */ + assign_tags (aCtx); /* setup to get next element */ + } + +/************************************************************************/ +/* str_done_fun */ +/* This is the cstr done function called when a struct cstr is done */ +/* Note: aCtx->asn1r_msg_level is one less than the value given to str_start (). */ +/************************************************************************/ + +static ST_VOID str_done_fun (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("pars_str_done_fun"); + + if (init_new_RT (aCtx, RT_STR_END, 0)) + return; + + cur_rt->u.str.num_rt_blks = /* Calc RT block count for struct. */ + rt_blk_start[aCtx->asn1r_msg_level+1]->u.str.num_rt_blks = + (cur_rt - rt_blk_start[aCtx->asn1r_msg_level+1] - 1); /* Copy count back to start. */ + + next_rt_index (aCtx); /* point to next runtime element */ + assign_tags (aCtx); /* setup to get next element */ + } + + +/************************************************************************/ +/************************************************************************/ +#if 0 /* Constructed bitstrings and octetstrings not supported */ +/************************************************************************/ +/************************************************************************/ +/* get_bstr_cstr */ +/* State function to extract a boolean value from an asn1 data element. */ +/************************************************************************/ + + +static ST_VOID get_bstr_cstr (ASN1_DEC_CTXT *aCtx) &&& This code not implemented. + { + MLOG_CDEC0 ("pars_get_bstr_cstr"); + + if (init_new_RT (aCtx, RT_STR_END, 0)) + return; + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = bs_cstr_done; + + next_rt_index (aCtx); /* point to next runtime element */ + assign_tags (aCtx); /* setup to get next element */ + } + + +/************************************************************************/ +/* bs_cstr_done */ +/* This function is called when an bit string constructor is */ +/* completed OK. Need to reset the decode state machine. */ +/* Note: aCtx->asn1r_msg_level is one less than the value given to get_bstr_cstr (). */ +/************************************************************************/ + +static ST_VOID bs_cstr_done (ASN1_DEC_CTXT *aCtx) &&& Not implemented yet + { +ST_INT abs_len; +ST_INT abs_count; +int i; +ST_CHAR *to_ptr; +ST_CHAR *from_ptr; + + abs_count = abs (cur_rt->u.p.el_len); + abs_len = CALC_BIT_LEN (abs_count); + +/* determine whether octet string is fixed or variable length */ + + if (cur_rt->u.p.el_len >=0) /* fixed length */ + { + if (aCtx->asn1r_bitcount != abs_count) + { + MLOG_NERR0 ("Fixed length bit string mismatch"); + asn1r_set_dec_err (aCtx, BAD_DATA); + } + } + else /* variable length bit string */ + { /* need to move down to allow for size ST_INT16 */ + from_ptr = datptr+abs_len-1; + to_ptr = from_ptr+sizeof (ST_INT16); + for (i = 0; i < abs_count; ++i) + *(to_ptr--) = *(from_ptr--); + + *((ST_INT16 *)datptr) = (ST_INT16) aCtx->asn1r_bitcount; + } + + datptr += cur_rt->el_size; /* Adjust data pointer */ + cur_rt++; /* point to next runtime element */ + assign_tags (aCtx); /* Assign tags for next data elt*/ + } + + +/************************************************************************/ +/* get_ostr_cstr */ +/* State function to extract an octet string from an asn1 data element. */ +/************************************************************************/ + +static ST_VOID get_ostr_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("pars_get_ostr_cstr"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = os_cstr_done; + asn1r_get_octstr_cstr (aCtx, abs (cur_rt->u.p.el_len), datptr); + } + +/************************************************************************/ +/* os_cstr_done */ +/* This function is called when an octet string constructor is */ +/* completed OK. Need to reset the decode state machine. */ +/************************************************************************/ + +static ST_VOID os_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT abs_len; +int i; +ST_CHAR *to_ptr; +ST_CHAR *from_ptr; + + abs_len = abs (cur_rt->u.p.el_len); + +/* determine whether octect string is fixed or variable length */ + + if (cur_rt->u.p.el_len >=0) /* fixed length */ + { + if (aCtx->asn1r_octetcount != abs_len) + { + MLOG_NERR0 ("Fixed length octet string mismatch"); + asn1r_set_dec_err (aCtx, BAD_DATA); + } + } + else /* variable length octet string */ + { /* need to move down to allow for size ST_INT16 */ + from_ptr = datptr+abs_len-1; + to_ptr = from_ptr+sizeof (ST_INT16); + for (i = 0; i < aCtx->asn1r_octetcount; ++i) + *(to_ptr--) = *(from_ptr--); + + *((ST_INT16 *)datptr) = (ST_INT16) aCtx->asn1r_octetcount; + } + + datptr += cur_rt->el_size; /* Adjust data pointer */ + cur_rt++; /* point to next runtime element */ + assign_tags (aCtx); /* Assign tags for next data elt*/ + } + +/************************************************************************/ +#endif +/************************************************************************/ +/************************************************************************/ + +/************************************************************************/ +/* get_bool_prim */ +/* State function to extract a boolean prim from an asn1 data element. */ +/************************************************************************/ + +static ST_VOID get_bool_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("pars_get_bool_prim"); + + if (init_new_RT (aCtx, RT_BOOL, aCtx->asn1r_elmnt_len)) + return; + + if (aCtx->asn1r_elmnt_len != 1) + { + MLOG_NERR0 ("Malformed boolean data"); + asn1r_set_dec_err (aCtx, BAD_DATA); /* checked by get function */ + } + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; /* Skip over data */ + + next_rt_index (aCtx); /* point to next runtime element */ + assign_tags (aCtx); /* setup to get next element */ + } + +/************************************************************************/ +/* get_bitstr_prim */ +/* State function to extract a bitstring prim from an asn1 data element */ +/************************************************************************/ + +static ST_VOID get_bitstr_prim (ASN1_DEC_CTXT *aCtx) + { +ST_INT bit_count; + + MLOG_CDEC0 ("pars_get_bitstr_prim"); + + bit_count = (aCtx->asn1r_elmnt_len > 1) ? ((aCtx->asn1r_elmnt_len-1)*8 - (*aCtx->asn1r_field_ptr & 7)) : 0; + if (!aCtx->asn1r_elmnt_len || (!bit_count && *aCtx->asn1r_field_ptr)) + { + MLOG_NERR0 ("Malformed bitstring data"); + asn1r_set_dec_err (aCtx, BAD_DATA); + } + + if (init_new_RT (aCtx, RT_BIT_STRING, bit_count)) + return; + + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; + + next_rt_index (aCtx); /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* get_int_prim */ +/* State function to extract an integer prim from an asn1 data element. */ +/************************************************************************/ + +static ST_VOID get_int_prim (ASN1_DEC_CTXT *aCtx) + { +ST_INT el_len; + + MLOG_CDEC0 ("pars_get_int_prim"); + + switch (aCtx->asn1r_elmnt_len) /* determine internal length */ + { + case 1: /* one byte int */ + el_len = 1; + break; + + case 2: /* two byte int */ + el_len = 2; + break; + + case 3: /* three byte int, expand to 4 */ + case 4: /* four byte integer */ + el_len = 4; + break; + +#ifdef INT64_SUPPORT + case 5: + case 6: + case 7: + case 8: + el_len = 8; + break; +#endif + + default : + MLOG_NERR0 ("Malformed integer data"); + asn1r_set_dec_err (aCtx, BAD_DATA); /* no other lengths are valid */ + return; + } + +/* Assume all integers at least 4 bytes (i.e. ST_INT32). */ + if (el_len < 4) + el_len = 4; + + if (init_new_RT (aCtx, RT_INTEGER, el_len)) + return; + + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; + next_rt_index (aCtx); /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* get_uint_prim */ +/* State function to extract an unsigned integer prim from an asn1 data */ +/* element. */ +/************************************************************************/ + +static ST_VOID get_uint_prim (ASN1_DEC_CTXT *aCtx) + { +ST_INT el_len; +ST_INT asn1ElmntLen; + + MLOG_CDEC0 ("pars_get_uint_prim"); + +/* Unsigned data may have a leading 0x00 if it otherwise would be neg */ + asn1ElmntLen = aCtx->asn1r_elmnt_len; + if (aCtx->asn1r_elmnt_len > 1 && + *aCtx->asn1r_field_ptr == 0 && + *(aCtx->asn1r_field_ptr+1) & 0x80) + { + --asn1ElmntLen; + } + + switch (asn1ElmntLen) /* determine internal length */ + { + case 1: /* one byte */ + el_len = 1; + break; + + case 2: /* two bytes */ + el_len = 2; + break; + + case 3: /* three bytes, expand to 4 */ + case 4: /* four bytes */ + el_len = 4; + break; + +#ifdef INT64_SUPPORT + case 5: + case 6: + case 7: + case 8: + el_len = 8; + break; +#endif + + default : + MLOG_NERR0 ("Malformed unsigned data"); + asn1r_set_dec_err (aCtx, BAD_DATA); /* no other lengths are valid */ + return; + } + +/* Assume all unsigned integers at least 4 bytes (i.e. ST_UINT32). */ + if (el_len < 4) + el_len = 4; + + if (init_new_RT (aCtx, RT_UNSIGNED, el_len)) + return; + + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; + next_rt_index (aCtx); /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* get_float_prim */ +/* State function to extract a floating point primitive from an asn1 */ +/* data element. */ +/************************************************************************/ + +#ifdef FLOAT_DATA_SUPPORT + +static ST_VOID get_float_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("pars_get_float_prim"); + + if (init_new_RT (aCtx, RT_FLOATING_POINT, aCtx->asn1r_elmnt_len)) + return; + + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; + next_rt_index (aCtx); /* point to next runtime element */ + assign_tags (aCtx); + } + +#endif + +/************************************************************************/ +/* get_octstr_prim */ +/* State function to extract an octet string primitive from an asn1 */ +/* data element. */ +/************************************************************************/ + +static ST_VOID get_octstr_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("pars_get_octstr_prim"); + + if (init_new_RT (aCtx, RT_OCTET_STRING, aCtx->asn1r_elmnt_len)) + return; + + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; + next_rt_index (aCtx); /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* get_vstr_prim */ +/* State function to extract a visible string primitive from an asn1 */ +/* data element. */ +/************************************************************************/ + +static ST_VOID get_vstr_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("pars_get_vstr_prim"); + + if (init_new_RT (aCtx, RT_VISIBLE_STRING, aCtx->asn1r_elmnt_len)) + return; + + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; + next_rt_index (aCtx); /* point to next runtime element*/ + assign_tags (aCtx); + } + +/************************************************************************/ +/* get_gtime_prim */ +/* State function to extract a generalized time primitive from an asn1 */ +/* data element. */ +/************************************************************************/ + +#ifdef TIME_DATA_SUPPORT + +static ST_VOID get_gtime_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("pars_get_gtime_prim"); + + if (init_new_RT (aCtx, RT_GENERAL_TIME, aCtx->asn1r_elmnt_len)) + return; + + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; + next_rt_index (aCtx); /* point to next runtime element */ + assign_tags (aCtx); + } + +#endif + +/************************************************************************/ +/* get_btime_prim */ +/* State function to extract a binary time primitive from an asn1 data */ +/* element. */ +/************************************************************************/ + +#ifdef BTOD_DATA_SUPPORT + +static ST_VOID get_btime_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("pars_get_btime_prim"); + + if (init_new_RT (aCtx, RT_BINARY_TIME, aCtx->asn1r_elmnt_len)) + return; + + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; + next_rt_index (aCtx); /* point to next runtime element */ + assign_tags (aCtx); + } + +#endif + +/************************************************************************/ +/* get_bcd_prim */ +/* State function to extract a binary coded decimal primitive from an */ +/* asn1 data element. */ +/************************************************************************/ + +static ST_VOID get_bcd_prim (ASN1_DEC_CTXT *aCtx) + { + + MLOG_CDEC0 ("pars_get_bcd_prim"); + + if (aCtx->asn1r_elmnt_len > 4) + { + MLOG_NERR0 ("Malformed bcd data"); + asn1r_set_dec_err (aCtx, BAD_DATA); + return; + } + + if (init_new_RT (aCtx, RT_BCD, aCtx->asn1r_elmnt_len)) + return; + + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; /* Adjust data pointer */ + next_rt_index (aCtx); /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* get_utc_time_prim */ +/* State function to extract a utc time primitive from an asn1 data */ +/* element. */ +/************************************************************************/ + +static ST_VOID get_utc_time_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("pars_get_utc_time_prim"); + + if (init_new_RT (aCtx, RT_UTC_TIME, aCtx->asn1r_elmnt_len)) + return; + + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; + next_rt_index (aCtx); /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* get_utf8_prim */ +/* State function to extract a Unicode UTF8string primitive from an */ +/* asn1 data element. */ +/* Assume string is "variable-length", so pass "negative" len. The len */ +/* is the number of Unicode characters. Each Unicode character takes */ +/* at least 1 byte, so the number of characters is ALWAYS <= */ +/* the ASN.1 encoded size. */ +/************************************************************************/ + +static ST_VOID get_utf8_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_utf8_prim"); + + /* Pass "negative" len to indicate "variable-length". */ + if (init_new_RT (aCtx, RT_UTF8_STRING, -aCtx->asn1r_elmnt_len)) + return; + + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; + next_rt_index (aCtx); /* point to next runtime element */ + assign_tags (aCtx); + } + +/************************************************************************/ +/* err_clean_fun */ +/************************************************************************/ + + +static ST_VOID err_clean_fun (ASN1_DEC_CTXT *aCtx, ST_RET err_code) + { + if (local_alloc_flag) + { + chk_free (rt_base); + rt_base = NULL; + } + nxt_un_rt = rt_base; /* Zero length runtime buffer. */ + } + + diff --git a/mmslib/mmsl/mmsdec.c b/mmslib/mmsl/mmsdec.c new file mode 100644 index 0000000..08bd1f7 --- /dev/null +++ b/mmslib/mmsl/mmsdec.c @@ -0,0 +1,768 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2008, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsdec.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the initial MMS message decode functions. */ +/* Decodes the header portion of MMS PDUs. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/17/08 EJV 10 Added slog. */ +/* 12/19/05 JRB 22 Chg cr to cr_mms, del static to fix warning.*/ +/* 09/07/05 JRB 08 Fix backwards client/server error log msgs. */ +/* 07/24/02 EJV 07 mmsdec_ucreq_opcode: corr err in the check */ +/* opcode due to recent MMSOP_xxx changes. */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* Del mms_err_invoke_fun proto (see mms_dfun.h)*/ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 04/07/99 MDE 04 Logging improvements (unsupported service) */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/18/98 JRB 01 Fix mmsdec_map_err for new error values. */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_err.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ + +static ST_VOID mmsdec_start (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code); +static ST_VOID mmsdec_invoke_id (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code); +#ifdef MOD_SUPPORT /* support modifiers */ +static ST_VOID mmsdec_modlist (ASN1_DEC_CTXT *aCtx, ST_UINT16 el_id); +static ST_VOID mmsdec_modlist_done_fun (ASN1_DEC_CTXT *aCtx); +#endif +static ST_VOID mmsdec_opcode (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code); +static ST_VOID mmsdec_ucreq_opcode (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code); +static ST_RET mmsdec_chk_req_op (ASN1_DEC_CTXT *aCtx, ST_INT opcode, ST_INT unsupp_code); +static ST_RET mmsdec_chk_resp_op (ASN1_DEC_CTXT *aCtx, ST_UINT opcode); +static ST_VOID mmsdec_map_err (ASN1_DEC_CTXT *aCtx); /* maps ASN.1 tool errors to MMS */ +#ifndef MMS_LITE /* don't assign op id's */ +static ST_VOID mmsdec_assign_rid (ST_INT opcode); +#endif + +/************************************************************************/ +const ST_CHAR cr_mms[] = + "(c) COPYRIGHT SYSTEMS INTEGRATION SPECIALISTS COMPANY INC., 1986 - 2005. All Rights Reserved."; +/************************************************************************/ +/* Operation Specific Decode Buffer Management */ + +ST_VOID *(*m_calloc_os_fun)(ST_UINT num, ST_UINT size); +ST_VOID *(*m_realloc_os_fun)(ST_VOID *old, ST_UINT new_size); +ST_VOID (*m_free_os_fun)(ST_VOID *buf); + +/************************************************************************/ +/* The array below is used to check the constructed state of a PDU */ + +SD_CONST static ST_UINT16 mmspdu_cstr_chk[] = + { + CONSTR, /* CONFIRMED REQUEST IS CONSTRUCTOR */ + CONSTR, /* CONFIRMED RESPONSE */ + CONSTR, /* CONFIRMED ERROR */ + CONSTR, /* UNCONFIRMED PDU */ + CONSTR, /* REJECT */ + 0, /* CANCEL REQUEST */ + 0, /* CANCEL RESPONSE */ + CONSTR, /* CANCEL ERROR */ + CONSTR, /* INITIATE REQUEST */ + CONSTR, /* INITIATE RESPONSE */ + CONSTR, /* INITIATE ERROR */ + 0, /* CONCLUDE REQUEST IS PRIMITIVE */ + 0, /* CONCLUDE RESPONSE */ + CONSTR /* CONCLUDE ERROR IS CONSTRUCTOR */ + }; + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mms_decode */ +/* Function to setup and initiate MMS PDU decode */ +/* Only fourteen context specific codes are legal at start */ +/* Input parameters : pointer to message start, length of message, */ +/* pointer to result buffer. */ +/************************************************************************/ + +ST_RET _ms_mms_decode (ST_UCHAR *msg_ptr, ST_INT len, MMSDEC_INFO *rslt_ptr) + { +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + MLOG_DEC0 ("Decoding MMS PDU"); + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean. */ + + aCtx->asn1r_decode_method = ASN1_CLASS_METHOD; /* select the class method */ + aCtx->asn1r_c_id_fun = mmsdec_start; /* point to mms decode initial function */ + aCtx->asn1r_u_id_fun = asn1r_class_err; /* no universals to start */ + aCtx->asn1r_a_id_fun = asn1r_class_err; /* no applications to start */ + aCtx->asn1r_p_id_fun = asn1r_class_err; /* no privates to start */ + + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + + _mmsdec_msglen = len; /* save decode message length */ + _mmsdec_msgptr = msg_ptr; /* save decode message ptr */ + _mmsdec_rslt = rslt_ptr; /* save the result pointer */ + rslt_ptr->err_code = NO_DECODE_ERR; /* start with no error */ + rslt_ptr->dec_level = 0; /* start with no usable info */ + rslt_ptr->data_pres = SD_FALSE; + rslt_ptr->mods.info_pres = SD_FALSE; + rslt_ptr->cs.cs_pres = SD_FALSE; + _mms_dec_info_pres = SD_FALSE; + +/* ASN.1 decode machine is set up for initial MMS decode. */ +/* Call 'asn1r_decode_asn1' to parse the message. */ + + asn1r_decode_asn1 (aCtx, msg_ptr,len); /* do message decode */ + mmsdec_map_err (aCtx); /* write the error code */ + if (aCtx->asn1r_pdu_dec_err == NO_DECODE_ERR) + return (SD_SUCCESS); /* return 'no error' code */ +#ifndef MMS_LITE + else + { + if (_mmsdec_rslt->mods.info_pres) /* see if there were any mods */ + chk_free (_mmsdec_rslt->mods.mod_list_ptr); + +/* Note that op specific buffer are free'd in _mms_dec_buf_free on error */ + + } +#endif + return (MVE_ASN1_DECODE_ERR); /* return error code */ + } + +/************************************************************************/ +/************************************************************************/ +/* mmsdec_start */ +/* Initial MMS decode context-specific code service function. This */ +/* function is called when the first data element of the message is a */ +/* context-specific class. */ +/************************************************************************/ + +#define MAX_MMS_PDU_TAG 13 + +static ST_VOID mmsdec_start (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code) + { + MLOG_CDEC0 ("mmsdec_start"); + +/* check for valid MMS PDU type, such as request, response, error, etc. */ +/* if valid tag and constructed state OK */ + if (id_code <= MAX_MMS_PDU_TAG && + !(mmspdu_cstr_chk[id_code] ^ aCtx->asn1r_constr_elmnt)) + { + _mmsdec_rslt->dec_level = 1; /* set flag that PDU type is OK */ + _mmsdec_rslt->type = id_code; /* save the type for the user */ + switch (id_code) + { + case MMSREQ : /* Confirmed Request PDU */ + aCtx->asn1r_u_id_fun = mmsdec_invoke_id; /* next must be uni, integer */ + /* invoke ID */ + aCtx->asn1r_c_id_fun = asn1r_class_err; /* can not context specific */ + break; + + case MMSRESP : /* Confirmed Response PDU */ + aCtx->asn1r_u_id_fun = mmsdec_invoke_id; /* next must be uni, integer */ + /* invoke ID */ + aCtx->asn1r_c_id_fun = asn1r_class_err; /* cannot be context specific */ + break; + + case MMSERROR : /* Confirmed Error PDU */ + aCtx->asn1r_c_id_fun = mms_err_invoke_fun; /* must be context specific */ + break; /* integer (invoke ID) */ + + case MMSUNREQ : /* Unconfirmed PDU */ + aCtx->asn1r_c_id_fun = mmsdec_ucreq_opcode; /* expect context-specific tag */ + break; + + case MMSREJECT : /* Reject PDU */ + aCtx->asn1r_c_id_fun = mms_reject; /* expect context-specific */ + break; + + case MMSCANREQ : /* Cancel Request PDU */ + if (!(mmsop_en[MMSOP_CANCEL] & RESP_EN)) /* protocol error if */ + asn1r_set_dec_err (aCtx, CANREQ_UNSPECIFIED); /* unsupported service */ + else + { + if (asn1r_get_u32 (aCtx, &_mmsdec_rslt->id)) + asn1r_set_dec_err (aCtx, CANREQ_INVAL_INVOKE); + else + { + _mmsdec_rslt->dec_level = 2; + (*mms_req_decode_fun [MMSOP_CANCEL]) (aCtx); + } + } + break; + + case MMSCANRESP : /* Cancel Response PDU */ + if (!(mmsop_en[MMSOP_CANCEL] & REQ_EN)) /* protocol error if */ + asn1r_set_dec_err (aCtx, CANRESP_UNSPECIFIED); /* not supported */ + else + { + if (asn1r_get_u32 (aCtx, &_mmsdec_rslt->id)) + asn1r_set_dec_err (aCtx, CANRESP_INVAL_INVOKE); + else + { + _mmsdec_rslt->dec_level = 2; /* Save inv. ID in rslt */ + (*mms_rsp_decode_fun [MMSOP_CANCEL]) (aCtx); + } + } + break; + + case MMSCANERR : /* Cancel Error PDU */ + if (!(mmsop_en[MMSOP_CANCEL] & REQ_EN)) /* protocol error if */ + asn1r_set_dec_err (aCtx, CANERR_INVAL_SERV); /* is not supported */ + else /* expect context-spec */ + aCtx->asn1r_c_id_fun = mms_err_invoke_fun; + break; + + case MMSINITREQ : /* Initiate Request PDU */ + if (!(mmsop_en[MMSOP_INITIATE] & RESP_EN)) /* if not enabled */ + asn1r_set_dec_err (aCtx, REQ_UNREC_SERV); /* as responder */ + else + { +#ifndef MMS_LITE + mmsdec_assign_rid (MMSOP_INITIATE); /* Assign opcode and */ + /* reserved Initiate ID */ +#endif + (*mms_req_decode_fun [MMSOP_INITIATE]) (aCtx); + } + break; + + case MMSINITRESP : /* Initiate Response PDU */ + if (!(mmsop_en[MMSOP_INITIATE] & REQ_EN)) /* if not enabled */ + asn1r_set_dec_err (aCtx, RESP_UNREC_SERV); /* as responder */ + else + { +#ifndef MMS_LITE + mmsdec_assign_rid (MMSOP_INITIATE); /* Assign opcode and */ + /* reserved Initiate ID */ +#endif + (*mms_rsp_decode_fun [MMSOP_INITIATE]) (aCtx); + } + break; + + case MMSINITERR : /* Initiate Error PDU */ + if (!(mmsop_en[MMSOP_INITIATE] & REQ_EN)) /* protocol error if */ + asn1r_set_dec_err (aCtx, ERR_UNREC_SERV); /* is not supported */ + else + { +#ifndef MMS_LITE + mmsdec_assign_rid (MMSOP_INITIATE); /* Assign opcode and */ + /* reserved Initiate ID */ +#endif + mms_err_rsp (aCtx); /* general err function */ + } + break; + + case MMSCNCLREQ : /* Conclude Requset PDU */ + if (!(mmsop_en[MMSOP_CONCLUDE] & RESP_EN)) /* protocol error if */ + asn1r_set_dec_err (aCtx, CONREQ_UNSPECIFIED); /* not supported */ + else + { + if (aCtx->asn1r_elmnt_len) + asn1r_set_dec_err (aCtx, CONREQ_INVAL_ARG); + else + { +#ifndef MMS_LITE + mmsdec_assign_rid (MMSOP_CONCLUDE);/* Assign opcode and */ + /* reserved Conclude ID */ +#endif + (*mms_req_decode_fun [MMSOP_CONCLUDE]) (aCtx); + } + } + break; + + case MMSCNCLRESP : /* Conclude Response PDU */ + if (!(mmsop_en[MMSOP_CONCLUDE] & REQ_EN)) /* protocol error if */ + asn1r_set_dec_err (aCtx, CONRESP_UNSPECIFIED); /* not supported */ + else + { + if (aCtx->asn1r_elmnt_len) + asn1r_set_dec_err (aCtx, CONRESP_INVAL_RSLT); /* if constructor */ + else + { +#ifndef MMS_LITE + mmsdec_assign_rid (MMSOP_CONCLUDE); /* Assign opcode and */ + /* reserved Concl ID */ +#endif + (*mms_rsp_decode_fun [MMSOP_CONCLUDE]) (aCtx); + } + } + break; + + case MMSCNCLERR : /* Conclude Error PDU */ + if (!(mmsop_en[MMSOP_CONCLUDE] & REQ_EN)) /* protocol error if */ + asn1r_set_dec_err (aCtx, CONERR_INVAL_SERV); /* is not supported */ + else + { +#ifndef MMS_LITE + mmsdec_assign_rid (MMSOP_CONCLUDE); /* Assign opcode and */ + /* reserved Conclude ID */ +#endif + mms_err_rsp (aCtx); /* general err function */ + } + break; + + default: + asn1r_set_dec_err (aCtx, PDU_UNKNOWN_TYPE); /* Not a legal MMS PDU type. */ + } + } + else + asn1r_set_dec_err (aCtx, PDU_UNKNOWN_TYPE); /* Not a legal MMS PDU type. */ + } /* or constructor error */ + + +/************************************************************************/ +/************************************************************************/ +/* mmsdec_invoke_id */ +/* Universal class service function called when invoke ID is expected */ +/* (after first data element in most MMS confirmed services has been */ +/* decoded, and this data element is a universal). */ +/************************************************************************/ + +static ST_VOID mmsdec_invoke_id (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code) + { + if (aCtx->asn1r_constr_elmnt || id_code != INT_CODE) + asn1r_set_dec_err (aCtx, PDU_INVALID); /* not a constr or INTEGER type */ + else + { + if (asn1r_get_u32 (aCtx, &_mmsdec_rslt->id)) + { + if (_mmsdec_rslt->type == MMSREQ) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); /* not a valid 4-byte integer */ + else + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); /* not a valid 4-byte integer */ + return; + } + } + + MLOG_CDEC1 ("Invoke ID = %lu",_mmsdec_rslt->id); + + _mmsdec_rslt->dec_level = 2; /* set flag that Invoke ID is OK */ + /* setup function pointers for next */ + aCtx->asn1r_c_id_fun = mmsdec_opcode; /* next is explicit context tag */ +#ifdef MOD_SUPPORT + if (_mmsdec_rslt->type == MMSREQ)/* if MMSREQ a modifier could be next */ + aCtx->asn1r_u_id_fun = mmsdec_modlist; /* modifiers are tagged universal */ + else +#endif + aCtx->asn1r_u_id_fun = asn1r_class_err; /* no more universals */ + } + +#ifdef MOD_SUPPORT +/************************************************************************/ +/************************************************************************/ +/* mmsdec_modlist */ +/* An MMS request has been received with a modifier list present. We */ +/* change the asn1_decode_method to TAG so _ms_get_mms_modlist can decode it. */ +/* During the decode the modifier list will be attached to _mmsdec_rslt. */ +/* Upon completion of the decode we see if we can give back any unused */ +/* memory and change the decod_method back to CLASS. */ +/************************************************************************/ + +static ST_VOID mmsdec_modlist (ASN1_DEC_CTXT *aCtx, ST_UINT16 el_id) + { +#ifdef MMS_LITE +extern ST_CHAR mms_dec_modbuf []; +#endif + + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* select TAG method for get_mms_modifer*/ + + _mmsdec_rslt->mods.num_of_mods = 0; +#ifndef MMS_LITE + _mmsdec_rslt->mods.mod_list_ptr = (MODIFIER *) + chk_calloc (m_max_mods, + sizeof (MODIFIER)); +#else + _mmsdec_rslt->mods.mod_list_ptr = (MODIFIER *) mms_dec_modbuf; +#endif + _ms_get_mms_modlist (aCtx, _mmsdec_rslt->mods.mod_list_ptr, + &(_mmsdec_rslt->mods.num_of_mods), + m_max_mods, + mmsdec_modlist_done_fun); + } + +/************************************************************************/ +/************************************************************************/ +/* mmsdec_modlist_done_fun */ +/* This function is called when the modifier list has been decoded. */ +/************************************************************************/ + +static ST_VOID mmsdec_modlist_done_fun (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_decode_method = ASN1_CLASS_METHOD; /* restore the class method */ + _mmsdec_rslt->mods.info_pres = SD_TRUE; + + } +#endif + +/************************************************************************/ +/************************************************************************/ +/* mmsdec_opcode */ +/* An MMS request with good invoke ID has been detected. Next field */ +/* should be an implicit context tag which represents the opcode. */ +/* This function is called if a context class is decoded. */ +/************************************************************************/ + +static ST_VOID mmsdec_opcode (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code) + { +ST_INT operr; + +#ifndef MMS_LITE + if (id_code > MAX_MMS_OPCODE) + { /* Must be a legal MMS opcode */ + if (_mmsdec_rslt->type == MMSREQ) + asn1r_set_dec_err (aCtx, REQ_UNREC_SERV); + else + asn1r_set_dec_err (aCtx, RESP_UNREC_SERV); + return; + } +#endif + + _mmsdec_rslt->dec_level = 3; /* set flag that opcode is read OK */ + _mmsdec_rslt->op = id_code; /* save the opcode for the user */ + + MLOG_CDEC1 ("MMS Opcode = %d",_mmsdec_rslt->op); + +/* Opcode has been saved. Check that the service corresponding to this */ +/* opcode is supported and there are no parse errors. */ + + if (_mmsdec_rslt->type == MMSREQ) + { + /* pass err code */ + operr = mmsdec_chk_req_op (aCtx, _mmsdec_rslt->op,REQ_UNREC_SERV); + if (!operr) + (*mms_req_decode_fun [_mmsdec_rslt->op]) (aCtx); + } + else + { + operr = mmsdec_chk_resp_op (aCtx, _mmsdec_rslt->op); + if (!operr) + (*mms_rsp_decode_fun [_mmsdec_rslt->op]) (aCtx); + } + } + + +/************************************************************************/ +/************************************************************************/ +/* mmsdec_ucreq_opcode */ +/* An MMS unconfirmed request has been detected. Next field should be */ +/* an implicit context tag which represents the opcode. This function */ +/* is called if a context class is decoded. */ +/************************************************************************/ + +static ST_VOID mmsdec_ucreq_opcode (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code) + { + if (id_code == 0) + _mmsdec_rslt->op = MMSOP_INFO_RPT; + else if (id_code == 1) + _mmsdec_rslt->op = MMSOP_USTATUS; + else if (id_code == 2) + _mmsdec_rslt->op = MMSOP_EVENT_NOT; + else + { /* Must be a legal MMS opcode */ + asn1r_set_dec_err (aCtx, PDU_INVALID); + return; + } + + MLOG_CDEC1 ("Unconfirmed request opcode = %d",_mmsdec_rslt->op); + + _mmsdec_rslt->dec_level = 3; /* set flag that opcode is read OK */ + _mmsdec_rslt->id = UNREQ_INVOKE; + +/* Opcode has been saved. Check that the service corresponding to this */ +/* opcode is supported and there are no parse errors. */ + + if (!mmsdec_chk_req_op (aCtx, _mmsdec_rslt->op,UNCONF_UNREC_SERV)) + (*mms_req_decode_fun [_mmsdec_rslt->op]) (aCtx); /* continue decode */ + } + + +/************************************************************************/ +/* mmsdec_chk_req_op */ +/* mmsdec_chk_resp_op */ +/* This function checks whether the given opcode is supported as */ +/* request or response (or both), if the data element containing the */ +/* opcode is of the proper form (either primitive or constructor), */ +/* and if it is a NULL when it is supposed to be. The mmsop_en table */ +/* contains the opcode support information. */ +/* Returns 0 for success, else non-zero error code */ +/************************************************************************/ + +static ST_RET mmsdec_chk_req_op (ASN1_DEC_CTXT *aCtx, ST_INT opcode, ST_INT unsupp_code) + { +ST_UCHAR op_en; + +/* First check that opcode range, then whether it is enabled */ + + if ((opcode > MAX_MMSOP_DIS) || ! ((op_en = mmsop_en[opcode]) & RESP_EN)) + { + if (opcode <= MAX_MMSOP_DIS) + { + MLOG_NERR1 ("MMS service %s not supported as server (cannot decode request)", + mms_op_string[opcode]); + } + else + { + MLOG_NERR1 ("MMS service opcode %d out of range", opcode); + } + asn1r_set_dec_err (aCtx, unsupp_code); /* req not supported */ + return (MVE_REQ_NOT_SUPP); + } + else + { + if ((aCtx->asn1r_constr_elmnt && !(op_en & 0x04)) || + (!aCtx->asn1r_constr_elmnt && (op_en & 0x04)) || + (aCtx->asn1r_elmnt_len > 0 && (op_en & 0x10))) + { + asn1r_set_dec_err (aCtx, PDU_INVALID); + return (MVE_INVALID_PDU); + } + return (SD_SUCCESS); /* return success code */ + } + } + +/************************************************************************/ +static ST_RET mmsdec_chk_resp_op (ASN1_DEC_CTXT *aCtx, ST_UINT opcode) + { +ST_UCHAR op_en; + +/* First check that opcode range, then whether it is enabled */ + + if ((opcode > MAX_MMSOP_DIS) || ! ((op_en = mmsop_en[opcode]) & REQ_EN)) + { + if (opcode <= MAX_MMSOP_DIS) + { + MLOG_NERR1 ("MMS service %s not supported as client (cannot decode response)", + mms_op_string[opcode]); + } + else + { + MLOG_NERR1 ("MMS service opcode %d out of range", opcode); + } + + asn1r_set_dec_err (aCtx, RESP_UNREC_SERV); /* resp not supported */ + return (MVE_RESP_NOT_SUPP); + } + else + { + if (opcode == MMSOP_INIT_DOWNLOAD) + { +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + { + if (aCtx->asn1r_constr_elmnt || aCtx->asn1r_elmnt_len) + { + asn1r_set_dec_err (aCtx, PDU_INVALID); + return (MVE_INVALID_PDU); + } + } + else /* DIS */ + { + if (!aCtx->asn1r_constr_elmnt || !aCtx->asn1r_elmnt_len) + { + asn1r_set_dec_err (aCtx, PDU_INVALID); + return (MVE_INVALID_PDU); + } + } + } + else + { + if ((aCtx->asn1r_constr_elmnt && !(op_en & 0x08)) || + (!aCtx->asn1r_constr_elmnt && (op_en & 0x08)) || + (aCtx->asn1r_elmnt_len > 0 && (op_en & 0x20))) + { + asn1r_set_dec_err (aCtx, PDU_INVALID); + return (MVE_INVALID_PDU); + } + } + + return (SD_SUCCESS); /* return success code */ + } + } + + +/************************************************************************/ +/* mmsdec_map_err */ +/* Function to map the error codes supplied by the generic ASN.1 tools */ +/* to the MMS error codes specified for the Reject service. Inputs are */ +/* the global variables: */ +/* ST_UINT16 aCtx->asn1r_pdu_dec_err; */ +/* MMSDEC_INFO *_mmsdec_rslt; */ +/* */ +/* (A aCtx->asn1r_pdu_dec_err value of 0 should not occur and maps to UNSPECIFIED.) */ +/************************************************************************/ +static ST_VOID mmsdec_map_err (ASN1_DEC_CTXT *aCtx) + { +ST_INT level; + + level = 0; + +/* asn1_pdu_dec_err codes of NO_DECODE_ERR are OK, and codes of > 15 have been */ +/* set by the MMS decode logic and so are OK. 15 is a special number */ +/* because the lowest reject code is a 0x10(REQ_UNSPECIFIED) */ + + if (aCtx->asn1r_pdu_dec_err == NO_DECODE_ERR || aCtx->asn1r_pdu_dec_err >= REQ_UNSPECIFIED) + { + _mmsdec_rslt->err_code = aCtx->asn1r_pdu_dec_err; + } + +/* We started to decode some type of PDU and it wasn't valid. Here we */ +/* try to determine how much of the PDU we parsed and generate a */ +/* pertainent error code */ + + else + { + level = _mmsdec_rslt -> dec_level; + if (level == 0) /* did we determine it's type ? */ + _mmsdec_rslt->err_code = PDU_INVALID; + else /* if we knew it's type we */ + { /* switch to figure out more */ + switch (_mmsdec_rslt->type) + { + +/* About the only time we get here and have to do this is when the MMS */ +/* decoder temporarily turned the decode over the the ASN.1 tools (via */ +/* parse_next, parse_cstr_contents, etc) and an error was discovered. */ +/* The error the ASN.1 tools will report is <= 15. Some, most or all */ +/* of the PDU was decoded. It's not fair to just say we couldn't tell */ +/* anything at all about the PDU. */ +/* These are the rules for determining what reject class and code get */ +/* returned for the rejected PDU. The protocol for the begining of */ +/* each MMSpdu is different so almost each type has to dealt with on an */ +/* individual basis. */ + + case MMSREQ : /* request for most confirmed services */ + if (level >= 2) + _mmsdec_rslt->err_code = REQ_INVAL_ARG; + else + _mmsdec_rslt->err_code = REQ_UNSPECIFIED; + break; + + case MMSRESP : /* response for most confirmed services */ + if (level >= 2) + _mmsdec_rslt->err_code = RESP_INVAL_RSLT; + else + _mmsdec_rslt->err_code = RESP_UNSPECIFIED; + break; + + case MMSERROR : /* error for most confirmed services */ + _mmsdec_rslt->err_code = ERR_UNSPECIFIED; + break; + + case MMSUNREQ : /* request for unconfirmed services */ + _mmsdec_rslt->err_code = UNCONF_UNSPECIFIED; + break; + + case MMSREJECT : /* reject */ + _mmsdec_rslt->err_code = PDU_UNKNOWN_TYPE; + break; + + case MMSCANREQ : /* request for the Cancel service */ + _mmsdec_rslt->err_code = CANREQ_UNSPECIFIED; + break; + + case MMSCANRESP : /* response for the Cancel service */ + _mmsdec_rslt->err_code = CANRESP_UNSPECIFIED; + break; + + case MMSCANERR : /* error for Cancel service */ + _mmsdec_rslt->err_code = CANERR_UNSPECIFIED; + break; + + case MMSINITREQ : /* request for Initiate service */ + _mmsdec_rslt->err_code = REQ_BAD_VALUE; + break; + + case MMSINITRESP : /* response for Initiate service */ + _mmsdec_rslt->err_code = RESP_BAD_VALUE; + break; + + case MMSINITERR : /* error for Initiate service */ + _mmsdec_rslt->err_code = ERR_BAD_VALUE; + break; + + case MMSCNCLREQ : /* request for Conclude service */ + _mmsdec_rslt->err_code = CONREQ_UNSPECIFIED; + break; + + case MMSCNCLRESP : /* response for Conclude service */ + _mmsdec_rslt->err_code = CONRESP_UNSPECIFIED; + break; + + case MMSCNCLERR : /* error for Conclude service */ + _mmsdec_rslt->err_code = CONERR_UNSPECIFIED; + break; + + default: + _mmsdec_rslt->err_code = PDU_INVALID; + break; + } + } + } + } + +/************************************************************************/ +/* mmsdec_assign_rid */ +/* Assign a reserved invoke ID for the given service on this channel */ +/* and store it in the _mmsdec_rslt structure. Also, set the opcode for */ +/* the specified service, which must be either Initiate or Conclude */ +/* (or their error responses). */ +/************************************************************************/ + +#ifndef MMS_LITE + +static ST_VOID mmsdec_assign_rid (ST_INT opcode) + { + /* assign reserved invoke id */ + if (opcode == MMSOP_INITIATE) + _mmsdec_rslt->id = INIT_INVOKE_ID + _mmsdechan; /* for Initiate */ + else + _mmsdec_rslt->id = CONCL_INVOKE_ID + _mmsdechan; /* for Conclude */ + + _mmsdec_rslt->op = opcode; /* save the opcode */ + _mmsdec_rslt->dec_level = 3; /* opcode & invoke ID are valid */ + } + +#endif + +/************************************************************************/ +/************************************************************************/ +/* _m_get_dec_buf */ +/************************************************************************/ + +ST_VOID *_m_get_dec_buf (ASN1_DEC_CTXT *aCtx, ST_UINT size) + { + _mms_dec_info = (*m_calloc_os_fun)(1, size); + aCtx->asn1r_err_fun = _mms_dec_buf_free; + _mms_dec_info_pres = SD_TRUE; + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* select TAG method for get_mms_modifer*/ + return (_mms_dec_info); + } diff --git a/mmslib/mmsl/mmsdtext.c b/mmslib/mmsl/mmsdtext.c new file mode 100644 index 0000000..450f6a6 --- /dev/null +++ b/mmslib/mmsl/mmsdtext.c @@ -0,0 +1,729 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2004-2004 All Rights Reserved */ +/* */ +/* MODULE NAME : mmsdtext.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Functions to convert local data to text. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* ms_local_to_text */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/13/08 JRB 04 Fix fraction & add qflags in LocToTextUtc. */ +/* 09/01/04 JRB 03 Add mmsdefs.h, mms_vvar.h (don't know how */ +/* it compiled before without them). */ +/* 08/06/04 JRB 02 Cast 1-st arg in call to LocToTextUtf8. */ +/* 01/23/04 JRB 01 New. Possible replacement for sxaLocalToText.*/ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "time.h" +#include "time_str.h" +#include "mem_chk.h" +#include "mms_log.h" +#include "mmslog.h" +#include "mmsdefs.h" +#include "mms_vvar.h" /* need RUNTIME_TYPE */ + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +#define TEMP_DATA_BUF_SIZE (100*1024) +#define DATA_SEPARATOR '\n' /* newline */ + +/************************************************************************/ +/* AddString */ +/* Copy "Src" string to end of the "Dst" string. */ +/************************************************************************/ +static ST_RET AddString (ST_CHAR *Src, ST_CHAR *Dst, ST_UINT DstSize, ST_UINT *pDstLen) + { +ST_UINT tmpDstLen = *pDstLen; + /* Watch out for overrun */ + if ((tmpDstLen + strlen (Src) + 1) > DstSize) + { + MLOG_NERR0 ("Local->Text buffer overrun"); + return (SD_FAILURE); + } + + /* Add separator after each string. Later strip off last separator. */ + strcpy (&Dst[tmpDstLen],Src); + tmpDstLen += strlen (Src); + Dst[tmpDstLen++] = DATA_SEPARATOR; + *pDstLen = tmpDstLen; /* update caller's buf len */ + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextInt8 () */ +/************************************************************************/ +static ST_RET LocToTextInt8 (ST_INT8 *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { + sprintf (text,"%d", (int) *pSrc); + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextInt16 () */ +/************************************************************************/ +static ST_RET LocToTextInt16 (ST_INT16 *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { + sprintf (text,"%d",(int) *pSrc); + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextInt32 () */ +/************************************************************************/ +static ST_RET LocToTextInt32 (ST_INT32 *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { + sprintf (text,"%ld",*pSrc); + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextInt64 () */ +/************************************************************************/ +#if defined(INT64_SUPPORT) +static ST_RET LocToTextInt64 (ST_INT64 *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { +#ifdef _WIN32 + sprintf (text,"%I64d",*pSrc); +#elif defined(_AIX) || defined(__hpux) || defined(linux) || defined(sun) || defined(__LYNX) + sprintf (text,"%lld",*pSrc); +#elif (defined(__alpha) && !defined(__VMS)) + sprintf (text,"%ld",*pSrc); +#else + #error Missing INT64 code for this platform. +#endif + return (SD_SUCCESS); + } +#endif +/************************************************************************/ +/* LocToTextUint8 () */ +/************************************************************************/ +static ST_RET LocToTextUint8 (ST_UINT8 *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { + sprintf (text,"%u",(unsigned) *pSrc); + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextUint16 () */ +/************************************************************************/ +static ST_RET LocToTextUint16 (ST_UINT16 *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { + sprintf (text,"%u",(unsigned) *pSrc); + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextUint32 () */ +/************************************************************************/ +static ST_RET LocToTextUint32 (ST_UINT32 *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { + sprintf (text,"%lu",(unsigned long) *pSrc); + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextUint64 () */ +/************************************************************************/ +#if defined(INT64_SUPPORT) +static ST_RET LocToTextUint64 (ST_UINT64 *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { +#ifdef _WIN32 + sprintf (text,"%I64u", *pSrc); +#elif defined(_AIX) || defined(__hpux) || defined(linux) || defined(sun) || defined(__LYNX) + sprintf (text,"%llu", *pSrc); +#elif (defined(__alpha) && !defined(__VMS)) + sprintf (text,"%lu", *pSrc); +#else + #error Missing INT64 code for this platform. +#endif + return (SD_SUCCESS); + } +#endif +/************************************************************************/ +/* LocToTextBcd1 () */ +/************************************************************************/ +static ST_RET LocToTextBcd1 (ST_INT8 *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { + sprintf (text,"%d", (int) *pSrc); + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextBcd2 () */ +/************************************************************************/ +static ST_RET LocToTextBcd2 (ST_INT16 *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { + sprintf (text,"%d",(int) *pSrc); + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextBcd4 () */ +/************************************************************************/ +static ST_RET LocToTextBcd4 (ST_INT32 *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { + sprintf (text,"%ld",*pSrc); + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextBool () */ +/************************************************************************/ +static ST_RET LocToTextBool (ST_BOOLEAN *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { + sprintf (text,"%u",(unsigned) *pSrc); + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextFlt () */ +/************************************************************************/ +static ST_RET LocToTextFlt (ST_FLOAT *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { +#if defined(_WIN32) || defined(__QNX__) + /* 7 significant digits */ + /*gcvt((ST_DOUBLE) *pSrc, 7, text);*/ + sprintf (text, "%.4f", (ST_DOUBLE) (*pSrc)); +#else + sprintf (text, "%.7g", (ST_DOUBLE) (*pSrc)); +#endif + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextDbl () */ +/************************************************************************/ +static ST_RET LocToTextDbl (ST_DOUBLE *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { +#if defined(_WIN32) || defined(__QNX__) + /* 16 significant digits */ + gcvt(*pSrc, 16, text); +#else + sprintf (text, "%.16g", *pSrc); +#endif + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextOct */ +/************************************************************************/ +static ST_RET LocToTextOct (ST_UCHAR *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { +int i, k; +int numBytes; +ST_INT16 *sp; +ST_CHAR *destBuf; + + text[0] = 0; + numBytes = rt->u.p.el_len; + + if (numBytes < 0) /* a variable length octet string */ + { + sp = (ST_INT16 *) pSrc; + numBytes = *sp; + k=2; + } + else + k=0; + + /* We take 3 bytes per octet, make sure it fits */ + if (numBytes > TEMP_DATA_BUF_SIZE/3) + { + MLOG_NERR1 ("Octet String (%d bytes) too long to encode", numBytes); + return SD_FAILURE; + } + + destBuf = text; + for (i = 0; i < numBytes; ++i, ++k) + { + sprintf (destBuf, "%02x ", (unsigned int) pSrc[k]); + destBuf += 3; + } + + /* Eliminate the trailing space */ + *(destBuf - 1) = 0; +#ifdef WIN32 //renxiaobao mod + if(text[0]==0) strcpy(destBuf,"0"); +#endif + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextBs */ +/************************************************************************/ +static ST_RET LocToTextBs (ST_UCHAR *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { +int i; +int j; +int k; +int numBits; +ST_INT16 *sp; +ST_CHAR *destBuf; +ST_UCHAR mask; + + text[0] = 0; + numBits = rt->u.p.el_len; + +/* We take 1 dest byte per bit, make sure it fits */ + if (numBits > TEMP_DATA_BUF_SIZE-1) + { + MLOG_NERR1 ("Bit String (%d bits) too long to encode", numBits); + return (SD_FAILURE); + } + + if (numBits < 0) /* a variable length bit string */ + { + sp = (ST_INT16 *) pSrc; + numBits = *sp; + k=2; + } + else + k=0; + + destBuf = text; + for (i = 0; i < numBits; ++k) /* for each byte, while bits remain */ + { + mask = 0x80; + for (j = 0; j < 8 && i < numBits; ++i, ++j) + { + if (pSrc[k] & mask) + destBuf[i] = '1'; + else + destBuf[i] = '0'; + mask >>= 1; + } + } + destBuf[i] = 0; +#ifdef WIN32 //renxiaobao mod + if(text[0]==0) strcpy(destBuf,"0"); +#endif + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextBtime4 */ +/************************************************************************/ +static ST_RET LocToTextBtime4 (ST_INT32 *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { + if (Btime4ValsToString (text, *pSrc)) + { + MLOG_NERR0 ("Btime4 String conversion error."); + return (SD_FAILURE); + } + + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextBtime6 */ +/************************************************************************/ +static ST_RET LocToTextBtime6 (ST_INT32 *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { +ST_INT32 *pDays, *pMsec; + + pMsec = pSrc; + pDays = (pSrc+1); + if (Btime6ValsToString (text, *pDays, *pMsec)) + { + MLOG_NERR0 ("Btime6 String conversion error."); + return (SD_FAILURE); + } + + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextGtime */ +/************************************************************************/ +static ST_RET LocToTextGtime (time_t *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { + if (tstrTimeToString (*pSrc, text)) + { + MLOG_NERR0 ("Time to String conversion error"); + return (SD_FAILURE); + } + + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextUtc */ +/************************************************************************/ +#ifdef WIN32 +//void printf_utctime(char *buf,void *utctime);//lnk±àÒëɾ³ý£¬Ô­Ç°ÖóÌÐòδʹÓà +#endif +static ST_RET LocToTextUtc (MMS_UTC_TIME *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { +#ifdef WIN32 + char tmpbuf[128]; + //printf_utctime(text,pSrc); + strcpy(text, "");//lnk±àÒëÐ޸ģ¬Ô­Ç°ÖóÌÐòδʹÓà +/* sprintf (tmpbuf," %02x",pSrc->qflags);*/ /*renxiaobao ʱ¼äÆ·ÖÊ*/ +/* strcat(text,tmpbuf);*/ +#else + sprintf (text,"UTC TIME seconds=%lu, fraction=%lu, qflags=%lu", + pSrc->secs, pSrc->fraction, pSrc->qflags); +#endif + return (SD_SUCCESS); + } +/************************************************************************/ +/* LocToTextUtf8 */ +/************************************************************************/ +#ifdef WIN32 +//void utf8_convert_gb2312(char *pOut, char *pText, int pLen); //lnk±àÒëɾ³ý£¬Ô­Ç°ÖóÌÐòδʹÓà +#endif +static ST_RET LocToTextUtf8 (ST_UCHAR *pSrc, RUNTIME_TYPE *rt, ST_CHAR *text) + { +#ifdef WIN32 + int len =strlen((char *)pSrc); + //if(len) utf8_convert_gb2312(text,(char *)pSrc,len);//lnk±àÒëÐ޸ģ¬Ô­Ç°ÖóÌÐòδʹÓà + if (len) { + memcpy(text, pSrc, len); + text[len] = 0; + } + else strcpy(text," "); + return (SD_SUCCESS); +#endif + sprintf (text,"UTF8string: can't display"); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* ms_local_to_text */ +/* NOTE: tmpBuf is passed to most "LocToText.." static functions. These */ +/* functions must NOT write past end of tmpBuf. */ +/************************************************************************/ + +ST_CHAR *ms_local_to_text (ST_CHAR *datptr, SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num, + ST_CHAR *textBuf, ST_UINT textBufSize) + { +RUNTIME_TYPE *rt_ptr; +RUNTIME_TYPE *rt_end; +ST_RET uDataRet; +ST_INT arr_loop_level,total_len; +ST_INT arr_loops[ASN1_MAX_LEVEL]; +ST_CHAR *ret_ptr; +static ST_CHAR tmpBuf[TEMP_DATA_BUF_SIZE]; +ST_UINT nStrLen = 0; /* Current text total length */ + + + tmpBuf[0] = 0;/*renxiaobao add*/ + + nStrLen = 0; + + arr_loop_level = 0; + + rt_ptr = (RUNTIME_TYPE *) rt_head; /* point to head rt_block */ + rt_end = rt_ptr + rt_num; /* done when pointer is here */ + + uDataRet = SD_SUCCESS; + while (rt_ptr < rt_end && uDataRet == SD_SUCCESS) + { + if (rt_ptr->el_tag == RT_ARR_END) /* treat case of array ending */ + { + if (--arr_loops[arr_loop_level] > 0) /* if need to do next ar elmnt */ + rt_ptr -= rt_ptr->u.arr.num_rt_blks; /* mv rt_ptr to start of arr */ + else + --arr_loop_level; + } + if (rt_ptr->el_tag == RT_ARR_START) /* treat case of array starting */ + { + /* initialize the loop counter for the array */ + ++arr_loop_level; + arr_loops[arr_loop_level] = rt_ptr->u.arr.num_elmnts; + } + + switch (rt_ptr->el_tag) + { + case RT_ARR_START : + break; /* do nothing */ + + case RT_ARR_END : /* array done */ + break; /* do nothing */ + + case RT_STR_START : + uDataRet = AddString ("{", textBuf, textBufSize, &nStrLen); + break; + + case RT_STR_END : /* structure done */ + uDataRet = AddString ("}", textBuf, textBufSize, &nStrLen); + break; + + case RT_BOOL : + uDataRet = LocToTextBool ((ST_BOOLEAN *) datptr, rt_ptr, tmpBuf); + if (uDataRet==SD_SUCCESS) /* If converted OK, add to working text*/ + uDataRet = AddString (tmpBuf, textBuf, textBufSize, &nStrLen); + break; + + case RT_BIT_STRING : + uDataRet = LocToTextBs ((ST_UCHAR *) datptr, rt_ptr, tmpBuf); + if (uDataRet==SD_SUCCESS) /* If converted OK, add to working text*/ + uDataRet = AddString (tmpBuf, textBuf, textBufSize, &nStrLen); + break; + + case RT_INTEGER : + switch (rt_ptr->u.p.el_len) /* determine length */ + { + case 1 : /* one byte int */ + uDataRet = LocToTextInt8 ((ST_INT8 *) datptr, rt_ptr, tmpBuf); + break; + + case 2 : /* two byte int */ + uDataRet = LocToTextInt16 ((ST_INT16 *) datptr, rt_ptr, tmpBuf); + break; + + case 4 : /* four byte integer */ + uDataRet = LocToTextInt32 ((ST_INT32 *) datptr, rt_ptr, tmpBuf); + break; + +#ifdef INT64_SUPPORT + case 8 : /* eight byte integer */ + uDataRet = LocToTextInt64 ((ST_INT64 *) datptr, rt_ptr, tmpBuf); + break; +#endif + default: + uDataRet = SD_FAILURE; + break; + } + if (uDataRet==SD_SUCCESS) /* If converted OK, add to working text*/ + uDataRet = AddString (tmpBuf, textBuf, textBufSize, &nStrLen); + break; + + case RT_UNSIGNED : + switch (rt_ptr->u.p.el_len) /* determine length */ + { + case 1 : /* one byte int */ + uDataRet = LocToTextUint8 ((ST_UCHAR *) datptr, rt_ptr, tmpBuf); + break; + + case 2 : /* two byte int */ + uDataRet = LocToTextUint16 ((ST_UINT16 *) datptr, rt_ptr, tmpBuf); + break; + + case 4 : /* four byte integer */ + uDataRet = LocToTextUint32 ((ST_UINT32 *) datptr, rt_ptr, tmpBuf); + break; + +#ifdef INT64_SUPPORT + case 8 : /* eight byte integer */ + uDataRet = LocToTextUint64 ((ST_UINT64 *) datptr, rt_ptr, tmpBuf); + break; +#endif /* INT64_SUPPORT */ + default: + uDataRet = SD_FAILURE; + break; + } + if (uDataRet==SD_SUCCESS) /* If converted OK, add to working text*/ + uDataRet = AddString (tmpBuf, textBuf, textBufSize, &nStrLen); + break; + +#ifdef FLOAT_DATA_SUPPORT + case RT_FLOATING_POINT : + if (rt_ptr->u.p.el_len != sizeof (ST_FLOAT)) + uDataRet = LocToTextDbl ((ST_DOUBLE *) datptr, rt_ptr, tmpBuf); + else + uDataRet = LocToTextFlt ((ST_FLOAT *) datptr, rt_ptr, tmpBuf); + if (uDataRet==SD_SUCCESS) /* If converted OK, add to working text*/ + uDataRet = AddString (tmpBuf, textBuf, textBufSize, &nStrLen); + break; +#endif + + case RT_OCTET_STRING : + uDataRet = LocToTextOct ((ST_UCHAR *) datptr, rt_ptr, tmpBuf); + if (uDataRet==SD_SUCCESS) /* If converted OK, add to working text*/ + uDataRet = AddString (tmpBuf, textBuf, textBufSize, &nStrLen); + break; + + case RT_VISIBLE_STRING : /* No conversion needed. Just add to working text*/ + #ifdef WIN32 //renxiaobao mod + if(datptr[0]==0) uDataRet = AddString (" ", textBuf, textBufSize, &nStrLen); + else + #endif + uDataRet = AddString (datptr, textBuf, textBufSize, &nStrLen); + break; + +#ifdef TIME_DATA_SUPPORT + case RT_GENERAL_TIME : + uDataRet = LocToTextGtime ((time_t *) datptr, rt_ptr, tmpBuf); + if (uDataRet==SD_SUCCESS) /* If converted OK, add to working text*/ + uDataRet = AddString (tmpBuf, textBuf, textBufSize, &nStrLen); + break; +#endif + +#ifdef BTOD_DATA_SUPPORT + case RT_BINARY_TIME : + switch (rt_ptr->u.p.el_len) /* determine length */ + { + case 4: + uDataRet = LocToTextBtime4 ((ST_INT32 *) datptr, rt_ptr, tmpBuf); + break; + case 6: + uDataRet = LocToTextBtime6 ((ST_INT32 *) datptr, rt_ptr, tmpBuf); + break; + default: + uDataRet = SD_FAILURE; + break; + } + if (uDataRet==SD_SUCCESS) /* If converted OK, add to working text*/ + uDataRet = AddString (tmpBuf, textBuf, textBufSize, &nStrLen); + break; +#endif + + case RT_BCD : + if (rt_ptr->u.p.el_len <= 2) + uDataRet = LocToTextBcd1 ((ST_INT8 *) datptr, rt_ptr, tmpBuf); + else if (rt_ptr->u.p.el_len <= 4) + uDataRet = LocToTextBcd2 ((ST_INT16 *) datptr, rt_ptr, tmpBuf); + else if (rt_ptr->u.p.el_len <= 8) + uDataRet = LocToTextBcd4 ((ST_INT32 *) datptr, rt_ptr, tmpBuf); + else + uDataRet = SD_FAILURE; + if (uDataRet==SD_SUCCESS) /* If converted OK, add to working text*/ + uDataRet = AddString (tmpBuf, textBuf, textBufSize, &nStrLen); + break; + + case RT_UTC_TIME : + uDataRet = LocToTextUtc ((MMS_UTC_TIME *) datptr, rt_ptr, tmpBuf); + if (uDataRet==SD_SUCCESS) /* If converted OK, add to working text*/ + uDataRet = AddString (tmpBuf, textBuf, textBufSize, &nStrLen); + break; + + case RT_UTF8_STRING : + uDataRet = LocToTextUtf8 ((ST_UCHAR *) datptr, rt_ptr, tmpBuf); + if (uDataRet==SD_SUCCESS) /* If converted OK, add to working text*/ + uDataRet = AddString (tmpBuf, textBuf, textBufSize, &nStrLen); + break; + + default : /* should not be any other tag */ + MLOG_ERR1 ("Invalid tag: %d", (int) rt_ptr->el_tag); + uDataRet = SD_FAILURE; + break; + } + if(strlen (tmpBuf)>sizeof (tmpBuf)) + { + total_len = strlen (tmpBuf); + } + assert (strlen (tmpBuf) < sizeof (tmpBuf)); /* Must not exceed buffer*/ + + datptr += rt_ptr->el_size; /* Adjust data pointer */ + rt_ptr++; /* point to next rt element */ + } + + assert (nStrLen <= textBufSize); /* checked in AddString so this should never fail*/ + if (uDataRet) + ret_ptr = NULL; + else + { + textBuf [--nStrLen] = '\0'; /* replace last '\n' with '\0' */ + ret_ptr = textBuf; + } + return (ret_ptr); + } +#if defined(WIN32) +char *va_data_to_text (char **va_data,RUNTIME_TYPE **rt_head, RUNTIME_TYPE *rt_end,int read_num) +{ + static char ret_text[128]; + static char ret_text_buf[12800]; + RUNTIME_TYPE *rt_ptr; + char *datptr,done; + ST_RET uDataRet; + static int arr_loop_level; + static int arr_loops[ASN1_MAX_LEVEL]; + + + rt_ptr = *rt_head; + datptr = *va_data; + ret_text_buf[0] = 0; + ret_text[0] = 0; + if(read_num==0) arr_loop_level = 0; + done = 0; + while(rt_ptrel_tag == RT_ARR_END) + { + if(--arr_loops[arr_loop_level] > 0) rt_ptr -= rt_ptr->u.arr.num_rt_blks; + else --arr_loop_level; + } + if (rt_ptr->el_tag == RT_ARR_START) + { + ++arr_loop_level;arr_loops[arr_loop_level] = rt_ptr->u.arr.num_elmnts; + } + switch (rt_ptr->el_tag) + { + case RT_ARR_START : break; + case RT_ARR_END : break; + case RT_STR_START : break; + case RT_STR_END : break; + case RT_BOOL : + uDataRet = LocToTextBool ((ST_BOOLEAN *)datptr, rt_ptr, ret_text); + done = 1; + break; + case RT_BIT_STRING : + uDataRet = LocToTextBs ((ST_UCHAR *) datptr, rt_ptr, ret_text); + done = 1; + break; + case RT_INTEGER : + if (rt_ptr->u.p.el_len==1) uDataRet = LocToTextInt8 ((ST_INT8 *) datptr, rt_ptr, ret_text); + else if(rt_ptr->u.p.el_len==2) uDataRet = LocToTextInt16((ST_INT16 *) datptr, rt_ptr, ret_text); + else if(rt_ptr->u.p.el_len==4) uDataRet = LocToTextInt32((ST_INT32 *) datptr, rt_ptr, ret_text); + done = 1; + break; + case RT_UNSIGNED : + if (rt_ptr->u.p.el_len==1) uDataRet = LocToTextUint8 ((ST_UINT8 *) datptr, rt_ptr, ret_text); + else if(rt_ptr->u.p.el_len==2) uDataRet = LocToTextUint16((ST_UINT16 *) datptr, rt_ptr, ret_text); + else if(rt_ptr->u.p.el_len==4) uDataRet = LocToTextUint32((ST_UINT32 *) datptr, rt_ptr, ret_text); + done = 1; + break; + case RT_FLOATING_POINT : + if (rt_ptr->u.p.el_len != sizeof (ST_FLOAT)) + uDataRet = LocToTextDbl ((ST_DOUBLE *) datptr, rt_ptr, ret_text); + else + uDataRet = LocToTextFlt ((ST_FLOAT *) datptr, rt_ptr, ret_text); + done = 1; + break; + case RT_OCTET_STRING : + uDataRet = LocToTextOct ((ST_UCHAR *) datptr, rt_ptr, ret_text); + done = 1; + break; + case RT_VISIBLE_STRING : + strcpy(ret_text,datptr); + done = 1; + break; + case RT_GENERAL_TIME : + uDataRet = LocToTextGtime ((time_t *) datptr, rt_ptr, ret_text); + done = 1; + break; + case RT_BINARY_TIME : + if (rt_ptr->u.p.el_len==4) LocToTextBtime4 ((ST_INT32 *) datptr, rt_ptr, ret_text); + else if(rt_ptr->u.p.el_len==6) LocToTextBtime6 ((ST_INT32 *) datptr, rt_ptr, ret_text); + done = 1; + break; + case RT_BCD : + if(rt_ptr->u.p.el_len <= 2) + uDataRet = LocToTextBcd1 ((ST_INT8 *) datptr, rt_ptr, ret_text); + else if (rt_ptr->u.p.el_len <= 4) + uDataRet = LocToTextBcd2 ((ST_INT16 *) datptr, rt_ptr, ret_text); + else if (rt_ptr->u.p.el_len <= 8) + uDataRet = LocToTextBcd4 ((ST_INT32 *) datptr, rt_ptr, ret_text); + done = 1; + break; + case RT_UTC_TIME : + uDataRet = LocToTextUtc ((MMS_UTC_TIME *) datptr, rt_ptr, ret_text); + done = 1; + break; + case RT_UTF8_STRING : + uDataRet = LocToTextUtf8 ((ST_UCHAR *) datptr, rt_ptr, ret_text); + done = 1; + break; + default : + break; + } + datptr += rt_ptr->el_size; + rt_ptr++; + if(done) strcat(ret_text_buf,ret_text); + if((read_num>=0)&&(done)) break; + done=0; + } + *rt_head=rt_ptr; + *va_data=datptr; + return ret_text_buf; +} +#endif diff --git a/mmslib/mmsl/mmsinit.c b/mmslib/mmsl/mmsinit.c new file mode 100644 index 0000000..71029b1 --- /dev/null +++ b/mmslib/mmsl/mmsinit.c @@ -0,0 +1,587 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsinit.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the common functions to decode and encode */ +/* an initiate operation. Note that the initiate request and the */ +/* initiate response are the same. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/31/03 JRB 06 Support MMS Version2. */ +/* asn1r_get_bitstr: add max_bits arg. */ +/* If received bitstr too long, truncate. */ +/* If received bitstr too short, set missing bits=0*/ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 12/10/97 MDE 02 Chaned max_nest to ST_INT8 */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pcon.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +#define MMS_V0_PARAM_SUPP_BITS 7 /* DIS */ +#define MMS_V1_PARAM_SUPP_BITS 11 +#define MMS_V1_SERV_SUPP_BITS 85 +/************************************************************************/ + +static INIT_INFO *info; + +#ifdef CS_SUPPORT +static CS_INIT_INFO *cs_info; +static ST_UCHAR *init_detail_start; +#endif + +static ST_BOOLEAN request; /* req/resp flag */ +static ST_RET val_err; /* asn1_set_dec_err code for bad value */ + + +/************************************************************************/ +/* static functions in this module */ +static ST_VOID get_maxseg (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_maxreq_calling (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_maxreq_called (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_max_nest (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_detail_seq (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_version (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_param_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_param_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_param_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_services_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_services_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_services_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID mms_detail_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID init_seq_done (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/************************************************************************/ +/* _mms_init_dec */ +/* This function is called from mmsdec.c when an initiate (req or resp) */ +/* is being decoded. We are in the InitiatePDU sequence. */ +/* Allocate an operation specific structure and set up to get either */ +/* the segment size or the max outstanding calling */ +/************************************************************************/ + +ST_VOID _mms_init_dec (ASN1_DEC_CTXT *aCtx, ST_BOOLEAN req) + { + request = req; /* save the request flag */ + if (request) + val_err = REQ_BAD_VALUE; + else + val_err = RESP_BAD_VALUE; + +/* Create an init_info structure data area to put the decoded info into.*/ + + + /* CRITICAL: "info" struct must be calloc'd, so if received bitstrings + * are too short, the missing bits=0. + */ +#ifdef CS_SUPPORT + if (_mmsdec_ctxt == MMS_PCI) + info = (INIT_INFO *) _m_get_dec_buf (aCtx, sizeof (INIT_INFO)); + else + cs_info = (CS_INIT_INFO *) _m_get_dec_buf (aCtx, sizeof (CS_INIT_INFO)); +#else + info = (INIT_INFO *) _m_get_dec_buf (aCtx, sizeof (INIT_INFO)); +#endif + + ASN1R_TAG_ADD (aCtx, CTX,0,get_maxseg); /* max seg size (opt) */ + ASN1R_TAG_ADD (aCtx, CTX,1,get_maxreq_calling); /* max outstdg calling */ + } + + +/************************************************************************/ +/* get_maxseg */ +/* The max_msgsegsize parameter has been encountered. Read its value. */ +/************************************************************************/ + +static ST_VOID get_maxseg (ASN1_DEC_CTXT *aCtx) + { +ST_INT32 local_detail; + + MLOG_CDEC0 ("get_maxseg"); + + if (asn1r_get_i32 (aCtx, &local_detail) || local_detail < 0) + { + if (request) + asn1r_set_dec_err (aCtx, REQ_INVAL_ARG); + else + asn1r_set_dec_err (aCtx, RESP_INVAL_RSLT); + } + else + { +#ifdef CS_SUPPORT + if (_mmsdec_ctxt == MMS_PCI) + { + info->max_segsize_pres = SD_TRUE; /* set present flag for segsize */ + info->max_segsize = local_detail; + } + else + { + cs_info->local_detail_pres = SD_TRUE; /* set present flag */ + cs_info->local_detail = local_detail; + } +#else + info->max_segsize_pres = SD_TRUE; /* set present flag for segsize */ + info->max_segsize = local_detail; +#endif + ASN1R_TAG_ADD (aCtx, CTX,1,get_maxreq_calling); + } + } + +/************************************************************************/ +/* get_maxreq_calling */ +/* proposed/negiotiated max outstanding calling encountered */ +/************************************************************************/ + +static ST_VOID get_maxreq_calling (ASN1_DEC_CTXT *aCtx) + { +ST_INT16 maxreq_calling; + + MLOG_CDEC0 ("get_maxreq_calling"); + +/* Get the value of the maxreq_calling parameter. */ + + if (asn1r_get_i16 (aCtx, &maxreq_calling)) + asn1r_set_dec_err (aCtx, val_err); + +#ifdef CS_SUPPORT + if (_mmsdec_ctxt == MMS_PCI) + info->maxreq_calling = maxreq_calling; + else + cs_info->maxreq_calling = maxreq_calling; +#else + info->maxreq_calling = maxreq_calling; +#endif + +/* The next data element is the maxreq_called parameter. */ + + ASN1R_TAG_ADD (aCtx, CTX,2,get_maxreq_called); + } + +/************************************************************************/ +/* get_maxreq_called */ +/* proposed/negiotiated max outstanding called encountered */ +/************************************************************************/ + +static ST_VOID get_maxreq_called (ASN1_DEC_CTXT *aCtx) + { +ST_INT16 maxreq_called; + + MLOG_CDEC0 ("get_maxreq_called"); + +/* Get the value of the maxreq_called parameter. */ + + if (asn1r_get_i16 (aCtx, &maxreq_called)) + asn1r_set_dec_err (aCtx, val_err); + +#ifdef CS_SUPPORT + if (_mmsdec_ctxt == MMS_PCI) + info->maxreq_called = maxreq_called; + else + cs_info->maxreq_called = maxreq_called; +#else + info->maxreq_called = maxreq_called; +#endif + +/* The next data element is either the max_nest parameter (optional) or */ +/* the initiate detail sequence or the CS detail. */ +/* All are optional, so we could be done */ + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = init_seq_done; + ASN1R_TAG_ADD (aCtx, CTX,3,get_max_nest); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,4,get_detail_seq); + } + +/************************************************************************/ +/* get_max_nest */ +/* The max_nest parameter has been encountered. Read its value. */ +/************************************************************************/ + +static ST_VOID get_max_nest (ASN1_DEC_CTXT *aCtx) + { +ST_INT8 max_nest; + + MLOG_CDEC0 ("get_max_nest"); + +/* Get the value of the max_nest parameter. */ + + if (asn1r_get_i8 (aCtx, &max_nest)) + asn1r_set_dec_err (aCtx, val_err); + else + { +#ifdef CS_SUPPORT + if (_mmsdec_ctxt == MMS_PCI) + { + info->max_nest_pres = SD_TRUE; + info->max_nest = max_nest; + } + else + { + cs_info->max_nest_pres = SD_TRUE; + cs_info->max_nest = max_nest; + /* Initiate detail sequence may be next, or CS detail */ + init_detail_start = aCtx->asn1r_field_ptr; + } +#else + info->max_nest_pres = SD_TRUE; + info->max_nest = max_nest; +#endif + } + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,4,get_detail_seq); + } + +/************************************************************************/ +/* get_detail_seq */ +/* The mms init detail sequence is now starting, first is version # */ +/************************************************************************/ + +static ST_VOID get_detail_seq (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_detail_seq"); + +/* Check if decoding an MMS CORE Initiate or a CS Initiate */ + +#ifdef CS_SUPPORT + if (_mmsdec_ctxt == MMS_PCI) + { + info->mms_detail_pres = SD_TRUE; /* set detail present flag */ + ASN1R_TAG_ADD (aCtx, CTX,0,get_version); /* Next comes version */ + } + else /* Companion Standard Initiate, accept sequence */ + asn1r_parse_cstr_contents (aCtx, mms_detail_cstr_done); +#else + info->mms_detail_pres = SD_TRUE; /* set detail present flag */ + ASN1R_TAG_ADD (aCtx, CTX,0,get_version); /* Next comes version */ +#endif + } + +/************************************************************************/ +/* get_version */ +/* The mms init detail sequence is now starting, this is version # */ +/************************************************************************/ + +static ST_VOID get_version (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_version"); + +/* Get the value of the max_nest parameter. */ + + if (asn1r_get_i16 (aCtx, &info->version) || info->version <0) + asn1r_set_dec_err (aCtx, val_err); + +/* Next is parameter support options, a 6 bit bitstring (prim or cstr) */ + + ASN1R_TAG_ADD (aCtx, CTX,1,get_param_prim); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_param_cstr); + } + + +/************************************************************************/ +/* get_param_prim */ +/* The parameter support BS has been encountered as a primitive data */ +/* element. Read its value. */ +/************************************************************************/ + +static ST_VOID get_param_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_param_prim"); + + /* NOTE: decode only the bits we recognize. + * For version0 (DIS) should get 7 bits. + * For version1 (IS) should get 11 bits. + * For version2 and higher, may get more than 11, but we ignore the + * higher bits because we don't support them. + */ + if (!asn1r_get_bitstr (aCtx, info->param_supp, MMS_V1_PARAM_SUPP_BITS)) + get_param_done (aCtx); /* set up for the next data element */ + else + asn1r_set_dec_err (aCtx, val_err); + } + +/************************************************************************/ +/* get_param_cstr */ +/* The parameter suport has been encountered as a constructor data */ +/* element. Read its value. */ +/************************************************************************/ + +static ST_VOID get_param_cstr (ASN1_DEC_CTXT *aCtx) + { + + MLOG_CDEC0 ("get_param_cstr"); + +/* Set up to call this function when done with constructor bitstring. */ + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = get_param_done; + +/* Get the value of the parameter support. For constructor */ +/* bitstrings, this requires returning and letting the ASN.1 tools */ +/* parse it to any nesting level. */ + + asn1r_get_bitstr_cstr (aCtx, MMS_V1_PARAM_SUPP_BITS,info->param_supp); + } + +/************************************************************************/ +/* get_param_done */ +/* Function called after the supported parameter has been parsed. */ +/************************************************************************/ + +static ST_VOID get_param_done (ASN1_DEC_CTXT *aCtx) + { + + MLOG_CDEC0 ("get_param_done"); + + ASN1R_TAG_ADD (aCtx, CTX,2,get_services_prim); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_services_cstr); + } + +/************************************************************************/ +/* get_services_prim */ +/* The services support BS has been encountered as a primitive data */ +/* element. Read its value. */ +/************************************************************************/ + +static ST_VOID get_services_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_services_prim"); + + /* NOTE: decode only the bits we recognize. + * For version0 (DIS) and version1 (IS) should get 85 bits. + * For version2 and higher, may get more than 85, but we ignore the + * higher bits because we don't support them. + */ + if (!asn1r_get_bitstr (aCtx, info->serv_supp, MMS_V1_SERV_SUPP_BITS)) + get_services_done (aCtx); /* set up for the next data element */ + else + asn1r_set_dec_err (aCtx, val_err); + } + +/************************************************************************/ +/* get_services_cstr */ +/* The service suport BS has been encountered as a constructor data */ +/* element. Read its value. */ +/************************************************************************/ + +static ST_VOID get_services_cstr (ASN1_DEC_CTXT *aCtx) + { + + MLOG_CDEC0 ("get_services_cstr"); + +/* Set up to call this function when done with constructor bitstring. */ + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = get_services_done; + +/* Get the value of the service support. For constructor */ +/* bitstrings, this requires returning and letting the ASN.1 tools */ +/* parse it to any nesting level. */ + + asn1r_get_bitstr_cstr (aCtx, MMS_V1_SERV_SUPP_BITS,info->serv_supp); + } + +/************************************************************************/ +/* get_services_done */ +/* Function called when entire mms_detail constructor is done */ +/************************************************************************/ + +static ST_VOID get_services_done (ASN1_DEC_CTXT *aCtx) + { + + MLOG_CDEC0 ("get_services_done"); + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = mms_detail_cstr_done; + } + +/************************************************************************/ +/* mms_detail_cstr_done */ +/* Function called when entire mms_detail constructor is done */ +/************************************************************************/ + +static ST_VOID mms_detail_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("mms_detail_cstr_done"); + +#ifdef CS_SUPPORT + if (_mmsdec_ctxt != MMS_PCI) + { + cs_info->init_detail_len = aCtx->asn1r_field_ptr - init_detail_start; + cs_info->init_detail = init_detail_start; + } +#endif + } + +/************************************************************************/ +/* init_seq_done */ +/* The parse of the Initiate PDU is complete, either with or without */ +/* CS detail. Just set decode done flag. */ +/************************************************************************/ + +static ST_VOID init_seq_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("init_seq_done"); + + aCtx->asn1r_decode_done = SD_TRUE; + aCtx->asn1r_decode_done_fun = _mms_dec_done_ok; + } + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_init */ +/* Function to construct an Initiate request or response PDU in the */ +/* selected buffer. Pass a pointer to the end of the build buffer, and */ +/* a pointer to a structure of type init_info that contains the build */ +/* control and data information. Returns a pointer to the first byte */ +/* of the encoded message. */ +/************************************************************************/ + +ST_UCHAR *_ms_mk_init (ASN1_ENC_CTXT *aCtx, ST_UCHAR *buf_ptr, ST_INT buf_len, + INIT_INFO *info_ptr, ST_INT pdutype, + ST_BOOLEAN cs_init) + { +#ifdef DEBUG_SISCO +ST_UCHAR *msg_start; /* These variables used for */ +ST_INT msg_len; /* debug print only. */ +#endif +#ifdef CS_SUPPORT +CS_INIT_INFO *cs_init_ptr; +#endif + + asn1r_strt_asn1_bld (aCtx, buf_ptr,buf_len); /* Initialize the ASN.1 tools */ + +#ifdef CS_SUPPORT + if (cs_init) /* COMPANION STANDARD INITIATE PDU */ + { + cs_init_ptr = (CS_INIT_INFO *) info_ptr; + +/* write the CS init detail constructor */ + asn1r_strt_constr (aCtx); /* start the CTX 5 cstr */ + asn1r_wr_octstr (aCtx, cs_init_ptr->init_detail,cs_init_ptr->init_detail_len); + asn1r_fin_constr (aCtx, 4,CTX,DEF); /* close the CS detail cstr */ + +/* maximum data nesting (optional) */ + if (cs_init_ptr->max_nest_pres) /* if desired to send - */ + { + asn1r_wr_i8 (aCtx, (ST_CHAR)cs_init_ptr->max_nest); + asn1r_fin_prim (aCtx, 3,CTX); /* context-specific, tag 2 */ + } + +/* max outstanding requests from called MMS-user */ + asn1r_wr_i16 (aCtx, cs_init_ptr->maxreq_called); + asn1r_fin_prim (aCtx, 2,CTX); /* context-specific, tag 2 */ + +/* max outstanding requests from calling MMS-user */ + asn1r_wr_i16 (aCtx, cs_init_ptr->maxreq_calling); + asn1r_fin_prim (aCtx, 1,CTX); /* context-specific, tag 1 */ + +/* max segment size (optional) */ + if (cs_init_ptr->local_detail_pres) /* if enabled */ + { + asn1r_wr_i32 (aCtx, cs_init_ptr->local_detail); + asn1r_fin_prim (aCtx, 0,CTX); /* context-specific, tag 0 */ + } + } + else /* MMS CORE INITIATE PDU */ + { +#endif +/* Now begin writing primitive data elements from back of PDU to front. */ + +/* write the mms init detail constructor, if enabled */ + if (info_ptr->mms_detail_pres) /* if we have MMS detail */ + { + asn1r_strt_constr (aCtx); + asn1r_wr_bitstr (aCtx, info_ptr->serv_supp,MMS_V1_SERV_SUPP_BITS); /* services supported BS */ + asn1r_fin_prim (aCtx, 2,CTX); /* context-specific, tag 2 */ + +/* parameters supported BS, write either 7 (DIS) or 11 (IS) bits */ + if (info_ptr->version == 0) /* If DIS is being proposed */ + { + asn1r_wr_bitstr (aCtx, info_ptr->param_supp,MMS_V0_PARAM_SUPP_BITS); + asn1r_fin_prim (aCtx, 1,CTX); + } + else /* IS is being proposed */ + { + asn1r_wr_bitstr (aCtx, info_ptr->param_supp,MMS_V1_PARAM_SUPP_BITS); + asn1r_fin_prim (aCtx, 1,CTX); /* context-specific, tag 1 */ + } + + asn1r_wr_i16 (aCtx, info_ptr->version); /* version number */ + asn1r_fin_prim (aCtx, 0,CTX); /* context-specific, tag 0 */ + + asn1r_fin_constr (aCtx, 4,CTX,DEF); /* close the MMS detail cstr */ + } + +/* Now write the core initiate parameters */ + +/* maximum data nesting (optional) */ + if (info_ptr->max_nest_pres) /* if desired to send - */ + { + asn1r_wr_i8 (aCtx, (ST_CHAR)info_ptr->max_nest); + asn1r_fin_prim (aCtx, 3,CTX); /* context-specific, tag 2 */ + } + +/* max outstanding requests from called MMS-user */ + asn1r_wr_i16 (aCtx, info_ptr->maxreq_called); + asn1r_fin_prim (aCtx, 2,CTX); /* context-specific, tag 2 */ + +/* max outstanding requests from calling MMS-user */ + asn1r_wr_i16 (aCtx, info_ptr->maxreq_calling); + asn1r_fin_prim (aCtx, 1,CTX); /* context-specific, tag 1 */ + +/* max segment size (optional) */ + if (info_ptr->max_segsize_pres) /* if enabled */ + { + asn1r_wr_i32 (aCtx, info_ptr->max_segsize); + asn1r_fin_prim (aCtx, 0,CTX); /* context-specific, tag 0 */ + } +#ifdef CS_SUPPORT + } +#endif + +/* Close the PDU. Building of either the request or response message */ +/* is complete. */ + +#ifdef DEBUG_SISCO + asn1r_fin_constr (aCtx, (ST_UINT16) pdutype,CTX,DEF); + msg_start = aCtx->asn1r_field_ptr + 1; + msg_len = (buf_ptr + buf_len) - msg_start; + + MLOG_ENC2 ("INITIATE %s built, len = %d", + pdutype == MMSINITREQ ? "request" : "response", + msg_len); + MLOG_ENCH (msg_len,msg_start); + MLOG_PAUSEENC (NULL); + + return (msg_start); +#else + asn1r_fin_constr (aCtx, (ST_UINT16) pdutype,CTX,DEF); + return (aCtx->asn1r_field_ptr + 1); +#endif + } diff --git a/mmslib/mmsl/mmsl_fin.c b/mmslib/mmsl/mmsl_fin.c new file mode 100644 index 0000000..8569e04 --- /dev/null +++ b/mmslib/mmsl/mmsl_fin.c @@ -0,0 +1,355 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsl_fin.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains common functions used to finish various */ +/* types of MMS PDU's */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* ST_INT16 mms_fin_null_resp (invoke_id,opcode) */ +/* ST_INT16 mms_fin_null_req (opcode) */ +/* ST_INT16 mms_resp_fin (opcode,invoke_id,mk_fun,info_ptr) */ +/* ST_INT16 mms_req_fin (opcode,mk_ptr,info_ptr) */ +/* ST_INT16 mms_unconf_req_fin (opcode,mk_ptr,info_ptr) */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/18/07 MDE 13 Fixed request log mask */ +/* 11/12/07 MDE 12 Pass MMSOP_READ to logging when usr handled */ +/* 04/09/07 MDE 11 Enhanced filtered logging */ +/* 03/11/04 GLB 10 Remove "thisFileName" */ +/* 12/12/02 JRB 09 _mms_unconf_req_fin: Add ASN1_ENC_CTXT arg, */ +/* do NOT call asn1r_strt_asn1_bld, do NOT set */ +/* global vars "mmsl_msg_*". */ +/* 04/08/02 MDE 08 Added log function pointers */ +/* 04/05/02 MDE 07 Cleaned up MMS Lite use of MLOG */ +/* 01/18/02 JRB 06 Del _ms_fin_pdu_debug. Use new _ms_fin_pdu */ +/* and _ms_fin_pdu_log (in mms_ced.c). */ +/* 01/02/02 JRB 05 Converted to use ASN1R. */ +/* Add ASN1_DEC_CTXT to (*mk_fun) calls in */ +/* mms_req_fin, mms_resp_fin, mms_unconf_req_fin*/ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 03/20/98 JRB 02 Don't need mmsop_en.h anymore. */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mloguser.h" +#include "mvl_defs.h" +#include "mvl_log.h" +#include "asn1defs.h" + +/************************************************************************/ +/************************************************************************/ + +ST_VOID (*ml_log_req_info_fun) (ST_INT invokeId, ST_INT op, ST_VOID *info); +ST_VOID (*ml_log_ind_info_fun) (ST_INT invokeId, ST_INT op, ST_VOID *info); + +ST_VOID (*ml_log_resp_info_fun) (ST_INT invokeId, ST_INT op, ST_VOID *info); +ST_VOID (*ml_log_conf_info_fun) (ST_INT invokeId, ST_INT op, ST_VOID *info); + +ST_VOID (*ml_log_unsol_req_info_fun) (ST_INT op, ST_VOID *info); +ST_VOID (*ml_log_unsol_ind_info_fun) (ST_INT op, ST_VOID *info); + +ST_VOID (*ml_log_error_conf_fun) (ST_INT invokeId, ST_VOID *info); +ST_VOID (*ml_log_error_resp_fun) (ST_INT invokeId, ST_VOID *info); + +ST_VOID (*ml_log_reject_send_fun) (ST_VOID *info); +ST_VOID (*ml_log_reject_recv_fun) (ST_VOID *info); + +/************************************************************************/ +/************************************************************************/ +/* GENERAL PDU FINISH FUNCTIONS */ +/************************************************************************/ +/* mms_fin_null_resp */ +/* general NULL response function, used for prim NULL responses */ +/************************************************************************/ + +ST_RET _mms_fin_null_resp (ST_UINT32 invoke_id, ST_INT opcode) + { +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + asn1r_strt_asn1_bld (aCtx, mmsl_enc_buf,mmsl_enc_buf_size); /* init the builder */ + +#ifdef CS_SUPPORT /* Check for CS information */ + if (cs_send.cs_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_delmnt (aCtx, cs_send.cs_ptr,cs_send.cs_len); + cs_send.cs_pres = cs_send_reset_val; + asn1r_fin_constr (aCtx, 79,CTX|CONSTR,DEF); + } +#endif + +/* write the context specific explicit asn1_tag for this opcode. */ + asn1r_fin_prim (aCtx, (ST_INT16)opcode,CTX); /* asn1_tag = opcode, ctx prim */ + + asn1r_wr_u32 (aCtx, invoke_id); /* write the invoke id */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + + mmsl_msg_start = _ms_fin_pdu (aCtx, MMSRESP, &mmsl_msg_len); +#ifdef DEBUG_SISCO + _ms_fin_pdu_log (MMSRESP, mms_op_string[opcode],mmsl_msg_start,mmsl_msg_len); +#endif + + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + return (ME_ASN1_ENCODE_OVERRUN); + + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* mms_fin_null_req */ +/* general NULL request function, used for prim NULL requests */ +/************************************************************************/ + +ST_RET _mms_fin_null_req (ST_INT opcode) + { +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + asn1r_strt_asn1_bld (aCtx, mmsl_enc_buf,mmsl_enc_buf_size); /* init the builder */ + +#ifdef CS_SUPPORT /* Check for CS information */ + if (cs_send.cs_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_delmnt (aCtx, cs_send.cs_ptr,cs_send.cs_len); + cs_send.cs_pres = cs_send_reset_val; + asn1r_fin_constr (aCtx, 79,CTX|CONSTR,DEF); + } +#endif + +/* Write the context specific explicit asn1_tag for this opcode on a NULL */ +/* data element. */ + + asn1r_fin_prim (aCtx, (ST_INT16)opcode, CTX); /* asn1_tag = opcode, context */ + +#ifdef MOD_SUPPORT /* check for modifier info */ + if ( modifier_list.info_pres ) + { + asn1r_strt_constr (aCtx); + wr_mms_modlist( modifier_list.mod_list_ptr, + modifier_list.num_of_mods ); + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); + modifier_list.info_pres = SD_FALSE; + } +#endif + + asn1r_wr_u32 (aCtx, mmsl_invoke_id++); /* write the invoke id */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + +/* Complete the outer ASN.1 element */ + mmsl_msg_start = _ms_fin_pdu (aCtx, MMSREQ, &mmsl_msg_len); +#ifdef DEBUG_SISCO + _ms_fin_pdu_log (MMSREQ, mms_op_string[opcode],mmsl_msg_start,mmsl_msg_len); +#endif + + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + { + return (ME_ASN1_ENCODE_OVERRUN); + } + +/* OK, message has been build successfully */ + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* mms_resp_fin */ +/* general mp_xxxxxx response function, used for prim responses */ +/************************************************************************/ + +ST_RET _mms_resp_fin (ST_INT opcode, ST_UINT32 invoke_id, + ST_VOID (*mk_fun)(ASN1_ENC_CTXT *ac, ST_CHAR *info), ST_CHAR *info_ptr) + { +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + asn1r_strt_asn1_bld (aCtx, mmsl_enc_buf,mmsl_enc_buf_size); /* init the builder */ + +#ifdef CS_SUPPORT /* Check for CS information */ + if (cs_send.cs_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_delmnt (aCtx, cs_send.cs_ptr,cs_send.cs_len); + cs_send.cs_pres = cs_send_reset_val; + asn1r_fin_constr (aCtx, 79,CTX|CONSTR,DEF); + } +#endif + + (*mk_fun) (aCtx, info_ptr); + + asn1r_wr_u32 (aCtx, invoke_id); /* write the invoke id */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + + mmsl_msg_start = _ms_fin_pdu (aCtx, MMSRESP, &mmsl_msg_len); +#ifdef DEBUG_SISCO + _ms_fin_pdu_log (MMSRESP, mms_op_string[opcode],mmsl_msg_start,mmsl_msg_len); +#endif + + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + { + + printf("asn1r_encode_overrun %d\n",mmsl_enc_buf_size); + return (ME_ASN1_ENCODE_OVERRUN); + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* mms_req_fin */ +/* general mp_xxxxx request function, used for prim requests */ +/************************************************************************/ + +ST_RET _mms_req_fin (ST_INT opcode, ST_VOID (*mk_ptr)(ASN1_ENC_CTXT *ac, ST_CHAR *info), + ST_CHAR *info_ptr) + { +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + asn1r_strt_asn1_bld (aCtx, mmsl_enc_buf,mmsl_enc_buf_size); /* init the builder */ + +#ifdef CS_SUPPORT /* Check for CS information */ + if (cs_send.cs_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_delmnt (aCtx, cs_send.cs_ptr,cs_send.cs_len); + cs_send.cs_pres = cs_send_reset_val; + asn1r_fin_constr (aCtx, 79,CTX|CONSTR,DEF); + } +#endif + + (*mk_ptr)(aCtx, info_ptr); /* write the PDU */ + +#ifdef MOD_SUPPORT /* check for modifier info */ + if ( modifier_list.info_pres ) + { + asn1r_strt_constr (aCtx); + wr_mms_modlist( modifier_list.mod_list_ptr, + modifier_list.num_of_mods ); + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); + modifier_list.info_pres = SD_FALSE; + } +#endif + + asn1r_wr_u32 (aCtx, mmsl_invoke_id++); /* write the invoke id */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + + mmsl_msg_start = _ms_fin_pdu (aCtx, MMSREQ, &mmsl_msg_len); +#ifdef DEBUG_SISCO + _ms_fin_pdu_log (MMSREQ, mms_op_string[opcode],mmsl_msg_start,mmsl_msg_len); +#endif + + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + { + return (ME_ASN1_ENCODE_OVERRUN); + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/* mms_unconf_req_fin */ +/* general mp_xxxxx request function, for unconfirmed requests */ +/************************************************************************/ + +ST_RET _mms_unconf_req_fin (ASN1_ENC_CTXT *aCtx, ST_INT opcode, ST_VOID (*mk_ptr)(ASN1_ENC_CTXT *ac, ST_CHAR *info), + ST_CHAR *info_ptr) + { +ST_UCHAR *msg_ptr; +ST_INT msg_len; + +/* Make sure that "asn1r_strt_asn1_bld" was called for this context. */ + assert (aCtx->asn1r_magic == ASN1_ENC_MAGIC_NUMBER); + +#ifdef CS_SUPPORT /* Check for CS information */ + if (cs_send.cs_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_delmnt (aCtx, cs_send.cs_ptr,cs_send.cs_len); + cs_send.cs_pres = cs_send_reset_val; + asn1r_fin_constr (aCtx, 79,CTX|CONSTR,DEF); + } +#endif + + (*mk_ptr)(aCtx, info_ptr); /* write the PDU */ + + msg_ptr = _ms_fin_pdu (aCtx, MMSUNREQ, &msg_len); +#ifdef DEBUG_SISCO + _ms_fin_pdu_log (MMSUNREQ, mms_op_string[opcode],msg_ptr,msg_len); +#endif + + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + return (ME_ASN1_ENCODE_OVERRUN); + + return (SD_SUCCESS); + } + + + +/************************************************************************/ +/************************************************************************/ +/* mpl_resp_log */ +/************************************************************************/ + +ST_VOID mpl_resp_log (MVL_IND_PEND *indCtrl, ST_VOID *respInfo) + { + if ((mms_debug_sel & MMS_LOG_RESP) && ml_log_resp_info_fun != NULL) + { + if (mvl_conn_filtered_logging == SD_FALSE || indCtrl->event->net_info->log_enable) + { + (*ml_log_resp_info_fun) (indCtrl->event->u.mms.dec_rslt.id, + indCtrl->op == MMSOP_RD_USR_HANDLED ? MMSOP_READ : indCtrl->op, + respInfo); + } + } + } + + +/************************************************************************/ +/* mpl_req_log */ +/************************************************************************/ + +ST_VOID mpl_req_log (MVL_REQ_PEND *reqCtrl, ST_VOID *reqInfo) + { + if ((mms_debug_sel & MMS_LOG_REQ) && ml_log_req_info_fun != NULL) + { + if (mvl_conn_filtered_logging == SD_FALSE || reqCtrl->net_info->log_enable) + { + (*ml_log_req_info_fun) (reqCtrl->invoke_id, reqCtrl->op, reqInfo); + } + } + } + + +/************************************************************************/ +/* mpl_unsol_req_log */ +/************************************************************************/ + +ST_VOID mpl_unsol_req_log (MVL_NET_INFO *netInfo, ST_INT op, ST_VOID *reqInfo) + { + if ((mms_debug_sel & MMS_LOG_REQ) && ml_log_unsol_req_info_fun != NULL) + { + if (mvl_conn_filtered_logging == SD_FALSE || netInfo->log_enable) + { + (*ml_log_unsol_req_info_fun) (op, reqInfo); + } + } + } diff --git a/mmslib/mmsl/mmslvar.c b/mmslib/mmsl/mmslvar.c new file mode 100644 index 0000000..bc4516d --- /dev/null +++ b/mmslib/mmsl/mmslvar.c @@ -0,0 +1,232 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmslvar.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* All global MMSEASE-LITE variables are defined in this module, */ +/* and declared in LMMSDEFS.H */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/17/08 JRB 15 Del m_use_long_ints flag. */ +/* 10/04/07 MDE 14 Tweaked LOGCFG_VALUE_GROUP/LOGCFGX_VALUE_MAP */ +/* 06/22/05 JRB 13 Remove static from usrLog* var. */ +/* 06/06/05 EJV 12 usrLogMaskMapCtrl not used when FOUNDRY def. */ +/* 05/23/05 EJV 11 Add xxxLogMaskMapCtrl for parsing logcfg.xml */ +/* 09/04/03 EJV 10 Chg mms_debug_sel to ST_UINT (from ST_UINT32)*/ +/* 03/13/03 JRB 09 Del u_ml_get_rt_type func ptr, it is func now*/ +/* 01/02/03 JRB 08 Add arg to u_ml_get_rt_type. */ +/* 03/15/01 JRB 07 Added user_debug_sel & _user_*_logstr */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 02/23/99 JRB 05 Don't init m_data_algn_tbl, it's a constant. */ +/* 10/21/98 MDE 04 Removed VMS ifdef */ +/* 10/08/98 MDE 03 Migrated to updated SLOG interface */ +/* 11/05/97 MDE 02 Changed mmsl_msg_start to ST_UCHAR * */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_err.h" +#include "mms_pvar.h" +#include "mms_vvar.h" + + +/************************************************************************/ +/************************************************************************/ +/* MMSEASE-LITE Global Variables */ +/************************************************************************/ + +ST_INT mmsl_enc_buf_size; +ST_UCHAR *mmsl_enc_buf; +ST_INT mmsl_dec_info_size; + +#if !defined(NO_GLB_VAR_INIT) +ST_INT16 mmsl_version = 1; /* select IS for version */ +ST_UINT32 mmsl_invoke_id = 1; +#else +ST_INT16 mmsl_version; /* select IS for version */ +ST_UINT32 mmsl_invoke_id; +#endif + +ST_UCHAR *mmsl_msg_start; +ST_INT mmsl_msg_len; + +/************************************************************************/ +/* Variables in common with MMS-EASE */ + +#if !defined(NO_GLB_VAR_INIT) +ST_UINT _mmsdec_ctxt = MMS_PCI;/* decode context type, default to core */ +#else +ST_UINT _mmsdec_ctxt; /* decode context type, default to core */ +#endif +ST_INT _mmsdec_msglen; /* MMS decode message length */ +ST_UCHAR *_mmsdec_msgptr; /* MMS decode message ptr */ +ST_BOOLEAN _mms_dec_info_pres; +MMSDEC_INFO *_mmsdec_rslt; +ST_VOID *_mms_dec_info; + +ADTNL_ERR_RESP_INFO adtnl_err_info; + +ST_RET mms_op_err; + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* Some Alternate Access related variables. These are defined in */ +/* mmsvar.c for MMS-EASE, but are put here for MMS-LITE */ + +#if !defined(NO_GLB_VAR_INIT) +ST_INT m_max_dec_aa = 50; +ST_INT m_max_rt_aa_ctrl = 1000; +#else +ST_INT m_max_dec_aa; +ST_INT m_max_rt_aa_ctrl; +#endif + +ST_INT m_hw_dec_aa; +ST_INT m_hw_rt_aa_ctrl; +ST_BOOLEAN m_alt_acc_packed; + +/************************************************************************/ +/************************************************************************/ +/* This variable can be set to force use of the DIS MMS floating point */ +/* type protocol (used in any over the wire and internal ASN.1 type */ +/* definitions). */ +/************************************************************************/ + +ST_BOOLEAN m_use_dis_float; + +/************************************************************************/ +/* Global variables for modifier support */ +/************************************************************************/ + +#if !defined (NO_GLB_VAR_INIT) +LIST_OF_MODS modifier_list; /* used to encode modifier info */ +ST_INT m_max_mods = 1; /* num of modifier structs calloced during dec. */ +#else +LIST_OF_MODS modifier_list; +ST_INT m_max_mods; +#endif + +/************************************************************************/ +/* Global variables for compantion standard (IS) */ +/************************************************************************/ + +CSI cs_send; /* SEND CS info structure */ +ST_BOOLEAN cs_send_reset_val; + +/************************************************************************/ +/* Logging variables */ +/************************************************************************/ + +#if !defined(NO_GLB_VAR_INIT) +ST_UINT mms_debug_sel = MMS_LOG_ERR; +ST_UINT user_debug_sel = USER_LOG_ERR; +#else +ST_UINT mms_debug_sel; +ST_UINT user_debug_sel; +#endif + +#ifdef DEBUG_SISCO +SD_CONST ST_CHAR *SD_CONST _mms_log_dec_logstr = "MMS_LOG_DEC"; +SD_CONST ST_CHAR *SD_CONST _mms_log_enc_logstr = "MMS_LOG_ENC"; +SD_CONST ST_CHAR *SD_CONST _mms_log_acse_logstr = "MMS_LOG_ACSE"; +SD_CONST ST_CHAR *SD_CONST _mms_log_llc_logstr = "MMS_LOG_LLC"; +SD_CONST ST_CHAR *SD_CONST _mms_log_ique_logstr = "MMS_LOG_IQUE"; +SD_CONST ST_CHAR *SD_CONST _mms_log_rque_logstr = "MMS_LOG_RQUE"; +SD_CONST ST_CHAR *SD_CONST _mms_log_ind_logstr = "MMS_LOG_IND"; +SD_CONST ST_CHAR *SD_CONST _mms_log_conf_logstr = "MMS_LOG_CONF"; +SD_CONST ST_CHAR *SD_CONST _mms_log_vm_logstr = "MMS_LOG_VM"; +SD_CONST ST_CHAR *SD_CONST _mms_log_err_logstr = "MMS_LOG_ERR"; +SD_CONST ST_CHAR *SD_CONST _mms_log_nerr_logstr = "MMS_LOG_NERR"; +SD_CONST ST_CHAR *SD_CONST _mms_log_pdu_logstr = "MMS_LOG_PDU"; +SD_CONST ST_CHAR *SD_CONST _mms_log_config_logstr = "MMS_LOG_CONFIG"; +SD_CONST ST_CHAR *SD_CONST _mms_log_always_logstr = "MMS_LOG_ALWAYS"; + +SD_CONST ST_CHAR *SD_CONST _user_err_logstr = "USER_LOG_ERR"; +SD_CONST ST_CHAR *SD_CONST _user_client_logstr = "USER_LOG_CLIENT"; +SD_CONST ST_CHAR *SD_CONST _user_server_logstr = "USER_LOG_SERVER"; + +LOGCFGX_VALUE_MAP mmsLogMaskMaps[] = + { + {"MMS_LOG_ERR", MMS_LOG_ERR, &mms_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Error"}, + {"MMS_LOG_NERR", MMS_LOG_NERR, &mms_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Notice"}, + {"MMS_LOG_DEC", MMS_LOG_DEC, &mms_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Decode"}, + {"MMS_LOG_ENC", MMS_LOG_ENC, &mms_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Encode"}, + + {"MMS_LOG_CLIENT", MMS_LOG_REQ|MMS_LOG_CONF, &mms_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Client"}, + {"MMS_LOG_SERVER", MMS_LOG_IND|MMS_LOG_RESP, &mms_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Server"}, + + {"MMS_LOG_REQ", MMS_LOG_REQ, &mms_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Request"}, + {"MMS_LOG_RESP", MMS_LOG_RESP, &mms_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Response"}, + {"MMS_LOG_IND", MMS_LOG_IND, &mms_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Indication"}, + {"MMS_LOG_CONF", MMS_LOG_CONF, &mms_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Confirm"}, + {"MMS_LOG_RT", MMS_LOG_RT, &mms_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "RuntimeType"}, + {"MMS_LOG_RTAA", MMS_LOG_RTAA, &mms_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "RuntimeAlternateAccess"}, + {"MMS_LOG_AA", MMS_LOG_AA, &mms_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "AlternateAccess"}, + }; + +LOGCFG_VALUE_GROUP mmsLogMaskMapCtrl = + { + {NULL,NULL}, + "MmsLogMasks", /* Parent Tag */ + sizeof(mmsLogMaskMaps)/sizeof(LOGCFGX_VALUE_MAP), + mmsLogMaskMaps + }; + +LOGCFGX_VALUE_MAP usrLogMaskMaps[] = + { + {"USER_LOG_ERR", USER_LOG_ERR, &user_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Error"}, + {"USER_LOG_CLIENT", USER_LOG_CLIENT, &user_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Client"}, + {"USER_LOG_SERVER", USER_LOG_SERVER, &user_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Server"} + }; + +LOGCFG_VALUE_GROUP usrLogMaskMapCtrl = + { + {NULL,NULL}, + "UserLogMasks", /* Parent Tag */ + sizeof(usrLogMaskMaps)/sizeof(LOGCFGX_VALUE_MAP), + usrLogMaskMaps + }; +#endif /* DEBUG_SISCO */ + +/************************************************************************/ +/* m_init_glb_vars */ +/************************************************************************/ + +#if defined(NO_GLB_VAR_INIT) +ST_VOID a_init_glb_vars (ST_VOID); + +ST_VOID m_init_glb_vars (ST_VOID) + { + a_init_glb_vars (); + mmsl_version = 1; + mmsl_invoke_id = 1; + _mmsdec_ctxt = MMS_PCI; + m_max_mods = 1; + mms_debug_sel = MMS_LOG_ERR; +#if defined(NO_GLB_VAR_INIT) + if (!m_data_algn_tbl) + m_data_algn_tbl = m_packed_data_algn_tbl; +#endif + m_max_dec_aa = 50; + m_max_rt_aa_ctrl = 1000; + } + +#endif + diff --git a/mmslib/mmsl/mmsstat.c b/mmslib/mmsl/mmsstat.c new file mode 100644 index 0000000..c055704 --- /dev/null +++ b/mmslib/mmsl/mmsstat.c @@ -0,0 +1,205 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mmsstat.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the common functions to perform the decode */ +/* of a status response or an unsolicited status request, which */ +/* have identical syntax. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 03/31/03 JRB 05 asn1r_get_bitstr: add max_bits arg. */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "asn1defs.h" + +/************************************************************************/ + +static STATUS_RESP_INFO *info; + +static ST_VOID local_detail_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_local_detail_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_local_detail_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_physical_stat (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_logical_stat (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_status */ +/* This function is called from mms_status_rsp (in rq_stat.c) or from */ +/* mms_ustatus_req (in rs_ustat.c) to decode either a Status response */ +/* PDU or an UnsolicitedStatus request PDU after the PDU type has been */ +/* determined. It sets up the parse of the next data element and */ +/* returns, letting the ASN.1 tools take over. */ +/************************************************************************/ + +ST_VOID mms_status (ASN1_DEC_CTXT *aCtx) + { +/* Create status_resp_info structure data area to put decoded info into.*/ + info = (STATUS_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (STATUS_RESP_INFO)); + +/* (NOTE: A structure of typp_info is excactly the same as */ +/* a structure of type ustat so this logic works with both */ + + ASN1R_TAG_ADD (aCtx, CTX,0,get_logical_stat);/* Set up to parse 1st param.*/ + } + + +/************************************************************************/ +/* get_logical_stat */ +/* The logical status parameter has been encountered. Read its value. */ +/************************************************************************/ + +static ST_VOID get_logical_stat (ASN1_DEC_CTXT *aCtx) + { +ST_INT high_lim; + + MLOG_CDEC0 ("get_logical_stat"); + + if (asn1r_get_i16 (aCtx, &info->logical_stat)) /* Read logical status. */ + { /* If error reading integer, */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); /* stop parse, report error */ + return; /* and return. */ + } + +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + high_lim = 3; + else /* DIS */ + high_lim = 2; + + if ((info->logical_stat < 0) || (info->logical_stat > high_lim)) + { /* validate range of values */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + +/* The next data element expected is the physical status. */ + ASN1R_TAG_ADD (aCtx, CTX,1,get_physical_stat); + } + + +/************************************************************************/ +/* get_physical_stat */ +/* The physical status parameter has been encountered. Read its value. */ +/************************************************************************/ + +static ST_VOID get_physical_stat (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_physical_stat"); + +/* Get the value of the physical status parameter. */ + + if (asn1r_get_i16 (aCtx, &info->physical_stat)) /* Read physical status. */ + { /* If error reading integer, */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); /* stop parse, report error */ + return; /* and return. */ + } + + if ((info->physical_stat < 0) || (info->physical_stat > 3)) + { /* validate range [0..3] */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + +/* The next data element is either the local detail parameter or the */ +/* additional detail parameter, or there may be no other data elements. */ + + ASN1R_TAG_ADD (aCtx, CTX,2,get_local_detail_prim); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_local_detail_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +/************************************************************************/ +/* get_local_detail_prim */ +/* The local detail parameter has been encountered as a primitive data */ +/* element. Read its value. */ +/************************************************************************/ + +static ST_VOID get_local_detail_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_local_detail_prim"); + +/* Get the value of the local detail parameter. */ + + if (aCtx->asn1r_elmnt_len <= MAX_IDENT_LEN)/* check length before moving data */ + { + if (!asn1r_get_bitstr (aCtx, info->local_detail, sizeof(info->local_detail)*8)) + { /* If everything is kosher, */ + local_detail_done (aCtx); /* set up for the next data element. */ + return; /* Return success and continue parse. */ + } + } + +/* Problem getting value - stop parse and report error. */ + + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + +/************************************************************************/ +/* get_local_detail_cstr */ +/* The local detail parameter has been encountered as a constructor */ +/* data element. Read its value. */ +/************************************************************************/ + +static ST_VOID get_local_detail_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_local_detail_cstr"); + +/* Set up to call this function when done with constructor bitstring. */ + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = local_detail_done; + +/* Get the value of the local detail parameter. For constructor */ +/* bitstrings, this requires returning and letting the ASN.1 tools */ +/* parse it to any nesting level. */ + + asn1r_get_bitstr_cstr (aCtx, 16,info->local_detail); + } + + +/************************************************************************/ +/* local_detail_done */ +/* Function called after the local_detail parameter has been parsed. */ +/************************************************************************/ + +static ST_VOID local_detail_done (ASN1_DEC_CTXT *aCtx) + { + + info -> local_detail_pres = SD_TRUE; + info -> local_detail_len = aCtx->asn1r_bitcount; + +/* The next data element, if there is one, is the additional detail */ +/* parameter. */ + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } diff --git a/mmslib/mmsl/ms_ext.c b/mmslib/mmsl/ms_ext.c new file mode 100644 index 0000000..1981789 --- /dev/null +++ b/mmslib/mmsl/ms_ext.c @@ -0,0 +1,442 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ms_ext.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 04 Cleaned up "thisFileName" */ +/* 03/31/03 JRB 03 asn1r_get_bitstr: add max_bits arg. */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 01 Added SD_CONST modifiers */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) && defined(S_MT_SUPPORT) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ + +ST_VOID ms_get_extern (ASN1_DEC_CTXT *aCtx, EXTERN_INFO *dest); + +static EXTERN_INFO *ext_dest; + +static ST_VOID ext_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID ext_cstr_done (ASN1_DEC_CTXT *aCtx); + +static ST_INT save_method; /* storage for decode method */ + +/************************************************************************/ +/* ms_decode_extern */ +/************************************************************************/ + +ST_RET ms_decode_extern (ST_UCHAR *asn1ptr, ST_INT asn1len, + EXTERN_INFO *dest) + { +ST_RET ret; +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean. */ + S_LOCK_COMMON_RESOURCES (); + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* select tag method */ + aCtx->asn1r_decode_done_fun = asn1r_done_err;/* not legal to be done at this time */ + aCtx->asn1r_err_fun = NULL; + + ext_dest = dest; + + ASN1R_TAG_ADD (aCtx, UNI|CONSTR, EXTERN_CODE, ext_cstr); + asn1r_decode_asn1 (aCtx, asn1ptr,asn1len);/* decode entire ASN.1 'Data' entity */ + + if (aCtx->asn1r_pdu_dec_err == NO_DECODE_ERR) /* check for sucess or return error */ + ret = SD_SUCCESS; + else + ret = MVE_DATA_CONVERT; + + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +/************************************************************************/ +/* ext_cstr */ +/* This function is called when an 'EXTERNAL' data element has been */ +/* found. It will put info into the selected structure. */ +/************************************************************************/ + +static ST_VOID ext_cstr (ASN1_DEC_CTXT *aCtx) + { + ms_get_extern (aCtx, ext_dest); + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = ext_cstr_done; + } + + +static ST_VOID ext_cstr_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_done = SD_TRUE; + aCtx->asn1r_decode_done_fun = NULL; + } + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +static EXTERN_INFO *ext_info_ptr; +static ST_VOID get_dir_ref (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_indir_ref (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_objdesc (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_sngl_asn1 (ASN1_DEC_CTXT *aCtx); +static ST_VOID sngl_parse_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID sngl_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_oct_alignd_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_oct_alignd_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID oct_alignd_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_arb_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID get_arb_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID arb_done (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/************************************************************************/ +/* ms_get_extern */ +/* This function is called when an 'EXTERNAL' data element has been */ +/* found. It will put info into the selected structure. */ +/************************************************************************/ + +ST_VOID ms_get_extern (ASN1_DEC_CTXT *aCtx, EXTERN_INFO *dest) + { + save_method = aCtx->asn1r_decode_method; /* use class method */ + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; + + ext_info_ptr = dest; /* save the destination */ + ext_info_ptr -> dir_ref_pres = SD_FALSE; /* clear pres flag */ + ext_info_ptr -> indir_ref_pres = SD_FALSE; /* clear pres flag */ + ext_info_ptr -> dv_descr_pres = SD_FALSE; /* clear present flag */ + + ASN1R_TAG_ADD (aCtx, UNI,OBJ_ID_CODE,get_dir_ref); /* transfer syntax name */ + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,get_indir_ref); /* PCI */ + ASN1R_TAG_ADD (aCtx, UNI,OBJDSCR_CODE,get_objdesc); /* object descripter */ + /* Data Types */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,get_sngl_asn1); /* single asn1 type */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_oct_alignd_cstr); /* oct alignd, cstr */ + ASN1R_TAG_ADD (aCtx, CTX,1,get_oct_alignd_prim); /* oct alignd, prim */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_arb_cstr); /* arbitrary, cstr */ + ASN1R_TAG_ADD (aCtx, CTX,2,get_arb_prim); /* arbitrary, prim */ + } + +/************************************************************************/ +/* get_dir_ref */ +/* This is the function called when : */ +/************************************************************************/ + +static ST_VOID get_dir_ref (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_dir_ref"); + + ext_info_ptr->dir_ref_pres = SD_TRUE; /* mark present */ + + if (asn1r_get_objid (aCtx, ext_info_ptr->dir_ref.comps, + &ext_info_ptr->dir_ref.num_comps)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,get_indir_ref); /* indir ref maybe */ + ASN1R_TAG_ADD (aCtx, UNI,OBJDSCR_CODE,get_objdesc); /* object descripter */ + /* Data Types */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,get_sngl_asn1); /* single asn1 type */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_oct_alignd_cstr); /* oct alignd, cstr */ + ASN1R_TAG_ADD (aCtx, CTX,1,get_oct_alignd_prim); /* oct alignd, prim */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_arb_cstr); /* arbitrary, cstr */ + ASN1R_TAG_ADD (aCtx, CTX,2,get_arb_prim); /* arbitrary, prim */ + } + +/************************************************************************/ +/* get_indir_ref */ +/* This is the function called when the PCI element of a PDV is found */ +/************************************************************************/ + +static ST_VOID get_indir_ref (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_indir_ref"); + + if (asn1r_get_i32 (aCtx, &ext_info_ptr->indir_ref)) /* If out of range for us */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + ext_info_ptr->indir_ref_pres = SD_TRUE; + ASN1R_TAG_ADD (aCtx, UNI,OBJDSCR_CODE,get_objdesc); /* object descripter */ + /* Data Types */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,get_sngl_asn1); /* single asn1 type */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_oct_alignd_cstr); /* oct alignd, cstr */ + ASN1R_TAG_ADD (aCtx, CTX,1,get_oct_alignd_prim); /* oct alignd, prim */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_arb_cstr); /* arbitrary, cstr */ + ASN1R_TAG_ADD (aCtx, CTX,2,get_arb_prim); /* arbitrary, prim */ + } + } + +/************************************************************************/ +/* get_objdesc */ +/* This is the function called when the PCI element of a PDV is found */ +/************************************************************************/ + +static ST_VOID get_objdesc (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_objdesc"); + + ext_info_ptr->dv_descr_pres = SD_TRUE; /* mark present */ + ext_info_ptr->dv_descr_len = aCtx->asn1r_elmnt_len; /* len of string */ + ext_info_ptr->dv_descr = aCtx->asn1r_field_ptr; /* leave it lie */ + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; /* skip over */ + +/* set up to get presentation data values - choice of three */ + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,get_sngl_asn1); /* single asn1 type */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_oct_alignd_cstr); /* oct alignd, cstr */ + ASN1R_TAG_ADD (aCtx, CTX,1,get_oct_alignd_prim); /* oct alignd, prim */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_arb_cstr); /* arbitrary, cstr */ + ASN1R_TAG_ADD (aCtx, CTX,2,get_arb_prim); /* arbitrary, prim */ + } + +/************************************************************************/ +/* get_sngl_asn1 */ +/* This is the function called when : */ +/************************************************************************/ + +static ST_VOID get_sngl_asn1 (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_sngl_asn1"); + +/* aCtx->asn1r_field_ptr points to 'any', elmnt is length of data */ + ext_info_ptr->encoding_tag = 0; /* write tag */ + ext_info_ptr->data_len = aCtx->asn1r_elmnt_len; /* len of ANY */ + ext_info_ptr->data_ptr = aCtx->asn1r_field_ptr; /* leave it lie */ + + asn1r_parse_next (aCtx, sngl_parse_done); + } + + +/************************************************************************/ +/* sngl_parse_done */ +/* */ +/************************************************************************/ + +static ST_VOID sngl_parse_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sngl_parse_done"); + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = sngl_done; + } + +/************************************************************************/ +/* sngl_done */ +/* This is the cstr done function called when : */ +/************************************************************************/ + +static ST_VOID sngl_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("sngl_done"); + + aCtx->asn1r_decode_method = save_method; /* this extern is now done */ + } + + +/************************************************************************/ +/* get_oct_alignd_prim */ +/* This is the function called when : */ +/************************************************************************/ + +static ST_VOID get_oct_alignd_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_oct_alignd_prim"); + +/* aCtx->asn1r_elmnt_len == # octects */ + + ext_info_ptr->encoding_tag = 1; /* write tag */ + ext_info_ptr->data_len = aCtx->asn1r_elmnt_len; /* len of ANY */ + ext_info_ptr->data_ptr = aCtx->asn1r_field_ptr; /* leave it lie */ + + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; /* skip over data */ + + aCtx->asn1r_decode_method = save_method; /* this extern is now done */ + } + +/************************************************************************/ +/* get_oct_alignd_cstr */ +/* This is the function called when : */ +/************************************************************************/ + +static ST_VOID get_oct_alignd_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_oct_alignd_cstr"); + + ext_info_ptr->encoding_tag = 1; /* write tag */ + ext_info_ptr->data_ptr = aCtx->asn1r_field_ptr; /* leave it lie */ + asn1r_get_octstr_cstr (aCtx, ASN1_MAX_PDU, aCtx->asn1r_field_ptr); + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = oct_alignd_done; + } + +/************************************************************************/ +/* oct_alignd_done */ +/* This is the cstr done function called when : */ +/************************************************************************/ + +static ST_VOID oct_alignd_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("oct_alignd_done"); + + ext_info_ptr->data_len = aCtx->asn1r_octetcount; /* len of octet string */ + aCtx->asn1r_decode_method = save_method; /* this extern is now done */ + } + +/************************************************************************/ +/* get_arb_prim */ +/* This is the function called when : */ +/************************************************************************/ + +static ST_VOID get_arb_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_arb_prim"); + +/* aCtx->asn1r_bitcount = bits */ + + ext_info_ptr->encoding_tag = 2; /* write tag */ + ext_info_ptr->data_len = aCtx->asn1r_elmnt_len-1; /* len of ANY */ + ext_info_ptr->data_ptr = aCtx->asn1r_field_ptr; /* leave it lie */ + asn1r_get_bitstr (aCtx, aCtx->asn1r_field_ptr,0); /* max_bits=0 (no limit)*/ + ext_info_ptr->num_bits = aCtx->asn1r_bitcount; + aCtx->asn1r_decode_method = save_method; /* this extern is now done */ + } + +/************************************************************************/ +/* get_arb_cstr */ +/* This is the function called when : */ +/************************************************************************/ + +static ST_VOID get_arb_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("get_arb_cstr"); + + ext_info_ptr->encoding_tag = 2; /* write tag */ + ext_info_ptr->data_ptr = aCtx->asn1r_field_ptr; /* leave it lie */ + + asn1r_get_bitstr_cstr (aCtx, ASN1_MAX_PDU, aCtx->asn1r_field_ptr); + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = arb_done; + } + + +/************************************************************************/ +/* arb_done */ +/* This is the cstr done function called when : */ +/************************************************************************/ + +static ST_VOID arb_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("arb_done"); + + ext_info_ptr->num_bits = aCtx->asn1r_bitcount; + ext_info_ptr->data_len = CALC_BIT_LEN (aCtx->asn1r_bitcount); + aCtx->asn1r_decode_method = save_method; /* this extern is now done */ + } + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* ms_encode_extern */ +/************************************************************************/ + +ST_RET ms_encode_extern (EXTERN_INFO *ext, ST_UCHAR *dest, ST_INT dest_len, + ST_INT *ext_len, ST_UCHAR **ext_ptr) + { +ST_RET ret; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + S_LOCK_COMMON_RESOURCES (); + asn1r_strt_asn1_bld (aCtx, dest,dest_len); /* init the builder */ + wr_external (aCtx, ext); + + *ext_ptr = aCtx->asn1r_field_ptr + 1; + *ext_len = (dest+dest_len) - *ext_ptr; + + if (!aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + ret = SD_SUCCESS; + else + ret = ME_ASN1_ENCODE_OVERRUN; + + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +/************************************************************************/ +/* wr_external */ +/************************************************************************/ + +ST_VOID wr_external (ASN1_ENC_CTXT *aCtx, EXTERN_INFO *ext) + { + asn1r_strt_constr (aCtx); /* start EXTERNAL */ + + if (ext->encoding_tag == 0) /* ANY */ + { + asn1r_wr_octstr (aCtx, ext->data_ptr,ext->data_len); + asn1r_fin_constr (aCtx, 0,CTX,DEF); + } + else if (ext->encoding_tag == 1) /* Octet Aligned */ + { + asn1r_wr_octstr (aCtx, ext->data_ptr,ext->data_len); + asn1r_fin_prim (aCtx, 1,CTX); /* finish octet-aligned string */ + } + else if (ext->encoding_tag == 2) /* Arbitrary */ + { + asn1r_wr_bitstr (aCtx, ext->data_ptr,ext->num_bits); + asn1r_fin_prim (aCtx, 2,CTX); + } + + if (ext->dv_descr_pres) + { + asn1r_wr_octstr (aCtx, ext->dv_descr,ext->dv_descr_len); + asn1r_fin_prim (aCtx, OBJDSCR_CODE,UNI); /* object descripter */ + } + + if (ext->indir_ref_pres) + { + asn1r_wr_i32 (aCtx, ext->indir_ref); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + } + + if (ext->dir_ref_pres) + { + asn1r_wr_objid (aCtx, ext->dir_ref.comps,ext->dir_ref.num_comps); + asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI); + } + + asn1r_fin_constr (aCtx, EXTERN_CODE,UNI,DEF); /* finish EXTERNAL */ + } + + diff --git a/mmslib/mmsl/ms_size.c b/mmslib/mmsl/ms_size.c new file mode 100644 index 0000000..3d59e8f --- /dev/null +++ b/mmslib/mmsl/ms_size.c @@ -0,0 +1,600 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ms_size.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains support functions for estimating maximum */ +/* size of Variable Access service PDUs (Read, Write, and InfoRpt).*/ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/14/03 JRB 09 Eliminate compiler warnings. */ +/* 04/02/03 JRB 08 Add UTF8string support (see RT_UTF8_STRING). */ +/* 11/14/01 EJV 07 Added support for new MMS type UtcTime: */ +/* ms_data_size: added case for RT_UTC_TIME */ +/* 10/18/00 RKR 06 Changed RT_UNSIGNED in ms_data_size */ +/* 09/15/00 MDE 05 Fixed MMS-EASE compile error */ +/* 09/07/00 MDE 04 Added MMS-LITE support */ +/* 02/10/98 MDE 03 Now don't use runtime type loops element */ +/* 08/15/97 MDE 02 Minor cleanup */ +/* 06/09/97 MDE 01 Changed Runtime Type, and it's use */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "asn1defs.h" +#if defined(MMS_LITE) +#include "mvl_defs.h" +#endif + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) && defined(S_MT_SUPPORT) +static ST_CHAR *thisFileName = __FILE__; +#endif + +static ST_LONG address_size (VAR_ACC_ADDR *address, ST_BOOLEAN req); +static ST_LONG obj_name_size (OBJECT_NAME *name, ST_BOOLEAN req); +static ST_LONG ms_data_size (RUNTIME_TYPE *rt_ptr, ST_INT rt_num, + ST_INT alt_len, ST_UCHAR *alt_ptr, + ST_BOOLEAN req); + +static ST_INT arr_loop_level; +static ST_INT *arr_loops; + +/************************************************************************/ +/************************************************************************/ +/* To allow the user to specify either MMS-EASE or UNKNOWN PDU style, */ +/* the following definitions & data structures are used. */ +/* See ms_size.doc for information on how these were derived. */ + +ST_INT ms_req_bld_id = UNKNOWN_BUILDER; +ST_INT ms_resp_bld_id = UNKNOWN_BUILDER; + +/* Because the MMS-EASE ASN.1 tools are a bit conservitive, need to */ +/* provide for a little extra overhead. */ +ST_INT ms_size_oh_pad = ASN1_MAX_ELEMENT_OVERHEAD; + +ST_LONG large_el_oh[] = + { + 6L, /* MMS-EASE is PDU Builder */ + 8L /* UNKNOWN PDU Builder */ + }; +ST_LONG med_el_oh[] = + { + 4L, /* MMS-EASE is PDU Builder */ + 8L /* UNKNOWN PDU Builder */ + }; +ST_LONG small_el_oh[] = + { + 2L, /* MMS-EASE is PDU Builder */ + 8L /* UNKNOWN PDU Builder */ + }; + +#define LARGE_EL_REQ_OH large_el_oh[ms_req_bld_id] +#define MED_EL_REQ_OH med_el_oh[ms_req_bld_id] +#define SMALL_EL_REQ_OH small_el_oh[ms_req_bld_id] + +#define LARGE_EL_RESP_OH large_el_oh[ms_resp_bld_id] +#define MED_EL_RESP_OH med_el_oh[ms_resp_bld_id] +#define SMALL_EL_RESP_OH small_el_oh[ms_resp_bld_id] + +/************************************************************************/ +/************************************************************************/ +/* Overhead for various types of MMS ASN.1 data elements */ + + +#define CONF_REQ_PDU_OH (ms_size_oh_pad+MED_EL_REQ_OH+SMALL_EL_REQ_OH+4) +#define CONF_RESP_PDU_OH (ms_size_oh_pad+MED_EL_RESP_OH+SMALL_EL_RESP_OH+4) +#define UNCONF_PDU_OH (ms_size_oh_pad+MED_EL_REQ_OH) + +/* Overhead for empty PDU's of various types */ +#define READ_REQ_OH (CONF_REQ_PDU_OH + (MED_EL_REQ_OH * 2)) +#define READ_RESP_OH (CONF_RESP_PDU_OH + (MED_EL_RESP_OH * 2)) +#define WRITE_REQ_OH (CONF_REQ_PDU_OH + (MED_EL_REQ_OH * 2)) +#define WRITE_RESP_OH (CONF_RESP_PDU_OH + MED_EL_RESP_OH) +#define INFO_REQ_OH (UNCONF_PDU_OH + (MED_EL_REQ_OH * 2)) + +/* Overhead for various components of interest */ +#define SPEC_IN_RSLT_SIZE (MED_EL_REQ_OH + 1) + +/* Object name overhead */ +#define VMD_OBJ_NAME_REQ_OH SMALL_EL_REQ_OH +#define DOM_OBJ_NAME_REQ_OH (MED_EL_REQ_OH + (SMALL_EL_REQ_OH * 2)) +#define AA_OBJ_NAME_REQ_OH SMALL_EL_REQ_OH + +#define VMD_OBJ_NAME_RESP_OH SMALL_EL_RESP_OH +#define DOM_OBJ_NAME_RESP_OH (MED_EL_RESP_OH + (SMALL_EL_RESP_OH * 2)) +#define AA_OBJ_NAME_RESP_OH SMALL_EL_RESP_OH + + +#define GENTIME_LEN 18L + +/************************************************************************/ +/************************************************************************/ + +/************************************************************************/ +/* ms_init_va_size */ +/* This function is called from the user as a first step in estimating */ +/* the maximum size of both the request and response PDUs of any of the */ +/* Variable Access services (Read, Write, and InformationReport). This */ +/* function initializes the values pointed to by req_size and resp_size */ +/* to the overhead in the PDU (before determining the size of the data */ +/* and specification of each variable to be included). The companion */ +/* function ms_va_size is then called for each variable to add on the */ +/* estimated size attributable to that variable. This function returns */ +/* 0 for success, else an error code. */ +/************************************************************************/ + +ST_RET ms_init_va_size (ST_INT op, ST_UCHAR spec_in_rslt, ST_INT16 var_acc_tag, + OBJECT_NAME *vl_name, ST_LONG *req_size, ST_LONG *resp_size) + { +ST_RET ret; + + S_LOCK_COMMON_RESOURCES (); + ret = SD_SUCCESS; + switch (op) + { + case MMSOP_READ: +/* initialize sizes to include all overhead for basic request */ + *req_size = READ_REQ_OH; + *resp_size = READ_RESP_OH; + +/* To send request for spec in result takes extra bytes, do does */ +/* sending the VA spec in the response. */ + if (spec_in_rslt) + { + *req_size += SPEC_IN_RSLT_SIZE; + *resp_size += MED_EL_RESP_OH; + } + break; + + case MMSOP_WRITE: +/* initialize sizes to include all overhead for basic request */ + *req_size = WRITE_REQ_OH; + *resp_size = WRITE_RESP_OH; + break; + + case MMSOP_INFO_RPT: +/* initialize sizes to include all overhead for basic request */ + *req_size = INFO_REQ_OH; + *resp_size = 0; + break; + + default : + ret = MVE_WRONG_OP; + } + +/* If the variable specification is a named list, add in the name, else */ +/* add in the sequence of sequence constructor overhead */ +/* Note that this is done here, NOT in later calls to ms_va_size */ + + if (var_acc_tag == VAR_ACC_NAMEDLIST) /* list of variables case */ + *req_size += MED_EL_REQ_OH + obj_name_size (vl_name,SD_TRUE); + else + *req_size += MED_EL_REQ_OH; /* seq of seq */ + + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + + +/************************************************************************/ +/* ms_va_size */ +/* This function is called from the user repetitively for each variable */ +/* expected to be included in a Read, Write, or InfoRpt PDU. Note that */ +/* the function ms_init_va_size should be called first to initialize */ +/* the two outputs req_size and resp_size. The values pointed to by */ +/* req_size and resp_size are incremented by the appropriate amount, */ +/* so that after this function has been called for all variables, they */ +/* represent valid estimates of the size of the request and response */ +/* PDUs for the given service (indicated by op). In some cases, the */ +/* type of the variable may be indicated both by the vl_ptr argument */ +/* and by the type argument; in this case, both must still be specified */ +/* and it is up to the user to verify that they are equal. This */ +/* function returns 0 for success, else an error code. */ +/* */ +/* NOTE: In the case of accessing a variable list object (as opposed */ +/* to a list of variable objects), a variable_list structure must */ +/* be built and filled in appropriately, with var_spec_tag set to */ +/* 5. (Otherwise, the value pointed to by req_size and, in */ +/* certain cases, the value pointed to by resp_size will be */ +/* much larger than necessary. */ +/************************************************************************/ + +#if !defined(MMS_LITE) +ST_RET ms_va_size (ST_INT op, ST_UCHAR spec_in_rslt, ST_INT16 var_acc_tag, + VARIABLE_LIST *vl_ptr, NAMED_TYPE *type, + ST_LONG *req_size, ST_LONG *resp_size) +#else +ST_RET ms_va_size (ST_INT op, ST_UCHAR spec_in_rslt, ST_INT16 var_acc_tag, + VARIABLE_LIST *vl_ptr, ST_INT type_id, + ST_LONG *req_size, ST_LONG *resp_size) +#endif + { +ST_LONG size; +ST_INT alt_acc_len; +RUNTIME_TYPE *rt; +ST_INT rt_num; +#if defined(MMS_LITE) +ST_INT rc; +#endif + +#if !defined(MMS_LITE) + rt = type->rt_head; + rt_num = type->rt_num; +#else + rc = mvl_get_runtime (type_id, &rt, &rt_num); + if (rc != SD_SUCCESS) + return (rc); +#endif + + S_LOCK_COMMON_RESOURCES (); + +/* non functional at this time */ + if (vl_ptr->alt_access_pres) + alt_acc_len = vl_ptr->alt_access.len; + else + alt_acc_len = 0; + +/* get the size of the data element based on the MMS type and add the */ +/* data element size to the target PDU */ + + if (op == MMSOP_READ) /* read response carries data */ + { + size = ms_data_size (rt, rt_num, alt_acc_len, + vl_ptr->alt_access.data,SD_FALSE); + *resp_size += size; + } + else /* WRITE or INFO */ + { + size = ms_data_size (rt, rt_num, alt_acc_len, + vl_ptr->alt_access.data,SD_TRUE); + *req_size += size; + + if (op == MMSOP_WRITE) /* Write response carries result */ + *resp_size += SMALL_EL_RESP_OH + 1; /* assume failure (+1) */ + } + if (size <= 0) /* verify the data size was OK */ + { + S_UNLOCK_COMMON_RESOURCES (); + return (MVE_TYPENAME); + } + +/* Now calculate the size of the variable access spec for this var. */ +/* Only req'd if var_acc_tag is list of vars (list name added already) */ + if (var_acc_tag == VAR_ACC_VARLIST) + { + size = MED_EL_REQ_OH; + switch (vl_ptr->var_spec.var_spec_tag) + { + case VA_SPEC_NAMED : + size += obj_name_size (&vl_ptr->var_spec.vs.name,SD_TRUE); + break; + +#if !defined(MMS_LITE) + case VA_SPEC_DESCRIBED : /* described gets address & type */ + size += type->asn1len + + address_size (&vl_ptr->var_spec.vs.address,SD_TRUE); + break; +#endif + + case VA_SPEC_ADDRESSED : + size += address_size (&vl_ptr->var_spec.vs.address,SD_TRUE); + break; + + case VA_SPEC_SCATTERED : /* not currently supported */ + case VA_SPEC_INVALIDATED : + default: + S_UNLOCK_COMMON_RESOURCES (); + return (MVE_VM_SERVICE_NOTSUPP); + } + +/* not really supported at this time, leave in anyway */ + if (vl_ptr->alt_access_pres) + size += (ST_LONG) alt_acc_len; + +/* Now we have the variable specification size, add to the request */ + *req_size += size; + +/* Now, if spec in result requested, calculate VA spec size for resp */ + if (op == MMSOP_READ && spec_in_rslt) + { + size = MED_EL_RESP_OH; + switch (vl_ptr->var_spec.var_spec_tag) + { + case VA_SPEC_NAMED : + size += obj_name_size (&vl_ptr->var_spec.vs.name,SD_FALSE); + break; + +#if !defined(MMS_LITE) + case VA_SPEC_DESCRIBED : /* described gets address & type */ + size += type->asn1len + + address_size (&vl_ptr->var_spec.vs.address,SD_FALSE); + + break; +#endif + + case VA_SPEC_ADDRESSED : + size += address_size (&vl_ptr->var_spec.vs.address,SD_FALSE); + break; + + case 5: /* variable list object case */ + S_UNLOCK_COMMON_RESOURCES (); + return (SD_SUCCESS); /* No variable spec. req'd */ + break; + + case VA_SPEC_SCATTERED : /* not currently supported */ + case VA_SPEC_INVALIDATED : + default: + S_UNLOCK_COMMON_RESOURCES (); + return (MVE_VM_SERVICE_NOTSUPP); + } + *resp_size += size; + } + } /* if VAR_ACC_VARLIST */ + +/* Now, if WRITE, need to add write result */ + + + S_UNLOCK_COMMON_RESOURCES (); + return (SD_SUCCESS); + } + + +/************************************************************************/ +/* obj_name_size */ +/* This function is called from ms_init_va_size and ms_va_size to */ +/* calculate (exactly) the size that a particular object name will take */ +/* up in a request or response PDU for the Read, Write, and InfoReport */ +/* services. Returns the size of the object name, or 0 if there is a */ +/* problem. */ +/************************************************************************/ + +static ST_LONG obj_name_size (OBJECT_NAME *name, ST_BOOLEAN req) + { +ST_LONG oh; + + switch (name->object_tag) + { + case VMD_SPEC : + if (req) /* if calculating for a request */ + oh = VMD_OBJ_NAME_REQ_OH; + else + oh = VMD_OBJ_NAME_RESP_OH; + + return (oh + (ST_LONG) strlen (name->obj_name.vmd_spec)); + break; + + case DOM_SPEC : + if (req) /* if calculating for a request */ + oh = DOM_OBJ_NAME_REQ_OH; + else + oh = DOM_OBJ_NAME_RESP_OH; + + return (oh + (ST_LONG) (strlen (name->obj_name.item_id) + + strlen (name->domain_id))); + break; + + case AA_SPEC : + if (req) /* if calculating for a request */ + oh = AA_OBJ_NAME_REQ_OH; + else + oh = AA_OBJ_NAME_RESP_OH; + + return (oh + (ST_LONG) strlen (name->obj_name.aa_spec)); + break; + } + + mms_op_err = MVE_OBJECT_SCOPE; + return (0L); /* indicates error condition */ + } + + +/************************************************************************/ +/* address_size */ +/* This function is called from ms_va_size to calculate (exactly) the */ +/* size that a particular address will take up in a request or response */ +/* PDU for the Read, Write, and InfoReport services. Returns the size */ +/* of the address, or 0 if there is a problem. */ +/************************************************************************/ + +static ST_LONG address_size (VAR_ACC_ADDR *address, ST_BOOLEAN req) + { +ST_LONG size; +ST_LONG numaddr; + + switch (address->addr_tag) + { + case NUM_ADDR : + if (req) /* if calculating for a request */ + size = SMALL_EL_REQ_OH; + else + size = SMALL_EL_RESP_OH; + numaddr = address->addr.num_addr; + if (numaddr < 128L) + size += 1; + else if (numaddr < 32768L) + size += 2; + else if (numaddr < 8388608L) + size += 3; + else + size += 4; + break; + + case SYM_ADDR : + if (req) /* if calculating for a request */ + size = MED_EL_REQ_OH; + else + size = MED_EL_RESP_OH; + size += strlen (address->addr.sym_addr); + break; + + case UNCON_ADDR : + if (req) /* if calculating for a request */ + size = MED_EL_REQ_OH; + else + size = MED_EL_RESP_OH; + size += address->addr.unc_addr.unc_len; + break; + + default: + mms_op_err = MVE_ADDR; + return (0); + } + return (size); + } + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* ms_data_size */ +/* This function is called from the user or the MMS-EASE virtual */ +/* machine to estimate the size that the data corresponding to a */ +/* particular type will take up in a request or response PDU for the */ +/* Read, Write, and InfoReport services. Returns the size of the data, */ +/* or 0 if there is a problem. (A rough error code can be found in */ +/* mms_op_err; a more detailed one in asn1_pdu_dec_err.) */ +/* */ +/* Note: Alternate access may be used to modify a type, thereby */ +/* affecting the size of the corresponding data. However, */ +/* the alternate access inputs are disregarded at this time. */ +/* This will be fixed in a later revision. */ +/************************************************************************/ + +static ST_LONG ms_data_size (RUNTIME_TYPE *rt_ptr, ST_INT rt_num, + ST_INT alt_len, ST_UCHAR *alt_ptr, + ST_BOOLEAN req) + { +ST_LONG size; +RUNTIME_TYPE *rt_end; +ST_LONG med_oh; +ST_LONG small_oh; +ST_UINT ellen; +ST_LONG len; +ST_INT arr_loop_buf[ASN1_MAX_LEVEL]; +ST_UINT el_size; /* num bytes to encode data */ + + arr_loop_level = 0; + arr_loops = arr_loop_buf; + + if (req) /* if calculating for a request */ + { + med_oh = MED_EL_REQ_OH; + small_oh = SMALL_EL_REQ_OH; + } + else /* calculating for response */ + { + med_oh = MED_EL_RESP_OH; + small_oh = SMALL_EL_RESP_OH; + } + + rt_end = rt_ptr + rt_num; /* end block */ + + size = 0; + while (rt_ptr < rt_end) + { + if (rt_ptr->el_tag == RT_ARR_END) /* treat case of array ending */ + { /* loops set at start of array */ + if (--arr_loops[arr_loop_level] > 0) /* if need to do next ar elmnt */ + rt_ptr -= rt_ptr->u.arr.num_rt_blks; /* mv rt_ptr to start of arr */ + else + --arr_loop_level; + } + + ellen = abs (rt_ptr->u.p.el_len); /* make sure positive */ + switch (rt_ptr->el_tag) + { + case RT_ARR_START : /* arrays don't have to be aligned */ + ++arr_loop_level; + arr_loops[arr_loop_level] = rt_ptr->u.arr.num_elmnts; + /* let fall through to STR_MMSOP_START */ + + case RT_STR_START : /* structure starting */ + size += med_oh; /* add in data element overhead */ + break; + + case RT_UNSIGNED : /* unsigned integer */ + size += small_oh + ellen + 1; /* high order bit set needs 0x00*/ + break; + + case RT_UTC_TIME : /* UTC time */ + case RT_BINARY_TIME : /* binary time */ + case RT_INTEGER : /* integer */ + case RT_FLOATING_POINT : /* float */ + size += small_oh + ellen; + break; + + case RT_VISIBLE_STRING : /* visible string */ + case RT_OCTET_STRING : /* octet string */ + size += ellen; + if (ellen < 128) + size += small_oh; + else + size += med_oh; + break; + + case RT_GENERAL_TIME : /* generalized time */ + size += small_oh + GENTIME_LEN; + break; + + case RT_BOOL : /* boolean */ + size += small_oh +1; + break; + + case RT_BCD : /* bcd */ + size += small_oh + ellen; + break; + + case RT_BIT_STRING : /* bit string */ + len = 1 + CALC_BIT_LEN (ellen); + + if (len < 128) + size += small_oh + len; /* add in data element overhead */ + else + size += med_oh + len; /* add in data element overhead */ + + break; + + case RT_UTF8_STRING : /* Unicode UTF8 string */ + el_size = ellen*4; /* Could take 4 bytes per char */ + size += el_size; + if (el_size < 128) + size += small_oh; + else + size += med_oh; + break; + + case RT_ARR_END : /* array done */ + case RT_STR_END : /* structure done */ + break; + + default : /* should not be any other tag */ + return (0); + break; + } + rt_ptr++; /* point to next block */ + } /* while (rt blocks) */ + return (size); + } + + diff --git a/mmslib/mmsl/ms_tdef.c b/mmslib/mmsl/ms_tdef.c new file mode 100644 index 0000000..e59eef7 --- /dev/null +++ b/mmslib/mmsl/ms_tdef.c @@ -0,0 +1,1153 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ms_tdef.c */ +/* PRODUCT(S) : MMS-EASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains some MMS-EASE virtual machine support */ +/* functions that help the user with MMS variable access and */ +/* type specifications. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/22/07 JRB 26 Log max on buffer overrun. */ +/* 01/17/06 NAV 25 ms_runtime_to_tdl: fix tdl_buf overwrite */ +/* 07/12/04 JRB 24 For RT_UTF8_STRING, chg "t18" to "t16" in */ +/* "tdlTypes" to match latest 61850-8-1. */ +/* 05/03/04 JRB 23 ms_mk_asn1_type: return err if struct empty, */ +/* ignore extra commas, use ASN1_ENC_* macros, */ +/* & log the ASN.1 produced. */ +/* type_subst: remove whitespace in dest string.*/ +/* 10/13/03 JRB 22 ms_runtime_to_tdl: Chg assert to err return. */ +/* 07/14/03 JRB 21 Use strlen(comp_name), was assuming maxlen=32*/ +/* 04/22/03 JRB 20 Allow fixed len UTF8 only if local fmt=UTF16.*/ +/* 04/02/03 JRB 19 Add UTF8string support (see RT_UTF8_STRING). */ +/* Use "RT_*" defines in "switch (type)". */ +/* DRASTICALLY simplify ms_runtime_to_tdl. */ +/* add_tdl_separator: add args (& fix spelling):*/ +/* - allows 3 global vars to be eliminated. */ +/* - allows semaphore to be eliminated. */ +/* 12/15/02 JRB 18 Add ms_tdl_to_runtime function. */ +/* 11/11/02 JRB 17 Replace ms_asn1_to.. w/ ms_runtime_create. */ +/* 03/04/02 JRB 16 Add more SD_CONST. Add str_util.h. */ +/* 12/20/01 JRB 15 Converted to use ASN1R (re-entrant ASN1) */ +/* 11/13/01 EJV 14 Added support for new MMS type UtcTime: */ +/* tdlTypes[]: added new type "Utctime" [17] */ +/* ms_mk_asn1_type: added case for type 17. */ +/* anticipated[]: added type 17 and moved other.*/ +/* ms_runtime_to_tdl: added RT_UTC_TIME case. */ +/* 03/08/01 JRB 13 Chk return val from ms_comp_name_find. */ +/* 08/24/00 JRB 12 Use ms_comp_name_find, so code works for */ +/* MMS_LITE (i.e. USE_RT_TYPE_2 or USE_RT_TYPE_3*/ +/* defined). */ +/* 07/28/00 JRB 11 Use new defines in #ifdef. */ +/* 09/13/99 MDE 10 Added SD_CONST modifiers */ +/* 09/21/98 MDE 09 Minor lint cleanup */ +/* 08/21/98 MDE 08 Eliminated warning in ms_asn1_to_tdl. */ +/* 06/03/98 MDE 07 Now check 'ms_asn1_to_runtime' return code */ +/* 03/11/98 MDE 06 Removed NEST_RT_TYPES */ +/* 02/10/98 MDE 05 Runtime type changes for LITE */ +/* 10/30/97 MDE 04 Calculate size of RT table before alloc */ +/* 09/16/97 MDE 03 Now don't require @VMD for referenced type */ +/* 06/19/97 MDE 02 Added 64 bit integer support, cleanup */ +/* 06/09/97 MDE 01 Changed Runtime Type, and it's use */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "mmsdefs.h" +#include "asn1defs.h" +#include "mem_chk.h" +#include "str_util.h" /* for strnicmp */ + +/************************************************************************/ + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/************************************************************************/ +/* TDL DEFINES */ +/* Defined constants giving the primitive syntax for the keywords: */ +/* Bool, Byte, Short, Long, Ubyte, Ushort, Ulong, Float, Double, */ +/* Vstring, Fstring, Ostring, Bstring, Gtime, Btime4, Btime8, respec- */ +/* tively. */ +/* These are used in 'ms_mk_asn1_type' for substitutions */ +/************************************************************************/ + +/************************************************************************/ + +static ST_INT type_subst (ST_CHAR *dest_str, ST_CHAR *src_str, ST_INT src_len); +static ST_RET wr_object_name (ASN1_ENC_CTXT *aCtx, ST_CHAR *objname); +static ST_UCHAR *err_rtn (ST_RET error, ST_CHAR *tspec); + +#ifdef MMS_LITE +ST_INT m_rt_type_limit = 50; /* max number of runtime blocks per def */ +#endif + +/* These checks catch if a define change breaks the code using "tdlTypes"*/ +/* The way "tdlTypes" is used, does not work if any of the RT_* defines change.*/ +/* It would be better to modify the code to always use the RT_* defines,*/ +/* but that is not so easy now. */ +#if (RT_BOOL != 3) +#error define does't match expected. tdlTypes array won't work. +#endif +#if (RT_BIT_STRING != 4) +#error define does't match expected. tdlTypes array won't work. +#endif +#if (RT_INTEGER != 5) +#error define does't match expected. tdlTypes array won't work. +#endif +#if (RT_UNSIGNED != 6) +#error define does't match expected. tdlTypes array won't work. +#endif +#if (RT_FLOATING_POINT != 7) +#error define does't match expected. tdlTypes array won't work. +#endif +#if (RT_OCTET_STRING != 9) +#error define does't match expected. tdlTypes array won't work. +#endif +#if (RT_VISIBLE_STRING != 10) +#error define does't match expected. tdlTypes array won't work. +#endif +#if (RT_GENERAL_TIME != 11) +#error define does't match expected. tdlTypes array won't work. +#endif +#if (RT_BINARY_TIME != 12) +#error define does't match expected. tdlTypes array won't work. +#endif +#if (RT_BCD != 13) +#error define does't match expected. tdlTypes array won't work. +#endif +#if (RT_BOOLEANARRAY != 14) +#error define does't match expected. tdlTypes array won't work. +#endif +#if (RT_UTC_TIME != 17) +#error define does't match expected. tdlTypes array won't work. +#endif +#if (RT_UTF8_STRING != 16) +#error define does't match expected. tdlTypes array won't work. +#endif + +/************************************************************************/ + +typedef struct + { + ST_CHAR *abbrev; + ST_CHAR *subType; + } TDL_TYPES; + +/* tdlTypes array + * CRITICAL: the number after the "t" in the 2nd string of each struct + * MUST match the ASN.1 tag for that type. The tags are defined in "mms_vvar.h" + * and they have a prefix of "RT_". + * For example, the ASN.1 tag for Boolean is 3, so "mms_vvar.h" has the define: + * #define RT_BOOL 3 + * and the string in this array for Boolean is: + * "t3" + */ + +TDL_TYPES tdlTypes[] = + { + { "Bool", "t3" }, + { "Byte", "t5+8" }, + { "Short", "t5+16" }, + { "Long", "t5+32" }, +#ifdef INT64_SUPPORT + { "Int64", "t5+64" }, +#endif + { "Ubyte", "t6+8" }, + { "Ushort", "t6+16" }, + { "Ulong", "t6+32" }, +#ifdef INT64_SUPPORT + { "Uint64", "t6+64" }, +#endif + { "Float", "t7+2071" }, + { "Double", "t7+2868" }, + { "Vstring", "t10-" }, + { "Fstring", "t10+" }, + { "Ostring", "t9+" }, + { "OVstring", "t9-" }, + { "Bstring", "t4+" }, + { "BVstring", "t4-" }, + { "Gtime", "t11" }, + { "Btime4", "t12+0" }, + { "Btime6", "t12+1" }, + { "Bcd", "t13+" }, + { "Utctime", "t17" }, + { "UTF8Vstring", "t16-" }, +#if (UNICODE_LOCAL_FORMAT==UNICODE_UTF16) + { "UTF8string", "t16+" }, +#endif + }; +ST_INT numTdlTypes = (sizeof (tdlTypes)/sizeof(TDL_TYPES)); + +/************************************************************************/ +/* ms_mk_asn1_type */ +/* Function to convert a character string type specification to an */ +/* ASN.1 string, as required by the ms_add_named_type function. It */ +/* is assumed that the function strt_asn1 has been called elsewhere */ +/* in the user's program. The input 'tspec' character string must */ +/* conform to the following syntax for specifying a type: */ +/* */ +/* Let N be a number, i.e. a sequence of digits. Let */ +/* IDENTIFIER be a character string which is a valid MMS */ +/* identifier. And let OBJECT_NAME be a character string */ +/* which represents a valid MMS object name of the form: */ +/* string1:IDENTIFIER, where string1 is "+" for a VMD- */ +/* specific object, "-" for an AA-specific object, or a */ +/* valid IDENTIFIER naming a domain for a domain-specific */ +/* object. Then we have the following Bacchus-Nauer rules */ +/* for specifying the syntax: */ +/* */ +/* Type ::= | tN+N | tN-N | tN | [N:Type] */ +/* | [pN:Type] | {Component_list} | {p:Component_list} */ +/* Component_list ::= Component | Component_list,Component */ +/* Component ::= Type | (IDENTIFIER)Type */ +/* */ +/* The above syntax may contain white space (blanks, tabs and new- */ +/* lines) to make it more readable. (Hence, a character string */ +/* constant input for 'tspec' may extend over several lines.) */ +/* However, the symbols appearing in the definition above (called */ +/* terminal symbols), such as '<', '>', 't', '+', ,'-', '[', ':', ']', */ +/* '{', '}', '(', ')', 'p' and ',', must be used exactly as specified. */ +/* The meaning of the above syntax is given below: */ +/* */ +/* - Name of a type object that has already been */ +/* declared to MMS-EASE using ms_add_named_type */ +/* or ms_add_std_types. */ +/* tN+N, tN-N, tN - Primitive type, where the first N indicates */ +/* the basic type, and the second N is the */ +/* length of the type (normally in bits, but */ +/* for octet-strings and visible-strings, it */ +/* represents the number of bytes, and floats */ +/* are a special case - see note below). The */ +/* basic types are explained below. If the type */ +/* length (+N or -N) is left off, it defaults */ +/* to zero. Note that char strings may have */ +/* negative type lengths, indicating variable- */ +/* length (i.e., can be <= N), but all other */ +/* types must have nonnegative type lengths. */ +/* [N:Type] - Array of N elements of the specified type. */ +/* {Component_list} - Structure consisting of one or more compo- */ +/* nents, separated by commas, with or without */ +/* component names. */ +/* (IDENTIFIER)Type - A component of a structure identified by a */ +/* component name, in order that it may be */ +/* referenced in a subsequent alternate access. */ +/* p - Used in arrays or structures to indicate */ +/* that it is 'packed', i.e. compressed in some */ +/* implementation-specific way. */ +/* */ +/* The basic types are numbers (first N following the 't' of a primi- */ +/* tive type) with the following meanings: */ +/* */ +/* 3 - Boolean, type length = 0 (or absent). Ex: "t3". */ +/* 4 - Bit-string, type length >= 0. Ex: "t4+27" for a 27-bit */ +/* bit-string. */ +/* 5 - Integer, type length = 16 or 32 for most computers. Ex: */ +/* "t5+16" for a 2-byte integer, "t5+32" for a 4-byte int. */ +/* 6 - Unsigned, type length = 16 or 32 for most computers. Ex: */ +/* "t6+16" for a 2-byte unsigned integer. */ +/* 7 - Floating point, type length = 2071 for single precision */ +/* or 2868 for double precision on most computers. See */ +/* the note below. */ +/* 9 - Octet-string, type length >= 0. Ex: "t9+19" for a 19- */ +/* byte octet-string. */ +/* 10 - Visible-string, any type length. Ex: "t10+30" specifies */ +/* a fixed-length string of exactly 30 characters, whereas */ +/* "t10-12" specifies a variable-length string of at most */ +/* 12 characters. */ +/* 11 - Generalized-time, type length = 0 (or absent). Ex: "t11". */ +/* 12 - Binary-time, type length = 0 or 1 (SD_FALSE or SD_TRUE). Ex: */ +/* "t12+1" for a 6-byte binary-time time of day, including */ +/* date. */ +/* 13 - BCD, type length >= 0 AND <= 8 */ +/* computers). Ex: "t13+8" for a 8-nibble BCD integer. */ +/* 17 - UTC Time is struct of 3 unsigned integers encoded as */ +/* 8 bytes octet string (ssssqmmm), where */ +/* ssss seconds since Jan 1, 1970, 4 bytes padded with */ +/* leading 0's */ +/* q quality flags, 1 byte */ +/* mmm microseconds in a second, 3 bytes in range */ +/* [0,999999], padded with 0's. */ +/* Note: this is new type added to the spec in 2001/2002. */ +/* 16 - UTF8string, any type length. Ex: "t16+30" specifies */ +/* a fixed-length string of exactly 30 characters, whereas */ +/* "t16-12" specifies a variable-length string of at most */ +/* 12 characters. */ +/* */ +/* NOTE: Floating point is a special case in that its length is */ +/* a combination of two numbers: fractional width (say 52 bits) */ +/* and exponent width (say 11 bits). The length of the floating */ +/* point type is computed according to the following algorithm: */ +/* N = e*256 + f, */ +/* where f = fractional width and e = exponent width. For stan- */ +/* dard IEEE floating point format, N = 2071 for single-precision */ +/* and N = 2868 for double-precision. Hence, most users will use */ +/* the following notation for floating point types: */ +/* "t7+2071" for single prec. and "t7+2868" for double prec. */ +/* WARNING: This function will not accept type specifications for */ +/* floating point exponents with a width greater than 127 bits or */ +/* mantissas with a width greater than 255 bits. */ +/* */ +/* The other input arguments of this function are the length of a */ +/* buffer to hold the ASN.1 string, and a pointer to that buffer. */ +/* The 'asn1_len' argument is modified to equal the actual length of */ +/* the ASN.1 string produced. */ +/* */ +/* If there is no error in this function, the return value is a */ +/* pointer to where the ASN.1 string starts in the buffer. (The */ +/* ASN.1 string always ends at the end of the buffer, but it begins */ +/* anywhere within the buffer.) If an error does occur in this */ +/* function, a NULL pointer is returned, and the global variable */ +/* 'mms_op_err' gives further detail as to the nature of the problem */ +/* that has caused this function to fail. */ +/************************************************************************/ + +#define TYPE_NAME 0 +#define BEG_STRUCT 2 +#define PACKED 0 +#define COMPONENT_NAME 0 +#define BEG_COMP_TYPE 1 + + +ST_UCHAR *ms_mk_asn1_type (ST_INT *asn1_len, ST_UCHAR *asn1, ST_CHAR *type_spec) + { +ST_CHAR *tspec; +ST_INT type; +ST_BOOLEAN literal; +ST_BOOLEAN number; +ST_INT type_len; +ST_BOOLEAN name; +ST_BOOLEAN m_packed; +ST_INT i; +ST_LONG num_elts; +ST_UCHAR acc_float_size; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + +/* Initialize everything first. */ + + S_LOCK_COMMON_RESOURCES (); + num_elts = 0L; + number = SD_FALSE; + name = SD_FALSE; + literal = SD_FALSE; + m_packed = SD_FALSE; + type_len = 0; + i = strlen (type_spec); + tspec = (ST_CHAR *) chk_malloc (2*i); + asn1r_strt_asn1_bld (aCtx, asn1,*asn1_len); + +/* Replace abbreviations in the type definition string with the */ +/* appropriate syntax and reset new length of type spec string. */ + if ((i = type_subst (tspec,type_spec,i)) < 1) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_LEN0,tspec)); + } +/* Loop through the 'tspec' string, from the back to the front. */ + + while (i > 0) + { + switch (tspec[--i]) + { + case '>' : + if (number || m_packed) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_GT,tspec)); + } + literal = SD_TRUE; + tspec[i] = '\0'; + asn1r_strt_constr (aCtx); + break; + + case '<' : + if (number || m_packed) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_LT,tspec)); + } + literal = SD_FALSE; + if (wr_object_name (aCtx, &tspec[i+1])) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_OBJNAME,tspec)); + } + asn1r_fin_constr (aCtx, TYPE_NAME, CTX, 0); + break; + + case '}' : + if (number || m_packed) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_RBRACE,tspec)); + } + asn1r_strt_constr (aCtx); /* Start structure type.*/ + asn1r_strt_constr (aCtx); /* Start component part.*/ + asn1r_strt_constr (aCtx); /* Start last component.*/ + asn1r_strt_constr (aCtx); /* Start component's */ + break; /* explicit type spec. */ + + case '{' : + if (number) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_LBRACE,tspec)); + } + if (tspec[i+1]=='}') /* Empty struct */ + { + MLOG_ERR2 ("ms_mk_asn1_type: empty struct defined starting at offset %d TDL=%s", i, &tspec[i]); + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_LBRACE,tspec)); + } + if (!name) + asn1r_fin_constr (aCtx, BEG_COMP_TYPE, CTX, 0); + asn1r_fin_constr (aCtx, SEQ_CODE, UNI, 0); + name = SD_FALSE; + asn1r_fin_constr (aCtx, 1, CTX, 0); + if (m_packed) + { + asn1r_wr_i16 (aCtx, 1); + asn1r_fin_prim (aCtx, PACKED,CTX); + } + asn1r_fin_constr (aCtx, BEG_STRUCT, CTX, 0); + m_packed = SD_FALSE; + break; + + case ',' : + if (number) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_COMMA,tspec)); + } + if (tspec[i+1]=='}' || tspec[i+1]==',') /* Ignore extra commas */ + { + MLOG_ENC0 ("ms_mk_asn1_type: ',' followed by ',' or '}' in TDL string ignored."); + } + else + { + if (!name) + asn1r_fin_constr (aCtx, BEG_COMP_TYPE, CTX, 0); + asn1r_fin_constr (aCtx, SEQ_CODE, UNI, 0); + name = SD_FALSE; + asn1r_strt_constr (aCtx); + asn1r_strt_constr (aCtx); + } + break; + + case ')' : + if (number || m_packed) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_RPAREN,tspec)); + } + asn1r_fin_constr (aCtx, BEG_COMP_TYPE, CTX, 0); + name = SD_TRUE; + literal = SD_TRUE; + tspec[i] = '\0'; + break; + + case '(' : + if (number || m_packed) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_LPAREN,tspec)); + } + literal = SD_FALSE; + asn1r_wr_vstr (aCtx, &tspec[i+1]); + asn1r_fin_prim (aCtx, COMPONENT_NAME, CTX); + break; + + case 'p' : + if (literal) + break; + if (m_packed) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_P,tspec)); + } + m_packed = SD_TRUE; + break; + + case '+' : + if (literal) + break; + if (!number || m_packed) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_PLUS,tspec)); + } + type_len = atoi (&tspec[i+1]); + tspec[i] = '\0'; + number = SD_FALSE; + break; + + case '-' : + if (literal) + break; + if (!number || m_packed) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_MINUS,tspec)); + } + type_len = -atoi (&tspec[i+1]); + tspec[i] = '\0'; + number = SD_FALSE; + break; + + case 't' : + if (literal) + break; + if (!number || m_packed) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_T,tspec)); + } + type = atoi (&tspec[i+1]); + switch (type) + { + case RT_BOOL : + case RT_GENERAL_TIME : + case RT_UTC_TIME : + if (type_len) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_BADLEN3,tspec)); + } + asn1r_fin_prim (aCtx, (ST_UINT16) type,CTX); + break; + + case RT_BIT_STRING : + case RT_OCTET_STRING : + case RT_VISIBLE_STRING : + case RT_UTF8_STRING: + asn1r_wr_i32 (aCtx, (ST_INT32) type_len); + asn1r_fin_prim (aCtx, (ST_UINT16) type,CTX); + break; + + case RT_INTEGER : + case RT_UNSIGNED : + case RT_BINARY_TIME : + if (type_len > 127) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_BADLEN5,tspec)); + } + asn1r_wr_u8 (aCtx, (ST_UCHAR) type_len); + asn1r_fin_prim (aCtx, (ST_UINT16) type, CTX); + break; + + case RT_BCD : + if (type_len > 8 || type_len <= 0) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_BADLEN5,tspec)); + } + asn1r_wr_u8 (aCtx, (ST_UCHAR) type_len); + asn1r_fin_prim (aCtx, (ST_UINT16) type, CTX); + break; + + case RT_FLOATING_POINT : + if (type_len < 256) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_BADLEN7,tspec)); + } + asn1r_strt_constr (aCtx); + asn1r_wr_u8 (aCtx, (ST_UCHAR) ((type_len>>8) & 0xFF)); /* write exp */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + +/* For IS MMS, first octet is exponent + sign + mantissa */ +/* For DIS MMS, first octet is mantissa */ + + if (!m_use_dis_float) + { + acc_float_size =(ST_UCHAR) ((type_len>>8) & 0xFF); /* exp */ + acc_float_size += (ST_UCHAR)(type_len & 0xFF); /* fract*/ + ++acc_float_size; /* sign */ + asn1r_wr_u8 (aCtx, acc_float_size); + } + else + asn1r_wr_u8 (aCtx, (ST_UCHAR)(type_len & 0xFF)); /* write fract */ + + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, (ST_UINT16) type, CTX, 0); + break; + + default : + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_BADTYPE,tspec)); + } + type_len = 0; + number = SD_FALSE; + break; + + case ':' : + if (literal) + break; + if (number || m_packed) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_COLON,tspec)); + } + tspec [i] = '\0'; + num_elts = -1L; + break; + + case ']' : + if (number || m_packed) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_RBRACKET,tspec)); + } + asn1r_strt_constr (aCtx); + asn1r_strt_constr (aCtx); + tspec [i] = '\0'; + break; + + case '[' : + if (!number || !num_elts) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_LBRACKET,tspec)); + } + asn1r_fin_constr (aCtx, 2,CTX,0); + if (m_packed) + num_elts = atol (strchr(&tspec[i+1],'p') + 1); + else + num_elts = atol (&tspec[i+1]); + if (num_elts < 1L) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_NUM_ELTS,tspec)); + } + asn1r_wr_i32 (aCtx, num_elts); + asn1r_fin_prim (aCtx, 1, CTX); + if (m_packed) + { + asn1r_wr_i16 (aCtx, 1); + asn1r_fin_prim (aCtx, PACKED,CTX); + } + asn1r_fin_constr (aCtx, 1, CTX, 0); + num_elts = 0L; + number = SD_FALSE; + m_packed = SD_FALSE; + break; + + case ' ' : + case '\t' : + case '\n' : + break; + + default : + if (literal) + break; + if (tspec[i] >= '0' && tspec[i] <= '9') + { + if (m_packed) + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_DIGIT,tspec)); + } + number = SD_TRUE; + break; + } + else + { + S_UNLOCK_COMMON_RESOURCES (); + return (err_rtn (MVE_TYPEDEF_SYM_OTHER,tspec)); + } + } + } /* end of while loop */ + + + chk_free (tspec); + if (aCtx->asn1r_encode_overrun) + { + mms_op_err = ME_ASN1_ENCODE_OVERRUN; + S_UNLOCK_COMMON_RESOURCES (); + return (NULL); + } + S_UNLOCK_COMMON_RESOURCES (); + MLOG_ENC1 ("ASN.1 type def encoded from TDL=%s", type_spec); + MLOG_ENCH (ASN1_ENC_LEN(aCtx), ASN1_ENC_PTR(aCtx)); + *asn1_len = ASN1_ENC_LEN(aCtx); + return (ASN1_ENC_PTR(aCtx)); + } + +/************************************************************************/ +/* type_subst */ +/* Function to pre-processes type definition strings. It substitutes */ +/* primitive syntax for certain abbreviations defined in the 'abbrev' */ +/* array. The syntax of the resulting string is able to be parsed */ +/* simply by ms_mk_asn1_type. This function returns the length of the */ +/* destination string. */ +/************************************************************************/ + +static ST_INT type_subst (ST_CHAR *dest_str, ST_CHAR *src_str, ST_INT src_len) + { +ST_BOOLEAN literal1, literal2; /* booleans indicating we're in a type */ + /* name or component name literal string*/ +ST_INT i, j, k, n; /* indexes and counters */ +ST_BOOLEAN found; /* boolean indicating a string starting */ + /* with a capital letter matches an */ + /* abbreviation and is to be replaced */ + + literal1 = literal2 = SD_FALSE; + i = j = 0; + + while (i < src_len) /* step through the source string */ + { + if (literal1) + { + if (src_str[i] == '>') /* Keep track of when a type name */ + literal1 = SD_FALSE; /* (delimited by '<' and '>') is */ + } /* beginning and ending. Abbreviations */ + else if (literal2) /* are not substituted inside type */ + { /* names. Ditto for component names */ + if (src_str[i] == ')') /* (delimited by '(' and ')'). */ + literal2 = SD_FALSE; + } + else if (src_str[i] == '<') + literal1 = SD_TRUE; + else if (src_str[i] == '(') + literal2 = SD_TRUE; + else if (src_str[i] >= 'A' && src_str[i] <= 'z') + { + found = SD_FALSE; + for (n = 0; n < numTdlTypes; n++) + { + if (strnicmp (tdlTypes[n].abbrev, &src_str[i], strlen (tdlTypes[n].abbrev))) + continue; + else + { + found = SD_TRUE; + break; + } + } + if (found) + { + k = strlen (tdlTypes[n].subType); + memcpy (&dest_str[j],tdlTypes[n].subType,k); + j += k; + i += strlen (tdlTypes[n].abbrev); + continue; + } + } + if (!isspace(src_str[i])) /* do not copy whitespace chars */ + dest_str[j++] = src_str[i]; + i++; /* ALWAYS increment src index */ + } + dest_str[j] = '\0'; + return (j); + } + + + +/************************************************************************/ +/* wr_object_name */ +/* Function to write an object name string to the ASN.1 stream */ +/* according to the ObjectName production in the MMS protocol */ +/* specification. The input string takes the form: */ +/* string1:IDENTIFIER, where string1 is "@VMD" for a VMD-specific */ +/* object, "@AA" for an AA-specific object, or a valid IDENTIFIER */ +/* naming a domain for a domain-specific object. IDENTIFIER is the */ +/* actual name of the object within the domain, VMD, or association- */ +/* specific environment. Returns 0 if successful, nonzero otherwise. */ +/************************************************************************/ + +static ST_RET wr_object_name (ASN1_ENC_CTXT *aCtx, ST_CHAR *objname) + { +ST_CHAR *ptr; + + if ((ptr = strchr (objname,':')) == NULL) /* check for colon */ + { + asn1r_wr_vstr (aCtx, objname); /* Default is VMD specific */ + asn1r_fin_prim (aCtx, 0,CTX); + return (SD_SUCCESS); + } + + *ptr = '\0'; /* replace colon with null char */ + ptr++; /* "ptr" pts to string after ':'*/ + if (!strcmp (objname,"@VMD")) + { + asn1r_wr_vstr (aCtx, ptr); + asn1r_fin_prim (aCtx, 0,CTX); + } + else if (!strcmp (objname,"@AA")) + { + asn1r_wr_vstr (aCtx, ptr); + asn1r_fin_prim (aCtx, 2,CTX); + } + else + { + asn1r_strt_constr (aCtx); /* Domain-specific when string */ + asn1r_wr_vstr (aCtx, ptr); /* before ':' is anything else */ + asn1r_fin_prim (aCtx, VISTR_CODE,UNI); + asn1r_wr_vstr (aCtx, objname); + asn1r_fin_prim (aCtx, VISTR_CODE,UNI); + asn1r_fin_constr (aCtx, 1,CTX,0); + } + return (SD_SUCCESS); + } + + +/************************************************************************/ +/* err_rtn */ +/* Function to be called when there is an error in ms_mk_asn1_type. */ +/************************************************************************/ + +static ST_UCHAR *err_rtn (ST_RET error, ST_CHAR *tspec) + { + mms_op_err = error; + chk_free (tspec); + return (NULL); + } + + +/************************************************************************/ +/* ms_asn1_to_tdl */ +/************************************************************************/ + +ST_CHAR *ms_asn1_to_tdl (ST_UCHAR *asn1_ptr, ST_INT asn1_len, ST_INT max_tdl_len) + { +ST_CHAR *tdl_buf; +ST_INT tdl_len; +RUNTIME_CTRL *rt_ctrl; + + S_LOCK_COMMON_RESOURCES (); + + /* Create temporary runtime type table. */ + /* Last arg allows biggest array "theoretically" possible to allocate.*/ + rt_ctrl = ms_runtime_create (asn1_ptr, asn1_len, + (UINT_MAX/sizeof(RUNTIME_TYPE))-100); + if (!rt_ctrl) /* if ASN.1 decode failed */ + { + mms_op_err = MVE_ASN1_TO_RT; + S_UNLOCK_COMMON_RESOURCES (); + return (NULL); /* quit */ + } + + tdl_buf = (ST_CHAR *) chk_calloc (1, max_tdl_len); + tdl_len = ms_runtime_to_tdl (rt_ctrl->rt_first, rt_ctrl->rt_num, tdl_buf, max_tdl_len); + + if (tdl_len == 0) + { + mms_op_err = MVE_ASN1_TO_RT; + chk_free (tdl_buf); + S_UNLOCK_COMMON_RESOURCES (); + return (NULL); + } + + tdl_buf = (ST_CHAR *) chk_realloc (tdl_buf, tdl_len); + ms_runtime_destroy (rt_ctrl); /* destroy temp rt type */ + + S_UNLOCK_COMMON_RESOURCES (); + return (tdl_buf); + } + +/************************************************************************/ +/* ms_runtime_to_tdl */ +/************************************************************************/ +static ST_INT add_tdl_separator (ST_CHAR *tdl_buf, ST_INT index, + ST_BOOLEAN member_found, + ST_BOOLEAN named_component_found); + +ST_INT ms_runtime_to_tdl (SD_CONST RUNTIME_TYPE *rt, ST_INT rt_num, + ST_CHAR *tdl_buf, ST_INT max_tdl_len) + { +ST_INT i; +ST_INT total_size; +SD_CONST RUNTIME_TYPE * rt_ptr; +#define SIZE_OF_TEMP_BUF 30 +ST_CHAR temp_buf[SIZE_OF_TEMP_BUF]; +ST_INT temp_size; /* len of string in temp_buf */ +ST_BOOLEAN overrun_detected; +SD_CONST ST_CHAR * comp_name; /* component name */ +ST_INT comp_name_len; /* len of component name*/ + +struct struct_tracking { + ST_BOOLEAN member_found; + }; +struct struct_tracking nest_level[ASN1_MAX_LEVEL]; +ST_BOOLEAN named_component_found; + +ST_INT cur_nest_level; + + for (i = 0; i < ASN1_MAX_LEVEL; i++) + { + nest_level[i].member_found = SD_FALSE; + } + + i=0; + overrun_detected = SD_FALSE; + rt_ptr = rt; + total_size = 0; + cur_nest_level = 0; + while ((i < rt_num) && (overrun_detected == SD_FALSE)) + { + named_component_found = SD_FALSE; /* assume comp name not found */ + comp_name = ms_comp_name_find (rt_ptr); + if (comp_name != NULL && comp_name[0] != 0) + { + comp_name_len = strlen (comp_name); + + /* Make sure there's room for comp_name + separator + '(' + ')'. */ + if ((total_size + comp_name_len + 3) < max_tdl_len) + { + /* CRITICAL: named_component_found is not yet set for this call.*/ + total_size += add_tdl_separator (tdl_buf, total_size, + nest_level[cur_nest_level].member_found, + named_component_found); + strcpy (&tdl_buf[total_size], "("); + total_size += 1; + strcpy (&tdl_buf[total_size],comp_name); + total_size += comp_name_len; + strcpy (&tdl_buf[total_size], ")"); + total_size += 1; + } + else + { + overrun_detected = SD_TRUE; + } + named_component_found = SD_TRUE; + } + + if (rt_ptr->el_tag == RT_ARR_END || rt_ptr->el_tag == RT_STR_END) + nest_level[cur_nest_level].member_found = SD_FALSE; + else + { + if (total_size + 1 < max_tdl_len) + { + total_size += add_tdl_separator (tdl_buf, total_size, + nest_level[cur_nest_level].member_found, + named_component_found); + } + else + overrun_detected = SD_TRUE; + nest_level[cur_nest_level].member_found = SD_TRUE; + } + + temp_buf[0] = '\0'; /* start with NULL string */ + switch (rt_ptr->el_tag) + { + case RT_ARR_START : + sprintf (temp_buf, "[%d:", (ST_INT)rt_ptr->u.arr.num_elmnts); + cur_nest_level++; + break; + + case RT_STR_START : + strcpy (temp_buf, "{"); + cur_nest_level++; + break; + + case RT_BOOL : + strcpy (temp_buf, "Bool"); + break; + + case RT_BIT_STRING : + if (rt_ptr->u.p.el_len < 0) + sprintf (temp_buf, "BVstring%d", abs (rt_ptr->u.p.el_len)); + else + sprintf (temp_buf, "Bstring%d", rt_ptr->u.p.el_len); + break; + + case RT_INTEGER : + switch (rt_ptr->u.p.el_len) + { + case 1: + strcpy (temp_buf, "Byte"); + break; + case 2: + strcpy (temp_buf, "Short"); + break; + case 4: + strcpy (temp_buf, "Long"); + break; +#ifdef INT64_SUPPORT + case 8: + strcpy (temp_buf, "Int64"); + break; +#endif + } + break; + + case RT_UNSIGNED : + switch (rt_ptr->u.p.el_len) + { + case 1: + strcpy (temp_buf, "Ubyte"); + break; + case 2: + strcpy (temp_buf, "Ushort"); + break; + case 4: + strcpy (temp_buf, "Ulong"); + break; +#ifdef INT64_SUPPORT + case 8: + strcpy (temp_buf, "Uint64"); + break; +#endif + } + break; + + case RT_FLOATING_POINT : + switch (rt_ptr->u.p.el_len) + { + case 4: + strcpy (temp_buf, "Float"); + break; + case 8: + strcpy (temp_buf, "Double"); + break; + } + break; + + case RT_OCTET_STRING : + if (rt_ptr->u.p.el_len < 0) + sprintf (temp_buf, "OVstring%d", abs (rt_ptr->u.p.el_len)); + else + sprintf (temp_buf, "Ostring%d", rt_ptr->u.p.el_len); + break; + + case RT_VISIBLE_STRING : + if (rt_ptr->u.p.el_len < 0) + sprintf (temp_buf, "Vstring%d", abs (rt_ptr->u.p.el_len)); + else + sprintf (temp_buf, "Fstring%d", rt_ptr->u.p.el_len); + break; + + case RT_GENERAL_TIME : + strcpy (temp_buf, "Gtime"); + break; + + case RT_BINARY_TIME : + sprintf (temp_buf, "Btime%d", rt_ptr->u.p.el_len); + break; + + case RT_BCD : + sprintf (temp_buf, "Bcd%d", (ST_INT)rt_ptr->u.p.el_len); + break; + + case RT_BOOLEANARRAY : + break; + + case RT_UTC_TIME: + strcpy (temp_buf, "Utctime"); + break; + + case RT_UTF8_STRING: + if (rt_ptr->u.p.el_len < 0) + sprintf (temp_buf, "UTF8Vstring%d", (ST_INT) abs (rt_ptr->u.p.el_len)); + else + sprintf (temp_buf, "UTF8string%d", (ST_INT) (rt_ptr->u.p.el_len)); + break; + + case RT_STR_END : + strcpy (temp_buf, "}"); + cur_nest_level--; + break; + + case RT_ARR_END : + strcpy (temp_buf, "]"); + cur_nest_level--; + break; + } + + + temp_size = strlen (temp_buf); + if (temp_size == 0) + { /* If buffer empty, rt_ptr contains unrecognized type*/ + /* DEBUG: this should NEVER happen. Chk for memory corruption. */ + MLOG_ERR1 ("RUNTIME_TYPE contains illegal el_tag = %d", rt_ptr->el_tag); + return (0); /* error */ + } + if (total_size + temp_size < max_tdl_len) + { + strcpy (&tdl_buf[total_size], temp_buf); + total_size += temp_size; + } + else + overrun_detected = SD_TRUE; + + rt_ptr++; /* point to next runtime element*/ + i++; + } /* end main loop*/ + + if (overrun_detected == SD_TRUE) + { + MLOG_NERR1 ("ms_runtime_to_tdl: tdl buffer overrun (max=%d)", max_tdl_len); + total_size = 0; + } + else + { + tdl_buf[total_size] = 0; /* ensure a Null terminator */ + total_size++; /* account for a Null terminator*/ + } + + return (total_size); + } + +/************************************************************************/ +/* add_tdl_separator */ +/************************************************************************/ + +static ST_INT add_tdl_separator (ST_CHAR *tdl_buf, ST_INT index, + ST_BOOLEAN member_found, + ST_BOOLEAN named_component_found) + { + if ((member_found == SD_TRUE) && + (named_component_found == SD_FALSE)) + { + strcpy (&tdl_buf[index], ","); + return (1); + } + else + { + return (0); + } + } + +/************************************************************************/ +/* ms_tdl_to_runtime */ +/* This function converts TDL to ASN.1 and then ASN.1 to RUNTIME_TYPE. */ +/* NOTE: this function allocates array of RUNTIME_TYPE structs by */ +/* calling "ms_runtime_create". The array must be freed by */ +/* calling "ms_runtime_destroy" (DO NOT use M_FREE or chk_free). */ +/************************************************************************/ +RUNTIME_CTRL *ms_tdl_to_runtime (ST_CHAR *tdl, /* TDL string */ + ST_UCHAR *asn1_buf, /* ASN.1 buffer */ + ST_INT asn1_buf_len) /* buffer len */ + { +ST_UCHAR *asn1_start; /* ptr to ASN.1 encoded type */ +RUNTIME_CTRL *rt_ctrl = NULL; /* assume failure */ + + /* NOTE: ms_mk_.. overwrites asn1_buf_len with len of ASN.1 encoding */ + asn1_start = ms_mk_asn1_type (&asn1_buf_len, asn1_buf, tdl); + if (asn1_start) /* successful */ + rt_ctrl = ms_runtime_create (asn1_start, asn1_buf_len, + (UINT_MAX/sizeof(RUNTIME_TYPE))-100); + return (rt_ctrl); + } diff --git a/mmslib/mmsl/ms_tdef2.c b/mmslib/mmsl/ms_tdef2.c new file mode 100644 index 0000000..91f4afa --- /dev/null +++ b/mmslib/mmsl/ms_tdef2.c @@ -0,0 +1,226 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_tdef2.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Functions to assist in using NESTED RUNTIME TYPES */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/01/05 JRB 13 Avoid risky cast to remove const. */ +/* 04/02/03 JRB 12 Add UTF8string support (see RT_UTF8_STRING). */ +/* 12/20/01 JRB 11 Converted to use ASN1R (re-entrant ASN1) */ +/* 11/14/01 EJV 10 Added support for new MMS type UtcTime: */ +/* ms_runtime_to_asn1: add case for RT_UTC_TIME */ +/* 10/18/01 JRB 09 Eliminate warning. */ +/* 07/28/00 JRB 08 Use ms_comp_name_find for everyone. */ +/* 07/13/00 JRB 07 Use new ms_comp_name_find to get comp names. */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 04/14/99 MDE 05 Removed unnecessary include files */ +/* 09/10/98 MDE 04 Removed 'mvlRtNames' declaration */ +/* 08/13/98 MDE 03 Added asn1 encode overrun test to loop */ +/* 03/11/98 MDE 02 Removed NEST_RT_TYPES */ +/* 04/08/97 MDE 01 Fixed 'RT Table too small prob w/named types */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/* ms_runtime_to_tdl */ +/************************************************************************/ +/* Converts RUNTIME TYPE to ASN.1. ASN.1 build must be started */ + +ST_RET ms_runtime_to_asn1 (ASN1_ENC_CTXT *aCtx, SD_CONST RUNTIME_TYPE *rt, ST_INT rt_num) + { +ST_INT i; +ST_INT level; +SD_CONST RUNTIME_TYPE *rt_ptr; +ST_BOOLEAN structComp[ASN1_MAX_LEVEL]; +ST_UCHAR v1; +ST_UCHAR v2; +const ST_CHAR *comp_name; + + S_LOCK_COMMON_RESOURCES (); + + level = 0; + rt_ptr = rt + (rt_num - 1); + for (i = 0; i < rt_num && aCtx->asn1r_encode_overrun == SD_FALSE; ++i, --rt_ptr) + { + switch (rt_ptr->el_tag) + { + case RT_ARR_START : + --level; + /* Finish typeSpecification */ + asn1r_fin_constr (aCtx, 2, CTX, SD_FALSE); + + /* Write numberOfElements */ + asn1r_wr_i32 (aCtx, (ST_INT32) rt_ptr->u.arr.num_elmnts); + asn1r_fin_prim (aCtx, 1,CTX); + + /* Finish array */ + asn1r_fin_constr (aCtx, 1, CTX, SD_FALSE); + break; + + case RT_ARR_END : + ++level; + structComp[level] = SD_FALSE; + asn1r_strt_constr (aCtx); /* Start array */ + asn1r_strt_constr (aCtx); /* Start typeSpecification */ + break; + + case RT_STR_START : + --level; + asn1r_fin_constr (aCtx, 1, CTX, SD_FALSE); /* Finish components */ + asn1r_fin_constr (aCtx, 2, CTX, SD_FALSE); /* Finish structure */ + break; + + case RT_STR_END : + ++level; + structComp[level] = SD_TRUE; + + asn1r_strt_constr (aCtx); /* Start structure */ + asn1r_strt_constr (aCtx); /* Start components */ + /* prepare for first component */ + asn1r_strt_constr (aCtx); /* Start component seq of seq */ + asn1r_strt_constr (aCtx); /* Start component type */ + break; + + case RT_BOOL : + asn1r_fin_prim (aCtx, RT_BOOL, CTX); + break; + + case RT_INTEGER : + asn1r_wr_u8 (aCtx, (ST_UCHAR) (rt_ptr->u.p.el_len * 8)); + asn1r_fin_prim (aCtx, RT_INTEGER, CTX); + break; + + case RT_UNSIGNED : + asn1r_wr_u8 (aCtx, (ST_UCHAR) (rt_ptr->u.p.el_len * 8)); + asn1r_fin_prim (aCtx, RT_UNSIGNED, CTX); + break; + + case RT_FLOATING_POINT : + asn1r_strt_constr (aCtx); + if (rt_ptr->u.p.el_len == 4) /* single precision */ + { + v1 = SNGL_EXP; + if (!m_use_dis_float) + v2 = SNGL_WHOLE; + else + v2 = SNGL_FRACT; + } + else + { + v1 = DOUBL_EXP; + if (!m_use_dis_float) + v2 = DOUBL_WHOLE; + else + v2 = DOUBL_FRACT; + } + asn1r_wr_u8 (aCtx, v1); /* write exp */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_wr_u8 (aCtx, v2); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, RT_FLOATING_POINT, CTX, SD_FALSE); + break; + + case RT_BIT_STRING : + case RT_OCTET_STRING : + case RT_VISIBLE_STRING : + case RT_UTF8_STRING : /* all same encoding w/ different tags*/ + asn1r_wr_i32 (aCtx, (ST_INT32) rt_ptr->u.p.el_len); + asn1r_fin_prim (aCtx, rt_ptr->el_tag, CTX); + break; + + case RT_GENERAL_TIME : + asn1r_fin_prim (aCtx, RT_GENERAL_TIME, CTX); + break; + + case RT_BINARY_TIME : + if (rt_ptr->u.p.el_len == 4) + asn1r_wr_u8 (aCtx, 0); + else + asn1r_wr_u8 (aCtx, 1); + asn1r_fin_prim (aCtx, RT_BINARY_TIME, CTX); + break; + + case RT_UTC_TIME : + asn1r_fin_prim (aCtx, RT_UTC_TIME, CTX); + break; + + case RT_BCD : + asn1r_wr_u8 (aCtx, (ST_UCHAR) rt_ptr->u.p.el_len); + asn1r_fin_prim (aCtx, RT_BCD, CTX); + break; + + case RT_BOOLEANARRAY : + break; + + default : + MLOG_ERR1 ("MS_RUNTIME_TO_ASN1: Invalid element tag (%d)", + rt_ptr->el_tag); + S_UNLOCK_COMMON_RESOURCES (); + return (SD_FAILURE); + break; + } + + if (level > 0 && structComp[level] == SD_TRUE && + rt_ptr->el_tag != RT_STR_END) + { + asn1r_fin_constr (aCtx, 1, CTX, SD_FALSE); /* Finish typeSpec */ + + comp_name = ms_comp_name_find (rt_ptr); + if (strlen (comp_name)) + { + asn1r_wr_vstr (aCtx, comp_name); + asn1r_fin_prim (aCtx, 0, CTX); + } + asn1r_fin_constr (aCtx, SEQ_CODE, UNI, SD_FALSE); + + if ((rt_ptr-1)->el_tag != RT_STR_START) + { + /* prepare for the next component */ + asn1r_strt_constr (aCtx); /* Start component seq of seq */ + asn1r_strt_constr (aCtx); /* Start component type */ + } + } + } + + S_UNLOCK_COMMON_RESOURCES (); + + if (aCtx->asn1r_encode_overrun) + { + MLOG_NERR0 ("ms_runtime_to_asn1 : ASN.1 encode overrun"); + return (SD_FAILURE); + } + return (SD_SUCCESS); + } + + diff --git a/mmslib/mmsl/ms_tdef4.c b/mmslib/mmsl/ms_tdef4.c new file mode 100644 index 0000000..2feec0b --- /dev/null +++ b/mmslib/mmsl/ms_tdef4.c @@ -0,0 +1,51 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003 - 2003, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : ms_tdef4.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Function called by "ms_runtime_create" to find base types when */ +/* building complex types. */ +/* NOTE: This module should be included in a library & should contain */ +/* ONLY "u_ml_get_rt_type", so that the user can easily replace */ +/* this function with a customized function. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* u_ml_get_rt_type */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/21/07 JRB 02 Just log & return error (removes dependence */ +/* on "mvl" library). If base types needed, */ +/* user app should create customized funct. */ +/* 04/24/03 JRB 01 New module. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_vvar.h" + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* u_ml_get_rt_type */ +/* Called by "ms_runtime_create" to find base types (INT32S, etc.). */ +/************************************************************************/ +ST_RET u_ml_get_rt_type (ASN1_DEC_CTXT *aCtx, OBJECT_NAME *type_name, + RUNTIME_TYPE **rt_out, ST_INT *num_rt_out) + { + /* DEBUG: if this error occurs, create customized function in user */ + /* application (see sample applications). */ + MLOG_ERR0 ("u_ml_get_rt_type: Finding base types not supported."); + return (SD_FAILURE); + } diff --git a/mmslib/mmsl/msdataas.c b/mmslib/mmsl/msdataas.c new file mode 100644 index 0000000..95c8eca --- /dev/null +++ b/mmslib/mmsl/msdataas.c @@ -0,0 +1,101 @@ +/***********************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : msdataas.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/02/02 JRB 04 Convert to use ASN1R (re-entrant ASN1). */ +/* 04/28/00 JRB 03 Lint cleanup */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 06/09/97 MDE 01 Modified Runtime Type handling */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* Stub functions, included to allow transparent linking */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +static ST_CHAR *nfStubMsg = "Non-functional stub function called"; +#endif + +/************************************************************************/ +/************************************************************************/ +/* The real version of these functions are found in mmsdataa.c */ + +#ifndef MMS_LITE + +ST_RET ms_asn1_to_locl_aa (NAMED_TYPE *tptr, + ALT_ACCESS *alt_acc, + ST_UCHAR *asn1ptr, /* pointer to ASN.1 'Data' */ + ST_INT asn1len, /* length of ASN.1 'Data' */ + ST_CHAR *dptr) /* local data buffer pointer */ + { + MLOG_NERR0 (nfStubMsg); + return (SD_FAILURE); + } +#endif + +ST_RET ms_asn1_to_local_aa (SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, + ALT_ACCESS *alt_acc, + ST_UCHAR *asn1ptr, + ST_INT asn1len, + ST_CHAR *dptr) + { + MLOG_NERR0 (nfStubMsg); + return (SD_FAILURE); + } + +/************************************************************************/ +/* The real version of these functions are found in mmsdataa.c */ + +#ifndef MMS_LITE + +ST_RET ms_locl_to_asn1_aa (ASN1_ENC_CTXT *aCtx, NAMED_TYPE *tptr, + ALT_ACCESS *alt_acc, + ST_CHAR *dptr) + { + MLOG_NERR0 (nfStubMsg); + return (SD_FAILURE); + } +#endif + + +ST_RET ms_local_to_asn1_aa (ASN1_ENC_CTXT *aCtx, SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, + ALT_ACCESS *alt_acc, + ST_CHAR *dptr) + { + MLOG_NERR0 (nfStubMsg); + return (SD_FAILURE); + } + diff --git a/mmslib/mmsl/rq_ackev.c b/mmslib/mmsl/rq_ackev.c new file mode 100644 index 0000000..9abc569 --- /dev/null +++ b/mmslib/mmsl/rq_ackev.c @@ -0,0 +1,113 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_ackev.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the acknowledge */ +/* event notification operation. It decodes the acknowledge event */ +/* notification response (confirm) & encodes the acknowledge event */ +/* notification request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_ackevnot_rsp */ +/* NOTE : Since the mms_ackevnot_type_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_ackevnot */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the acknowledge event notification request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_ackevnot (ST_INT chan, ACKEVNOT_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_ACK_EVENT_NOT, + M_CAST_MK_FUN (_ms_mk_ackevnot_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_ackevnot */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the acknowledge event notification request. */ +/************************************************************************/ + +ST_RET mpl_ackevnot (ACKEVNOT_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_ACK_EVENT_NOT, + M_CAST_MK_FUN (_ms_mk_ackevnot_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_ackevnot_req */ +/* construct an acknowledge event notification request. */ +/************************************************************************/ + +ST_VOID _ms_mk_ackevnot_req (ASN1_ENC_CTXT *aCtx, ACKEVNOT_REQ_INFO *info) + { + /* check for acknowledgement event condition name */ + if (info->ackec_name_pres) + { /* ack event cond name present */ + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + _ms_wr_mms_objname (aCtx, &info->ackec_name); /* write ack event cond name */ + asn1r_fin_constr (aCtx, 4, CTX, DEF); /* context tag 4 */ + } + + asn1r_strt_constr (aCtx); /* start context tag 3 cstr */ + _ms_wr_mms_evtime (aCtx, &info->evtime); + asn1r_fin_constr (aCtx, 3, CTX, DEF); /* finish context tag 3 */ + + asn1r_wr_i16 (aCtx, info->ack_state); /* write ack state */ + asn1r_fin_prim (aCtx, 2, CTX); /* context tag 2 */ + + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + _ms_wr_mms_objname (aCtx, &info->evenroll_name);/* write event condition name */ + asn1r_fin_constr (aCtx, 0, CTX, DEF); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_ACK_EVENT_NOT,CTX,DEF); /* tag = opcode, ctx cstr */ + } diff --git a/mmslib/mmsl/rq_cancl.c b/mmslib/mmsl/rq_cancl.c new file mode 100644 index 0000000..8fbc16f --- /dev/null +++ b/mmslib/mmsl/rq_cancl.c @@ -0,0 +1,153 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_cancl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the cancel */ +/* operation. It decodes the cancel response (confirm) & encodes */ +/* the cancel request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/28/05 EJV 04 Elim Linux warnings in if (a=b) */ +/* 03/11/04 GLB 03 Cleaned up "thisFileName" */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 01 Added SD_CONST modifiers */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pcon.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) && defined(S_MT_SUPPORT) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ + +/* variables global to the DECODE portion : NONE */ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_cancel_rsp */ +/* This function is called from mmsdec when a response is received and */ +/* the opcode for this operation is decoded. Set up state machine */ +/* function pointers to end the parse, since the parse is complete. */ +/************************************************************************/ + +ST_VOID mms_cancel_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Cancel Response"); + + _mmsdec_rslt->data_pres = SD_FALSE; /* cancel just has invoke id */ + aCtx->asn1r_decode_done = SD_TRUE; + asn1r_set_all_cstr_done (aCtx); + aCtx->asn1r_decode_done_fun = NULL; + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_cancel */ +/* Send cancel request. Returns a pointer to the same request control */ +/* structure that was input unless the cancel request does not get sent.*/ +/************************************************************************/ + +MMSREQ_PEND *mp_cancel (MMSREQ_PEND *reqptr) + { +ST_UCHAR *msg_ptr; +ST_INT msg_len; +LLP_ADDR_INFO add_llp_info; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + if (reqptr -> op > MAX_MMS_OPCODE) + { + mms_op_err = MVE_WRONG_OP; + return ((MMSREQ_PEND *)0); + } + + S_LOCK_COMMON_RESOURCES (); + msg_ptr = _ms_mk_cancel (aCtx, SD_TRUE,m_build_buf,mms_max_msgsize,reqptr -> id); + msg_len = M_BUILD_BUF_END - msg_ptr; /* find length of message */ + + add_llp_info.i.LLC.use_rem_addr = SD_FALSE; + add_llp_info.i.LLC.send_type = CONFIRMED_REQ_PDU; + add_llp_info.i.LLC.req_ptr = (ST_CHAR *)reqptr; + + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + { + mms_op_err = ME_ASN1_ENCODE_OVERRUN; + S_UNLOCK_COMMON_RESOURCES (); + return ((MMSREQ_PEND *)NULL); /* return error code */ + } + else if ((mms_op_err = _mms_send_data (reqptr->chan, msg_len, msg_ptr, + reqptr->context, &add_llp_info)) != 0) + { + S_UNLOCK_COMMON_RESOURCES (); + return ((MMSREQ_PEND *)NULL); /* return error code */ + } + else + { /* Adjust state of service request to be cancelled. */ + reqptr -> cancl_state = CANCEL_REQUESTED; + S_UNLOCK_COMMON_RESOURCES (); + return (reqptr); + } + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_cancel */ +/* Send cancel request. Returns a pointer to the same request control */ +/* structure that was input unless the cancel request does not get sent.*/ +/************************************************************************/ + +ST_RET mpl_cancel (ST_VOID) + { +ST_RET ret; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + mmsl_msg_start = _ms_mk_cancel (aCtx, SD_TRUE, mmsl_enc_buf, mmsl_enc_buf_size, + mmsl_invoke_id); + mmsl_msg_len = (mmsl_enc_buf + mmsl_enc_buf_size) - mmsl_msg_start; + + if (!aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + ret = SD_SUCCESS; + else + ret = ME_ASN1_ENCODE_OVERRUN; + + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } +#endif + +/************************************************************************/ +/* _ms_mk_cancel */ +/* Note that there is only one _ms_mk_cancel function, and it is listed in */ +/* the mmscancl.c module. */ +/************************************************************************/ diff --git a/mmslib/mmsl/rq_concl.c b/mmslib/mmsl/rq_concl.c new file mode 100644 index 0000000..fd4edba --- /dev/null +++ b/mmslib/mmsl/rq_concl.c @@ -0,0 +1,151 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2007, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_concl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the conclude */ +/* operation. It decodes the conclude response (confirm) & */ +/* encodes the conclude request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/01/07 EJV 05 Rem obsolete LLC30... code. */ +/* 02/28/05 EJV 04 Elim Linux warnings in if (a=b) */ +/* 03/11/04 GLB 03 Cleaned up "thisFileName" */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 01 Added SD_CONST modifiers */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pcon.h" +#include "asn1defs.h" +#include "slog.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) && defined(S_MT_SUPPORT) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/* External functions (see mmsconcl) : */ +/* ST_CHAR *_ms_mk_conclude (buf_ptr,buf_len,pdutype) */ + +/************************************************************************/ +/************************************************************************/ +/* mms_conclude_rsp */ +/* NOTE : Since a CONCLUDE is a NULL PDU, the decode is continued */ +/* by '_mms_null_pdu_dec', which simply sets decode done = 1 and sets */ +/* the decode done function to point to the general decode done fun */ +/* See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_conclude */ +/* create and send a conclude request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_conclude (ST_INT chan) + { +ST_UCHAR *msg_ptr; +ST_INT msg_len; +MMSREQ_PEND *reqptr; +LLP_ADDR_INFO add_llp_info; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + S_LOCK_COMMON_RESOURCES (); + + reqptr = _ms_get_req_ptr (chan,MMSOP_CONCLUDE,(ST_CHAR *) 0); + if (!reqptr) + { + S_UNLOCK_COMMON_RESOURCES (); + return ((MMSREQ_PEND *) 0); + } + + msg_ptr = _ms_mk_conclude (aCtx,m_build_buf,mms_max_msgsize,MMSCNCLREQ); + msg_len = M_BUILD_BUF_END - msg_ptr; /* find length */ + + add_llp_info.i.LLC.use_rem_addr = SD_FALSE; + add_llp_info.i.LLC.send_type = CONCLUDE_REQ_PDU; + add_llp_info.i.LLC.req_ptr = (ST_CHAR *)reqptr; + + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + { + mms_op_err = ME_ASN1_ENCODE_OVERRUN; + _ms_deact_pend_req (reqptr); /* move from pend to avail */ + S_UNLOCK_COMMON_RESOURCES (); + return ((MMSREQ_PEND *) 0); /* return error code */ + } + else if ((mms_op_err = _mms_send_data (chan, msg_len, msg_ptr, + reqptr->context, &add_llp_info)) != 0) + { /* need to recover req ctrl */ + _ms_deact_pend_req (reqptr); /* move from pend to avail */ + S_UNLOCK_COMMON_RESOURCES (); + return ((MMSREQ_PEND *) 0); /* return error code */ + } + else + { + mms_chan_info[chan].ctxt.chan_state |= M_CONCL_REQ_PEND; + + /* If a request logging function is installed, call it */ + if (m_log_req_info_fun && (mms_debug_sel & MMS_LOG_REQ)) + (*m_log_req_info_fun) (reqptr, NULL); + + S_UNLOCK_COMMON_RESOURCES (); + return (reqptr); + } + } +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_conclude */ +/* create a conclude request. */ +/************************************************************************/ + +ST_RET mpl_conclude (ST_VOID) + { +ST_RET ret; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + S_LOCK_COMMON_RESOURCES (); + mmsl_msg_start = _ms_mk_conclude (aCtx, mmsl_enc_buf, mmsl_enc_buf_size, MMSCNCLREQ); + mmsl_msg_len = (mmsl_enc_buf + mmsl_enc_buf_size) - mmsl_msg_start; + + if (!aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + ret = SD_SUCCESS; + else + ret = ME_ASN1_ENCODE_OVERRUN; + + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } +#endif + +/************************************************************************/ +/* _ms_mk_conclude */ +/* Note that there is only one _ms_mk_conclude function, and it is listed */ +/* in the mmsconcl.c module. */ +/************************************************************************/ + diff --git a/mmslib/mmsl/rq_defee.c b/mmslib/mmsl/rq_defee.c new file mode 100644 index 0000000..d0ced02 --- /dev/null +++ b/mmslib/mmsl/rq_defee.c @@ -0,0 +1,127 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_defee.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of define event */ +/* enrollment. It decodes the define event enrollment response */ +/* (confirm) & encodes the define event enrollment request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ +/************************************************************************/ +/************************************************************************/ +/* mms_defee_rsp */ +/* NOTE : Since the mms_defee_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_defee */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the define event enrollment request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_defee (ST_INT chan, DEFEE_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DEF_EE, + M_CAST_MK_FUN (_ms_mk_defee_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_defee */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the define event enrollment request. */ +/************************************************************************/ + +ST_RET mpl_defee (DEFEE_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DEF_EE, + M_CAST_MK_FUN (_ms_mk_defee_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_defee_req */ +/* ENCODE a define event enrollment REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_defee_req (ASN1_ENC_CTXT *aCtx, DEFEE_REQ_INFO *info) + { + if (info->ackec_name_pres) + { + asn1r_strt_constr (aCtx); /* start ctx tag 6 constructor */ + _ms_wr_mms_objname (aCtx, &info->ackec_name); /* write ack event cond name */ + asn1r_fin_constr (aCtx, 6,CTX,DEF); /* context specific tag 6 */ + } + + if (info->client_app_pres) + { + asn1r_strt_constr (aCtx); /* start the ctx 5 constr */ + asn1r_wr_delmnt (aCtx, info->client_app,info->client_app_len); + asn1r_fin_constr (aCtx, 5,CTX,DEF); /* finish ctx 5 constructor */ + } + + if (info->evact_name_pres) + { + asn1r_strt_constr (aCtx); /* start ctx tag 4 constructor */ + _ms_wr_mms_objname (aCtx, &info->evact_name); /* write event action name */ + asn1r_fin_constr (aCtx, 4,CTX,DEF); /* context specific tag 4 */ + } + + asn1r_wr_i16 (aCtx, info->alarm_ack_rule); + asn1r_fin_prim (aCtx, 3, CTX); + + asn1r_wr_bitstr (aCtx, (ST_UCHAR *)&info->ec_transitions, 7); + asn1r_fin_prim (aCtx, 2, CTX); + + asn1r_strt_constr (aCtx); /* start ctx tag 1 constructor */ + _ms_wr_mms_objname (aCtx, &info->evcon_name); /* write event condition name */ + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* context specific tag 1 */ + + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &info->evenroll_name);/* write event enrollment name */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context specific tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEF_EE,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsl/rq_evnot.c b/mmslib/mmsl/rq_evnot.c new file mode 100644 index 0000000..d8ec771 --- /dev/null +++ b/mmslib/mmsl/rq_evnot.c @@ -0,0 +1,181 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2004, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_evnot.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the event */ +/* notification service. It encodes the event notification */ +/* request. There is no response (confirm). */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/28/05 JRB 05 Incl suicacse if MMS_LITE not defined. */ +/* 09/17/04 EJV 04 Use new mms_chk_resource. */ +/* 12/12/02 JRB 03 Add ASN1_ENC_CTXT arg to mpl_evnot */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +#ifndef MMS_LITE +#include "mms_pevn.h" +#include "suicacse.h" /* for SE_QUE_FULL only */ + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/* mp_evnot */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the event notification request. */ +/************************************************************************/ + +ST_RET mp_evnot (ST_INT chan, EVNOT_REQ_INFO *info_ptr) + { +ST_RET rc; +ST_INT avail; + + /* locking here will assure that _mms_chk_resource will work in */ + /* multiple threads when mp_* functions are called to send */ + /* unconfirmed requests */ + S_LOCK_COMMON_RESOURCES (); + + avail = _mms_chk_resource (chan); + if (avail > 0) + rc = _mms_unconf_req_send (MMSOP_EVENT_NOT, + M_CAST_MK_FUN (_ms_mk_evnot_req), + chan,(ST_CHAR *)info_ptr); + else + rc = SE_QUE_FULL; + + S_UNLOCK_COMMON_RESOURCES (); + + return (rc); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_evnot */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the event notification request. */ +/************************************************************************/ + +ST_RET mpl_evnot (ASN1_ENC_CTXT *aCtx, EVNOT_REQ_INFO *info_ptr) + { + return (_mms_unconf_req_fin (aCtx, MMSOP_EVENT_NOT, + M_CAST_MK_FUN (_ms_mk_evnot_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_evnot_req */ +/* construct an event notification request. */ +/************************************************************************/ + +ST_VOID _ms_mk_evnot_req (ASN1_ENC_CTXT *aCtx, EVNOT_REQ_INFO *info) + { + if (info->evact_result_pres) + { /* write event action result */ + asn1r_strt_constr (aCtx); /* start context tag 8 cstr */ + asn1r_strt_constr (aCtx); /* start ctx tag 0 or 1 cstr */ + + if (info->evact_result_tag == 1) /* failure, write service error */ + { /* then check for modifier pos */ + _ms_wr_service_err (aCtx, (info->serv_err)->eclass,(info->serv_err)->code, + &(info->serv_err)->adtnl); + asn1r_fin_constr (aCtx, 1, CTX, DEF); + +#ifdef MOD_SUPPORT + if (info->mod_pos_pres) + { + asn1r_wr_u32 (aCtx, info->mod_pos); + asn1r_fin_prim (aCtx, 0, CTX); + } +#endif + } + else /* SD_SUCCESS */ + { +#ifdef CS_SUPPORT /* first check for CS response detail */ + if (info->cs_rdetail_pres) + { + asn1r_strt_constr (aCtx); /* start context tag 79 cstr */ + asn1r_wr_delmnt (aCtx, info->cs_rdetail, info->cs_rdetail_len); + asn1r_fin_constr (aCtx, 79, CTX, DEF); /* CS is cstr 79 */ + } +#endif + asn1r_wr_delmnt (aCtx, info->conf_serv_resp, info->conf_serv_resp_len); + } + asn1r_fin_constr (aCtx, info->evact_result_tag, CTX, DEF); /* cstr 0 or 1 */ + _ms_wr_mms_objname (aCtx, &info->evact_name); /* write event action name */ + asn1r_fin_constr (aCtx, 8, CTX, DEF); /* finish context tag 8 cstr */ + } + + if (info->alarm_ack_rule_pres) + { /* write alarm ack rule */ + asn1r_wr_i16 (aCtx, info->alarm_ack_rule); + asn1r_fin_prim (aCtx, 7, CTX); + } + + if (info->not_lost) + { /* not the defalut */ + asn1r_wr_bool (aCtx, info->not_lost); /* write notification lost */ + asn1r_fin_prim (aCtx, 6, CTX); + } + + asn1r_strt_constr (aCtx); /* start context tag 4 cstr */ + _ms_wr_mms_evtime (aCtx, &info->trans_time); /* write event time */ + asn1r_fin_constr (aCtx, 4, CTX, DEF); /* finish context tag 4 cstr */ + + if (info->cur_state_pres) + { + asn1r_wr_i16 (aCtx, info->cur_state); /* write the current state */ + asn1r_fin_prim (aCtx, 3, CTX); + } + + asn1r_wr_u8 (aCtx, info->severity); /* write the severity */ + asn1r_fin_prim (aCtx, 2, CTX); + + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + _ms_wr_mms_objname (aCtx, &info->evcon_name); /* write event condition name */ + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish the ev con name cstr */ + + asn1r_strt_constr (aCtx); /* start event enrollment name */ + _ms_wr_mms_objname (aCtx, &info->evenroll_name);/* write event enrollment name */ + asn1r_fin_constr (aCtx, 0, CTX, DEF); /* finish eventenrollment cstr */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rq_getcl.c b/mmslib/mmsl/rq_getcl.c new file mode 100644 index 0000000..1993b7a --- /dev/null +++ b/mmslib/mmsl/rq_getcl.c @@ -0,0 +1,225 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_getcl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of get capability */ +/* list. It decodes the get capability list response (confirm) & */ +/* encodes the get capability list request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +static GETCL_RESP_INFO *rsp_info; + +static ST_CHAR **cap_ptr; +static ST_INT max_capabilities; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID getcl_cap_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getcl_get_cap (ASN1_DEC_CTXT *aCtx); +static ST_VOID getcl_cap_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getcl_get_more_follows (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_getcl_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_getcl_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("Get Capability List Response"); + +#if defined(FIXED_DECBUF) + max_capabilities = m_cl_max_getcl_cap; + rsp_size = mmsl_dec_info_size; +#else + /* determine maximum size */ + max_capabilities = _mmsdec_msglen/2; + if (m_cl_max_getcl_cap && (max_capabilities > m_cl_max_getcl_cap)) + max_capabilities = m_cl_max_getcl_cap; + +/* get storage for resp info */ + rsp_size = sizeof (GETCL_RESP_INFO) + + (max_capabilities * (sizeof (ST_CHAR *))); +#endif + +/* get storage for request information */ + rsp_info = (GETCL_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + cap_ptr = (ST_CHAR **) (rsp_info + 1); + rsp_info->more_follows = SD_TRUE; + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, getcl_cap_cstr); + } + +/************************************************************************/ +/* getcl_cap_cstr */ +/* get capability list RESPONSE (confirm) is being decoded: */ +/* capability list constructor was encountered. */ +/************************************************************************/ + +static ST_VOID getcl_cap_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getcl_cap_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, getcl_get_cap); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getcl_cap_cstr_done; + aCtx->asn1r_decode_done_fun = _mms_dec_done_ok; + } + +/************************************************************************/ +/* getcl_get_cap */ +/* get capability list RESPONSE (confirm) is being decoded: */ +/* capability was encountered. */ +/************************************************************************/ + +static ST_VOID getcl_get_cap (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getcl_get_cap"); + + rsp_info->num_of_capab++; /* increment # of capabilities */ + if (rsp_info->num_of_capab > max_capabilities) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + /* copy capability back onto itself shifted by one character */ + *cap_ptr = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_vstr (aCtx, *cap_ptr)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + cap_ptr++; + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, getcl_get_cap); + } + +/************************************************************************/ +/* getcl_cap_cstr_done */ +/* get capability list RESPONSE (confirm) is being decoded: */ +/* capability list constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID getcl_cap_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + /* find actual size for response info */ +/* OK to be done, or may have more follows indicator */ + rsp_size = sizeof (GETCL_RESP_INFO) + + (sizeof (ST_CHAR *) * rsp_info->num_of_capab); + + /* give back unused _mms_dec_info; */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,rsp_size); + rsp_info = (GETCL_RESP_INFO *) _mms_dec_info; + + ASN1R_TAG_ADD (aCtx, CTX,1,getcl_get_more_follows); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* getcl_get_more_follows */ +/* get capability list RESPONSE (confirm) is being decoded: */ +/* more follows was encountered. */ +/************************************************************************/ + +static ST_VOID getcl_get_more_follows (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getcl_get_more_follows"); + + if (asn1r_get_bool (aCtx, &rsp_info->more_follows)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getcl */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get capability list request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_getcl (ST_INT chan, GETCL_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_GET_CAP_LIST, + M_CAST_MK_FUN (_ms_mk_getcl_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getcl */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get capability list request. */ +/************************************************************************/ + +ST_RET mpl_getcl (GETCL_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_GET_CAP_LIST, + M_CAST_MK_FUN (_ms_mk_getcl_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getcl_req */ +/* ENCODE a get capability list REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_getcl_req (ASN1_ENC_CTXT *aCtx, GETCL_REQ_INFO *info) + { + + if (info->cont_after_pres) + { + asn1r_wr_vstr (aCtx, info->continue_after); /* write the continue after */ + asn1r_fin_prim (aCtx, VISTR_CODE,UNI); + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_CAP_LIST,CTX,DEF); /* tag = opcode, context */ + } diff --git a/mmslib/mmsl/rq_getdo.c b/mmslib/mmsl/rq_getdo.c new file mode 100644 index 0000000..35fa83f --- /dev/null +++ b/mmslib/mmsl/rq_getdo.c @@ -0,0 +1,354 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_getdom.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of get domain */ +/* attribute. It decodes the get domain attribute response */ +/* (confirm) & encodes the get domain attribute request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +static GETDOM_RESP_INFO *rsp_info; + + +static ST_CHAR **cap_ptr; +static ST_CHAR **pin_ptr; +static ST_INT max_capabilities; +static ST_INT max_pi_names; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID getdom_get_upl_in_prog (ASN1_DEC_CTXT *aCtx); +static ST_VOID getdom_get_pin (ASN1_DEC_CTXT *aCtx); +static ST_VOID getdom_pin_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getdom_pin_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getdom_get_sharable (ASN1_DEC_CTXT *aCtx); +static ST_VOID getdom_get_mms_deletable (ASN1_DEC_CTXT *aCtx); +static ST_VOID getdom_get_state (ASN1_DEC_CTXT *aCtx); +static ST_VOID getdom_get_cap (ASN1_DEC_CTXT *aCtx); +static ST_VOID getdom_cap_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getdom_cap_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_get_dom_attr_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_get_dom_attr_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("Get Domain Attribute Response"); + +#if defined(FIXED_DECBUF) + max_capabilities = _mmsdec_msglen/2; + max_pi_names = _mmsdec_msglen/2; + rsp_size = mmsl_dec_info_size; +#else + /* determine maximum size */ + max_capabilities = _mmsdec_msglen/2; + max_pi_names = _mmsdec_msglen/2; + if (m_cl_max_getdom_cap && (max_capabilities > m_cl_max_getdom_cap)) + max_capabilities = m_cl_max_getdom_cap; + if (m_cl_max_getdom_pi && (max_pi_names > m_cl_max_getdom_pi)) + max_pi_names = m_cl_max_getdom_pi; + rsp_size = sizeof (GETDOM_RESP_INFO) + + (max_capabilities * (sizeof (ST_CHAR *))) + + (max_pi_names * (sizeof (ST_CHAR *))); + /* get storage for resp info */ +#endif + +/* get storage for request information */ + rsp_info = (GETDOM_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + cap_ptr = (ST_CHAR **) (rsp_info + 1); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, getdom_cap_cstr);/* cap list is next*/ + } + +/************************************************************************/ +/* getdom_cap_cstr */ +/* get domain attribute RESPONSE (confirm) is being decoded: */ +/* capability list constructor was encountered. */ +/************************************************************************/ + +static ST_VOID getdom_cap_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getdom_cap_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, getdom_get_cap); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getdom_cap_cstr_done; + } + +/************************************************************************/ +/* getdom_get_cap */ +/* get domain attribute RESPONSE (confirm) is being decoded: */ +/* capability was encountered. */ +/************************************************************************/ + +static ST_VOID getdom_get_cap (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getdom_get_cap"); + + rsp_info->num_of_capab++; /* increment # of capabilities */ + if (rsp_info->num_of_capab > max_capabilities) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + /* copy capability back onto itself shifted by one character */ + *cap_ptr = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_vstr (aCtx, *cap_ptr)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + cap_ptr++; + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, getdom_get_cap); + } + +/************************************************************************/ +/* getdom_cap_cstr_done */ +/* get domain attribute RESPONSE (confirm) is being decoded: */ +/* capability list constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID getdom_cap_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX, 1, getdom_get_state); + } + +/************************************************************************/ +/* getdom_get_state */ +/* get domain attribute RESPONSE (confirm) is being decoded: */ +/* state was encountered. */ +/************************************************************************/ + +static ST_VOID getdom_get_state (ASN1_DEC_CTXT *aCtx) + { +ST_INT ver; + + MLOG_CDEC0 ("getdom_get_state"); + +#ifndef MMS_LITE + ver = mms_chan_info[_mmsdechan].version; +#else + ver = mmsl_version; +#endif + + if ((asn1r_get_i16 (aCtx, &(rsp_info->state))) || /* get & verify state */ + (rsp_info->state < 0) || + (!ver && rsp_info->state > 5) || /* DIS */ + (ver && rsp_info->state > 15)) /* IS */ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 2, getdom_get_mms_deletable); + } + +/************************************************************************/ +/* getdom_get_mms_deletable */ +/* get domain attribute RESPONSE (confirm) is being decoded: */ +/* mms deletable was encountered. */ +/************************************************************************/ + +static ST_VOID getdom_get_mms_deletable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getdom_get_mms_deletable"); + + if (asn1r_get_bool (aCtx, &(rsp_info->mms_deletable))) /* get mms deletable */ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 3, getdom_get_sharable); + } + +/************************************************************************/ +/* getdom_get_sharable */ +/* get domain attribute RESPONSE (confirm) is being decoded: */ +/* sharable was encountered. */ +/************************************************************************/ + +static ST_VOID getdom_get_sharable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getdom_get_sharable"); + + if (asn1r_get_bool (aCtx, &(rsp_info->sharable))) /* get sharable */ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, getdom_pin_cstr); + } + + +/************************************************************************/ +/* getdom_pin_cstr */ +/* get domain attribute RESPONSE (confirm) is being decoded: */ +/* program invocation name list constructor was encountered. */ +/************************************************************************/ + +static ST_VOID getdom_pin_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getdom_pin_cstr"); + + pin_ptr = (ST_CHAR **) (cap_ptr); + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, getdom_get_pin); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getdom_pin_cstr_done; + } + +/************************************************************************/ +/* getdom_get_pin */ +/* get domain attribute RESPONSE (confirm) is being decoded: */ +/* progran invocation name was encountered. */ +/************************************************************************/ + +static ST_VOID getdom_get_pin (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getdom_get_pin"); + + rsp_info->num_of_pinames++; /* increment # of pi names */ + if (rsp_info->num_of_pinames > max_pi_names) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + /* copy pi name back onto itself shifted by one character */ + *pin_ptr = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_identifier (aCtx, *pin_ptr)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + pin_ptr++; + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, getdom_get_pin); + } + +/************************************************************************/ +/* getdom_pin_cstr_done */ +/* get domain attribute RESPONSE (confirm) is being decoded: */ +/* program invocation name list constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID getdom_pin_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX, 5, getdom_get_upl_in_prog); + } + +/************************************************************************/ +/* getdom_get_upl_in_prog */ +/* get domain attribute RESPONSE (confirm) is being decoded: */ +/* upload in progress was encountered. */ +/************************************************************************/ + +static ST_VOID getdom_get_upl_in_prog (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("getdom_get_upl_in_prog"); + + if (asn1r_get_i8 (aCtx, &(rsp_info->upload_in_progress))) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + /* find actual size for response info */ + rsp_size = sizeof (GETDOM_RESP_INFO) + + (sizeof (ST_CHAR *) * rsp_info->num_of_capab) + + (sizeof (ST_CHAR *) * rsp_info->num_of_pinames); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,rsp_size); + rsp_info = (GETDOM_RESP_INFO *) _mms_dec_info; + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getdom */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get domain attribute request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_getdom (ST_INT chan, GETDOM_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_GET_DOM_ATTR, + M_CAST_MK_FUN (_ms_mk_getdom_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getdom */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get domain attribute request. */ +/************************************************************************/ + +ST_RET mpl_getdom (GETDOM_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_GET_DOM_ATTR, + M_CAST_MK_FUN (_ms_mk_getdom_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getdom_req */ +/* ENCODE a get domain attribute REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_getdom_req (ASN1_ENC_CTXT *aCtx, GETDOM_REQ_INFO *info) + { + asn1r_wr_vstr (aCtx, info->dname); /* write the domain name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_GET_DOM_ATTR,CTX); /* tag = opcode, context */ + } diff --git a/mmslib/mmsl/rq_getea.c b/mmslib/mmsl/rq_getea.c new file mode 100644 index 0000000..828c609 --- /dev/null +++ b/mmslib/mmsl/rq_getea.c @@ -0,0 +1,290 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_geteaa.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the get event */ +/* action attributes. It decodes the get event action attributes */ +/* response (confirm) & encodes the get event action attributes */ +/* request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 04/28/00 JRB 05 Lint cleanup */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETEAA_RESP_INFO *rsp_info; + +#ifdef MOD_SUPPORT +static MODIFIER *mod_ptr; +static ST_INT max_modifiers; +#endif + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID geteaa_get_mms_deletable (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteaa_get_modlist (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteaa_modlist_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteaa_conf_serv_req_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteaa_conf_serv_req_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteaa_conf_serv_req_cstr_done (ASN1_DEC_CTXT *aCtx); +#ifdef CS_SUPPORT +static ST_VOID geteaa_cs_rdetail_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteaa_cs_rdetail_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteaa_cs_rdetail_cstr_done (ASN1_DEC_CTXT *aCtx); +#endif + + +/************************************************************************/ +/************************************************************************/ +/* mms_geteaa_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_geteaa_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("Get Event Action Attributes Response"); + /* find maximum size for response info */ + +#if defined(FIXED_DECBUF) + rsp_size = sizeof (GETEAA_RESP_INFO); +#else +#ifdef MOD_SUPPORT + max_modifiers = _mmsdec_msglen / 2; + rsp_size = sizeof (GETEAA_RESP_INFO) + + (sizeof (MODIFIER) * max_modifiers); + mod_ptr = (MODIFIER *) (rsp_info + 1); +#else + rsp_size = sizeof (GETEAA_RESP_INFO); +#endif +#endif + +/* get storage for request information */ + rsp_info = (GETEAA_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + + ASN1R_TAG_ADD (aCtx, CTX, 0, geteaa_get_mms_deletable); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, geteaa_get_modlist); + } + +/************************************************************************/ +/* geteaa_get_mms_deletable */ +/* Decoding get event action attributes response: mms deletable was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID geteaa_get_mms_deletable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteaa_get_mms_deletable"); + /* read mms deletable */ + if (asn1r_get_bool (aCtx, &(rsp_info->mms_deletable))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, geteaa_get_modlist); + } + +/************************************************************************/ +/* geteaa_get_modlist */ +/* Decoding get event action attributes response: list of modifiers */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID geteaa_get_modlist (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteaa_get_modlist"); + +#ifdef MOD_SUPPORT + _ms_get_mms_modlist (aCtx, mod_ptr, &rsp_info->num_of_modifiers, + max_modifiers, geteaa_modlist_done); +#else /* must be empty if not supported */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = geteaa_modlist_done; +#endif + } + +/************************************************************************/ +/* geteaa_modlist_done */ +/* Decoding get event action attributes response: list of modifiers */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID geteaa_modlist_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteaa_modlist_done"); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, geteaa_conf_serv_req_cstr); + } + +/************************************************************************/ +/* geteaa_conf_serv_req_cstr */ +/* Decoding get event action attributes response: confirmed service */ +/* request constructor was encountered. */ +/************************************************************************/ + +static ST_VOID geteaa_conf_serv_req_cstr (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("geteaa_conf_serv_req_cstr"); + /* find actual size for response info */ + rsp_size = sizeof (GETEAA_RESP_INFO) + + (sizeof (MODIFIER)*rsp_info->num_of_modifiers); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info, rsp_size); + rsp_info = (GETEAA_RESP_INFO *) _mms_dec_info; + + /* get the confirmed service request */ + rsp_info->conf_serv_req = aCtx->asn1r_field_ptr; + + asn1r_parse_next (aCtx, geteaa_conf_serv_req_done); /* parse the contents */ + } + +/************************************************************************/ +/* geteaa_conf_serv_req_done */ +/* Decoding get event action attributes response: confirmed service */ +/* request has been obtained. */ +/************************************************************************/ + +static ST_VOID geteaa_conf_serv_req_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteaa_conf_serv_req_done"); + + rsp_info->conf_serv_req_len = aCtx->asn1r_octetcount; /* save the length */ + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = geteaa_conf_serv_req_cstr_done; + } + +/************************************************************************/ +/* geteaa_conf_serv_req_cstr_done */ +/* Decoding get event action attributes response: confirmed service */ +/* request constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID geteaa_conf_serv_req_cstr_done (ASN1_DEC_CTXT *aCtx) + { +#ifdef CS_SUPPORT + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 79, geteaa_cs_rdetail_cstr); +#endif + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +#ifdef CS_SUPPORT +/************************************************************************/ +/* geteaa_cs_rdetail_cstr */ +/* Decoding get event action attributes response: companion standard */ +/* request detail was encountered. */ +/************************************************************************/ + +static ST_VOID geteaa_cs_rdetail_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteaa_cs_rdetail_cstr"); + + rsp_info->cs_rdetail_pres = SD_TRUE; /* set flag */ + + rsp_info->cs_rdetail = aCtx->asn1r_field_ptr; /* get the CS request detail */ + asn1r_parse_next (aCtx, geteaa_cs_rdetail_done); /* parse the contents */ + } + +/************************************************************************/ +/* geteaa_cs_rdetail_done */ +/************************************************************************/ + +static ST_VOID geteaa_cs_rdetail_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteaa_cs_rdetail_done"); + + rsp_info->cs_rdetail_len = aCtx->asn1r_octetcount; /* save the length */ + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = geteaa_cs_rdetail_cstr_done; + } + +/************************************************************************/ +/* geteaa_cs_rdetail_cstr_done */ +/* event notification request is being decoded: action result success: */ +/* confirmed service response cstr done has been encountered. */ +/************************************************************************/ + +static ST_VOID geteaa_cs_rdetail_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } +#endif + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_geteaa */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the get event action attributes request */ +/************************************************************************/ + +MMSREQ_PEND *mp_geteaa (ST_INT chan, GETEAA_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_GET_EA_ATTR, + M_CAST_MK_FUN (_ms_mk_geteaa_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_geteaa */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get event action attributes request. */ +/************************************************************************/ + +ST_RET mpl_geteaa (GETEAA_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_GET_EA_ATTR, + M_CAST_MK_FUN (_ms_mk_geteaa_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_geteaa_req */ +/* construct a get event action attributes request */ +/************************************************************************/ + +ST_VOID _ms_mk_geteaa_req (ASN1_ENC_CTXT *aCtx, GETEAA_REQ_INFO *info) + { + _ms_wr_mms_objname (aCtx, &info->evact_name); /* write event action name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_EA_ATTR,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rq_getec.c b/mmslib/mmsl/rq_getec.c new file mode 100644 index 0000000..e31f2b9 --- /dev/null +++ b/mmslib/mmsl/rq_getec.c @@ -0,0 +1,321 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_geteca.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of get event */ +/* condition attributes. It decodes the get event condition */ +/* attributes response (confirm) and encodes the get event */ +/* condition attributes request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETECA_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID geteca_var_ref_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteca_get_ec_class (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteca_get_severity (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteca_get_as_reports (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteca_monitored_var_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteca_monitored_var_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteca_get_eval_int (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteca_get_var_ref_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteca_get_undefined (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteca_get_priority (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteca_get_mms_deletable (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_geteca_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_geteca_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Event Condition Attributes Response"); + + +/* get storage for request information */ + rsp_info = (GETECA_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (GETECA_RESP_INFO)); + rsp_info->priority = MMS_NORM_PRIORITY; /* set default value */ + rsp_info->severity = MMS_NORM_SEVERITY; +/* rsp_info->mms_deletable = SD_FALSE; */ +/* rsp_info->as_reports = SD_FALSE; */ +/* rsp_info->addl_detail_pres = SD_FALSE; */ +/* rsp_info->eval_int_pres = SD_FALSE; */ + + ASN1R_TAG_ADD (aCtx, CTX, 0, geteca_get_mms_deletable); + ASN1R_TAG_ADD (aCtx, CTX, 1, geteca_get_ec_class); + } + +/************************************************************************/ +/* geteca_get_mms_deletable */ +/* Decoding get event condition attributes response: mms deletable was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID geteca_get_mms_deletable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteca_get_mms_deletable"); + /* read mms deletable */ + if (asn1r_get_u8 (aCtx, &(rsp_info->mms_deletable))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 1, geteca_get_ec_class); + } + +/************************************************************************/ +/* geteca_get_ec_class */ +/* Decoding get event condition attributes response: ec class was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID geteca_get_ec_class (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteca_get_ec_class"); + /* read event condition class */ + if (asn1r_get_i16 (aCtx, &(rsp_info->eclass))) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + else if ((rsp_info->eclass < 0) || (rsp_info->eclass > 1)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 2, geteca_get_priority); + ASN1R_TAG_ADD (aCtx, CTX, 3, geteca_get_severity); + ASN1R_TAG_ADD (aCtx, CTX, 4, geteca_get_as_reports); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 6, geteca_monitored_var_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 7, geteca_get_eval_int); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* geteca_get_priority */ +/* Decoding get event condition attributes response: priority was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID geteca_get_priority (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteca_get_priority"); + /* read priority */ + if (asn1r_get_u8 (aCtx, &(rsp_info->priority))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 3, geteca_get_severity); + ASN1R_TAG_ADD (aCtx, CTX, 4, geteca_get_as_reports); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 6, geteca_monitored_var_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 7, geteca_get_eval_int); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* geteca_get_severity */ +/* Decoding get event condition attributes response: severity was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID geteca_get_severity (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteca_get_severity"); + /* read severity */ + if (asn1r_get_u8 (aCtx, &(rsp_info->severity))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 4, geteca_get_as_reports); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 6, geteca_monitored_var_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 7, geteca_get_eval_int); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* geteca_get_as_reports */ +/* Decoding get event condition attributes response: alarm summary */ +/* reports was encountered. */ +/************************************************************************/ + +static ST_VOID geteca_get_as_reports (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteca_get_as_reports"); + /* read alarm summary reports */ + if (asn1r_get_u8 (aCtx, &(rsp_info->as_reports))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 6, geteca_monitored_var_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 7, geteca_get_eval_int); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* geteca_monitored_var_cstr */ +/* Decoding get event condition attributes response: monitored variable */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID geteca_monitored_var_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteca_monitored_var_cstr"); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, geteca_get_var_ref_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 1, geteca_get_undefined); + } + +/************************************************************************/ +/* geteca_get_var_ref_cstr */ +/* Decoding get event condition attributes response: variable reference */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID geteca_get_var_ref_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteca_get_var_ref_cstr"); + + rsp_info->mon_var_tag = SD_SUCCESS; /* set to variable reference */ + + _ms_get_va_var_spec (aCtx, &rsp_info->var_ref, geteca_var_ref_done); + } + +/************************************************************************/ +/* geteca_var_ref_done */ +/************************************************************************/ + +static ST_VOID geteca_var_ref_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteca_var_ref_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = NULL; + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level-1] = geteca_monitored_var_cstr_done; + } + +/************************************************************************/ +/* geteca_get_undefined */ +/* Decoding get event condition attributes response: undefined was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID geteca_get_undefined (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteca_get_undefined"); + + rsp_info->mon_var_tag = SD_FAILURE; /* set to undefined */ + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = geteca_monitored_var_cstr_done; + } + +/************************************************************************/ +/* geteca_monitored_var_cstr_done */ +/* Decoding get event condition attributes response: monitored variable */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID geteca_monitored_var_cstr_done (ASN1_DEC_CTXT *aCtx) + { + rsp_info->mon_var_pres = SD_TRUE; + ASN1R_TAG_ADD (aCtx, CTX, 7, geteca_get_eval_int); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* geteca_get_eval_int */ +/* Decoding get event condition attributes response: evaluation */ +/* interval was encountered. */ +/************************************************************************/ + +static ST_VOID geteca_get_eval_int (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteca_get_eval_int"); + + rsp_info->eval_int_pres = SD_TRUE; + /* read evaluation interval */ + if (asn1r_get_u32 (aCtx, &(rsp_info->eval_interval))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_geteca */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get event condition attributes */ +/* request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_geteca (ST_INT chan, GETECA_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_GET_EC_ATTR, + M_CAST_MK_FUN (_ms_mk_geteca_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_geteca */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get event condition attributes request. */ +/************************************************************************/ + +ST_RET mpl_geteca (GETECA_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_GET_EC_ATTR, + M_CAST_MK_FUN (_ms_mk_geteca_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_geteca_req */ +/* construct a get event condition attributes request */ +/************************************************************************/ + +ST_VOID _ms_mk_geteca_req (ASN1_ENC_CTXT *aCtx, GETECA_REQ_INFO *info) + { + _ms_wr_mms_objname (aCtx, &info->evcon_name); /* write the object name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_EC_ATTR,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsl/rq_getee.c b/mmslib/mmsl/rq_getee.c new file mode 100644 index 0000000..ba431f9 --- /dev/null +++ b/mmslib/mmsl/rq_getee.c @@ -0,0 +1,807 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_geteea.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the get event */ +/* enrollment attributes. It decodes the get event enrollment */ +/* attributes response (confirm) & encodes the get event */ +/* enrollment attributes request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 04/28/00 JRB 05 Lint cleanup */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETEEA_RESP_INFO *rsp_info; + +static EVENT_ENROLLMENT *ee_ptr; +static ST_INT max_ev_enrolls; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID _g_eelist_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_evenroll_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_eename_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_eename_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_eename_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_ecname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_ecname_objname (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_ecname_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_ecname_objname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_ecname_undefined (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_ecname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_eaname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_eaname_objname (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_eaname_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_eaname_objname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_eaname_undefined (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_eaname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_client_app_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_app_ref_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_client_app_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_get_mms_deletable (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_get_ee_class (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_get_duration (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_get_invoke (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_get_rem_acc_delay (ASN1_DEC_CTXT *aCtx); +#ifdef CS_SUPPORT +static ST_VOID _g_addl_detail_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_addl_detail_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_addl_detail_cstr_done (ASN1_DEC_CTXT *aCtx); +#endif +static ST_VOID _g_aecname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_aecname_objname (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_aecname_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_aecname_objname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_aecname_undefined (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_aecname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_evenroll_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_eelist_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_get_more_follows (ASN1_DEC_CTXT *aCtx); +static ST_VOID _g_dec_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_geteea_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_geteea_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("Get Event Enrollment Attributes Response"); + +#if defined(FIXED_DECBUF) + max_ev_enrolls = m_cl_max_event_enrollment; + rsp_size = mmsl_dec_info_size; +#else + max_ev_enrolls = _mmsdec_msglen / 2; /* find maximum size for response info */ + if (m_cl_max_event_enrollment && (max_ev_enrolls > m_cl_max_event_enrollment)) + max_ev_enrolls = m_cl_max_event_enrollment; + +/* get storage for request information */ + rsp_size = sizeof (GETEEA_RESP_INFO) + + (sizeof (EVENT_ENROLLMENT) * max_ev_enrolls); +#endif + +/* get storage for request information */ + rsp_info = (GETEEA_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + ee_ptr = (EVENT_ENROLLMENT *) (rsp_info + 1); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, _g_eelist_cstr); + } + +/************************************************************************/ +/* _g_eelist_cstr */ +/* Decoding get event enrollment attributes response: list of event */ +/* enrollment names constructor was encountered. */ +/************************************************************************/ + +static ST_VOID _g_eelist_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_eelist_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, _g_evenroll_cstr); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_eelist_cstr_done; + } + +/************************************************************************/ +/* _g_evenroll_cstr */ +/* decoding get event enrollment attributes response: event enrollment */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID _g_evenroll_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_evenroll_cstr"); + + rsp_info->num_of_evenroll++; /* inc # of event enrollments */ + if (rsp_info->num_of_evenroll > max_ev_enrolls) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, _g_eename_cstr); + } + +/************************************************************************/ +/* _g_eename_cstr */ +/* decoding get event enrollment attributes response: event enrollment */ +/* name constructor was encountered. */ +/************************************************************************/ + +static ST_VOID _g_eename_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_eename_cstr"); + + _ms_get_mms_objname (aCtx, &ee_ptr->evenroll_name, _g_eename_done); + } + +/************************************************************************/ +/* _g_eename_done */ +/* decoding get event enrollment attributes response: event enrollment */ +/* name has been decoded. */ +/************************************************************************/ + +static ST_VOID _g_eename_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_eename_done"); + /* set the cstr done function */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_eename_cstr_done; + } + +/************************************************************************/ +/* _g_eename_cstr_done */ +/* decoding get event enrollment attributes response: event enrollment */ +/* name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID _g_eename_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, _g_ecname_cstr); + } + +/************************************************************************/ +/* _g_ecname_cstr */ +/* decoding get event enrollment attributes response: event condition */ +/* name constructor was encountered */ +/************************************************************************/ + +static ST_VOID _g_ecname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_ecname_cstr"); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, _g_ecname_objname); + ASN1R_TAG_ADD (aCtx, CTX, 1, _g_ecname_undefined); + } + +/************************************************************************/ +/* _g_ecname_objname */ +/* decoding get event enrollment attributes response: event condition */ +/* name object name constructor was encountered. */ +/************************************************************************/ + +static ST_VOID _g_ecname_objname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_ecname_objname"); + + ee_ptr->evcon_name_tag = 0; /* set tag to event condition */ + + _ms_get_mms_objname (aCtx, &ee_ptr->evcon_name, _g_ecname_objname_done); + } + +/************************************************************************/ +/* _g_ecname_objname_done */ +/* decoding get event enrollment attributes response: event condition */ +/* name object name has been obtained. */ +/************************************************************************/ + +static ST_VOID _g_ecname_objname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_ecname_objname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_ecname_objname_cstr_done; + } + +/************************************************************************/ +/* _g_ecname_objname_cstr_done */ +/* decoding get event enrollment attributes response: event condition */ +/* name object name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID _g_ecname_objname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_ecname_cstr_done; + } + +/************************************************************************/ +/* _g_ecname_undefined */ +/* decoding get event enrollment attributes response: event condition */ +/* name undefined primitive was encountered. */ +/************************************************************************/ + +static ST_VOID _g_ecname_undefined (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_ecname_undefined"); + + ee_ptr->evcon_name_tag = 1; /* set tag to undefined */ + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_ecname_cstr_done; + } + +/************************************************************************/ +/* _g_ecname_cstr_done */ +/* decoding get event enrollment attributes response: event condition */ +/* name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID _g_ecname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, _g_eaname_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, _g_client_app_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 4, _g_get_mms_deletable); + ASN1R_TAG_ADD (aCtx, CTX, 5, _g_get_ee_class); + } + +/************************************************************************/ +/* _g_eaname_cstr */ +/* decoding get event enrollment attributes response: event action */ +/* name constructor was encountered */ +/************************************************************************/ + +static ST_VOID _g_eaname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_eaname_cstr"); + + ee_ptr->evact_name_pres = SD_TRUE; /* event action name present */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, _g_eaname_objname); + ASN1R_TAG_ADD (aCtx, CTX, 1, _g_eaname_undefined); + } + +/************************************************************************/ +/* _g_eaname_objname */ +/* decoding get event enrollment attributes response: event action */ +/* name object name constructor was encountered. */ +/************************************************************************/ + +static ST_VOID _g_eaname_objname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_eaname_objname"); + + ee_ptr->evact_name_tag = 0; /* set tag to event action */ + + _ms_get_mms_objname (aCtx, &ee_ptr->evact_name, _g_eaname_objname_done); + } + +/************************************************************************/ +/* _g_eaname_objname_done */ +/* decoding get event enrollment attributes response: event action */ +/* name object name has been obtained. */ +/************************************************************************/ + +static ST_VOID _g_eaname_objname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_eaname_objname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_eaname_objname_cstr_done; + } + +/************************************************************************/ +/* _g_eaname_objname_cstr_done */ +/* decoding get event enrollment attributes response: event action */ +/* name object name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID _g_eaname_objname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_eaname_cstr_done; + } + +/************************************************************************/ +/* _g_eaname_undefined */ +/* decoding get event enrollment attributes response: event action */ +/* name undefined primitive was encountered. */ +/************************************************************************/ + +static ST_VOID _g_eaname_undefined (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_eaname_undefined"); + + ee_ptr->evact_name_tag = 1; /* set tag to undefined */ + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_eaname_cstr_done; + } + +/************************************************************************/ +/* _g_eaname_cstr_done */ +/* decoding get event enrollment attributes response: event action */ +/* name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID _g_eaname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, _g_client_app_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 4, _g_get_mms_deletable); + ASN1R_TAG_ADD (aCtx, CTX, 5, _g_get_ee_class); + } + +/************************************************************************/ +/* _g_client_app_cstr */ +/* Decoding get event enrollment attributes response: client application*/ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID _g_client_app_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_client_app_cstr"); + + ee_ptr->client_app_pres = SD_TRUE; /* set client app present */ + + _ms_get_mms_app_ref (aCtx, &ee_ptr->client_app,&ee_ptr->client_app_len, + _g_app_ref_done); + } + +/************************************************************************/ +/* _g_app_ref_done */ +/* Decoding get event enrollment attributes response: client application*/ +/* has been obtained. */ +/************************************************************************/ + +static ST_VOID _g_app_ref_done (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_client_app_cstr_done; + } + +/************************************************************************/ +/* _g_client_app_cstr_done */ +/* Decoding get event enrollment attributes response: client application*/ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID _g_client_app_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX, 4, _g_get_mms_deletable); + ASN1R_TAG_ADD (aCtx, CTX, 5, _g_get_ee_class); + } + +/************************************************************************/ +/* _g_get_mms_deletable */ +/* Decoding get event enrollment attributes response: mms deletable was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID _g_get_mms_deletable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_get_mms_deletable"); + /* read mms deletable */ + if (asn1r_get_bool (aCtx, &(ee_ptr->mms_deletable))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 5, _g_get_ee_class); + } + +/************************************************************************/ +/* _g_get_ee_class */ +/* Decoding get event enrollment attributes response: event enrollment */ +/* class was encountered. */ +/************************************************************************/ + +static ST_VOID _g_get_ee_class (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_get_ee_class"); + /* read event condition class */ + if (asn1r_get_i16 (aCtx, &(ee_ptr->ee_class))) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + else if ((ee_ptr->ee_class < 0) || (ee_ptr->ee_class > 1)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 6, _g_get_duration); + ASN1R_TAG_ADD (aCtx, CTX, 7, _g_get_invoke); + ASN1R_TAG_ADD (aCtx, CTX, 8, _g_get_rem_acc_delay); +#ifdef CS_SUPPORT + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 9, _g_addl_detail_cstr); +#endif + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,10, _g_aecname_cstr); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_evenroll_cstr_done; + } + +/************************************************************************/ +/* _g_get_duration */ +/* Decoding get event enrollment attributes response: duration was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID _g_get_duration (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_get_duration"); + /* read the duration */ + if (asn1r_get_i16 (aCtx, &(ee_ptr->duration))) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + else if ((ee_ptr->duration < 0) || (ee_ptr->duration > 1)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 7, _g_get_invoke); + ASN1R_TAG_ADD (aCtx, CTX, 8, _g_get_rem_acc_delay); +#ifdef CS_SUPPORT + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 9, _g_addl_detail_cstr); +#endif + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,10, _g_aecname_cstr); + } + +/************************************************************************/ +/* _g_get_invoke */ +/* Decoding get event enrollment attributes response: invoke was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID _g_get_invoke (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_get_invoke"); + + ee_ptr->invoke_id_pres = SD_TRUE; /* set invoke id present */ + + /* read the invoke id */ + if (asn1r_get_u32 (aCtx, &(ee_ptr->invoke_id))) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 8, _g_get_rem_acc_delay); +#ifdef CS_SUPPORT + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 9, _g_addl_detail_cstr); +#endif + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,10, _g_aecname_cstr); + } + +/************************************************************************/ +/* _g_get_rem_acc_delay */ +/* Decoding get event enrollment attributes response: remaining */ +/* acceptable delay was encountered. */ +/************************************************************************/ + +static ST_VOID _g_get_rem_acc_delay (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_get_rem_acc_delay"); + + ee_ptr->rem_acc_delay_pres = SD_TRUE; /* set rem acc delay present */ + + /* read the rem acc delay */ + if (asn1r_get_u32 (aCtx, &(ee_ptr->rem_acc_delay))) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + +#ifdef CS_SUPPORT + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 9, _g_addl_detail_cstr); +#endif + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,10, _g_aecname_cstr); + } + +#ifdef CS_SUPPORT +/************************************************************************/ +/* _g_addl_detail_cstr */ +/* Decoding get event enrollment attributes response: additional detail */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID _g_addl_detail_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_addl_detail_cstr"); + + ee_ptr->addl_detail_pres = SD_TRUE; /* set flag */ + ee_ptr->addl_detail = aCtx->asn1r_field_ptr; + + asn1r_parse_next (aCtx, _g_addl_detail_done); /* parse the contents */ + } + +/************************************************************************/ +/* _g_addl_detail_done */ +/************************************************************************/ + +static ST_VOID _g_addl_detail_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_addl_detail_done"); + + ee_ptr->addl_detail_len = aCtx->asn1r_octetcount; /* save length */ + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_addl_detail_cstr_done; + } + +/************************************************************************/ +/* _g_addl_detail_cstr_done */ +/************************************************************************/ + +static ST_VOID _g_addl_detail_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,10, _g_aecname_cstr); + } +#endif + +/************************************************************************/ +/* _g_aecname_cstr */ +/* decoding get event enrollment attributes response: acknowledgement */ +/* event condition name constructor was encountered */ +/************************************************************************/ + +static ST_VOID _g_aecname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_aecname_cstr"); + + ee_ptr->ackec_name_pres = SD_TRUE; /* event action name present */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, _g_aecname_objname); + ASN1R_TAG_ADD (aCtx, CTX, 1, _g_aecname_undefined); + } + +/************************************************************************/ +/* _g_aecname_objname */ +/* decoding get event enrollment attributes response: acknowledgement */ +/* event condition name object name was encountered. */ +/************************************************************************/ + +static ST_VOID _g_aecname_objname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_aecname_objname"); + + ee_ptr->ackec_name_tag = 0; /* set tag to event action */ + + _ms_get_mms_objname (aCtx, &ee_ptr->ackec_name, _g_aecname_objname_done); + } + +/************************************************************************/ +/* _g_aecname_objname_done */ +/* decoding get event enrollment attributes response: acknowledgement */ +/* event condition name object name has been obtained. */ +/************************************************************************/ + +static ST_VOID _g_aecname_objname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_aecname_objname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_aecname_objname_cstr_done; + } + +/************************************************************************/ +/* _g_aecname_objname_cstr_done */ +/* decoding get event enrollment attributes response: acknowledgement */ +/* event condition name object name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID _g_aecname_objname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_aecname_cstr_done; + } + +/************************************************************************/ +/* _g_aecname_undefined */ +/* decoding get event enrollment attributes response: acknowledgement */ +/* event condition name undefined primitive was encountered. */ +/************************************************************************/ + +static ST_VOID _g_aecname_undefined (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_aecname_undefined"); + + ee_ptr->ackec_name_tag = 1; /* set tag to undefined */ + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_aecname_cstr_done; + } + +/************************************************************************/ +/* _g_aecname_cstr_done */ +/* decoding get event enrollment attributes response: acknowledgement */ +/* event condition name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID _g_aecname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _g_evenroll_cstr_done; + } + +/************************************************************************/ +/* _g_evenroll_cstr_done */ +/* Decoding get event enrollment attributes response: event enrollment */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID _g_evenroll_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ee_ptr++; /* point to where next will go */ + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, _g_evenroll_cstr); + } + +/************************************************************************/ +/* _g_eelist_cstr_done */ +/* Decoding get event enrollment attributes response: list of event */ +/* enrollments constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID _g_eelist_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, _g_get_more_follows); + + aCtx->asn1r_decode_done_fun = _g_dec_done; /* ok to be done */ + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* _g_get_more_follows */ +/* Decoding get event enrollment attributes response: more follows was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID _g_get_more_follows (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("_g_get_more_follows"); + /* read more follows */ + if (asn1r_get_bool (aCtx, &(rsp_info->more_follows))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* _g_dec_done */ +/* decode done, realloc the structure to desired size */ +/************************************************************************/ + +static ST_VOID _g_dec_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + /* find actual size for request info */ + rsp_size = sizeof (GETEEA_RESP_INFO) + + (sizeof (EVENT_ENROLLMENT) * rsp_info->num_of_evenroll); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,rsp_size); + rsp_info = (GETEEA_RESP_INFO *) _mms_dec_info; + + _mms_dec_done_ok (aCtx); + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_geteea */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the get event enrollment attributes request */ +/************************************************************************/ + +MMSREQ_PEND *mp_geteea (ST_INT chan, GETEEA_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_GET_EE_ATTR, + M_CAST_MK_FUN (_ms_mk_geteea_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_geteea */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get event enrollment attributes request. */ +/************************************************************************/ + +ST_RET mpl_geteea (GETEEA_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_GET_EE_ATTR, + M_CAST_MK_FUN (_ms_mk_geteea_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_geteea_req */ +/* construct a get event enrollment attributes request */ +/************************************************************************/ + +ST_VOID _ms_mk_geteea_req (ASN1_ENC_CTXT *aCtx, GETEEA_REQ_INFO *info) + { +ST_INT i; +OBJECT_NAME *obj_ptr; + + if (info->ca_name_pres) + { + asn1r_strt_constr (aCtx); /* start ctx tag 5 constructor */ + _ms_wr_mms_objname (aCtx, &info->ca_name); /* write continue after name */ + asn1r_fin_constr (aCtx, 5,CTX,DEF); /* finish ctx tag 5 constructor */ + } + + if (info->evact_name_pres) + { + asn1r_strt_constr (aCtx); /* start ctx tag 4 constructor */ + _ms_wr_mms_objname (aCtx, &info->evact_name); /* write event enrollment name */ + asn1r_fin_constr (aCtx, 4,CTX,DEF); /* finish ctx tag 4 constructor */ + } + + if (info->evcon_name_pres) + { + asn1r_strt_constr (aCtx); /* start ctx tag 3 constructor */ + _ms_wr_mms_objname (aCtx, &info->evcon_name); /* write event condition name */ + asn1r_fin_constr (aCtx, 3,CTX,DEF); /* finish ctx tag 3 constructor */ + } + + if (info->client_app_pres) + { + asn1r_strt_constr (aCtx); /* start ctx tag 2 constructor */ + asn1r_wr_delmnt (aCtx, info->client_app,info->client_app_len); + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* finish ctx tag 2 constructor */ + } + + if (info->eenames_pres) + { + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + obj_ptr = (OBJECT_NAME *) (info + 1); + obj_ptr +=info->num_of_eenames-1; /* point to last object name */ + for (i = 0; i < info->num_of_eenames; i++) + { + _ms_wr_mms_objname (aCtx, obj_ptr); + obj_ptr--; + } + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish context tag 1 cstr */ + } + + if (info->scope_of_req != 1) + { /* not the default (1 = client) */ + asn1r_wr_i16 (aCtx, info->scope_of_req); /* write the scope of request */ + asn1r_fin_prim (aCtx, 0, CTX); /* ctx tag 0 */ + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_EE_ATTR,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rq_getpi.c b/mmslib/mmsl/rq_getpi.c new file mode 100644 index 0000000..0aab577 --- /dev/null +++ b/mmslib/mmsl/rq_getpi.c @@ -0,0 +1,327 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_getpi.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of get program */ +/* invocation attribute. It decodes the get program invocation */ +/* attribute response (confirm) & encodes the get program */ +/* invocation attribute request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETPI_RESP_INFO *rsp_info; + +static ST_CHAR **dom_ptr; +static ST_INT max_domain_names; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID getpi_get_monitor (ASN1_DEC_CTXT *aCtx); +static ST_VOID getpi_get_start_arg (ASN1_DEC_CTXT *aCtx); +static ST_VOID getpi_domain_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getpi_get_reusable (ASN1_DEC_CTXT *aCtx); +static ST_VOID getpi_get_mms_deletable (ASN1_DEC_CTXT *aCtx); +static ST_VOID getpi_get_domain_name (ASN1_DEC_CTXT *aCtx); +static ST_VOID getpi_domain_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getpi_get_state (ASN1_DEC_CTXT *aCtx); +static ST_VOID extern_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_get_pi_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_get_pi_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("Get Program Invocation Attribute Response"); + +#if defined(FIXED_DECBUF) + max_domain_names = m_cl_max_getpi_doms; + rsp_size = mmsl_dec_info_size; +#else + /* determine maximum size */ + max_domain_names = _mmsdec_msglen/2; + if (m_cl_max_getpi_doms && (max_domain_names > m_cl_max_getpi_doms)) + max_domain_names = m_cl_max_getpi_doms; + + /* get storage for resp info */ + rsp_size = sizeof (GETPI_RESP_INFO) + (max_domain_names * (sizeof (ST_CHAR *))); +#endif + +/* get storage for request information */ + rsp_info = (GETPI_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + dom_ptr = (ST_CHAR **) (rsp_info + 1); + ASN1R_TAG_ADD (aCtx, CTX, 0, getpi_get_state); /* state is next */ + } + +/************************************************************************/ +/* getpi_get_state */ +/* get program invocation attribute RESPONSE (confirm) is being decoded:*/ +/* decode the state. */ +/************************************************************************/ + +static ST_VOID getpi_get_state (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getpi_get_state"); + + if (asn1r_get_i16 (aCtx, &(rsp_info->state))) /* read state from the message */ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, getpi_domain_cstr); + } + +/************************************************************************/ +/* getpi_domain_cstr */ +/* get program invocation attribute RESPONSE (confirm) is being decoded:*/ +/* domain name list constructor was encountered. */ +/************************************************************************/ + +static ST_VOID getpi_domain_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getpi_domain_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, getpi_get_domain_name); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getpi_domain_cstr_done; + } + +/************************************************************************/ +/* getpi_get_domain_name */ +/* get program invocation attribute RESPONSE (confirm) is being decoded:*/ +/* domain name was encountered. */ +/************************************************************************/ + +static ST_VOID getpi_get_domain_name (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getpi_get_domain_name"); + + rsp_info->num_of_dnames++; /* increment # of domain names */ + if (rsp_info->num_of_dnames > max_domain_names) + { /* too many domain names */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + if (aCtx->asn1r_elmnt_len > MAX_IDENT_LEN) + { /* domain name is too ST_INT32 */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + /* copy domain name back onto itself shifted by one character */ + *dom_ptr = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_identifier (aCtx, *dom_ptr)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + dom_ptr++; + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, getpi_get_domain_name); + } + +/************************************************************************/ +/* getpi_domain_cstr_done */ +/* get program invocation attribute RESPONSE (confirm) is being decoded:*/ +/* domain name list constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID getpi_domain_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + rsp_size = sizeof (GETPI_RESP_INFO) + + (sizeof (ST_CHAR *) * rsp_info->num_of_dnames); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,rsp_size); + rsp_info = (GETPI_RESP_INFO *) _mms_dec_info; + + + ASN1R_TAG_ADD (aCtx, CTX, 2, getpi_get_mms_deletable); + } + +/************************************************************************/ +/* getpi_get_mms_deletable */ +/* get program invocation attribute RESPONSE (confirm) is being decoded:*/ +/* decode the mms deletable flag. */ +/************************************************************************/ + +static ST_VOID getpi_get_mms_deletable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getpi_get_mms_deletable"); + + if (asn1r_get_bool (aCtx, &(rsp_info->mms_deletable))) /* read mms deletable */ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + ASN1R_TAG_ADD (aCtx, CTX, 3, getpi_get_reusable); + } + +/************************************************************************/ +/* getpi_get_reusable */ +/* get program invocation attribute RESPONSE (confirm) is being decoded:*/ +/* decode the mms reusable flag. */ +/************************************************************************/ + +static ST_VOID getpi_get_reusable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getpi_get_reusable"); + + if (asn1r_get_bool (aCtx, &(rsp_info->reusable))) /* read mms deletable */ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + ASN1R_TAG_ADD (aCtx, CTX, 4, getpi_get_monitor); + } + +/************************************************************************/ +/* getpi_get_monitor */ +/* get program invocation attribute RESPONSE (confirm) is being decoded:*/ +/* decode the monitor flag. */ +/************************************************************************/ + +static ST_VOID getpi_get_monitor (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getpi_get_monitor"); + + if (asn1r_get_bool (aCtx, &(rsp_info->monitor))) /* read monitor from message */ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + ASN1R_TAG_ADD (aCtx, CTX, 5, getpi_get_start_arg); + +/* If MMS IS, Check for ENCODED string */ +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + _ms_chk_for_extern (aCtx, &rsp_info->start_arg_len, + &rsp_info->start_arg, + extern_done); + } + +/************************************************************************/ +/* getpi_get_start_arg */ +/* get program invocation attribute RESPONSE (confirm) is being decoded:*/ +/* decode the start argument. */ +/************************************************************************/ + +static ST_VOID getpi_get_start_arg (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getpi_get_start_arg"); + + rsp_info->start_arg = (ST_UCHAR *) aCtx->asn1r_field_ptr - 1; + rsp_info->start_arg_type = ARG_TYPE_SIMPLE; + + if (asn1r_get_vstr (aCtx, (ST_CHAR *) rsp_info->start_arg)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* extern_done */ +/************************************************************************/ + +static ST_VOID extern_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("extern_done"); + + rsp_info->start_arg_type = ARG_TYPE_ENCODED; + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getpi */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get program invocation attrubute */ +/* request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_getpi (ST_INT chan, GETPI_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_GET_PI_ATTR, + M_CAST_MK_FUN (_ms_mk_getpi_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getpi */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get program invocation attrubute request. */ +/************************************************************************/ + +ST_RET mpl_getpi (GETPI_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_GET_PI_ATTR, + M_CAST_MK_FUN (_ms_mk_getpi_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getpi_req */ +/* ENCODE a get program invocation attribute REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_getpi_req (ASN1_ENC_CTXT *aCtx, GETPI_REQ_INFO *info) + { + + asn1r_wr_vstr (aCtx, info->piname); /* write pgm invocation name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_GET_PI_ATTR,CTX); /* tag = opcode, context */ + } diff --git a/mmslib/mmsl/rq_getty.c b/mmslib/mmsl/rq_getty.c new file mode 100644 index 0000000..c2572b9 --- /dev/null +++ b/mmslib/mmsl/rq_getty.c @@ -0,0 +1,141 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_gettype.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the get named */ +/* type attributes. It decodes the get named type attributes */ +/* response (confirm) & encodes the get named type attributes */ +/* request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETTYPE_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID gettype_type_spec_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID gettype_get_mms_deletable (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_get_type_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_get_type_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Named Type Attributes Response"); + +/* get storage for request information */ + rsp_info = (GETTYPE_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (GETTYPE_RESP_INFO)); + ASN1R_TAG_ADD (aCtx, CTX, 0, gettype_get_mms_deletable); + } + +/************************************************************************/ +/* gettype_get_mms_deletable */ +/* Decoding get named type attributes response: mms deletable was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID gettype_get_mms_deletable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("gettype_get_mms_deletable"); + /* read mms deletable */ + if (asn1r_get_bool (aCtx, &(rsp_info->mms_deletable))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + _ms_get_va_type_spec (aCtx, &rsp_info->type_spec, gettype_type_spec_done); + } + +/************************************************************************/ +/* gettype_type_spec_done */ +/* Decoding get named type attributes response: type specification has */ +/* been decoded. */ +/************************************************************************/ + +static ST_VOID gettype_type_spec_done (ASN1_DEC_CTXT *aCtx) + { + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_gettype */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get named type attributes request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_gettype (ST_INT chan, GETTYPE_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_GET_TYPE, + M_CAST_MK_FUN (_ms_mk_gettype_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_gettype */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get named type attributes request. */ +/************************************************************************/ + +ST_RET mpl_gettype (GETTYPE_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_GET_TYPE, + M_CAST_MK_FUN (_ms_mk_gettype_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_gettype_req */ +/* construct a get named type attributes request */ +/************************************************************************/ + +ST_VOID _ms_mk_gettype_req (ASN1_ENC_CTXT *aCtx, GETTYPE_REQ_INFO *info) + { + _ms_wr_mms_objname (aCtx, &info->type_name); /* write the type name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_TYPE,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rq_getva.c b/mmslib/mmsl/rq_getva.c new file mode 100644 index 0000000..ca441f7 --- /dev/null +++ b/mmslib/mmsl/rq_getva.c @@ -0,0 +1,225 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_getvar.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the get variable */ +/* access attributes. It decodes the get variable access */ +/* attributes response (confirm) & encodes the get variable access */ +/* attributes request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETVAR_RESP_INFO *rsp_info; + + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/* static functions with multiple references */ + +static ST_VOID getvar_typespec_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getvar_typespec_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getvar_address_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getvar_address_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getvar_address_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getvar_get_mms_deletable (ASN1_DEC_CTXT *aCtx); +static ST_VOID getvar_typespec_cstr_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_get_var_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_get_var_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Variable Access Attributes Response"); + +/* get storage for request information */ + rsp_info = (GETVAR_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (GETVAR_RESP_INFO)); + rsp_info->address_pres = SD_FALSE; /* set default value */ + + ASN1R_TAG_ADD (aCtx, CTX, 0, getvar_get_mms_deletable); + } + +/************************************************************************/ +/* getvar_get_mms_deletable */ +/* Decoding get variable access attributes response: mms deletable was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID getvar_get_mms_deletable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getvar_get_mms_deletable"); + /* read mms deletable */ + if (asn1r_get_bool (aCtx, &(rsp_info->mms_deletable))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, getvar_address_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, getvar_typespec_cstr); + } + +/************************************************************************/ +/* getvar_address_cstr */ +/* get variable access attributes request: address constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID getvar_address_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getvar_address_cstr"); + + rsp_info->address_pres = SD_TRUE; /* set address present */ + + _ms_get_va_address (aCtx, &rsp_info->address, getvar_address_done); + } + +/************************************************************************/ +/* getvar_address_done */ +/* get variable access attributes request: address has been decoded */ +/************************************************************************/ + +static ST_VOID getvar_address_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getvar_address_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getvar_address_cstr_done; + } + +/************************************************************************/ +/* getvar_address_cstr_done */ +/* get variable access attributes request: address constructor done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID getvar_address_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, getvar_typespec_cstr); + } + +/************************************************************************/ +/* getvar_typespec_cstr */ +/* get variable access attributes request: type spec constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID getvar_typespec_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getvar_typespec_cstr"); + + _ms_get_va_type_spec (aCtx, &rsp_info->type_spec, getvar_typespec_done); + } + +/************************************************************************/ +/* getvar_typespec_done */ +/* get variable access attributes request: type spec has been decoded */ +/************************************************************************/ + +static ST_VOID getvar_typespec_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getvar_typespec_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getvar_typespec_cstr_done; + } + +/************************************************************************/ +/* getvar_typespec_cstr_done */ +/* get variable access attributes request: typespec constructor done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID getvar_typespec_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getvar */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the get variable access attributes request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_getvar (ST_INT chan, GETVAR_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_GET_VAR, + M_CAST_MK_FUN (_ms_mk_getvar_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getvar */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get variable access attributes request. */ +/************************************************************************/ + +ST_RET mpl_getvar (GETVAR_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_GET_VAR, + M_CAST_MK_FUN (_ms_mk_getvar_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getvar_req */ +/* construct a get variable access attributes request */ +/************************************************************************/ + +ST_VOID _ms_mk_getvar_req (ASN1_ENC_CTXT *aCtx, GETVAR_REQ_INFO *info) + { + if (info->req_tag == 1) + { + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + _ms_wr_va_address (aCtx, &info->address); /* write the address */ + asn1r_fin_constr (aCtx, 1, CTX, DEF); /* finish context tag 1 cstr */ + } + else + { + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + _ms_wr_mms_objname (aCtx, &info->name); /* write the object name */ + asn1r_fin_constr (aCtx, 0, CTX, DEF); /* finish context tag 0 cstr */ + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_VAR,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rq_getvl.c b/mmslib/mmsl/rq_getvl.c new file mode 100644 index 0000000..0270d75 --- /dev/null +++ b/mmslib/mmsl/rq_getvl.c @@ -0,0 +1,187 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_getvlist.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the get named */ +/* variable list attributes. It decodes the get named variable */ +/* list attributes response (confirm) & encodes the get named */ +/* variable list attributes request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETVLIST_RESP_INFO *rsp_info; + +static VARIABLE_LIST *vl_ptr; +static ST_INT max_vars; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID getvlist_list_of_var_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getvlist_get_varlist (ASN1_DEC_CTXT *aCtx); +static ST_VOID getvlist_get_mms_deletable (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_get_vlist_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_get_vlist_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("Get Named Variable List Attributes Response"); + +#if defined(FIXED_DECBUF) + max_vars = m_cl_max_getvla_vars; + rsp_size = mmsl_dec_info_size; +#else + /* find maximum storage required */ + max_vars = _mmsdec_msglen / 4; + if (m_cl_max_getvla_vars && (max_vars > m_cl_max_getvla_vars)) + max_vars = m_cl_max_getvla_vars; + + rsp_size = sizeof (GETVLIST_RESP_INFO) + + (sizeof (VARIABLE_LIST) * max_vars); +#endif + +/* get storage for request information */ + rsp_info = (GETVLIST_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + vl_ptr = (VARIABLE_LIST *) (rsp_info + 1); + + ASN1R_TAG_ADD (aCtx, CTX, 0, getvlist_get_mms_deletable); + } + +/************************************************************************/ +/* getvlist_get_mms_deletable */ +/* Decoding get named variable list attributes response: mms deletable */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID getvlist_get_mms_deletable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getvlist_get_mms_deletable"); + /* read mms deletable */ + if (asn1r_get_bool (aCtx, &(rsp_info->mms_deletable))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, getvlist_get_varlist); + } + +/************************************************************************/ +/* getvlist_get_varlist */ +/* Decoding get named variable list attributes response: list of */ +/* variables constructor was encountered. */ +/************************************************************************/ + +static ST_VOID getvlist_get_varlist (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getvlist_get_varlist"); + + _ms_get_va_var_list (aCtx, vl_ptr, &rsp_info->num_of_variables, + max_vars, getvlist_list_of_var_done); + } + +/************************************************************************/ +/* getvlist_list_of_var_done */ +/* get named variable list attributes request: list of variables has */ +/* been obtained. */ +/************************************************************************/ + +static ST_VOID getvlist_list_of_var_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("getvlist_list_of_var_done"); + /* find actual size for request info */ + rsp_size = sizeof (GETVLIST_RESP_INFO) + + (sizeof (VARIABLE_LIST) * rsp_info->num_of_variables); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,rsp_size); + rsp_info = (GETVLIST_RESP_INFO *) _mms_dec_info; + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getvlist */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the get named variable list attributes */ +/* request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_getvlist (ST_INT chan, GETVLIST_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_GET_VLIST, + M_CAST_MK_FUN (_ms_mk_getvlist_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getvlist */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get named variable list attributes request. */ +/************************************************************************/ + +ST_RET mpl_getvlist (GETVLIST_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_GET_VLIST, + M_CAST_MK_FUN (_ms_mk_getvlist_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getvlist_req */ +/* construct a get named variable list attributes request */ +/************************************************************************/ + +ST_VOID _ms_mk_getvlist_req (ASN1_ENC_CTXT *aCtx, GETVLIST_REQ_INFO *info) + { + _ms_wr_mms_objname (aCtx, &info->vl_name); /* write named var list name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_VLIST,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rq_ident.c b/mmslib/mmsl/rq_ident.c new file mode 100644 index 0000000..d40874f --- /dev/null +++ b/mmslib/mmsl/rq_ident.c @@ -0,0 +1,247 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_ident.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the Identify */ +/* service. It decodes the Identify response (indication) and */ +/* encodes the Identify request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +static IDENT_RESP_INFO *info; +static ST_CHAR *vstr; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID ident_get_model (ASN1_DEC_CTXT *aCtx); +static ST_VOID ident_get_vendor (ASN1_DEC_CTXT *aCtx); +static ST_VOID ident_get_rev (ASN1_DEC_CTXT *aCtx); +static ST_VOID ident_start_as (ASN1_DEC_CTXT *aCtx); +static ST_VOID ident_get_as (ASN1_DEC_CTXT *aCtx); +static ST_VOID ident_as_seq_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_identify_rsp */ +/* Function called to decode an Identify response PDU after the PDU */ +/* type has been determined. Sets up state machine function pointers */ +/* and returns, letting the ASN1DE tools take over. */ +/************************************************************************/ + +ST_VOID mms_identify_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Identify Response"); + + +/* get storage for request information */ + info = (IDENT_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (IDENT_RESP_INFO)); + ASN1R_TAG_ADD (aCtx, CTX,0,ident_get_vendor); + } + +/************************************************************************/ +/* ident_get_vendor */ +/* Identify response is being decoded: vendor name has been encountered.*/ +/************************************************************************/ + +static ST_VOID ident_get_vendor (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("ident_get_vendor"); + +/* copy vendor name back onto itself shifted by one character */ + + vstr = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_vstr (aCtx, vstr)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + if (strlen (vstr) < MAX_VEND_LEN) + strcpy (info->vend, vstr); + else + memcpy (info->vend, vstr, MAX_VEND_LEN); /* only take up to MAX_VEND_LEN */ + info->vend[ MAX_VEND_LEN ] = 0x00; /* NULL term. end just in case */ + + ASN1R_TAG_ADD (aCtx, CTX,1,ident_get_model); + } + + +/************************************************************************/ +/* ident_get_model */ +/* Identify response is being decoded: model name has been encountered. */ +/************************************************************************/ + +static ST_VOID ident_get_model (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("ident_get_model"); + + vstr = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_vstr (aCtx, vstr)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + if (strlen (vstr) < MAX_MOD_LEN) + strcpy (info->model, vstr); + else + memcpy (info->model, vstr, MAX_MOD_LEN); /* only take up to MAX_MOD_LEN */ + info->model[ MAX_MOD_LEN ] = 0x00; /* NULL term. end just in case */ + + ASN1R_TAG_ADD (aCtx, CTX,2,ident_get_rev); + } + +/************************************************************************/ +/* ident_get_rev */ +/* Identify response is being decoded: revision name was encountered. */ +/************************************************************************/ + +static ST_VOID ident_get_rev (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("ident_get_rev"); + + vstr = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_vstr (aCtx, vstr)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + if (strlen (vstr) < MAX_REV_LEN) + strcpy (info->rev, vstr); + else + memcpy (info->rev, vstr, MAX_REV_LEN); /* only take up to MAX_REV_LEN */ + info->rev[ MAX_REV_LEN ] = 0x00; /* NULL term. end just in case */ + + + _ms_set_cs_check (aCtx); /* check for CS info */ + +/* if using IS, could have a list of abstract syntax's following */ + +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,3,ident_start_as); +#else + if (mmsl_version) /* IS */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,3,ident_start_as); +#endif + } + +/************************************************************************/ +/* ident_start_as */ +/* Identify response is being decoded: AS sequence detected */ +/************************************************************************/ + +static ST_VOID ident_start_as (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("ident_start_as"); + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = ident_as_seq_done; + + ASN1R_TAG_ADD (aCtx, UNI,OBJ_ID_CODE,ident_get_as); + } + +/************************************************************************/ +/* ident_get_as */ +/* Identify response is being decoded: AS obj id found */ +/************************************************************************/ + +static ST_VOID ident_get_as (ASN1_DEC_CTXT *aCtx) + { +ST_INT new_size; +struct mms_obj_id *obj; + + MLOG_CDEC0 ("ident_get_as"); + + new_size = sizeof (IDENT_RESP_INFO) + + (sizeof (struct mms_obj_id) * (info->num_as+1)); + + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,new_size); + info = (IDENT_RESP_INFO *) _mms_dec_info; + obj = (struct mms_obj_id *) (info +1); /* point to first */ + obj += info->num_as; /* point to next spot */ + + + if (asn1r_get_objid (aCtx, obj->comps,&obj->num_comps)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + +/* get ready for another in the sequence */ + ASN1R_TAG_ADD (aCtx, UNI,OBJ_ID_CODE,ident_get_as); + info->num_as++; + } + +/************************************************************************/ +/* ident_as_seq_done */ +/* Identify response is being decoded: AS sequence complete */ +/************************************************************************/ + +static ST_VOID ident_as_seq_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("ident_as_seq_done"); + + _ms_set_cs_check (aCtx); /* check for CS info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_ident */ +/* This function is called from the user to ENCODE and send the */ +/* Identify request PDU. */ +/************************************************************************/ + +MMSREQ_PEND *mp_ident (ST_INT chan) + { + return (_mms_send_null_req (chan,MMSOP_IDENTIFY)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_ident */ +/* This function is called from the user to ENCODE and send the */ +/* Identify request PDU. */ +/************************************************************************/ + +ST_RET mpl_ident (ST_VOID) + { + return (_mms_fin_null_req (MMSOP_IDENTIFY)); + } + +#endif diff --git a/mmslib/mmsl/rq_info.c b/mmslib/mmsl/rq_info.c new file mode 100644 index 0000000..42ebce0 --- /dev/null +++ b/mmslib/mmsl/rq_info.c @@ -0,0 +1,127 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2004, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_info.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of information */ +/* report. It encodes the information report request. There */ +/* is no response (confirm). */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/28/05 JRB 05 Incl suicacse if MMS_LITE not defined. */ +/* 09/17/04 EJV 04 Use new mms_chk_resource. */ +/* 12/12/02 JRB 03 Add ASN1_ENC_CTXT arg to mpl_info */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +#ifndef MMS_LITE +#include "mms_vcon.h" +#include "suicacse.h" /* for SE_QUE_FULL only */ + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/* mp_info */ +/* Create and send an information report request. */ +/************************************************************************/ + +ST_RET mp_info (ST_INT chan, INFO_REQ_INFO *info_ptr) + { +ST_RET rc; +ST_INT avail; + + /* locking here will assure that _mms_chk_resource will work in */ + /* multiple threads when mp_* functions are called to send */ + /* unconfirmed requests */ + S_LOCK_COMMON_RESOURCES (); + + avail = _mms_chk_resource (chan); + if (avail > 0) + rc = _mms_unconf_req_send (MMSOP_INFO_RPT, + M_CAST_MK_FUN (_ms_mk_info_req), + chan,(ST_CHAR *)info_ptr); + else + rc = SE_QUE_FULL; + + S_UNLOCK_COMMON_RESOURCES (); + + return (rc); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_info */ +/* Create an information report request. */ +/************************************************************************/ + +ST_RET mpl_info (ASN1_ENC_CTXT *aCtx, INFO_REQ_INFO *info_ptr) + { + return (_mms_unconf_req_fin (aCtx, MMSOP_INFO_RPT, + M_CAST_MK_FUN (_ms_mk_info_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_info_req */ +/* construct an information report request */ +/************************************************************************/ + +ST_VOID _ms_mk_info_req (ASN1_ENC_CTXT *aCtx, INFO_REQ_INFO *info_ptr) + { +ST_INT i; +ACCESS_RESULT *ar_ptr; + + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + ar_ptr = info_ptr->acc_rslt_list; + ar_ptr += info_ptr->num_of_acc_result - 1; + for (i = 0; i < info_ptr->num_of_acc_result; i++) + { + _ms_wr_va_access_rslt (aCtx, ar_ptr); + ar_ptr--; + } + asn1r_fin_constr (aCtx, 0, CTX, DEF); /* finish context tag 0 cstr */ + + _ms_wr_va_spec (aCtx, &info_ptr->va_spec); + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsl/rq_init.c b/mmslib/mmsl/rq_init.c new file mode 100644 index 0000000..50fe6e3 --- /dev/null +++ b/mmslib/mmsl/rq_init.c @@ -0,0 +1,251 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_init.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the initiate */ +/* operation. It decodes the initiate response (confirm) & */ +/* encodes the initiate request. */ +/* This module makes use of common functions in mmsinit.c */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/28/05 EJV 04 Elim Linux warnings in if (a=b) */ +/* Fixed thisFileName for MMS-EASE */ +/* 03/11/04 GLB 03 Cleaned up "thisFileName" */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 01 Added SD_CONST modifiers */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pcon.h" +#ifndef MMS_LITE +#include "mms_ms.h" +#endif +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) && (defined(S_MT_SUPPORT) || !defined(MMS_LITE)) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/* mms_init_rsp */ +/* Function called to decode an Initiate response PDU after the PDU */ +/* type has been determined. Sets request to false, and calls the */ +/* common initiate decode function. */ +/* */ +/* NOTE : This functionality has been moved to mmsinit.c, because the */ +/* request and response are identical. The call to mms_init_rsp was */ +/* put back to better support MMSEASE-LITE. */ +/************************************************************************/ + +ST_VOID mms_init_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("decode initiate response"); + _mms_init_dec (aCtx, SD_FALSE); + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_init */ +/* create and send an initiate request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_init (ST_INT chan, ST_CHAR *partner, INIT_INFO *info_ptr) + { +ST_UCHAR *msg_ptr; +MMSREQ_PEND *reqptr; +LLP_ADDR_INFO add_llp_info; +ST_INT i; +ST_INT num_ui; +INIT_UI *ui; +INIT_UI *ui_ptr; +ST_UCHAR *buf; +ST_INT16 pend_req_save; +ST_INT num_cs; +ST_INT cs_count; +CS_INIT_INFO *cs_info_ptr; +ST_UCHAR *cs_build_bufs[MAX_INIT_CONTEXTS]; +ST_INT req_count; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + if (info_ptr->num_cs_init > MAX_INIT_CONTEXTS) + { + mms_op_err = ME_TOO_MANY_CONTEXTS; + return ((MMSREQ_PEND *) 0); + } + +/* Make sure this channel is IDLE */ + if (mms_chan_info[chan].ctxt.chan_state != M_IDLE) + { + mms_op_err = ME_CHAN_STATE; + return ((MMSREQ_PEND *) 0); + } + + S_LOCK_COMMON_RESOURCES (); + +/* Flush all pending requests (should be 0 already, check anyway) */ + req_count = ms_count_req_pend (chan); + if (req_count) + { + MLOG_ERR2 ("%d Pending Requests on Idle Channel %d ", + req_count, + (ST_INT) chan); + } + ms_disconn_pend_req (chan); + + +/* Need to save the max pending request count (could be 0) before */ +/* getting the request control pointer. */ + + pend_req_save = mms_chan_info[chan].maxpend_req; + mms_chan_info[chan].maxpend_req = 1; + + reqptr = _ms_get_req_ptr (chan,MMSOP_INITIATE,(ST_CHAR *)info_ptr); + +/* restore max pending request for initiate request */ + mms_chan_info[chan].maxpend_req = pend_req_save; + + if (reqptr) + { + _mms_pend_init[chan].req = reqptr; /* save INITIATE request ctrl */ + + num_ui = num_cs = info_ptr->num_cs_init; + if (info_ptr->mms_p_context_pres) + num_ui++; + + ui = ui_ptr = (INIT_UI *) chk_calloc (num_ui, sizeof (INIT_UI)); + cs_count = 0; + cs_info_ptr = (CS_INIT_INFO *) (info_ptr + 1); + for (i = 0; i < num_ui; ++i, ++ui_ptr) + { +/* build the core initiate, if used and position reached or if no */ +/* companion standard initiates are to be sent */ + + if ((info_ptr->mms_p_context_pres && i == info_ptr->core_position) || + !info_ptr->num_cs_init) + { + msg_ptr = _ms_mk_init (aCtx, m_build_buf,mms_max_msgsize,info_ptr,MMSINITREQ,SD_FALSE); + ui_ptr->context = MMS_PCI; + ui_ptr->ui_len = M_BUILD_BUF_END - msg_ptr; + ui_ptr->ui_ptr = msg_ptr; + } + else /* build a CS Initiate PDU */ + { + buf = cs_build_bufs[cs_count++] = (ST_UCHAR *) + chk_calloc (1,M_INIT_BUILD_LEN); + msg_ptr = _ms_mk_init (aCtx, buf,M_INIT_BUILD_LEN, + (INIT_INFO *) cs_info_ptr,MMSINITREQ,SD_TRUE); + + ui_ptr->context = cs_info_ptr->p_context; + ui_ptr->ui_len = (buf + M_INIT_BUILD_LEN) - msg_ptr; + ui_ptr->ui_ptr = msg_ptr; + ++cs_info_ptr; + } + } + + add_llp_info.i.LLC.use_rem_addr = SD_FALSE; + add_llp_info.i.LLC.req_ptr = (ST_CHAR *)reqptr; + add_llp_info.i.LLC.send_type = INITIATE_REQ_PDU; + + /* If a request logging function is installed, call it */ + if (m_log_req_info_fun && (mms_debug_sel & MMS_LOG_REQ)) + (*m_log_req_info_fun) (reqptr, info_ptr); + + if ((mms_op_err = _mllp_init_req (chan, partner, reqptr->context, + num_ui, ui,&add_llp_info)) != 0) + { + _ms_deact_pend_req (reqptr); + chk_free (ui); + S_UNLOCK_COMMON_RESOURCES (); + return ((MMSREQ_PEND *) 0); + } + + chk_free (ui); + for (i = 0; i < num_cs; ++i) /* free CS build buffers */ + chk_free (cs_build_bufs[i]); + } + S_UNLOCK_COMMON_RESOURCES (); + return (reqptr); /* return request control ptr */ + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_init */ +/* create a core initiate request. */ +/************************************************************************/ + +ST_RET mpl_init (INIT_INFO *info_ptr) + { +ST_RET ret; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + S_LOCK_COMMON_RESOURCES (); + mmsl_msg_start = _ms_mk_init (aCtx, mmsl_enc_buf, mmsl_enc_buf_size, + info_ptr,MMSINITREQ,SD_FALSE); + mmsl_msg_len = (mmsl_enc_buf + mmsl_enc_buf_size) - mmsl_msg_start; + + if (!aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + ret = SD_SUCCESS; + else + ret = ME_ASN1_ENCODE_OVERRUN; + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +#ifdef CS_SUPPORT +/************************************************************************/ +/************************************************************************/ +/* mpl_cs_init */ +/* create a companion standard initiate request. */ +/************************************************************************/ + +ST_INT16 mpl_cs_init (CS_INIT_INFO *info_ptr) + { +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + mmsl_msg_start = _ms_mk_init (aCtx, mmsl_enc_buf, mmsl_enc_buf_size, + (INIT_INFO *) info_ptr,MMSINITREQ,SD_TRUE); + mmsl_msg_len = (mmsl_enc_buf + mmsl_enc_buf_size) - mmsl_msg_start; + + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + return (ME_ASN1_ENCODE_OVERRUN); + return (SD_SUCCESS); + } +#endif + +#endif + +/************************************************************************/ +/* mk_initiate */ +/* Note that there is only one mk_initiate function, and it is listed */ +/* in the mmsinit.c module. */ +/************************************************************************/ + diff --git a/mmslib/mmsl/rq_namel.c b/mmslib/mmsl/rq_namel.c new file mode 100644 index 0000000..0fd3a9b --- /dev/null +++ b/mmslib/mmsl/rq_namel.c @@ -0,0 +1,253 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_namelist.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the GetNameList */ +/* service. It decodes the GetNameList response (indication) and */ +/* encodes the GetNameList request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +static NAMELIST_RESP_INFO *info; + +static ST_CHAR **nptr; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID namelist_get_list_of_ident (ASN1_DEC_CTXT *aCtx); +static ST_VOID namelist_get_identifier (ASN1_DEC_CTXT *aCtx); +static ST_VOID namelist_list_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID namelist_more_follows (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_namelist_rsp */ +/* Function called to decode a GetNameList response PDU after the PDU */ +/* type has been determined. Sets up state machine function pointers */ +/* and returns, letting the ASN1DE tools take over. */ +/************************************************************************/ + +ST_VOID mms_namelist_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; +ST_INT max_vstr; + + MLOG_CDEC0 ("Get Named List"); + +#if defined(FIXED_DECBUF) + max_vstr = m_cl_max_namel_names; + rsp_size = mmsl_dec_info_size; +#else + +/* Allocate enough memory to hold the namelist_resp_info structure and */ +/* a list of pointers to the names returned in the GetNameList response.*/ + + max_vstr = _mmsdec_msglen/2; + if (m_cl_max_namel_names && (max_vstr > m_cl_max_namel_names)) + max_vstr = m_cl_max_namel_names; + rsp_size = sizeof(NAMELIST_RESP_INFO) + (sizeof(ST_CHAR *) * max_vstr); +#endif + +/* get storage for request information */ + info = (NAMELIST_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,namelist_get_list_of_ident); /* declare next elmnt expected */ + } + +/************************************************************************/ +/* namelist_get_list_of_ident */ +/* GetNameList response is being decoded: the SEQUENCEOF Identifier has */ +/* been encountered. */ +/************************************************************************/ + +static ST_VOID namelist_get_list_of_ident (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("namelist_get_list_of_ident"); + +/* Initialize nptr to just after the namelist_resp_info structure, and */ +/* initialize the number of names to zero. */ + + nptr = (ST_CHAR **) (info + 1); + info -> num_names = 0; + info -> more_follows = SD_TRUE; /* set the default value */ + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = namelist_list_done; + ASN1R_TAG_ADD (aCtx, UNI,VISTR_CODE,namelist_get_identifier); + } + +/************************************************************************/ +/* namelist_get_identifier */ +/* GetNameList resp. is being decoded: model name has been encountered. */ +/************************************************************************/ + +static ST_VOID namelist_get_identifier (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("namelist_get_identifier"); + +/* Increment the number of names, assign the pointer to the new name, */ +/* and read the name into the space in the existing message. */ + + nptr[info->num_names] = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_identifier (aCtx, nptr[info->num_names])) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + ++info->num_names; + + asn1r_tag_restore (aCtx); + } + +/************************************************************************/ +/* namelist_list_done */ +/* GetNameList response is being decoded: end of name list encountered. */ +/************************************************************************/ + +static ST_VOID namelist_list_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT resp_size; + +/* There are no other data elements in the message, resize the struct. */ + + /* find the exact size of the storage used */ + resp_size = sizeof (NAMELIST_RESP_INFO) + + (info->num_names) * sizeof (ST_CHAR *); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,resp_size); + info = (NAMELIST_RESP_INFO *) _mms_dec_info; + + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + ASN1R_TAG_ADD (aCtx, CTX,1,namelist_more_follows); + } + +/************************************************************************/ +/* namelist_more_follows */ +/* GetNameList response is being decoded: the more follows parameter */ +/* has been encountered. */ +/************************************************************************/ + +static ST_VOID namelist_more_follows (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("namelist_more_follows"); + + if (aCtx->asn1r_elmnt_len != 1) + { /* If not of length 1 (boolean),*/ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); /* stop parse, report error */ + return; /* and return. */ + } + + if (asn1r_get_bool (aCtx, &info -> more_follows)) /* Read more_follows boolean. */ + { /* If error reading integer, */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); /* stop parse, report error */ + return; /* and return. */ + } + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_namelist */ +/* ENCODE and send a GetNameList REQUEST: */ +/************************************************************************/ + +MMSREQ_PEND *mp_namelist (ST_INT chan, NAMELIST_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_GET_NAMLIST, + M_CAST_MK_FUN (_ms_mk_namel_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_namelist */ +/* ENCODE a GetNameList REQUEST: */ +/************************************************************************/ + +ST_RET mpl_namelist (NAMELIST_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_GET_NAMLIST, + M_CAST_MK_FUN (_ms_mk_namel_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_namel_req */ +/* ENCODE a GetNameList REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_namel_req (ASN1_ENC_CTXT *aCtx, NAMELIST_REQ_INFO *info_ptr) + { + + if (info_ptr->cont_after_pres) + { + asn1r_wr_vstr (aCtx, info_ptr->continue_after); /* write continue-after name */ + asn1r_fin_prim (aCtx, 2,CTX); + } + + asn1r_strt_constr (aCtx); /* start the object scope cstr */ + + if (info_ptr->objscope == DOM_SPEC) /* if domain specific */ + asn1r_wr_vstr (aCtx, info_ptr->dname); /* write domain_name identifier */ + asn1r_fin_prim (aCtx, info_ptr->objscope,CTX); /* either NULL or identifier */ + + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish the object scope cstr */ + + asn1r_strt_constr (aCtx); /* start extendedObjectClass */ +#ifdef CS_SUPPORT + if (info_ptr->cs_objclass_pres) /* if companion standard */ + { + asn1r_wr_octstr (aCtx, info_ptr->obj.cs.cs_class,info_ptr->obj.cs.len); + asn1r_fin_constr (aCtx, 1,CTX,DEF); + } + else + { + asn1r_wr_i16 (aCtx, info_ptr->obj.mms_class); /* write the object scope */ + asn1r_fin_prim (aCtx, 0,CTX); + } +#else + asn1r_wr_i16 (aCtx, info_ptr->obj.mms_class); /* write the object scope */ + asn1r_fin_prim (aCtx, 0,CTX); +#endif + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish the extendedObjClass */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_NAMLIST,CTX,DEF); /* complete GetNameList req */ + } + diff --git a/mmslib/mmsl/rq_read.c b/mmslib/mmsl/rq_read.c new file mode 100644 index 0000000..5783b40 --- /dev/null +++ b/mmslib/mmsl/rq_read.c @@ -0,0 +1,276 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_read.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of variable read. */ +/* It decodes the variable read response (confirm) & encodes */ +/* the variable read request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 08 Remove "thisFileName" */ +/* 12/20/01 JRB 07 Converted to use ASN1R (re-entrant ASN1) */ +/* 05/29/01 RKR 06 Corrected max_acc_rslt = _mmsdec_msglen / 2 */ +/* 01/21/00 MDE 05 Corrected buffer size calculations for */ +/* 'm_cl_max_read_acc_rslt' != 0 */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 06/27/97 MDE 01 Fixed max_acc_rslt bug */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static READ_RESP_INFO *rsp_info; +static ACCESS_RESULT *ar_ptr; + +static ST_INT max_vars; +static ST_INT max_acc_rslt; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID read_acc_rslt_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID read_acc_rslt_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID read_acc_rslt_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID read_va_spec_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID read_va_spec_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID read_va_spec_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_read_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_read_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; +ST_INT rsp_size2; + + MLOG_CDEC0 ("Variable Read Response"); + +#if defined(FIXED_DECBUF) + max_acc_rslt = m_cl_max_read_acc_rslt; + max_vars = m_cl_max_read_var_spec; + rsp_size = mmsl_dec_info_size; +#else + max_vars = _mmsdec_msglen / 4; + max_acc_rslt = _mmsdec_msglen / 2; + if (m_cl_max_read_acc_rslt && (max_acc_rslt > m_cl_max_read_acc_rslt)) + max_acc_rslt = m_cl_max_read_acc_rslt; + + if (m_cl_read_spec_in_result) + { + if (m_cl_max_read_var_spec && (max_vars > m_cl_max_read_var_spec)) + max_vars = m_cl_max_read_var_spec; + rsp_size2 = sizeof(READ_RESP_INFO) + (sizeof(VARIABLE_LIST) * max_vars); + } + else + rsp_size2 = 0; + + rsp_size = sizeof(READ_RESP_INFO) + (sizeof(ACCESS_RESULT) * max_acc_rslt); + if (rsp_size < rsp_size2) + rsp_size = rsp_size2; +#endif + +/* get storage for request information */ + rsp_info = (READ_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + rsp_info->va_spec_pres = SD_FALSE; /* set default value */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, read_va_spec_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, read_acc_rslt_cstr); + } + +/************************************************************************/ +/* read_va_spec_cstr */ +/* decoding variable read request: variable access constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID read_va_spec_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("read_va_spec_cstr"); + + rsp_info->va_spec_pres = SD_TRUE; /* set va spec present */ + + _ms_get_va_spec (aCtx, &rsp_info->va_spec, max_vars, read_va_spec_done); + } + +/************************************************************************/ +/* read_va_spec_done */ +/* decoding variable read request: variable access specification */ +/* has been decoded. */ +/************************************************************************/ + +static ST_VOID read_va_spec_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("read_va_spec_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = read_va_spec_cstr_done; + } + +/************************************************************************/ +/* read_va_spec_cstr_done */ +/* decoding variable read request: variable access constructor done */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID read_va_spec_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, read_acc_rslt_cstr); + } + +/************************************************************************/ +/* read_acc_rslt_cstr */ +/* decoding variable read request: access result constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID read_acc_rslt_cstr (ASN1_DEC_CTXT *aCtx) + { +VARIABLE_LIST *temp; + + MLOG_CDEC0 ("read_acc_rslt_cstr"); + + temp = (VARIABLE_LIST *) (rsp_info + 1); + temp += rsp_info->va_spec.num_of_variables; + + rsp_info->num_of_acc_result = 0; + rsp_info->acc_rslt_list = (ACCESS_RESULT *) temp; + ar_ptr = rsp_info->acc_rslt_list; + + _ms_get_va_access_rslt (aCtx, ar_ptr, read_acc_rslt_done); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = read_acc_rslt_cstr_done; + } + +/************************************************************************/ +/* read_acc_rslt_done */ +/* decoding variable read request: access result has been decoded. */ +/************************************************************************/ + +static ST_VOID read_acc_rslt_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("read_acc_rslt_done"); + + rsp_info->num_of_acc_result++; + if ((rsp_info->num_of_acc_result + 1) <= max_acc_rslt) + { + ar_ptr++; + _ms_get_va_access_rslt (aCtx, ar_ptr, read_acc_rslt_done); + } + } + +/************************************************************************/ +/* read_acc_rslt_cstr_done */ +/* decoding variable read request: access result constructor done */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID read_acc_rslt_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; +VARIABLE_LIST *temp; + + MLOG_CDEC0 ("read_acc_rslt_cstr_done"); + + /* find actual size for request info */ + rsp_size = sizeof (READ_RESP_INFO) + + (sizeof (VARIABLE_LIST)*rsp_info->va_spec.num_of_variables) + + (sizeof (ACCESS_RESULT)*rsp_info->num_of_acc_result); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,rsp_size); + rsp_info = (READ_RESP_INFO *) _mms_dec_info; + +/* some C run time library mem mgmt. functions will always give back a */ +/* new pointer when reallocating smaller. In the case of read_resp_info*/ +/* we have to update the acc_rslt_list ptr to point to this new mem loc */ + + temp = (VARIABLE_LIST *) (rsp_info + 1); + temp += rsp_info->va_spec.num_of_variables; + rsp_info->acc_rslt_list = (ACCESS_RESULT *) temp; + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_read */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the variable read request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_read (ST_INT chan, READ_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_READ, + M_CAST_MK_FUN (_ms_mk_read_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_read */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the variable read request. */ +/************************************************************************/ + + +ST_RET mpl_read (READ_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_READ, + M_CAST_MK_FUN (_ms_mk_read_req), + (ST_CHAR *) info_ptr)); + } +#endif + + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_read_req */ +/* construct a variable read request. */ +/************************************************************************/ + +ST_VOID _ms_mk_read_req (ASN1_ENC_CTXT *aCtx, READ_REQ_INFO *info) + { + + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + _ms_wr_va_spec (aCtx, &info->va_spec); + asn1r_fin_constr (aCtx, 1, CTX, DEF); /* finish context tag 1 cstr */ + + if (info->spec_in_result) + { /* not the default (false) */ + asn1r_wr_bool (aCtx, info->spec_in_result); /* write specification in rslt */ + asn1r_fin_prim (aCtx, 0, CTX); /* context tag 0 primitive */ + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_READ,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rq_repea.c b/mmslib/mmsl/rq_repea.c new file mode 100644 index 0000000..e1c7ac7 --- /dev/null +++ b/mmslib/mmsl/rq_repea.c @@ -0,0 +1,117 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_repeas.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the report event */ +/* action status. It decodes the report event action status */ +/* response (confirm) & encodes the report event action status */ +/* request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static REPEAS_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_repeas_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_repeas_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Report Event Action Status Response"); + +/* get storage for request information */ + rsp_info = (REPEAS_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (REPEAS_RESP_INFO)); + + if (asn1r_get_u32 (aCtx, &rsp_info->num_of_ev_enroll)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_repeas */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the report event action status request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_repeas (ST_INT chan, REPEAS_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_REP_EA_STAT, + M_CAST_MK_FUN (_ms_mk_repeas_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_repeas */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the report event action status request. */ +/************************************************************************/ + +ST_RET mpl_repeas (REPEAS_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_REP_EA_STAT, + M_CAST_MK_FUN (_ms_mk_repeas_req), + (ST_CHAR *)info_ptr)); + } + +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_repeas_req */ +/* construct a get event action attributes request */ +/************************************************************************/ + +ST_VOID _ms_mk_repeas_req (ASN1_ENC_CTXT *aCtx, REPEAS_REQ_INFO *info) + { + _ms_wr_mms_objname (aCtx, &info->evact_name); /* write event action name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_REP_EA_STAT,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rq_repec.c b/mmslib/mmsl/rq_repec.c new file mode 100644 index 0000000..60e6a44 --- /dev/null +++ b/mmslib/mmsl/rq_repec.c @@ -0,0 +1,249 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_repecs.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of report event */ +/* condition status. It decodes the report event condition */ +/* status response (confirm) and encodes the report event */ +/* condition status request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static REPECS_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID repecs_tta_time_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID repecs_tti_time_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID repecs_tta_time_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID repecs_tta_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID repecs_get_enabled (ASN1_DEC_CTXT *aCtx); +static ST_VOID repecs_get_enrolls (ASN1_DEC_CTXT *aCtx); +static ST_VOID repecs_get_cur_state (ASN1_DEC_CTXT *aCtx); +static ST_VOID repecs_tti_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_repecs_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_repecs_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Report Event Condition Status Response"); + + + +/* get storage for request information */ + rsp_info = (REPECS_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (REPECS_RESP_INFO)); + rsp_info->enabled_pres = SD_FALSE; /* set default value */ + rsp_info->tta_time_pres = SD_FALSE; + rsp_info->tti_time_pres = SD_FALSE; + + ASN1R_TAG_ADD (aCtx, CTX, 0, repecs_get_cur_state); + } + +/************************************************************************/ +/* repecs_get_cur_state */ +/* Decoding report event condition status response: current state was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID repecs_get_cur_state (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("repecs_get_cur_state"); + /* read current state */ + if (asn1r_get_i16 (aCtx, &(rsp_info->cur_state))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 1, repecs_get_enrolls); + } + +/************************************************************************/ +/* repecs_get_enrolls */ +/* Decoding report event condition status response: number of event */ +/* enrollments was encountered. */ +/************************************************************************/ + +static ST_VOID repecs_get_enrolls (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("repecs_get_enrolls"); + /* read number of event enrollments */ + if (asn1r_get_u32 (aCtx, &(rsp_info->num_of_ev_enroll))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 2, repecs_get_enabled); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, repecs_tta_time_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, repecs_tti_time_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* repecs_get_enabled */ +/* Decoding report event condition status response: enabled indicator */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID repecs_get_enabled (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("repecs_get_enabled"); + + rsp_info->enabled_pres = SD_TRUE; /* set enabled present */ + /* read enabled indicator */ + if (asn1r_get_bool (aCtx, &(rsp_info->enabled))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, repecs_tta_time_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, repecs_tti_time_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* repecs_tta_time_cstr */ +/* Decoding report event condition status response: transition to */ +/* active time cstr was encountered. */ +/************************************************************************/ + +static ST_VOID repecs_tta_time_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("repecs_tta_time_cstr"); + + rsp_info->tta_time_pres = SD_TRUE; /* set tran to active present */ + + _ms_get_mms_evtime (aCtx, &rsp_info->tta_time, repecs_tta_done); + } + +/************************************************************************/ +/* repecs_tta_done */ +/* Decoding report event condition status response: transition to */ +/* active time has been obtained. */ +/************************************************************************/ + +static ST_VOID repecs_tta_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("repecs_tta_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = repecs_tta_time_cstr_done; + } + +/************************************************************************/ +/* repecs_tta_time_cstr_done */ +/* Decoding report event condition status response: transition to */ +/* active time cstr done has been encountered. */ +/************************************************************************/ + +static ST_VOID repecs_tta_time_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, repecs_tti_time_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* repecs_tti_time_cstr */ +/* Decoding report event condition status response: transition to */ +/* idle time cstr has been encountered. */ +/************************************************************************/ + +static ST_VOID repecs_tti_time_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("repecs_tti_time_cstr"); + + rsp_info->tti_time_pres = SD_TRUE; /* set tran to active present */ + + _ms_get_mms_evtime (aCtx, &rsp_info->tti_time, repecs_tti_done); + } + +/************************************************************************/ +/* repecs_tti_done */ +/* Decoding report event condition status response: transition to */ +/* idle time has been obtained. */ +/************************************************************************/ + +static ST_VOID repecs_tti_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("repecs_tti_done"); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_repecs */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the report event condition status */ +/* request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_repecs (ST_INT chan, REPECS_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_REP_EC_STAT, + M_CAST_MK_FUN (_ms_mk_repecs_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_repecs */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the report event condition status request. */ +/************************************************************************/ + +ST_RET mpl_repecs (REPECS_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_REP_EC_STAT, + M_CAST_MK_FUN (_ms_mk_repecs_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_repecs_req */ +/* construct a report event condition status request */ +/************************************************************************/ + +ST_VOID _ms_mk_repecs_req (ASN1_ENC_CTXT *aCtx, REPECS_REQ_INFO *info) + { + _ms_wr_mms_objname (aCtx, &info->evcon_name); /* write the object name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_REP_EC_STAT,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsl/rq_repee.c b/mmslib/mmsl/rq_repee.c new file mode 100644 index 0000000..00d0e0a --- /dev/null +++ b/mmslib/mmsl/rq_repee.c @@ -0,0 +1,262 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_repees.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the report event */ +/* enrollment status. It decodes the report event enrollment */ +/* status response (confirm) & encodes the report event enrollment */ +/* status request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 03/31/03 JRB 06 asn1r_get_bitstr: add max_bits arg. */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static REPEES_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID repees_get_ect_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID repees_get_ect_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID repees_get_ect_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID repees_get_not_lost (ASN1_DEC_CTXT *aCtx); +static ST_VOID repees_get_duration (ASN1_DEC_CTXT *aCtx); +static ST_VOID repees_get_alarm_ack_rule (ASN1_DEC_CTXT *aCtx); +static ST_VOID repees_get_cur_state (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_repees_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_repees_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Report Event Enrollment Status Response"); + +/* get storage for request information */ + rsp_info = (REPEES_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (REPEES_RESP_INFO)); + ASN1R_TAG_ADD (aCtx, CTX, 0, repees_get_ect_prim); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, repees_get_ect_cstr); + } + +/************************************************************************/ +/* repees_get_ect_prim */ +/* report event enrollment status response is being decoded: event */ +/* condition transitions primitive was encountered. */ +/************************************************************************/ + +static ST_VOID repees_get_ect_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("repees_get_ect_prim"); + if (!asn1r_get_bitstr (aCtx, &rsp_info->ec_transitions, 7)) + repees_get_ect_done (aCtx); /* set up for the next data element */ + else + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + } + +/************************************************************************/ +/* repees_get_ect_cstr */ +/* report event enrollment status response is being decoded: event */ +/* condition transitions constructor was encountered. */ +/************************************************************************/ + +static ST_VOID repees_get_ect_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("repees_get_ect_cstr"); + /* set up bitstring cstr done function */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = repees_get_ect_done; + + asn1r_get_bitstr_cstr (aCtx, 7,&rsp_info->ec_transitions); + } + +/************************************************************************/ +/* repees_get_ect_done */ +/* report event enrollment status response is being decoded: event */ +/* condition transitions constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID repees_get_ect_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("repees_get_ect_done"); + /* Check aCtx->asn1r_bitcount for correct # of bits */ + if (aCtx->asn1r_bitcount != 7) /* should be 7 bits */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else /* now get alarm ack rule */ + { + ASN1R_TAG_ADD (aCtx, CTX, 1, repees_get_not_lost); + ASN1R_TAG_ADD (aCtx, CTX, 2, repees_get_duration); + } + } + +/************************************************************************/ +/* repees_get_not_lost */ +/* report event enrollment status response is being decoded: */ +/* notification lost has been encountered. */ +/************************************************************************/ + +static ST_VOID repees_get_not_lost (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("repees_get_not_lost"); + + if (asn1r_get_bool (aCtx, &(rsp_info->not_lost))) /* get notification lost*/ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 2, repees_get_duration); + } + +/************************************************************************/ +/* repees_get_duration */ +/* Decoding report event enrollment status response: duration was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID repees_get_duration (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("repees_get_duration"); + /* read duration */ + if (asn1r_get_i16 (aCtx, &(rsp_info->duration))) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + else if ((rsp_info->duration < 0) || (rsp_info->duration > 1)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 3, repees_get_alarm_ack_rule); + ASN1R_TAG_ADD (aCtx, CTX, 4, repees_get_cur_state); + } + +/************************************************************************/ +/* repees_get_alarm_ack_rule */ +/* Decoding report event enrollment status response: alarm ack rule */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID repees_get_alarm_ack_rule (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("repees_get_alarm_ack_rule"); + + rsp_info->alarm_ack_rule_pres = SD_TRUE; + /* read alarm ack rule */ + if (asn1r_get_i16 (aCtx, &(rsp_info->alarm_ack_rule))) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + else if ((rsp_info->alarm_ack_rule < 0) || (rsp_info->alarm_ack_rule > 3)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 4, repees_get_cur_state); + } + +/************************************************************************/ +/* repees_get_cur_state */ +/* Decoding report event enrollment status response: current state was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID repees_get_cur_state (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("repees_get_cur_state"); + /* read current state */ + if (asn1r_get_i16 (aCtx, &(rsp_info->cur_state))) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + else if ((rsp_info->cur_state < 0) || (rsp_info->cur_state > 7)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_repees */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the report event enrollment status request */ +/************************************************************************/ + +MMSREQ_PEND *mp_repees (ST_INT chan, REPEES_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_REP_EE_STAT, + M_CAST_MK_FUN (_ms_mk_repees_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_repees */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the report event enrollment status request. */ +/************************************************************************/ + +ST_RET mpl_repees (REPEES_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_REP_EE_STAT, + M_CAST_MK_FUN (_ms_mk_repees_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_repees_req */ +/* construct a report event enrollment status response */ +/************************************************************************/ + +ST_VOID _ms_mk_repees_req (ASN1_ENC_CTXT *aCtx, REPEES_REQ_INFO *info) + { + _ms_wr_mms_objname (aCtx, &info->evenroll_name);/* write event enrollment name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_REP_EE_STAT,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rq_stat.c b/mmslib/mmsl/rq_stat.c new file mode 100644 index 0000000..dfbb6b7 --- /dev/null +++ b/mmslib/mmsl/rq_stat.c @@ -0,0 +1,107 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_stat.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the functions to decode a status response */ +/* and encode a status request message. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 04 Remove "thisFileName" */ +/* 12/20/01 JRB 03 Converted to use ASN1R (re-entrant ASN1) */ +/* Deleted mms_status proto (see mms_dfun.h) */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "asn1defs.h" + +/************************************************************************/ +/************************************************************************/ +/* mms_status_rsp */ +/* This function is called from mmsdec to decode a Status response PDU */ +/* after the PDU type has been determined. It simply calls mms_status */ +/* in the module mmsstat.c. */ +/************************************************************************/ + +ST_VOID mms_status_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("decode status response"); + + mms_status (aCtx); + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_status */ +/* This function is called from the user to ENCODE and send the */ +/* Status request PDU. */ +/************************************************************************/ + +MMSREQ_PEND *mp_status (ST_INT chan, STATUS_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_STATUS, + M_CAST_MK_FUN (_ms_mk_stat_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_status */ +/* This function is called by the user to ENCODE the Status request */ +/* PDU. */ +/************************************************************************/ + +ST_RET mpl_status (STATUS_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_STATUS, + M_CAST_MK_FUN (_ms_mk_stat_req), + (ST_CHAR *)info_ptr)); + } +#endif + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_stat_req */ +/* ENCODE an Status REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_stat_req (ASN1_ENC_CTXT *aCtx, STATUS_REQ_INFO *info_ptr) + { + +/* Write the ST_BOOLEAN value represented by the "extended" component of */ +/* the status_req_info structure (0 means false, nonzero means true). */ + + if (info_ptr -> extended) + asn1r_wr_bool (aCtx, 0x7F); + else + asn1r_wr_bool (aCtx, 0x00); + +/* Write the context specific explicit tag for this opcode on the */ +/* ST_BOOLEAN data element just written. */ + + asn1r_fin_prim (aCtx, MMSOP_STATUS,CTX); /* tag = opcode, context */ + } + + diff --git a/mmslib/mmsl/rq_trige.c b/mmslib/mmsl/rq_trige.c new file mode 100644 index 0000000..8db0111 --- /dev/null +++ b/mmslib/mmsl/rq_trige.c @@ -0,0 +1,104 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_trige.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of trigger event. */ +/* It decodes the trigger event response (confirm) & encodes the */ +/* trigger event request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_trige_rsp */ +/* NOTE : Since the mms_trige_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_trige */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the trigger event request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_trige (ST_INT chan, TRIGE_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_TRIGGER_EV, + M_CAST_MK_FUN (_ms_mk_trige_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_trige */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the trigger event request. */ +/************************************************************************/ + +ST_RET mpl_trige (TRIGE_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_TRIGGER_EV, + M_CAST_MK_FUN (_ms_mk_trige_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_trige_req */ +/* ENCODE a trigger event REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_trige_req (ASN1_ENC_CTXT *aCtx, TRIGE_REQ_INFO *info) + { + if (info->priority_pres) + { + asn1r_wr_u8 (aCtx, info->priority); /* write the priority */ + asn1r_fin_prim (aCtx, 1, CTX); /* ctx tag 1 */ + } + + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &info->evcon_name); /* write event cond mon name */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context specific tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_TRIGGER_EV,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsl/rq_ustat.c b/mmslib/mmsl/rq_ustat.c new file mode 100644 index 0000000..618e128 --- /dev/null +++ b/mmslib/mmsl/rq_ustat.c @@ -0,0 +1,118 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_ustat.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the functions to encode an unsolicited */ +/* status request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/28/05 JRB 05 Incl suicacse if MMS_LITE not defined. */ +/* 09/17/04 EJV 04 Use new mms_chk_resource. */ +/* 12/12/02 JRB 03 Add ASN1_ENC_CTXT arg to mpl_ustatus. */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "asn1defs.h" + +#ifndef MMS_LITE +#include "mms_pvmd.h" +#include "suicacse.h" /* for SE_QUE_FULL only */ + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/* mp_ustatus */ +/* This function is called from the user to ENCODE and send the */ +/* Unsolicited Status request PDU. */ +/************************************************************************/ + +ST_RET mp_ustatus (ST_INT chan, USTATUS_REQ_INFO *info_ptr) + { +ST_RET rc; +ST_INT avail; + + /* locking here will assure that _mms_chk_resource will work in */ + /* multiple threads when mp_* functions are called to send */ + /* unconfirmed requests */ + S_LOCK_COMMON_RESOURCES (); + + avail = _mms_chk_resource (chan); + if (avail > 0) + rc = _mms_unconf_req_send (MMSOP_USTATUS, + M_CAST_MK_FUN (_ms_mk_ustat_req), + chan,(ST_CHAR *)info_ptr); + else + rc = SE_QUE_FULL; + + S_UNLOCK_COMMON_RESOURCES (); + + return (rc); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_ustatus */ +/* This function is called by the user to ENCODE an Unsolicited Status */ +/* request PDU. */ +/************************************************************************/ + +ST_RET mpl_ustatus (ASN1_ENC_CTXT *aCtx, USTATUS_REQ_INFO *info_ptr) + { + return (_mms_unconf_req_fin (aCtx, MMSOP_USTATUS, + M_CAST_MK_FUN (_ms_mk_ustat_req), + (ST_CHAR *)info_ptr)); + } +#endif + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_ustat_req */ +/* ENCODE an Status RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_ustat_req (ASN1_ENC_CTXT *aCtx, USTATUS_REQ_INFO *info) + { + + if (info->local_detail_pres) /* if present, write the local */ + { /* detail parameter */ + asn1r_wr_bitstr (aCtx, info->local_detail,info->local_detail_len); + asn1r_fin_prim (aCtx, 2,CTX); + } + + asn1r_wr_i16 (aCtx, info->physical_stat); /* write the physical status */ + asn1r_fin_prim (aCtx, 1,CTX); + + asn1r_wr_i16 (aCtx, info->logical_stat); /* write the logical status */ + asn1r_fin_prim (aCtx, 0,CTX); + +/* Write the context-specific tag for this unconfirmed request service. */ + asn1r_fin_constr (aCtx, 1,CTX,DEF); + } + diff --git a/mmslib/mmsl/rq_write.c b/mmslib/mmsl/rq_write.c new file mode 100644 index 0000000..1a1c10b --- /dev/null +++ b/mmslib/mmsl/rq_write.c @@ -0,0 +1,212 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_write.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of variable write. */ +/* It decodes the variable write response (confirm) & encodes */ +/* the variable write request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static WRITE_RESP_INFO *rsp_info; + +static WRITE_RESULT *rslt_ptr; +static ST_INT max_rslts; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID write_get_failure (ASN1_DEC_CTXT *aCtx); +static ST_VOID write_get_success (ASN1_DEC_CTXT *aCtx); +static ST_VOID write_all_done (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/************************************************************************/ +/* mms_write_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_write_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("Variable Write Response"); + +#if defined(FIXED_DECBUF) + max_rslts = m_cl_max_write_rslts; + rsp_size = mmsl_dec_info_size; +#else + max_rslts = _mmsdec_msglen / 2; /* find maximum storage required */ + if (m_cl_max_write_rslts && (max_rslts > m_cl_max_write_rslts)) + max_rslts = m_cl_max_write_rslts; + + rsp_size = sizeof (WRITE_RESP_INFO) + (sizeof (WRITE_RESULT) * max_rslts); +#endif + +/* get storage for request information */ + rsp_info = (WRITE_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + + rsp_info->num_of_result = 0; + rslt_ptr = (WRITE_RESULT *) (rsp_info + 1); + + ASN1R_TAG_ADD (aCtx, CTX, 0, write_get_failure); + ASN1R_TAG_ADD (aCtx, CTX, 1, write_get_success); + aCtx->asn1r_decode_done_fun = write_all_done; + } + +/************************************************************************/ +/* write_get_failure */ +/* Decoding variable write response: failure was encountered. */ +/************************************************************************/ + +static ST_VOID write_get_failure (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("write_get_failure"); + + if (++rsp_info->num_of_result > max_rslts) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + rslt_ptr->resp_tag = SD_FALSE; /* set tag to failure */ + + if (asn1r_get_i16 (aCtx, &(rslt_ptr->failure))) /* read the failure code */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + rslt_ptr++; /* point at the next element */ + ASN1R_TAG_ADD (aCtx, CTX, 0, write_get_failure); + ASN1R_TAG_ADD (aCtx, CTX, 1, write_get_success); + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* write_get_success */ +/* Decoding variable write response: success was encountered. */ +/************************************************************************/ + +static ST_VOID write_get_success (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("write_get_success"); + + if (++rsp_info->num_of_result > max_rslts) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + rslt_ptr->resp_tag = SD_TRUE; /* set tag to success */ + + if (aCtx->asn1r_elmnt_len != SD_FALSE) /* verify the null */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + rslt_ptr++; /* point at the next element */ + ASN1R_TAG_ADD (aCtx, CTX, 0, write_get_failure); + ASN1R_TAG_ADD (aCtx, CTX, 1, write_get_success); + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* write_all_done */ +/* All of the write response has been obtained, give back unused */ +/* storage. */ +/************************************************************************/ + +static ST_VOID write_all_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + /* find actual size for request info */ + rsp_size = sizeof (WRITE_RESP_INFO) + + (sizeof (WRITE_RESULT) * rsp_info->num_of_result); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info, rsp_size); + rsp_info = (WRITE_RESP_INFO *) _mms_dec_info; + + _mms_dec_done_ok (aCtx); + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_write */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the variable write request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_write (ST_INT chan, WRITE_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_WRITE, + M_CAST_MK_FUN (_ms_mk_write_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_write */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the variable write request. */ +/************************************************************************/ + +ST_RET mpl_write (WRITE_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_WRITE, + M_CAST_MK_FUN (_ms_mk_write_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_write_req */ +/* construct a variable write request. */ +/************************************************************************/ + +ST_VOID _ms_mk_write_req (ASN1_ENC_CTXT *aCtx, WRITE_REQ_INFO *info) + { +ST_INT i; +VAR_ACC_DATA *data_ptr; + + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + data_ptr = info->va_data; + data_ptr += (info->num_of_data - 1); + for (i = 0; i < info->num_of_data; i++) + { + _ms_wr_va_data (aCtx, data_ptr); + data_ptr--; + } + asn1r_fin_constr (aCtx, 0, CTX, DEF); /* finish context tag 0 cstr */ + + _ms_wr_va_spec (aCtx, &info->va_spec); + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_WRITE,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rs_ackev.c b/mmslib/mmsl/rs_ackev.c new file mode 100644 index 0000000..245702d --- /dev/null +++ b/mmslib/mmsl/rs_ackev.c @@ -0,0 +1,231 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_ackevnot.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the acknowledge */ +/* event notification operation. It decodes the acknowledge event */ +/* notification request (indication) and encodes the acknowledge */ +/* event notification response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static ACKEVNOT_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID ackevnot_enroll_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID ackevnot_enroll_name_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID ackevnot_enroll_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID ackevnot_get_state (ASN1_DEC_CTXT *aCtx); +static ST_VOID ackevnot_evtime_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID ackevnot_evtime_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID ackevnot_evtime_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID ackevnot_ack_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID ackevnot_ack_name_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_ackevnot_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_ackevnot_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Acknowledge Event Notification Request"); + + +/* get storage for request information */ + req_info = (ACKEVNOT_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (ACKEVNOT_REQ_INFO)); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, ackevnot_enroll_name_cstr); + } + +/************************************************************************/ +/* ackevnot_enroll_name_cstr */ +/* decoding acknowledge event notification request: event enrollment */ +/* name constructor was encountered. */ +/************************************************************************/ + +static ST_VOID ackevnot_enroll_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("ackevnot_enroll_name_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->evenroll_name, ackevnot_enroll_name_done); + } + +/************************************************************************/ +/* ackevnot_enroll_name_done */ +/* decoding acknowledge event notification request: event enrollment */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID ackevnot_enroll_name_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("ackevnot_enroll_name_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = ackevnot_enroll_name_cstr_done; + } + +/************************************************************************/ +/* ackevnot_enroll_name_cstr_done */ +/* decoding acknowledge event notification request: event enrollment */ +/* name constructor done has been encountered. */ +/************************************************************************/ + +static ST_VOID ackevnot_enroll_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX,2, ackevnot_get_state); + } + +/************************************************************************/ +/* ackevnot_get_state */ +/* acknowledge event notification REQUEST is being decoded: acknowledge */ +/* state was encountered. */ +/************************************************************************/ + +static ST_VOID ackevnot_get_state (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("ackevnot_get_state"); + + if (asn1r_get_i16 (aCtx, &(req_info->ack_state))) /* acknowledge state */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + else if ((req_info->ack_state < 0) || (req_info->ack_state > 2)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, ackevnot_evtime_cstr); + } + +/************************************************************************/ +/* ackevnot_evtime_cstr */ +/* decoding event notification request: event time constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID ackevnot_evtime_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("ackevnot_evtime_cstr"); + + _ms_get_mms_evtime (aCtx, &req_info->evtime, ackevnot_evtime_done); + } + +/************************************************************************/ +/* ackevnot_evtime_done */ +/* decoding acknowledge event notification request: event time has been */ +/* obtained. */ +/************************************************************************/ + +static ST_VOID ackevnot_evtime_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("ackevnot_evtime_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = ackevnot_evtime_cstr_done; + } + +/************************************************************************/ +/* ackevnot_evtime_cstr_done */ +/* decoding acknowledge event notification request: event time */ +/* constructor done has been encountered. */ +/************************************************************************/ + +static ST_VOID ackevnot_evtime_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 4, ackevnot_ack_name_cstr); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* ackevnot_ack_name_cstr */ +/* acknowledge event notification REQUEST is being decoded: */ +/* acknowledgment event condition constructor was encountered. */ +/************************************************************************/ + +static ST_VOID ackevnot_ack_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("ackevnot_ack_name_cstr"); + + req_info->ackec_name_pres = SD_TRUE; /* ack event cond name present */ + + _ms_get_mms_objname (aCtx, &req_info->ackec_name, ackevnot_ack_name_done); + } + +/************************************************************************/ +/* ackevnot_ack_name_done */ +/* decoding acknowledge event notification request: acknowledgement */ +/* event condition name has been obtained. */ +/************************************************************************/ + +static ST_VOID ackevnot_ack_name_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("ackevnot_ack_name_done"); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_ackevnot_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the acknowledge event notification response.*/ +/************************************************************************/ + +ST_RET mp_ackevnot_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_ACK_EVENT_NOT)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_ackevnot_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the acknowledge event notification response. */ +/************************************************************************/ + +ST_RET mpl_ackevnot_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_ACK_EVENT_NOT)); + } +#endif diff --git a/mmslib/mmsl/rs_cancl.c b/mmslib/mmsl/rs_cancl.c new file mode 100644 index 0000000..856d5ce --- /dev/null +++ b/mmslib/mmsl/rs_cancl.c @@ -0,0 +1,147 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2007, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_cancl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the cancel */ +/* operation. It decodes the cancel request (indication) and */ +/* encodes the cancel response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/01/07 EJV 06 Rem obsolete LLC30... code. */ +/* 03/09/05 EJV 05 Fixed thisFileName for MMS-EASE */ +/* 03/11/04 GLB 04 Cleaned up "thisFileName" */ +/* 12/20/01 JRB 03 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 05/07/98 MDE 01 Fixed logging */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pcon.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) && (defined(S_MT_SUPPORT) || !defined(MMS_LITE)) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ + + +/* variables global to the DECODE portion : NONE */ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_cancel_req */ +/* This function is called from mmsdec when a request is received and */ +/* the opcode for this operation is decoded. Set up state machine */ +/* function pointers to end the parse, since the parse is complete. */ +/************************************************************************/ + +ST_VOID mms_cancel_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Cancel Request"); + + _mmsdec_rslt->data_pres = SD_FALSE; /* cancel just has invoke id */ + aCtx->asn1r_decode_done = SD_TRUE; + asn1r_set_all_cstr_done (aCtx); + aCtx->asn1r_decode_done_fun = NULL; + } + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_cancel_resp */ +/* Format a Cancel response PDU. */ +/************************************************************************/ + +ST_RET mp_cancel_resp (MMSREQ_IND *indptr) + { +ST_UCHAR *msg_ptr; +ST_INT msg_len; +ST_RET ret; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + S_LOCK_COMMON_RESOURCES (); + if (!(ret = _ms_check_ind_actv (indptr))) + { + if (indptr -> cancl_state != CANCEL_REQUESTED) + { + S_UNLOCK_COMMON_RESOURCES (); + return (MVE_CANCEL_STATE); + } + msg_ptr = _ms_mk_cancel (aCtx, SD_FALSE,m_build_buf,mms_max_msgsize,indptr->id); + msg_len = M_BUILD_BUF_END - msg_ptr; + + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + ret = ME_ASN1_ENCODE_OVERRUN; + else + ret = _mms_send_data (indptr->chan, msg_len, msg_ptr, + indptr->context, indptr->add_addr_info); + + + MLOG_ALWAYS0 ("ISSUING MMS CANCEL RESPONSE"); + MLOG_CALWAYS1 ("Channel = %d",indptr->chan); + MLOG_CALWAYS1 ("Context = %02x",indptr->context); + MLOG_CALWAYS1 ("Original Invoke ID = %lu",indptr->id); + + } + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_cancel_resp */ +/* Create a Cancel response PDU. */ +/************************************************************************/ +ST_RET mpl_cancel_resp (ST_VOID) + { +ST_RET ret; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + S_LOCK_COMMON_RESOURCES (); + mmsl_msg_start = _ms_mk_cancel (aCtx, SD_FALSE, mmsl_enc_buf, mmsl_enc_buf_size, + mmsl_invoke_id); + mmsl_msg_len = (mmsl_enc_buf + mmsl_enc_buf_size) - mmsl_msg_start; + + if (!aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + ret = SD_SUCCESS; + else + ret = ME_ASN1_ENCODE_OVERRUN; + + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } +#endif + + +/************************************************************************/ +/* _ms_mk_cancel */ +/* Note that there is only one _ms_mk_cancel function, and it is listed in */ +/* the mmscancl.c module. */ +/************************************************************************/ diff --git a/mmslib/mmsl/rs_concl.c b/mmslib/mmsl/rs_concl.c new file mode 100644 index 0000000..1c3ef7f --- /dev/null +++ b/mmslib/mmsl/rs_concl.c @@ -0,0 +1,136 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2007, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_conclude.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the conclude */ +/* operation. It decodes the conclude request (indication) and */ +/* encodes the conclude response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/01/07 EJV 04 Rem obsolete LLC30... code. */ +/* 03/11/04 GLB 03 Cleaned up "thisFileName" */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 01 Added SD_CONST modifiers */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pcon.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) && defined(S_MT_SUPPORT) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/* External conclude functions (see mmsconcl) : */ +/* ST_CHAR *_ms_mk_conclude (buf_ptr,buf_len,pdutype) */ + +/************************************************************************/ +/************************************************************************/ +/* mms_conclude_req */ +/* NOTE : Since a MMSOP_CONCLUDE is a NULL PDU, the decode is continued */ +/* by '_mms_null_pdu_dec', which simply sets decode done = 1 and sets */ +/* the decode done function to point to the general decode done fun */ +/* See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_concl_resp */ +/* create and send a conclude response. */ +/************************************************************************/ + +ST_RET mp_conclude_resp (MMSREQ_IND *indptr) + { +ST_UCHAR *msg_ptr; +ST_INT msg_len; +ST_RET ret; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + S_LOCK_COMMON_RESOURCES (); + if (!(ret = _ms_check_ind_actv (indptr))) + { + msg_ptr = _ms_mk_conclude (aCtx, m_build_buf,mms_max_msgsize,MMSCNCLRESP); + msg_len = M_BUILD_BUF_END - msg_ptr; + + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + { + S_UNLOCK_COMMON_RESOURCES (); + return (ME_ASN1_ENCODE_OVERRUN); + } + else + ret = _mms_send_data (indptr->chan, msg_len, msg_ptr, + indptr->context, indptr->add_addr_info); + + if (!ret) + { + mms_chan_info[indptr->chan].ctxt.chan_state |= M_REL_IND_WAIT; + + /* If a response logging function is installed, call it */ + if (m_log_resp_info_fun && (mms_debug_sel & MMS_LOG_RESP)) + (*m_log_resp_info_fun) (indptr, NULL); + } + + _ms_ind_serve_done (indptr); + } + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_concl_resp */ +/* create a conclude response. */ +/************************************************************************/ + +ST_RET mpl_conclude_resp (ST_VOID) + { +ST_RET ret; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + S_LOCK_COMMON_RESOURCES (); + mmsl_msg_start = _ms_mk_conclude (aCtx, mmsl_enc_buf, mmsl_enc_buf_size, MMSCNCLRESP); + mmsl_msg_len = (mmsl_enc_buf + mmsl_enc_buf_size) - mmsl_msg_start; + + if (!aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + ret = SD_SUCCESS; + else + ret = ME_ASN1_ENCODE_OVERRUN; + + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } +#endif + +/************************************************************************/ +/* _ms_mk_conclude */ +/* Note that there is only one _ms_mk_conclude function, and it is listed */ +/* in the mmsconcl.c module. */ +/************************************************************************/ + diff --git a/mmslib/mmsl/rs_defee.c b/mmslib/mmsl/rs_defee.c new file mode 100644 index 0000000..080dc5d --- /dev/null +++ b/mmslib/mmsl/rs_defee.c @@ -0,0 +1,387 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_defee.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of define event */ +/* enrollment. It decodes the define event enrollment request */ +/* (indication) & encodes the define event enrollment response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 03/31/03 JRB 05 asn1r_get_bitstr: add max_bits arg. */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DEFEE_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID defee_eename_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_eename_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_eename_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_ecname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_ecname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_ecname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_get_ect_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_get_ect_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_get_ect_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_get_alarm_ack_rule (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_eaname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_eaname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_eaname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_client_app_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_app_ref_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_client_app_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_aecname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_aecname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defee_aecname_cstr_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_defee_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_defee_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Define Event Enrollment Request"); + + +/* get storage for request information */ + req_info = (DEFEE_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (DEFEE_REQ_INFO)); + +/* req_info->evact_name_pres = SD_FALSE; */ +/* req_info->client_app_pres = SD_FALSE; */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, defee_eename_cstr); + } + +/************************************************************************/ +/* defee_eename_cstr */ +/* define event enrollment request is being decoded: event enrollment */ +/* name constructor was encountered. */ +/************************************************************************/ + +static ST_VOID defee_eename_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defee_eename_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->evenroll_name, defee_eename_done); + } + +/************************************************************************/ +/* defee_eename_done */ +/* define event enrollment request is being decoded: event enrollment */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID defee_eename_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defee_eename_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defee_eename_cstr_done; + } + +/************************************************************************/ +/* defee_eename_cstr_done */ +/* define event enrollment request is being decoded: event enrollment */ +/* name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID defee_eename_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, defee_ecname_cstr); + } + +/************************************************************************/ +/* defee_ecname_cstr */ +/* define event enrollment request is being decoded: event condition */ +/* name constructor was encountered. */ +/************************************************************************/ + +static ST_VOID defee_ecname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defee_ecname_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->evcon_name, defee_ecname_done); + } + +/************************************************************************/ +/* defee_ecname_done */ +/* define event enrollment request is being decoded: event condition */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID defee_ecname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defee_ecname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defee_ecname_cstr_done; + } + +/************************************************************************/ +/* defee_ecname_cstr_done */ +/* define event enrollment request is being decoded: event condition */ +/* name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID defee_ecname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 2, defee_get_ect_prim); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, defee_get_ect_cstr); + } + +/************************************************************************/ +/* defee_get_ect_prim */ +/* define event enrollment request is being decoded: event condition */ +/* transitions primitive was encountered. */ +/************************************************************************/ + +static ST_VOID defee_get_ect_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defee_get_ect_prim"); + /* check length before moving bitstring */ + if (!asn1r_get_bitstr (aCtx, &req_info->ec_transitions, 7)) + defee_get_ect_done (aCtx); /* set up for the next data element */ + else + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + } + +/************************************************************************/ +/* defee_get_ect_cstr */ +/* define event enrollment request is being decoded: event condition */ +/* transitions constructor was encountered. */ +/************************************************************************/ + +static ST_VOID defee_get_ect_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defee_get_ect_cstr"); + /* set up bitstring cstr done function */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = defee_get_ect_done; + + asn1r_get_bitstr_cstr (aCtx, 7,&req_info->ec_transitions); + } + +/************************************************************************/ +/* defee_get_ect_done */ +/* define event enrollment request is being decoded: event condition */ +/* transitions constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID defee_get_ect_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defee_get_ect_done"); + /* Check aCtx->asn1r_bitcount for correct # of bits */ + if (aCtx->asn1r_bitcount != 7) /* should be 7 bits */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + else /* now get alarm ack rule */ + ASN1R_TAG_ADD (aCtx, CTX,3,defee_get_alarm_ack_rule); + } + +/************************************************************************/ +/* defee_get_alarm_ack_rule */ +/* Decoding define event enrollment request: alarm acknowledgment rule */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID defee_get_alarm_ack_rule (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defee_get_alarm_ack_rule"); + /* read alarm ack rule */ + if (asn1r_get_i16 (aCtx, &(req_info->alarm_ack_rule))) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + else if ((req_info->alarm_ack_rule < 0) || (req_info->alarm_ack_rule > 3)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, defee_eaname_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, defee_client_app_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 6, defee_aecname_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* defee_eaname_cstr */ +/* define event enrollment request is being decoded: event action */ +/* name constructor was encountered. */ +/************************************************************************/ + +static ST_VOID defee_eaname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defee_eaname_cstr"); + + req_info->evact_name_pres = SD_TRUE; + + _ms_get_mms_objname (aCtx, &req_info->evact_name, defee_eaname_done); + } + +/************************************************************************/ +/* defee_eaname_done */ +/* define event enrollment request is being decoded: event action */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID defee_eaname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defee_eaname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defee_eaname_cstr_done; + } + +/************************************************************************/ +/* defee_eaname_cstr_done */ +/* define event enrollment request is being decoded: event action */ +/* name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID defee_eaname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, defee_client_app_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 6, defee_aecname_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* defee_client_app_cstr */ +/* Decoding define event enrollment request: client application cstr */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID defee_client_app_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defee_client_app_cstr"); + + req_info->client_app_pres = SD_TRUE; + + _ms_get_mms_app_ref (aCtx, &req_info->client_app,&req_info->client_app_len, + defee_app_ref_done); + } + +/************************************************************************/ +/* defee_app_ref_done */ +/* Decoding define event enrollment request: client application has */ +/* been obtained. */ +/************************************************************************/ + +static ST_VOID defee_app_ref_done (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defee_client_app_cstr_done; + } + +/************************************************************************/ +/* defee_client_app_cstr_done */ +/* Decoding define event enrollment request: client application cstr */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID defee_client_app_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 6, defee_aecname_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* defee_aecname_cstr */ +/* define event enrollment request is being decoded: acknowledgement */ +/* event condition name constructor was encountered. */ +/************************************************************************/ + +static ST_VOID defee_aecname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defee_aecname_cstr"); + + req_info->ackec_name_pres = SD_TRUE; + + _ms_get_mms_objname (aCtx, &req_info->ackec_name, defee_aecname_done); + } + +/************************************************************************/ +/* defee_aecname_done */ +/* define event enrollment request is being decoded: event action */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID defee_aecname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defee_aecname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defee_aecname_cstr_done; + } + +/************************************************************************/ +/* defee_aecname_cstr_done */ +/* define event enrollment request is being decoded: event action */ +/* name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID defee_aecname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_defee_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the define event enrollment response. */ +/************************************************************************/ + +ST_RET mp_defee_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_DEF_EE)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_defee_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the define event enrollment response. */ +/************************************************************************/ + +ST_RET mpl_defee_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_DEF_EE)); + } +#endif diff --git a/mmslib/mmsl/rs_evnot.c b/mmslib/mmsl/rs_evnot.c new file mode 100644 index 0000000..99db09a --- /dev/null +++ b/mmslib/mmsl/rs_evnot.c @@ -0,0 +1,479 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_evnot.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of event */ +/* notification. It decodes the event notification request */ +/* (indication). There is no response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* ST_VOID mms_evnot_req () */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 08 Remove "thisFileName" */ +/* 12/20/01 JRB 07 Converted to use ASN1R (re-entrant ASN1) */ +/* 04/28/00 JRB 06 More Lint */ +/* 04/27/00 MDE 05 Lint cleanup */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static EVNOT_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID evnot_enrol_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_enrol_name_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_enrol_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_cond_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_cond_name_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_cond_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_get_severity (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_get_state (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_evtime_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_evtime_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_evtime_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_get_not_lost (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_get_alarm_ack_rule (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_action_result_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_ar_ean_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_ar_get_success (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_ars_csr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_ar_get_failure (ASN1_DEC_CTXT *aCtx); +#ifdef MOD_SUPPORT +static ST_VOID evnot_arf_get_mod_pos (ASN1_DEC_CTXT *aCtx); +#endif +static ST_VOID evnot_arf_get_serv_err (ASN1_DEC_CTXT *aCtx); +#ifdef CS_SUPPORT +static ST_VOID evnot_ars_cs_rdet_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_ars_cs_rdet_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_ars_cs_rdet_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID evnot_action_result_cstr_done (ASN1_DEC_CTXT *aCtx); +#endif + +/************************************************************************/ +/************************************************************************/ +/* mms_evnot_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_evnot_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Event Notification Request"); + +/* get storage for request information */ + req_info = (EVNOT_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (EVNOT_REQ_INFO) + sizeof (ERR_INFO)); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, evnot_enrol_name_cstr); + } + +/************************************************************************/ +/* evnot_enrol_name_cstr */ +/* decoding event notification request: event enrollment name cstr */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID evnot_enrol_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_enrol_name_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->evenroll_name, evnot_enrol_name_done); + } + +/************************************************************************/ +/* evnot_enrol_name_done */ +/* decoding event notification request: event enrollment name has been */ +/* obtained. */ +/************************************************************************/ + +static ST_VOID evnot_enrol_name_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_enrol_name_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = evnot_enrol_name_cstr_done; + } + +/************************************************************************/ +/* evnot_enrol_name_cstr_done */ +/* decoding event notification request: event enrollment name cstr */ +/* has been decoded OK. */ +/************************************************************************/ + +static ST_VOID evnot_enrol_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_enrol_name_cstr_done"); + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 1, evnot_cond_name_cstr); + } + +/************************************************************************/ +/* evnot_cond_name_cstr */ +/* decoding event notification request: event condition name cstr */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID evnot_cond_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_cond_name_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->evcon_name, evnot_cond_name_done); + } + +/************************************************************************/ +/* evnot_cond_name_done */ +/* decoding event notification request: event condition name has been */ +/* obtained. */ +/************************************************************************/ + +static ST_VOID evnot_cond_name_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_cond_name_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = evnot_cond_name_cstr_done; + } + +/************************************************************************/ +/* evnot_cond_name_cstr_done */ +/* decoding event notification request: event condition name cstr */ +/* has been encountered. */ +/************************************************************************/ + +static ST_VOID evnot_cond_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_cond_name_cstr_done"); + + ASN1R_TAG_ADD (aCtx, CTX, 2, evnot_get_severity); + } + +/************************************************************************/ +/* evnot_get_severity */ +/* event notification REQUEST is being decoded: severity was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID evnot_get_severity (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_get_severity"); + + if (asn1r_get_u8 (aCtx, &(req_info->severity))) /* get severity */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 3, evnot_get_state); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 4, evnot_evtime_cstr); + } + +/************************************************************************/ +/* evnot_get_state */ +/* event notification REQUEST is being decoded: state was encountered. */ +/************************************************************************/ + +static ST_VOID evnot_get_state (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_get_state"); + + if (asn1r_get_i16 (aCtx, &(req_info->cur_state)) || /* get current state */ + (req_info->cur_state < 0) || + (req_info->cur_state > 2)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + req_info->cur_state_pres = SD_TRUE; /* set present flag */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, evnot_evtime_cstr); + } + +/************************************************************************/ +/* evnot_evtime_cstr */ +/* decoding event notification request: event time constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID evnot_evtime_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_evtime_cstr"); + + _ms_get_mms_evtime (aCtx, &req_info->trans_time, evnot_evtime_done); + } + +/************************************************************************/ +/* evnot_evtime_done */ +/* decoding event notification request: event time has been obtained. */ +/************************************************************************/ + +static ST_VOID evnot_evtime_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_evtime_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = evnot_evtime_cstr_done; + } + +/************************************************************************/ +/* evnot_evtime_cstr_done */ +/* decoding event notification request: event time constructor done */ +/* has been encountered. */ +/************************************************************************/ + +static ST_VOID evnot_evtime_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX, 6, evnot_get_not_lost); + ASN1R_TAG_ADD (aCtx, CTX, 7, evnot_get_alarm_ack_rule); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 8, evnot_action_result_cstr); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* evnot_get_not_lost */ +/* decoding event notification request: notification lost has been */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID evnot_get_not_lost (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_get_not_lost"); + + if (asn1r_get_bool (aCtx, &(req_info->not_lost))) /* notification lost */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 7, evnot_get_alarm_ack_rule); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 8, evnot_action_result_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* evnot_get_alarm_ack_rule */ +/* decoding event notification request: alarm ack rule has been */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID evnot_get_alarm_ack_rule (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_get_alarm_ack_rule"); + + req_info->alarm_ack_rule_pres = SD_TRUE; /* set alarm ack rult present */ + + if (asn1r_get_i16 (aCtx, &(req_info->alarm_ack_rule))) /* get alarm ack rule */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + else if ((req_info->alarm_ack_rule < 0) || (req_info->alarm_ack_rule > 3)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 8, evnot_action_result_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* evnot_action_result_cstr */ +/* decoding event notification request: action result constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID evnot_action_result_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_action_result_cstr"); + + req_info->evact_result_pres = SD_TRUE; /* set action result present */ + + _ms_get_mms_objname (aCtx, &req_info->evact_name, evnot_ar_ean_done); + } + +/************************************************************************/ +/* evnot_ar_ean_done */ +/* decoding event notification request: action result event action name */ +/* has been obtained. */ +/************************************************************************/ + +static ST_VOID evnot_ar_ean_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_ar_ean_done"); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, evnot_ar_get_success); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, evnot_ar_get_failure); + } + +/************************************************************************/ +/* evnot_ar_get_success */ +/* decoding event notification request: action result success has */ +/* been encountered, get the confirmed service response. */ +/************************************************************************/ + +static ST_VOID evnot_ar_get_success (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_ar_get_success"); + + req_info->evact_result_tag = 0; /* set success action result */ + + /* leave confirmed service response in place; just parse it. */ + req_info->conf_serv_resp = aCtx->asn1r_field_ptr; + asn1r_parse_next (aCtx, evnot_ars_csr_done); + } + +/************************************************************************/ +/* evnot_ars_csr_done */ +/* event notification request is being decoded: action result success: */ +/* confirmed service response has been parsed. */ +/************************************************************************/ + +static ST_VOID evnot_ars_csr_done (ASN1_DEC_CTXT *aCtx) + { + req_info->conf_serv_resp_len = aCtx->asn1r_octetcount; /* save length */ +#ifdef CS_SUPPORT /* check for Companion Standard response detail */ + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 79, evnot_ars_cs_rdet_cstr); +#endif + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +#ifdef CS_SUPPORT +/************************************************************************/ +/* evnot_ars_cs_rdet_cstr */ +/* decoding event notification request: action result success: */ +/* companion standard response detail constructor has been encountered. */ +/************************************************************************/ + +static ST_VOID evnot_ars_cs_rdet_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_ars_cs_rdet_cstr"); + + req_info->cs_rdetail_pres = SD_TRUE; /* set the present flag */ + + /* leave CS response detail in place; just parse it. */ + req_info->cs_rdetail = aCtx->asn1r_field_ptr; + asn1r_parse_next (aCtx, evnot_ars_cs_rdet_done); + } + +/************************************************************************/ +/* evnot_ars_cs_rdet_done */ +/* event notification request is being decoded: action result success: */ +/* companion standard response detail has been parsed. */ +/************************************************************************/ + +static ST_VOID evnot_ars_cs_rdet_done (ASN1_DEC_CTXT *aCtx) + { + req_info->cs_rdetail_len = aCtx->asn1r_octetcount; /* save length */ + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = evnot_ars_cs_rdet_cstr_done; + } + +/************************************************************************/ +/* evnot_ars_cs_rdet_cstr_done */ +/* event notification request is being decoded: action result success: */ +/* confirmed service response cstr done has been encountered. */ +/************************************************************************/ + +static ST_VOID evnot_ars_cs_rdet_cstr_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = evnot_action_result_cstr_done; + } +#endif + +/************************************************************************/ +/* evnot_ar_get_failure */ +/* decoding event notification request: action result failure has */ +/* been encountered. */ +/************************************************************************/ + +static ST_VOID evnot_ar_get_failure (ASN1_DEC_CTXT *aCtx) + { + + MLOG_CDEC0 ("evnot_ar_get_failure"); + + req_info->evact_result_tag = 1; /* get failure action result */ + +#ifdef MOD_SUPPORT /* IS, could have modifier position */ + ASN1R_TAG_ADD (aCtx, CTX, 0, evnot_arf_get_mod_pos); +#endif + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 1, evnot_arf_get_serv_err); + } + +#ifdef MOD_SUPPORT +/************************************************************************/ +/* evnot_arf_get_mod_pos */ +/* decoding event notification request: action result failure: modifier */ +/* position has been encountered. */ +/************************************************************************/ + +static ST_VOID evnot_arf_get_mod_pos (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("evnot_arf_get_mod_pos"); + + req_info->mod_pos_pres = SD_TRUE; /* set modifier pos present */ + + if (asn1r_get_u32 (aCtx, &(req_info->mod_pos))) /* get modifier position */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 1, evnot_arf_get_serv_err); + } +#endif + +/************************************************************************/ +/* evnot_arf_get_serv_err */ +/* event notification request is being decoded: action result failure: */ +/* service error constructor has been encountered. */ +/************************************************************************/ + +static ST_VOID evnot_arf_get_serv_err (ASN1_DEC_CTXT *aCtx) + { + + MLOG_CDEC0 ("evnot_arf_get_serv_err"); + + /* set up pointer (already allocated) */ + req_info->serv_err = (ERR_INFO *) (req_info+1); + /* decode service error contents */ + _mms_get_service_err (aCtx, req_info->serv_err); + } + +/************************************************************************/ +/* evnot_action_result_cstr_done */ +/* decoding event notification request: action_result_cstr_done has */ +/* been encountered. */ +/************************************************************************/ + +#ifdef CS_SUPPORT + +static ST_VOID evnot_action_result_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +#endif diff --git a/mmslib/mmsl/rs_getcl.c b/mmslib/mmsl/rs_getcl.c new file mode 100644 index 0000000..4f3a39f --- /dev/null +++ b/mmslib/mmsl/rs_getcl.c @@ -0,0 +1,158 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_getcl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of get capability */ +/* list. It decodes the get capability list request (indication) */ +/* & encodes the get capability list response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETCL_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID getcl_get_cont_after (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_getcl_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_getcl_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Capability List Request"); + + +/* get storage for request information */ + req_info = (GETCL_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (GETCL_REQ_INFO)); + req_info->cont_after_pres = SD_FALSE; + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, getcl_get_cont_after); + asn1r_set_all_cstr_done (aCtx); /* clear cstr done functions */ + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* getcl_get_cont_after */ +/* get capability list REQUEST (indication) is being decoded: */ +/* continue after was encountered. */ +/************************************************************************/ + +static ST_VOID getcl_get_cont_after (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getcl_get_cont_after"); + + req_info->cont_after_pres = SD_TRUE; + +/* copy continue after back onto itself, shifted by one character */ + req_info->continue_after = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_vstr (aCtx, req_info->continue_after)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getcl_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get capability list response. */ +/************************************************************************/ + +ST_RET mp_getcl_resp (MMSREQ_IND *indptr, GETCL_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_GET_CAP_LIST,indptr, + M_CAST_MK_FUN (_ms_mk_getcl_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getcl_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get capability list response. */ +/************************************************************************/ + +ST_RET mpl_getcl_resp (ST_UINT32 invoke_id, GETCL_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_GET_CAP_LIST,invoke_id, + M_CAST_MK_FUN (_ms_mk_getcl_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getcl_resp */ +/* ENCODE a get capability list RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_getcl_resp (ASN1_ENC_CTXT *aCtx, GETCL_RESP_INFO *info) + { +ST_INT i; +ST_CHAR **cap_ptr; + + if (!info->more_follows) /* not the default of SD_TRUE */ + { /* write more follows not pres */ + asn1r_wr_bool (aCtx, info->more_follows); + asn1r_fin_prim (aCtx, 1,CTX); + } + + asn1r_strt_constr (aCtx); /* start ctx tag 1 constructor */ + + cap_ptr = (ST_CHAR **) (info + 1); + cap_ptr += (info->num_of_capab - 1); /* point to last capability */ + for (i = 0; i < info->num_of_capab; i++) + { + asn1r_wr_vstr (aCtx, *cap_ptr); + asn1r_fin_prim (aCtx, VISTR_CODE, UNI); + cap_ptr--; + } + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* ctx tag 1 constructor */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_CAP_LIST,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsl/rs_getdo.c b/mmslib/mmsl/rs_getdo.c new file mode 100644 index 0000000..03cf2ff --- /dev/null +++ b/mmslib/mmsl/rs_getdo.c @@ -0,0 +1,151 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_getdom.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of get domain */ +/* attribute. It decodes the get domain attribute request */ +/* (indication) & encodes the get domain attribute response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETDOM_REQ_INFO *req_info; + + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_get_dom_attr_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_get_dom_attr_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Domain Attribute Request"); + + +/* get storage for request information */ + req_info = (GETDOM_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (GETDOM_REQ_INFO)); + if (asn1r_get_identifier (aCtx, req_info->dname)) /* read the domain name */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getdom_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get domain attribute response. */ +/************************************************************************/ + +ST_RET mp_getdom_resp (MMSREQ_IND *indptr, GETDOM_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_GET_DOM_ATTR,indptr, + M_CAST_MK_FUN (_ms_mk_getdom_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getdom_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get domain attribute response. */ +/************************************************************************/ + +ST_RET mpl_getdom_resp (ST_UINT32 invoke_id, GETDOM_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_GET_DOM_ATTR,invoke_id, + M_CAST_MK_FUN (_ms_mk_getdom_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getdom_resp */ +/* ENCODE a get domain attribute RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_getdom_resp (ASN1_ENC_CTXT *aCtx, GETDOM_RESP_INFO *info) + { +ST_INT i; +ST_CHAR **cap_ptr; +ST_CHAR **pin_ptr; + + asn1r_wr_i8 (aCtx, info->upload_in_progress); /* write upload in progress */ + asn1r_fin_prim (aCtx, 5,CTX); /* ctx tag 5 */ + + asn1r_strt_constr (aCtx); /* start ctx tag 4 constructor */ + cap_ptr = (ST_CHAR **) (info + 1); + cap_ptr += (info->num_of_capab - 1); /* point to last capability */ + pin_ptr = cap_ptr + 1; + pin_ptr += (info->num_of_pinames-1); /* point to last pi name */ + for (i = 0; i < info->num_of_pinames; i++) + { + asn1r_wr_vstr (aCtx, *pin_ptr); + asn1r_fin_prim (aCtx, VISTR_CODE, UNI); + pin_ptr--; + } + asn1r_fin_constr (aCtx, 4,CTX,DEF); /* ctx tag 4 constructor */ + + asn1r_wr_bool (aCtx, info->sharable); /* write sharable */ + asn1r_fin_prim (aCtx, 3,CTX); /* ctx tag 3 */ + + asn1r_wr_bool (aCtx, info->mms_deletable); /* write mms deletable */ + asn1r_fin_prim (aCtx, 2,CTX); /* ctx tag 2 */ + + asn1r_wr_i16 (aCtx, info->state); /* write state */ + asn1r_fin_prim (aCtx, 1,CTX); /* ctx tag 1 */ + + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + for (i = 0; i < info->num_of_capab; i++) + { + asn1r_wr_vstr (aCtx, *cap_ptr); + asn1r_fin_prim (aCtx, VISTR_CODE, UNI); + cap_ptr--; + } + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* ctx tag 0 constructor */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_DOM_ATTR,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsl/rs_getea.c b/mmslib/mmsl/rs_getea.c new file mode 100644 index 0000000..5fcc60a --- /dev/null +++ b/mmslib/mmsl/rs_getea.c @@ -0,0 +1,154 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_geteaa.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the get event */ +/* action attributes. It decodes the get event action attributes */ +/* request (indication) and encodes the get event action */ +/* attributes response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETEAA_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID geteaa_objname_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_geteaa_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_geteaa_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Event Action Attributes Request"); + +/* get storage for request information */ + req_info = (GETEAA_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (GETEAA_REQ_INFO)); + _ms_get_mms_objname (aCtx, &req_info->evact_name, geteaa_objname_done); + } + +/************************************************************************/ +/* geteaa_objname_done */ +/* Decoding get event action attributes request: event action name */ +/* has been obtained. */ +/************************************************************************/ + +static ST_VOID geteaa_objname_done (ASN1_DEC_CTXT *aCtx) + { + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_geteaa_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get event action attributes response */ +/************************************************************************/ + +ST_RET mp_geteaa_resp (MMSREQ_IND *indptr, GETEAA_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_GET_EA_ATTR,indptr, + M_CAST_MK_FUN (_ms_mk_geteaa_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_geteaa_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get event action attributes response. */ +/************************************************************************/ + +ST_RET mpl_geteaa_resp (ST_UINT32 invoke_id, GETEAA_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_GET_EA_ATTR,invoke_id, + M_CAST_MK_FUN (_ms_mk_geteaa_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_geteaa_resp */ +/* Construct a get event action attributes response. */ +/************************************************************************/ + +ST_VOID _ms_mk_geteaa_resp (ASN1_ENC_CTXT *aCtx, GETEAA_RESP_INFO *info) + { +#ifdef MOD_SUPPORT +MODIFIER *mod_ptr; + + mod_ptr = (MODIFIER *) (info + 1); +#endif + +#ifdef CS_SUPPORT /* if companion standards are supported */ + if (info->cs_rdetail_pres) /* check for CS request detail */ + { + asn1r_strt_constr (aCtx); /* start ctx tag 79 constructor */ + asn1r_wr_delmnt (aCtx, info->cs_rdetail, info->cs_rdetail_len); + asn1r_fin_constr (aCtx, 79, CTX, DEF); /* CS is cstr 79 */ + } +#endif + + asn1r_strt_constr (aCtx); /* start ctx tag 2 constructor */ + asn1r_wr_delmnt (aCtx, info->conf_serv_req,info->conf_serv_req_len); + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* finish ctx tag 2 constructor */ + + asn1r_strt_constr (aCtx); /* start ctx tag 1 constructor */ +#ifdef MOD_SUPPORT /* don't write if not supported */ + _ms_wr_mms_modlist (aCtx, mod_ptr, info->num_of_modifiers); +#endif + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish ctx tag 1 constructor */ + + if (info->mms_deletable) + { /* not the default */ + asn1r_wr_u8 (aCtx, info->mms_deletable); /* write mms deletable indicator*/ + asn1r_fin_prim (aCtx, 0, CTX); /* ctx tag 0 */ + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_EA_ATTR,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rs_getec.c b/mmslib/mmsl/rs_getec.c new file mode 100644 index 0000000..f116474 --- /dev/null +++ b/mmslib/mmsl/rs_getec.c @@ -0,0 +1,170 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_geteca.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the get event */ +/* condition attributes. It decodes the get event condition */ +/* attributes request (indication) and encodes the get event */ +/* condition attributes response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETECA_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID geteca_objname_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_geteca_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_geteca_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Event Condition Attributes Request"); +/* get storage for request information */ + req_info = (GETECA_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (GETECA_REQ_INFO)); + _ms_get_mms_objname (aCtx, &req_info->evcon_name, geteca_objname_done); + } + +/************************************************************************/ +/* geteca_objname_done */ +/* Decoding get event condition attributes request: event condition */ +/* name has been obtained */ +/************************************************************************/ + +static ST_VOID geteca_objname_done (ASN1_DEC_CTXT *aCtx) + { + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_geteca_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get event condition attributes */ +/* response. */ +/************************************************************************/ + +ST_RET mp_geteca_resp (MMSREQ_IND *indptr, GETECA_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_GET_EC_ATTR,indptr, + M_CAST_MK_FUN (_ms_mk_geteca_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_geteca_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get event condition attributes response. */ +/************************************************************************/ + +ST_RET mpl_geteca_resp (ST_UINT32 invoke_id, GETECA_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_GET_EC_ATTR,invoke_id, + M_CAST_MK_FUN (_ms_mk_geteca_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_geteca_resp */ +/* Construct a get event condition attributes response. */ +/************************************************************************/ + +ST_VOID _ms_mk_geteca_resp (ASN1_ENC_CTXT *aCtx, GETECA_RESP_INFO *info) +{ + if (info->eval_int_pres) + { + asn1r_wr_u32 (aCtx, info->eval_interval); /* write evaluation interval */ + asn1r_fin_prim (aCtx, 7, CTX); /* ctx tag 7 */ + } + + if (info->mon_var_pres) + { + asn1r_strt_constr (aCtx); /* start ctx tag 6 constructor */ + if (info->mon_var_tag == SD_TRUE) /* write undefined (NULL) */ + asn1r_fin_prim (aCtx, 1, CTX); /* ctx tag 1 */ + else + { /* write variable reference */ + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_va_var_spec (aCtx, &info->var_ref); + asn1r_fin_constr (aCtx, 0, CTX, DEF); /* finish ctx tag 0 */ + } + asn1r_fin_constr (aCtx, 6, CTX, DEF); /* finish ctx tag 6 */ + } + + if (info->as_reports) + { /* not the default */ + asn1r_wr_u8 (aCtx, info->as_reports); /* write alarm summary reports */ + asn1r_fin_prim (aCtx, 4, CTX); /* ctx tag 4 */ + } + + if (info->severity != MMS_NORM_SEVERITY) + { /* not the default */ + asn1r_wr_u8 (aCtx, info->severity); + asn1r_fin_prim (aCtx, 3, CTX); + } + + if (info->priority != MMS_NORM_PRIORITY) + { /* not the default */ + asn1r_wr_u8 (aCtx, info->priority); + asn1r_fin_prim (aCtx, 2, CTX); + } + + asn1r_wr_i16 (aCtx, info->eclass); + asn1r_fin_prim (aCtx, 1, CTX); + + if (info->mms_deletable) + { /* not the default */ + asn1r_wr_u8 (aCtx, info->mms_deletable); /* write mms deletable indicator*/ + asn1r_fin_prim (aCtx, 0, CTX); /* ctx tag 0 */ + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_EC_ATTR,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rs_getee.c b/mmslib/mmsl/rs_getee.c new file mode 100644 index 0000000..89b4196 --- /dev/null +++ b/mmslib/mmsl/rs_getee.c @@ -0,0 +1,527 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_geteea.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the get event */ +/* enrollment attributes. It decodes the get event enrollment */ +/* attributes request (indication) and encodes the get event */ +/* enrollment attributes response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETEEA_REQ_INFO *req_info; + +static OBJECT_NAME *obj_ptr; +static ST_INT max_obj_name; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID geteea_get_scope (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_eelist_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_eelist_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_client_app_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_client_app_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_client_app_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_ecname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_ecname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_ecname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_eaname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_eaname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_eaname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_caname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_caname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_caname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID geteea_dec_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_geteea_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_geteea_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Get Event Enrollment Attributes Request"); + +#if defined(FIXED_DECBUF) + max_obj_name = m_sv_max_obj_name; + req_size = mmsl_dec_info_size; +#else + max_obj_name = _mmsdec_msglen / 2; /* find maximum size */ + if (m_sv_max_obj_name && (max_obj_name > m_sv_max_obj_name)) + max_obj_name = m_sv_max_obj_name; + req_size = sizeof (GETEEA_REQ_INFO) + (sizeof (OBJECT_NAME) * max_obj_name); +#endif + +/* get storage for request information */ + req_info = (GETEEA_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + + req_info->scope_of_req = 1; /* default is client */ +/* req_info->eenames_pres = SD_FALSE; default not present */ +/* req_info->client_app_pres = SD_FALSE; default not present */ +/* req_info->evcon_pres = SD_FALSE; default not present */ +/* req_info->evact_pres = SD_FALSE; default not present */ +/* req_info->ca_name_pres = SD_FALSE; default not present */ + + ASN1R_TAG_ADD (aCtx, CTX, 0, geteea_get_scope); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, geteea_eelist_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, geteea_client_app_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, geteea_ecname_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, geteea_eaname_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, geteea_caname_cstr); + + aCtx->asn1r_decode_done_fun = geteea_dec_done; /* ok to be done */ + _ms_set_cs_check2 (aCtx); /* check for CS info */ + } + +/************************************************************************/ +/* geteea_get_scope */ +/* Decoding get event enrollment attributes request: scope was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID geteea_get_scope (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteea_get_scope"); + /* read the scope */ + if (asn1r_get_i16 (aCtx, &(req_info->scope_of_req))) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + else if ((req_info->scope_of_req < 0) || (req_info->scope_of_req > 3)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, geteea_eelist_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, geteea_client_app_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, geteea_ecname_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, geteea_eaname_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, geteea_caname_cstr); + _ms_set_cs_check2 (aCtx); /* check for CS info */ + } + +/************************************************************************/ +/* geteea_eelist_cstr */ +/* decoding get event enrollment attributes request: event enrollment */ +/* name list constructor was encountered. */ +/************************************************************************/ + +static ST_VOID geteea_eelist_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteea_eelist_cstr"); + + req_info->eenames_pres = SD_TRUE; /* set list of names present */ + obj_ptr = (OBJECT_NAME *) (req_info + 1); + + _ms_get_mms_objname (aCtx, obj_ptr, geteea_objname_done); + + /* set the cstr done function */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = geteea_eelist_cstr_done; + } + +/************************************************************************/ +/* geteea_objname_done */ +/* decoding get event enrollment attributes request: object name has */ +/* been decoded. */ +/************************************************************************/ + +static ST_VOID geteea_objname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteea_objname_done"); + + req_info->num_of_eenames++; /* inc # of event enroll names */ + if (req_info->num_of_eenames > max_obj_name) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + else + { + obj_ptr++; /* point to where next will go */ + _ms_get_mms_objname (aCtx, obj_ptr, geteea_objname_done); + } + } + +/************************************************************************/ +/* geteea_eelist_cstr_done */ +/* decoding get event enrollment attributes request: event enrollment */ +/* name list constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID geteea_eelist_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, geteea_client_app_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, geteea_ecname_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, geteea_eaname_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, geteea_caname_cstr); + _ms_set_cs_check2 (aCtx); /* check for CS info */ + } + +/************************************************************************/ +/* geteea_client_app_cstr */ +/* Decoding get event enrollment attributes request: client application */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID geteea_client_app_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteea_client_app_cstr"); + + req_info->client_app_pres = SD_TRUE; /* set client app present */ + + _ms_get_mms_app_ref (aCtx, &req_info->client_app,&req_info->client_app_len, + geteea_client_app_done); + } + +/************************************************************************/ +/* geteea_client_app_done */ +/* Decoding get event enrollment attributes request: client application */ +/* has been obtained. */ +/************************************************************************/ + +static ST_VOID geteea_client_app_done (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = geteea_client_app_cstr_done; + } + +/************************************************************************/ +/* geteea_client_app_cstr_done */ +/* Decoding get event enrollment attributes request: client application */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID geteea_client_app_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, geteea_ecname_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, geteea_eaname_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, geteea_caname_cstr); + _ms_set_cs_check2 (aCtx); /* check for CS info */ + } + +/************************************************************************/ +/* geteea_ecname_cstr */ +/* decoding get event enrollment attributes request: event condition */ +/* name constructor was encountered */ +/************************************************************************/ + +static ST_VOID geteea_ecname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteea_ecname_cstr"); + + req_info->evcon_name_pres = SD_TRUE; /* event condition name present */ + + _ms_get_mms_objname (aCtx, &req_info->evcon_name, geteea_ecname_done); + } + +/************************************************************************/ +/* geteea_ecname_done */ +/* decoding get event enrollment attributes request: event condition */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID geteea_ecname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteea_ecname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = geteea_ecname_cstr_done; + } + +/************************************************************************/ +/* geteea_ecname_cstr_done */ +/* decoding get event enrollment attributes request: event condition */ +/* name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID geteea_ecname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, geteea_eaname_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, geteea_caname_cstr); + _ms_set_cs_check2 (aCtx); /* check for CS info */ + } + +/************************************************************************/ +/* geteea_eaname_cstr */ +/* decoding get event enrollment attributes request: event action */ +/* name constructor was encountered */ +/************************************************************************/ + +static ST_VOID geteea_eaname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteea_eaname_cstr"); + + req_info->evact_name_pres = SD_TRUE; /* event action name present */ + + _ms_get_mms_objname (aCtx, &req_info->evact_name, geteea_eaname_done); + } + +/************************************************************************/ +/* geteea_eaname_done */ +/* decoding get event enrollment attributes request: event action */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID geteea_eaname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteea_eaname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = geteea_eaname_cstr_done; + } + +/************************************************************************/ +/* geteea_eaname_cstr_done */ +/* decoding get event enrollment attributes request: event condition */ +/* name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID geteea_eaname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, geteea_caname_cstr); + _ms_set_cs_check2 (aCtx); /* check for CS info */ + } + +/************************************************************************/ +/* geteea_caname_cstr */ +/* decoding get event enrollment attributes request: continue after */ +/* name constructor was encountered */ +/************************************************************************/ + +static ST_VOID geteea_caname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteea_caname_cstr"); + + req_info->ca_name_pres = SD_TRUE; /* continue after name present */ + + _ms_get_mms_objname (aCtx, &req_info->ca_name, geteea_caname_done); + } + +/************************************************************************/ +/* geteea_caname_done */ +/* decoding get event enrollment attributes request: continue after */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID geteea_caname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("geteea_caname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = geteea_caname_cstr_done; + } + +/************************************************************************/ +/* geteea_caname_cstr_done */ +/* decoding get event enrollment attributes request: continue after */ +/* name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID geteea_caname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check2 (aCtx); /* check for CS info */ + } + +/************************************************************************/ +/* geteea_dec_done */ +/* decode done, realloc the structure to desired size */ +/************************************************************************/ + +static ST_VOID geteea_dec_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + /* find actual size for request info */ + req_size = sizeof (GETEEA_REQ_INFO) + + (sizeof (OBJECT_NAME) * req_info->num_of_eenames); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (GETEEA_REQ_INFO *) _mms_dec_info; + + _mms_dec_done_ok (aCtx); + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_geteea_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get event enrollment attributes */ +/* response. */ +/************************************************************************/ + +ST_RET mp_geteea_resp (MMSREQ_IND *indptr, GETEEA_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_GET_EE_ATTR,indptr, + M_CAST_MK_FUN (_ms_mk_geteea_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_geteea_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get event enrollment attributes response. */ +/************************************************************************/ + +ST_RET mpl_geteea_resp (ST_UINT32 invoke_id, GETEEA_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_GET_EE_ATTR,invoke_id, + M_CAST_MK_FUN (_ms_mk_geteea_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_geteea_resp */ +/* Construct a get event enrollment attributes attributes response. */ +/************************************************************************/ + +ST_VOID _ms_mk_geteea_resp (ASN1_ENC_CTXT *aCtx, GETEEA_RESP_INFO *info) + { +ST_INT i; +EVENT_ENROLLMENT *ee_ptr; + + if (info->more_follows) + { /* not the default */ + asn1r_wr_u8 (aCtx, info->more_follows); /* write more follows indicator */ + asn1r_fin_prim (aCtx, 1, CTX); /* ctx tag 1 */ + } + + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + ee_ptr = (EVENT_ENROLLMENT *) (info + 1); + ee_ptr +=info->num_of_evenroll-1; /* point to last event enroll */ + for (i = 0; i < info->num_of_evenroll; i++) + { + asn1r_strt_constr (aCtx); /* start uni seq constructor */ + if (ee_ptr->ackec_name_pres) + { + asn1r_strt_constr (aCtx); /* start ctx tag 10 constructor */ + if (ee_ptr->ackec_name_tag == 1) + asn1r_fin_prim (aCtx, 1, CTX); /* event action name undefined */ + else + { /* write event action name */ + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &ee_ptr->ackec_name); + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish ctx tag 0 constructor */ + } + asn1r_fin_constr (aCtx, 10,CTX,DEF); /* finish ctx tag 10 constructor */ + } + +#ifdef CS_SUPPORT + if (ee_ptr->addl_detail_pres) + { + asn1r_strt_constr (aCtx); /* start ctx tag 9 constructor */ + asn1r_wr_delmnt (aCtx, ee_ptr->addl_detail,ee_ptr->addl_detail_len); + asn1r_fin_constr (aCtx, 9,CTX,DEF); /* finish ctx tag 9 constructor */ + } +#endif + + if (ee_ptr->rem_acc_delay_pres) + { + asn1r_wr_u32 (aCtx, ee_ptr->rem_acc_delay); /* write remaining acc delay */ + asn1r_fin_prim (aCtx, 8, CTX); /* ctx tag 8 */ + } + + if (ee_ptr->invoke_id_pres) + { + asn1r_wr_u32 (aCtx, ee_ptr->invoke_id); /* write the invoke id */ + asn1r_fin_prim (aCtx, 7, CTX); /* ctx tag 7 */ + } + + if (ee_ptr->duration != 0) + { /* not the default of current */ + asn1r_wr_i16 (aCtx, ee_ptr->duration); /* write the duration */ + asn1r_fin_prim (aCtx, 6, CTX); /* ctx tag 6 */ + } + + asn1r_wr_i16 (aCtx, ee_ptr->ee_class); /* write event enrollment class */ + asn1r_fin_prim (aCtx, 5, CTX); /* ctx tag 5 */ + + if (ee_ptr->mms_deletable) + { /* not the default of SD_FALSE */ + asn1r_wr_bool (aCtx, ee_ptr->mms_deletable); /* write mms deletable */ + asn1r_fin_prim (aCtx, 4, CTX); /* ctx tag 4 */ + } + + if (ee_ptr->client_app_pres) + { + asn1r_strt_constr (aCtx); /* start ctx tag 3 constructor */ + asn1r_wr_delmnt (aCtx, ee_ptr->client_app,ee_ptr->client_app_len); + asn1r_fin_constr (aCtx, 3,CTX,DEF); /* finish ctx tag 3 constructor */ + } + + if (ee_ptr->evact_name_pres) + { + asn1r_strt_constr (aCtx); /* start ctx tag 2 constructor */ + if (ee_ptr->evact_name_tag == 1) + asn1r_fin_prim (aCtx, 1, CTX); /* event action name undefined */ + else + { /* write event action name */ + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &ee_ptr->evact_name); + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish ctx tag 0 constructor */ + } + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* finish ctx tag 2 constructor */ + } + + asn1r_strt_constr (aCtx); /* start ctx tag 1 constructor */ + if (ee_ptr->evcon_name_tag == 1) + asn1r_fin_prim (aCtx, 1, CTX); /* event condition name undef */ + else + { /* write event condition name */ + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &ee_ptr->evcon_name); + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish ctx tag 0 constructor */ + } + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish ctx tag 1 constructor */ + + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &ee_ptr->evenroll_name); + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish ctx tag 0 constructor */ + + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish uni seq constructor */ + ee_ptr--; + } + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish ctx tag 0 constructor */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_EE_ATTR,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rs_getpi.c b/mmslib/mmsl/rs_getpi.c new file mode 100644 index 0000000..5daddc1 --- /dev/null +++ b/mmslib/mmsl/rs_getpi.c @@ -0,0 +1,148 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_getpi.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of get program */ +/* invocation attribute. It decodes the get program invocation */ +/* attribute request (indication) & encodes the get program */ +/* invocation attribute response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETPI_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_get_pi_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_get_pi_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Program Invocation Attribute Request"); + + +/* get storage for request information */ + req_info = (GETPI_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (GETPI_REQ_INFO)); + if (asn1r_get_identifier (aCtx, req_info->piname))/* read program invocation name */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getpi_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get program invocation attribute */ +/* response. */ +/************************************************************************/ + +ST_RET mp_getpi_resp (MMSREQ_IND *indptr, GETPI_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_GET_PI_ATTR,indptr, + M_CAST_MK_FUN (_ms_mk_getpi_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getpi_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get program invocation attribute response. */ +/************************************************************************/ + +ST_RET mpl_getpi_resp (ST_UINT32 invoke_id, GETPI_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_GET_PI_ATTR,invoke_id, + M_CAST_MK_FUN (_ms_mk_getpi_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getpi_resp */ +/* ENCODE a get program invocation attribute RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_getpi_resp (ASN1_ENC_CTXT *aCtx, GETPI_RESP_INFO *info) +{ +ST_INT i; +ST_CHAR **dom_ptr; + + if (info->start_arg_type == ARG_TYPE_SIMPLE) + { + asn1r_wr_vstr (aCtx, (ST_CHAR *)info->start_arg); /* write the start argument */ + asn1r_fin_prim (aCtx, 5,CTX); /* ctx tag 5 */ + } + else /* ENCODED data, write as complete ASN.1 EXTERNAL */ + asn1r_wr_delmnt (aCtx, info->start_arg,info->start_arg_len); + + asn1r_wr_bool (aCtx, info->monitor); /* write the monitor flag */ + asn1r_fin_prim (aCtx, 4,CTX); /* ctx tag 4 */ + + asn1r_wr_bool (aCtx, info->reusable); /* write the reusable flag */ + asn1r_fin_prim (aCtx, 3,CTX); /* ctx tag 3 */ + + asn1r_wr_bool (aCtx, info->mms_deletable); /* write mms deletable flag */ + asn1r_fin_prim (aCtx, 2,CTX); /* ctx tag 2 */ + + asn1r_strt_constr (aCtx); /* start ctx tag 2 constructor */ + dom_ptr = (ST_CHAR **) (info + 1); + dom_ptr += (info->num_of_dnames - 1); /* point to last domain name */ + for (i = 0; i < info->num_of_dnames; i++) + { + asn1r_wr_vstr (aCtx, *dom_ptr); + asn1r_fin_prim (aCtx, VISTR_CODE, UNI); + dom_ptr--; + } + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* ctx tag 1 constructor */ + + asn1r_wr_i16 (aCtx, info->state); /* write the state */ + asn1r_fin_prim (aCtx, 0,CTX); /* ctx tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_PI_ATTR,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsl/rs_getty.c b/mmslib/mmsl/rs_getty.c new file mode 100644 index 0000000..59d2290 --- /dev/null +++ b/mmslib/mmsl/rs_getty.c @@ -0,0 +1,126 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_gettype.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of get named type */ +/* attributes. It decodes the get named type attributes request */ +/* (indication) & encodes the get named type attributes response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETTYPE_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID gettype_type_name_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_get_type_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_get_type_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Named Type Attributes Request"); + +/* get storage for request information */ + req_info = (GETTYPE_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (GETTYPE_REQ_INFO)); + _ms_get_mms_objname (aCtx, &req_info->type_name, gettype_type_name_done); + } + +/************************************************************************/ +/* gettype_type_name_done */ +/* decoding get named type attributes request: type name has been */ +/* obtained. */ +/************************************************************************/ + +static ST_VOID gettype_type_name_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_gettype_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get named type attributes response. */ +/************************************************************************/ + +ST_RET mp_gettype_resp (MMSREQ_IND *indptr, GETTYPE_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_GET_TYPE,indptr, + M_CAST_MK_FUN (_ms_mk_gettype_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_gettype_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get named type attributes response. */ +/************************************************************************/ + +ST_RET mpl_gettype_resp (ST_UINT32 invoke_id, GETTYPE_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_GET_TYPE,invoke_id, + M_CAST_MK_FUN (_ms_mk_gettype_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_gettype_resp */ +/* Construct a get named type attributes response. */ +/************************************************************************/ + +ST_VOID _ms_mk_gettype_resp (ASN1_ENC_CTXT *aCtx, GETTYPE_RESP_INFO *info) + { + _ms_wr_va_type_spec (aCtx, &info->type_spec); /* write the type specification */ + + asn1r_wr_bool (aCtx , info->mms_deletable); /* write mms deletable flag */ + asn1r_fin_prim (aCtx , 0,CTX); /* context tag 1 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx , MMSOP_GET_TYPE,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsl/rs_getva.c b/mmslib/mmsl/rs_getva.c new file mode 100644 index 0000000..f48e1a4 --- /dev/null +++ b/mmslib/mmsl/rs_getva.c @@ -0,0 +1,170 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_getvar.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of get variable */ +/* access attributes. It decodes the get variable access */ +/* attributes request (indication) & encodes the get variable */ +/* access attributes response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETVAR_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID getvar_na_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getvar_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getvar_addr_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_get_var_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_get_var_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Variable Access Attributes Request"); + + /* get storage for request information */ +/* get storage for request information */ + req_info = (GETVAR_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (GETVAR_REQ_INFO)); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, getvar_name_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, getvar_addr_cstr); + } + +/************************************************************************/ +/* getvar_name_cstr */ +/* decoding get variable access attributes request: name constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID getvar_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getvar_name_cstr"); + + req_info->req_tag = SD_SUCCESS; /* set tag to name */ + + _ms_get_mms_objname (aCtx, &req_info->name, getvar_na_done); + } + +/************************************************************************/ +/* getvar_addr_cstr */ +/* decoding get variable access attributes request: address constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID getvar_addr_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getvar_addr_cstr"); + + req_info->req_tag = SD_TRUE; /* set tag to address */ + + _ms_get_va_address (aCtx, &req_info->address, getvar_na_done); + } + +/************************************************************************/ +/* getvar_na_done */ +/* decoding get variable access attributes request: name or address has */ +/* been obtained. */ +/************************************************************************/ + +static ST_VOID getvar_na_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getvar_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the get variable access attributes response */ +/************************************************************************/ + +ST_RET mp_getvar_resp (MMSREQ_IND *indptr, GETVAR_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_GET_VAR,indptr, + M_CAST_MK_FUN (_ms_mk_getvar_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getvar_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get variable access attributes response */ +/************************************************************************/ + +ST_RET mpl_getvar_resp (ST_UINT32 invoke_id, GETVAR_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_GET_VAR,invoke_id, + M_CAST_MK_FUN (_ms_mk_getvar_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getvar_resp */ +/* Construct a get variable access attributes response. */ +/************************************************************************/ + +ST_VOID _ms_mk_getvar_resp (ASN1_ENC_CTXT *aCtx, GETVAR_RESP_INFO *info) + { + asn1r_strt_constr (aCtx); /* start context tag 2 cstr */ + _ms_wr_va_type_spec (aCtx, &info->type_spec); /* write the type specification */ + asn1r_fin_constr (aCtx, 2, CTX, DEF); /* finish context tag 2 cstr */ + + if (info->address_pres) + { + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + _ms_wr_va_address (aCtx, &info->address); /* write the address */ + asn1r_fin_constr (aCtx, 1, CTX, DEF); /* finish context tag 1 cstr */ + } + + asn1r_wr_bool (aCtx, info->mms_deletable); /* write mms deletable flag */ + asn1r_fin_prim (aCtx, 0,CTX); /* context tag 1 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_VAR,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsl/rs_getvl.c b/mmslib/mmsl/rs_getvl.c new file mode 100644 index 0000000..34955ec --- /dev/null +++ b/mmslib/mmsl/rs_getvl.c @@ -0,0 +1,139 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_getvlist.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of get scattered */ +/* access attributes. It decodes the get named variable list */ +/* attributes request (indication) & encodes the get scattered */ +/* access attributes response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETVLIST_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID getvlist_name_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_get_vlist_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_get_vlist_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Named Variable List Attributes Request"); + + /* get storage for request information */ +/* get storage for request information */ + req_info = (GETVLIST_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (GETVLIST_REQ_INFO)); + _ms_get_mms_objname (aCtx, &req_info->vl_name, getvlist_name_done); + } + +/************************************************************************/ +/* getvlist_name_done */ +/* decoding get named variable list attributes request: variable list */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID getvlist_name_done (ASN1_DEC_CTXT *aCtx) + { + asn1r_set_all_cstr_done (aCtx); /* clear cstr done functions */ + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getvlist_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the get named variable list attributes */ +/* response. */ +/************************************************************************/ + +ST_RET mp_getvlist_resp (MMSREQ_IND *indptr, GETVLIST_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_GET_VLIST,indptr, + M_CAST_MK_FUN (_ms_mk_getvlist_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getvlist_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get named variable list attributes response. */ +/************************************************************************/ + +ST_RET mpl_getvlist_resp (ST_UINT32 invoke_id, + GETVLIST_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_GET_VLIST,invoke_id, + M_CAST_MK_FUN (_ms_mk_getvlist_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getvlist_resp */ +/* Construct a get named variable list attributes response. */ +/************************************************************************/ + +ST_VOID _ms_mk_getvlist_resp (ASN1_ENC_CTXT *aCtx, GETVLIST_RESP_INFO *info) + { +VARIABLE_LIST *vl_ptr; + + /* get ptr to list of variables */ + vl_ptr = (VARIABLE_LIST *) (info + 1); + + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + _ms_wr_va_var_list (aCtx, vl_ptr, info->num_of_variables); + asn1r_fin_constr (aCtx, 1, CTX, DEF); /* finish context tag 1 cstr */ + + asn1r_wr_bool (aCtx, info->mms_deletable); /* write mms deletable flag */ + asn1r_fin_prim (aCtx, 0,CTX); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_VLIST,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsl/rs_ident.c b/mmslib/mmsl/rs_ident.c new file mode 100644 index 0000000..1b78a90 --- /dev/null +++ b/mmslib/mmsl/rs_ident.c @@ -0,0 +1,122 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_ident.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the Identify */ +/* service. It decodes the Identify request (indication) and */ +/* encodes the Identify response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : */ +/* IDENT_RESP_INFO mmse_ident_info; */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_identify_req */ +/* NOTE : Since the identify req is a NULL PDU, the decode is continued */ +/* by '_mms_null_pdu_dec', which simply sets decode done = 1 and sets */ +/* the decode done function to point to the general decode done fun */ +/* See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_ident_resp */ +/* This function is called from the user to ENCODE and send the */ +/* Identify response PDU. */ +/************************************************************************/ + +ST_RET mp_ident_resp (MMSREQ_IND *indptr, IDENT_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_IDENTIFY,indptr, + M_CAST_MK_FUN (_ms_mk_ident_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_ident_resp */ +/* This function is called from the user to ENCODE the Identify */ +/* response PDU. */ +/************************************************************************/ + +ST_RET mpl_ident_resp (ST_UINT32 invoke_id, IDENT_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_IDENTIFY,invoke_id, + M_CAST_MK_FUN (_ms_mk_ident_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_ident_resp */ +/* ENCODE an Identify RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_ident_resp (ASN1_ENC_CTXT *aCtx, IDENT_RESP_INFO *info) + { +ST_INT i; +struct mms_obj_id *obj; + + asn1r_strt_constr (aCtx); + + if (info->num_as) /* if user wants to send AS */ + { + asn1r_strt_constr (aCtx); /* sequence */ + obj = (struct mms_obj_id *) (info +1); /* point to first AS */ + + for (i = 0; i < info->num_as; ++i, ++obj) + { + asn1r_wr_objid (aCtx, obj->comps, obj->num_comps); + asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI); + } + asn1r_fin_constr (aCtx, 3,CTX,DEF); /* finish sequence of AS */ + } + + asn1r_wr_vstr (aCtx, info->rev); /* write the revision name */ + asn1r_fin_prim (aCtx, 2,CTX); + + asn1r_wr_vstr (aCtx, info->model); /* write the model name */ + asn1r_fin_prim (aCtx, 1,CTX); + + asn1r_wr_vstr (aCtx, info->vend); /* write the vendor name */ + asn1r_fin_prim (aCtx, 0,CTX); + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_IDENTIFY,CTX,DEF); /* tag = opcode, context */ + } diff --git a/mmslib/mmsl/rs_info.c b/mmslib/mmsl/rs_info.c new file mode 100644 index 0000000..127496a --- /dev/null +++ b/mmslib/mmsl/rs_info.c @@ -0,0 +1,184 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_info.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of information */ +/* report. It decodes the information report request (indication). */ +/* There is no response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static INFO_REQ_INFO *req_info; + + +static ACCESS_RESULT *ar_ptr; +static ST_INT max_vars; +static ST_INT max_acc_rslt; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID info_acc_rslt_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID info_acc_rslt_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID info_acc_rslt_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID info_va_spec_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_info_rpt_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_info_rpt_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT size1; +ST_INT size2; +ST_INT req_size; + + MLOG_CDEC0 ("Information Report Request"); + +#if defined(FIXED_DECBUF) + max_acc_rslt = m_cl_max_info_acc_rslt; + max_vars = m_cl_max_info_var_spec; + req_size = mmsl_dec_info_size; +#else + +/* First assume a list of variables (each var has a data) */ + max_vars = _mmsdec_msglen / 7; + if (m_cl_max_info_var_spec && (max_vars > m_cl_max_info_var_spec)) + max_vars = m_cl_max_info_var_spec; + + size1 = sizeof(INFO_REQ_INFO) + + (max_vars * (sizeof(VARIABLE_LIST) + sizeof(ACCESS_RESULT))); + +/* Now assume a named variable list name */ + max_acc_rslt = _mmsdec_msglen / 3; + if (m_cl_max_info_acc_rslt && (max_acc_rslt > m_cl_max_info_acc_rslt)) + max_acc_rslt = m_cl_max_info_acc_rslt; + size2 = sizeof(INFO_REQ_INFO) + (sizeof(ACCESS_RESULT) * max_acc_rslt); + + req_size = max(size1, size2); +#endif + +/* get storage for request information */ + req_info = (INFO_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + _ms_get_va_spec (aCtx, &req_info->va_spec, max_vars, info_va_spec_done); + } + +/************************************************************************/ +/* info_va_spec_done */ +/* decoding information report request: variable access specification */ +/* has been decoded. */ +/************************************************************************/ + +static ST_VOID info_va_spec_done (ASN1_DEC_CTXT *aCtx) + { + +VARIABLE_LIST *temp; + + MLOG_CDEC0 ("info_va_spec_done"); + + temp = (VARIABLE_LIST *) (req_info + 1); + temp += req_info->va_spec.num_of_variables; + + req_info->acc_rslt_list = (ACCESS_RESULT *) temp; + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, info_acc_rslt_cstr); + } + +/************************************************************************/ +/* info_acc_rslt_cstr */ +/* decoding information report request: access result constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID info_acc_rslt_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("info_acc_rslt_cstr"); + + ar_ptr = req_info->acc_rslt_list; + + _ms_get_va_access_rslt (aCtx, ar_ptr, info_acc_rslt_done); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = info_acc_rslt_cstr_done; + } + +/************************************************************************/ +/* info_acc_rslt_done */ +/* decoding information report request: access result has been decoded. */ +/************************************************************************/ + +static ST_VOID info_acc_rslt_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("info_acc_rslt_done"); + + req_info->num_of_acc_result++; + if ((req_info->num_of_acc_result + 1) <= max_acc_rslt) + { + ar_ptr++; + _ms_get_va_access_rslt (aCtx, ar_ptr, info_acc_rslt_done); + } + } + +/************************************************************************/ +/* info_acc_rslt_cstr_done */ +/* decoding information report request: access result constructor done */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID info_acc_rslt_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; +VARIABLE_LIST *temp; + + MLOG_CDEC0 ("info_acc_rslt_cstr_done"); + /* find actual size for request info */ + req_size = sizeof (INFO_REQ_INFO) + + (sizeof (VARIABLE_LIST)*req_info->va_spec.num_of_variables) + + (sizeof (ACCESS_RESULT)*req_info->num_of_acc_result); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (INFO_REQ_INFO *) _mms_dec_info; + +/* some C run time library mem mgmt. functions will always give back a */ +/* new pointer when reallocating smaller. In the case of info_req_info */ +/* we have to update the acc_rslt_list ptr to point to this new mem loc */ + + temp = (VARIABLE_LIST *) (req_info + 1); + temp += req_info->va_spec.num_of_variables; + req_info->acc_rslt_list = (ACCESS_RESULT *) temp; + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } diff --git a/mmslib/mmsl/rs_init.c b/mmslib/mmsl/rs_init.c new file mode 100644 index 0000000..b51c136 --- /dev/null +++ b/mmslib/mmsl/rs_init.c @@ -0,0 +1,266 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2007, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_init.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the initiate */ +/* operation. It decodes the initiate request (indication) and */ +/* encodes the initiate response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/01/07 EJV 09 Rem obsolete LLC30... code. */ +/* 03/09/05 EJV 08 Fixed thisFileName for MMS-EASE */ +/* 03/11/04 GLB 07 Cleaned up "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/08/00 RKR 05 Log error response for negative initiate resp*/ +/* instead of calling m_log_resp_info_fun. */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 04/07/98 MDE 01 Minor restructure to eliminate warnings */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pcon.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) && (defined(S_MT_SUPPORT) || !defined(MMS_LITE)) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/* mms_init_req */ +/* Function called to decode an Initiate request PDU after the PDU type */ +/* has been determined. Sets up the parse of the next data element and */ +/* returns, letting the ASN.1 tools take over. */ +/* */ +/* NOTE : This functionality has been moved to mmsinit.c, because the */ +/* request and response are identical. The call to mms_init_req was */ +/* put back to better support MMSEASE-LITE. */ +/************************************************************************/ + +ST_VOID mms_init_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("decode initiate request"); + _mms_init_dec (aCtx, SD_TRUE); + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_init_resp */ +/* create and send an initiate response */ +/************************************************************************/ + +ST_RET mp_init_resp (MMSREQ_IND *indptr, INIT_INFO *info) + { +ST_UCHAR *msg_ptr; +ST_RET ret; +ST_INT i; +ST_INT num_ui; +INIT_UI *ui; +INIT_UI *ui_ptr; +ST_INT cs_count; +CS_INIT_INFO *cs_info_ptr; +ST_UCHAR *cs_build_bufs[MAX_INIT_CONTEXTS]; +ST_UCHAR *buf; +ST_BOOLEAN context_accepted; +ST_RET result; +ST_INT16 reason; +ST_INT16 eclass; +ST_INT16 code; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + if (info->num_cs_init > MAX_INIT_CONTEXTS) + return (ME_TOO_MANY_CONTEXTS); + + S_LOCK_COMMON_RESOURCES (); + context_accepted = SD_FALSE; /* clear flag */ + + if (!(ret = _ms_check_ind_actv (indptr))) + { + num_ui = info->num_cs_init; + if (info->mms_p_context_pres) + num_ui++; + + if (num_ui) + ui = ui_ptr = (INIT_UI *) chk_calloc (num_ui, sizeof (INIT_UI)); + else + ui = NULL; + + cs_count = 0; + cs_info_ptr = (CS_INIT_INFO *) (info + 1); + for (i = 0; i < num_ui; ++i, ++ui_ptr) + { +/* build the core initiate, if used and position reached or if no */ +/* companion standard initiates are to be sent */ + + if ((info->mms_p_context_pres && i == info->core_position) || + !info->num_cs_init) + { + if (info->rslt.accept_context) + { + context_accepted = SD_TRUE; /* set flag */ + msg_ptr = _ms_mk_init (aCtx, m_build_buf,mms_max_msgsize,info,MMSINITRESP,SD_FALSE); + } + else + { + msg_ptr = _ms_mk_err_resp (aCtx, m_build_buf,mms_max_msgsize,indptr->op,indptr->id, + info->rslt.err.eclass,info->rslt.err.code); + eclass = info->rslt.err.eclass; + code = info->rslt.err.code; + } + ui_ptr->context = MMS_PCI; + if (info->rslt.accept_context) + ui_ptr->reject = SD_FALSE; + else + ui_ptr->reject = SD_TRUE; + ui_ptr->ui_len = M_BUILD_BUF_END - msg_ptr; + } + else + { + buf = cs_build_bufs[cs_count++] = (ST_UCHAR *) + chk_calloc (1,M_INIT_BUILD_LEN); + if (cs_info_ptr->rslt.accept_context) + { + context_accepted = SD_TRUE; /* set flag */ + msg_ptr = _ms_mk_init (aCtx, buf,M_INIT_BUILD_LEN, + (INIT_INFO *) cs_info_ptr,MMSINITRESP,SD_TRUE); + } + else + { + msg_ptr = _ms_mk_err_resp (aCtx, buf,M_INIT_BUILD_LEN,indptr->op,indptr->id, + cs_info_ptr->rslt.err.eclass,cs_info_ptr->rslt.err.code); + eclass = cs_info_ptr->rslt.err.eclass; + code = cs_info_ptr->rslt.err.code; + } + + ui_ptr->context = cs_info_ptr->p_context; + if (cs_info_ptr->rslt.accept_context) + ui_ptr->reject = SD_FALSE; + else + ui_ptr->reject = SD_TRUE; + ui_ptr->ui_len = (buf + M_INIT_BUILD_LEN) - msg_ptr; + } + ui_ptr->ui_ptr = msg_ptr; + } + +/* Now set up the ACSE result & reason parameteds */ + if (context_accepted) /* if any context accepted */ + { + result = 0; + reason = 0; + } + else /* no context was accepted */ + { + result = 1; + reason = 1; + } + + /* If a response logging function is installed, call it */ + + if (result==0) + { + if (m_log_resp_info_fun && (mms_debug_sel & MMS_LOG_RESP)) + (*m_log_resp_info_fun) (indptr, info); + } + else + { + if (m_log_error_resp_fun && (mms_debug_sel & MMS_LOG_RESP)) + (*m_log_error_resp_fun) (indptr, eclass, code); + } + + ret = _mllp_init_resp (indptr->chan,result,reason, + num_ui, ui,indptr->add_addr_info); + + _ms_ind_serve_done (indptr); + + if (ui) + chk_free (ui); + + for (i = 0; i < info->num_cs_init; ++i) /* free CS build buffers */ + chk_free (cs_build_bufs[i]); + } + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_init_resp */ +/* create an initiate response */ +/************************************************************************/ + +ST_RET mpl_init_resp (INIT_INFO *info_ptr) + { +ST_RET ret; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + S_LOCK_COMMON_RESOURCES (); + + mmsl_msg_start = _ms_mk_init (aCtx, mmsl_enc_buf, mmsl_enc_buf_size, + info_ptr,MMSINITRESP,SD_FALSE); + mmsl_msg_len = (mmsl_enc_buf + mmsl_enc_buf_size) - mmsl_msg_start; + + if (!aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + ret = SD_SUCCESS; + else + ret = ME_ASN1_ENCODE_OVERRUN; + + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +#ifdef CS_SUPPORT +/************************************************************************/ +/************************************************************************/ +/* mpl_cs_init_resp */ +/* create a companion standard initiate response */ +/************************************************************************/ + +ST_RET mpl_cs_init_resp (CS_INIT_INFO *info_ptr) + { +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + mmsl_msg_start = _ms_mk_init (aCtx, mmsl_enc_buf, mmsl_enc_buf_size, + (INIT_INFO *) info_ptr,MMSINITRESP,SD_TRUE); + mmsl_msg_len = (mmsl_enc_buf + mmsl_enc_buf_size) - mmsl_msg_start; + + if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ + return (ME_ASN1_ENCODE_OVERRUN); + return (SD_SUCCESS); + } +#endif + +#endif + +/************************************************************************/ +/* mk_initiate */ +/* Note that there is only one mk_initiate function, and it is listed */ +/* in the mmsinit.c module. */ +/************************************************************************/ diff --git a/mmslib/mmsl/rs_namel.c b/mmslib/mmsl/rs_namel.c new file mode 100644 index 0000000..6527041 --- /dev/null +++ b/mmslib/mmsl/rs_namel.c @@ -0,0 +1,341 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2002, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_namel.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the GetNameList */ +/* service. It decodes the GetNameList request (indication) and */ +/* encodes the GetNameList response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 10 Remove "thisFileName" */ +/* 07/01/02 EJV 09 NLV: support namelist for dom specific jou. */ +/* 12/20/01 JRB 08 Converted to use ASN1R (re-entrant ASN1) */ +/* 05/05/00 JRB 07 Lint cleanup */ +/* 04/07/00 RKR 06 Added code to check for illegal scope & class*/ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static NAMELIST_REQ_INFO *info; + +/* static functions */ +static ST_VOID namelist_get_extobjclass (ASN1_DEC_CTXT *aCtx); +static ST_VOID namelist_get_objclass (ASN1_DEC_CTXT *aCtx); +#ifdef CS_SUPPORT +static ST_VOID namelist_get_cs_objclass (ASN1_DEC_CTXT *aCtx); +static ST_VOID namelist_cs_objclass_done (ASN1_DEC_CTXT *aCtx); +#endif +static ST_VOID namelist_extobj_class_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID namelist_get_objscope (ASN1_DEC_CTXT *aCtx); +static ST_VOID namelist_get_vmdscope (ASN1_DEC_CTXT *aCtx); +static ST_VOID namelist_get_domscope (ASN1_DEC_CTXT *aCtx); +static ST_VOID namelist_get_aascope (ASN1_DEC_CTXT *aCtx); +static ST_VOID namelist_objscope_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID namelist_get_continue_after (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_namelist_req */ +/* This function is called from MMSDEC when the opcode of a request */ +/* PDU for this operation is decoded. Setup state machine function */ +/* pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_namelist_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("GetNameList Request"); + + +/* get storage for request information */ + info = (NAMELIST_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (NAMELIST_REQ_INFO)); + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,namelist_get_extobjclass); + } + +/************************************************************************/ +/* namelist_get_extobjclass */ +/* GetNameList response is being decoded: object class parameter has */ +/* been encountered. */ +/************************************************************************/ + +static ST_VOID namelist_get_extobjclass (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("namelist_get_extobjclass"); + + ASN1R_TAG_ADD (aCtx, CTX,0,namelist_get_objclass); +#ifdef CS_SUPPORT + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,namelist_get_cs_objclass); +#endif + } + +/************************************************************************/ +/* namelist_get_objclass */ +/* GetNameList response is being decoded: object class parameter has */ +/* been encountered. */ +/************************************************************************/ + +static ST_VOID namelist_get_objclass (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("namelist_get_objclass"); + /* read the object class */ + if (asn1r_get_i16 (aCtx, &info->obj.mms_class) || + info->obj.mms_class < 0 || + info->obj.mms_class > 11) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = namelist_extobj_class_done; + } + +#ifdef CS_SUPPORT +/************************************************************************/ +/* namelist_get_cs_objclass */ +/* GetNameList response is being decoded: CS object class parameter has */ +/* been encountered. The contents here are a ANY, defined by CS. */ +/************************************************************************/ + +static ST_VOID namelist_get_cs_objclass (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("namelist_get_cs_objclass"); + + info->cs_objclass_pres = SD_TRUE; /* set flag for CS object */ + info->obj.cs.len = aCtx->asn1r_elmnt_len; /* save pointer and len */ + info->obj.cs.cs_class = aCtx->asn1r_field_ptr; + + asn1r_parse_next (aCtx, namelist_cs_objclass_done); /* ensure valid ASN.1 CS data */ + } + +/************************************************************************/ +/* namelist_cs_objclass_done */ +/************************************************************************/ + +static ST_VOID namelist_cs_objclass_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("namelist_cs_objclass_done"); + /* OK for extended object class to be done */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = namelist_extobj_class_done; + } +#endif + +/************************************************************************/ +/* namelist_extobj_class_done */ +/* extendedObjectClass constructor done function. Set up to get Scope */ +/************************************************************************/ + +static ST_VOID namelist_extobj_class_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("namelist_extobj_class_done"); + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,namelist_get_objscope); /* get Object Scope */ + } + +/************************************************************************/ +/* namelist_get_objscope */ +/* GetNameList response is being decoded: object scope constructor has */ +/* been encountered, set up to get scope */ +/************************************************************************/ + +static ST_VOID namelist_get_objscope (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("namelist_get_objscope"); + +/* This constructor contains one of three data elements, where the tag */ +/* is the scope identifier. */ + + ASN1R_TAG_ADD (aCtx, CTX,0,namelist_get_vmdscope); + ASN1R_TAG_ADD (aCtx, CTX,1,namelist_get_domscope); + ASN1R_TAG_ADD (aCtx, CTX,2,namelist_get_aascope); + } + +/************************************************************************/ +/* namelist_get_vmdscope */ +/* VMD scope, must be null */ +/************************************************************************/ + +static ST_VOID namelist_get_vmdscope (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("namelist_get_vmdscope"); + + if (aCtx->asn1r_elmnt_len) /* if not NULL */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + info->objscope = VMD_SPEC; /* set scope */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = namelist_objscope_done; + } + +/************************************************************************/ +/* namelist_get_domscope */ +/* VMD scope, must be null */ +/************************************************************************/ + +static ST_VOID namelist_get_domscope (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("namelist_get_domscope"); + + if ((asn1r_get_identifier (aCtx, info->dname)) || /* read the domain name */ + (info->obj.mms_class == MMS_CLASS_DOM) || + (info->obj.mms_class == MMS_CLASS_PI) || + (info->obj.mms_class == MMS_CLASS_OPER_STA)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + info->objscope = DOM_SPEC; /* set scope */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = namelist_objscope_done; + } + +/************************************************************************/ +/* namelist_get_aascope */ +/* VMD scope, must be null */ +/************************************************************************/ + +static ST_VOID namelist_get_aascope (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("namelist_get_aascope"); + + if ((aCtx->asn1r_elmnt_len) || /* if not NULL */ + (info->obj.mms_class == MMS_CLASS_DOM) || + (info->obj.mms_class == MMS_CLASS_PI) || + (info->obj.mms_class == MMS_CLASS_OPER_STA) || + (info->obj.mms_class == MMS_CLASS_SEM)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + info->objscope = AA_SPEC; /* set scope */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = namelist_objscope_done; + } + +/************************************************************************/ +/* namelist_objscope_done */ +/* object scope constructor complete, now the message could be done. */ +/************************************************************************/ + +static ST_VOID namelist_objscope_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("namelist_objscope_done"); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + ASN1R_TAG_ADD (aCtx, CTX,2,namelist_get_continue_after); + } + +/************************************************************************/ +/* namelist_get_continue_after */ +/* GetNameList response is being decoded: continue after parameter was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID namelist_get_continue_after (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("namelist_get_continue_after"); + + info->cont_after_pres = SD_TRUE; /* read the continue */ + if (asn1r_get_identifier (aCtx, info->continue_after)) /* after parameter */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + +/* There are no other data elements in the message. Indicate that the */ +/* end of the message should have been reached, and that all construc- */ +/* tors should have ended at this point. */ + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_namelist_resp */ +/* This function is called from the user to ENCODE and send the */ +/* GetNameList response PDU. */ +/************************************************************************/ + +ST_RET mp_namelist_resp (MMSREQ_IND *indptr, NAMELIST_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_GET_NAMLIST,indptr, + M_CAST_MK_FUN (_ms_mk_namel_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_namelist_resp */ +/* This function is called by the user to ENCODE a GetNameList response */ +/* PDU. */ +/************************************************************************/ + +ST_RET mpl_namelist_resp (ST_UINT32 invoke_id, NAMELIST_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_GET_NAMLIST,invoke_id, + M_CAST_MK_FUN (_ms_mk_namel_resp), + (ST_CHAR *)info_ptr)); + } +#endif + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_namel_resp */ +/* Construct a GetNameList RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_namel_resp (ASN1_ENC_CTXT *aCtx, NAMELIST_RESP_INFO *info_ptr) + { +ST_CHAR **nptr; /* Ptr to array of name ptrs */ +ST_INT i; + + if (!info_ptr -> more_follows) /* if not default value (SD_TRUE) */ + { + asn1r_wr_bool (aCtx, info_ptr -> more_follows); /* write end of list boolean */ + asn1r_fin_prim (aCtx, 1,CTX); + } + + asn1r_strt_constr (aCtx); /* start the 'seqof' names cstr */ + +/* Calculate the address of the first name pointer. */ + + nptr = (ST_CHAR **)(info_ptr + 1); + nptr += (info_ptr->num_names - 1); /* point to last name */ + + for (i=0;i < info_ptr -> num_names;i++) + { + asn1r_wr_vstr (aCtx, *nptr); /* write the list of names */ + asn1r_fin_prim (aCtx, VISTR_CODE,UNI); + nptr--; + } + + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* complete sequence of names */ + asn1r_fin_constr (aCtx, MMSOP_GET_NAMLIST,CTX,DEF); /* complete GetNameList resp */ + } diff --git a/mmslib/mmsl/rs_read.c b/mmslib/mmsl/rs_read.c new file mode 100644 index 0000000..7ccd932 --- /dev/null +++ b/mmslib/mmsl/rs_read.c @@ -0,0 +1,209 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_read.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of variable read. */ +/* It decodes the variable read request (indication) & encodes */ +/* the variable read response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static READ_REQ_INFO *req_info; +static ST_INT max_vars; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID read_va_spec_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID read_va_spec_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID read_va_spec_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID read_get_spec_in_rslt (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/************************************************************************/ +/* mms_read_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_read_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Variable Read Request"); + +#if defined(FIXED_DECBUF) + max_vars = m_sv_max_read_var_spec; + req_size = mmsl_dec_info_size; +#else + max_vars = _mmsdec_msglen / 4; /* find maximum storage required */ + if (m_sv_max_read_var_spec && (max_vars > m_sv_max_read_var_spec)) + max_vars = m_sv_max_read_var_spec; + req_size = sizeof (READ_REQ_INFO) + (sizeof (VARIABLE_LIST) * max_vars); +#endif + +/* get storage for request information */ + req_info = (READ_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + req_info->spec_in_result = SD_FALSE; /* set default value */ + ASN1R_TAG_ADD (aCtx, CTX, 0, read_get_spec_in_rslt); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, read_va_spec_cstr); + } + +/************************************************************************/ +/* read_get_spec_in_rslt */ +/* decoding variable read request: specification in result was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID read_get_spec_in_rslt (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("read_get_spec_in_rslt"); + + req_info->spec_in_result = SD_TRUE; /* specification in rslt pres */ + if (asn1r_get_bool (aCtx, &req_info->spec_in_result)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, read_va_spec_cstr); + } + +/************************************************************************/ +/* read_va_spec_cstr */ +/* decoding variable read request: variable access specification */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID read_va_spec_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("read_va_spec_cstr"); + + _ms_get_va_spec (aCtx, &req_info->va_spec, max_vars, read_va_spec_done); + } + +/************************************************************************/ +/* read_va_spec_done */ +/* decoding variable read request: variable access specification */ +/* has been decoded. */ +/************************************************************************/ + +static ST_VOID read_va_spec_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("read_va_spec_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = read_va_spec_cstr_done; + } + +/************************************************************************/ +/* read_va_spec_cstr_done */ +/* decoding variable read request: variable access specification */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID read_va_spec_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + /* find actual size for request info */ + req_size = sizeof (READ_REQ_INFO) + + (sizeof (VARIABLE_LIST)*req_info->va_spec.num_of_variables); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (READ_REQ_INFO *) _mms_dec_info; + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_read_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the variable read response. */ +/************************************************************************/ + +ST_RET mp_read_resp (MMSREQ_IND *indptr, READ_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_READ,indptr, + M_CAST_MK_FUN (_ms_mk_read_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_read_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the variable read response. */ +/************************************************************************/ + +ST_RET mpl_read_resp (ST_UINT32 invoke_id, READ_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_READ,invoke_id, + M_CAST_MK_FUN (_ms_mk_read_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_read_resp */ +/* Construct a variable read response. */ +/************************************************************************/ + +ST_VOID _ms_mk_read_resp (ASN1_ENC_CTXT *aCtx, READ_RESP_INFO *info) + { +ST_INT i; +ACCESS_RESULT *ar_ptr; + + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + ar_ptr = info->acc_rslt_list; + ar_ptr += info->num_of_acc_result - 1; + for (i = 0; i < info->num_of_acc_result; i++) + { + _ms_wr_va_access_rslt (aCtx, ar_ptr); + ar_ptr--; + } + asn1r_fin_constr (aCtx, 1,CTX, DEF); /* finish context tag 1 cstr */ + + if (info->va_spec_pres) + { + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + _ms_wr_va_spec (aCtx, &info->va_spec); + asn1r_fin_constr (aCtx, 0, CTX, DEF); /* finish context tag 0 cstr */ + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_READ,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsl/rs_repea.c b/mmslib/mmsl/rs_repea.c new file mode 100644 index 0000000..0c702db --- /dev/null +++ b/mmslib/mmsl/rs_repea.c @@ -0,0 +1,126 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_repeas.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the report event */ +/* action status. It decodes the report event action status */ +/* request (indication) and encodes the report event action */ +/* status response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static REPEAS_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID repeas_objname_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_repeas_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_repeas_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Report Event Action Status Request"); + +/* get storage for request information */ + req_info = (REPEAS_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (REPEAS_REQ_INFO)); + aCtx->asn1r_err_fun = _mms_dec_buf_free; + _ms_get_mms_objname (aCtx, &req_info->evact_name, repeas_objname_done); + } + +/************************************************************************/ +/* repeas_objname_done */ +/* Decoding get event action attributes request: event action name */ +/* has been obtained. */ +/************************************************************************/ + +static ST_VOID repeas_objname_done (ASN1_DEC_CTXT *aCtx) + { + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_repeas_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the report event action status response */ +/************************************************************************/ + +ST_RET mp_repeas_resp (MMSREQ_IND *indptr, REPEAS_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_REP_EA_STAT,indptr, + M_CAST_MK_FUN (_ms_mk_repeas_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_repeas_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the report event action status response. */ +/************************************************************************/ + +ST_RET mpl_repeas_resp (ST_UINT32 invoke_id, REPEAS_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_REP_EA_STAT,invoke_id, + M_CAST_MK_FUN (_ms_mk_repeas_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_repeas_resp */ +/* Construct a get event action attributes response. */ +/************************************************************************/ + +ST_VOID _ms_mk_repeas_resp (ASN1_ENC_CTXT *aCtx, REPEAS_RESP_INFO *info) + { + asn1r_wr_u32 (aCtx, info->num_of_ev_enroll); /* write # of event enrollments */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_REP_EA_STAT,CTX); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rs_repec.c b/mmslib/mmsl/rs_repec.c new file mode 100644 index 0000000..5856aba --- /dev/null +++ b/mmslib/mmsl/rs_repec.c @@ -0,0 +1,148 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_repec.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the report event */ +/* condition status. It decodes the report event condition status */ +/* request (indication) and encodes the report event condition */ +/* status response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static REPECS_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID repecs_objname_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_repecs_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_repecs_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Report Event Condition Status Request"); + /* get storage for request information */ + req_info = (REPECS_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (REPECS_REQ_INFO)); + _ms_get_mms_objname (aCtx, &req_info->evcon_name, repecs_objname_done); + } + +/************************************************************************/ +/* repecs_objname_done */ +/* Decoding report event condition status request: event condition */ +/* name has been obtained */ +/************************************************************************/ + +static ST_VOID repecs_objname_done (ASN1_DEC_CTXT *aCtx) + { + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_repecs_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the report event condition status */ +/************************************************************************/ + +ST_RET mp_repecs_resp (MMSREQ_IND *indptr, REPECS_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_REP_EC_STAT,indptr, + M_CAST_MK_FUN (_ms_mk_repecs_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_repecs_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the report event condition status. */ +/************************************************************************/ + +ST_RET mpl_repecs_resp (ST_UINT32 invoke_id, REPECS_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_REP_EC_STAT,invoke_id, + M_CAST_MK_FUN (_ms_mk_repecs_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_repecs_resp */ +/* Construct a report event condition status response. */ +/************************************************************************/ + +ST_VOID _ms_mk_repecs_resp (ASN1_ENC_CTXT *aCtx, REPECS_RESP_INFO *info) + { + if (info->tti_time_pres) + { /* write tran to idle time */ + asn1r_strt_constr (aCtx); /* start ctx tag 4 constructor */ + _ms_wr_mms_evtime (aCtx, &info->tti_time); + asn1r_fin_constr (aCtx, 4,CTX,DEF); /* finish ctx tag 4 constructor */ + } + + if (info->tta_time_pres) + { /* write tran to active time */ + asn1r_strt_constr (aCtx); /* start ctx tag 3 constructor */ + _ms_wr_mms_evtime (aCtx, &info->tta_time); + asn1r_fin_constr (aCtx, 3,CTX,DEF); /* finish ctx tag 3 constructor */ + } + + if (info->enabled_pres) + { /* write enabled indicator */ + asn1r_wr_bool (aCtx, info->enabled); + asn1r_fin_prim (aCtx, 2,CTX); /* finish ctx tag 2 */ + } + + asn1r_wr_u32 (aCtx, info->num_of_ev_enroll); /* write # of event enrollments */ + asn1r_fin_prim (aCtx, 1, CTX); /* ctx tag 1 */ + + asn1r_wr_i16 (aCtx, info->cur_state); + asn1r_fin_prim (aCtx, 0, CTX); + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_REP_EC_STAT,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rs_repee.c b/mmslib/mmsl/rs_repee.c new file mode 100644 index 0000000..af79040 --- /dev/null +++ b/mmslib/mmsl/rs_repee.c @@ -0,0 +1,142 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_repees.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the report event */ +/* enrollment status. It decodes the report event enrollment */ +/* status request (indication) and encodes the report event */ +/* enrollment status response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static REPEES_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID repees_objname_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_repees_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_repees_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Report Event Enrollment Status Request"); + req_info = (REPEES_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (REPEES_REQ_INFO)); + _ms_get_mms_objname (aCtx, &req_info->evenroll_name, repees_objname_done); + } + +/************************************************************************/ +/* repees_objname_done */ +/* Decoding report event enrollment status request: event enrollment */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID repees_objname_done (ASN1_DEC_CTXT *aCtx) + { + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_repees_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the report event enrollment status response */ +/************************************************************************/ + +ST_RET mp_repees_resp (MMSREQ_IND *indptr, REPEES_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_REP_EE_STAT,indptr, + M_CAST_MK_FUN (_ms_mk_repees_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_repees_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the report event enrollment status response. */ +/************************************************************************/ + +ST_RET mpl_repees_resp (ST_UINT32 invoke_id, REPEES_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_REP_EE_STAT,invoke_id, + M_CAST_MK_FUN (_ms_mk_repees_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_repees_resp */ +/* Construct a report event enrollment status response. */ +/************************************************************************/ + +ST_VOID _ms_mk_repees_resp (ASN1_ENC_CTXT *aCtx, REPEES_RESP_INFO *info) + { + asn1r_wr_i16 (aCtx, info->cur_state); /* write current state */ + asn1r_fin_prim (aCtx, 4, CTX); /* ctx tag 4 */ + + if (info->alarm_ack_rule_pres) + { + asn1r_wr_i16 (aCtx, info->alarm_ack_rule); /* write alarm ack rule */ + asn1r_fin_prim (aCtx, 3, CTX); /* ctx tag 3 */ + } + + asn1r_wr_i16 (aCtx, info->duration); /* write the duration */ + asn1r_fin_prim (aCtx, 2, CTX); /* ctx tag 2 */ + + if (info->not_lost) + { /* not the default */ + asn1r_wr_u8 (aCtx, info->not_lost); /* write notification lost */ + asn1r_fin_prim (aCtx, 1, CTX); /* ctx tag 1 */ + } + + asn1r_wr_bitstr (aCtx, &info->ec_transitions, 7); + asn1r_fin_prim (aCtx, 0, CTX); + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_REP_EE_STAT,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsl/rs_stat.c b/mmslib/mmsl/rs_stat.c new file mode 100644 index 0000000..33b0e67 --- /dev/null +++ b/mmslib/mmsl/rs_stat.c @@ -0,0 +1,120 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_stat.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the functions to decode a status request */ +/* and encode a status response message. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "asn1defs.h" + +/************************************************************************/ + +static STATUS_REQ_INFO *info; + + +/************************************************************************/ +/************************************************************************/ +/* mms_status_req */ +/* This function is called from mmsdec to decode a Status request PDU */ +/* after the PDU type has been determined. It sets up the parse of */ +/* the next data element and returns, letting the ASN.1 tools take over.*/ +/************************************************************************/ + +ST_VOID mms_status_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("decode status request"); + + info = (STATUS_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (STATUS_REQ_INFO)); + if (asn1r_get_bool (aCtx, &info -> extended)) /* Read extended flag. */ + { /* If error reading boolean, */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); /* stop parse, report error */ + return; /* and return. */ + } + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_status_resp */ +/* This function is called from the user to ENCODE and send the */ +/* Status response PDU. */ +/************************************************************************/ + +ST_RET mp_status_resp (MMSREQ_IND *indptr, STATUS_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_STATUS,indptr, + M_CAST_MK_FUN (_ms_mk_stat_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_status_resp */ +/* This function is called by the user to ENCODE the Status response */ +/* PDU. */ +/************************************************************************/ + +ST_RET mpl_status_resp (ST_UINT32 invoke_id, STATUS_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_STATUS,invoke_id, + M_CAST_MK_FUN (_ms_mk_stat_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_stat_req */ +/* ENCODE a Status RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_stat_resp (ASN1_ENC_CTXT *aCtx, STATUS_RESP_INFO *info_ptr) + { + if (info_ptr->local_detail_pres) /* if present, write the local */ + { /* detail parameter */ + asn1r_wr_bitstr (aCtx, info_ptr->local_detail,info_ptr->local_detail_len); + asn1r_fin_prim (aCtx, 2,CTX); + } + + asn1r_wr_i16 (aCtx, info_ptr->physical_stat); /* write the physical status */ + asn1r_fin_prim (aCtx, 1,CTX); + + asn1r_wr_i16 (aCtx, info_ptr->logical_stat); /* write the logical status */ + asn1r_fin_prim (aCtx, 0,CTX); + +/* Write the context-specific tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_STATUS,CTX,DEF); + } diff --git a/mmslib/mmsl/rs_trige.c b/mmslib/mmsl/rs_trige.c new file mode 100644 index 0000000..9bf3c74 --- /dev/null +++ b/mmslib/mmsl/rs_trige.c @@ -0,0 +1,151 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_trige.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of trigger event. */ +/* It decodes the trigger event request (indication) & encodes */ +/* the trigger event response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static TRIGE_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID trige_get_priority (ASN1_DEC_CTXT *aCtx); +static ST_VOID trige_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID trige_name_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID trige_name_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_trige_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_trige_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Trigger Event Request"); + req_info = (TRIGE_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (TRIGE_REQ_INFO)); + +/* req_info->priority_pres = SD_FALSE; set default values */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, trige_name_cstr); + } + +/************************************************************************/ +/* trige_name_cstr */ +/* trigger event request is being decoded: event condition name constr */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID trige_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("trige_name_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->evcon_name, trige_name_done); + } + +/************************************************************************/ +/* trige_name_done */ +/* trigger event request is being decoded: event condition name has */ +/* been obtained. */ +/************************************************************************/ + +static ST_VOID trige_name_done (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = trige_name_cstr_done; + } + +/************************************************************************/ +/* trige_name_cstr_done */ +/* trigger event request is being decoded: event condition name constr */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID trige_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("trige_name_done"); + + ASN1R_TAG_ADD (aCtx, CTX, 1, trige_get_priority); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* trige_get_priority */ +/* Decoding trigger event request: priority was encountered. */ +/************************************************************************/ + +static ST_VOID trige_get_priority (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("trige_get_priority"); + + req_info->priority_pres = SD_TRUE; + + if (asn1r_get_u8 (aCtx, &(req_info->priority))) /* read priority */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_trige_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the trigger event response. */ +/************************************************************************/ + +ST_RET mp_trige_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_TRIGGER_EV)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_trige_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the trigger event response. */ +/************************************************************************/ + +ST_RET mpl_trige_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_TRIGGER_EV)); + } +#endif diff --git a/mmslib/mmsl/rs_ustat.c b/mmslib/mmsl/rs_ustat.c new file mode 100644 index 0000000..3aed6b9 --- /dev/null +++ b/mmslib/mmsl/rs_ustat.c @@ -0,0 +1,47 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_ustat.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the functions to decode an Unsolicited */ +/* status request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 03 Remove "thisFileName" */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* Deleted mms_status proto (see mms_dfun.h) */ +/* 09/13/99 MDE 01 Added SD_CONST modifiers */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "asn1defs.h" + +/************************************************************************/ +/************************************************************************/ +/* mms_ustatus_req */ +/* This function is called from mmsdec to decode an UnsolicitedStatus */ +/* request PDU after the PDU type has been determined. It simply calls */ +/* mms_status in the module mmsstat.c. */ +/************************************************************************/ + +ST_VOID mms_ustatus_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("decode unsolicited status reques"); + mms_status (aCtx); + } diff --git a/mmslib/mmsl/rs_write.c b/mmslib/mmsl/rs_write.c new file mode 100644 index 0000000..8988cdb --- /dev/null +++ b/mmslib/mmsl/rs_write.c @@ -0,0 +1,248 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_write.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of variable write. */ +/* It decodes the variable write request (indication) & encodes */ +/* the variable write response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static WRITE_REQ_INFO *req_info; + +static VAR_ACC_DATA *data_ptr; +static ST_INT max_vars; +static ST_INT max_data_count; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID write_data_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID write_data_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID write_data_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID write_va_spec_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_write_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_write_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; +ST_INT req_size1; +ST_INT req_size2; + + MLOG_CDEC0 ("Variable Write Request"); + +#if defined(FIXED_DECBUF) + max_vars = m_sv_max_write_var_spec; + max_data_count = m_sv_max_write_data; + req_size = mmsl_dec_info_size; +#else + max_vars = _mmsdec_msglen / 7; + max_data_count = _mmsdec_msglen / 3; + + if (m_sv_max_write_var_spec && (max_vars > m_sv_max_write_var_spec)) + max_vars = m_sv_max_write_var_spec; + + if (m_sv_max_write_data && (max_data_count > m_sv_max_write_data)) + max_data_count = m_sv_max_write_data; + +/* Case of list of variables */ + req_size1 = (sizeof(VARIABLE_LIST) + sizeof(VAR_ACC_DATA)) * max_vars; + +/* Case of named variable list */ + req_size2 = sizeof (VAR_ACC_DATA) * max_data_count; + +/* Choose the largest */ + req_size = sizeof (WRITE_REQ_INFO) + max (req_size1, req_size2); +#endif + +/* get storage for request information */ + req_info = (WRITE_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + _ms_get_va_spec (aCtx, &req_info->va_spec, max_vars, write_va_spec_done); + } + +/************************************************************************/ +/* write_va_spec_done */ +/* decoding variable write request: variable access specification */ +/* has been decoded. */ +/************************************************************************/ + +static ST_VOID write_va_spec_done (ASN1_DEC_CTXT *aCtx) + { +VARIABLE_LIST *temp; + + MLOG_CDEC0 ("write_va_spec_done"); + + temp = (VARIABLE_LIST *) (req_info + 1); + temp += req_info->va_spec.num_of_variables; + + req_info->va_data = (VAR_ACC_DATA *) temp; + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, write_data_cstr); + } + +/************************************************************************/ +/* write_data_cstr */ +/* decoding variable write request: write data constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID write_data_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("write_data_cstr"); + + data_ptr = req_info->va_data; + + _ms_get_va_data (aCtx, data_ptr, write_data_done); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = write_data_cstr_done; + } + +/************************************************************************/ +/* write_data_done */ +/* decoding variable write request: write data has been decoded. */ +/************************************************************************/ + +static ST_VOID write_data_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("write_data_done"); + + req_info->num_of_data++; + if ((req_info->num_of_data + 1) <= max_data_count) + { + data_ptr++; + _ms_get_va_data (aCtx, data_ptr, write_data_done); + } + } + +/************************************************************************/ +/* write_data_cstr_done */ +/* decoding variable write request: write data constructor done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID write_data_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; +VARIABLE_LIST *temp; + + MLOG_CDEC0 ("write_data_cstr_done"); + /* find actual size for request info */ + req_size = sizeof (WRITE_REQ_INFO) + + (sizeof (VARIABLE_LIST)*req_info->va_spec.num_of_variables) + + (sizeof (VAR_ACC_DATA) *req_info->num_of_data); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (WRITE_REQ_INFO *) _mms_dec_info; + +/* some C run time library mem mgmt. functions will always give back a */ +/* new pointer when reallocating smaller. In the case of write_req_info */ +/* we have to update the va_data to point to this new mem loc */ + temp = (VARIABLE_LIST *) (req_info + 1); + temp += req_info->va_spec.num_of_variables; + + req_info->va_data = (VAR_ACC_DATA *) temp; + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_write_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the variable write response. */ +/************************************************************************/ + +ST_RET mp_write_resp (MMSREQ_IND *indptr, WRITE_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_WRITE,indptr, + M_CAST_MK_FUN (_ms_mk_write_resp), + (ST_CHAR *) info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_write_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the variable write response. */ +/************************************************************************/ + +ST_RET mpl_write_resp (ST_UINT32 invoke_id, WRITE_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_WRITE,invoke_id, + M_CAST_MK_FUN (_ms_mk_write_resp), + (ST_CHAR *) info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_write_resp */ +/* Construct a variable write response. */ +/************************************************************************/ + +ST_VOID _ms_mk_write_resp (ASN1_ENC_CTXT *aCtx, WRITE_RESP_INFO *info) + { +ST_INT i; +WRITE_RESULT *temp; /* index into array of structs */ + + temp = (WRITE_RESULT *) (info + 1); + temp += (info->num_of_result - 1); + for (i = info->num_of_result; i ; --i) + { + if (temp->resp_tag == SD_TRUE) + { /* success, null response */ + asn1r_fin_prim (aCtx, 1, CTX); /* finish context tag 1 prim */ + } + else + { /* failure, write failure code */ + asn1r_wr_i16 (aCtx, temp->failure); + asn1r_fin_prim (aCtx, 0, CTX); /* finish context tag 0 prim */ + } + temp--; + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_WRITE,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/mms_ced1.c b/mmslib/mmsle/mms_ced1.c new file mode 100644 index 0000000..f015b60 --- /dev/null +++ b/mmslib/mmsle/mms_ced1.c @@ -0,0 +1,448 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_ced1.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains common primitive encode/decode functions */ +/* particular to get and write journal service. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 04/28/00 JRB 03 Lint cleanup */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 08/15/97 MDE 01 BTOD handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pjou.h" +#include "asn1defs.h" + +/************************************************************************/ +/* global structures & functions */ +/************************************************************************/ + +static ENTRY_CONTENT *ent_cont_ptr; + +static ST_VOID (*get_jou_ent_cont_done) (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_get_data_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_get_annotation (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_list_of_var_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_vlist_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_vlist_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_vs_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_value_spec_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_get_var_tag (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_event_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_get_state (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_evcon_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_ecn_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_evcon_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_event_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_data_cstr_done (ASN1_DEC_CTXT *aCtx); +#ifdef CS_SUPPORT +static ST_VOID jec_addl_detail_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_addl_detail_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jec_get_addl_detail (ASN1_DEC_CTXT *aCtx); +#endif +static ST_VOID jec_get_occur_time (ASN1_DEC_CTXT *aCtx); + +static VAR_INFO *var_info_ptr; + +static ST_INT MAX_DATA_VARS; +static ST_RET ERROR_CODE; + + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_jou_ent_cont */ +/* Function to get a Journal Entry Content from the received message. */ +/************************************************************************/ + +ST_VOID _ms_get_jou_ent_cont (ASN1_DEC_CTXT *aCtx, ENTRY_CONTENT *data_ptr, + ST_INT max_vars, + ST_VOID (*done_fun) (ASN1_DEC_CTXT *aCtx)) + { + /* set decode error for request or response */ + if (_mmsdec_rslt->type == MMSRESP) + ERROR_CODE = RESP_BAD_VALUE; + else + ERROR_CODE = REQ_BAD_VALUE; + + ent_cont_ptr = data_ptr; + MAX_DATA_VARS = max_vars; + get_jou_ent_cont_done = done_fun; + + ent_cont_ptr->addl_detail_pres = SD_FALSE; /* set default values */ + ent_cont_ptr->entry_form_tag = 0; + ASN1R_TAG_ADD (aCtx, CTX, 0, jec_get_occur_time); + } + +/************************************************************************/ +/* jec_get_occur_time */ +/* journal entry content is being decoded: occurrence time was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jec_get_occur_time (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jec_get_occur_time"); + /* read time from message */ + if (asn1r_get_btod (aCtx, &ent_cont_ptr->occur_time)) + asn1r_set_dec_err (aCtx, ERROR_CODE); + +#ifdef CS_SUPPORT + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, jec_get_addl_detail); +#endif + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, jec_get_data_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 3, jec_get_annotation); + + /* set cstr done function */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = get_jou_ent_cont_done; + } + +#ifdef CS_SUPPORT +/************************************************************************/ +/* jec_get_addl_detail */ +/* journal entry content is being decoded: additional detail was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jec_get_addl_detail (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jec_get_addl_detail"); + + ent_cont_ptr->addl_detail_pres = SD_TRUE; /* set addl detail pres */ + + /* leave additional detail in place; just parse it. */ + ent_cont_ptr->addl_detail = aCtx->asn1r_field_ptr; + asn1r_parse_next (aCtx, jec_addl_detail_done); + } + +/************************************************************************/ +/* jec_addl_detail_done */ +/* journal entry content is being decoded: additional detail has been */ +/* parsed. */ +/************************************************************************/ + +static ST_VOID jec_addl_detail_done (ASN1_DEC_CTXT *aCtx) + { + + ent_cont_ptr->addl_detail_len = aCtx->asn1r_octetcount; /* save length */ + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jec_addl_detail_cstr_done; + } + +/************************************************************************/ +/* jec_addl_detail_cstr_done */ +/* journal entry content is being decoded: additional detail cstr done */ +/* has been encountered. */ +/************************************************************************/ + +static ST_VOID jec_addl_detail_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, jec_get_data_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 3, jec_get_annotation); + } +#endif + +/************************************************************************/ +/* jec_get_data_cstr */ +/* journal entry content is being decoded: data constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jec_get_data_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jec_get_data_cstr"); + + ent_cont_ptr->entry_form_tag = 2; /* set data form tag */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, jec_event_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, jec_list_of_var_cstr); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jec_data_cstr_done; + } + +/************************************************************************/ +/* jec_event_cstr */ +/* journal entry content is being decoded: event cstr was encountered. */ +/************************************************************************/ + +static ST_VOID jec_event_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jec_event_cstr"); + + ent_cont_ptr->ef.data.event_pres = SD_TRUE; /* set event present */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, jec_evcon_name_cstr); + } + +/************************************************************************/ +/* jec_evcon_name_cstr */ +/* journal entry content is being decoded: event condition name cstr */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jec_evcon_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jec_evcon_name_cstr"); + + _ms_get_mms_objname (aCtx, &ent_cont_ptr->ef.data.evcon_name, jec_ecn_done); + } + +/************************************************************************/ +/* jec_ecn_done */ +/* journal entry content is being decoded: event condition name has */ +/* been obtained. */ +/************************************************************************/ + +static ST_VOID jec_ecn_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jec_ecn_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jec_evcon_name_cstr_done; + } + +/************************************************************************/ +/* jec_evcon_name_cstr_done */ +/* journal entry content is being decoded: event condition name cstr */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID jec_evcon_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, jec_get_state); + } + +/************************************************************************/ +/* jec_get_state */ +/* journal entry content is being decoded: current state was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jec_get_state (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jec_get_state"); + /* read time from message */ + if (asn1r_get_i16 (aCtx, &ent_cont_ptr->ef.data.cur_state) || + (ent_cont_ptr->ef.data.cur_state < 0) || + (ent_cont_ptr->ef.data.cur_state > 2)) + asn1r_set_dec_err (aCtx, UNCONF_BAD_VALUE); + /* set cstr done function */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jec_event_cstr_done; + } + +/************************************************************************/ +/* jec_event_cstr_done */ +/* journal entry content is being decoded: event cstr done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jec_event_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, jec_list_of_var_cstr); + } + +/************************************************************************/ +/* jec_list_of_var_cstr */ +/* journal entry content is being decoded: list of variables cstr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jec_list_of_var_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jec_list_of_var_cstr"); + + ent_cont_ptr->ef.data.list_of_var_pres = SD_TRUE; + + ent_cont_ptr->ef.data.num_of_var = 0; /* initialize # of variables */ + /* initialize var list pointer*/ + var_info_ptr = (VAR_INFO *) (ent_cont_ptr + 1); + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, jec_vlist_cstr); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = NULL; + } + +/************************************************************************/ +/* jec_vlist_cstr */ +/* journal entry content is being decoded: variable list constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jec_vlist_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jec_vlist_cstr"); + + ent_cont_ptr->ef.data.num_of_var++; /* increment # of variables */ + if (ent_cont_ptr->ef.data.num_of_var > MAX_DATA_VARS) + asn1r_set_dec_err (aCtx, ERROR_CODE); + + ASN1R_TAG_ADD (aCtx, CTX, 0, jec_get_var_tag); + } + +/************************************************************************/ +/* jec_get_var_tag */ +/* journal entry content is being decoded: variable tag was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jec_get_var_tag (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jec_get_var_tag"); + + /* copy variable tag back onto itself shifted by 1 char */ + var_info_ptr->var_tag = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + + /* read variable tag from message */ + if (asn1r_get_vstr (aCtx, var_info_ptr->var_tag)) + asn1r_set_dec_err (aCtx, ERROR_CODE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, jec_value_spec_cstr); + } + +/************************************************************************/ +/* jec_value_spec_cstr */ +/* journal entry content is being decoded: value specification cstr */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jec_value_spec_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jec_value_spec_cstr"); + + _ms_get_va_data (aCtx, &var_info_ptr->value_spec, jec_vs_done); + } + +/************************************************************************/ +/* jec_vs_done */ +/* journal entry content is being decoded: value specification has been */ +/* obtained. */ +/************************************************************************/ + +static ST_VOID jec_vs_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jec_vs_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = NULL; + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level-1] = jec_vlist_cstr_done; + } + +/************************************************************************/ +/* jec_vlist_cstr_done */ +/* journal entry content is being decoded: variable list constructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID jec_vlist_cstr_done (ASN1_DEC_CTXT *aCtx) + { + var_info_ptr++; /* point to where next will go */ + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, jec_vlist_cstr); + } + +/************************************************************************/ +/* jec_data_cstr_done */ +/* journal entry content is being decoded: data constructor done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jec_data_cstr_done (ASN1_DEC_CTXT *aCtx) + { + } + +/************************************************************************/ +/* jec_get_annotation */ +/* journal entry content is being decoded: annotation was encountered. */ +/************************************************************************/ + +static ST_VOID jec_get_annotation (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jec_get_annotation"); + + /* copy annotation back onto itself shifted by 1 char */ + + ent_cont_ptr->entry_form_tag = 3; + ent_cont_ptr->ef.annotation = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + + if (asn1r_get_vstr (aCtx, ent_cont_ptr->ef.annotation)) /* read annotation */ + asn1r_set_dec_err (aCtx, ERROR_CODE); + } + + +/************************************************************************/ +/************************************************************************/ +/* _ms_wr_jou_ent_cont */ +/* Function to write a Journal Entry Content to the message. */ +/************************************************************************/ + +ST_VOID _ms_wr_jou_ent_cont (ASN1_ENC_CTXT *aCtx, ENTRY_CONTENT *data_ptr) + { +VAR_INFO *vi_ptr; +ST_INT i; + + if (data_ptr->entry_form_tag == 3) + { /* write annotation */ + asn1r_wr_vstr (aCtx, data_ptr->ef.annotation); + asn1r_fin_prim (aCtx, 3, CTX); /* context tag 3 */ + } + else + { + asn1r_strt_constr (aCtx); /* start context tag 2 cstr */ + if (data_ptr->ef.data.list_of_var_pres) + { + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + vi_ptr = (VAR_INFO *) (data_ptr + 1); + vi_ptr += data_ptr->ef.data.num_of_var - 1; + for (i = 0; i < data_ptr->ef.data.num_of_var; i++) + { + asn1r_strt_constr (aCtx); /* start universal sequece cstr */ + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + _ms_wr_va_data (aCtx, &vi_ptr->value_spec); + asn1r_fin_constr (aCtx, 1, CTX, DEF); /* finish context tag 1 cstr */ + asn1r_wr_vstr (aCtx, vi_ptr->var_tag); + asn1r_fin_prim (aCtx, 0, CTX); + asn1r_fin_constr (aCtx, SEQ_CODE, UNI, DEF); + vi_ptr--; /* point to previous var name */ + } + asn1r_fin_constr (aCtx, 1, CTX, DEF); /* finish context tag 1 cstr */ + } + if (data_ptr->ef.data.event_pres) + { + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + asn1r_wr_i16 (aCtx, data_ptr->ef.data.cur_state);/* write the current state */ + asn1r_fin_prim (aCtx, 1,CTX); /* context tag 1 */ + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + _ms_wr_mms_objname (aCtx, &data_ptr->ef.data.evcon_name); + asn1r_fin_constr (aCtx, 0, CTX, DEF); /* finish context tag 0 cstr */ + asn1r_fin_constr (aCtx, 0, CTX, DEF); /* finish context tag 0 cstr */ + } + asn1r_fin_constr (aCtx, 2, CTX, DEF); /* finish context tag 2 cstr */ + } + + if (data_ptr->addl_detail_pres) + { + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + asn1r_wr_delmnt (aCtx, data_ptr->addl_detail,data_ptr->addl_detail_len); + asn1r_fin_constr (aCtx, 1, CTX, DEF); /* context tag 1 */ + } + /* select short form if not present */ + asn1r_wr_btod (aCtx, &data_ptr->occur_time); + asn1r_fin_prim (aCtx, 0, CTX); /* context tag 0 */ + } diff --git a/mmslib/mmsle/mms_ced2.c b/mmslib/mmsle/mms_ced2.c new file mode 100644 index 0000000..c122451 --- /dev/null +++ b/mmslib/mmsle/mms_ced2.c @@ -0,0 +1,115 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mms_ced2.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains common primitive encode/decode functions */ +/* particular getting and writing filenames. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 03 Remove "thisFileName" */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 01 Added SD_CONST modifiers */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "asn1defs.h" + +/************************************************************************/ + +static ST_VOID fname_get_name (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/* global structures & functions */ +/************************************************************************/ + +static FILE_NAME *fname_ptr; + + +static ST_INT MAX_FNAMES; +static ST_INT *fname_count; +static ST_RET ERROR_CODE; + + +/************************************************************************/ +/************************************************************************/ +/* _ms_get_mms_fname */ +/************************************************************************/ + +ST_VOID _ms_get_mms_fname (ASN1_DEC_CTXT *aCtx, FILE_NAME *data_ptr, ST_INT ptr_len, + ST_INT *num_of_names_ptr) + { + MLOG_CDEC0 ("_ms_get_mms_fname"); + + if (_mmsdec_rslt->type == MMSRESP) + ERROR_CODE = RESP_BAD_VALUE; + else + ERROR_CODE = REQ_BAD_VALUE; + + fname_ptr = data_ptr; /* save the addr of the array */ + MAX_FNAMES = ptr_len; /* save the array upper bounds */ + fname_count = num_of_names_ptr; /* save the ptr to the count */ + ASN1R_TAG_ADD (aCtx, UNI, GRAFSTR_CODE, fname_get_name); + } + +/************************************************************************/ +/* fname_get_name */ +/************************************************************************/ + +static ST_VOID fname_get_name (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fname_get_name"); + + (*fname_count)++; /* increment # of file names */ + if (*fname_count > MAX_FNAMES) + { + asn1r_set_dec_err (aCtx, ERROR_CODE); + return; + } + /* save file name pointer & length */ + fname_ptr->fn_len = aCtx->asn1r_elmnt_len; + fname_ptr->fname = (ST_CHAR *) aCtx->asn1r_field_ptr; + asn1r_get_octstr (aCtx, (ST_UCHAR *) fname_ptr->fname); + + fname_ptr++; /* point to where next will go */ + + ASN1R_TAG_ADD (aCtx, UNI, GRAFSTR_CODE, fname_get_name); + } + + +/************************************************************************/ +/************************************************************************/ +/* _ms_wr_mms_fname */ +/* encode a list of file names. */ +/************************************************************************/ + +ST_VOID _ms_wr_mms_fname (ASN1_ENC_CTXT *aCtx, FILE_NAME *data_ptr, ST_INT len) + { +ST_INT i; +FILE_NAME *fn_ptr; + + fn_ptr = data_ptr; + fn_ptr += len - 1; /* point to last file name */ + for (i = 0; i < len; i++) + { + asn1r_wr_octstr (aCtx, (ST_UCHAR *) fn_ptr->fname,fn_ptr->fn_len);/* file name */ + asn1r_fin_prim (aCtx, GRAFSTR_CODE,UNI); /* universal grafstring */ + fn_ptr--; + } + } diff --git a/mmslib/mmsle/rq_altec.c b/mmslib/mmsle/rq_altec.c new file mode 100644 index 0000000..a064b74 --- /dev/null +++ b/mmslib/mmsle/rq_altec.c @@ -0,0 +1,124 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_altec.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of alter event */ +/* condition monitoring. It decodes the alter event condition */ +/* monitoring response (confirm) & encodes the alter event */ +/* condition monitoring request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_altecm_rsp */ +/* NOTE : Since the mms_altecm_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_altecm */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the alter event condition monitoring */ +/* request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_altecm (ST_INT chan, ALTECM_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_ALT_EC_MON, + M_CAST_MK_FUN (_ms_mk_altecm_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_altecm */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the alter event condition monitoring request. */ +/************************************************************************/ + +ST_RET mpl_altecm (ALTECM_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_ALT_EC_MON, + M_CAST_MK_FUN (_ms_mk_altecm_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_altecm_req */ +/* ENCODE a alter event condition monitoring REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_altecm_req (ASN1_ENC_CTXT *aCtx, ALTECM_REQ_INFO *info) + { + if (info->eval_int_pres) + { + asn1r_wr_u32 (aCtx, info->eval_int); /* write evaluation interval */ + asn1r_fin_prim (aCtx, 4, CTX); /* ctx tag 4 */ + } + + if (info->as_reports_pres) + { + asn1r_wr_bool (aCtx, info->as_reports); /* write alarm summary reports */ + asn1r_fin_prim (aCtx, 3, CTX); /* ctx tag 3 */ + } + + if (info->priority_pres) + { + asn1r_wr_u8 (aCtx, info->priority); /* write the priority */ + asn1r_fin_prim (aCtx, 2, CTX); /* ctx tag 2 */ + } + + if (info->enabled_pres) + { + asn1r_wr_bool (aCtx, info->enabled); /* write enabled */ + asn1r_fin_prim (aCtx, 1, CTX); /* ctx tag 1 */ + } + + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &info->evcon_name); /* write event cond mon name */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context specific tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_ALT_EC_MON,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_altee.c b/mmslib/mmsle/rq_altee.c new file mode 100644 index 0000000..c0d6e07 --- /dev/null +++ b/mmslib/mmsle/rq_altee.c @@ -0,0 +1,233 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_altee.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of alter event */ +/* enrollment. It decodes the alter event enrollment response */ +/* (confirm) & encodes the alter event enrollment request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static ALTEE_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID altee_cur_state_cstr (ASN1_DEC_CTXT *ac); +static ST_VOID altee_get_state (ASN1_DEC_CTXT *ac); +static ST_VOID altee_get_undef (ASN1_DEC_CTXT *ac); +static ST_VOID altee_cur_state_cstr_done (ASN1_DEC_CTXT *ac); +static ST_VOID altee_ttime_cstr (ASN1_DEC_CTXT *ac); +static ST_VOID altee_ttime_done (ASN1_DEC_CTXT *ac); +static ST_VOID altee_ttime_cstr_done (ASN1_DEC_CTXT *ac); + + +/************************************************************************/ +/************************************************************************/ +/* mms_altee_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_altee_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Alter Event Enrollment Response"); + +/* get storage for request information */ + rsp_info = (ALTEE_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (ALTEE_RESP_INFO)); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, altee_cur_state_cstr); + } + +/************************************************************************/ +/* altee_cur_state_cstr */ +/* Decoding alter event enrollment response: current state constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID altee_cur_state_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altee_cur_state_cstr"); + + ASN1R_TAG_ADD (aCtx, CTX, 0, altee_get_state); + ASN1R_TAG_ADD (aCtx, CTX, 1, altee_get_undef); + } + +/************************************************************************/ +/* altee_get_state */ +/* Decoding alter event enrollment request: state was encountered. */ +/************************************************************************/ + +static ST_VOID altee_get_state (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altee_get_state"); + + rsp_info->cur_state_tag = 0; /* set tag to state */ + + if (asn1r_get_i16 (aCtx, &(rsp_info->state))) + { /* read the state */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + else if ((rsp_info->state < 0) || (rsp_info->state > 7)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = altee_cur_state_cstr_done; + } + +/************************************************************************/ +/* altee_get_undef */ +/* Decoding alter event enrollment request: undefined was encountered. */ +/************************************************************************/ + +static ST_VOID altee_get_undef (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altee_get_undef"); + + rsp_info->cur_state_tag = 1; /* set tag to undefined */ + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = altee_cur_state_cstr_done; + } + +/************************************************************************/ +/* altee_cur_state_cstr_done */ +/* Decoding alter event enrollment response: current state constructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID altee_cur_state_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, altee_ttime_cstr); + } + +/************************************************************************/ +/* altee_ttime_cstr */ +/* Decoding alter event enrollment response: transition time constr */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID altee_ttime_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altee_ttime_cstr"); + + _ms_get_mms_evtime (aCtx, &rsp_info->trans_time, altee_ttime_done); + } + +/************************************************************************/ +/* altee_ttime_done */ +/* Decoding alter event enrollment response: transition time has been */ +/* obtained. */ +/************************************************************************/ + +static ST_VOID altee_ttime_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altee_ttime_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = altee_ttime_cstr_done; + } + +/************************************************************************/ +/* altee_ttime_cstr_done */ +/* Decoding alter event enrollment response: transition time constr */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID altee_ttime_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_altee */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the alter event enrollment request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_altee (ST_INT chan, ALTEE_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_ALT_EE, + M_CAST_MK_FUN (_ms_mk_altee_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_altee */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the alter event enrollment request. */ +/************************************************************************/ + +ST_RET mpl_altee (ALTEE_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_ALT_EE, + M_CAST_MK_FUN (_ms_mk_altee_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_altee_req */ +/* ENCODE a alter event enrollment REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_altee_req (ASN1_ENC_CTXT *aCtx, ALTEE_REQ_INFO *info) + { + if (info->alarm_ack_rule_pres) + { + asn1r_wr_i16 (aCtx, info->alarm_ack_rule); + asn1r_fin_prim (aCtx, 2, CTX); + } + + if (info->ec_transitions_pres) + { + asn1r_wr_bitstr (aCtx, &info->ec_transitions, 7); + asn1r_fin_prim (aCtx, 1, CTX); + } + + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &info->evenroll_name);/* write event enrollment name */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context specific tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_ALT_EE,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_crepi.c b/mmslib/mmsle/rq_crepi.c new file mode 100644 index 0000000..9fb7c51 --- /dev/null +++ b/mmslib/mmsle/rq_crepi.c @@ -0,0 +1,122 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_crepi.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of create program */ +/* invocation. It decodes the create program invocation response */ +/* (confirm) & encodes the create program invocation request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_create_pi_rsp */ +/* NOTE: Since the mms_create_pi_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode */ +/* done fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_crepi */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the create program invocation request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_crepi (ST_INT chan, CREPI_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_CREATE_PI, + M_CAST_MK_FUN (_ms_mk_crepi_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_crepi */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the create program invocation request. */ +/************************************************************************/ + +ST_RET mpl_crepi (CREPI_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_CREATE_PI, + M_CAST_MK_FUN (_ms_mk_crepi_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_crepi_req */ +/* construct a create program invocation request */ +/************************************************************************/ + +ST_VOID _ms_mk_crepi_req (ASN1_ENC_CTXT *aCtx, CREPI_REQ_INFO *info) + { +ST_INT i; +ST_CHAR **dom_ptr; + + if (info->monitor_pres) + { + asn1r_wr_bool (aCtx, info->monitor); /* write the monitor flag */ + asn1r_fin_prim (aCtx, 3,CTX); /* ctx tag 3 */ + } + + if (!info->reusable) /* SD_TRUE is default */ + { + asn1r_wr_bool (aCtx, info->reusable); /* write the re-usable flag */ + asn1r_fin_prim (aCtx, 2,CTX); /* ctx tag 2 */ + } + /* Write list of Domain Names */ + asn1r_strt_constr (aCtx); /* start ctx tag 1 constructor */ + dom_ptr = (ST_CHAR **) (info + 1); + dom_ptr += (info->num_of_dnames - 1); /* point to last domain name */ + for (i = 0; i < info->num_of_dnames; i++) + { + asn1r_wr_vstr (aCtx, *dom_ptr); + asn1r_fin_prim (aCtx, VISTR_CODE, UNI); + dom_ptr--; + } + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* ctx tag 1 constructor */ + + asn1r_wr_vstr (aCtx, info->piname); /* write pgm invocation name */ + asn1r_fin_prim (aCtx, 0,CTX); /* ctx tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_CREATE_PI,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_defea.c b/mmslib/mmsle/rq_defea.c new file mode 100644 index 0000000..30f5e45 --- /dev/null +++ b/mmslib/mmsle/rq_defea.c @@ -0,0 +1,125 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_defea.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of define event */ +/* action. It decodes the define event action response (confirm) */ +/* & encodes the define event action request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_defea_rsp */ +/* NOTE : Since the mms_defea_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_defea */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the define event action request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_defea (ST_INT chan, DEFEA_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DEF_EA, + M_CAST_MK_FUN (_ms_mk_defea_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_defea */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the define event action request. */ +/************************************************************************/ + +ST_RET mpl_defea (DEFEA_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DEF_EA, + M_CAST_MK_FUN (_ms_mk_defea_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_defea_req */ +/* ENCODE a define event action REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_defea_req (ASN1_ENC_CTXT *aCtx, DEFEA_REQ_INFO *info) + { +#ifdef MOD_SUPPORT +MODIFIER *mod_ptr; +#endif + +#ifdef CS_SUPPORT /* if companion standards are supported */ + if (info->cs_rdetail_pres) /* check for CS request detail */ + { + asn1r_strt_constr (aCtx); /* start ctx tag 79 constructor */ + asn1r_wr_delmnt (aCtx, info->cs_rdetail, info->cs_rdetail_len); + asn1r_fin_constr (aCtx, 79, CTX, DEF); /* CS is cstr 79 */ + } +#endif + + asn1r_strt_constr (aCtx); /* start ctx tag 2 constructor */ + asn1r_wr_delmnt (aCtx, info->conf_serv_req,info->conf_serv_req_len); + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* finish ctx tag 2 constructor */ + +#ifdef MOD_SUPPORT + if (info->modlist_pres) + { + mod_ptr = (MODIFIER *) (info + 1); + asn1r_strt_constr (aCtx); /* start ctx tag 1 constructor */ + _ms_wr_mms_modlist (aCtx, mod_ptr, info->num_of_modifiers); + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish ctx tag 1 constructor */ + } +#endif + + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &info->evact_name); /* write event action name */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context specific tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEF_EA,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_defec.c b/mmslib/mmsle/rq_defec.c new file mode 100644 index 0000000..3e125cd --- /dev/null +++ b/mmslib/mmsle/rq_defec.c @@ -0,0 +1,131 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_defec.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of define event */ +/* condition. It decodes the define event condition response */ +/* (confirm) & encodes the define event condition request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_defec_rsp */ +/* NOTE : Since the mms_defec_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_defec */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the define event condition request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_defec (ST_INT chan, DEFEC_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DEF_EC, + M_CAST_MK_FUN (_ms_mk_defec_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_defec */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the define event condition request. */ +/************************************************************************/ + +ST_RET mpl_defec (DEFEC_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DEF_EC, + M_CAST_MK_FUN (_ms_mk_defec_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_defec_req */ +/* ENCODE a define event condition REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_defec_req (ASN1_ENC_CTXT *aCtx, DEFEC_REQ_INFO *info) + { + if (info->eval_int_pres) + { + asn1r_wr_u32 (aCtx, info->eval_interval); /* write evaluation interval */ + asn1r_fin_prim (aCtx, 7, CTX); /* ctx tag 7 */ + } + + if (info->mon_var_pres) + { /* write variable specification */ + asn1r_strt_constr (aCtx); /* start ctx tag 6 constructor */ + _ms_wr_va_var_spec (aCtx, &info->var_ref); + asn1r_fin_constr (aCtx, 6, CTX, DEF); /* finish ctx tag 6 */ + } + + if (info->as_reports_pres) + { + asn1r_wr_bool (aCtx, info->as_reports); /* write alarm summary reports */ + asn1r_fin_prim (aCtx, 4, CTX); /* ctx tag 4 */ + } + + if (info->severity != MMS_NORM_SEVERITY) + { /* not the default */ + asn1r_wr_u8 (aCtx, info->severity); + asn1r_fin_prim (aCtx, 3, CTX); + } + + if (info->priority != MMS_NORM_PRIORITY) + { /* not the default */ + asn1r_wr_u8 (aCtx, info->priority); + asn1r_fin_prim (aCtx, 2, CTX); + } + + asn1r_wr_i16 (aCtx, info->eclass); + asn1r_fin_prim (aCtx, 1, CTX); + + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &info->evcon_name); /* write event condition name */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context specific tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEF_EC,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_defsc.c b/mmslib/mmsle/rq_defsc.c new file mode 100644 index 0000000..4360abc --- /dev/null +++ b/mmslib/mmsle/rq_defsc.c @@ -0,0 +1,100 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_defscat.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of define scattered */ +/* access. It decodes the define scattered access response */ +/* (confirm) & encodes the define scattered access request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_def_scat_rsp */ +/* NOTE : Since the mms_def_scat_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_defscat */ +/* Create and send a define scattered access request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_defscat (ST_INT chan, DEFSCAT_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DEF_SCAT, + M_CAST_MK_FUN (_ms_mk_defscat_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_defscat */ +/* Create a define scattered access request. */ +/************************************************************************/ + +ST_RET mpl_defscat (DEFSCAT_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DEF_SCAT, + M_CAST_MK_FUN (_ms_mk_defscat_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_defscat_req */ +/* construct a define scattered access request */ +/************************************************************************/ + +ST_VOID _ms_mk_defscat_req (ASN1_ENC_CTXT *aCtx, DEFSCAT_REQ_INFO *info_ptr) + { + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + _ms_wr_va_scat_access (aCtx, &info_ptr->sa_descr); + asn1r_fin_constr (aCtx, 1, CTX, DEF); /* finish context tag 1 cstr */ + + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + _ms_wr_mms_objname (aCtx, &info_ptr->sa_name); + asn1r_fin_constr (aCtx, 0, CTX, DEF); /* finish context tag 0 cstr */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEF_SCAT,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_defse.c b/mmslib/mmsle/rq_defse.c new file mode 100644 index 0000000..2c64429 --- /dev/null +++ b/mmslib/mmsle/rq_defse.c @@ -0,0 +1,104 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_defsem.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the define */ +/* semaphore. It decodes the define semaphore response (confirm) */ +/* and encodes the define semaphore request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_psem.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_defsem_rsp */ +/* NOTE : Since the mms_defsem_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_defsem */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the define semaphore request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_defsem (ST_INT chan, DEFSEM_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DEFINE_SEM, + M_CAST_MK_FUN (_ms_mk_defsem_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_defsem */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the define semaphore request. */ +/************************************************************************/ + +ST_RET mpl_defsem (DEFSEM_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DEFINE_SEM, + M_CAST_MK_FUN (_ms_mk_defsem_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_defsem_req */ +/* construct a define semaphore request */ +/************************************************************************/ + +ST_VOID _ms_mk_defsem_req (ASN1_ENC_CTXT *aCtx, DEFSEM_REQ_INFO *info) + { + asn1r_strt_constr (aCtx); /* start sequence constr */ + + asn1r_wr_u16 (aCtx, info->num_of_tokens); /* write number of named tokens */ + asn1r_fin_prim (aCtx, 1, CTX); /* context tag 1 */ + + asn1r_strt_constr (aCtx); /* object name constructor */ + + _ms_wr_mms_objname (aCtx, &info->sem_name); /* write the object name */ + + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEFINE_SEM,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_defty.c b/mmslib/mmsle/rq_defty.c new file mode 100644 index 0000000..b2a8d72 --- /dev/null +++ b/mmslib/mmsle/rq_defty.c @@ -0,0 +1,96 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_deftype.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of define named */ +/* type. It decodes the define named type response (confirm) & */ +/* encodes the define named type request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_def_type_rsp */ +/* NOTE : Since the mms_def_type_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_deftype */ +/* Create and send a define named type request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_deftype (ST_INT chan, DEFTYPE_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DEF_TYPE, + M_CAST_MK_FUN (_ms_mk_deftype_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_deftype */ +/* Create a define named type request. */ +/************************************************************************/ + +ST_RET mpl_deftype (DEFTYPE_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DEF_TYPE, + M_CAST_MK_FUN (_ms_mk_deftype_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_deftype_req */ +/* construct a define type definition request */ +/************************************************************************/ + +ST_VOID _ms_mk_deftype_req (ASN1_ENC_CTXT *aCtx, DEFTYPE_REQ_INFO *info_ptr) + { + _ms_wr_va_type_spec (aCtx, &info_ptr->type_spec); + + _ms_wr_mms_objname (aCtx, &info_ptr->type_name); + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEF_TYPE,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_defva.c b/mmslib/mmsle/rq_defva.c new file mode 100644 index 0000000..fc6faaa --- /dev/null +++ b/mmslib/mmsle/rq_defva.c @@ -0,0 +1,100 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_defvar.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of define named */ +/* variable. It decodes the define named variable response */ +/* (confirm) & encodes the define named variable request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* ST_VOID mms_def_var_rsp () */ +/* MMSREQ_PEND *mp_defvar (chan,info_ptr) */ +/* ST_INT16 mpl_defvar (info_ptr) - MMSEASE-LITE */ +/* ST_VOID _ms_mk_defvar_req (info) */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_defvar */ +/* Create and send a define named variable request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_defvar (ST_INT chan, DEFVAR_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DEF_VAR, + M_CAST_MK_FUN (_ms_mk_defvar_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_defvar */ +/* Create a define named variable request. */ +/************************************************************************/ + +ST_RET mpl_defvar (DEFVAR_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DEF_VAR, + M_CAST_MK_FUN (_ms_mk_defvar_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_defvar_req */ +/* construct a define named variable request */ +/************************************************************************/ + +ST_VOID _ms_mk_defvar_req (ASN1_ENC_CTXT *aCtx, DEFVAR_REQ_INFO *info_ptr) + { + if (info_ptr->type_spec_pres) + { + asn1r_strt_constr (aCtx); /* start context tag 2 cstr */ + _ms_wr_va_type_spec (aCtx, &info_ptr->type_spec); + asn1r_fin_constr (aCtx, 2, CTX, DEF); /* finish context tag 2 cstr */ + } + + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + _ms_wr_va_address (aCtx, &info_ptr->address); + asn1r_fin_constr (aCtx, 1, CTX, DEF); /* finish context tag 1 cstr */ + + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + _ms_wr_mms_objname (aCtx, &info_ptr->name); + asn1r_fin_constr (aCtx, 0, CTX, DEF); /* finish context tag 0 cstr */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEF_VAR,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_defvl.c b/mmslib/mmsle/rq_defvl.c new file mode 100644 index 0000000..f7f67dd --- /dev/null +++ b/mmslib/mmsle/rq_defvl.c @@ -0,0 +1,106 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_defvlist.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the define named */ +/* variable list. It decodes the get named variable list */ +/* response (confirm) & encodes the get named variable list */ +/* request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_def_vlist_rsp */ +/* NOTE : Since the mms_def_vlist_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_defvlist */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the define named variable list request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_defvlist (ST_INT chan, DEFVLIST_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DEF_VLIST, + M_CAST_MK_FUN (_ms_mk_defvlist_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_defvlist */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the define named variable list request. */ +/************************************************************************/ + +ST_RET mpl_defvlist (DEFVLIST_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DEF_VLIST, + M_CAST_MK_FUN (_ms_mk_defvlist_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_defvlist_req */ +/* construct a define named variable list request */ +/************************************************************************/ + +ST_VOID _ms_mk_defvlist_req (ASN1_ENC_CTXT *aCtx, DEFVLIST_REQ_INFO *info) + { +VARIABLE_LIST *vl_ptr; + + /* get ptr to list of variables */ + vl_ptr = (VARIABLE_LIST *) (info + 1); + + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + _ms_wr_va_var_list (aCtx, vl_ptr, info->num_of_variables); + asn1r_fin_constr (aCtx, 0, CTX, DEF); /* finish context tag 0 cstr */ + + _ms_wr_mms_objname (aCtx, &info->vl_name); /* write the variable list name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEF_VLIST,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsle/rq_deldo.c b/mmslib/mmsle/rq_deldo.c new file mode 100644 index 0000000..3f0beb3 --- /dev/null +++ b/mmslib/mmsle/rq_deldo.c @@ -0,0 +1,93 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_deldom.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of delete domain. */ +/* It decodes the delete domain response (confirm) & encodes the */ +/* delete domain request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_delete_domain_rsp */ +/* NOTE : Since the mms_delete_domain_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_deldom */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the delete domain request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_deldom (ST_INT chan, DELDOM_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DELETE_DOMAIN, + M_CAST_MK_FUN (_ms_mk_deldom_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_deldom */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the delete domain request. */ +/************************************************************************/ + +ST_RET mpl_deldom (DELDOM_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DELETE_DOMAIN, + M_CAST_MK_FUN (_ms_mk_deldom_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_deldom_req */ +/* construct a delete domain request */ +/************************************************************************/ + +ST_VOID _ms_mk_deldom_req (ASN1_ENC_CTXT *aCtx, DELDOM_REQ_INFO *info) + { + asn1r_wr_vstr (aCtx, info->dname); /* write the domain name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_DELETE_DOMAIN,CTX); /* tag = opcode, ctx prim */ + } diff --git a/mmslib/mmsle/rq_delea.c b/mmslib/mmsle/rq_delea.c new file mode 100644 index 0000000..15fe71a --- /dev/null +++ b/mmslib/mmsle/rq_delea.c @@ -0,0 +1,141 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_delea.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of delete event */ +/* action. It decodes the delete event action response (confirm) */ +/* & encodes the delete event action request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DELEA_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_delea_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_delea_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Decoding : Delete Event Action Response"); + +/* get storage for request information */ + rsp_info = (DELEA_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (DELEA_RESP_INFO)); + if (asn1r_get_u32 (aCtx, &rsp_info->cand_not_deleted)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_delea */ +/* Create and send a delete event action request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_delea (ST_INT chan, DELEA_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DEL_EA, + M_CAST_MK_FUN (_ms_mk_delea_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_delea */ +/* Create a delete event action request. */ +/************************************************************************/ + +ST_RET mpl_delea (DELEA_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DEL_EA, + M_CAST_MK_FUN (_ms_mk_delea_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_delea_req */ +/* construct a delete event action request */ +/************************************************************************/ + +ST_VOID _ms_mk_delea_req (ASN1_ENC_CTXT *aCtx, DELEA_REQ_INFO *info_ptr) + { +ST_INT i; +OBJECT_NAME *obj_ptr; + + switch (info_ptr->req_tag) + { + case 4 : + asn1r_fin_prim (aCtx, 4, CTX); /* ctx tag 4, vmd is null */ + break; + + case 3 : + asn1r_wr_vstr (aCtx, info_ptr->dname); /* write the domain name */ + asn1r_fin_prim (aCtx, 3,CTX); /* context tag 3 */ + break; + + case 1 : + asn1r_fin_prim (aCtx, 1, CTX); /* ctx tag 1, aa spec is null */ + break; + + case 0 : + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + obj_ptr = (OBJECT_NAME *) (info_ptr + 1); + obj_ptr +=info_ptr->num_of_names-1;/* point to last object name */ + for (i = 0; i < info_ptr->num_of_names; i++) + { + _ms_wr_mms_objname (aCtx, obj_ptr); + obj_ptr--; + } + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish context tag 0 cstr */ + break; + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEL_EA,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_delec.c b/mmslib/mmsle/rq_delec.c new file mode 100644 index 0000000..d3ad1df --- /dev/null +++ b/mmslib/mmsle/rq_delec.c @@ -0,0 +1,142 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_delec.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of delete event */ +/* condition. It decodes the delete event condition response */ +/* (confirm) & encodes the delete event condition request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DELEC_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_delec_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_delec_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Decoding : Delete Event Condition Response"); + +/* get storage for request information */ + rsp_info = (DELEC_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (DELEC_RESP_INFO)); + + if (asn1r_get_u32 (aCtx, &rsp_info->cand_not_deleted)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_delec */ +/* Create and send a delete event condition request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_delec (ST_INT chan, DELEC_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DEL_EC, + M_CAST_MK_FUN (_ms_mk_delec_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_delec */ +/* Create a delete event condition request. */ +/************************************************************************/ + +ST_RET mpl_delec (DELEC_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DEL_EC, + M_CAST_MK_FUN (_ms_mk_delec_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_delec_req */ +/* construct a delete event condition request */ +/************************************************************************/ + +ST_VOID _ms_mk_delec_req (ASN1_ENC_CTXT *aCtx, DELEC_REQ_INFO *info_ptr) + { +ST_INT i; +OBJECT_NAME *obj_ptr; + + switch (info_ptr->req_tag) + { + case 3 : + asn1r_fin_prim (aCtx, 3, CTX); /* ctx tag 3, vmd is null */ + break; + + case 2 : + asn1r_wr_vstr (aCtx, info_ptr->dname); /* write the domain name */ + asn1r_fin_prim (aCtx, 2,CTX); /* context tag 2 */ + break; + + case 1 : + asn1r_fin_prim (aCtx, 1, CTX); /* ctx tag 1, aa spec is null */ + break; + + case 0 : + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + obj_ptr = (OBJECT_NAME *) (info_ptr + 1); + obj_ptr +=info_ptr->num_of_names-1;/* point to last object name */ + for (i = 0; i < info_ptr->num_of_names; i++) + { + _ms_wr_mms_objname (aCtx, obj_ptr); + obj_ptr--; + } + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish context tag 0 cstr */ + break; + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEL_EC,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_delee.c b/mmslib/mmsle/rq_delee.c new file mode 100644 index 0000000..1802694 --- /dev/null +++ b/mmslib/mmsle/rq_delee.c @@ -0,0 +1,141 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_delee.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of delete event */ +/* enrollment. It decodes the delete event enrollment response */ +/* (confirm) & encodes the delete event enrollment request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DELEE_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_delee_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_delee_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Delete Event Enrollment Response"); + +/* get storage for request information */ + rsp_info = (DELEE_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (DELEE_RESP_INFO)); + if (asn1r_get_u32 (aCtx, &rsp_info->cand_not_deleted)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_delee */ +/* Create and send a delete event enrollment request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_delee (ST_INT chan, DELEE_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DEL_EE, + M_CAST_MK_FUN (_ms_mk_delee_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_delee */ +/* Create a delete event enrollment request. */ +/************************************************************************/ + +ST_RET mpl_delee (DELEE_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DEL_EE, + M_CAST_MK_FUN (_ms_mk_delee_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_delee_req */ +/* construct a delete event enrollment request */ +/************************************************************************/ + +ST_VOID _ms_mk_delee_req (ASN1_ENC_CTXT *aCtx, DELEE_REQ_INFO *info_ptr) + { +ST_INT i; +OBJECT_NAME *obj_ptr; + + switch (info_ptr->req_tag) + { + case 2 : /* event action */ + asn1r_strt_constr (aCtx); /* start context tag 2 cstr */ + _ms_wr_mms_objname (aCtx, &info_ptr->sod.evact_name); + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* finish context tag 2 cstr */ + break; + + case 1 : /* event condition */ + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + _ms_wr_mms_objname (aCtx, &info_ptr->sod.evcon_name); + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish context tag 1 cstr */ + break; + + case 0 : /* specific */ + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + obj_ptr = (OBJECT_NAME *) (info_ptr + 1); + /* point to last object name */ + obj_ptr +=info_ptr->sod.num_of_names-1; + for (i = 0; i < info_ptr->sod.num_of_names; i++) + { + _ms_wr_mms_objname (aCtx, obj_ptr); + obj_ptr--; + } + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish context tag 0 cstr */ + break; + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEL_EE,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_delpi.c b/mmslib/mmsle/rq_delpi.c new file mode 100644 index 0000000..146febb --- /dev/null +++ b/mmslib/mmsle/rq_delpi.c @@ -0,0 +1,96 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_delpi.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of delete program */ +/* invocation. It decodes the delete program invocation response */ +/* (confirm) & encodes the delete program invocation request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_delete_pi_rsp */ +/* NOTE: Since the mms_delete_pi_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode */ +/* done fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_delpi */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the delete program invocation request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_delpi (ST_INT chan, DELPI_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DELETE_PI, + M_CAST_MK_FUN (_ms_mk_delpi_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_delpi */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the delete program invocation request. */ +/************************************************************************/ + +ST_RET mpl_delpi (DELPI_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DELETE_PI, + M_CAST_MK_FUN (_ms_mk_delpi_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_delpi_req */ +/* construct a delete program invocation request */ +/************************************************************************/ + +ST_VOID _ms_mk_delpi_req (ASN1_ENC_CTXT *aCtx, DELPI_REQ_INFO *info) + { + + asn1r_wr_vstr (aCtx, info->piname); /* write pgm invocation name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_DELETE_PI,CTX); /* tag = opcode, ctx prim */ + } diff --git a/mmslib/mmsle/rq_delse.c b/mmslib/mmsle/rq_delse.c new file mode 100644 index 0000000..888a5ab --- /dev/null +++ b/mmslib/mmsle/rq_delse.c @@ -0,0 +1,97 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_delsem.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the delete */ +/* semaphore. It decodes the file delete semaphore response */ +/* (confirm) and encodes the delete semaphore request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_psem.h" +#include "asn1defs.h" + + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_delsem_rsp */ +/* NOTE : Since the mms_delsem_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_delsem */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the delete semaphore request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_delsem (ST_INT chan, DELSEM_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DELETE_SEM, + M_CAST_MK_FUN (_ms_mk_delsem_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_delsem */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the delete semaphore request. */ +/************************************************************************/ + +ST_RET mpl_delsem (DELSEM_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DELETE_SEM, + M_CAST_MK_FUN (_ms_mk_delsem_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_delsem_req */ +/* construct a delete semaphore request */ +/************************************************************************/ + +ST_VOID _ms_mk_delsem_req (ASN1_ENC_CTXT *aCtx, DELSEM_REQ_INFO *info) + { + + _ms_wr_mms_objname (aCtx, &info->sem_name); /* write the object name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DELETE_SEM,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_delty.c b/mmslib/mmsle/rq_delty.c new file mode 100644 index 0000000..954f55b --- /dev/null +++ b/mmslib/mmsle/rq_delty.c @@ -0,0 +1,169 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_deltype.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of delete named */ +/* type. It decodes the delete named type response (confirm) & */ +/* encodes the delete named type request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DELTYPE_RESP_INFO *rsp_info; + + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID deltyp_num_matched (ASN1_DEC_CTXT *aCtx); +static ST_VOID deltyp_num_deleted (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_del_type_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_del_type_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Delete Type Response"); + +/* get storage for request information */ + rsp_info = (DELTYPE_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (DELTYPE_RESP_INFO)); + ASN1R_TAG_ADD (aCtx, CTX, 0, deltyp_num_matched); + } + +/************************************************************************/ +/* deltyp_num_matched */ +/* number matched element encountered, read into info structure. */ +/************************************************************************/ + +static ST_VOID deltyp_num_matched (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("deltyp_num_matched"); + + if (asn1r_get_u32 (aCtx, &rsp_info->num_matched)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + ASN1R_TAG_ADD (aCtx, CTX, 1, deltyp_num_deleted); + } + +/************************************************************************/ +/* deltyp_num_deleted */ +/* number deleted element encountered, read into info structure. */ +/************************************************************************/ + +static ST_VOID deltyp_num_deleted (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("deltyp_num_delete"); + + if (asn1r_get_u32 (aCtx, &rsp_info->num_deleted)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_deltype */ +/* Create and send a delete named type request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_deltype (ST_INT chan, DELTYPE_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DEL_TYPE, + M_CAST_MK_FUN (_ms_mk_deltype_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_deltype */ +/* Create and send a delete named type request. */ +/************************************************************************/ + +ST_RET mpl_deltype (DELTYPE_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DEL_TYPE, + M_CAST_MK_FUN (_ms_mk_deltype_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_deltype_req */ +/* construct a delete type definition request */ +/************************************************************************/ + +ST_VOID _ms_mk_deltype_req (ASN1_ENC_CTXT *aCtx, DELTYPE_REQ_INFO *info_ptr) + { +ST_INT i; +OBJECT_NAME *obj_ptr; + + if (info_ptr->dname_pres) + { + asn1r_wr_vstr (aCtx, info_ptr->dname); /* write the domain name */ + asn1r_fin_prim (aCtx, 2,CTX); /* context tag 2 */ + } + + if (info_ptr->tnames_pres) + { + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + obj_ptr = (OBJECT_NAME *) (info_ptr + 1); + obj_ptr +=info_ptr->num_of_tnames-1;/* point to last type name */ + for (i = 0; i < info_ptr->num_of_tnames; i++) + { + _ms_wr_mms_objname (aCtx, obj_ptr); + obj_ptr--; + } + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish context tag 1 cstr */ + } + + if (info_ptr->scope != 0) /* default is 0-specific */ + { /* not the default, so */ + asn1r_wr_i16 (aCtx, info_ptr->scope); /* write the scope of delete */ + asn1r_fin_prim (aCtx, 0,CTX); /* context tag 0 */ + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEL_TYPE,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_delva.c b/mmslib/mmsle/rq_delva.c new file mode 100644 index 0000000..be56894 --- /dev/null +++ b/mmslib/mmsle/rq_delva.c @@ -0,0 +1,168 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_delvar.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of delete variable */ +/* access. It decodes the delete variable access response */ +/* (confirm) & encodes the delete variable access request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DELVAR_RESP_INFO *rsp_info; + +static ST_VOID delvar_num_matched (ASN1_DEC_CTXT *aCtx); +static ST_VOID delvar_num_deleted (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_del_var_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_del_var_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Delete Variable Access Response"); + +/* get storage for request information */ + rsp_info = (DELVAR_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (DELVAR_RESP_INFO)); + ASN1R_TAG_ADD (aCtx, CTX, 0, delvar_num_matched); + } + +/************************************************************************/ +/* delvar_num_matched */ +/* number matched element encountered, read into info structure. */ +/************************************************************************/ + +static ST_VOID delvar_num_matched (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delvar_num_matched"); + + if (asn1r_get_u32 (aCtx, &rsp_info->num_matched)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + ASN1R_TAG_ADD (aCtx, CTX, 1, delvar_num_deleted); + } + +/************************************************************************/ +/* delvar_num_deleted */ +/* number deleted element encountered, read into info structure. */ +/************************************************************************/ + +static ST_VOID delvar_num_deleted (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delvar_num_deleted"); + + if (asn1r_get_u32 (aCtx, &rsp_info->num_deleted)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_delvar */ +/* Create and send a delete named variable request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_delvar (ST_INT chan, DELVAR_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DEL_VAR, + M_CAST_MK_FUN (_ms_mk_delvar_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_delvar */ +/* Create and send a delete named variable request. */ +/************************************************************************/ + +ST_RET mpl_delvar (DELVAR_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DEL_VAR, + M_CAST_MK_FUN (_ms_mk_delvar_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_delvar_req */ +/* construct a delete variable access request */ +/************************************************************************/ + +ST_VOID _ms_mk_delvar_req (ASN1_ENC_CTXT *aCtx, DELVAR_REQ_INFO *info_ptr) + { +ST_INT i; +OBJECT_NAME *obj_ptr; + + if (info_ptr->dname_pres) + { + asn1r_wr_vstr (aCtx, info_ptr->dname); /* write the domain name */ + asn1r_fin_prim (aCtx, 2,CTX); /* context tag 2 */ + } + + if (info_ptr->vnames_pres) + { + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + obj_ptr = (OBJECT_NAME *) (info_ptr + 1); + obj_ptr +=info_ptr->num_of_vnames-1;/* point to last variable name */ + for (i = 0; i < info_ptr->num_of_vnames; i++) + { + _ms_wr_mms_objname (aCtx, obj_ptr); + obj_ptr--; + } + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish context tag 1 cstr */ + } + + if (info_ptr->scope != 0) /* default is 0-specific */ + { /* not the default, so */ + asn1r_wr_i16 (aCtx, info_ptr->scope); /* write the scope of delete */ + asn1r_fin_prim (aCtx, 0,CTX); /* context tag 0 */ + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEL_VAR,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_delvl.c b/mmslib/mmsle/rq_delvl.c new file mode 100644 index 0000000..3be8a53 --- /dev/null +++ b/mmslib/mmsle/rq_delvl.c @@ -0,0 +1,171 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_delvlist.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of delete named */ +/* variable list. It decodes the delete named variable list */ +/* response (confirm) & encodes the delete named variable list */ +/* request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DELVLIST_RESP_INFO *rsp_info; + +static ST_VOID delvlist_num_matched (ASN1_DEC_CTXT *aCtx); +static ST_VOID delvlist_num_deleted (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_del_vlist_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_del_vlist_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Delete Named Variable List Response"); + +/* get storage for request information */ + rsp_info = (DELVLIST_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (DELVLIST_RESP_INFO)); + ASN1R_TAG_ADD (aCtx, CTX, 0, delvlist_num_matched); + } + +/************************************************************************/ +/* delvlist_num_matched */ +/* Decoding delete named variable list response: number matched was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID delvlist_num_matched (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delvlist_num_matched"); + + if (asn1r_get_u32 (aCtx, &rsp_info->num_matched)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + ASN1R_TAG_ADD (aCtx, CTX, 1, delvlist_num_deleted); + } + +/************************************************************************/ +/* delvlist_num_deleted */ +/* Decoding delete named variable list response: number deleted was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID delvlist_num_deleted (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delvlist_num_deleted"); + + if (asn1r_get_u32 (aCtx, &rsp_info->num_deleted)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + else + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_delvlist */ +/* Create and send a delete named variable list request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_delvlist (ST_INT chan, DELVLIST_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DEL_VLIST, + M_CAST_MK_FUN (_ms_mk_delvlist_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_delvlist */ +/* Create a delete named variable list request. */ +/************************************************************************/ + +ST_RET mpl_delvlist (DELVLIST_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DEL_VLIST, + M_CAST_MK_FUN (_ms_mk_delvlist_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_delvlist_req */ +/* construct a delete named variable list request */ +/************************************************************************/ + +ST_VOID _ms_mk_delvlist_req (ASN1_ENC_CTXT *aCtx, DELVLIST_REQ_INFO *info_ptr) + { +ST_INT i; +OBJECT_NAME *obj_ptr; + + if (info_ptr->dname_pres) + { + asn1r_wr_vstr (aCtx, info_ptr->dname); /* write the domain name */ + asn1r_fin_prim (aCtx, 2,CTX); /* context tag 2 */ + } + + if (info_ptr->vnames_pres) + { + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + obj_ptr = (OBJECT_NAME *) (info_ptr + 1); + obj_ptr +=info_ptr->num_of_vnames-1;/* point to last variable name */ + for (i = 0; i < info_ptr->num_of_vnames; i++) + { + _ms_wr_mms_objname (aCtx, obj_ptr); + obj_ptr--; + } + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish context tag 1 cstr */ + } + + if (info_ptr->scope != 0) /* default is 0-specific */ + { /* not the default, so */ + asn1r_wr_i16 (aCtx, info_ptr->scope); /* write the scope of delete */ + asn1r_fin_prim (aCtx, 0,CTX); /* context tag 0 */ + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEL_VLIST,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_downl.c b/mmslib/mmsle/rq_downl.c new file mode 100644 index 0000000..43527c0 --- /dev/null +++ b/mmslib/mmsle/rq_downl.c @@ -0,0 +1,214 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_download.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the download */ +/* segment. It decodes the download segment response (confirm) */ +/* & encodes the download segment request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 08/28/03 EJV 06 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DOWNLOAD_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID download_get_more_follows (ASN1_DEC_CTXT *aCtx); +static ST_VOID download_get_load_data (ASN1_DEC_CTXT *aCtx); +static ST_VOID download_load_data_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID download_load_data_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID extern_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_download_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_download_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Download Segment Response"); + +/* get storage for request information */ + rsp_info = (DOWNLOAD_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (DOWNLOAD_RESP_INFO)); + rsp_info->more_follows = SD_TRUE; /* set default value */ + + ASN1R_TAG_ADD (aCtx, CTX, 0, download_get_load_data); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, download_load_data_cstr); + +/* If MMS IS, Check for CODED load data */ +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + _ms_chk_for_extern (aCtx, &rsp_info->load_data_len, + &rsp_info->load_data, + extern_done); + } + +/************************************************************************/ +/* download_get_load_data */ +/* Decoding download segment response: load data octets primitive was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID download_get_load_data (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("download_get_load_data"); + + /* decode load data onto itself, shifted by one character */ + rsp_info->load_data = aCtx->asn1r_field_ptr -1; + /* read load data */ + if (asn1r_get_octstr (aCtx, rsp_info->load_data)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + rsp_info->load_data_type = LOAD_DATA_NON_CODED; + rsp_info->load_data_len = aCtx->asn1r_octetcount; /* save the load data length */ + + ASN1R_TAG_ADD (aCtx, CTX, 1, download_get_more_follows); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* download_load_data_cstr */ +/* Decoding download segment response: load data octets constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID download_load_data_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("download_load_data_cstr"); + + /* decode entry id onto itself, shifted by one character */ + rsp_info->load_data = aCtx->asn1r_field_ptr - 1; + + /* set up where to go when done decoding cstr */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = download_load_data_cstr_done; + + /* read load data from the received message */ + asn1r_get_octstr_cstr (aCtx, _mmsdec_msglen, rsp_info->load_data); + } + +/************************************************************************/ +/* download_load_data_cstr_done */ +/* Decoding download segment response: load data octets constructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID download_load_data_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + rsp_info->load_data_len = aCtx->asn1r_octetcount; /* save the load data length */ + + ASN1R_TAG_ADD (aCtx, CTX, 1, download_get_more_follows); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* extern_done */ +/************************************************************************/ + +static ST_VOID extern_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("extern_done"); + + rsp_info->load_data_type = LOAD_DATA_CODED; + ASN1R_TAG_ADD (aCtx, CTX, 1, download_get_more_follows); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* download_get_more_follows */ +/* Decoding download segment response: more follows was encountered. */ +/************************************************************************/ + +static ST_VOID download_get_more_follows (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("download_get_more_follows"); + /* read more follows */ + if (asn1r_get_bool (aCtx, &(rsp_info->more_follows))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_download */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the download segment request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_download (ST_INT chan, DOWNLOAD_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DOWN_LOAD, + M_CAST_MK_FUN (_ms_mk_download_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_download */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the download segment request. */ +/************************************************************************/ + +ST_RET mpl_download (DOWNLOAD_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DOWN_LOAD, + M_CAST_MK_FUN (_ms_mk_download_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/* _ms_mk_download_req */ +/* construct a download segment request */ +/************************************************************************/ + +ST_VOID _ms_mk_download_req (ASN1_ENC_CTXT *aCtx, DOWNLOAD_REQ_INFO *info) + { + asn1r_wr_vstr (aCtx, info->dname); /* write the domain name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_DOWN_LOAD,CTX); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsle/rq_fclos.c b/mmslib/mmsle/rq_fclos.c new file mode 100644 index 0000000..ca56777 --- /dev/null +++ b/mmslib/mmsle/rq_fclos.c @@ -0,0 +1,96 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_fclose.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the file close. */ +/* It decodes the file close response (confirm) & encodes the */ +/* file close request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_file_close_rsp */ +/* NOTE : Since the mms_file_close_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_fclose */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file close request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_fclose (ST_INT chan, FCLOSE_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_FILE_CLOSE, + M_CAST_MK_FUN (_ms_mk_fclose_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_fclose */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file close request. */ +/************************************************************************/ + +ST_RET mpl_fclose (FCLOSE_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_FILE_CLOSE, + M_CAST_MK_FUN (_ms_mk_fclose_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_fclose_req */ +/* construct a file close request */ +/************************************************************************/ + +ST_VOID _ms_mk_fclose_req (ASN1_ENC_CTXT *aCtx, FCLOSE_REQ_INFO *info) + { + + asn1r_wr_i32 (aCtx, info->frsmid); /* write the frsmid */ + + /* write the context specific tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_FILE_CLOSE,CTX); + } diff --git a/mmslib/mmsle/rq_fdele.c b/mmslib/mmsle/rq_fdele.c new file mode 100644 index 0000000..a6c5adc --- /dev/null +++ b/mmslib/mmsle/rq_fdele.c @@ -0,0 +1,97 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_fdelete.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the file delete. */ +/* It decodes the file delete response (confirm) & encodes the */ +/* file delete request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_file_delete_rsp */ +/* NOTE : Since the mms_file_delete_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_fdelete */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file delete request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_fdelete (ST_INT chan, FDELETE_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_FILE_DELETE, + M_CAST_MK_FUN (_ms_mk_fdelete_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_fdelete */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file delete request. */ +/************************************************************************/ + +ST_RET mpl_fdelete (FDELETE_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_FILE_DELETE, + M_CAST_MK_FUN (_ms_mk_fdelete_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_fdelete_req */ +/* construct a file delete request */ +/************************************************************************/ + +ST_VOID _ms_mk_fdelete_req (ASN1_ENC_CTXT *aCtx, FDELETE_REQ_INFO *info) + { + asn1r_strt_constr (aCtx); + _ms_wr_mms_fname (aCtx, (FILE_NAME *)(info + 1), + info -> num_of_fname); + + /* write the context specific tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_FILE_DELETE,CTX,DEF); + } diff --git a/mmslib/mmsle/rq_fdir.c b/mmslib/mmsle/rq_fdir.c new file mode 100644 index 0000000..28994d2 --- /dev/null +++ b/mmslib/mmsle/rq_fdir.c @@ -0,0 +1,351 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_fdir.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of file directory. */ +/* It decodes the file directory response (confirm) & encodes the */ +/* file directory request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static FDIR_RESP_INFO *fop_info; + +static FDIR_DIR_ENT *ent_ptr; +static FDIR_DIR_ENT *dir_ptr; +static ST_INT max_dir_ents; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID fdir_dir_entry (ASN1_DEC_CTXT *aCtx); +static ST_VOID fdir_more_follows (ASN1_DEC_CTXT *aCtx); +static ST_VOID fdir_get_fil_mtim (ASN1_DEC_CTXT *aCtx); +static ST_VOID fdir_dir_ent_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID fdir_get_fil_siz (ASN1_DEC_CTXT *aCtx); +static ST_VOID fdir_get_fil_attr (ASN1_DEC_CTXT *aCtx); +static ST_VOID fdir_fname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID fdir_fname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID fdir_dir_list_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID fdir_dir_seq (ASN1_DEC_CTXT *aCtx); +static ST_VOID fdir_dir_list (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_file_dir_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_file_dir_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("File Directory Response"); + + +#if defined(FIXED_DECBUF) + max_dir_ents = m_cl_max_file_directory; + rsp_size = mmsl_dec_info_size; +#else + max_dir_ents = _mmsdec_msglen/8; /* determine maximum size */ + if (m_cl_max_file_directory && (max_dir_ents > m_cl_max_file_directory)) + max_dir_ents = m_cl_max_file_directory; + +/* get storage for resp info */ + rsp_size = sizeof (FDIR_RESP_INFO) + + (max_dir_ents * (sizeof (FDIR_DIR_ENT))) + + (max_dir_ents * (sizeof (FILE_NAME))); +#endif + +/* get storage for request information */ + fop_info = (FDIR_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + fop_info->num_dir_ent = 0; /* set default values */ + fop_info->more_follows = SD_FALSE; + ent_ptr = (FDIR_DIR_ENT *) (fop_info + 1); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, fdir_dir_list); + } + +/************************************************************************/ +/* fdir_dir_list */ +/* file directory response is being decoded: directory list constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID fdir_dir_list (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fdir_dir_list"); + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, fdir_dir_seq); + } + +/************************************************************************/ +/* fdir_dir_seq */ +/* file directory response is being decoded: directory entry constr */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID fdir_dir_seq (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fdir_dir_seq"); + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, fdir_dir_entry); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = NULL; + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level - 1] = fdir_dir_list_done; + } + +/************************************************************************/ +/* fdir_dir_entry */ +/* file directory response is being decoded: directory sequence was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID fdir_dir_entry (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fdir_dir_entry"); + + fop_info->num_dir_ent++; /* increment directory entry count */ + if (fop_info->num_dir_ent > max_dir_ents) + asn1r_set_dec_err (aCtx, RESP_UNSPECIFIED); + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,fdir_fname_cstr); + } + +/************************************************************************/ +/* fdir_fname_cstr */ +/* request domain download request is being decoded: filename cstr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID fdir_fname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fdir_fname_cstr"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = fdir_fname_cstr_done; + _ms_get_mms_fname (aCtx, (FILE_NAME *)(ent_ptr + 1), + max_dir_ents, &ent_ptr->num_of_fname); + } + +/************************************************************************/ +/* fdir_fname_cstr_done */ +/* request domain download request is being decoded: file name list */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID fdir_fname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, fdir_get_fil_attr); + } + +/************************************************************************/ +/* fdir_get_fil_attr */ +/* file directory response is being decoded: file attributes constr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID fdir_get_fil_attr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fdir_get_fil_attr"); + + ASN1R_TAG_ADD (aCtx, CTX, 0, fdir_get_fil_siz); + } + +/************************************************************************/ +/* fdir_get_fil_siz */ +/* file directory response is being decoded: file size was found, */ +/* modified time can be next, or can be done. */ +/************************************************************************/ + +static ST_VOID fdir_get_fil_siz (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fdir_get_fil_si"); + + if (asn1r_get_u32 (aCtx, &(ent_ptr->fsize))) /* read the file size */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX,1,fdir_get_fil_mtim); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = NULL; /* ok for file attr to be done */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level-1] = fdir_dir_ent_done; + } + +/************************************************************************/ +/* fdir_get_fil_mtim */ +/* file directory response is being decoded: directory entry was */ +/* encountered, and modified time was found; creator can be next. */ +/************************************************************************/ + +static ST_VOID fdir_get_fil_mtim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fdir_get_fil_mtim"); + + ent_ptr->mtimpres = SD_TRUE; /* set modify time present */ + if (asn1r_get_time (aCtx, &ent_ptr->mtime)) /* read the last modified time */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + } + +/************************************************************************/ +/* fdir_dir_ent_done */ +/* DECODING file directory response: directory entry was completed. */ +/* Re-initialize the valid states. */ +/************************************************************************/ + +static ST_VOID fdir_dir_ent_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fdir_dir_ent_done"); + +/* point to where the next directory entry will start */ + + ent_ptr = (FDIR_DIR_ENT *)(((FILE_NAME *)(ent_ptr + 1)) + + (ent_ptr -> num_of_fname)); + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, fdir_dir_entry); + } + +/************************************************************************/ +/* fdir_dir_list_done */ +/* DECODING file directory response: directory list was completed. */ +/* Re-initialize the valid states. */ +/************************************************************************/ + +static ST_VOID fdir_dir_list_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT resp_size; +ST_INT i; +ST_INT fname_count; + + MLOG_CDEC0 ("fdir_dir_list_done"); + + fname_count = 0; + ASN1R_TAG_ADD (aCtx, CTX, 1, fdir_more_follows); + + /* find the exact size of the storage used */ + + dir_ptr = (FDIR_DIR_ENT *)(fop_info + 1); + for (i=0; i < fop_info->num_dir_ent; ++i) + { + fname_count += dir_ptr->num_of_fname; + dir_ptr = (FDIR_DIR_ENT *)(((FILE_NAME *)(dir_ptr + 1)) + + (dir_ptr -> num_of_fname)); + } + /* give back unused storage */ + resp_size = sizeof (FDIR_RESP_INFO) + + ((fop_info->num_dir_ent) * sizeof (FDIR_DIR_ENT)) + + (fname_count * sizeof (FILE_NAME)); + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,resp_size); + fop_info = (FDIR_RESP_INFO *) _mms_dec_info; + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* fdir_more_follows */ +/* file directory response is being decoded: more follows indicator */ +/* has been encountered. */ +/************************************************************************/ + +static ST_VOID fdir_more_follows (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fdir_more_follows"); + + if (asn1r_get_bool (aCtx, &(fop_info->more_follows))) /* read more follows */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_fdir */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file directory request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_fdir (ST_INT chan, FDIR_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_FILE_DIR, + M_CAST_MK_FUN (_ms_mk_fdir_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_fdir */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file directory request. */ +/************************************************************************/ + +ST_RET mpl_fdir (FDIR_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_FILE_DIR, + M_CAST_MK_FUN (_ms_mk_fdir_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_fdir_req */ +/* ENCODE a file directory REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_fdir_req (ASN1_ENC_CTXT *aCtx, FDIR_REQ_INFO *info) + { +FILE_NAME *fname_idx; + + if (info->cont_after_pres) + { /* write continue after name */ + asn1r_strt_constr (aCtx); + fname_idx = (FILE_NAME *)(info + 1); + fname_idx += info->num_of_fs_fname; + _ms_wr_mms_fname (aCtx, fname_idx, info->num_of_ca_fname); + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* context specific tag 1 */ + } + + if (info->filespec_pres) + { /* write the file specification */ + asn1r_strt_constr (aCtx); + fname_idx = (FILE_NAME *)(info + 1); + _ms_wr_mms_fname (aCtx, fname_idx, info->num_of_fs_fname); + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context specific tag 0 */ + } + + /* write the context specific tag for this opcode */ + asn1r_fin_constr (aCtx, MMSOP_FILE_DIR,CTX,DEF); + } diff --git a/mmslib/mmsle/rq_fopen.c b/mmslib/mmsle/rq_fopen.c new file mode 100644 index 0000000..c9313d5 --- /dev/null +++ b/mmslib/mmsle/rq_fopen.c @@ -0,0 +1,197 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_fopen.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the file open. */ +/* It decodes the file open response (confirm) & encodes the */ +/* file open request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static FOPEN_RESP_INFO *fop_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID fopen_fil_attr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID fopen_get_fil_mtim (ASN1_DEC_CTXT *aCtx); +static ST_VOID fopen_get_fil_siz (ASN1_DEC_CTXT *aCtx); +static ST_VOID fopen_get_fil_attr (ASN1_DEC_CTXT *aCtx); +static ST_VOID fopen_get_frsmid (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_file_open_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_file_open_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("File Open Response"); + + +/* get storage for request information */ + fop_info = (FOPEN_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (FOPEN_RESP_INFO)); + ASN1R_TAG_ADD (aCtx, CTX, 0, fopen_get_frsmid); + } + +/************************************************************************/ +/* fopen_get_frsmid */ +/* file open response is being decoded: file read state machine id was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID fopen_get_frsmid (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fopen_get_frsmid"); + + if (asn1r_get_i32 (aCtx, &(fop_info->frsmid))) /* read the frsmid */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, fopen_get_fil_attr); + } + +/************************************************************************/ +/* fopen_get_fil_attr */ +/* file open response is being decoded: file attributes constr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID fopen_get_fil_attr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fopen_get_fil_attr"); + + ASN1R_TAG_ADD (aCtx, CTX, 0, fopen_get_fil_siz); + } + +/************************************************************************/ +/* fopen_get_fil_siz */ +/* file open response is being decoded: file size was found, last */ +/* modified time can be next, or can be done. */ +/************************************************************************/ + +static ST_VOID fopen_get_fil_siz (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fopen_get_fil_siz"); + + if (asn1r_get_u32 (aCtx, &(fop_info->ent.fsize))) /* read the file size */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX,1,fopen_get_fil_mtim); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = fopen_fil_attr_done; + } + +/************************************************************************/ +/* fopen_get_fil_mtim */ +/* file open response is being decoded: modified time was encountered, */ +/* must be done now. */ +/************************************************************************/ + +static ST_VOID fopen_get_fil_mtim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fopen_get_fil_mtim"); + + fop_info->ent.mtimpres = SD_TRUE; /* set modify time present */ + if (asn1r_get_time (aCtx, &fop_info->ent.mtime)) /* read the last modified time */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + } + +/************************************************************************/ +/* fopen_fil_attr_done */ +/* DECODING file open response: file attribute constructor completed. */ +/* Set the valid state to done. */ +/************************************************************************/ + +static ST_VOID fopen_fil_attr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fopen_fil_attr_done"); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_fopen */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file open request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_fopen (ST_INT chan, FOPEN_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_FILE_OPEN, + M_CAST_MK_FUN (_ms_mk_fopen_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_fopen */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file open request. */ +/************************************************************************/ + +ST_RET mpl_fopen (FOPEN_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_FILE_OPEN, + M_CAST_MK_FUN (_ms_mk_fopen_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_fopen_req */ +/* ENCODE a file openectory REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_fopen_req (ASN1_ENC_CTXT *aCtx, FOPEN_REQ_INFO *info) + { + + asn1r_wr_u32 (aCtx, info->init_pos); /* write the initial position */ + asn1r_fin_prim (aCtx, 1,CTX); /* context specific tag 1 */ + + asn1r_strt_constr (aCtx); + _ms_wr_mms_fname (aCtx, (FILE_NAME *)(info + 1), + info -> num_of_fname); + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context specific tag 0 */ + + /* write the context specific tag for this opcode */ + asn1r_fin_constr (aCtx, MMSOP_FILE_OPEN,CTX,DEF); + } diff --git a/mmslib/mmsle/rq_fread.c b/mmslib/mmsle/rq_fread.c new file mode 100644 index 0000000..b17e69b --- /dev/null +++ b/mmslib/mmsle/rq_fread.c @@ -0,0 +1,190 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_fread.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the file read. */ +/* It decodes the file read response (confirm) & encodes the */ +/* file read request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 08/28/03 EJV 06 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static FREAD_RESP_INFO *fop_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/* static functions with multiple references */ + +static ST_VOID fread_file_data_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID fread_get_fd_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID fread_get_fd_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID fread_get_more_follows (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/* mms_file_read_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_file_read_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("File Read Response"); + + +/* get storage for request information */ + fop_info = (FREAD_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (FREAD_RESP_INFO)); + fop_info->more_follows = SD_TRUE; /* set default value */ + ASN1R_TAG_ADD (aCtx, CTX,0, fread_get_fd_prim); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 0, fread_get_fd_cstr); + } + + +/************************************************************************/ +/* fread_get_fd_prim */ +/* file read response is being decoded: file data was encountered. */ +/************************************************************************/ + +static ST_VOID fread_get_fd_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fread_get_fd_prim"); + + /* decode file data back onto itself */ + fop_info->filedata = aCtx->asn1r_field_ptr; + + if (asn1r_get_octstr (aCtx, fop_info->filedata)) /* read file data from message */ + asn1r_set_dec_err (aCtx, RESP_UNSPECIFIED); + + fread_file_data_done (aCtx); /* save octet count, setup to continue */ + } + +/************************************************************************/ +/* fread_get_fd_cstr */ +/* file read response is being decoded: file data was encountered. */ +/************************************************************************/ + +static ST_VOID fread_get_fd_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fread_get_fd_cstr"); + + /* decode file data back onto itself */ + fop_info->filedata = aCtx->asn1r_field_ptr; + + /* set up done decoding octet cstr destination */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = fread_file_data_done; + + /* get file data from the received message */ + /* set maximum length to accept entire message */ + asn1r_get_octstr_cstr (aCtx, _mmsdec_msglen, fop_info->filedata); + } + +/************************************************************************/ +/* fread_file_data_done */ +/* file read response is being decoded: end of file data constructor */ +/* This is called directly from prim octet or from c_done fun. */ +/************************************************************************/ + +static ST_VOID fread_file_data_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("data_don"); + + fop_info->fd_len = aCtx->asn1r_octetcount; /* save the file data length */ + /* set up done decoding file data cstr dest */ + + ASN1R_TAG_ADD (aCtx, CTX, 1, fread_get_more_follows); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* fread_get_more_follows */ +/* file read response is being decoded: more data follows indicator was */ +/* encountered, must be done now. */ +/************************************************************************/ + +static ST_VOID fread_get_more_follows (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fread_get_more_follows"); + + if (asn1r_get_bool (aCtx, &(fop_info->more_follows))) /* read more follows */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_fread */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file read request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_fread (ST_INT chan, FREAD_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_FILE_READ, + M_CAST_MK_FUN (_ms_mk_fread_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_fread */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file read request. */ +/************************************************************************/ + +ST_RET mpl_fread (FREAD_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_FILE_READ, + M_CAST_MK_FUN (_ms_mk_fread_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_fread_req */ +/* ENCODE a file readectory REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_fread_req (ASN1_ENC_CTXT *aCtx, FREAD_REQ_INFO *info) + { + asn1r_wr_i32 (aCtx, info->frsmid); /* write the frsmid */ + /* write the context specific tag for this opcode */ + asn1r_fin_prim (aCtx, MMSOP_FILE_READ,CTX); + } diff --git a/mmslib/mmsle/rq_frena.c b/mmslib/mmsle/rq_frena.c new file mode 100644 index 0000000..0d80e66 --- /dev/null +++ b/mmslib/mmsle/rq_frena.c @@ -0,0 +1,108 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_frename.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the file rename. */ +/* It decodes the file rename response (confirm) & encodes the */ +/* file rename request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_file_rename_rsp */ +/* NOTE : Since the mms_file_rename_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_frename */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file rename request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_frename (ST_INT chan, FRENAME_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_FILE_RENAME, + M_CAST_MK_FUN (_ms_mk_frename_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_frename */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file rename request. */ +/************************************************************************/ + +ST_RET mpl_frename (FRENAME_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_FILE_RENAME, + M_CAST_MK_FUN (_ms_mk_frename_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_frename_req */ +/* construct a file rename request */ +/************************************************************************/ + +ST_VOID _ms_mk_frename_req (ASN1_ENC_CTXT *aCtx, FRENAME_REQ_INFO *info) + { +FILE_NAME *fname_idx; + + /* write the new file name */ + asn1r_strt_constr (aCtx); + fname_idx = (FILE_NAME *)(info + 1); + fname_idx += info->num_of_cur_fname; + _ms_wr_mms_fname (aCtx, fname_idx, info -> num_of_new_fname); + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* context specific tag 1 */ + + /* write the current file name */ + asn1r_strt_constr (aCtx); + fname_idx = (FILE_NAME *)(info + 1); + _ms_wr_mms_fname (aCtx, fname_idx, info -> num_of_cur_fname); + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context specific tag 0 */ + + /* write the context specific tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_FILE_RENAME,CTX,DEF); + } diff --git a/mmslib/mmsle/rq_getae.c b/mmslib/mmsle/rq_getae.c new file mode 100644 index 0000000..27c75a0 --- /dev/null +++ b/mmslib/mmsle/rq_getae.c @@ -0,0 +1,682 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_getaes.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of get alarm */ +/* enrollment summary. It decodes the get alarm enrollment */ +/* summary response (confirm) & encodes the get alarm enrollment */ +/* summary request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 04/28/00 JRB 04 Lint cleanup */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +static GETAES_RESP_INFO *rsp_info; + +static ALARM_ENROLL_SUMMARY *aes_ptr; +static ST_INT max_enroll_sums; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID getaes_aes_list_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_eename_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_eename_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_eename_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_client_app_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_client_app_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_client_app_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_get_severity (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_get_cur_state (ASN1_DEC_CTXT *aCtx); +#ifdef CS_SUPPORT +static ST_VOID getaes_addl_detail_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_addl_detail_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_addl_detail_cstr_done (ASN1_DEC_CTXT *aCtx); +#endif +static ST_VOID getaes_get_not_lost (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_get_alarm_ack_rule (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_get_ee_state (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_tta_time_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_tta_time_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_tta_time_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_aack_time_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_aack_time_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_aack_time_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_tti_time_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_tti_time_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_tti_time_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_iack_time_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_iack_time_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_alarm_esum_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_alarm_esum_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_aes_list_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_get_more_follows (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_getaes_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_getaes_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("Get Alarm Enrollment Summary Response"); + +#if defined(FIXED_DECBUF) + max_enroll_sums = m_cl_max_enrollment_summary; + rsp_size = mmsl_dec_info_size; +#else + max_enroll_sums = _mmsdec_msglen/8; /* determine maximum size */ + if (m_cl_max_enrollment_summary && (max_enroll_sums > m_cl_max_enrollment_summary)) + max_enroll_sums = m_cl_max_enrollment_summary; + rsp_size = sizeof (GETAES_RESP_INFO) + + (max_enroll_sums * (sizeof (ALARM_ENROLL_SUMMARY))); + /* get storage for resp info */ +#endif + +/* get storage for request information */ + rsp_info = (GETAES_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + aes_ptr = (ALARM_ENROLL_SUMMARY *) (rsp_info + 1); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, getaes_aes_list_cstr); + } + +/************************************************************************/ +/* getaes_aes_list_cstr */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* alarm enrollment summary list constructor was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_aes_list_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_aes_list_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, getaes_alarm_esum_cstr); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getaes_aes_list_cstr_done; + } + +/************************************************************************/ +/* getaes_alarm_esum_cstr */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* alarm enrollment summary was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_alarm_esum_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_alarm_esum_cstr"); + + rsp_info->num_of_alarm_esum++; /* inc alarm enrollment sum cnt */ + + if (rsp_info->num_of_alarm_esum > max_enroll_sums) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, getaes_eename_cstr); + } + +/************************************************************************/ +/* getaes_eename_cstr */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* event enrollment name cstr was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_eename_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_eename_cstr"); + + _ms_get_mms_objname (aCtx, &aes_ptr->evenroll_name, getaes_eename_done); + } + +/************************************************************************/ +/* getaes_eename_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* event enrollment name has been obtained. */ +/************************************************************************/ + +static ST_VOID getaes_eename_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_eename_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getaes_eename_cstr_done; + } + +/************************************************************************/ +/* getaes_eename_cstr_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* event enrollment name cstr done has been encountered. */ +/************************************************************************/ + +static ST_VOID getaes_eename_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, getaes_client_app_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 3, getaes_get_severity); + } + +/************************************************************************/ +/* getaes_client_app_cstr */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* client application constructor was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_client_app_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_client_app_cstr"); + + aes_ptr->client_app_pres = SD_TRUE; /* set client app present */ + + _ms_get_mms_app_ref (aCtx, &aes_ptr->client_app,&aes_ptr->client_app_len, + getaes_client_app_done); + } + +/************************************************************************/ +/* getaes_client_app_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* client application has been obtained. */ +/************************************************************************/ + +static ST_VOID getaes_client_app_done (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getaes_client_app_cstr_done; + } + +/************************************************************************/ +/* getaes_client_app_cstr_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* client application constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_client_app_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX, 3, getaes_get_severity); + } + +/************************************************************************/ +/* getaes_get_severity */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* severity was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_get_severity (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_get_severity"); + + if (asn1r_get_u8 (aCtx, &aes_ptr->severity)) /* get the severity */ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 4, getaes_get_cur_state); + } + +/************************************************************************/ +/* getaes_get_cur_state */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* current state was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_get_cur_state (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_get_cur_state"); + + if (asn1r_get_i16 (aCtx, &aes_ptr->cur_state)) /* get current state */ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + else if ((aes_ptr->cur_state < 0) || (aes_ptr->cur_state > 2)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + +#ifdef CS_SUPPORT + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, getaes_addl_detail_cstr); +#endif + ASN1R_TAG_ADD (aCtx, CTX, 6, getaes_get_not_lost); + ASN1R_TAG_ADD (aCtx, CTX, 7, getaes_get_alarm_ack_rule); + } + +#ifdef CS_SUPPORT +/************************************************************************/ +/* getaes_addl_detail_cstr */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* additional detail constructor was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_addl_detail_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_addl_detail_cstr"); + + aes_ptr->addl_detail_pres = SD_TRUE; /* set flag */ + aes_ptr->addl_detail = aCtx->asn1r_field_ptr; + aes_ptr->addl_detail_len = aCtx->asn1r_elmnt_len; + + asn1r_parse_next (aCtx, getaes_addl_detail_done); /* parse the contents */ + } + +/************************************************************************/ +/* getaes_addl_detail_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* additional detail has been obtained. */ +/************************************************************************/ + +static ST_VOID getaes_addl_detail_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_addl_detail_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getaes_addl_detail_cstr_done; + } + +/************************************************************************/ +/* getaes_addl_detail_cstr_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* additional detail constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_addl_detail_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX, 6, getaes_get_not_lost); + ASN1R_TAG_ADD (aCtx, CTX, 7, getaes_get_alarm_ack_rule); + } +#endif + +/************************************************************************/ +/* getaes_get_not_lost */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* notification lost was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_get_not_lost (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_get_not_lost"); + + if (asn1r_get_bool (aCtx, &(aes_ptr->not_lost))) /* get notification lost*/ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 7, getaes_get_alarm_ack_rule); + } + +/************************************************************************/ +/* getaes_get_alarm_ack_rule */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* alarm acknowledgment rule was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_get_alarm_ack_rule (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_get_alarm_ack_rule"); + /* read alarm ack rule */ + if (asn1r_get_i16 (aCtx, &(aes_ptr->alarm_ack_rule))) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + else if ((aes_ptr->alarm_ack_rule < 0) || (aes_ptr->alarm_ack_rule > 3)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 8, getaes_get_ee_state); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 9, getaes_tta_time_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,10, getaes_aack_time_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,11, getaes_tti_time_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,12, getaes_iack_time_cstr); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getaes_alarm_esum_cstr_done; + } + +/************************************************************************/ +/* getaes_get_ee_state */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* event enrollment state was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_get_ee_state (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_get_ee_state"); + + aes_ptr->ee_state_pres = SD_TRUE; /* set event cond state pres */ + + if (asn1r_get_i16 (aCtx, &aes_ptr->ee_state)) /* get event cond state */ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + else if ((aes_ptr->ee_state < 0) || (aes_ptr->ee_state > 7)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 9, getaes_tta_time_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,10, getaes_aack_time_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,11, getaes_tti_time_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,12, getaes_iack_time_cstr); + } + +/************************************************************************/ +/* getaes_tta_time_cstr */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* transition to active time cstr was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_tta_time_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_tta_time_cstr"); + + aes_ptr->tta_time_pres = SD_TRUE; /* set tran to active present */ + + _ms_get_mms_evtime (aCtx, &aes_ptr->tta_time, getaes_tta_time_done); + } + +/************************************************************************/ +/* getaes_tta_time_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* transition to active time has been obtained. */ +/************************************************************************/ + +static ST_VOID getaes_tta_time_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_tta_time_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getaes_tta_time_cstr_done; + } + +/************************************************************************/ +/* getaes_tta_time_cstr_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* transition to active time cstr done has been encountered. */ +/************************************************************************/ + +static ST_VOID getaes_tta_time_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,10, getaes_aack_time_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,11, getaes_tti_time_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,12, getaes_iack_time_cstr); + } + +/************************************************************************/ +/* getaes_aack_time_cstr */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* active acknowledgment time cstr was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_aack_time_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_aack_time_cstr"); + + aes_ptr->aack_time_pres = SD_TRUE; /* active acknowledgment pres */ + + _ms_get_mms_evtime (aCtx, &aes_ptr->aack_time, getaes_aack_time_done); + } + +/************************************************************************/ +/* getaes_aack_time_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* active acknowledgment time has been obtained. */ +/************************************************************************/ + +static ST_VOID getaes_aack_time_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_aack_time_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getaes_aack_time_cstr_done; + } + +/************************************************************************/ +/* getaes_aack_time_cstr_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* active acknowledgment time cstr done was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_aack_time_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,11, getaes_tti_time_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,12, getaes_iack_time_cstr); + } + +/************************************************************************/ +/* getaes_tti_time_cstr */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* transition to idle time cstr was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_tti_time_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_tti_time_cstr"); + + aes_ptr->tti_time_pres = SD_TRUE; /* set tran to idle present */ + + _ms_get_mms_evtime (aCtx, &aes_ptr->tti_time, getaes_tti_time_done); + } + +/************************************************************************/ +/* getaes_tti_time_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* transition to idle time has been obtained. */ +/************************************************************************/ + +static ST_VOID getaes_tti_time_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_tti_time_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getaes_tti_time_cstr_done; + } + +/************************************************************************/ +/* getaes_tti_time_cstr_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* transition to idle time cstr done was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_tti_time_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,12, getaes_iack_time_cstr); + } + +/************************************************************************/ +/* getaes_iack_time_cstr */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* idle acknowledgment time cstr was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_iack_time_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_iack_time_cstr"); + + aes_ptr->iack_time_pres = SD_TRUE; /* idle acknowledgment present */ + + _ms_get_mms_evtime (aCtx, &aes_ptr->iack_time, getaes_iack_time_done); + } + +/************************************************************************/ +/* getaes_iack_time_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): */ +/* idle acknowledgment time has been obtained. */ +/************************************************************************/ + +static ST_VOID getaes_iack_time_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_iack_time_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = NULL; + } + +/************************************************************************/ +/* getaes_alarm_esum_cstr_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): alarm */ +/* summary constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_alarm_esum_cstr_done (ASN1_DEC_CTXT *aCtx) + { + aes_ptr++; /* point to where next will go */ + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, getaes_alarm_esum_cstr); + } + +/************************************************************************/ +/* getaes_aes_list_cstr_done */ +/* decoding get alarm enrollment summary RESPONSE (confirm): alarm */ +/* summary list constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_aes_list_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + /* find actual size for response info */ + rsp_size = sizeof (GETAES_RESP_INFO) + + (sizeof (ALARM_ENROLL_SUMMARY) * rsp_info->num_of_alarm_esum); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,rsp_size); + rsp_info = (GETAES_RESP_INFO *) _mms_dec_info; + + ASN1R_TAG_ADD (aCtx, CTX, 1, getaes_get_more_follows); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* getaes_get_more_follows */ +/* decoding get alarm enrollment summary RESPONSE (confirm): more */ +/* follows indicator was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_get_more_follows (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_get_more_follows"); + + if (asn1r_get_bool (aCtx, &rsp_info->more_follows)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getaes */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the decoding get alarm enrollment summary */ +/* request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_getaes (ST_INT chan, GETAES_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_GET_ALARM_ESUM, + M_CAST_MK_FUN (_ms_mk_getaes_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getaes */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the decoding get alarm enrollment summary request. */ +/************************************************************************/ + +ST_RET mpl_getaes (GETAES_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_GET_ALARM_ESUM, + M_CAST_MK_FUN (_ms_mk_getaes_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getaes_req */ +/* ENCODE a decoding get alarm enrollment summary REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_getaes_req (ASN1_ENC_CTXT *aCtx, GETAES_REQ_INFO *info) + { + if (info->ca_name_pres) + { + asn1r_strt_constr (aCtx); /* start ctx tag 5 cstr */ + _ms_wr_mms_objname (aCtx, &info->ca_name); /* write continue after name */ + asn1r_fin_constr (aCtx, 5,CTX,DEF); /* finish ctx tag 5 cstr */ + } + + if (info->least_sev_filter != 127 || /* not the defaults */ + info->most_sev_filter != 0) + { + asn1r_strt_constr (aCtx); /* start ctx tag 3 cstr */ + asn1r_wr_u8 (aCtx, info->least_sev_filter); /* write least severe filter */ + asn1r_fin_prim (aCtx, 1,CTX); + + asn1r_wr_u8 (aCtx, info->most_sev_filter); /* write most severe filter */ + asn1r_fin_prim (aCtx, 0,CTX); + asn1r_fin_constr (aCtx, 3,CTX,DEF); /* finish ctx tag 3 cstr */ + } + + if (info->ack_filter != SD_FALSE) + { + asn1r_wr_i16 (aCtx, info->ack_filter); /* write acknowledge filter */ + asn1r_fin_prim (aCtx, 2,CTX); + } + + if (!info->act_alarms_only) + { + asn1r_wr_bool (aCtx, info->act_alarms_only); /* write active alarms only */ + asn1r_fin_prim (aCtx, 1,CTX); + } + + if (!info->enroll_only) + { + asn1r_wr_bool (aCtx, info->enroll_only); /* write enrollments only */ + asn1r_fin_prim (aCtx, 0,CTX); + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_ALARM_ESUM,CTX,DEF); /* tag = opcode, context */ + } diff --git a/mmslib/mmsle/rq_getas.c b/mmslib/mmsle/rq_getas.c new file mode 100644 index 0000000..64f1611 --- /dev/null +++ b/mmslib/mmsle/rq_getas.c @@ -0,0 +1,498 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_getas.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of get alarm */ +/* summary. It decodes the get alarm summary response (confirm) */ +/* & encodes the get alarm summary request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 04/28/00 JRB 04 Lint cleanup */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +static GETAS_RESP_INFO *rsp_info; + +static ALARM_SUMMARY *as_ptr; +static ST_INT max_summaries; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/* static functions with multiple references */ +static ST_VOID getas_as_list_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_alarm_sum_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_cond_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_cond_name_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_cond_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_get_severity (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_get_state (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_get_unack_state (ASN1_DEC_CTXT *aCtx); +#ifdef CS_SUPPORT +static ST_VOID getas_addl_detail_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_addl_detail_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_addl_detail_cstr_done (ASN1_DEC_CTXT *aCtx); +#endif +static ST_VOID getas_tta_time_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_tta_time_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_tta_time_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_tti_time_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_tti_time_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_alarm_sum_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_as_list_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_get_more_follows (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_getas_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_getas_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("Get Alarm Summary Response"); + +#if defined(FIXED_DECBUF) + max_summaries = m_cl_max_alarm_summary; + rsp_size = mmsl_dec_info_size; +#else + max_summaries = _mmsdec_msglen/8; /* determine maximum size */ + if (m_cl_max_alarm_summary && (max_summaries > m_cl_max_alarm_summary)) + max_summaries = m_cl_max_alarm_summary; + +/* get storage for resp info */ + rsp_size = sizeof (GETAS_RESP_INFO) + + (max_summaries * (sizeof (ALARM_SUMMARY))); +#endif + +/* get storage for request information */ + rsp_info = (GETAS_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + as_ptr = (ALARM_SUMMARY *) (rsp_info + 1); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, getas_as_list_cstr); + } + +/************************************************************************/ +/* getas_as_list_cstr */ +/* get alarm summary RESPONSE (confirm) is being decoded: */ +/* alarm summary list constructor was encountered. */ +/************************************************************************/ + +static ST_VOID getas_as_list_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_as_list_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, getas_alarm_sum_cstr); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getas_as_list_cstr_done; + } + +/************************************************************************/ +/* getas_alarm_sum_cstr */ +/* get alarm summary RESPONSE (confirm) is being decoded: */ +/* alarm summary was encountered. */ +/************************************************************************/ + +static ST_VOID getas_alarm_sum_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_alarm_sum_cstr"); + + rsp_info->num_of_alarm_sum++; /* increment alarm summary cnt */ + + if (rsp_info->num_of_alarm_sum > max_summaries) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, getas_cond_name_cstr); + } + +/************************************************************************/ +/* getas_cond_name_cstr */ +/* get alarm summary RESPONSE (confirm) is being decoded: */ +/* event condition name cstr was encountered. */ +/************************************************************************/ + +static ST_VOID getas_cond_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_cond_name_cstr"); + + _ms_get_mms_objname (aCtx, &as_ptr->evcon_name, getas_cond_name_done); + } + +/************************************************************************/ +/* getas_cond_name_done */ +/* get alarm summary RESPONSE (confirm) is being decoded: */ +/* event condition name has been obtained. */ +/************************************************************************/ + +static ST_VOID getas_cond_name_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_cond_name_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getas_cond_name_cstr_done; + } + +/************************************************************************/ +/* getas_cond_name_cstr_done */ +/* get alarm summary RESPONSE (confirm) is being decoded: */ +/* event condition name cstr done has been encountered. */ +/************************************************************************/ + +static ST_VOID getas_cond_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, getas_get_severity); + } + +/************************************************************************/ +/* getas_get_severity */ +/* get alarm summary RESPONSE (confirm) is being decoded: */ +/* severity was encountered. */ +/************************************************************************/ + +static ST_VOID getas_get_severity (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_get_severity"); + + if (asn1r_get_u8 (aCtx, &as_ptr->severity)) /* get the severity */ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 2, getas_get_state); + } + +/************************************************************************/ +/* getas_get_state */ +/* get alarm summary RESPONSE (confirm) is being decoded: */ +/* current state was encountered. */ +/************************************************************************/ + +static ST_VOID getas_get_state (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_get_state"); + + if (asn1r_get_i16 (aCtx, &as_ptr->cur_state)) /* get current state */ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + else if ((as_ptr->cur_state < 0) || (as_ptr->cur_state > 2)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 3, getas_get_unack_state); + } + +/************************************************************************/ +/* getas_get_unack_state */ +/* get alarm summary RESPONSE (confirm) is being decoded: */ +/* unack state was encountered. */ +/************************************************************************/ + +static ST_VOID getas_get_unack_state (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_get_unack_state"); + + if (asn1r_get_i16 (aCtx, &as_ptr->unack_state)) /* get unack state */ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + else if ((as_ptr->unack_state < 0) || (as_ptr->unack_state > 3)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + +#ifdef CS_SUPPORT + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, getas_addl_detail_cstr); +#endif + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, getas_tta_time_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 6, getas_tti_time_cstr); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getas_alarm_sum_cstr_done; + } + +#ifdef CS_SUPPORT +/************************************************************************/ +/* getas_addl_detail_cstr */ +/* get alarm summary RESPONSE (confirm) is being decoded: additional */ +/* detail was encountered. */ +/************************************************************************/ + +static ST_VOID getas_addl_detail_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_addl_detail_cstr"); + + as_ptr->addl_detail_pres = SD_TRUE; /* set add'nl detail present */ + + /* leave additional detail in place; just parse it. */ + as_ptr->addl_detail = aCtx->asn1r_field_ptr; + asn1r_parse_next (aCtx, getas_addl_detail_done); + } + +/************************************************************************/ +/* getas_addl_detail_done */ +/* get alarm summary RESPONSE (confirm) is being decoded: additional */ +/* detail has been parsed. */ +/************************************************************************/ + +static ST_VOID getas_addl_detail_done (ASN1_DEC_CTXT *aCtx) + { + + as_ptr->addl_detail_len = aCtx->asn1r_octetcount; /* save length */ + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getas_addl_detail_cstr_done; + } + +/************************************************************************/ +/* getas_addl_detail_cstr_done */ +/* get alarm summary RESPONSE (confirm) is being decoded: additional */ +/* detail cstr done has been encountered. */ +/************************************************************************/ + +static ST_VOID getas_addl_detail_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, getas_tta_time_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 6, getas_tti_time_cstr); + } +#endif + +/************************************************************************/ +/* getas_tta_time_cstr */ +/* get alarm summary RESPONSE (confirm) is being decoded: */ +/* transition to active time cstr was encountered. */ +/************************************************************************/ + +static ST_VOID getas_tta_time_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_tta_time_cstr"); + + as_ptr->tta_time_pres = SD_TRUE; /* set tran to active present */ + + _ms_get_mms_evtime (aCtx, &as_ptr->tta_time, getas_tta_time_done); + } + +/************************************************************************/ +/* getas_tta_time_done */ +/* get alarm summary RESPONSE (confirm) is being decoded: */ +/* transition to active time has been obtained. */ +/************************************************************************/ + +static ST_VOID getas_tta_time_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_tta_time_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getas_tta_time_cstr_done; + } + +/************************************************************************/ +/* getas_tta_time_cstr_done */ +/* get alarm summary RESPONSE (confirm) is being decoded: */ +/* transition to active time cstr done has been encountered. */ +/************************************************************************/ + +static ST_VOID getas_tta_time_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 6, getas_tti_time_cstr); + } + +/************************************************************************/ +/* getas_tti_time_cstr */ +/* get alarm summary RESPONSE (confirm) is being decoded: */ +/* transition to idle time cstr was encountered. */ +/************************************************************************/ + +static ST_VOID getas_tti_time_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_tti_time_cstr"); + + as_ptr->tti_time_pres = SD_TRUE; /* set tran to active present */ + + _ms_get_mms_evtime (aCtx, &as_ptr->tti_time, getas_tti_time_done); + } + +/************************************************************************/ +/* getas_tti_time_done */ +/* get alarm summary RESPONSE (confirm) is being decoded: */ +/* transition to idle time has been obtained. */ +/************************************************************************/ + +static ST_VOID getas_tti_time_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_tti_time_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = NULL; + } + +/************************************************************************/ +/* getas_alarm_sum_cstr_done */ +/* get alarm summary RESPONSE (confirm) is being decoded: alarm */ +/* summary constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID getas_alarm_sum_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + as_ptr++; /* point to where next will go */ + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, getas_alarm_sum_cstr); + } + +/************************************************************************/ +/* getas_as_list_cstr_done */ +/* get alarm summary RESPONSE (confirm) is being decoded: alarm */ +/* summary list constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID getas_as_list_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + ASN1R_TAG_ADD (aCtx, CTX, 1, getas_get_more_follows); + /* find actual size for response info */ + rsp_size = sizeof (GETAS_RESP_INFO) + + (sizeof (ALARM_SUMMARY) * rsp_info->num_of_alarm_sum); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,rsp_size); + rsp_info = (GETAS_RESP_INFO *) _mms_dec_info; + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* getas_get_more_follows */ +/* get alarm summary RESPONSE (confirm) is being decoded: more */ +/* follows indicator was encountered. */ +/************************************************************************/ + +static ST_VOID getas_get_more_follows (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_get_more_follows"); + + if (asn1r_get_bool (aCtx, &rsp_info->more_follows)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getas */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get alarm summary request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_getas (ST_INT chan, GETAS_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_GET_ALARM_SUM, + M_CAST_MK_FUN (_ms_mk_getas_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getas */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get alarm summary request. */ +/************************************************************************/ + +ST_RET mpl_getas (GETAS_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_GET_ALARM_SUM, + M_CAST_MK_FUN (_ms_mk_getas_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getas_req */ +/* ENCODE a get alarm summary REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_getas_req (ASN1_ENC_CTXT *aCtx, GETAS_REQ_INFO *info) + { + if (info->ca_pres) + { + asn1r_strt_constr (aCtx); /* start ctx tag 5 cstr */ + _ms_wr_mms_objname (aCtx, &info->ca_name); /* write continue after name */ + asn1r_fin_constr (aCtx, 5,CTX,DEF); /* finish ctx tag 5 cstr */ + } + + if (info->least_sev_filter != 127 || /* not the defaults */ + info->most_sev_filter != 0) + { + asn1r_strt_constr (aCtx); /* start ctx tag 3 cstr */ + asn1r_wr_u8 (aCtx, info->least_sev_filter); /* write least severe filter */ + asn1r_fin_prim (aCtx, 1,CTX); + + asn1r_wr_u8 (aCtx, info->most_sev_filter); /* write most severe filter */ + asn1r_fin_prim (aCtx, 0,CTX); + asn1r_fin_constr (aCtx, 3,CTX,DEF); /* finish ctx tag 3 cstr */ + } + + if (info->ack_filter != SD_FALSE) + { + asn1r_wr_i16 (aCtx, info->ack_filter); /* write acknowledge filter */ + asn1r_fin_prim (aCtx, 2,CTX); + } + + if (!info->act_alarms_only) + { + asn1r_wr_bool (aCtx, info->act_alarms_only); /* write active alarms only */ + asn1r_fin_prim (aCtx, 1,CTX); + } + + if (!info->enroll_only) + { + asn1r_wr_bool (aCtx, info->enroll_only); /* write enrollments only */ + asn1r_fin_prim (aCtx, 0,CTX); + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_ALARM_SUM,CTX,DEF); /* tag = opcode, context */ + } diff --git a/mmslib/mmsle/rq_getsc.c b/mmslib/mmsle/rq_getsc.c new file mode 100644 index 0000000..ef9299d --- /dev/null +++ b/mmslib/mmsle/rq_getsc.c @@ -0,0 +1,168 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_getscat.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the get scattered */ +/* access attributes. It decodes the get scattered access */ +/* attributes response (confirm) & encodes the get scattered */ +/* access attributes request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETSCAT_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID getscat_scat_acc_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getscat_scat_acc_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getscat_scat_acc_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getscat_get_mms_deletable (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_get_scat_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_get_scat_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Scattered Access Attributes Response"); + +/* get storage for request information */ + rsp_info = (GETSCAT_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (GETSCAT_RESP_INFO)); + ASN1R_TAG_ADD (aCtx, CTX, 0, getscat_get_mms_deletable); + } + +/************************************************************************/ +/* getscat_get_mms_deletable */ +/* Decoding get scattered access attributes response: mms deletable was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID getscat_get_mms_deletable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getscat_get_mms_deletable"); + /* read mms deletable */ + if (asn1r_get_bool (aCtx, &(rsp_info->mms_deletable))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, getscat_scat_acc_cstr); + } + +/************************************************************************/ +/* getscat_scat_acc_cstr */ +/* get scattered access attributes request: scattered access constr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID getscat_scat_acc_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getscat_scat_acc_cstr"); + + _ms_get_va_scat_access (aCtx, &rsp_info->sa_descr, getscat_scat_acc_done); + } + +/************************************************************************/ +/* getscat_scat_acc_done */ +/* get scattered access attributes request: scattered access has been */ +/* decoded. */ +/************************************************************************/ + +static ST_VOID getscat_scat_acc_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getscat_scat_acc_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getscat_scat_acc_cstr_done; + } + +/************************************************************************/ +/* getscat_scat_acc_cstr_done */ +/* get scattered access attributes request: scattered access constr */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID getscat_scat_acc_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getscat */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the get scattered access attributes request */ +/************************************************************************/ + +MMSREQ_PEND *mp_getscat (ST_INT chan, GETSCAT_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_GET_SCAT, + M_CAST_MK_FUN (_ms_mk_getscat_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getscat */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get scattered access attributes request. */ +/************************************************************************/ + +ST_RET mpl_getscat (GETSCAT_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_GET_SCAT, + M_CAST_MK_FUN (_ms_mk_getscat_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getscat_req */ +/* construct a get scattered access attributes request */ +/************************************************************************/ + +ST_VOID _ms_mk_getscat_req (ASN1_ENC_CTXT *aCtx, GETSCAT_REQ_INFO *info) + { + _ms_wr_mms_objname (aCtx, &info->sa_name); /* write scattered access name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_SCAT,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsle/rq_initd.c b/mmslib/mmsle/rq_initd.c new file mode 100644 index 0000000..071323c --- /dev/null +++ b/mmslib/mmsle/rq_initd.c @@ -0,0 +1,146 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_initdown.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of initiate download */ +/* sequence. It decodes the initiate download sequence response */ +/* (confirm) & encodes the initiate download sequence request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 04 Remove "thisFileName" */ +/* 12/20/01 JRB 03 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID init_download_null (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_init_download_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_init_download_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Initiate Download Sequence Response"); + +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + _mms_null_pdu_dec (aCtx); /* IS PDU is NULL */ + else /* DIS */ + { + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Set decode method to TAG */ + ASN1R_TAG_ADD (aCtx, UNI, NULL_CODE, init_download_null); + } + } + +/************************************************************************/ +/* init_download_null */ +/* This function is called from MMSDEC when the NULL contents of this */ +/* response is found. No action required. */ +/************************************************************************/ + +static ST_VOID init_download_null (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("init_download_null"); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_initdown */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the initiate download sequence. */ +/************************************************************************/ + +MMSREQ_PEND *mp_initdown (ST_INT chan, INITDOWN_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_INIT_DOWNLOAD, + M_CAST_MK_FUN (_ms_mk_initdown_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_initdown */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the initiate download sequence. */ +/************************************************************************/ + +ST_RET mpl_initdown (INITDOWN_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_INIT_DOWNLOAD, + M_CAST_MK_FUN (_ms_mk_initdown_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_initdown_req */ +/* ENCODE an initiate download sequence REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_initdown_req (ASN1_ENC_CTXT *aCtx, INITDOWN_REQ_INFO *info) + { +ST_INT16 i; +ST_CHAR **cap_ptr; + + asn1r_wr_bool (aCtx, info->sharable); /* write 'sharable' element */ + asn1r_fin_prim (aCtx, 2,CTX); + +/* Write the list of capabilities */ + + asn1r_strt_constr (aCtx); /* start ctx tag 1 constructor */ + cap_ptr = (ST_CHAR **) (info + 1); + cap_ptr += info->num_of_capab - 1; /* point to last capability */ + for (i = 0; i < info->num_of_capab; i++) + { + asn1r_wr_vstr (aCtx, *cap_ptr); /* write the capability */ + asn1r_fin_prim (aCtx, VISTR_CODE,UNI); /* universal string */ + cap_ptr--; + } + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* ctx tag 1 constructor done */ + + asn1r_wr_vstr (aCtx, info->dname); /* write the domain name */ + asn1r_fin_prim (aCtx, 0,CTX); /* context specific tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_INIT_DOWNLOAD,CTX,DEF); /* tag = opcode, ctx constr */ + } + diff --git a/mmslib/mmsle/rq_initu.c b/mmslib/mmsle/rq_initu.c new file mode 100644 index 0000000..3073c38 --- /dev/null +++ b/mmslib/mmsle/rq_initu.c @@ -0,0 +1,215 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_initupl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of initiate upload */ +/* sequence. It decodes the initiate upload sequence response */ +/* (confirm) & encodes the initiate upload sequence request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +static INITUPL_RESP_INFO *rsp_info; + +static ST_CHAR **cap_ptr; +static ST_INT max_capabilities; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID initupl_get_cap (ASN1_DEC_CTXT *aCtx); +static ST_VOID initupl_cap_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID initupl_cap_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID initupl_get_ulsmid (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_init_upload_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_init_upload_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("Initiate Upload Sequence Response"); + +#if defined(FIXED_DECBUF) + max_capabilities = m_cl_max_initupl_cap; + rsp_size = mmsl_dec_info_size; +#else + max_capabilities = _mmsdec_msglen/2; /* determine maximum size */ + if (m_cl_max_initupl_cap && (max_capabilities > m_cl_max_initupl_cap)) + max_capabilities = m_cl_max_initupl_cap; + rsp_size = sizeof (INITUPL_RESP_INFO) + + (max_capabilities * (sizeof (ST_CHAR *))); +#endif + +/* get storage for request information */ + rsp_info = (INITUPL_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + cap_ptr = (ST_CHAR **) (rsp_info + 1); + ASN1R_TAG_ADD (aCtx, CTX, 0, initupl_get_ulsmid); /* ulsm id is next */ + } + +/************************************************************************/ +/* initupl_get_ulsmid */ +/* initiate upload sequence RESPONSE (confirm) is being decoded: */ +/* decode the upload state machine id. */ +/************************************************************************/ + +static ST_VOID initupl_get_ulsmid (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("initupl_get_ulsmid"); + + if (asn1r_get_i32 (aCtx, &(rsp_info->ulsmid))) /* get upload state machine id */ + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, initupl_cap_cstr); + } + +/************************************************************************/ +/* initupl_cap_cstr */ +/* initiate upload sequence RESPONSE (confirm) is being decoded: */ +/* capability list constructor was encountered. */ +/************************************************************************/ + +static ST_VOID initupl_cap_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("initupl_cap_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, initupl_get_cap); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = initupl_cap_cstr_done; + } + +/************************************************************************/ +/* initupl_get_cap */ +/* initiate upload sequence RESPONSE (confirm) is being decoded: */ +/* capability was encountered. */ +/************************************************************************/ + +static ST_VOID initupl_get_cap (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("initupl_get_cap"); + + rsp_info->num_of_capab++; /* increment # of capabilities */ + if (rsp_info->num_of_capab > max_capabilities) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + /* copy capability back onto itself shifted by one character */ + *cap_ptr = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_vstr (aCtx, *cap_ptr)) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + cap_ptr++; + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, initupl_get_cap); + } + +/************************************************************************/ +/* initupl_cap_cstr_done */ +/* initiate upload sequence RESPONSE (confirm) is being decoded: */ +/* capability list constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID initupl_cap_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + +/* OK to be done, or may have upload detail */ + + /* find actual size for response info */ + rsp_size = sizeof (INITUPL_RESP_INFO) + + (sizeof (ST_CHAR *) * rsp_info->num_of_capab); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,rsp_size); + rsp_info = (INITUPL_RESP_INFO *) _mms_dec_info; + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_initupl */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the initiate upload sequence. */ +/************************************************************************/ + +MMSREQ_PEND *mp_initupl (ST_INT chan, INITUPL_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_INIT_UPLOAD, + M_CAST_MK_FUN (_ms_mk_initupl_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_initupl */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the initiate upload sequence. */ +/************************************************************************/ + +ST_RET mpl_initupl (INITUPL_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_INIT_UPLOAD, + M_CAST_MK_FUN (_ms_mk_initupl_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_initupl_req */ +/* ENCODE an initiate upload sequence REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_initupl_req (ASN1_ENC_CTXT *aCtx, INITUPL_REQ_INFO *info) + { + asn1r_wr_vstr (aCtx, info->dname); /* write the domain name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_INIT_UPLOAD,CTX); /* tag = opcode, context */ + } diff --git a/mmslib/mmsle/rq_input.c b/mmslib/mmsle/rq_input.c new file mode 100644 index 0000000..127b896 --- /dev/null +++ b/mmslib/mmsle/rq_input.c @@ -0,0 +1,146 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_input.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the input */ +/* operation. It decodes the input request (indication) and */ +/* encodes the input response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pocs.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static INPUT_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_input_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_input_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Input Response"); + + +/* get storage for request information */ + rsp_info = (INPUT_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (INPUT_RESP_INFO)); + rsp_info->input_resp = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; /* set ptr to in rsp*/ + if (asn1r_get_vstr (aCtx, rsp_info->input_resp)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_input */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the input request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_input (ST_INT chan, INPUT_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_INPUT, + M_CAST_MK_FUN (_ms_mk_input_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_input */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the input request. */ +/************************************************************************/ + +ST_RET mpl_input (INPUT_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_INPUT, + M_CAST_MK_FUN (_ms_mk_input_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_input_req */ +/* ENCODE an input REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_input_req (ASN1_ENC_CTXT *aCtx, INPUT_REQ_INFO *info) + { +ST_INT i; +ST_CHAR **prompt_data; + + asn1r_strt_constr (aCtx); /* start sequence constructor */ + + if (info->timeout_pres) + { + asn1r_wr_u32 (aCtx, info->timeout); /* write input timeout */ + asn1r_fin_prim (aCtx, 3,CTX); /* context specific tag 3 */ + } + + if (info->prompt_pres) + { + asn1r_strt_constr (aCtx); /* start prompt data list cstr */ + prompt_data = (ST_CHAR **) (info + 1);/* point to first prompt data */ + prompt_data += info->prompt_count -1; /* point to last prompt data */ + for (i = 0; i < info->prompt_count; i++) + { + asn1r_wr_vstr (aCtx, *prompt_data); /* write the prompt data */ + asn1r_fin_prim (aCtx, VISTR_CODE,UNI); /* universal string */ + prompt_data--; + } + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* context specific tag 2 */ + } + + if (!info->echo) + { /* different from default */ + asn1r_wr_bool (aCtx, info->echo); /* write the echo */ + asn1r_fin_prim (aCtx, 1,CTX); /* context tag 1 */ + } + + asn1r_wr_vstr (aCtx, info->station_name); /* write the station name */ + asn1r_fin_prim (aCtx, 0,CTX); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_INPUT,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_jcrea.c b/mmslib/mmsle/rq_jcrea.c new file mode 100644 index 0000000..51c079e --- /dev/null +++ b/mmslib/mmsle/rq_jcrea.c @@ -0,0 +1,97 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_jcreate.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of create journal. */ +/* It decodes the create journal response (confirm) & encodes the */ +/* create journal request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pjou.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_jcreate_rsp */ +/* NOTE : Since the mms_jcreate_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_jcreate */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the create journal request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_jcreate (ST_INT chan, JCREATE_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_CREATE_JOURNAL, + M_CAST_MK_FUN (_ms_mk_jcreate_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_jcreate */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the create journal request. */ +/************************************************************************/ + +ST_RET mpl_jcreate (JCREATE_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_CREATE_JOURNAL, + M_CAST_MK_FUN (_ms_mk_jcreate_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_jcreate_req */ +/* ENCODE a create journal REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_jcreate_req (ASN1_ENC_CTXT *aCtx, JCREATE_REQ_INFO *info) + { + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &info->jou_name); /* write the journal name */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context specific tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_CREATE_JOURNAL,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_jdele.c b/mmslib/mmsle/rq_jdele.c new file mode 100644 index 0000000..b68decf --- /dev/null +++ b/mmslib/mmsle/rq_jdele.c @@ -0,0 +1,97 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_jdelete.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of delete journal. */ +/* It decodes the delete journal response (confirm) & encodes the */ +/* delete journal request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pjou.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_jdelete_rsp */ +/* NOTE : Since the mms_jdelete_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_jdelete */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the delete journal request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_jdelete (ST_INT chan, JDELETE_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_DELETE_JOURNAL, + M_CAST_MK_FUN (_ms_mk_jdelete_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_jdelete */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the delete journal request. */ +/************************************************************************/ + +ST_RET mpl_jdelete (JDELETE_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_DELETE_JOURNAL, + M_CAST_MK_FUN (_ms_mk_jdelete_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_jdelete_req */ +/* ENCODE a delete journal REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_jdelete_req (ASN1_ENC_CTXT *aCtx, JDELETE_REQ_INFO *info) + { + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &info->jou_name); /* write the journal name */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context specific tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DELETE_JOURNAL,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_jinit.c b/mmslib/mmsle/rq_jinit.c new file mode 100644 index 0000000..65841c3 --- /dev/null +++ b/mmslib/mmsle/rq_jinit.c @@ -0,0 +1,130 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_jinit.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requestor portion of initialize */ +/* journal. It decodes the initialize journal response (confirm) */ +/* and encodes the initialize journal request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 08/15/97 MDE 02 BTOD handling changes */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pjou.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static JINIT_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_jinit_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_jinit_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Initialize Journal Response"); + + +/* get storage for request information */ + rsp_info = (JINIT_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (JINIT_RESP_INFO)); + if (asn1r_get_u32 (aCtx, &rsp_info->del_entries)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_jinit */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the initialize journal request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_jinit (ST_INT chan, JINIT_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_INIT_JOURNAL, + M_CAST_MK_FUN (_ms_mk_jinit_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_jinit */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the initialize journal request. */ +/************************************************************************/ + +ST_RET mpl_jinit (JINIT_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_INIT_JOURNAL, + M_CAST_MK_FUN (_ms_mk_jinit_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_jinit_req */ +/* ENCODE an initialize journal REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_jinit_req (ASN1_ENC_CTXT *aCtx, JINIT_REQ_INFO *info) + { + + if (info->limit_spec_pres) + { /* write limit specification */ + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + if (info->limit_entry_pres) + { /* write limiting entry */ + asn1r_wr_octstr (aCtx, info->limit_entry, info->limit_entry_len); + asn1r_fin_prim (aCtx, 1,CTX); + } + asn1r_wr_btod (aCtx, &info->limit_time); + asn1r_fin_prim (aCtx, 0,CTX); + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish context tag 1 cstr */ + } + + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + _ms_wr_mms_objname (aCtx, &info->jou_name); /* write the journal name */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish context tag 0 cstr */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_INIT_JOURNAL,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_jread.c b/mmslib/mmsle/rq_jread.c new file mode 100644 index 0000000..d95998f --- /dev/null +++ b/mmslib/mmsle/rq_jread.c @@ -0,0 +1,431 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_jread.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of read journal. */ +/* It decodes the read journal response (confirm) & encodes the */ +/* read journal request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 08/28/03 EJV 06 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 08/15/97 MDE 01 BTOD handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pjou.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static JREAD_RESP_INFO *rsp_info; + +static JOURNAL_ENTRY *je_ptr; +static ST_INT max_jou_ent; +static ST_INT max_ec_vars; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID jread_get_orig_ae (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_jou_entry_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_get_more_follows (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_jou_entry_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_ec_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_ec_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_orig_ae_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_orig_ae_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_entry_id_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_entry_id_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_entry_id_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_list_of_je_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_list_of_je_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_jread_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_jread_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("Read Journal Response"); + +#if defined(FIXED_DECBUF) + max_jou_ent = m_cl_max_journal_entries; + max_ec_vars = m_cl_max_entry_content; + rsp_size = mmsl_dec_info_size; +#else +/* determine maximum storage - this over-estimates the maximum */ +/* required storage, storage for the maximum number of journal */ +/* entries would be sufficient. */ + max_jou_ent = _mmsdec_msglen/10; + max_ec_vars = _mmsdec_msglen/4; + + if (m_cl_max_journal_entries && (max_jou_ent > m_cl_max_journal_entries)) + max_jou_ent = m_cl_max_journal_entries; + if (m_cl_max_entry_content && (max_ec_vars > m_cl_max_entry_content)) + max_ec_vars = m_cl_max_entry_content; + rsp_size = sizeof (JREAD_RESP_INFO) + + (sizeof (JOURNAL_ENTRY) * max_jou_ent) + + (sizeof (VAR_INFO) * max_ec_vars); +#endif + +/* get storage for request information */ + rsp_info = (JREAD_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + je_ptr = (JOURNAL_ENTRY *) (rsp_info + 1); + rsp_info->more_follows = SD_FALSE; /* set default value */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, jread_list_of_je_cstr); + } + +/************************************************************************/ +/* jread_list_of_je_cstr */ +/* read journal RESPONSE (confirm) is being decoded: list of journal */ +/* entry constructor was encountered. */ +/************************************************************************/ + +static ST_VOID jread_list_of_je_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_list_of_je_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, jread_jou_entry_cstr); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jread_list_of_je_cstr_done; + } + +/************************************************************************/ +/* jread_jou_entry_cstr */ +/* read journal response is being decoded: journal entry cstr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jread_jou_entry_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_jou_entry_cstr"); + + rsp_info->num_of_jou_entry++; /* increment # of journal entry */ + if (rsp_info->num_of_jou_entry > max_jou_ent) + { + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 0, jread_entry_id_prim); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, jread_entry_id_cstr); + } + +/************************************************************************/ +/* jread_entry_id_prim */ +/* read journal response is being decoded: entry id primitive was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jread_entry_id_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_entry_id_prim"); + + /* decode entry id back onto itself */ + je_ptr->entry_id = aCtx->asn1r_field_ptr; + + if (asn1r_get_octstr (aCtx, je_ptr->entry_id)) /* read entry id */ + asn1r_set_dec_err (aCtx, RESP_UNSPECIFIED); + + je_ptr->entry_id_len = aCtx->asn1r_octetcount; + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, jread_get_orig_ae); + } + +/************************************************************************/ +/* jread_entry_id_cstr */ +/* read journal response is being decoded: entry id constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jread_entry_id_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_entry_id_cstr"); + + /* decode entry id back onto itself */ + je_ptr->entry_id = aCtx->asn1r_field_ptr; + + /* set up done decoding octet cstr destination */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jread_entry_id_cstr_done; + + /* get entry id from the received message */ + /* set maximum length to accept entire message */ + asn1r_get_octstr_cstr (aCtx, _mmsdec_msglen, je_ptr->entry_id); + } + +/************************************************************************/ +/* jread_entry_id_cstr_done */ +/* read journal response is being decoded: entry id constructor done */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jread_entry_id_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + je_ptr->entry_id_len = aCtx->asn1r_octetcount; /* save entry id len */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, jread_get_orig_ae); + } + +/************************************************************************/ +/* jread_get_orig_ae */ +/* read journal response is being decoded: originating ae cstr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jread_get_orig_ae (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_get_orig_ae"); + + _ms_get_mms_app_ref (aCtx, &je_ptr->orig_ae, &je_ptr->orig_ae_len, jread_orig_ae_done); + } + +/************************************************************************/ +/* jread_orig_ae_done */ +/* read journal response is being decoded: originating ae cstr done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jread_orig_ae_done (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = jread_orig_ae_cstr_done; + } + +/************************************************************************/ +/* jread_orig_ae_cstr_done */ +/* read journal response is being decoded: originating ae cstr done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jread_orig_ae_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, jread_ec_cstr); + } + +/************************************************************************/ +/* jread_ec_cstr */ +/* read journal response is being decoded: entry content constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jread_ec_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_ec_cstr"); + + _ms_get_jou_ent_cont (aCtx, &je_ptr->ent_content, max_ec_vars, jread_ec_done); + } + +/************************************************************************/ +/* jread_ec_done */ +/* read journal response is being decoded: entry content has been */ +/* obtained. */ +/************************************************************************/ + +static ST_VOID jread_ec_done (ASN1_DEC_CTXT *aCtx) + { +VAR_INFO *vi_ptr; + + MLOG_CDEC0 ("jread_ec_done"); + + /* point to where next will go */ + if (je_ptr->ent_content.entry_form_tag == 2 && + je_ptr->ent_content.ef.data.list_of_var_pres) + { + vi_ptr = (VAR_INFO *) (je_ptr + 1); + je_ptr = (JOURNAL_ENTRY *) + (vi_ptr + je_ptr->ent_content.ef.data.num_of_var); + } + else + je_ptr++; + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jread_jou_entry_cstr_done; + } + +/************************************************************************/ +/* jread_jou_entry_cstr_done */ +/* read journal response is being decoded: journal entry constructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID jread_jou_entry_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, jread_jou_entry_cstr); + } + +/************************************************************************/ +/* jread_list_of_je_cstr_done */ +/* read journal response is being decoded: list of journal entry cstr */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID jread_list_of_je_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + ASN1R_TAG_ADD (aCtx, CTX, 1, jread_get_more_follows); + /* find actual size for response info */ + rsp_size = (char *) je_ptr - (char *) rsp_info; + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,rsp_size); + rsp_info = (JREAD_RESP_INFO *) _mms_dec_info; + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* jread_get_more_follows */ +/* read journal response is being decoded: more follows indicator */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jread_get_more_follows (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_get_more_follows"); + + if (asn1r_get_bool (aCtx, &rsp_info->more_follows)) /* read more follows */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_jread */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the read journal request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_jread (ST_INT chan, JREAD_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_READ_JOURNAL, + M_CAST_MK_FUN (_ms_mk_jread_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_jread */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the read journal request. */ +/************************************************************************/ + +ST_RET mpl_jread (JREAD_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_READ_JOURNAL, + M_CAST_MK_FUN (_ms_mk_jread_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_jread_req */ +/* ENCODE a read journal REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_jread_req (ASN1_ENC_CTXT *aCtx, JREAD_REQ_INFO *info) + { +ST_INT i; +ST_CHAR **var_ptr; + + asn1r_strt_constr (aCtx); /* start sequence constructor */ + + if (info->sa_entry_pres) + { /* write start after entry */ + asn1r_strt_constr (aCtx); /* start context tag 5 cstr */ + asn1r_wr_octstr (aCtx, info->entry_spec, info->entry_spec_len); + asn1r_fin_prim (aCtx, 1,CTX); + asn1r_wr_btod (aCtx, &info->time_spec); + asn1r_fin_prim (aCtx, 0,CTX); + asn1r_fin_constr (aCtx, 5,CTX,DEF); /* finish context tag 5 cstr */ + } + + if (info->list_of_var_pres) + { /* write list of variables */ + asn1r_strt_constr (aCtx); /* start context tag 4 cstr */ + var_ptr = (ST_CHAR **) (info + 1); + var_ptr += info->num_of_var - 1; /* point to last entry */ + for (i = 0; i < info->num_of_var; i++) + { + asn1r_wr_vstr (aCtx, *var_ptr); /* write the variable */ + asn1r_fin_prim (aCtx, VISTR_CODE,UNI); /* universal string */ + var_ptr--; + } + asn1r_fin_constr (aCtx, 4,CTX,DEF); /* finish context tag 4 cstr */ + } + + if (info->range_stop_pres) + { /* write range stop */ + asn1r_strt_constr (aCtx); /* start context tag 2 cstr */ + if (info->stop_tag == SD_TRUE) + { /* write the number of entries */ + asn1r_wr_i32 (aCtx, info->num_of_entries); + asn1r_fin_prim (aCtx, 1,CTX); + } + else + { /* write the ending time */ + asn1r_wr_btod (aCtx, &info->end_time); + asn1r_fin_prim (aCtx, 0,CTX); + } + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* finish context tag 2 cstr */ + } + + if (info->range_start_pres) + { /* write range start */ + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + if (info->start_tag == 1) + { /* write the starting entry */ + asn1r_wr_octstr (aCtx, info->start_entry, info->start_entry_len); + asn1r_fin_prim (aCtx, 1,CTX); + } + else + { /* write the starting time */ + asn1r_wr_btod (aCtx, &info->start_time); + asn1r_fin_prim (aCtx, 0,CTX); + } + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish context tag 1 cstr */ + } + + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + _ms_wr_mms_objname (aCtx, &info->jou_name); /* write the journal name */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish context tag 0 cstr */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_READ_JOURNAL,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_jstat.c b/mmslib/mmsle/rq_jstat.c new file mode 100644 index 0000000..1a81fdb --- /dev/null +++ b/mmslib/mmsle/rq_jstat.c @@ -0,0 +1,144 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_jstat.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requestor portion of report journal */ +/* status. It decodes the report journal status response (confirm) */ +/* and encodes the report journal status request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pjou.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static JSTAT_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID jstat_get_deletable (ASN1_DEC_CTXT *aCtx); +static ST_VOID jstat_get_cur_entries (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_jstat_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_jstat_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Report Journal Status Response"); + +/* get storage for request information */ + rsp_info = (JSTAT_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (JSTAT_RESP_INFO)); + + ASN1R_TAG_ADD (aCtx, CTX, 0, jstat_get_cur_entries); + } + +/************************************************************************/ +/* jstat_get_cur_entries */ +/* report journal status response is being decoded: current entries */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jstat_get_cur_entries (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Report journal status response"); + + if (asn1r_get_u32 (aCtx, &rsp_info->cur_entries)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 1, jstat_get_deletable); /* deletable is next */ + } + +/************************************************************************/ +/* jstat_get_deletable */ +/* report journal status response is being decoded: current entries */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jstat_get_deletable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jstat_get_deletable"); + + if (asn1r_get_bool (aCtx, &rsp_info->mms_deletable)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_jstat */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the report journal status request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_jstat (ST_INT chan, JSTAT_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_STAT_JOURNAL, + M_CAST_MK_FUN (_ms_mk_jstat_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_jstat */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the report journal status request. */ +/************************************************************************/ + +ST_RET mpl_jstat (JSTAT_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_STAT_JOURNAL, + M_CAST_MK_FUN (_ms_mk_jstat_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_jstat_req */ +/* ENCODE a report journal status REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_jstat_req (ASN1_ENC_CTXT *aCtx, JSTAT_REQ_INFO *info) + { + _ms_wr_mms_objname (aCtx, &info->jou_name); /* write the journal name */ +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_STAT_JOURNAL,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_jwrit.c b/mmslib/mmsle/rq_jwrit.c new file mode 100644 index 0000000..48b1e74 --- /dev/null +++ b/mmslib/mmsle/rq_jwrit.c @@ -0,0 +1,144 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_jwrite.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of write journal. */ +/* It decodes the write journal response (confirm) & encodes the */ +/* write journal request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 03 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pjou.h" +#include "asn1defs.h" +#include "mem_chk.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_jwrite_rsp */ +/* NOTE : Since the mms_jwrite_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_jwrite */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the write journal request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_jwrite (ST_INT chan, JWRITE_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_WRITE_JOURNAL, + M_CAST_MK_FUN (_ms_mk_jwrite_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_jwrite */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the write journal request. */ +/************************************************************************/ + +ST_RET mpl_jwrite (JWRITE_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_WRITE_JOURNAL, + M_CAST_MK_FUN (_ms_mk_jwrite_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_jwrite_req */ +/* ENCODE a write journal REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_jwrite_req (ASN1_ENC_CTXT *aCtx, JWRITE_REQ_INFO *info) + { +ST_INT i; +ENTRY_CONTENT **ec_list; +ENTRY_CONTENT *ec_ptr; +VAR_INFO *vi_ptr; +ST_INT ecl_size; + + ecl_size = sizeof (ENTRY_CONTENT *) * info->num_of_jou_entry; + ec_list = (ENTRY_CONTENT **) chk_calloc (1, ecl_size); + + /* find first entry content */ + ec_ptr = (ENTRY_CONTENT *) (info + 1); + for (i = 0; i < info->num_of_jou_entry; i++) + { /* find ptrs to entry contents */ + /* if variable list follows */ + *(ec_list++) = ec_ptr; + if (ec_ptr->entry_form_tag == 2 && ec_ptr->ef.data.list_of_var_pres) + { + vi_ptr = (VAR_INFO *) (ec_ptr + 1); + vi_ptr += ec_ptr->ef.data.num_of_var; + ec_ptr = (ENTRY_CONTENT *) vi_ptr; + } + else + ec_ptr++; /* annoatation or no var list */ + + } + + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + for (i = 0; i < info->num_of_jou_entry; i++) + { + ec_ptr = *(--ec_list); + asn1r_strt_constr (aCtx); /* start universal seq cstr */ + _ms_wr_jou_ent_cont (aCtx, ec_ptr); /* write the entry content */ + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish universal seq cstr */ + } + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish context tag 1 cstr */ + chk_free (ec_list); + + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &info->jou_name); /* write the journal name */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context specific tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_WRITE_JOURNAL,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_kill.c b/mmslib/mmsle/rq_kill.c new file mode 100644 index 0000000..1be3e00 --- /dev/null +++ b/mmslib/mmsle/rq_kill.c @@ -0,0 +1,96 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_kill.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the kill */ +/* operation. It decodes the kill response (confirm) & encodes */ +/* the kill request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_kill_rsp */ +/* NOTE : Since the mms_kill_rsp is a NULL PDU, the decode is continued */ +/* by '_mms_null_pdu_dec', which simply sets decode done = 1 and sets */ +/* the decode done function to point to the general decode done fun */ +/* See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_kill */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the kill request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_kill (ST_INT chan, KILL_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_KILL, + M_CAST_MK_FUN (_ms_mk_kill_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_kill */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the kill request. */ +/************************************************************************/ + +ST_RET mpl_kill (KILL_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_KILL, + M_CAST_MK_FUN (_ms_mk_kill_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_kill_req */ +/* Construct a kill request */ +/************************************************************************/ + +ST_VOID _ms_mk_kill_req (ASN1_ENC_CTXT *aCtx, KILL_REQ_INFO *info) + { + asn1r_wr_vstr (aCtx, info->piname); /* write pgm invocation name */ + asn1r_fin_prim (aCtx, 0, CTX); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_KILL,CTX,DEF); /* tag = opcode, ctx cstr */ + } diff --git a/mmslib/mmsle/rq_loadd.c b/mmslib/mmsle/rq_loadd.c new file mode 100644 index 0000000..97587ac --- /dev/null +++ b/mmslib/mmsle/rq_loadd.c @@ -0,0 +1,126 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_loaddom.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of load domain */ +/* content. It decodes the load domain content response (confirm) */ +/* & encodes the load domain content request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/* variables global to the DECODE portion : NONE */ + +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_load_domain_rsp */ +/* NOTE : Since the mms_load_domain_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_loaddom */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the load domain content request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_loaddom (ST_INT chan, LOADDOM_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_LOAD_DOMAIN, + M_CAST_MK_FUN (_ms_mk_loaddom_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_loaddom */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the load domain content request. */ +/************************************************************************/ + +ST_RET mpl_loaddom (LOADDOM_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_LOAD_DOMAIN, + M_CAST_MK_FUN (_ms_mk_loaddom_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_loaddom_req */ +/* ENCODE a load domain content REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_loaddom_req (ASN1_ENC_CTXT *aCtx, LOADDOM_REQ_INFO *info) + { +ST_INT i; +ST_CHAR **cap_ptr; +FILE_NAME *fname_idx; + + if (info->third_pty_pres) + { + asn1r_wr_delmnt (aCtx, info->third_pty, info->third_pty_len); + *(aCtx->asn1r_field_ptr+1) = (ST_UCHAR) 0xA5; + } + + asn1r_strt_constr (aCtx); + cap_ptr = (ST_CHAR **) (info + 1); + cap_ptr += info->num_of_capab; /* point to first file_name */ + fname_idx = (FILE_NAME *)cap_ptr; + _ms_wr_mms_fname (aCtx, fname_idx, info -> num_of_fname); + asn1r_fin_constr (aCtx, 4,CTX,DEF); /* context specific tag 4 */ + + asn1r_wr_bool (aCtx, info->sharable); /* write the sharable flag */ + asn1r_fin_prim (aCtx, 2,CTX); /* context specific tag 2 */ + + asn1r_strt_constr (aCtx); /* start ctx tag 1 constructor */ + cap_ptr--; /* point to last capability */ + for (i = 0; i < info->num_of_capab; i++) + { + asn1r_wr_vstr (aCtx, *cap_ptr); /* write the capability */ + asn1r_fin_prim (aCtx, VISTR_CODE,UNI); /* universal string */ + cap_ptr--; + } + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* ctx tag 1 constructor done */ + + asn1r_wr_vstr (aCtx, info->dname); /* write the domain name */ + asn1r_fin_prim (aCtx, 0,CTX); /* context specific tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_LOAD_DOMAIN,CTX,DEF); /* tag = opcode, ctx constr */ + } + diff --git a/mmslib/mmsle/rq_obtfi.c b/mmslib/mmsle/rq_obtfi.c new file mode 100644 index 0000000..76687f5 --- /dev/null +++ b/mmslib/mmsle/rq_obtfi.c @@ -0,0 +1,115 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_obtfile.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the obtain file. */ +/* It decodes the obtain file response (confirm) & encodes the */ +/* obtain file request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_obtain_file_rsp */ +/* NOTE : Since the mms_obtain_file_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_obtfile */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the obtain file request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_obtfile (ST_INT chan, OBTFILE_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_OBTAIN_FILE, + M_CAST_MK_FUN (_ms_mk_obtfile_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_obtfile */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the obtain file request. */ +/************************************************************************/ + +ST_RET mpl_obtfile (OBTFILE_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_OBTAIN_FILE, + M_CAST_MK_FUN (_ms_mk_obtfile_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_obtfile_req */ +/* construct an obtain file request */ +/************************************************************************/ + +ST_VOID _ms_mk_obtfile_req (ASN1_ENC_CTXT *aCtx, OBTFILE_REQ_INFO *info) + { +FILE_NAME *fname_idx; + + /* write the destinaion file */ + asn1r_strt_constr (aCtx); + fname_idx = (FILE_NAME *)(info + 1); + fname_idx += info->num_of_src_fname; + _ms_wr_mms_fname (aCtx, fname_idx, info->num_of_dest_fname); + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* context specific tag 2 */ + + /* write the source file */ + asn1r_strt_constr (aCtx); + fname_idx = (FILE_NAME *)(info + 1); + _ms_wr_mms_fname (aCtx, fname_idx, info->num_of_src_fname); + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* context specific tag 1 */ + + if (info->ar_title_pres) + { + asn1r_wr_delmnt (aCtx, info->ar_title, info->ar_len); + *(aCtx->asn1r_field_ptr+1) = (ST_UCHAR) 0xA0; + } + +/* Obtain file request contents complete, finish the sequence by */ +/* writing the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_OBTAIN_FILE,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_outpu.c b/mmslib/mmsle/rq_outpu.c new file mode 100644 index 0000000..aec9c61 --- /dev/null +++ b/mmslib/mmsle/rq_outpu.c @@ -0,0 +1,110 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_output.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the output */ +/* operation. It decodes the output response (confirm) & encodes */ +/* the output request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pocs.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_output_rsp */ +/* NOTE : Since the mms_output_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_output */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the output request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_output (ST_INT chan, OUTPUT_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_OUTPUT, + M_CAST_MK_FUN (_ms_mk_output_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_output */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the output request. */ +/************************************************************************/ + +ST_RET mpl_output (OUTPUT_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_OUTPUT, + M_CAST_MK_FUN (_ms_mk_output_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_output_req */ +/* construct an output request */ +/************************************************************************/ + +ST_VOID _ms_mk_output_req (ASN1_ENC_CTXT *aCtx, OUTPUT_REQ_INFO *info) + { +ST_INT i; +ST_CHAR **output_data; + + asn1r_strt_constr (aCtx); /* start sequence constr */ + output_data = (ST_CHAR **) (info + 1); /* point to first output string */ + output_data += info->data_count - 1; /* point to last output string */ + for (i = 0; i < info->data_count; i++) + { + asn1r_wr_vstr (aCtx, *output_data); /* write the output data */ + asn1r_fin_prim (aCtx, VISTR_CODE,UNI); /* universal string */ + output_data--; /* point to previous string */ + } + asn1r_fin_constr (aCtx, 1, CTX, DEF); /* context tag 1 */ + + asn1r_wr_vstr (aCtx, info->station_name); /* write the station name */ + asn1r_fin_prim (aCtx, 0,CTX); /* universal string */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_OUTPUT,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_rddwn.c b/mmslib/mmsle/rq_rddwn.c new file mode 100644 index 0000000..367c0f4 --- /dev/null +++ b/mmslib/mmsle/rq_rddwn.c @@ -0,0 +1,121 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_rddwn.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of request domain */ +/* download. It decodes the request domain download response */ +/* (confirm) & encodes the request domain download request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_rddwn_rsp */ +/* NOTE : Since the mms_rddwn_rsp is a NULL PDU, the decode is continued*/ +/* by '_mms_null_pdu_dec', which simply sets decode done = 1 and sets the*/ +/* decode done function to point to the general decode done fun. See */ +/* mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_rddwn */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the request domain download request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_rddwn (ST_INT chan, RDDWN_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_REQ_DOM_DOWN, + M_CAST_MK_FUN (_ms_mk_rddwn_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_rddwn */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the request domain download request. */ +/************************************************************************/ + +ST_RET mpl_rddwn (RDDWN_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_REQ_DOM_DOWN, + M_CAST_MK_FUN (_ms_mk_rddwn_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_rddwn_req */ +/* ENCODE a request domain download REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_rddwn_req (ASN1_ENC_CTXT *aCtx, RDDWN_REQ_INFO *info) + { +ST_INT i; +ST_CHAR **cap_ptr; +FILE_NAME *fname_idx; + + asn1r_strt_constr (aCtx); + cap_ptr = (ST_CHAR **) (info + 1); + cap_ptr += info->num_of_capab; /* point to first file_name */ + fname_idx = (FILE_NAME *)(cap_ptr); + _ms_wr_mms_fname (aCtx, fname_idx, info->num_of_fname); + asn1r_fin_constr (aCtx, 4,CTX,DEF); /* context specific tag 4 */ + + asn1r_wr_bool (aCtx, info->sharable); /* write 'sharable' element */ + asn1r_fin_prim (aCtx, 2,CTX); + +/* Write the list of capabilities */ + + asn1r_strt_constr (aCtx); /* start ctx tag 1 constructor */ + cap_ptr--; /* point to last capability */ + for (i = 0; i < info->num_of_capab; i++) + { + asn1r_wr_vstr (aCtx, *cap_ptr); /* write the capability */ + asn1r_fin_prim (aCtx, VISTR_CODE,UNI); /* universal string */ + cap_ptr--; + } + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* ctx tag 1 constructor done */ + + asn1r_wr_vstr (aCtx, info->dname); /* write the domain name */ + asn1r_fin_prim (aCtx, 0,CTX); /* context specific tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_REQ_DOM_DOWN,CTX,DEF); /* tag = opcode, ctx constr */ + } + diff --git a/mmslib/mmsle/rq_rdupl.c b/mmslib/mmsle/rq_rdupl.c new file mode 100644 index 0000000..e4fadd4 --- /dev/null +++ b/mmslib/mmsle/rq_rdupl.c @@ -0,0 +1,100 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_rdupl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of request domain */ +/* upload. It decodes the request domain upload response */ +/* (confirm) & encodes the request domain upload request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_rdupl_rsp */ +/* NOTE : Since the mms_rdupl_rsp is a NULL PDU, the decode is continued*/ +/* by '_mms_null_pdu_dec', which simply sets decode done = 1 and sets the*/ +/* decode done function to point to the general decode done fun. See */ +/* mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_rdupl */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the request domain upload request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_rdupl (ST_INT chan, RDUPL_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_REQ_DOM_UPL, + M_CAST_MK_FUN (_ms_mk_rdupl_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_rdupl */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the request domain upload request. */ +/************************************************************************/ + +ST_RET mpl_rdupl (RDUPL_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_REQ_DOM_UPL, + M_CAST_MK_FUN (_ms_mk_rdupl_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_rdupl_req */ +/* ENCODE a request domain upload REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_rdupl_req (ASN1_ENC_CTXT *aCtx, RDUPL_REQ_INFO *info) + { + asn1r_strt_constr (aCtx); + _ms_wr_mms_fname (aCtx, (FILE_NAME *)(info + 1), + info->num_of_fname); + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* context specific tag 1 */ + + asn1r_wr_vstr (aCtx, info->dname); /* write the domain name */ + asn1r_fin_prim (aCtx, 0,CTX); /* context specific tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_REQ_DOM_UPL,CTX,DEF); /* tag = opcode, ctx constr */ + } + diff --git a/mmslib/mmsle/rq_relct.c b/mmslib/mmsle/rq_relct.c new file mode 100644 index 0000000..de7955e --- /dev/null +++ b/mmslib/mmsle/rq_relct.c @@ -0,0 +1,108 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_relctrl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of relinquish */ +/* semaphore control. It decodes the relinquish control response */ +/* (confirm) & encodes the relinguish control request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_psem.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_relctrl_rsp */ +/* NOTE : Since the mms_relctrl_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_relctrl */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the relinquish control request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_relctrl (ST_INT chan, RELCTRL_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_REL_CONTROL, + M_CAST_MK_FUN (_ms_mk_relctrl_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_relctrl */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the relinquish control request. */ +/************************************************************************/ + +ST_RET mpl_relctrl (RELCTRL_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_REL_CONTROL, + M_CAST_MK_FUN (_ms_mk_relctrl_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_relctrl_req */ +/* construct a relinquish control request */ +/************************************************************************/ + +ST_VOID _ms_mk_relctrl_req (ASN1_ENC_CTXT *aCtx, RELCTRL_REQ_INFO *info) + { + + asn1r_strt_constr (aCtx); /* start sequence constr */ + + if (info->named_token_pres) + { + asn1r_wr_vstr (aCtx, info->named_token); /* write the named token */ + asn1r_fin_prim (aCtx, 1, CTX); /* context tag 1 */ + } + + asn1r_strt_constr (aCtx); /* object name constructor */ + + _ms_wr_mms_objname (aCtx, &info->sem_name); /* write the object name */ + + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_REL_CONTROL,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_renam.c b/mmslib/mmsle/rq_renam.c new file mode 100644 index 0000000..e4abcc9 --- /dev/null +++ b/mmslib/mmsle/rq_renam.c @@ -0,0 +1,120 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_rename.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the rename */ +/* service. It decodes the rename response (indication) and */ +/* encodes the rename request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_rename_rsp */ +/* NOTE : Since the mms_rename_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_rename */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send a rename REQUEST: */ +/************************************************************************/ + +MMSREQ_PEND *mp_rename (ST_INT chan, RENAME_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_RENAME, + M_CAST_MK_FUN (_ms_mk_rename_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_rename */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE a rename REQUEST: */ +/************************************************************************/ + +ST_RET mpl_rename (RENAME_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_RENAME, + M_CAST_MK_FUN (_ms_mk_rename_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_rename_req */ +/* ENCODE a rename REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_rename_req (ASN1_ENC_CTXT *aCtx, RENAME_REQ_INFO *info_ptr) + { + asn1r_wr_vstr (aCtx, info_ptr->new_ident); /* write the new identifier */ + asn1r_fin_prim (aCtx, 2,CTX); /* context specific tag 2 */ + + asn1r_strt_constr (aCtx); /* start ctx tag 1 constructor */ + _ms_wr_mms_objname (aCtx, &info_ptr->cur_name); /* write the current name */ + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* context specific tag 1 */ + + asn1r_strt_constr (aCtx); /* start extendedObjectClass */ +#ifdef CS_SUPPORT + if (info_ptr->cs_objclass_pres) /* if companion standard */ + { + asn1r_strt_constr (aCtx); /* start cs ObjectClass cstr */ + asn1r_wr_octstr (aCtx, info_ptr->obj.cs.cs_class,info_ptr->obj.cs.len); + asn1r_fin_constr (aCtx, 1,CTX,DEF); + } + else + { + asn1r_wr_i16 (aCtx, info_ptr->obj.mms_class); /* write the object scope */ + asn1r_fin_prim (aCtx, 0,CTX); + } +#else + asn1r_wr_i16 (aCtx, info_ptr->obj.mms_class); /* write the object scope */ + asn1r_fin_prim (aCtx, 0,CTX); +#endif + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish the extendedObjClass */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_RENAME,CTX,DEF); /* complete rename req */ + } diff --git a/mmslib/mmsle/rq_reset.c b/mmslib/mmsle/rq_reset.c new file mode 100644 index 0000000..225a8be --- /dev/null +++ b/mmslib/mmsle/rq_reset.c @@ -0,0 +1,96 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_reset.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the reset */ +/* operation. It decodes the reset response (confirm) & encodes */ +/* the reset request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_reset_rsp */ +/* NOTE: Since the mms_reset_ rsp is a NULL PDU, the decode is continued*/ +/* by '_mms_null_pdu_dec', which simply sets decode done = 1 and sets */ +/* the decode done function to point to the general decode done fun */ +/* See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_reset */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the reset request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_reset (ST_INT chan, RESET_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_RESET, + M_CAST_MK_FUN (_ms_mk_reset_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_reset */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the reset request. */ +/************************************************************************/ + +ST_RET mpl_reset (RESET_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_RESET, + M_CAST_MK_FUN (_ms_mk_reset_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_reset_req */ +/* construct a reset request */ +/************************************************************************/ + +ST_VOID _ms_mk_reset_req (ASN1_ENC_CTXT *aCtx, RESET_REQ_INFO *info) + { + asn1r_wr_vstr (aCtx, info->piname); /* write pgm invocation name */ + asn1r_fin_prim (aCtx, 0, CTX); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_RESET,CTX,DEF); /* tag = opcode, ctx cstr */ + } diff --git a/mmslib/mmsle/rq_resum.c b/mmslib/mmsle/rq_resum.c new file mode 100644 index 0000000..bd92ad2 --- /dev/null +++ b/mmslib/mmsle/rq_resum.c @@ -0,0 +1,107 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_resume.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the resume */ +/* operation. It decodes the resume response (confirm) & encodes */ +/* the resume request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_resume_rsp */ +/* NOTE: Since the mms_resume_rsp is a NULL PDU, the decode is continued*/ +/* by '_mms_null_pdu_dec', which simply sets decode done = 1 and sets */ +/* the decode done function to point to the general decode done fun */ +/* See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_resume */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the resume request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_resume (ST_INT chan, RESUME_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_RESUME, + M_CAST_MK_FUN (_ms_mk_resume_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_resume */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the resume request. */ +/************************************************************************/ + +ST_RET mpl_resume (RESUME_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_RESUME, + M_CAST_MK_FUN (_ms_mk_resume_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_resume_req */ +/* construct a resume request */ +/************************************************************************/ + +ST_VOID _ms_mk_resume_req (ASN1_ENC_CTXT *aCtx, RESUME_REQ_INFO *info) + { + if (info->resume_arg_pres) + { + if (info->resume_arg_type == ARG_TYPE_SIMPLE) + { + asn1r_wr_vstr (aCtx, (ST_CHAR *)info->resume_arg); /* write the resume argument */ + asn1r_fin_prim (aCtx, 1, CTX); /* context tag 1 */ + } + else /* ENCODED data, write as complete ASN.1 EXTERNAL */ + asn1r_wr_delmnt (aCtx, info->resume_arg,info->resume_arg_len); + } + + asn1r_wr_vstr (aCtx, info->piname); /* write pgm invocation name */ + asn1r_fin_prim (aCtx, 0, CTX); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_RESUME,CTX,DEF); /* tag = opcode, ctx cstr */ + } diff --git a/mmslib/mmsle/rq_rsent.c b/mmslib/mmsle/rq_rsent.c new file mode 100644 index 0000000..8872b37 --- /dev/null +++ b/mmslib/mmsle/rq_rsent.c @@ -0,0 +1,457 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_rsentry.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of report semaphore */ +/* entry status. It decodes the report semaphore entry status */ +/* response (confirm) & encodes the report semaphore entry status */ +/* request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 08/28/03 EJV 05 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_psem.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static RSENTRY_RESP_INFO *rsp_info; + +static SEMAPHORE_ENTRY *sent_ptr; +static ST_INT max_sem_entries; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID rsentry_get_entry_class (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_app_ref_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_get_priority (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_get_rem_timeout (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_get_abrt_timeout (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_get_rel_conn_lost (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_entry_seq_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_get_named_token (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_entry_seq_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID app_ref_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID app_ref_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_entry_id_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_get_entry_id (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_entry_id_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_sem_entry_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_sem_entry_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_get_more_follows (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_rsentry_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_rsentry_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("Report Semaphore Entry Status Response"); + +#if defined(FIXED_DECBUF) + max_sem_entries = m_cl_max_semaphore_entries; + rsp_size = mmsl_dec_info_size; +#else + max_sem_entries = _mmsdec_msglen / 6; /* find maximum size of response info */ + if (m_cl_max_semaphore_entries && (max_sem_entries > m_cl_max_semaphore_entries)) + max_sem_entries = m_cl_max_semaphore_entries; + rsp_size = sizeof (RSENTRY_RESP_INFO) + + (sizeof (SEMAPHORE_ENTRY) * max_sem_entries); +#endif + +/* get storage for request information */ + rsp_info = (RSENTRY_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + sent_ptr = (SEMAPHORE_ENTRY *) (rsp_info + 1); + + rsp_info->more_follows = SD_TRUE;/* set default value for more follows */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, rsentry_sem_entry_cstr); + } + +/************************************************************************/ +/* rsentry_sem_entry_cstr */ +/* Decoding report semaphore entry status request: semaphore entry list */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_sem_entry_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsentry_sem_entry_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, rsentry_entry_seq_cstr); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = rsentry_sem_entry_cstr_done; + } + +/************************************************************************/ +/* rsentry_entry_seq_cstr */ +/* Decoding report semaphore entry status request: semaphore entry */ +/* sequence constructor was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_entry_seq_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsentry_entry_seq_cstr"); + + rsp_info->num_of_sent++; /* increment number of entries */ + if (rsp_info->num_of_sent > max_sem_entries) + { /* too many semaphore entries */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + sent_ptr->priority = MMS_NORM_PRIORITY; /* set defaults */ + sent_ptr->rel_conn_lost = SD_TRUE; + + ASN1R_TAG_ADD (aCtx, CTX, 0, rsentry_get_entry_id); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, rsentry_entry_id_cstr); + } + +/************************************************************************/ +/* rsentry_get_entry_id */ +/* Decoding report semaphore entry status request: entry id primitive */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_get_entry_id (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("txdwn_get_entry_id"); + + /* decode entry id onto itself, shifted by one character */ + sent_ptr->entry_id = aCtx->asn1r_field_ptr - 1; + + /* read entry id from message */ + if (asn1r_get_octstr (aCtx, sent_ptr->entry_id)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + sent_ptr->ei_len = aCtx->asn1r_octetcount; /* save the entry id length */ + + ASN1R_TAG_ADD (aCtx, CTX, 1, rsentry_get_entry_class); + } + +/************************************************************************/ +/* rsentry_entry_id_cstr */ +/* Decoding report semaphore entry status request: entry id constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_entry_id_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsentry_entry_id_cstr"); + + /* decode entry id onto itself, shifted by one character */ + sent_ptr->entry_id = aCtx->asn1r_field_ptr - 1; + + /* set up where to go when done decoding cstr */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = rsentry_entry_id_cstr_done; + + /* read entry id from the received message */ + asn1r_get_octstr_cstr (aCtx, _mmsdec_msglen, sent_ptr->entry_id); + } + +/************************************************************************/ +/* rsentry_entry_id_cstr_done */ +/* Decoding report semaphore entry status request: entry id constructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_entry_id_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + sent_ptr->ei_len = aCtx->asn1r_octetcount; /* save the entry id length */ + + ASN1R_TAG_ADD (aCtx, CTX, 1, rsentry_get_entry_class); + } + +/************************************************************************/ +/* rsentry_get_entry_class */ +/* Decoding report semaphore entry status request: entry class */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_get_entry_class (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsentry_get_entry_class"); + + if (asn1r_get_i8 (aCtx, &sent_ptr->entry_class)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, rsentry_app_ref_cstr); + } + + +/************************************************************************/ +/* rsentry_app_ref_cstr */ +/* Decoding report semaphore entry status request: application */ +/* reference constructor was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_app_ref_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsentry_app_ref_cstr"); + + _ms_get_mms_app_ref (aCtx, &sent_ptr->app_ref,&sent_ptr->app_ref_len, + app_ref_done); + } + +/************************************************************************/ +/* app_ref_done */ +/* Decoding report semaphore entry status request: application */ +/* reference constructor has ben read, OK for CTX 2 to be done. */ +/************************************************************************/ + +static ST_VOID app_ref_done (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = app_ref_cstr_done; + } + +/************************************************************************/ +/* app_ref_cstr_done */ +/* Decoding report semaphore entry status request: application */ +/* reference constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID app_ref_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 3, rsentry_get_named_token ); + ASN1R_TAG_ADD (aCtx, CTX, 4, rsentry_get_priority); + ASN1R_TAG_ADD (aCtx, CTX, 5, rsentry_get_rem_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 6, rsentry_get_abrt_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 7, rsentry_get_rel_conn_lost); + +/* Was last mandatory SemaphoreEntry Parameter, OK for it to be done */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = rsentry_entry_seq_cstr_done; + } + +/************************************************************************/ +/* rsentry_get_named_token */ +/* Decoding report semaphore entry status request: named token */ +/* primitve was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_get_named_token (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsentry_get_named_token"); + + if (aCtx->asn1r_elmnt_len > MAX_IDENT_LEN) + { /* named token is too ST_INT32 */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + /* read named token from the received message */ + sent_ptr->named_token_pres = SD_TRUE; + if (asn1r_get_vstr (aCtx, sent_ptr->named_token)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 4, rsentry_get_priority); + ASN1R_TAG_ADD (aCtx, CTX, 5, rsentry_get_rem_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 6, rsentry_get_abrt_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 7, rsentry_get_rel_conn_lost); + } + +/************************************************************************/ +/* rsentry_get_priority */ +/* Decoding report semaphore entry status request: priority primitive */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_get_priority (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsentry_get_priority"); + + /* read priority from the received message */ + if (asn1r_get_u8 (aCtx, &(sent_ptr->priority))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 5, rsentry_get_rem_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 6, rsentry_get_abrt_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 7, rsentry_get_rel_conn_lost); + } + +/************************************************************************/ +/* rsentry_get_rem_timeout */ +/* Decoding report semaphore entry status request: remaining timeout */ +/* primitve was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_get_rem_timeout (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsentry_get_rem_timeout"); + /* read remaining timeout from received message */ + sent_ptr->rem_timeout_pres = SD_TRUE; + if (asn1r_get_u32 (aCtx, &(sent_ptr->rem_timeout))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 6, rsentry_get_abrt_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 7, rsentry_get_rel_conn_lost); + } + +/************************************************************************/ +/* rsentry_get_abrt_timeout */ +/* Decoding report semaphore entry status request: relinquish if */ +/* connection lost primitve was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_get_abrt_timeout (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsentry_get_abrt_timeout"); + /* read abort on timeout */ + sent_ptr->abrt_on_timeout_pres = SD_TRUE; + if (asn1r_get_bool (aCtx, &sent_ptr->abrt_on_timeout)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + ASN1R_TAG_ADD (aCtx, CTX, 7, rsentry_get_rel_conn_lost); + } + +/************************************************************************/ +/* rsentry_get_rel_conn_lost */ +/* Decoding report semaphore entry status request: relinquish if */ +/* connection lost primitve was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_get_rel_conn_lost (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsentry_get_rel_conn_lost"); + /* read relinquish if conn lost from message */ + if (asn1r_get_bool (aCtx, &(sent_ptr->rel_conn_lost))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + } + +/************************************************************************/ +/* rsentry_entry_seq_cstr_done */ +/* Decoding report semaphore entry status request: semaphore entry */ +/* sequence constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_entry_seq_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + sent_ptr++; /* point to where next will go */ + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, rsentry_entry_seq_cstr); + } + +/************************************************************************/ +/* rsentry_sem_entry_cstr_done */ +/* Decoding report semaphore entry status request: semaphore entry */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_sem_entry_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, rsentry_get_more_follows); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* rsentry_get_more_follows */ +/* Decoding report semaphore entry status request: more follows */ +/* indicator was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_get_more_follows (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsentry_get_more_follows"); + /* read more follows indicator from message */ + if (asn1r_get_bool (aCtx, &(rsp_info->more_follows))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_rsentry */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the report semaphore entry status request.*/ +/************************************************************************/ + +MMSREQ_PEND *mp_rsentry (ST_INT chan, RSENTRY_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_REP_SEMENTRY, + M_CAST_MK_FUN (_ms_mk_rsentry_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_rsentry */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the report semaphore entry status request. */ +/************************************************************************/ + +ST_RET mpl_rsentry (RSENTRY_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_REP_SEMENTRY, + M_CAST_MK_FUN (_ms_mk_rsentry_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_rsentry_req */ +/* construct a report semaphore entry status request */ +/************************************************************************/ + +ST_VOID _ms_mk_rsentry_req (ASN1_ENC_CTXT *aCtx, RSENTRY_REQ_INFO *info) + { + + asn1r_strt_constr (aCtx); /* start sequence constructor */ + + if (info->start_after_pres) + { /* write app to start after */ + asn1r_wr_octstr (aCtx, info->start_after, info->sa_len); + asn1r_fin_prim (aCtx, 2, CTX); /* context tag 2 */ + } + + asn1r_wr_i16 (aCtx, info->state); /* write the semaphore state */ + asn1r_fin_prim (aCtx, 1, CTX); /* context tag 1 */ + + asn1r_strt_constr (aCtx); /* start object name constr */ + + _ms_wr_mms_objname (aCtx, &info->sem_name); /* write the object name */ + + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_REP_SEMENTRY,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_rspoo.c b/mmslib/mmsle/rq_rspoo.c new file mode 100644 index 0000000..7d1897d --- /dev/null +++ b/mmslib/mmsle/rq_rspoo.c @@ -0,0 +1,221 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_rspool.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of report pool */ +/* semaphore status. It decodes the report pool semaphore status */ +/* response (confirm) & encodes the report pool semahpore status */ +/* request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 08/28/03 EJV 05 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_psem.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static RSPOOL_RESP_INFO *rsp_info; + + +static TOKEN_ID *token_ptr; +static ST_INT max_named_tokens; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID rspool_get_named_token (ASN1_DEC_CTXT *aCtx); +static ST_VOID rspool_named_token_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID rspool_named_token_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID rspool_get_more_follows (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/************************************************************************/ +/* mms_rspool_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_rspool_rsp (ASN1_DEC_CTXT *aCtx) + { +ST_INT rsp_size; + + MLOG_CDEC0 ("Report Pool Semaphore Status Response"); + +#if defined(FIXED_DECBUF) + max_named_tokens = m_cl_max_named_tokens; + rsp_size = mmsl_dec_info_size; +#else + max_named_tokens = _mmsdec_msglen / 2; /* find maximum size */ + if (m_cl_max_named_tokens && (max_named_tokens > m_cl_max_named_tokens)) + max_named_tokens = m_cl_max_named_tokens; + rsp_size = sizeof (RSPOOL_RESP_INFO) + + (sizeof (TOKEN_ID) * max_named_tokens); +#endif + +/* get storage for request information */ + rsp_info = (RSPOOL_RESP_INFO *) _m_get_dec_buf (aCtx, rsp_size); + token_ptr = (TOKEN_ID *) (rsp_info + 1); + + rsp_info->num_of_tokens = 0; /* initialize number of named tokens */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, rspool_named_token_cstr); + } + +/************************************************************************/ +/* rspool_named_token_cstr */ +/* Decoding report pool semaphore status request: named token list */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID rspool_named_token_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rspool_named_token_cstr"); + + ASN1R_TAG_ADD (aCtx, CTX, 0, rspool_get_named_token); + ASN1R_TAG_ADD (aCtx, CTX, 1, rspool_get_named_token); + ASN1R_TAG_ADD (aCtx, CTX, 2, rspool_get_named_token); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = rspool_named_token_cstr_done; + } + +/************************************************************************/ +/* rspool_get_named_token */ +/* Decoding report pool semaphore status request: named token was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID rspool_get_named_token (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rspool_get_named_token"); + + rsp_info->num_of_tokens++; + if (rsp_info->num_of_tokens > max_named_tokens) + { /* too many named tokens */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + + token_ptr->token_tag = aCtx->asn1r_elmnt_id; + +#if defined(USE_COMPACT_MMS_STRUCTS) + token_ptr->named_token = (ST_CHAR *) (aCtx->asn1r_field_ptr - 1); +#endif + + /* read free token from the received message */ + if (asn1r_get_identifier (aCtx, token_ptr->named_token)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + token_ptr++; /* point to where next named token will go */ + asn1r_tag_restore (aCtx); + } + +/************************************************************************/ +/* rspool_named_token_cstr_done */ +/* Decoding report pool semaphore status request: named token constr */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID rspool_named_token_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, rspool_get_more_follows); + } + +/************************************************************************/ +/* rspool_get_more_follows */ +/* Decoding report pool semaphore status request: more follows indicator*/ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID rspool_get_more_follows (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rspool_get_more_follows"); + /* read more follows indicator from message */ + if (asn1r_get_bool (aCtx, &(rsp_info->more_follows))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_rspool */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the report pool semaphore status request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_rspool (ST_INT chan, RSPOOL_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_REP_SEMPOOL, + M_CAST_MK_FUN (_ms_mk_rspool_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_rspool */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the report pool semaphore status request. */ +/************************************************************************/ + +ST_RET mpl_rspool (RSPOOL_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_REP_SEMPOOL, + M_CAST_MK_FUN (_ms_mk_rspool_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_rspool_req */ +/* construct a report pool semaphore status request */ +/************************************************************************/ + +ST_VOID _ms_mk_rspool_req (ASN1_ENC_CTXT *aCtx, RSPOOL_REQ_INFO *info) + { + + if (info->start_after_pres) + { + asn1r_wr_vstr (aCtx, info->start_after); /* write app to start after */ + asn1r_fin_prim (aCtx, 1, CTX); /* context tag 1 */ + } + + asn1r_strt_constr (aCtx); /* start object name constr */ + + _ms_wr_mms_objname (aCtx, &info->sem_name); /* write the object name */ + + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_REP_SEMPOOL,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_rssta.c b/mmslib/mmsle/rq_rssta.c new file mode 100644 index 0000000..3f4d7e1 --- /dev/null +++ b/mmslib/mmsle/rq_rssta.c @@ -0,0 +1,198 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_rsstat.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of report semaphore */ +/* status. It decodes the report semaphore status response */ +/* (confirm) and encodes the report semaphore status request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 09/30/03 EJV 06 Corr spelling for 'receive' */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_psem.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + + +static RSSTAT_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID rsstat_get_num_of_owned (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsstat_get_num_of_tokens (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsstat_get_class (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsstat_get_mms_deletable (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsstat_get_num_of_hung (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/************************************************************************/ +/* mms_rsstat_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_rsstat_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Report Semaphore Status Response"); + +/* get storage for request information */ + rsp_info = (RSSTAT_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (RSSTAT_RESP_INFO)); + ASN1R_TAG_ADD (aCtx, CTX, 0, rsstat_get_mms_deletable); + } + +/************************************************************************/ +/* rsstat_get_mms_deletable */ +/* Decoding report semaphore status request: mms deletable name was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID rsstat_get_mms_deletable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsstat_get_mms_deletable"); + /* read mms deletable from received message */ + if (asn1r_get_bool (aCtx, &(rsp_info->mms_deletable))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 1, rsstat_get_class); + } + +/************************************************************************/ +/* rsstat_get_class */ +/* Decoding report semaphore status request: class was encountered. */ +/************************************************************************/ + +static ST_VOID rsstat_get_class (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsstat_get_class"); + /* read the class from the received message */ + if (asn1r_get_i16 (aCtx, &(rsp_info->tclass))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + if ((rsp_info->tclass < 0) || (rsp_info->tclass > 1)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 2, rsstat_get_num_of_tokens); + } + +/************************************************************************/ +/* rsstat_get_num_of_tokens */ +/* Decoding report semaphore status request: number of tokens was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID rsstat_get_num_of_tokens (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsstat_get_num_of_tokens"); + /* read number of tokens from received message */ + if (asn1r_get_u16 (aCtx, &(rsp_info->num_of_tokens))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 3, rsstat_get_num_of_owned); + } + +/************************************************************************/ +/* rsstat_get_num_of_owned */ +/* Decoding report semaphore status request: number of owned tokens was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID rsstat_get_num_of_owned (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsstat_get_num_of_owned"); + /* read number of owned tokens from message */ + if (asn1r_get_u16 (aCtx, &(rsp_info->num_of_owned))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 4, rsstat_get_num_of_hung); + } + +/************************************************************************/ +/* rsstat_get_num_of_hung */ +/* Decoding report semaphore status request: number of hung tokens was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID rsstat_get_num_of_hung (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsstat_get_num_of_hung"); + /* read number of hung tokens from message */ + if (asn1r_get_u16 (aCtx, &(rsp_info->num_of_hung))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_rsstat */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the report semaphore status request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_rsstat (ST_INT chan, RSSTAT_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_REP_SEMSTAT, + M_CAST_MK_FUN (_ms_mk_rsstat_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_rsstat */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the report semaphore status request. */ +/************************************************************************/ + +ST_RET mpl_rsstat (RSSTAT_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_REP_SEMSTAT, + M_CAST_MK_FUN (_ms_mk_rsstat_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_rsstat_req */ +/* construct a report semaphore status request */ +/************************************************************************/ + +ST_VOID _ms_mk_rsstat_req (ASN1_ENC_CTXT *aCtx, RSSTAT_REQ_INFO *info) + { + + _ms_wr_mms_objname (aCtx, &info->sem_name); /* write the object name */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_REP_SEMSTAT,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_start.c b/mmslib/mmsle/rq_start.c new file mode 100644 index 0000000..f8a5d1f --- /dev/null +++ b/mmslib/mmsle/rq_start.c @@ -0,0 +1,108 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_start.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the start */ +/* operation. It decodes the start response (confirm) & encodes */ +/* the start request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_start_resp */ +/* NOTE : Since the start resp is a NULL PDU, the decode is continued */ +/* by '_mms_null_pdu_dec', which simply sets decode done = 1 and sets */ +/* the decode done function to point to the general decode done fun */ +/* See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_start */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the start request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_start (ST_INT chan, START_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_START, + M_CAST_MK_FUN (_ms_mk_start_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_start */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the start request. */ +/************************************************************************/ + +ST_RET mpl_start (START_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_START, + M_CAST_MK_FUN (_ms_mk_start_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_start_req */ +/* construct a start request */ +/************************************************************************/ + +ST_VOID _ms_mk_start_req (ASN1_ENC_CTXT *aCtx, START_REQ_INFO *info) + { + + if (info->start_arg_pres) + { + if (info->start_arg_type == ARG_TYPE_SIMPLE) + { + asn1r_wr_vstr (aCtx, (ST_CHAR *)info->start_arg); /* write the start argument */ + asn1r_fin_prim (aCtx, 1, CTX); /* context tag 1 */ + } + else /* ENCODED data, write as complete ASN.1 EXTERNAL */ + asn1r_wr_delmnt (aCtx, info->start_arg,info->start_arg_len); + } + + asn1r_wr_vstr (aCtx, info->piname); /* write pgm invocation name */ + asn1r_fin_prim (aCtx, 0, CTX); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_START,CTX,DEF); /* tag = opcode, ctx cstr */ + } diff --git a/mmslib/mmsle/rq_stop.c b/mmslib/mmsle/rq_stop.c new file mode 100644 index 0000000..218d17d --- /dev/null +++ b/mmslib/mmsle/rq_stop.c @@ -0,0 +1,96 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_stop.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the stop */ +/* operation. It decodes the stop response (confirm) & encodes */ +/* the stop request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_stop_rsp */ +/* NOTE : Since the mms_stop_rsp is a NULL PDU, the decode is continued */ +/* by '_mms_null_pdu_dec', which simply sets decode done = 1 and sets */ +/* the decode done function to point to the general decode done fun */ +/* See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_stop */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the stop request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_stop (ST_INT chan, STOP_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_STOP, + M_CAST_MK_FUN (_ms_mk_stop_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_stop */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the stop request. */ +/************************************************************************/ + +ST_RET mpl_stop (STOP_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_STOP, + M_CAST_MK_FUN (_ms_mk_stop_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_stop_req */ +/* construct a stop request */ +/************************************************************************/ + +ST_VOID _ms_mk_stop_req (ASN1_ENC_CTXT *aCtx, STOP_REQ_INFO *info) + { + asn1r_wr_vstr (aCtx, info->piname); /* write pgm invocation name */ + asn1r_fin_prim (aCtx, 0, CTX); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_STOP,CTX,DEF); /* tag = opcode, ctx cstr */ + } diff --git a/mmslib/mmsle/rq_store.c b/mmslib/mmsle/rq_store.c new file mode 100644 index 0000000..0350cf5 --- /dev/null +++ b/mmslib/mmsle/rq_store.c @@ -0,0 +1,108 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_storedom.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of store domain */ +/* content. It decodes the store domain content response (confirm) */ +/* & encodes the store domain content request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/************************************************************************/ +/* mms_store_domain_rsp */ +/* NOTE : Since the mms_store_domain_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_storedom */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the store domain content request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_storedom (ST_INT chan, STOREDOM_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_STORE_DOMAIN, + M_CAST_MK_FUN (_ms_mk_storedom_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_storedom */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the store domain content request. */ +/************************************************************************/ + +ST_RET mpl_storedom (STOREDOM_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_STORE_DOMAIN, + M_CAST_MK_FUN (_ms_mk_storedom_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_storedom_req */ +/* ENCODE a store domain content REQUEST: */ +/************************************************************************/ + +ST_VOID _ms_mk_storedom_req (ASN1_ENC_CTXT *aCtx, STOREDOM_REQ_INFO *info) + { + asn1r_strt_constr (aCtx); /* start sequence constructor */ + + if (info->third_pty_pres) + { + asn1r_wr_delmnt (aCtx, info->third_pty, info->third_pty_len); + *(aCtx->asn1r_field_ptr+1) = (ST_UCHAR) 0xA2; + } + + asn1r_strt_constr (aCtx); + _ms_wr_mms_fname (aCtx, (FILE_NAME *)(info + 1), + info -> num_of_fname); + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* context specific tag 1 */ + + asn1r_wr_vstr (aCtx, info->dname); /* write the domain name */ + asn1r_fin_prim (aCtx, 0,CTX); /* context specific tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_STORE_DOMAIN,CTX,DEF); /* tag = opcode, ctx constr */ + } + diff --git a/mmslib/mmsle/rq_takec.c b/mmslib/mmsle/rq_takec.c new file mode 100644 index 0000000..8256e92 --- /dev/null +++ b/mmslib/mmsle/rq_takec.c @@ -0,0 +1,192 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_takectrl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of take semahpore */ +/* control. It decodes the take control response (confirm) & */ +/* encodes the take control request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_psem.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static TAKECTRL_RESP_INFO *info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID takectrl_get_named_token (ASN1_DEC_CTXT *aCtx); +static ST_VOID takectrl_get_null (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_takectrl_rsp */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_takectrl_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Take Control Response"); + +/* get storage for request information */ + info = (TAKECTRL_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (TAKECTRL_RESP_INFO)); + ASN1R_TAG_ADD (aCtx, CTX, 0, takectrl_get_null); + ASN1R_TAG_ADD (aCtx, CTX, 1, takectrl_get_named_token); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* takectrl_get_null */ +/* take control response is being decoded: ctx 0 was encountered. */ +/************************************************************************/ + +static ST_VOID takectrl_get_null (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("takectrl_get_null"); + + info->resp_tag = SD_FALSE; /* set tag to NULL response */ + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* takectrl_get_named_token */ +/* take control response is being decoded: ctx 1 was encountered. */ +/************************************************************************/ + +static ST_VOID takectrl_get_named_token (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("takectrl_get_named_token"); + + info->resp_tag = SD_TRUE; /* set tag to named token resp */ + + if (asn1r_get_identifier (aCtx, info->named_token)) + { /* not a visible string */ + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + return; + } + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_takectrl */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the take control request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_takectrl (ST_INT chan, TAKECTRL_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_TAKE_CONTROL, + M_CAST_MK_FUN (_ms_mk_takectrl_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_takectrl */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the take control request. */ +/************************************************************************/ + +ST_RET mpl_takectrl (TAKECTRL_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_TAKE_CONTROL, + M_CAST_MK_FUN (_ms_mk_takectrl_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_takectrl_req */ +/* construct a take control request */ +/************************************************************************/ + +ST_VOID _ms_mk_takectrl_req (ASN1_ENC_CTXT *aCtx, TAKECTRL_REQ_INFO *info_ptr) + { + if (info_ptr->app_preempt_pres) + { + asn1r_wr_delmnt (aCtx, info_ptr->app_preempt, info_ptr->app_len); + *(aCtx->asn1r_field_ptr+1) = (ST_UCHAR) 0xA7; + } + + if (!info_ptr->rel_conn_lost) + { /* NOT the default */ + asn1r_wr_bool (aCtx, info_ptr->rel_conn_lost); /* write the rel if conn lost */ + asn1r_fin_prim (aCtx, 6, CTX); /* context tag 6 */ + } + + if (info_ptr->abrt_on_timeout_pres) + { + asn1r_wr_bool (aCtx, info_ptr->abrt_on_timeout);/* write the abort on timeout */ + asn1r_fin_prim (aCtx, 5, CTX); /* context tag 5 */ + } + + if (info_ptr->ctrl_timeout_pres) + { + asn1r_wr_u32 (aCtx, info_ptr->ctrl_timeout); /* write the control timeout */ + asn1r_fin_prim (aCtx, 4, CTX); /* context tag 4 */ + } + + if (info_ptr->acc_delay_pres) + { + asn1r_wr_u32 (aCtx, info_ptr->acc_delay); /* write the acceptable delay */ + asn1r_fin_prim (aCtx, 3, CTX); /* context tag 3 */ + } + + if (info_ptr->priority != MMS_NORM_PRIORITY) + { /* NOT the default */ + asn1r_wr_bool (aCtx, info_ptr->priority); /* write the priority */ + asn1r_fin_prim (aCtx, 2, CTX); /* context tag 2 */ + } + + if (info_ptr->named_token_pres) + { + asn1r_wr_vstr (aCtx, info_ptr->named_token); /* write the named token */ + asn1r_fin_prim (aCtx, 1, CTX); /* context tag 1 */ + } + + asn1r_strt_constr (aCtx); /* object name constructor */ + + _ms_wr_mms_objname (aCtx, &info_ptr->sem_name); /* write the object name */ + + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_TAKE_CONTROL,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rq_termd.c b/mmslib/mmsle/rq_termd.c new file mode 100644 index 0000000..e23bf75 --- /dev/null +++ b/mmslib/mmsle/rq_termd.c @@ -0,0 +1,143 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_termdown.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of the terminate */ +/* download sequence. It decodes the terminate download sequence */ +/* response (confirm) & encodes the terminate download sequence */ +/* request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/09/05 EJV 06 MMS_LITE does not need thisFileName. */ +/* 03/17/04 RKR 05 Changed thisFileName */ +/* 03/11/04 GLB 04 Remove "thisFileName" */ +/* 12/20/01 JRB 03 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#if defined(DEBUG_SISCO) && (defined(S_MT_SUPPORT) && !defined(MMS_LITE)) +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/* variables global to the DECODE portion : NONE */ + +#ifndef MMS_LITE +/* variables global to the ENCODE portion : */ +static ST_INT channel; +#else +/* variables global to the ENCODE portion : NONE */ +#endif + + +/************************************************************************/ +/************************************************************************/ +/* mms_term_download_rsp */ +/* NOTE : Since the mms_term_download_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_termdown */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the terminate download sequence request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_termdown (ST_INT chan, TERMDOWN_REQ_INFO *info_ptr) + { +MMSREQ_PEND *ret; + + S_LOCK_COMMON_RESOURCES (); + channel = chan; /* save for mk function to use */ + ret = _mms_req_send (MMSOP_TERM_DOWNLOAD, + M_CAST_MK_FUN (_ms_mk_termdown_req), + + chan, (ST_CHAR *)info_ptr); + S_UNLOCK_COMMON_RESOURCES (); + return (ret); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_termdown */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the terminate download sequence request. */ +/************************************************************************/ + +ST_RET mpl_termdown (TERMDOWN_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_TERM_DOWNLOAD, + M_CAST_MK_FUN (_ms_mk_termdown_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_termdown_req */ +/* construct a terminate download sequence request */ +/************************************************************************/ + +ST_VOID _ms_mk_termdown_req (ASN1_ENC_CTXT *aCtx, TERMDOWN_REQ_INFO *info) + { + asn1r_strt_constr (aCtx); /* start sequence constr */ + + if (info->discarded) + { /* NOT the default (SD_FALSE) */ +#ifndef MMS_LITE + if (mms_chan_info[channel].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + { + _ms_wr_service_err (aCtx, (info->err)->eclass,(info->err)->code, + &(info->err)->adtnl); + asn1r_fin_constr (aCtx, 1,CTX,DEF); + } + else /* DIS */ + { + asn1r_wr_bool (aCtx, info->discarded); /* write the discard flag */ + asn1r_fin_prim (aCtx, 1, CTX); /* context tag 1 */ + } + } + + asn1r_wr_vstr (aCtx, info->dname); /* write the domain name */ + asn1r_fin_prim (aCtx, 0, CTX); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_TERM_DOWNLOAD,CTX,DEF); /* tag = opcode, ctx constr */ + } + diff --git a/mmslib/mmsle/rq_termu.c b/mmslib/mmsle/rq_termu.c new file mode 100644 index 0000000..6cca8b7 --- /dev/null +++ b/mmslib/mmsle/rq_termu.c @@ -0,0 +1,94 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_termupl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of terminate upload */ +/* sequence. It decodes the terminate upload sequence response */ +/* (confirm) & encodes the terminate upload sequence request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/* variables global to the DECODE portion : NONE */ + +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_term_upload_rsp */ +/* NOTE : Since the mms_term_upload_rsp is a NULL PDU, the decode is */ +/* continued by '_mms_null_pdu_dec', which simply sets decode done = 1 */ +/* and sets the decode done function to point to the general decode done*/ +/* fun. See mmsdec.c for the general functions. */ +/************************************************************************/ + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_termupl */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the terminate upload sequence request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_termupl (ST_INT chan, TERMUPL_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_TERM_UPLOAD, + M_CAST_MK_FUN (_ms_mk_termupl_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_termupl */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the terminate upload sequence request. */ +/************************************************************************/ + +ST_RET mpl_termupl (TERMUPL_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_TERM_UPLOAD, + M_CAST_MK_FUN (_ms_mk_termupl_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_termupl_req */ +/* construct a terminate upload sequence request */ +/************************************************************************/ + +ST_VOID _ms_mk_termupl_req (ASN1_ENC_CTXT *aCtx, TERMUPL_REQ_INFO *info) + { + asn1r_wr_i32 (aCtx, info->ulsmid); /* write upload state machind id*/ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_TERM_UPLOAD,CTX); /* tag = opcode, ctx prim */ + } diff --git a/mmslib/mmsle/rq_uploa.c b/mmslib/mmsle/rq_uploa.c new file mode 100644 index 0000000..9c463aa --- /dev/null +++ b/mmslib/mmsle/rq_uploa.c @@ -0,0 +1,216 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rq_upload.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the requester portion of upload segment. */ +/* It decodes the upload segment response (confirm) & encodes the */ +/* upload segment request. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 08/28/03 EJV 06 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +static UPLOAD_RESP_INFO *rsp_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID upload_get_more_follows (ASN1_DEC_CTXT *aCtx); +static ST_VOID upload_load_data_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID upload_load_data_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID upload_load_data_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID extern_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_upload_rsp */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_upload_rsp (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Upload Segment Response"); + + +/* get storage for request information */ + rsp_info = (UPLOAD_RESP_INFO *) _m_get_dec_buf (aCtx, sizeof (UPLOAD_RESP_INFO)); + rsp_info->more_follows = SD_TRUE; /* set default value */ + + ASN1R_TAG_ADD (aCtx, CTX, 0, upload_load_data_prim); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, upload_load_data_cstr); + +/* If MMS IS, Check for CODED load data */ +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + _ms_chk_for_extern (aCtx, &rsp_info->load_data_len, + &rsp_info->load_data, + extern_done); + } + +/************************************************************************/ +/* upload_load_data_prim */ +/* upload segment response: decode the load data primitive */ +/************************************************************************/ + +static ST_VOID upload_load_data_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("upload_load_data_pri"); + + /* decode load data back onto itself, shifted by one character */ + rsp_info->load_data = aCtx->asn1r_field_ptr - 1; + + /* read load data from message */ + if (asn1r_get_octstr (aCtx, rsp_info->load_data)) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + rsp_info->load_data_len = aCtx->asn1r_octetcount; + + ASN1R_TAG_ADD (aCtx, CTX, 1, upload_get_more_follows); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + + } + +/************************************************************************/ +/* upload_load_data_cstr */ +/* upload segment response: decode load data constructor */ +/************************************************************************/ + +static ST_VOID upload_load_data_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("upload_load_data_cstr"); + + /* decode load data back onto itself, shifted by one character */ + rsp_info->load_data = aCtx->asn1r_field_ptr - 1; + + /* set up where to go when done decoding cstr */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = upload_load_data_cstr_done; + + /* get load data from the received message */ + asn1r_get_octstr_cstr (aCtx, _mmsdec_msglen, rsp_info->load_data); + } + +/************************************************************************/ +/* upload_load_data_cstr_done */ +/* upload segment response: load data constructor is done */ +/************************************************************************/ + +static ST_VOID upload_load_data_cstr_done (ASN1_DEC_CTXT *aCtx) + { + rsp_info->load_data_len = aCtx->asn1r_octetcount; /* save the load data length */ + + ASN1R_TAG_ADD (aCtx, CTX, 1, upload_get_more_follows); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* extern_done */ +/************************************************************************/ + +static ST_VOID extern_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("extern_done"); + + rsp_info->load_data_type = LOAD_DATA_CODED; + ASN1R_TAG_ADD (aCtx, CTX, 1, upload_get_more_follows); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* upload_get_more_follows */ +/* upload segment response: decode the more follows flag */ +/************************************************************************/ + +static ST_VOID upload_get_more_follows (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("upload_get_more_follows"); + /* read end of pgm from message */ + if (asn1r_get_bool (aCtx, &(rsp_info->more_follows))) + asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_upload */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the upload segment request. */ +/************************************************************************/ + +MMSREQ_PEND *mp_upload (ST_INT chan, UPLOAD_REQ_INFO *info_ptr) + { + return (_mms_req_send (MMSOP_UP_LOAD, + M_CAST_MK_FUN (_ms_mk_upload_req), + chan,(ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_upload */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the upload segment request. */ +/************************************************************************/ + +ST_RET mpl_upload (UPLOAD_REQ_INFO *info_ptr) + { + return (_mms_req_fin (MMSOP_UP_LOAD, + M_CAST_MK_FUN (_ms_mk_upload_req), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_upload_req */ +/* construct an upload segment request */ +/************************************************************************/ + +ST_VOID _ms_mk_upload_req (ASN1_ENC_CTXT *aCtx, UPLOAD_REQ_INFO *info) + { + asn1r_strt_constr (aCtx); /* start sequence constr */ + + asn1r_wr_i32 (aCtx, info->ulsmid); /* write upload state machine id*/ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_UP_LOAD,CTX); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsle/rs_altec.c b/mmslib/mmsle/rs_altec.c new file mode 100644 index 0000000..f7044b1 --- /dev/null +++ b/mmslib/mmsle/rs_altec.c @@ -0,0 +1,226 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_altecm.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of alter event */ +/* condition monitoring. It decodes the alter event condition */ +/* monitoring request (indication) & encodes the alter event */ +/* condition monitoring response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------ */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static ALTECM_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID altecm_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID altecm_name_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID altecm_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID altecm_get_enabled (ASN1_DEC_CTXT *aCtx); +static ST_VOID altecm_get_priority (ASN1_DEC_CTXT *aCtx); +static ST_VOID altecm_get_as_reports (ASN1_DEC_CTXT *aCtx); +static ST_VOID altecm_get_eval_int (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_altecm_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_altecm_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Alter Event Condition Monitoring Request"); + + +/* get storage for request information */ + req_info = (ALTECM_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (ALTECM_REQ_INFO)); + +/* req_info->enabled_pres = SD_FALSE; set default values */ +/* req_info->priority_pres = SD_FALSE; */ +/* req_info->as_reports_pres = SD_FALSE; */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, altecm_name_cstr); + } + +/************************************************************************/ +/* altecm_name_cstr */ +/* alter event condition monitoring request is being decoded: event */ +/* condition name constructor was encountered. */ +/************************************************************************/ + +static ST_VOID altecm_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altecm_name_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->evcon_name, altecm_name_done); + } + +/************************************************************************/ +/* altecm_name_done */ +/* alter event condition monitoring request is being decoded: event */ +/* condition name has been obtained. */ +/************************************************************************/ + +static ST_VOID altecm_name_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altecm_name_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = altecm_name_cstr_done; + } + +/************************************************************************/ +/* altecm_name_cstr_done */ +/* alter event condition monitoring request is being decoded: event */ +/* condition name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID altecm_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, altecm_get_enabled); + ASN1R_TAG_ADD (aCtx, CTX, 2, altecm_get_priority); + ASN1R_TAG_ADD (aCtx, CTX, 3, altecm_get_as_reports); + ASN1R_TAG_ADD (aCtx, CTX, 4, altecm_get_eval_int); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* altecm_get_enabled */ +/* Decoding alter event condition monitoring request: enabled was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID altecm_get_enabled (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altecm_get_enabled"); + + req_info->enabled_pres = SD_TRUE; + + if (asn1r_get_bool (aCtx, &(req_info->enabled))) /* read enabled */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 2, altecm_get_priority); + ASN1R_TAG_ADD (aCtx, CTX, 3, altecm_get_as_reports); + ASN1R_TAG_ADD (aCtx, CTX, 4, altecm_get_eval_int); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* altecm_get_priority */ +/* Decoding alter event condition monitoring request: priority was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID altecm_get_priority (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altecm_get_priority"); + + req_info->priority_pres = SD_TRUE; + + if (asn1r_get_u8 (aCtx, &(req_info->priority))) /* read priority */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 3, altecm_get_as_reports); + ASN1R_TAG_ADD (aCtx, CTX, 4, altecm_get_eval_int); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* altecm_get_as_reports */ +/* Decoding alter event condition monitoring request: alarm summary */ +/* reports was encountered. */ +/************************************************************************/ + +static ST_VOID altecm_get_as_reports (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altecm_get_as_reports"); + + req_info->as_reports_pres = SD_TRUE; /* set present flag */ + /* read alarm summary reports */ + if (asn1r_get_bool (aCtx, &(req_info->as_reports))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 4, altecm_get_eval_int); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* altecm_get_eval_int */ +/* Decoding alter event condition monitoring request: evaluation */ +/* interval was encountered. */ +/************************************************************************/ + +static ST_VOID altecm_get_eval_int (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altecm_get_eval_int"); + + req_info->eval_int_pres = SD_TRUE; + + if (asn1r_get_u32 (aCtx, &(req_info->eval_int))) /* read evaluation int */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_altecm_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the alter event condition monitoring */ +/* response. */ +/************************************************************************/ + +ST_RET mp_altecm_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_ALT_EC_MON)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_altecm_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the alter event condition monitoring response. */ +/************************************************************************/ + +ST_RET mpl_altecm_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_ALT_EC_MON)); + } +#endif diff --git a/mmslib/mmsle/rs_altee.c b/mmslib/mmsle/rs_altee.c new file mode 100644 index 0000000..0b7f314 --- /dev/null +++ b/mmslib/mmsle/rs_altee.c @@ -0,0 +1,256 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_altee.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of alter event */ +/* enrollment. It decodes the alter event enrollment request */ +/* (indication) & encodes the alter event enrollment response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 03/31/03 JRB 06 asn1r_get_bitstr: add max_bits arg. */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static ALTEE_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID altee_eename_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID altee_eename_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID altee_eename_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID altee_get_ect_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID altee_get_ect_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID altee_get_ect_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID altee_get_alarm_ack_rule (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_altee_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_altee_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Alter Event Enrollment Request"); + + +/* get storage for request information */ + req_info = (ALTEE_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (ALTEE_REQ_INFO)); + +/* req_info->ec_transitions_pres = SD_FALSE; */ +/* req_info->alarm_ack_rule_pres = SD_FALSE; */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, altee_eename_cstr); + } + +/************************************************************************/ +/* altee_eename_cstr */ +/* alter event enrollment request is being decoded: event enrollment */ +/* name constructor was encountered. */ +/************************************************************************/ + +static ST_VOID altee_eename_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altee_eename_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->evenroll_name, altee_eename_done); + } + +/************************************************************************/ +/* altee_eename_done */ +/* alter event enrollment request is being decoded: event enrollment */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID altee_eename_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altee_eename_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = altee_eename_cstr_done; + } + +/************************************************************************/ +/* altee_eename_cstr_done */ +/* alter event enrollment request is being decoded: event enrollment */ +/* name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID altee_eename_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, altee_get_ect_prim); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, altee_get_ect_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 2, altee_get_alarm_ack_rule); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* altee_get_ect_prim */ +/* alter event enrollment request is being decoded: event condition */ +/* transitions primitive was encountered. */ +/************************************************************************/ + +static ST_VOID altee_get_ect_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altee_get_ect_prim"); + /* check length before moving bitstring */ + if (!asn1r_get_bitstr (aCtx, &req_info->ec_transitions, 7)) + altee_get_ect_done (aCtx); /* set up for the next data element */ + else + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + } + +/************************************************************************/ +/* altee_get_ect_cstr */ +/* alter event enrollment request is being decoded: event condition */ +/* transitions constructor was encountered. */ +/************************************************************************/ + +static ST_VOID altee_get_ect_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altee_get_ect_cstr"); + /* set up bitstring cstr done function */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = altee_get_ect_done; + + asn1r_get_bitstr_cstr (aCtx, 7,&req_info->ec_transitions); + } + +/************************************************************************/ +/* altee_get_ect_done */ +/* alter event enrollment request is being decoded: event condition */ +/* transitions constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID altee_get_ect_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altee_get_ect_done"); + + req_info->ec_transitions_pres = SD_TRUE; /* set present flag */ + + /* Check aCtx->asn1r_bitcount for correct # of bits */ + if (aCtx->asn1r_bitcount != 7) /* should be 7 bits */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + else /* now get alarm ack rule */ + { + ASN1R_TAG_ADD (aCtx, CTX,2,altee_get_alarm_ack_rule); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + } + +/************************************************************************/ +/* altee_get_alarm_ack_rule */ +/* Decoding alter event enrollment request: alarm acknowledgment rule */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID altee_get_alarm_ack_rule (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("altee_get_alarm_ack_rule"); + + req_info->alarm_ack_rule_pres = SD_TRUE; + /* read alarm ack rule */ + if (asn1r_get_i16 (aCtx, &(req_info->alarm_ack_rule))) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + else if ((req_info->alarm_ack_rule < 0) || (req_info->alarm_ack_rule > 3)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_altee_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the alter event enrollment response. */ +/************************************************************************/ + +ST_RET mp_altee_resp (MMSREQ_IND *indptr, ALTEE_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_ALT_EE,indptr, + M_CAST_MK_FUN (_ms_mk_altee_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_altee_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the alter event enrollment response. */ +/************************************************************************/ + +ST_RET mpl_altee_resp (ST_UINT32 invoke_id, ALTEE_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_ALT_EE,invoke_id, + M_CAST_MK_FUN (_ms_mk_altee_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_altee_resp */ +/* ENCODE an alter event enrollment RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_altee_resp (ASN1_ENC_CTXT *aCtx, ALTEE_RESP_INFO *info) + { + asn1r_strt_constr (aCtx); /* start ctx tag 1 constructor */ + _ms_wr_mms_evtime (aCtx, &info->trans_time); + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish ctx tag 1 constructor */ + + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + if (info->cur_state_tag == 1) + asn1r_fin_prim (aCtx, 1, CTX); /* write undefined */ + else + { + asn1r_wr_i16 (aCtx, info->state); /* write state */ + asn1r_fin_prim (aCtx, 0, CTX); + } + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish ctx tag 0 constructor */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_ALT_EE,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rs_crepi.c b/mmslib/mmsle/rs_crepi.c new file mode 100644 index 0000000..c944ac0 --- /dev/null +++ b/mmslib/mmsle/rs_crepi.c @@ -0,0 +1,242 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_crepi.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of create program */ +/* invocation. It decodes the create program invocation request */ +/* (indication) & encodes the create program invocation response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static CREPI_REQ_INFO *req_info; + +static ST_CHAR **dom_ptr; +static ST_INT max_vstr; +static ST_INT num_vstr; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID crepi_get_reusable (ASN1_DEC_CTXT *aCtx); +static ST_VOID crepi_get_monitor (ASN1_DEC_CTXT *aCtx); +static ST_VOID crepi_get_domain_name (ASN1_DEC_CTXT *aCtx); +static ST_VOID crepi_domain_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID crepi_domain_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID crepi_get_piname (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_create_pi_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_create_pi_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Create Program Invocation Request"); + +#if defined(FIXED_DECBUF) + max_vstr = m_sv_max_vstr; + req_size = mmsl_dec_info_size; +#else + max_vstr = _mmsdec_msglen/2; /* determine maximum size */ + if (m_sv_max_vstr && (max_vstr > m_sv_max_vstr)) + max_vstr = m_sv_max_vstr; + + req_size = sizeof (CREPI_REQ_INFO) + (sizeof (ST_CHAR *)*max_vstr); +#endif + +/* get storage for request information */ + req_info = (CREPI_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + dom_ptr = (ST_CHAR **) (req_info + 1); /* point to where first will go */ + num_vstr = 0; + ASN1R_TAG_ADD (aCtx, CTX, 0, crepi_get_piname); /* pi name is next */ + } + +/************************************************************************/ +/* crepi_get_piname */ +/* create program invocation REQUEST (indication) is being decoded: */ +/* decode the state. */ +/************************************************************************/ + +static ST_VOID crepi_get_piname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("crepi_get_piname"); + + if (asn1r_get_identifier (aCtx, req_info->piname))/* read the pgm invocation name */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, crepi_domain_cstr); + } + +/************************************************************************/ +/* crepi_domain_cstr */ +/* create program invocation REQUEST (indication) is being decoded: */ +/* domain name list constructor was encountered. */ +/************************************************************************/ + +static ST_VOID crepi_domain_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("crepi_domain_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, crepi_get_domain_name); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = crepi_domain_cstr_done; + } + +/************************************************************************/ +/* crepi_get_domain_name */ +/* create program invocation REQUEST (indication) is being decoded: */ +/* domain name was encountered. */ +/************************************************************************/ + +static ST_VOID crepi_get_domain_name (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("crepi_get_domain_name"); + + req_info->num_of_dnames++; /* increment # of domain names */ + + num_vstr++; /* increment number of vstr */ + if (num_vstr > max_vstr) + { /* too many visible strings */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + /* copy domain name back onto itself shifted by one character */ + *dom_ptr = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_identifier (aCtx, *dom_ptr)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + dom_ptr++; /* point to where next will go */ + + asn1r_tag_restore (aCtx); + } + +/************************************************************************/ +/* crepi_domain_cstr_done */ +/* create program invocation REQUEST (indication) is being decoded: */ +/* domain name list constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID crepi_domain_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + req_info->reusable = SD_TRUE; /* SD_TRUE us default value */ + ASN1R_TAG_ADD (aCtx, CTX, 2, crepi_get_reusable); + ASN1R_TAG_ADD (aCtx, CTX, 3, crepi_get_monitor); + + /* find actual size for request info */ + req_size = (ST_CHAR *)dom_ptr - ((ST_CHAR *) req_info) + 1; + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (CREPI_REQ_INFO *) _mms_dec_info; + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +/************************************************************************/ +/* crepi_get_reusable */ +/* create program invocation REQUEST (indication) is being decoded: */ +/* decode the reusable flag. */ +/************************************************************************/ + +static ST_VOID crepi_get_reusable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("crepi_get_reusable"); + + if (asn1r_get_bool (aCtx, &(req_info->reusable))) /* read reusable from message */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + ASN1R_TAG_ADD (aCtx, CTX, 3, crepi_get_monitor); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* crepi_get_monitor */ +/* create program invocation REQUEST (indication) is being decoded: */ +/* decode the monitor flag. */ +/************************************************************************/ + +static ST_VOID crepi_get_monitor (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("crepi_get_monitor"); + + req_info->monitor_pres = SD_TRUE; /* set monitor present */ + + if (asn1r_get_bool (aCtx, &(req_info->monitor))) /* read monitor from message */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_crepi_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the create program invocation response. */ +/************************************************************************/ + +ST_RET mp_crepi_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_CREATE_PI)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_crepi_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the create program invocation response. */ +/************************************************************************/ + +ST_RET mpl_crepi_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_CREATE_PI)); + } +#endif diff --git a/mmslib/mmsle/rs_defea.c b/mmslib/mmsle/rs_defea.c new file mode 100644 index 0000000..aec5158 --- /dev/null +++ b/mmslib/mmsle/rs_defea.c @@ -0,0 +1,315 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_defea.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of define event */ +/* action. It decodes the define event action request */ +/* (indication) & encodes the define event action response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 04/28/00 JRB 04 Lint cleanup */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DEFEA_REQ_INFO *req_info; + +#ifdef MOD_SUPPORT +static MODIFIER *mod_ptr; +static ST_INT max_modifiers; +#endif + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/* static functions with multiple references */ +static ST_VOID defea_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID defea_name_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defea_name_cstr_done (ASN1_DEC_CTXT *aCtx); +#ifdef MOD_SUPPORT +static ST_VOID defea_get_modlist (ASN1_DEC_CTXT *aCtx); +static ST_VOID defea_modlist_done (ASN1_DEC_CTXT *aCtx); +#endif +static ST_VOID defea_get_conf_serv_req (ASN1_DEC_CTXT *aCtx); +static ST_VOID defea_conf_serv_req_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defea_conf_serv_cstr_done (ASN1_DEC_CTXT *aCtx); +#ifdef CS_SUPPORT +static ST_VOID defea_cs_rdetail_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID defea_cs_rdetail_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defea_cs_rdetail_cstr_done (ASN1_DEC_CTXT *aCtx); +#endif + +/************************************************************************/ +/************************************************************************/ +/* mms_defea_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_defea_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Define Event Action Request"); + /* find maximum size for request info */ + +#if defined(FIXED_DECBUF) + max_modifiers = 0; + req_size = sizeof (DEFEA_REQ_INFO); +#else +#ifdef MOD_SUPPORT + max_modifiers = _mmsdec_msglen / 2; + req_size = sizeof (DEFEA_REQ_INFO) + + (sizeof (MODIFIER) * max_modifiers); +#else + req_size = sizeof (DEFEA_REQ_INFO); +#endif +#endif + +/* get storage for request information */ + req_info = (DEFEA_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + + +/* req_info->modlist_pres = SD_FALSE; set default values */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, defea_name_cstr); + } + +/************************************************************************/ +/* defea_name_cstr */ +/* define event action request is being decoded: event action name */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID defea_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defea_name_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->evact_name, defea_name_done); + } + +/************************************************************************/ +/* defea_name_done */ +/* define event action request is being decoded: event action name */ +/* has been obtained. */ +/************************************************************************/ + +static ST_VOID defea_name_done (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defea_name_cstr_done; + } + +/************************************************************************/ +/* defea_name_cstr_done */ +/* define event action request is being decoded: event action name */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID defea_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + +#ifdef MOD_SUPPORT + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, defea_get_modlist); +#endif + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, defea_get_conf_serv_req); +#ifdef CS_SUPPORT + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,79, defea_cs_rdetail_cstr); +#endif + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +#ifdef MOD_SUPPORT +/************************************************************************/ +/* defea_get_modlist */ +/* Decoding define event action request: list of modifiers constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID defea_get_modlist (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defea_get_modlist"); + + req_info->modlist_pres = SD_TRUE; /* list of modifiers present */ + + mod_ptr = (MODIFIER *) (req_info + 1); + + _ms_get_mms_modlist (aCtx, mod_ptr, &req_info->num_of_modifiers, + max_modifiers, defea_modlist_done); + } + +/************************************************************************/ +/* defea_modlist_done */ +/* Decoding define event action request: list of modifiers constructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID defea_modlist_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defea_modlist_done"); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, defea_get_conf_serv_req); +#ifdef CS_SUPPORT + ASN1R_TAG_ADD (aCtx, CTX | CONSTR,79, defea_cs_rdetail_cstr); +#endif + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } +#endif + +/************************************************************************/ +/* defea_get_conf_serv_req */ +/* Decoding define event action request: confirmed service request */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID defea_get_conf_serv_req (ASN1_DEC_CTXT *aCtx) + { +#ifdef MOD_SUPPORT +ST_INT req_size; +#endif + + MLOG_CDEC0 ("defea_get_conf_serv_req"); + /* find actual size for request info */ +#ifdef MOD_SUPPORT + req_size = sizeof (DEFEA_REQ_INFO) + + (sizeof (MODIFIER)*req_info->num_of_modifiers); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info, req_size); + req_info = (DEFEA_REQ_INFO *) _mms_dec_info; +#endif + + /* get the confirmed service request */ + req_info->conf_serv_req = aCtx->asn1r_field_ptr; + + asn1r_parse_next (aCtx, defea_conf_serv_req_done); /* parse the contents */ + } + +/************************************************************************/ +/* defea_conf_serv_req_done */ +/* Decoding define event action request: confirmed service request */ +/* has been obtained. */ +/************************************************************************/ + +static ST_VOID defea_conf_serv_req_done (ASN1_DEC_CTXT *aCtx) + { + req_info->conf_serv_req_len = aCtx->asn1r_octetcount; /* save length */ + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defea_conf_serv_cstr_done; + } + +/************************************************************************/ +/* defea_conf_serv_cstr_done */ +/* Decoding define event action request: confirmed service request */ +/* constructor done has been encountered. */ +/************************************************************************/ + +static ST_VOID defea_conf_serv_cstr_done (ASN1_DEC_CTXT *aCtx) + { +#ifdef CS_SUPPORT + /* check for Companion Standard request detail */ + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 79, defea_cs_rdetail_cstr); +#endif + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +#ifdef CS_SUPPORT +/************************************************************************/ +/* defea_cs_rdetail_cstr */ +/* Decoding define event action request: companion standard request */ +/* detail constructor has been encountered. */ +/************************************************************************/ + +static ST_VOID defea_cs_rdetail_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defea_cs_rdetail_cstr"); + + req_info->cs_rdetail_pres = SD_TRUE; /* set the present flag */ + + /* leave CS response detail in place; just parse it. */ + req_info->cs_rdetail = aCtx->asn1r_field_ptr; + asn1r_parse_next (aCtx, defea_cs_rdetail_done); + } + +/************************************************************************/ +/* defea_cs_rdetail_done */ +/* event notification request is being decoded: action result success: */ +/* companion standard response detail has been parsed. */ +/************************************************************************/ + +static ST_VOID defea_cs_rdetail_done (ASN1_DEC_CTXT *aCtx) + { + req_info->cs_rdetail_len = aCtx->asn1r_octetcount; /* save length */ + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defea_cs_rdetail_cstr_done; + } + +/************************************************************************/ +/* defea_cs_rdetail_cstr_done */ +/* event notification request is being decoded: action result success: */ +/* confirmed service response cstr done has been encountered. */ +/************************************************************************/ + +static ST_VOID defea_cs_rdetail_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } +#endif + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_defea_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the define event action response. */ +/************************************************************************/ + +ST_RET mp_defea_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_DEF_EA)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_defea_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the define event action response. */ +/************************************************************************/ + +ST_RET mpl_defea_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_DEF_EA)); + } +#endif diff --git a/mmslib/mmsle/rs_defec.c b/mmslib/mmsle/rs_defec.c new file mode 100644 index 0000000..b68cbca --- /dev/null +++ b/mmslib/mmsle/rs_defec.c @@ -0,0 +1,290 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_defec.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of define event */ +/* condition. It decodes the define event condition request */ +/* (indication) & encodes the define event condition response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DEFEC_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID defec_get_severity (ASN1_DEC_CTXT *aCtx); +static ST_VOID defec_get_as_reports (ASN1_DEC_CTXT *aCtx); +static ST_VOID defec_monitored_var_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID defec_get_eval_int (ASN1_DEC_CTXT *aCtx); +static ST_VOID defec_monitored_var_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defec_var_spec_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defec_get_priority (ASN1_DEC_CTXT *aCtx); +static ST_VOID defec_get_ec_class (ASN1_DEC_CTXT *aCtx); +static ST_VOID defec_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defec_name_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defec_name_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_defec_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_defec_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Define Event Condition Request"); + + +/* get storage for request information */ + req_info = (DEFEC_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (DEFEC_REQ_INFO)); + + req_info->priority = MMS_NORM_PRIORITY; /* set default value */ + req_info->severity = MMS_NORM_SEVERITY; +/* req_info->as_reports = SD_FALSE; */ +/* req_info->addl_detail_pres = SD_FALSE; */ +/* req_info->mon_var_pres = SD_FALSE; */ +/* req_info->eval_int_pres = SD_FALSE; */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, defec_name_cstr); + } + +/************************************************************************/ +/* defec_name_cstr */ +/* define event condition request is being decoded: event condition */ +/* name constructor was encountered. */ +/************************************************************************/ + +static ST_VOID defec_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defec_name_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->evcon_name, defec_name_done); + } + +/************************************************************************/ +/* defec_name_done */ +/* define event condition request is being decoded: event condition */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID defec_name_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defec_name_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defec_name_cstr_done; + } + +/************************************************************************/ +/* defec_name_cstr_done */ +/* define event condition request is being decoded: event condition */ +/* name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID defec_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, defec_get_ec_class); + } + +/************************************************************************/ +/* defec_get_ec_class */ +/* Decoding define event condition request: ec class was encountered. */ +/************************************************************************/ + +static ST_VOID defec_get_ec_class (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defec_get_ec_class"); + /* read event condition class */ + if (asn1r_get_i16 (aCtx, &(req_info->eclass))) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + else if ((req_info->eclass < 0) || (req_info->eclass > 1)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 2, defec_get_priority); + ASN1R_TAG_ADD (aCtx, CTX, 3, defec_get_severity); + ASN1R_TAG_ADD (aCtx, CTX, 4, defec_get_as_reports); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 6, defec_monitored_var_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 7, defec_get_eval_int); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* defec_get_priority */ +/* Decoding define event condition request: priority was encountered. */ +/************************************************************************/ + +static ST_VOID defec_get_priority (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defec_get_priority"); + /* read priority */ + if (asn1r_get_u8 (aCtx, &(req_info->priority))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 3, defec_get_severity); + ASN1R_TAG_ADD (aCtx, CTX, 4, defec_get_as_reports); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 6, defec_monitored_var_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 7, defec_get_eval_int); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* defec_get_severity */ +/* Decoding define event condition request: severity was encountered. */ +/************************************************************************/ + +static ST_VOID defec_get_severity (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defec_get_severity"); + /* read severity */ + if (asn1r_get_u8 (aCtx, &(req_info->severity))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 4, defec_get_as_reports); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 6, defec_monitored_var_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 7, defec_get_eval_int); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* defec_get_as_reports */ +/* Decoding define event condition request: alarm summary reports was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID defec_get_as_reports (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defec_get_as_reports"); + + req_info->as_reports_pres = SD_TRUE; /* set present flag */ + /* read alarm summary reports */ + if (asn1r_get_bool (aCtx, &(req_info->as_reports))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 6, defec_monitored_var_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 7, defec_get_eval_int); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* defec_monitored_var_cstr */ +/* Decoding define event condition request: monitored variable was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID defec_monitored_var_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defec_monitored_var_cstr"); + + req_info->mon_var_pres = SD_TRUE; /* set present flag */ + + _ms_get_va_var_spec (aCtx, &req_info->var_ref, defec_var_spec_done); + } + +/************************************************************************/ +/* defec_var_spec_done */ +/************************************************************************/ + +static ST_VOID defec_var_spec_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defec_var_spec_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defec_monitored_var_cstr_done; + } + +/************************************************************************/ +/* defec_monitored_var_cstr_done */ +/* Decoding define event condition request: monitored variable constr */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID defec_monitored_var_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX, 7, defec_get_eval_int); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* defec_get_eval_int */ +/* Decoding define event condition request: evaluation interval was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID defec_get_eval_int (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defec_get_eval_int"); + + req_info->eval_int_pres = SD_TRUE; + /* read evaluation interval */ + if (asn1r_get_u32 (aCtx, &(req_info->eval_interval))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_defec_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the define event condition response. */ +/************************************************************************/ + +ST_RET mp_defec_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_DEF_EC)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_defec_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the define event condition response. */ +/************************************************************************/ + +ST_RET mpl_defec_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_DEF_EC)); + } +#endif diff --git a/mmslib/mmsle/rs_defsc.c b/mmslib/mmsle/rs_defsc.c new file mode 100644 index 0000000..85dfa41 --- /dev/null +++ b/mmslib/mmsle/rs_defsc.c @@ -0,0 +1,169 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_defscat.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of define scattered */ +/* access. It decodes the define scattered access request */ +/* (indication) and encodes the define scattered access response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DEFSCAT_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID defscat_scat_acc_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defscat_scat_acc_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defscat_scat_acc_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID defscat_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defscat_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defscat_name_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_def_scat_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_def_scat_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Define Scattered Access Request"); + +/* get storage for request information */ + req_info = (DEFSCAT_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (DEFSCAT_REQ_INFO)); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, defscat_name_cstr); + } + +/************************************************************************/ +/* defscat_name_cstr */ +/* define scattered access request: scattered access name constr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID defscat_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defscat_name_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->sa_name, defscat_objname_done); + } + +/************************************************************************/ +/* defscat_objname_done */ +/* define scattered access request: scattered access name has been */ +/* decoded. */ +/************************************************************************/ + +static ST_VOID defscat_objname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defscat_objname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defscat_name_cstr_done; + } + +/************************************************************************/ +/* defscat_name_cstr_done */ +/* define scattered access request: scattered access name constructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID defscat_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, defscat_scat_acc_cstr); + } + +/************************************************************************/ +/* defscat_address_cstr */ +/* define scattered access request: scattered access constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID defscat_scat_acc_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defscat_scat_acc_cstr"); + + _ms_get_va_scat_access (aCtx, &req_info->sa_descr, defscat_scat_acc_done); + } + +/************************************************************************/ +/* defscat_scat_acc_done */ +/* define scattered access request: scattered access has been decoded. */ +/************************************************************************/ + +static ST_VOID defscat_scat_acc_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defscat_scat_acc_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defscat_scat_acc_cstr_done; + } + +/************************************************************************/ +/* defscat_scat_acc_cstr_done */ +/* define scattered access request: scattered access constr done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID defscat_scat_acc_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_defscat_resp */ +/* Create and send a define scattered access response. */ +/************************************************************************/ + +ST_RET mp_defscat_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_DEF_SCAT)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_defscat_resp */ +/* Create a define scattered access response. */ +/************************************************************************/ + +ST_RET mpl_defscat_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_DEF_SCAT)); + } +#endif diff --git a/mmslib/mmsle/rs_defse.c b/mmslib/mmsle/rs_defse.c new file mode 100644 index 0000000..5e9c22b --- /dev/null +++ b/mmslib/mmsle/rs_defse.c @@ -0,0 +1,147 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_defsem.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the define */ +/* semaphore operation. It decodes the define semaphore request */ +/* (indication) and encodes the define semaphore response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 08/28/03 EJV 05 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_psem.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DEFSEM_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID defsem_sem_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defsem_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defsem_sem_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID defsem_get_num_of_tokens (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_defsem_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_defsem_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Define Semaphore Request"); + +/* get storage for request information */ + req_info = (DEFSEM_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (DEFSEM_REQ_INFO)); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, defsem_sem_name_cstr); + } + +/************************************************************************/ +/* defsem_sem_name_cstr */ +/* Decoding define semaphore request: semaphore name constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID defsem_sem_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Define Semaphore Request"); + _ms_get_mms_objname (aCtx, &req_info->sem_name, defsem_objname_done); + } + +/************************************************************************/ +/* defsem_objname_done */ +/* Decoding Define Semaphore Request: Semaphore name has been obtained. */ +/************************************************************************/ + +static ST_VOID defsem_objname_done (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defsem_sem_name_cstr_done; + } + +/************************************************************************/ +/* defsem_sem_name_cstr_done */ +/* Decoding define semaphore request: semaphore name contructor done */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID defsem_sem_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, defsem_get_num_of_tokens); + } + +/************************************************************************/ +/* defsem_get_num_of_tokens */ +/* Decoding define semaphore request: number of tokens name was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID defsem_get_num_of_tokens (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defsem_get_num_of_tokens"); + + /* read number of tokens from received message */ + if (asn1r_get_u16 (aCtx, &(req_info->num_of_tokens))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_defsem_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the define semaphore response. */ +/************************************************************************/ + +ST_RET mp_defsem_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_DEFINE_SEM)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_defsem_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the define semaphore response. */ +/************************************************************************/ + +ST_RET mpl_defsem_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_DEFINE_SEM)); + } +#endif diff --git a/mmslib/mmsle/rs_defty.c b/mmslib/mmsle/rs_defty.c new file mode 100644 index 0000000..568a6fa --- /dev/null +++ b/mmslib/mmsle/rs_defty.c @@ -0,0 +1,116 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_deftype.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of define named */ +/* type. It decodes the define named type request (indication) */ +/* and encodes the define named type response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DEFTYPE_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID deftype_typespec_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID deftype_objname_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_def_type_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_def_type_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Define Named Type Request"); + +/* get storage for request information */ + req_info = (DEFTYPE_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (DEFTYPE_REQ_INFO)); + + _ms_get_mms_objname (aCtx, &req_info->type_name, deftype_objname_done); + } + +/************************************************************************/ +/* deftype_objname_done */ +/* define named type request: type name has been decoded. */ +/************************************************************************/ + +static ST_VOID deftype_objname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("deftype_objname_done"); + + _ms_get_va_type_spec (aCtx, &req_info->type_spec, deftype_typespec_done); + } + +/************************************************************************/ +/* deftype_typespec_done */ +/* define named type request: type specification has been decoded. */ +/************************************************************************/ + +static ST_VOID deftype_typespec_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("deftype_typespec_done"); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_deftype_resp */ +/* Create and send a define named type response. */ +/************************************************************************/ + +ST_RET mp_deftype_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_DEF_TYPE)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_deftype_resp */ +/* Create a define named type response. */ +/************************************************************************/ + +ST_RET mpl_deftype_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_DEF_TYPE)); + } +#endif diff --git a/mmslib/mmsle/rs_defva.c b/mmslib/mmsle/rs_defva.c new file mode 100644 index 0000000..3462a70 --- /dev/null +++ b/mmslib/mmsle/rs_defva.c @@ -0,0 +1,198 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_defvar.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of define named */ +/* variable. It decodes the define named variable request */ +/* (indication) and encodes the define named variable response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DEFVAR_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID defvar_typespec_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID defvar_address_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defvar_address_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defvar_address_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID defvar_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defvar_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defvar_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID defvar_typespec_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_def_var_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_def_var_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Define Named Variable Request"); + +/* get storage for request information */ + req_info = (DEFVAR_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (DEFVAR_REQ_INFO)); + req_info->type_spec_pres = SD_FALSE; /* set default value */ + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, defvar_name_cstr); + } + +/************************************************************************/ +/* defvar_name_cstr */ +/* define named variable request: variable name constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID defvar_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defvar_name_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->name, defvar_objname_done); + } + +/************************************************************************/ +/* defvar_objname_done */ +/* define named variable request: variable name has been decoded. */ +/************************************************************************/ + +static ST_VOID defvar_objname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defvar_objname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defvar_name_cstr_done; + } + +/************************************************************************/ +/* defvar_name_cstr_done */ +/* define named variable request: variable name constructor done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID defvar_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, defvar_address_cstr); + } + +/************************************************************************/ +/* defvar_address_cstr */ +/* define named variable request: address constructor was encountered. */ +/************************************************************************/ + +static ST_VOID defvar_address_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defvar_address_cstr"); + + _ms_get_va_address (aCtx, &req_info->address, defvar_address_done); + } + +/************************************************************************/ +/* defvar_address_done */ +/* define named variable request: address has been decoded. */ +/************************************************************************/ + +static ST_VOID defvar_address_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defvar_address_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = defvar_address_cstr_done; + } + +/************************************************************************/ +/* defvar_address_cstr_done */ +/* define named variable request: address constructor done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID defvar_address_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, defvar_typespec_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* defvar_typespec_cstr */ +/* define named variable request: type spec constructor was encountered */ +/************************************************************************/ + +static ST_VOID defvar_typespec_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defvar_typespec_cstr"); + + req_info->type_spec_pres = SD_TRUE; /* set type specification pres */ + + _ms_get_va_type_spec (aCtx, &req_info->type_spec, defvar_typespec_done); + } + +/************************************************************************/ +/* defvar_typespec_done */ +/* define named type request: type specification has been decoded. */ +/************************************************************************/ + +static ST_VOID defvar_typespec_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("defvar_typespec_done"); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_defvar_resp */ +/* Create and send a define named variable response. */ +/************************************************************************/ + +ST_RET mp_defvar_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_DEF_VAR)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_defvar_resp */ +/* Create a define named variable response. */ +/************************************************************************/ + +ST_RET mpl_defvar_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_DEF_VAR)); + } +#endif diff --git a/mmslib/mmsle/rs_defvl.c b/mmslib/mmsle/rs_defvl.c new file mode 100644 index 0000000..27cfa1b --- /dev/null +++ b/mmslib/mmsle/rs_defvl.c @@ -0,0 +1,177 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_defvlist.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of define named */ +/* variable list. It decodes the define named variable list */ +/* request (indication) & encodes the define named variable list */ +/* response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 08 Remove "thisFileName" */ +/* 12/20/01 JRB 07 Converted to use ASN1R (re-entrant ASN1) */ +/* 08/21/01 JRB 06 Don't allow compile if INT_MAX not defined. */ +/* 06/22/01 RKR 05 Added limits.h */ +/* 04/27/00 MDE 04 Lint cleanup */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include +#ifndef INT_MAX +#error INT_MAX must be defined. Usually defined in limits.h +#endif +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static VARIABLE_LIST *vlist_ptr; +static ST_INT max_num_vars; + +static DEFVLIST_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID defvlist_list_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID defvlist_get_varlist (ASN1_DEC_CTXT *aCtx); +static ST_VOID defvlist_name_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_def_vlist_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +/* This is used to restrict the maximum buffer size to 0xFF00, which is */ +/* close to the max allowed for the chk_xxx series for 16 bit systems */ +#define MAX_ALLOWED_VARS ((0xFF00 - sizeof (DEFVLIST_REQ_INFO)) / sizeof (VARIABLE_LIST)) + + +ST_VOID mms_def_vlist_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Define Named Variable List Request"); + +#if defined(FIXED_DECBUF) + max_num_vars = m_sv_max_num_vars; + req_size = mmsl_dec_info_size; +#else + max_num_vars = _mmsdec_msglen / 2; + if (m_sv_max_num_vars && (max_num_vars > m_sv_max_num_vars)) + max_num_vars = m_sv_max_num_vars; + + /* verify buffer size is allocatable */ +#if (INT_MAX <= 0x7FFF) + if (max_num_vars > MAX_ALLOWED_VARS) + max_num_vars = MAX_ALLOWED_VARS; +#endif + + req_size = sizeof(DEFVLIST_REQ_INFO) + + (sizeof(VARIABLE_LIST) * max_num_vars); +#endif + +/* get storage for request information */ + req_info = (DEFVLIST_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + vlist_ptr = (VARIABLE_LIST *) (req_info + 1); + + _ms_get_mms_objname (aCtx, &req_info->vl_name, defvlist_name_done); + } + +/************************************************************************/ +/* defvlist_name_done */ +/* decoding define named variable list request: variable list name has */ +/* been obtained. */ +/************************************************************************/ + +static ST_VOID defvlist_name_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, defvlist_get_varlist); + } + +/************************************************************************/ +/* defvlist_get_varlist */ +/* decoding define named variable list request: list of variables */ +/* constructor has been obtained. */ +/************************************************************************/ + +static ST_VOID defvlist_get_varlist (ASN1_DEC_CTXT *aCtx) + { + + req_info->num_of_variables = 0; + _ms_get_va_var_list (aCtx, vlist_ptr, &req_info->num_of_variables, + max_num_vars, defvlist_list_done); + } + +/************************************************************************/ +/* defvlist_list_done */ +/* decoding define named variable list request: list of variables has */ +/* been obtained. */ +/************************************************************************/ + +static ST_VOID defvlist_list_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + /* find actual size for request info */ + req_size = sizeof (DEFVLIST_REQ_INFO) + + (sizeof (VARIABLE_LIST)*req_info->num_of_variables); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info, req_size); + req_info = (DEFVLIST_REQ_INFO *) _mms_dec_info; + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_defvlist_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the define named variable list response. */ +/************************************************************************/ + +ST_RET mp_defvlist_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_DEF_VLIST)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_defvlist_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the define named variable list response. */ +/************************************************************************/ + +ST_RET mpl_defvlist_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_DEF_VLIST)); + } +#endif diff --git a/mmslib/mmsle/rs_deldo.c b/mmslib/mmsle/rs_deldo.c new file mode 100644 index 0000000..6adc2c6 --- /dev/null +++ b/mmslib/mmsle/rs_deldo.c @@ -0,0 +1,96 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_deldom.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of delete domain. */ +/* It decodes the delete domain request (indication) & encodes */ +/* the delete domain response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 08/28/03 EJV 05 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : NONE */ + +static DELDOM_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_delete_domain_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_delete_domain_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Delete Domain Request"); + + +/* get storage for request information */ + req_info = (DELDOM_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (DELDOM_REQ_INFO)); + /* read doamin name from received message */ + if (asn1r_get_identifier (aCtx, req_info->dname)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_deldom_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the delete domain response. */ +/************************************************************************/ + +ST_RET mp_deldom_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_DELETE_DOMAIN)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_deldom_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the delete domain response. */ +/************************************************************************/ + +ST_RET mpl_deldom_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_DELETE_DOMAIN)); + } +#endif diff --git a/mmslib/mmsle/rs_delea.c b/mmslib/mmsle/rs_delea.c new file mode 100644 index 0000000..3c38da2 --- /dev/null +++ b/mmslib/mmsle/rs_delea.c @@ -0,0 +1,250 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_delea.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of delete event */ +/* action. It decodes the delete event action request */ +/* (indication) and encodes the delete event action response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DELEA_REQ_INFO *req_info; + +static OBJECT_NAME *obj_ptr; +static ST_INT max_obj_name; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID delea_name_list_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID delea_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID delea_name_list_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID delea_get_aa_spec (ASN1_DEC_CTXT *aCtx); +static ST_VOID delea_get_domain (ASN1_DEC_CTXT *aCtx); +static ST_VOID delea_get_vmd (ASN1_DEC_CTXT *aCtx); +static ST_VOID delea_dec_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_delea_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_delea_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Delete Event Action Request"); + +#if defined(FIXED_DECBUF) + max_obj_name = m_sv_max_obj_name; + req_size = mmsl_dec_info_size; +#else + max_obj_name = _mmsdec_msglen / 2; /* find maximum size */ + if (m_sv_max_obj_name && (max_obj_name > m_sv_max_obj_name)) + max_obj_name = m_sv_max_obj_name; + req_size = sizeof (DELEA_REQ_INFO) + (sizeof (OBJECT_NAME) * max_obj_name); +#endif + +/* get storage for request information */ + req_info = (DELEA_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, delea_name_list_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 1, delea_get_aa_spec); + ASN1R_TAG_ADD (aCtx, CTX, 3, delea_get_domain); + ASN1R_TAG_ADD (aCtx, CTX, 4, delea_get_vmd); + } + +/************************************************************************/ +/* delea_name_list_cstr */ +/* decoding delete event action request: decode the specific name list */ +/* constructor. */ +/************************************************************************/ + +static ST_VOID delea_name_list_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delea_name_list_cstr"); + + req_info->req_tag = 0; /* set tag to specific */ + obj_ptr = (OBJECT_NAME *) (req_info + 1); + + _ms_get_mms_objname (aCtx, obj_ptr, delea_objname_done); + + /* set the cstr done function */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = delea_name_list_cstr_done; + } + +/************************************************************************/ +/* delea_objname_done */ +/* decoding delete event action request: object name has been */ +/* decoded. */ +/************************************************************************/ + +static ST_VOID delea_objname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delea_objname_done"); + + req_info->num_of_names++; /* inc # of variable names */ + if (req_info->num_of_names > max_obj_name) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + else + { + obj_ptr++; /* point to where next will go */ + _ms_get_mms_objname (aCtx, obj_ptr, delea_objname_done); + } + } + +/************************************************************************/ +/* delea_name_list_cstr_done */ +/* decoding delete event action request: specific name list constr */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID delea_name_list_cstr_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_done_fun = delea_dec_done; + _ms_set_cs_check2 (aCtx); + } + +/************************************************************************/ +/* delea_get_aa_spec */ +/* decoding delete event action request: aa specific was encountered */ +/************************************************************************/ + +static ST_VOID delea_get_aa_spec (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delea_get_aa_spec"); + + req_info->req_tag = 1; /* set tag to aa specific */ + aCtx->asn1r_decode_done_fun = delea_dec_done; + _ms_set_cs_check2 (aCtx); + } + +/************************************************************************/ +/* delea_get_domain */ +/* decoding delete event action request: domain was encountered. */ +/************************************************************************/ + +static ST_VOID delea_get_domain (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delea_get_domain"); + + req_info->req_tag = 3; /* set tag to domain */ + + if (asn1r_get_identifier (aCtx, req_info->dname))/* read the domain name */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + aCtx->asn1r_decode_done_fun = delea_dec_done; + _ms_set_cs_check2 (aCtx); + } + +/************************************************************************/ +/* delea_get_vmd */ +/* decoding delete event action request: vmd was encountered. */ +/************************************************************************/ + +static ST_VOID delea_get_vmd (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delea_get_vmd"); + + req_info->req_tag = 4; /* set tag to vmd */ + aCtx->asn1r_decode_done_fun = delea_dec_done; + _ms_set_cs_check2 (aCtx); + } + +/************************************************************************/ +/* delea_dec_done */ +/* decode done, realloc the structure to desired size */ +/************************************************************************/ + +static ST_VOID delea_dec_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + /* find actual size for request info */ + req_size = sizeof (DELEA_REQ_INFO) + + (sizeof (OBJECT_NAME) * req_info->num_of_names); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (DELEA_REQ_INFO *) _mms_dec_info; + + _mms_dec_done_ok (aCtx); + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_delea_resp */ +/* Create and send a delete event action response. */ +/************************************************************************/ + +ST_RET mp_delea_resp (MMSREQ_IND *indptr, DELEA_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_DEL_EA,indptr, + M_CAST_MK_FUN (_ms_mk_delea_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_delea_resp */ +/* Create a delete event action response. */ +/************************************************************************/ + +ST_RET mpl_delea_resp (ST_UINT32 invoke_id, DELEA_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_DEL_EA,invoke_id, + M_CAST_MK_FUN (_ms_mk_delea_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_delea_resp */ +/* construct a delete event action response. */ +/************************************************************************/ + +ST_VOID _ms_mk_delea_resp (ASN1_ENC_CTXT *aCtx, DELEA_RESP_INFO *info) + { + asn1r_wr_u32 (aCtx, info->cand_not_deleted); /* canditates not deleted */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_DEL_EA,CTX); /* tag = opcode, ctx primitive */ + } diff --git a/mmslib/mmsle/rs_delec.c b/mmslib/mmsle/rs_delec.c new file mode 100644 index 0000000..20609ab --- /dev/null +++ b/mmslib/mmsle/rs_delec.c @@ -0,0 +1,250 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_delec.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of delete event */ +/* condition. It decodes the delete event condition request */ +/* (indication) and encodes the delete event condition response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DELEC_REQ_INFO *req_info; + +static OBJECT_NAME *obj_ptr; +static ST_INT max_obj_name; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID delec_dec_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID delec_name_list_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID delec_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID delec_name_list_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID delec_get_aa_spec (ASN1_DEC_CTXT *aCtx); +static ST_VOID delec_get_domain (ASN1_DEC_CTXT *aCtx); +static ST_VOID delec_get_vmd (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_delec_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_delec_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Delete Event Condition Request"); + +#if defined(FIXED_DECBUF) + max_obj_name = m_sv_max_obj_name; + req_size = mmsl_dec_info_size; +#else + max_obj_name = _mmsdec_msglen / 2; /* find maximum size */ + if (m_sv_max_obj_name && (max_obj_name > m_sv_max_obj_name)) + max_obj_name = m_sv_max_obj_name; + req_size = sizeof (DELEC_REQ_INFO) + (sizeof (OBJECT_NAME) * max_obj_name); +#endif + +/* get storage for request information */ + req_info = (DELEC_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, delec_name_list_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 1, delec_get_aa_spec); + ASN1R_TAG_ADD (aCtx, CTX, 2, delec_get_domain); + ASN1R_TAG_ADD (aCtx, CTX, 3, delec_get_vmd); + } + +/************************************************************************/ +/* delec_name_list_cstr */ +/* decoding delete event condition request: decode the specific */ +/* name list constructor. */ +/************************************************************************/ + +static ST_VOID delec_name_list_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delec_name_list_cstr"); + + req_info->req_tag = 0; /* set tag to specific */ + obj_ptr = (OBJECT_NAME *) (req_info + 1); + + _ms_get_mms_objname (aCtx, obj_ptr, delec_objname_done); + + /* set the cstr done function */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = delec_name_list_cstr_done; + } + +/************************************************************************/ +/* delec_objname_done */ +/* decoding delete event condition request: object name has been */ +/* decoded. */ +/************************************************************************/ + +static ST_VOID delec_objname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delec_objname_done"); + + req_info->num_of_names++; /* inc # of variable names */ + if (req_info->num_of_names > max_obj_name) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + else + { + obj_ptr++; /* point to where next will go */ + _ms_get_mms_objname (aCtx, obj_ptr, delec_objname_done); + } + } + +/************************************************************************/ +/* delec_name_list_cstr_done */ +/* decoding delete event condition request: specific name list constr */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID delec_name_list_cstr_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_done_fun = delec_dec_done; + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* delec_get_aa_spec */ +/* decoding delete event condition request: aa specific was encountered */ +/************************************************************************/ + +static ST_VOID delec_get_aa_spec (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delec_get_aa_spec"); + + req_info->req_tag = 1; /* set tag to aa specific */ + aCtx->asn1r_decode_done_fun = delec_dec_done; + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* delec_get_domain */ +/* decoding delete event condition request: domain was encountered. */ +/************************************************************************/ + +static ST_VOID delec_get_domain (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delec_get_domain"); + + req_info->req_tag = 2; /* set tag to domain */ + + if (asn1r_get_identifier (aCtx, req_info->dname))/* read the domain name */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + aCtx->asn1r_decode_done_fun = delec_dec_done; + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* delec_get_vmd */ +/* decoding delete event condition request: vmd was encountered. */ +/************************************************************************/ + +static ST_VOID delec_get_vmd (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delec_get_vmd"); + + req_info->req_tag = 3; /* set tag to vmd */ + aCtx->asn1r_decode_done_fun = delec_dec_done; + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* delec_dec_done */ +/* decode done, realloc the structure to desired size */ +/************************************************************************/ + +static ST_VOID delec_dec_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + /* find actual size for request info */ + req_size = sizeof (DELEC_REQ_INFO) + + (sizeof (OBJECT_NAME) * req_info->num_of_names); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (DELEC_REQ_INFO *) _mms_dec_info; + + _mms_dec_done_ok (aCtx); + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_delec_resp */ +/* Create and send a delete event condition response. */ +/************************************************************************/ + +ST_RET mp_delec_resp (MMSREQ_IND *indptr, DELEC_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_DEL_EC,indptr, + M_CAST_MK_FUN (_ms_mk_delec_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_delec_resp */ +/* Create a delete event condition response. */ +/************************************************************************/ + +ST_RET mpl_delec_resp (ST_UINT32 invoke_id, DELEC_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_DEL_EC,invoke_id, + M_CAST_MK_FUN (_ms_mk_delec_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_delec_resp */ +/* construct a delete event condition response. */ +/************************************************************************/ + +ST_VOID _ms_mk_delec_resp (ASN1_ENC_CTXT *aCtx, DELEC_RESP_INFO *info) + { + asn1r_wr_u32 (aCtx, info->cand_not_deleted); /* canditates not deleted */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_DEL_EC,CTX); /* tag = opcode, ctx primitive */ + } diff --git a/mmslib/mmsle/rs_delee.c b/mmslib/mmsle/rs_delee.c new file mode 100644 index 0000000..a11c93c --- /dev/null +++ b/mmslib/mmsle/rs_delee.c @@ -0,0 +1,286 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_delee.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of delete event */ +/* enrollment. It decodes the delete event enrollment request */ +/* (indication) and encodes the delete event enrollment response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DELEE_REQ_INFO *req_info; + +static OBJECT_NAME *obj_ptr; +static ST_INT max_obj_name; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID delee_dec_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID delee_eaname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID delee_eaname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID delee_ecname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID delee_ecname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID delee_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID delee_name_list_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID delee_name_list_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID delee_ecname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID delee_eaname_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_delee_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_delee_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Delete Event Enrollment Request"); + +#if defined(FIXED_DECBUF) + max_obj_name = m_sv_max_obj_name; + req_size = mmsl_dec_info_size; +#else + max_obj_name = _mmsdec_msglen / 2; /* find maximum size */ + if (m_sv_max_obj_name && (max_obj_name > m_sv_max_obj_name)) + max_obj_name = m_sv_max_obj_name; + req_size = sizeof (DELEE_REQ_INFO) + (sizeof (OBJECT_NAME) * max_obj_name); +#endif + +/* get storage for request information */ + req_info = (DELEE_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, delee_name_list_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, delee_ecname_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, delee_eaname_cstr); + } + +/************************************************************************/ +/* delee_name_list_cstr */ +/* decoding delete event enrollment request: decode the specific name */ +/* list constructor. */ +/************************************************************************/ + +static ST_VOID delee_name_list_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delee_name_list_cstr"); + + req_info->req_tag = 0; /* set tag to specific */ + obj_ptr = (OBJECT_NAME *) (req_info + 1); + + _ms_get_mms_objname (aCtx, obj_ptr, delee_objname_done); + + /* set the cstr done function */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = delee_name_list_cstr_done; + } + +/************************************************************************/ +/* delee_objname_done */ +/* decoding delete event enrollment request: object name has been */ +/* decoded. */ +/************************************************************************/ + +static ST_VOID delee_objname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delee_objname_done"); + + req_info->sod.num_of_names++; /* inc # of object names */ + if (req_info->sod.num_of_names > max_obj_name) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + else + { + obj_ptr++; /* point to where next will go */ + _ms_get_mms_objname (aCtx, obj_ptr, delee_objname_done); + } + } + +/************************************************************************/ +/* delee_name_list_cstr_done */ +/* decoding delete event enrollment request: specific name list constr */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID delee_name_list_cstr_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_done_fun = delee_dec_done; + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* delee_ecname_cstr */ +/* decoding delete event enrollment request: event condition name cstr */ +/* was encountered */ +/************************************************************************/ + +static ST_VOID delee_ecname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delee_ecname_cstr"); + + req_info->req_tag = 1; /* set tag to event condition */ + + _ms_get_mms_objname (aCtx, &req_info->sod.evcon_name, delee_ecname_done); + } + +/************************************************************************/ +/* delee_ecname_done */ +/* delete event enrollment request is being decoded: event condition */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID delee_ecname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delee_ecname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = delee_ecname_cstr_done; + } + +/************************************************************************/ +/* delee_ecname_cstr_done */ +/* delete event enrollment request is being decoded: event condition */ +/* name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID delee_ecname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_done_fun = delee_dec_done; + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* delee_eaname_cstr */ +/* decoding delete event enrollment request: event action name cstr */ +/* was encountered */ +/************************************************************************/ + +static ST_VOID delee_eaname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delee_eaname_cstr"); + + req_info->req_tag = 2; /* set tag to event action */ + + _ms_get_mms_objname (aCtx, &req_info->sod.evact_name, delee_eaname_done); + } + +/************************************************************************/ +/* delee_eaname_done */ +/* delete event enrollment request is being decoded: event action */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID delee_eaname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("delee_eaname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = delee_eaname_cstr_done; + } + +/************************************************************************/ +/* delee_eaname_cstr_done */ +/* delete event enrollment request is being decoded: event action */ +/* name constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID delee_eaname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* delee_dec_done */ +/* decode done, realloc the structure to desired size */ +/************************************************************************/ + +static ST_VOID delee_dec_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + /* find actual size for request info */ + req_size = sizeof (DELEE_REQ_INFO) + + (sizeof (OBJECT_NAME) * req_info->sod.num_of_names); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (DELEE_REQ_INFO *) _mms_dec_info; + + _mmsdec_rslt->data_pres = SD_TRUE; + _mmsdec_rslt->data_ptr = (ST_CHAR *) req_info; + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_delee_resp */ +/* Create and send a delete event enrollment response. */ +/************************************************************************/ + +ST_RET mp_delee_resp (MMSREQ_IND *indptr, DELEE_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_DEL_EE,indptr, + M_CAST_MK_FUN (_ms_mk_delee_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_delee_resp */ +/* Create a delete event enrollment response. */ +/************************************************************************/ + +ST_RET mpl_delee_resp (ST_UINT32 invoke_id, DELEE_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_DEL_EE,invoke_id, + M_CAST_MK_FUN (_ms_mk_delee_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_delee_resp */ +/* construct a delete event enrollment response. */ +/************************************************************************/ + +ST_VOID _ms_mk_delee_resp (ASN1_ENC_CTXT *aCtx, DELEE_RESP_INFO *info) + { + asn1r_wr_u32 (aCtx, info->cand_not_deleted); /* canditates not deleted */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_DEL_EE,CTX); /* tag = opcode, ctx primitive */ + } diff --git a/mmslib/mmsle/rs_delpi.c b/mmslib/mmsle/rs_delpi.c new file mode 100644 index 0000000..8402c0c --- /dev/null +++ b/mmslib/mmsle/rs_delpi.c @@ -0,0 +1,95 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_delpi.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of delete program */ +/* invocation. It decodes the delete program invocation request */ +/* (indication) & encodes the delete program invocation response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DELPI_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_delete_pi_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_delete_pi_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Delete Program Invocation Request"); + + +/* get storage for request information */ + req_info = (DELPI_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (DELPI_REQ_INFO)); + /* read program invocation name from message */ + if (asn1r_get_identifier (aCtx, req_info->piname)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_delpi_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the delete program invocation response. */ +/************************************************************************/ + +ST_RET mp_delpi_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_DELETE_PI)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_delpi_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the delete program invocation response. */ +/************************************************************************/ + +ST_RET mpl_delpi_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_DELETE_PI)); + } +#endif diff --git a/mmslib/mmsle/rs_delse.c b/mmslib/mmsle/rs_delse.c new file mode 100644 index 0000000..9cedc53 --- /dev/null +++ b/mmslib/mmsle/rs_delse.c @@ -0,0 +1,102 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_delsem.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the delete */ +/* semaphore. It decodes the delete semaphore request (indication) */ +/* and encodes the delete semaphore response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_psem.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DELSEM_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID delsem_objname_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_delsem_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_delsem_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Delete Semaphore Request"); + +/* get storage for request information */ + req_info = (DELSEM_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (DELSEM_REQ_INFO)); + _ms_get_mms_objname (aCtx, &req_info->sem_name, delsem_objname_done); + } + +/************************************************************************/ +/* delsem_objname_done */ +/* Decoding delete semaphore request: semaphore name obtained */ +/************************************************************************/ + +static ST_VOID delsem_objname_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_delsem_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the delete semaphore response. */ +/************************************************************************/ + +ST_RET mp_delsem_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_DELETE_SEM)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_delsem_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the delete semaphore response. */ +/************************************************************************/ + +ST_RET mpl_delsem_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_DELETE_SEM)); + } +#endif diff --git a/mmslib/mmsle/rs_delty.c b/mmslib/mmsle/rs_delty.c new file mode 100644 index 0000000..72da936 --- /dev/null +++ b/mmslib/mmsle/rs_delty.c @@ -0,0 +1,251 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_deltype.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of delete named */ +/* type. It decodes the delete named type request (indication) */ +/* and encodes the delete named type response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DELTYPE_REQ_INFO *req_info; + +static OBJECT_NAME *obj_ptr; +static ST_INT max_obj_name; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ +/* static functions with multiple references */ + +static ST_VOID deltype_get_dname (ASN1_DEC_CTXT *aCtx); +static ST_VOID deltype_name_list_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID deltype_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID deltype_name_list_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID deltype_dec_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID deltype_get_scope (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_del_type_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_del_type_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Delete Named Type Request"); + +#if defined(FIXED_DECBUF) + max_obj_name = m_sv_max_obj_name; + req_size = mmsl_dec_info_size; +#else + max_obj_name = _mmsdec_msglen / 2; /* find maximum size */ + if (m_sv_max_obj_name && (max_obj_name > m_sv_max_obj_name)) + max_obj_name = m_sv_max_obj_name; + req_size = sizeof (DELTYPE_REQ_INFO) + (sizeof (OBJECT_NAME) * max_obj_name); +#endif + +/* get storage for request information */ + req_info = (DELTYPE_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + +/* req_info->tnames_pres = SD_FALSE; */ +/* req_info->num_of_tnames = ZERO_ENTRIES; */ +/* req_info->dname_pres = SD_FALSE; */ + + + ASN1R_TAG_ADD (aCtx, CTX, 0, deltype_get_scope); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, deltype_name_list_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 2, deltype_get_dname); + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + + asn1r_set_all_cstr_done (aCtx); /* clear cstr done functions */ + aCtx->asn1r_decode_done_fun = deltype_dec_done; /* ok to be done, set done fun */ + } + +/************************************************************************/ +/* deltype_get_scope */ +/* delete named type request: decode the scope. */ +/************************************************************************/ + +static ST_VOID deltype_get_scope (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("deltype_get_scope"); + /* read scope from message */ + if (asn1r_get_i16 (aCtx, &req_info->scope)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + if ((req_info->scope < 0) || (req_info->scope > 3)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); /* validate range of scope [0..3] */ + + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, deltype_name_list_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 2, deltype_get_dname); + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* deltype_name_list_cstr */ +/* delete named type request: decode the type name constructor */ +/************************************************************************/ + +static ST_VOID deltype_name_list_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("deltype_name_list_cstr"); + + req_info->tnames_pres = SD_TRUE; /* set type name list present */ + + obj_ptr = (OBJECT_NAME *) (req_info + 1); + + _ms_get_mms_objname (aCtx, obj_ptr, deltype_objname_done); + + /* set the cstr done function */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = deltype_name_list_cstr_done; + } + +/************************************************************************/ +/* deltype_objname_done */ +/* delete named type request: type name has been decoded. */ +/************************************************************************/ + +static ST_VOID deltype_objname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("deltype_objname_done"); + + req_info->num_of_tnames++; /* increment # of type names */ + if ((req_info->num_of_tnames + 1) <= max_obj_name) + { + obj_ptr++; /* point to where next will go */ + _ms_get_mms_objname (aCtx, obj_ptr, deltype_objname_done); + } + } + +/************************************************************************/ +/* deltype_name_list_cstr_done */ +/* delete named type request: end of the type name list constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID deltype_name_list_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX, 2, deltype_get_dname); + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* deltype_get_dname */ +/* delete named type request: domain name was encountered. */ +/************************************************************************/ + +static ST_VOID deltype_get_dname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("deltype_get_dname"); + + req_info->dname_pres = SD_TRUE; /* set domain name present */ + + if (asn1r_get_identifier (aCtx, req_info->dname))/* read the domain name */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* deltype_dec_done */ +/* decode done, realloc the structure to desired size */ +/************************************************************************/ + +static ST_VOID deltype_dec_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + /* find actual size for request info */ + req_size = sizeof (DELTYPE_REQ_INFO) + + (sizeof (OBJECT_NAME) * req_info->num_of_tnames); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (DELTYPE_REQ_INFO *) _mms_dec_info; + _mms_dec_done_ok (aCtx); /* decode done, set done, etc */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_deltype_resp */ +/* Create and send a delete type response. */ +/************************************************************************/ + +ST_RET mp_deltype_resp (MMSREQ_IND *indptr, DELTYPE_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_DEL_TYPE,indptr, + M_CAST_MK_FUN (_ms_mk_deltype_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_deltype_resp */ +/* Create a delete type response. */ +/************************************************************************/ + +ST_RET mpl_deltype_resp (ST_UINT32 invoke_id, DELTYPE_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_DEL_TYPE,invoke_id, + M_CAST_MK_FUN (_ms_mk_deltype_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_deltype_resp */ +/* construct a delete type response. */ +/************************************************************************/ + +ST_VOID _ms_mk_deltype_resp (ASN1_ENC_CTXT *aCtx, DELTYPE_RESP_INFO *info) + { + asn1r_wr_u32 (aCtx, info->num_deleted); /* write # deleted */ + asn1r_fin_prim (aCtx, 1,CTX); + + asn1r_wr_u32 (aCtx, info->num_matched); /* write # matched */ + asn1r_fin_prim (aCtx, 0,CTX); + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEL_TYPE,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rs_delva.c b/mmslib/mmsle/rs_delva.c new file mode 100644 index 0000000..3c0d0a1 --- /dev/null +++ b/mmslib/mmsle/rs_delva.c @@ -0,0 +1,101 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_delvar.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of delete variable */ +/* access. It decodes the delete variable access request */ +/* (indication) and encodes the delete variable access response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_del_var_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_del_var_req (ASN1_DEC_CTXT *aCtx) + { + mms_del_type_req (aCtx); + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_delvar_resp */ +/* Create and send a delete variable access response. */ +/************************************************************************/ + +ST_RET mp_delvar_resp (MMSREQ_IND *indptr, DELVAR_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_DEL_VAR,indptr, + M_CAST_MK_FUN (_ms_mk_delvar_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_delvar_resp */ +/* Create a delete variable access response. */ +/************************************************************************/ + +ST_RET mpl_delvar_resp (ST_UINT32 invoke_id, DELVAR_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_DEL_VAR,invoke_id, + M_CAST_MK_FUN (_ms_mk_delvar_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_delvar_resp */ +/* construct a delete variable access response. */ +/************************************************************************/ + +ST_VOID _ms_mk_delvar_resp (ASN1_ENC_CTXT *aCtx, DELVAR_RESP_INFO *info) + { + asn1r_wr_u32 (aCtx, info->num_deleted); /* write # deleted */ + asn1r_fin_prim (aCtx, 1,CTX); + + asn1r_wr_u32 (aCtx, info->num_matched); /* write # matched */ + asn1r_fin_prim (aCtx, 0,CTX); + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEL_VAR,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rs_delvl.c b/mmslib/mmsle/rs_delvl.c new file mode 100644 index 0000000..0abc702 --- /dev/null +++ b/mmslib/mmsle/rs_delvl.c @@ -0,0 +1,103 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_delvlist.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of delete named */ +/* variable list. It decodes the delete named variable list */ +/* request (indication) and encodes the delete named variable */ +/* list response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 02 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_del_vlist_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_del_vlist_req (ASN1_DEC_CTXT *aCtx) + { + mms_del_type_req (aCtx); + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_delvlist_resp */ +/* Create and send a delete named variable list response. */ +/************************************************************************/ + +ST_RET mp_delvlist_resp (MMSREQ_IND *indptr, DELVLIST_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_DEL_VLIST,indptr, + M_CAST_MK_FUN (_ms_mk_delvlist_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_delvlist_resp */ +/* Create a delete named variable list response. */ +/************************************************************************/ + +ST_RET mpl_delvlist_resp (ST_UINT32 invoke_id, + DELVLIST_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_DEL_VLIST,invoke_id, + M_CAST_MK_FUN (_ms_mk_delvlist_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_delvlist_resp */ +/* construct a delete named variable list response. */ +/************************************************************************/ + +ST_VOID _ms_mk_delvlist_resp (ASN1_ENC_CTXT *aCtx, DELVLIST_RESP_INFO *info) + { + asn1r_wr_u32 (aCtx, info->num_deleted); /* write # deleted */ + asn1r_fin_prim (aCtx, 1,CTX); + + asn1r_wr_u32 (aCtx, info->num_matched); /* write # matched */ + asn1r_fin_prim (aCtx, 0,CTX); + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DEL_VLIST,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rs_downl.c b/mmslib/mmsle/rs_downl.c new file mode 100644 index 0000000..663d036 --- /dev/null +++ b/mmslib/mmsle/rs_downl.c @@ -0,0 +1,130 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_download.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of download segment. */ +/* It decodes the download segment request (indication) & encodes */ +/* the download segment response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 08 Remove "thisFileName" */ +/* 08/28/03 EJV 07 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static DOWNLOAD_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_download_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_download_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Download Segment Request"); + +/* get storage for request information */ + req_info = (DOWNLOAD_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (DOWNLOAD_REQ_INFO)); + /* read domain name from the received message */ + if (asn1r_get_identifier (aCtx, req_info->dname)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_download_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the download segment response. */ +/************************************************************************/ + +ST_RET mp_download_resp (MMSREQ_IND *indptr,DOWNLOAD_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_DOWN_LOAD,indptr, + M_CAST_MK_FUN (_ms_mk_download_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_download_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the download segment response. */ +/************************************************************************/ + +ST_RET mpl_download_resp (ST_UINT32 invoke_id, + DOWNLOAD_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_DOWN_LOAD,invoke_id, + M_CAST_MK_FUN (_ms_mk_download_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_download_resp */ +/* Construct a download segment response. */ +/************************************************************************/ + +ST_VOID _ms_mk_download_resp (ASN1_ENC_CTXT *aCtx, DOWNLOAD_RESP_INFO *info) +{ + asn1r_strt_constr (aCtx); /* start the sequence constr */ + if (!info->more_follows) + { /* NOT the default (SD_TRUE) */ + asn1r_wr_bool (aCtx, info->more_follows); /* write more follows indicator */ + asn1r_fin_prim (aCtx, 1,CTX); /* context tag 1 */ + } + + if (info->load_data_type == LOAD_DATA_NON_CODED) + { + asn1r_wr_octstr (aCtx, info->load_data,info->load_data_len); + asn1r_fin_prim (aCtx, 0,CTX); /* context tag 0 */ + } + else /* CODED data, write as complete ASN.1 EXTERNAL */ + asn1r_wr_delmnt (aCtx, info->load_data,info->load_data_len); + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_DOWN_LOAD,CTX,DEF); /* tag = opcode, ctx constr */ + } + diff --git a/mmslib/mmsle/rs_fclos.c b/mmslib/mmsle/rs_fclos.c new file mode 100644 index 0000000..41f618e --- /dev/null +++ b/mmslib/mmsle/rs_fclos.c @@ -0,0 +1,101 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_fclose.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the file close. */ +/* It decodes the file close request (indication) and encodes */ +/* the file close response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* ST_VOID mms_file_close_req () */ +/* ST_INT16 mp_fclose_resp (indptr) */ +/* ST_INT16 mpl_fclose_resp (invoke_id) - MMSEASE-LITE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 08/28/03 EJV 06 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static FCLOSE_REQ_INFO *fop_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_file_close_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_file_close_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("File Close Request"); + + +/* get storage for request information */ + fop_info = (FCLOSE_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (FCLOSE_REQ_INFO)); + + /* read frsmid from the received message */ + if (asn1r_get_i32 (aCtx, &(fop_info->frsmid))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_fclose_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file close response. */ +/************************************************************************/ + +ST_RET mp_fclose_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_FILE_CLOSE)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_fclose_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file close response. */ +/************************************************************************/ + +ST_RET mpl_fclose_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_FILE_CLOSE)); + } +#endif diff --git a/mmslib/mmsle/rs_fdele.c b/mmslib/mmsle/rs_fdele.c new file mode 100644 index 0000000..570b759 --- /dev/null +++ b/mmslib/mmsle/rs_fdele.c @@ -0,0 +1,134 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_fdelete.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the file delete. */ +/* It decodes the file delete request (indication) and encodes */ +/* the file delete response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static FDELETE_REQ_INFO *info; + +static ST_INT max_fnames; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID fdelete_fname_cstr_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_file_delete_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/* file delete request: decode the file name. */ +/************************************************************************/ + +ST_VOID mms_file_delete_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("File Delete Request"); + + + if (aCtx->asn1r_elmnt_len > MAX_FILE_NAME) + { /* delete file name is too ST_INT32 */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + +#if defined(FIXED_DECBUF) + max_fnames = m_sv_max_file_names; + req_size = mmsl_dec_info_size; +#else + max_fnames = (_mmsdec_msglen/2); + if (m_sv_max_file_names && (max_fnames > m_sv_max_file_names)) + max_fnames = m_sv_max_file_names; + req_size = sizeof (FDELETE_REQ_INFO) + (max_fnames * sizeof (FILE_NAME)); +#endif + +/* get storage for request information */ + info = (FDELETE_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = fdelete_fname_cstr_done; + _ms_get_mms_fname (aCtx, (FILE_NAME *)(info + 1), max_fnames, &info->num_of_fname); + } + +/************************************************************************/ +/* fdelete_fname_cstr_done */ +/* file delete request is being decoded: file name list constructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID fdelete_fname_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + /* find actual size for request info */ + req_size = sizeof (FDELETE_REQ_INFO) + + (sizeof (FILE_NAME) * info->num_of_fname); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + info = (FDELETE_REQ_INFO *) _mms_dec_info; + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_fdelete_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file delete response. */ +/************************************************************************/ + +ST_RET mp_fdelete_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_FILE_DELETE)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_fdelete_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file delete response. */ +/************************************************************************/ + +ST_RET mpl_fdelete_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_FILE_DELETE)); + } +#endif diff --git a/mmslib/mmsle/rs_fdir.c b/mmslib/mmsle/rs_fdir.c new file mode 100644 index 0000000..3175b6b --- /dev/null +++ b/mmslib/mmsle/rs_fdir.c @@ -0,0 +1,298 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_fdir.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of file directory. */ +/* It decodes the file directory request (indication) and encodes */ +/* the file directory response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "asn1defs.h" +#include "mem_chk.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static FDIR_REQ_INFO *fop_info; + +static ST_INT max_fnames; +static FILE_NAME *fname_idx; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID fdir_fs_fname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID fdir_ca_fname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID fdir_ca_fname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID fdir_fs_fname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID fdir_dec_done_ok (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_file_dir_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_file_dir_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("File Directory Request"); + +#if defined(FIXED_DECBUF) + max_fnames = m_sv_max_file_names; + req_size = mmsl_dec_info_size; +#else + max_fnames = (_mmsdec_msglen/2); + if (m_sv_max_file_names && (max_fnames > m_sv_max_file_names)) + max_fnames = m_sv_max_file_names; + req_size = sizeof (FDIR_REQ_INFO) + (max_fnames * sizeof (FILE_NAME)); +#endif + +/* get storage for request information */ + fop_info = (FDIR_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + if (aCtx->asn1r_elmnt_len > 0) /* a constructor is present */ + { + fname_idx = (FILE_NAME *)(fop_info + 1); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 0, fdir_fs_fname_cstr); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 1, fdir_ca_fname_cstr); + } + else /* all optional constructors were excluded */ + { + fop_info->filespec_pres = SD_FALSE; /* reset filespec present */ + fop_info->cont_after_pres = SD_FALSE; /* reset continue after present */ + } + aCtx->asn1r_decode_done_fun = fdir_dec_done_ok; + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* fdir_fs_fname_cstr */ +/* file directory request is being decoded: file specification filename */ +/* cstr was encountered. */ +/************************************************************************/ + +static ST_VOID fdir_fs_fname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fdir_fs_fname_cstr"); + + fop_info->filespec_pres = SD_TRUE; /* set file spec present */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = fdir_fs_fname_cstr_done; + _ms_get_mms_fname (aCtx, fname_idx, max_fnames, &fop_info->num_of_fs_fname); + } + +/************************************************************************/ +/* fdir_fs_fname_cstr_done */ +/* file directory request is being decoded: file specification file */ +/* name list constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID fdir_fs_fname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 1, fdir_ca_fname_cstr); + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* fdir_ca_fname_cstr */ +/* file directory request is being decoded: continue after filename */ +/* cstr was encountered. */ +/************************************************************************/ + +static ST_VOID fdir_ca_fname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fdir_ca_fname_cstr"); + + fop_info->cont_after_pres = SD_TRUE; /* set continue name present */ + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = fdir_ca_fname_cstr_done; + fname_idx += fop_info -> num_of_fs_fname; + _ms_get_mms_fname (aCtx, fname_idx, max_fnames, &fop_info->num_of_ca_fname); + } + +/************************************************************************/ +/* fdir_ca_fname_cstr_done */ +/* file directory request is being decoded: continue after file name */ +/* list constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID fdir_ca_fname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fdir_ca_fname_cstr_done"); + + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* fdir_dec_done_ok */ +/* file directory request is completely done. Any extra storage is */ +/* given back. */ +/************************************************************************/ + +static ST_VOID fdir_dec_done_ok (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + /* find actual size for request info */ + req_size = sizeof (FDIR_REQ_INFO) + + (sizeof (FILE_NAME) * fop_info->num_of_fs_fname) + + (sizeof (FILE_NAME) * fop_info->num_of_ca_fname); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + fop_info = (FDIR_REQ_INFO *) _mms_dec_info; + + _mms_dec_done_ok (aCtx); + + MLOG_PAUSEDEC (NULL); + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_fdir_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file directory response. */ +/************************************************************************/ + +ST_RET mp_fdir_resp (MMSREQ_IND *indptr, FDIR_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_FILE_DIR,indptr, + M_CAST_MK_FUN (_ms_mk_fdir_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_fdir_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file directory response. */ +/************************************************************************/ + +ST_RET mpl_fdir_resp (ST_UINT32 invoke_id, FDIR_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_FILE_DIR,invoke_id, + M_CAST_MK_FUN (_ms_mk_fdir_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_fdir_resp */ +/* ENCODE a file directory RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_fdir_resp (ASN1_ENC_CTXT *aCtx, FDIR_RESP_INFO *info_ptr) + { +FDIR_DIR_ENT *ent_ptr; +ST_INT i; +ST_INT tab_size; +FDIR_DIR_ENT **dir_ent_tab; +FDIR_DIR_ENT *dir_ptr; +ST_INT dir_ent_idx; + +/* allocate an array of fdir_dir_ent pointers */ + + tab_size = info_ptr->num_dir_ent * sizeof (FDIR_DIR_ENT *); + tab_size++; /* make sure not 0 */ + + dir_ent_tab = (FDIR_DIR_ENT **)chk_calloc (1, tab_size); + + dir_ptr = (FDIR_DIR_ENT *)(info_ptr + 1); + + for (i=0; i < info_ptr->num_dir_ent; ++i) + { + dir_ent_tab[ i ] = dir_ptr; + dir_ptr = (FDIR_DIR_ENT *) + ((FILE_NAME *) (dir_ptr + 1) + dir_ptr -> num_of_fname); + } + + asn1r_strt_constr (aCtx); /* start the fdir seq constr */ + + if (info_ptr->more_follows) + { /* NOT the default value - */ + asn1r_wr_bool (aCtx, info_ptr->more_follows); /* encode more follows */ + asn1r_fin_prim (aCtx, 1,CTX); /* finish the primitive */ + } + + asn1r_strt_constr (aCtx); /* start list of dir ent constr */ + asn1r_strt_constr (aCtx); /* start seq of dir ent constr */ + + if (info_ptr->num_dir_ent > 0) /* if data is to be included - */ + { + /* point to last dir entry */ + dir_ent_idx = info_ptr->num_dir_ent - 1; + ent_ptr = dir_ent_tab[ dir_ent_idx ]; + for (i = 0; i < info_ptr->num_dir_ent; ++i) + { + asn1r_strt_constr (aCtx); /* start the dir entry constr */ + + asn1r_strt_constr (aCtx); /* start the file attr constr */ + if (ent_ptr->mtimpres) + { + asn1r_wr_time (aCtx, ent_ptr->mtime); /* write the last modified time */ + asn1r_fin_prim (aCtx, 1,CTX); + } + asn1r_wr_u32 (aCtx, ent_ptr->fsize); /* write the file size */ + asn1r_fin_prim (aCtx, 0,CTX); + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* close file attr constructor */ + + /* write the file name */ + asn1r_strt_constr (aCtx); + _ms_wr_mms_fname (aCtx, (FILE_NAME *)(ent_ptr + 1), + ent_ptr->num_of_fname); + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context specific tag 0 */ + + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* close dir entry constructor */ + dir_ent_idx--; + ent_ptr = dir_ent_tab[ dir_ent_idx ]; + } + } + + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish seq of dir ents cstr */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish list of dir ents cstr */ + +/* write the context specific explicit tag for this opcode. */ + + asn1r_fin_constr (aCtx, MMSOP_FILE_DIR,CTX,DEF); /* tag = opcode, ctx constr */ + chk_free (dir_ent_tab); + } diff --git a/mmslib/mmsle/rs_fopen.c b/mmslib/mmsle/rs_fopen.c new file mode 100644 index 0000000..32bfd0c --- /dev/null +++ b/mmslib/mmsle/rs_fopen.c @@ -0,0 +1,190 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_fopen.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the file open. */ +/* It decodes the file open request (indication) and encodes */ +/* the file open response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static FOPEN_REQ_INFO *fop_info; + +static ST_INT max_fnames; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID fopen_fname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID fopen_fname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID fopen_get_init_pos (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/* mms_file_open_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_file_open_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("File Open Request"); + +#if defined(FIXED_DECBUF) + max_fnames = m_sv_max_file_names; + req_size = mmsl_dec_info_size; +#else + max_fnames = (_mmsdec_msglen/2); + if (m_sv_max_file_names && (max_fnames > m_sv_max_file_names)) + max_fnames = m_sv_max_file_names; + req_size = sizeof (FOPEN_REQ_INFO) + (max_fnames * (sizeof (FILE_NAME))); +#endif + +/* get storage for request information */ + fop_info = (FOPEN_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,fopen_fname_cstr); + } + +/************************************************************************/ +/* fopen_fname_cstr */ +/* file open request is being decoded: filename cstr was encountered. */ +/************************************************************************/ + +static ST_VOID fopen_fname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("fopen_fname_cstr"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = fopen_fname_cstr_done; + _ms_get_mms_fname (aCtx, (FILE_NAME *)(fop_info + 1), max_fnames, + &fop_info->num_of_fname); + } + +/************************************************************************/ +/* fopen_fname_cstr_done */ +/* file open request is being decoded: file name list constructor done */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID fopen_fname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, fopen_get_init_pos); + } + +/************************************************************************/ +/* fopen_get_init_pos */ +/* file open request is being decoded: initial position was encountered */ +/* this must be all. */ +/************************************************************************/ + +static ST_VOID fopen_get_init_pos (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("fopen_get_init_pos"); + + if (asn1r_get_u32 (aCtx, &(fop_info->init_pos))) /* read the initial position */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + /* find actual size for request info */ + req_size = sizeof (FOPEN_REQ_INFO) + + (sizeof (FILE_NAME) * fop_info->num_of_fname); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + fop_info = (FOPEN_REQ_INFO *) _mms_dec_info; + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_fopen_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file open response. */ +/************************************************************************/ + +ST_RET mp_fopen_resp (MMSREQ_IND *indptr, FOPEN_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_FILE_OPEN,indptr, + M_CAST_MK_FUN (_ms_mk_fopen_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_fopen_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file open response. */ +/************************************************************************/ + +ST_RET mpl_fopen_resp (ST_UINT32 invoke_id, FOPEN_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_FILE_OPEN,invoke_id, + M_CAST_MK_FUN (_ms_mk_fopen_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_fopen_resp */ +/* ENCODE a file open RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_fopen_resp (ASN1_ENC_CTXT *aCtx, FOPEN_RESP_INFO *info_ptr) + { + asn1r_strt_constr (aCtx); /* start the file attr constr */ + if (info_ptr->ent.mtimpres) /* if data is to be included - */ + { + asn1r_wr_time (aCtx, info_ptr->ent.mtime); /* write the last modified time */ + asn1r_fin_prim (aCtx, 1,CTX); + } + + asn1r_wr_u32 (aCtx, info_ptr->ent.fsize); /* write the file size */ + asn1r_fin_prim (aCtx, 0,CTX); + + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* close file attr constructor */ + + asn1r_wr_i32 (aCtx, info_ptr->frsmid); /* write the frsmid */ + asn1r_fin_prim (aCtx, 0,CTX); + + /* write the context specific tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_FILE_OPEN,CTX,DEF); + } diff --git a/mmslib/mmsle/rs_fread.c b/mmslib/mmsle/rs_fread.c new file mode 100644 index 0000000..a812cbf --- /dev/null +++ b/mmslib/mmsle/rs_fread.c @@ -0,0 +1,122 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_fread.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the file read. */ +/* It decodes the file read request (indication) and encodes */ +/* the file read response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static FREAD_REQ_INFO *fop_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_file_read_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_file_read_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("File Read Request"); + +/* get storage for request information */ + fop_info = (FREAD_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (FREAD_REQ_INFO)); + if (asn1r_get_i32 (aCtx, &(fop_info->frsmid))) /* read the frsmid */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_fread_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file read response. */ +/************************************************************************/ + +ST_RET mp_fread_resp (MMSREQ_IND *indptr, FREAD_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_FILE_READ,indptr, + M_CAST_MK_FUN (_ms_mk_fread_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_fread_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file read response. */ +/************************************************************************/ + +ST_RET mpl_fread_resp (ST_UINT32 invoke_id, FREAD_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_FILE_READ,invoke_id, + M_CAST_MK_FUN (_ms_mk_fread_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_fread_resp */ +/* ENCODE a file read RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_fread_resp (ASN1_ENC_CTXT *aCtx, FREAD_RESP_INFO *info_ptr) + { + + if (!info_ptr->more_follows) /* if data is to be included - */ + { /* different from the default */ + asn1r_wr_bool (aCtx, info_ptr->more_follows); /* write more follows indicator */ + asn1r_fin_prim (aCtx, 1,CTX); + } + + /* write the file data octets */ + asn1r_wr_octstr (aCtx, info_ptr->filedata, info_ptr->fd_len); + asn1r_fin_prim (aCtx, 0,CTX); + + /* write the context specific tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_FILE_READ,CTX,DEF); + } diff --git a/mmslib/mmsle/rs_frena.c b/mmslib/mmsle/rs_frena.c new file mode 100644 index 0000000..1787b47 --- /dev/null +++ b/mmslib/mmsle/rs_frena.c @@ -0,0 +1,172 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_frena.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the file rename. */ +/* It decodes the file rename request (indication) and encodes */ +/* the file rename response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static FRENAME_REQ_INFO *fop_info; + +static ST_INT max_fnames; +static FILE_NAME *fname_idx; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID frename_new_fname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID frename_new_fname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID frename_cur_fname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID frename_cur_fname_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_file_rename_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_file_rename_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("File Rename Request"); + +#if defined(FIXED_DECBUF) + max_fnames = m_sv_max_file_names; + req_size = mmsl_dec_info_size; +#else + max_fnames = (_mmsdec_msglen/2); + if (m_sv_max_file_names && (max_fnames > m_sv_max_file_names)) + max_fnames = m_sv_max_file_names; + req_size = sizeof (FRENAME_REQ_INFO) + (max_fnames * sizeof (FILE_NAME)); +#endif + +/* get storage for request information */ + fop_info = (FRENAME_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + fname_idx = (FILE_NAME *)(fop_info + 1); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 0, frename_cur_fname_cstr); + } + +/************************************************************************/ +/* frename_cur_fname_cstr */ +/* request domain download request is being decoded: filename cstr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID frename_cur_fname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("frename_cur_fname_cstr"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = frename_cur_fname_cstr_done; + _ms_get_mms_fname (aCtx, fname_idx, max_fnames, &fop_info->num_of_cur_fname); + } + +/************************************************************************/ +/* frename_cur_fname_cstr_done */ +/* file rename request is being decoded: file name list constructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID frename_cur_fname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 1, frename_new_fname_cstr); + } + +/************************************************************************/ +/* frename_new_fname_cstr */ +/* request domain download request is being decoded: filename cstr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID frename_new_fname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("frename_new_fname_cstr"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = frename_new_fname_cstr_done; + fname_idx += fop_info -> num_of_cur_fname; + _ms_get_mms_fname (aCtx, fname_idx, max_fnames, &fop_info->num_of_new_fname); + } + +/************************************************************************/ +/* frename_new_fname_cstr_done */ +/* request domain download request is being decoded: file name list */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID frename_new_fname_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + /* find actual size for request info */ + req_size = sizeof (FRENAME_REQ_INFO) + + (sizeof (FILE_NAME) * fop_info->num_of_cur_fname) + + (sizeof (FILE_NAME) * fop_info->num_of_new_fname); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + fop_info = (FRENAME_REQ_INFO *) _mms_dec_info; + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_frename_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file rename response. */ +/************************************************************************/ + +ST_RET mp_frename_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_FILE_RENAME)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_frename_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the file rename response. */ +/************************************************************************/ + +ST_RET mpl_frename_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_FILE_RENAME)); + } +#endif diff --git a/mmslib/mmsle/rs_getae.c b/mmslib/mmsle/rs_getae.c new file mode 100644 index 0000000..f71c38f --- /dev/null +++ b/mmslib/mmsle/rs_getae.c @@ -0,0 +1,378 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_getaes.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of get alarm */ +/* enrollment summary. It decodes the get alarm enrollment */ +/* summary request (indication) & encodes the get alarm */ +/* enrollment summary response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/21/08 JRB 08 Use asn1r_wr_bool to write aes_ptr->not_lost.*/ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETAES_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID getaes_get_enrolls_only (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_get_act_alarms_only (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_get_ack_filter (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_sev_filter_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_get_most_sev (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_get_least_sev (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_sev_filter_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_ca_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getaes_ca_name_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_getaes_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_getaes_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Alarm Enrollment Summary Request"); + + +/* get storage for request information */ + req_info = (GETAES_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (GETAES_REQ_INFO)); + req_info->enroll_only = SD_TRUE; /* set default values */ + req_info->act_alarms_only = SD_TRUE; + +/* Done by calloc */ +/* req_info->ack_filter = 0; */ +/* req_info->most_sev_filter = 0; */ + req_info->least_sev_filter = 127; + + ASN1R_TAG_ADD (aCtx, CTX, 0, getaes_get_enrolls_only); + ASN1R_TAG_ADD (aCtx, CTX, 1, getaes_get_act_alarms_only); + ASN1R_TAG_ADD (aCtx, CTX, 2, getaes_get_ack_filter); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, getaes_sev_filter_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, getaes_ca_name_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* getaes_get_enrolls_only */ +/* get alarm enrollment summary REQUEST (indication) is being decoded: */ +/* enrollments only was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_get_enrolls_only (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_get_enrolls_only"); + + if (asn1r_get_bool (aCtx, &req_info->enroll_only)) /* get enrollments only */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 1, getaes_get_act_alarms_only); + ASN1R_TAG_ADD (aCtx, CTX, 2, getaes_get_ack_filter); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, getaes_sev_filter_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, getaes_ca_name_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* getaes_get_act_alarms_only */ +/* get alarm enrollment summary REQUEST is being decoded: active */ +/* enrollments only was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_get_act_alarms_only (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_get_act_alarms_only"); + + if (asn1r_get_bool (aCtx, &req_info->act_alarms_only)) /* active enrollments */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 2, getaes_get_ack_filter); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, getaes_sev_filter_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, getaes_ca_name_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* getaes_get_ack_filter */ +/* get alarm enrollment summary REQUEST is being decoded: ack filter */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_get_ack_filter (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_get_ack_filter"); + + if (asn1r_get_i16 (aCtx, &req_info->ack_filter)) /* get ack filter */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + else if ((req_info->ack_filter < 0) || (req_info->ack_filter > 2)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, getaes_sev_filter_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, getaes_ca_name_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* getaes_sev_filter_cstr */ +/* get alarm enrollment summary REQUEST is being decoded: severity */ +/* filter constructor was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_sev_filter_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_sev_filter_cstr"); + + ASN1R_TAG_ADD (aCtx, CTX, 0, getaes_get_most_sev); + ASN1R_TAG_ADD (aCtx, CTX, 1, getaes_get_least_sev); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getaes_sev_filter_cstr_done; + } + +/************************************************************************/ +/* getaes_get_most_sev */ +/* get alarm enrollment summary REQUEST is being decoded: most severe */ +/* filter was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_get_most_sev (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_get_most_sev"); + + if (asn1r_get_u8 (aCtx, &req_info->most_sev_filter)) /* most severe filter */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 1, getaes_get_least_sev); + } + +/************************************************************************/ +/* getaes_get_least_sev */ +/* get alarm enrollment summary REQUEST is being decoded: least severe */ +/* filter was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_get_least_sev (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_get_least_sev"); + + if (asn1r_get_u8 (aCtx, &req_info->least_sev_filter)) /* least severe filter */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + } + +/************************************************************************/ +/* getaes_sev_filter_cstr_done */ +/* get alarm enrollment summary REQUEST is being decoded: severity */ +/* filter constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_sev_filter_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, getaes_ca_name_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* getaes_ca_name_cstr */ +/* get alarm enrollment summary REQUEST is being decoded: continue */ +/* after name constructor was encountered. */ +/************************************************************************/ + +static ST_VOID getaes_ca_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_ca_name_cstr"); + + req_info->ca_name_pres = SD_TRUE; /* continue after name present */ + + _ms_get_mms_objname (aCtx, &req_info->ca_name, getaes_ca_name_done); + } + +/************************************************************************/ +/* getaes_ca_name_done */ +/* get alarm enrollment summary RESPONSE (confirm) is being decoded: */ +/* continue after name has been obtained. */ +/************************************************************************/ + +static ST_VOID getaes_ca_name_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getaes_ca_name_done"); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getaes_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get alarm enrollment summary response */ +/************************************************************************/ + +ST_RET mp_getaes_resp (MMSREQ_IND *indptr, GETAES_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_GET_ALARM_ESUM,indptr, + M_CAST_MK_FUN (_ms_mk_getaes_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getaes_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get alarm enrollment summary response. */ +/************************************************************************/ + +ST_RET mpl_getaes_resp (ST_UINT32 invoke_id, GETAES_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_GET_ALARM_ESUM,invoke_id, + M_CAST_MK_FUN (_ms_mk_getaes_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getaes_resp */ +/* ENCODE a get alarm enrollment summary RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_getaes_resp (ASN1_ENC_CTXT *aCtx, GETAES_RESP_INFO *info) + { +ST_INT i; +ALARM_ENROLL_SUMMARY *aes_ptr; + + if (info->more_follows) + { /* not the default */ + asn1r_wr_bool (aCtx, info->more_follows); /* write more follows indicator */ + asn1r_fin_prim (aCtx, 1, CTX); /* ctx tag 1 */ + } + + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + aes_ptr = (ALARM_ENROLL_SUMMARY *) (info + 1); + /* point to last alarm enrollment summary */ + aes_ptr += (info->num_of_alarm_esum-1); + for (i = 0; i < info->num_of_alarm_esum; i++) + { + asn1r_strt_constr (aCtx); /* start universal seq cstr */ + if (aes_ptr->iack_time_pres) + { /* write idle acknowlegment time*/ + asn1r_strt_constr (aCtx); /* start ctx tag 12 constructor */ + _ms_wr_mms_evtime (aCtx, &aes_ptr->iack_time); + asn1r_fin_constr (aCtx, 12,CTX,DEF); /* finish ctx tag 12 constructor */ + } + if (aes_ptr->tti_time_pres) + { /* write tran to idle time */ + asn1r_strt_constr (aCtx); /* start ctx tag 11 constructor */ + _ms_wr_mms_evtime (aCtx, &aes_ptr->tti_time); + asn1r_fin_constr (aCtx, 11,CTX,DEF); /* finish ctx tag 11 constructor */ + } + if (aes_ptr->aack_time_pres) + { /* write active acknowledge time*/ + asn1r_strt_constr (aCtx); /* start ctx tag 10 constructor */ + _ms_wr_mms_evtime (aCtx, &aes_ptr->aack_time); + asn1r_fin_constr (aCtx, 10,CTX,DEF); /* finish ctx tag 10 constructor */ + } + if (aes_ptr->tta_time_pres) + { /* write tran to active time */ + asn1r_strt_constr (aCtx); /* start ctx tag 9 constructor */ + _ms_wr_mms_evtime (aCtx, &aes_ptr->tta_time); + asn1r_fin_constr (aCtx, 9,CTX,DEF); /* finish ctx tag 9 constructor */ + } + if (aes_ptr->ee_state_pres) + { /* write event enroll state */ + asn1r_wr_i16 (aCtx, aes_ptr->ee_state); + asn1r_fin_prim (aCtx, 8, CTX); + } + asn1r_wr_i16 (aCtx, aes_ptr->alarm_ack_rule); + asn1r_fin_prim (aCtx, 7, CTX); + + if (aes_ptr->not_lost) + { /* not the default of SD_FALSE */ + asn1r_wr_bool (aCtx, aes_ptr->not_lost); /* write notification lost */ + asn1r_fin_prim (aCtx, 6, CTX); + } +#ifdef CS_SUPPORT + if (aes_ptr->addl_detail_pres) + { /* write additional detail */ + asn1r_strt_constr (aCtx); /* start ctx tag 5 constructor */ + asn1r_wr_delmnt (aCtx, aes_ptr->addl_detail,aes_ptr->addl_detail_len); + asn1r_fin_constr (aCtx, 5,CTX,DEF); /* finish ctx tag 5 constructor */ + } +#endif + asn1r_wr_i16 (aCtx, aes_ptr->cur_state); + asn1r_fin_prim (aCtx, 4, CTX); + + asn1r_wr_u8 (aCtx, aes_ptr->severity); + asn1r_fin_prim (aCtx, 3, CTX); + + if (aes_ptr->client_app_pres) + { + asn1r_strt_constr (aCtx); /* start ctx tag 2 constructor */ + asn1r_wr_delmnt (aCtx, aes_ptr->client_app,aes_ptr->client_app_len); + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* finish ctx tag 2 constructor */ + } + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &aes_ptr->evenroll_name); + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish ctx tag 0 constructor */ + + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish universal seq cstr */ + aes_ptr--; + } + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* ctx tag 0 constructor */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_ALARM_ESUM,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rs_getas.c b/mmslib/mmsle/rs_getas.c new file mode 100644 index 0000000..e234bd8 --- /dev/null +++ b/mmslib/mmsle/rs_getas.c @@ -0,0 +1,348 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_getas.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of get alarm */ +/* summary. It decodes the get alarm summary request (indication) */ +/* & encodes the get alarm summary response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pevn.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETAS_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID getas_get_enrolls_only (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_get_act_alarms_only (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_get_ack_filter (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_sev_filter_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_get_most_sev (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_get_least_sev (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_sev_filter_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_ca_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID getas_ca_name_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_getas_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_getas_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Alarm Summary Request"); + + +/* get storage for request information */ + req_info = (GETAS_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (GETAS_REQ_INFO)); + req_info->enroll_only = SD_TRUE; /* set default values */ + req_info->act_alarms_only = SD_TRUE; + +/* Done by calloc */ +/* req_info->ack_filter = 0; */ +/* req_info->most_sev_filter = 0; */ + req_info->least_sev_filter = 127; + + ASN1R_TAG_ADD (aCtx, CTX, 0, getas_get_enrolls_only); + ASN1R_TAG_ADD (aCtx, CTX, 1, getas_get_act_alarms_only); + ASN1R_TAG_ADD (aCtx, CTX, 2, getas_get_ack_filter); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, getas_sev_filter_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, getas_ca_name_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* getas_get_enrolls_only */ +/* get alarm summary REQUEST (indication) is being decoded: */ +/* enrollments only was encountered. */ +/************************************************************************/ + +static ST_VOID getas_get_enrolls_only (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_get_enrolls_only"); + + if (asn1r_get_bool (aCtx, &req_info->enroll_only)) /* get enrollments only */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 1, getas_get_act_alarms_only); + ASN1R_TAG_ADD (aCtx, CTX, 2, getas_get_ack_filter); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, getas_sev_filter_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, getas_ca_name_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* getas_get_act_alarms_only */ +/* get alarm summary REQUEST is being decoded: active enrollments only */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID getas_get_act_alarms_only (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_get_act_alarms_only"); + + if (asn1r_get_bool (aCtx, &req_info->act_alarms_only)) /* active enrollments */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 2, getas_get_ack_filter); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, getas_sev_filter_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, getas_ca_name_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* getas_get_ack_filter */ +/* get alarm summary REQUEST is being decoded: ack filter was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID getas_get_ack_filter (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_get_ack_filter"); + + if (asn1r_get_i16 (aCtx, &req_info->ack_filter)) /* get ack filter */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + else if ((req_info->ack_filter < 0) || (req_info->ack_filter > 2)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 3, getas_sev_filter_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, getas_ca_name_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* getas_sev_filter_cstr */ +/* get alarm summary REQUEST is being decoded: severity filter cstr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID getas_sev_filter_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_sev_filter_cstr"); + + ASN1R_TAG_ADD (aCtx, CTX, 0, getas_get_most_sev); + ASN1R_TAG_ADD (aCtx, CTX, 1, getas_get_least_sev); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = getas_sev_filter_cstr_done; + } + +/************************************************************************/ +/* getas_get_most_sev */ +/* get alarm summary REQUEST is being decoded: most severe filter was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID getas_get_most_sev (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_get_most_sev"); + + if (asn1r_get_u8 (aCtx, &req_info->most_sev_filter)) /* most severe filter */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX, 1, getas_get_least_sev); + } + +/************************************************************************/ +/* getas_get_least_sev */ +/* get alarm summary REQUEST is being decoded: least severe filter was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID getas_get_least_sev (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_get_least_sev"); + + if (asn1r_get_u8 (aCtx, &req_info->least_sev_filter)) /* least severe filter */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + } + +/************************************************************************/ +/* getas_sev_filter_cstr_done */ +/* get alarm summary REQUEST is being decoded: severity filter cstr */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID getas_sev_filter_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, getas_ca_name_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* getas_ca_name_cstr */ +/* get alarm summary REQUEST is being decoded: continue after name */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID getas_ca_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_ca_name_cstr"); + + req_info->ca_pres = SD_TRUE; + _ms_get_mms_objname (aCtx, &req_info->ca_name, getas_ca_name_done); + } + +/************************************************************************/ +/* getas_ca_name_done */ +/* get alarm summary RESPONSE (confirm) is being decoded: */ +/* continue after name has been obtained. */ +/************************************************************************/ + +static ST_VOID getas_ca_name_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("getas_ca_name_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = NULL; /* clear cstr done functions */ + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getas_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the get alarm summary response. */ +/************************************************************************/ + +ST_RET mp_getas_resp (MMSREQ_IND *indptr, GETAS_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_GET_ALARM_SUM,indptr, + M_CAST_MK_FUN (_ms_mk_getas_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getas_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get alarm summary response. */ +/************************************************************************/ + +ST_RET mpl_getas_resp (ST_UINT32 invoke_id, GETAS_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_GET_ALARM_SUM,invoke_id, + M_CAST_MK_FUN (_ms_mk_getas_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getas_resp */ +/* ENCODE a get alarm summary RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_getas_resp (ASN1_ENC_CTXT *aCtx, GETAS_RESP_INFO *info) + { +ST_INT i; +ALARM_SUMMARY *as_ptr; + + if (info->more_follows) + { /* not the default */ + asn1r_wr_bool (aCtx, info->more_follows); /* write more follows indicator */ + asn1r_fin_prim (aCtx, 1, CTX); /* ctx tag 1 */ + } + + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + as_ptr = (ALARM_SUMMARY *) (info + 1); + as_ptr += (info->num_of_alarm_sum-1); /* point to last alarm summary */ + for (i = 0; i < info->num_of_alarm_sum; i++) + { + asn1r_strt_constr (aCtx); /* start universal seq cstr */ + if (as_ptr->tti_time_pres) + { /* write tran to idle time */ + asn1r_strt_constr (aCtx); /* start ctx tag 6 constructor */ + _ms_wr_mms_evtime (aCtx, &as_ptr->tti_time); + asn1r_fin_constr (aCtx, 6,CTX,DEF); /* finish ctx tag 6 constructor */ + } + if (as_ptr->tta_time_pres) + { /* write tran to active time */ + asn1r_strt_constr (aCtx); /* start ctx tag 5 constructor */ + _ms_wr_mms_evtime (aCtx, &as_ptr->tta_time); + asn1r_fin_constr (aCtx, 5,CTX,DEF); /* finish ctx tag 5 constructor */ + } +#ifdef CS_SUPPORT + if (as_ptr->addl_detail_pres) + { /* write additional detail */ + asn1r_strt_constr (aCtx); /* start ctx tag 4 constructor */ + asn1r_wr_delmnt (aCtx, as_ptr->addl_detail,as_ptr->addl_detail_len); + asn1r_fin_constr (aCtx, 4,CTX,DEF); /* finish ctx tag 4 constructor */ + } +#endif + asn1r_wr_i16 (aCtx, as_ptr->unack_state); + asn1r_fin_prim (aCtx, 3, CTX); + + asn1r_wr_i16 (aCtx, as_ptr->cur_state); + asn1r_fin_prim (aCtx, 2, CTX); + + asn1r_wr_u8 (aCtx, as_ptr->severity); + asn1r_fin_prim (aCtx, 1, CTX); + + asn1r_strt_constr (aCtx); /* start ctx tag 0 constructor */ + _ms_wr_mms_objname (aCtx, &as_ptr->evcon_name); + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish ctx tag 0 constructor */ + + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish universal seq cstr */ + as_ptr--; + } + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* ctx tag 0 constructor */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_ALARM_SUM,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rs_getsc.c b/mmslib/mmsle/rs_getsc.c new file mode 100644 index 0000000..4fa082c --- /dev/null +++ b/mmslib/mmsle/rs_getsc.c @@ -0,0 +1,135 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_getscat.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of get scattered */ +/* access attributes. It decodes the get scattered access */ +/* attributes request (indication) & encodes the get scattered */ +/* access attributes response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static GETSCAT_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/* static functions with multiple references */ + +static ST_VOID getscat_name_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_get_scat_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_get_scat_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Get Scattered Access Attributes Request"); + +/* get storage for request information */ + req_info = (GETSCAT_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (GETSCAT_REQ_INFO)); + _ms_get_mms_objname (aCtx, &req_info->sa_name, getscat_name_done); + } + +/************************************************************************/ +/* getscat_name_done */ +/* decoding get scattered access attributes request: scattered access */ +/* name has been obtained. */ +/************************************************************************/ + +static ST_VOID getscat_name_done (ASN1_DEC_CTXT *aCtx) + { + asn1r_set_all_cstr_done (aCtx); /* clear cstr done functions */ + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_getscat_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE & send the get scattered access attributes */ +/* response. */ +/************************************************************************/ + +ST_RET mp_getscat_resp (MMSREQ_IND *indptr, GETSCAT_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_GET_SCAT,indptr, + M_CAST_MK_FUN (_ms_mk_getscat_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_getscat_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the get scattered access attributes response. */ +/************************************************************************/ + +ST_RET mpl_getscat_resp (ST_UINT32 invoke_id, GETSCAT_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_GET_SCAT,invoke_id, + M_CAST_MK_FUN (_ms_mk_getscat_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_getscat_resp */ +/* Construct a get scattered access attributes response. */ +/************************************************************************/ + +ST_VOID _ms_mk_getscat_resp (ASN1_ENC_CTXT *aCtx, GETSCAT_RESP_INFO *info) + { + asn1r_strt_constr (aCtx); /* start context tag 1 cstr */ + _ms_wr_va_scat_access (aCtx, &info->sa_descr); /* write scattered access descr */ + asn1r_fin_constr (aCtx, 1, CTX, DEF); /* finish context tag 1 cstr */ + + asn1r_wr_bool (aCtx, info->mms_deletable); /* write mms deletable flag */ + asn1r_fin_prim (aCtx, 0,CTX); /* context tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_GET_SCAT,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rs_initd.c b/mmslib/mmsle/rs_initd.c new file mode 100644 index 0000000..f239c2f --- /dev/null +++ b/mmslib/mmsle/rs_initd.c @@ -0,0 +1,240 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_initdown.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of initiate download */ +/* sequence. It decodes the initiate download sequence request */ +/* (indication) & encodes the initiate download sequence response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* _ms_mk_initdown_resp:added ST_VOID *dummyInfo*/ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static INITDOWN_REQ_INFO *req_info; + +static ST_CHAR **cap_ptr; +static ST_INT max_capabilities; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID initdown_get_sharable (ASN1_DEC_CTXT *aCtx); +static ST_VOID initdown_get_cap (ASN1_DEC_CTXT *aCtx); +static ST_VOID initdown_cap_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID initdown_cap_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID initdown_get_dname (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_init_download_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_init_download_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Initiate Download Sequence Request"); + +#if defined(FIXED_DECBUF) + max_capabilities = m_sv_max_initdnld_cap; + req_size = mmsl_dec_info_size; +#else + max_capabilities = (_mmsdec_msglen/2); + if (m_sv_max_initdnld_cap && (max_capabilities > m_sv_max_initdnld_cap)) + max_capabilities = m_sv_max_initdnld_cap; + req_size = sizeof (INITDOWN_REQ_INFO) + (max_capabilities * sizeof (ST_CHAR *)); +#endif + +/* get storage for request information */ + req_info = (INITDOWN_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + cap_ptr = (ST_CHAR **) (req_info + 1); + aCtx->asn1r_err_fun = _mms_dec_buf_free; + ASN1R_TAG_ADD (aCtx, CTX, 0,initdown_get_dname); + } + +/************************************************************************/ +/* initdown_get_dname */ +/* initiate download sequence request is being decoded: domain name */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID initdown_get_dname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("initdown_get_dname"); + + if (asn1r_get_identifier (aCtx, req_info->dname)) /* read the domain name */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, initdown_cap_cstr); + } + +/************************************************************************/ +/* initdown_cap_cstr */ +/* initiate download sequence request is being decoded: capability */ +/* list constructor was encountered. */ +/************************************************************************/ + +static ST_VOID initdown_cap_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("initdown_cap_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI,VISTR_CODE,initdown_get_cap); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = initdown_cap_cstr_done; + } + +/************************************************************************/ +/* initdown_get_cap */ +/* initiate download sequence request is being decoded: capability */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID initdown_get_cap (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("initdown_get_cap"); + + req_info->num_of_capab++; /* increment # of capabilities */ + if (req_info->num_of_capab > max_capabilities) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + /* copy capability back onto itself shifted by one character */ + *cap_ptr = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_vstr (aCtx, *cap_ptr)) + { /* capability is too ST_INT32 */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + cap_ptr++; /* point to where next will go */ + + ASN1R_TAG_ADD (aCtx, UNI,VISTR_CODE,initdown_get_cap); + } + +/************************************************************************/ +/* initdown_cap_cstr_done */ +/* initiate download sequence request is being decoded: capability */ +/* list constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID initdown_cap_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX,2,initdown_get_sharable); + } + +/************************************************************************/ +/* initdown_get_sharable */ +/* initiate download sequence request is being decoded: sharable */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID initdown_get_sharable (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("initdown_get_sharable"); + + /* read sharable from the received message */ + if (asn1r_get_bool (aCtx, &(req_info->sharable))) + { /* sharable is too ST_INT32 */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + /* find actual size for request info */ + req_size = sizeof (INITDOWN_REQ_INFO) + + (sizeof (ST_CHAR *) * req_info->num_of_capab); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (INITDOWN_REQ_INFO *) _mms_dec_info; + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_initdown_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the initiate download sequence response. */ +/************************************************************************/ + +ST_RET mp_initdown_resp (MMSREQ_IND *indptr) + { + if (mms_chan_info[_mmsdechan].version) /* IS */ + return (_mms_send_null_resp (indptr,MMSOP_INIT_DOWNLOAD)); + else /* DIS */ + return (_mms_resp_send (MMSOP_INIT_DOWNLOAD,indptr, + M_CAST_MK_FUN (_ms_mk_initdown_resp), + NULL)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_initdown_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the initiate download sequence response. */ +/************************************************************************/ + +ST_RET mpl_initdown_resp (ST_UINT32 invoke_id) + { + if (mmsl_version) /* IS */ + return (_mms_fin_null_resp (invoke_id,MMSOP_INIT_DOWNLOAD)); + else /* DIS */ + return (_mms_resp_fin (MMSOP_INIT_DOWNLOAD,invoke_id, + M_CAST_MK_FUN (_ms_mk_initdown_resp), + NULL)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_initdown_resp */ +/* ENCODE an initiate download RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_initdown_resp (ASN1_ENC_CTXT *aCtx, ST_VOID *dummyInfo) + { +/* write the context specific explicit tag for this opcode. */ + + asn1r_fin_prim (aCtx, NULL_CODE,0); /* Write NULL field */ + asn1r_fin_constr (aCtx, MMSOP_INIT_DOWNLOAD,CTX,DEF); /* tag = opcode, ctx cstr */ + } diff --git a/mmslib/mmsle/rs_initu.c b/mmslib/mmsle/rs_initu.c new file mode 100644 index 0000000..9d21c7c --- /dev/null +++ b/mmslib/mmsle/rs_initu.c @@ -0,0 +1,132 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_initupl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of initiate upload */ +/* sequence. It decodes the initiate upload sequence request */ +/* (indication) & encodes the initiate upload sequence response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static INITUPL_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_init_upload_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_init_upload_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Initiate Upload Sequence Request"); + + +/* get storage for request information */ + req_info = (INITUPL_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (INITUPL_REQ_INFO)); + aCtx->asn1r_err_fun = _mms_dec_buf_free; + + if (asn1r_get_identifier (aCtx, req_info->dname)) /* read the domain name */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_initupl_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the initiate upload sequence response. */ +/************************************************************************/ + +ST_RET mp_initupl_resp (MMSREQ_IND *indptr, INITUPL_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_INIT_UPLOAD,indptr, + M_CAST_MK_FUN (_ms_mk_initupl_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_initupl_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the initiate upload sequence response. */ +/************************************************************************/ + +ST_RET mpl_initupl_resp (ST_UINT32 invoke_id, INITUPL_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_INIT_UPLOAD,invoke_id, + M_CAST_MK_FUN (_ms_mk_initupl_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_initupl_resp */ +/* ENCODE an initiate upload sequence RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_initupl_resp (ASN1_ENC_CTXT *aCtx, INITUPL_RESP_INFO *info) + { +ST_INT i; +ST_CHAR **cap_ptr; + + asn1r_strt_constr (aCtx); /* start ctx tag 1 constructor */ + + cap_ptr = (ST_CHAR **) (info + 1); + cap_ptr += (info->num_of_capab - 1); /* point to last capability */ + for (i = 0; i < info->num_of_capab; i++) + { + asn1r_wr_vstr (aCtx, *cap_ptr); + asn1r_fin_prim (aCtx, VISTR_CODE, UNI); + cap_ptr--; + } + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* ctx tag 1 constructor */ + + asn1r_wr_i32 (aCtx, info->ulsmid); /* write upload state machine id*/ + asn1r_fin_prim (aCtx, 0,CTX); /* ctx tag 0 */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_INIT_UPLOAD,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rs_input.c b/mmslib/mmsle/rs_input.c new file mode 100644 index 0000000..8589b21 --- /dev/null +++ b/mmslib/mmsle/rs_input.c @@ -0,0 +1,251 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_input.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the input */ +/* operation. It decodes the input request (indication) and */ +/* encodes the input response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pocs.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static INPUT_REQ_INFO *req_info; + +static ST_INT max_prompt_count; +static ST_CHAR **prompt_ptr; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID input_prompt_data_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID input_get_timeout (ASN1_DEC_CTXT *aCtx); +static ST_VOID input_get_prompt_data (ASN1_DEC_CTXT *aCtx); +static ST_VOID input_prompt_data_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID input_get_echo (ASN1_DEC_CTXT *aCtx); +static ST_VOID input_get_station_name (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_input_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_input_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Input Request"); + +#if defined(FIXED_DECBUF) + max_prompt_count = m_sv_max_prompt_count; + req_size = mmsl_dec_info_size; +#else + max_prompt_count = _mmsdec_msglen / 2; /* find maximum size */ + if (m_sv_max_prompt_count && (max_prompt_count > m_sv_max_prompt_count)) + max_prompt_count = m_sv_max_prompt_count; + req_size = sizeof (INPUT_REQ_INFO) + (sizeof (ST_CHAR *) * max_prompt_count); +#endif + +/* get storage for request information */ + req_info = (INPUT_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + prompt_ptr = (ST_CHAR **) (req_info + 1); + req_info->echo = SD_TRUE; + req_info->timeout_pres = SD_FALSE; + req_info->prompt_count = 0; + + ASN1R_TAG_ADD (aCtx, CTX, 0, input_get_station_name); + } + +/************************************************************************/ +/* input_get_station_name */ +/* input request is being decoded: get the station name. */ +/************************************************************************/ + +static ST_VOID input_get_station_name (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("input_get_station_name"); + + if (asn1r_get_identifier (aCtx, req_info->station_name)) /* read station name */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 1, input_get_echo); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, input_prompt_data_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 3, input_get_timeout); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* input_get_echo */ +/* input request is being decoded: input echo was encountered. */ +/************************************************************************/ + +static ST_VOID input_get_echo (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("input_get_echo"); + + if (asn1r_get_bool (aCtx, &req_info->echo)) /* read input echo */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, input_prompt_data_cstr); + ASN1R_TAG_ADD (aCtx, CTX, 3, input_get_timeout); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* input_prompt_data_cstr */ +/* input request is being decoded: prompt data list constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID input_prompt_data_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("input_prompt_data_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, input_get_prompt_data); + req_info->prompt_pres = SD_TRUE; + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = input_prompt_data_cstr_done; + } + +/************************************************************************/ +/* input_get_prompt_data */ +/* input request is being decoded: prompt data was encountered. */ +/************************************************************************/ + +static ST_VOID input_get_prompt_data (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("input_get_prompt_dat"); + + req_info->prompt_count++; /* increment prompt data count */ + if (req_info->prompt_count > max_prompt_count) + { /* too many prompt data strings */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + *prompt_ptr = (ST_CHAR *) aCtx->asn1r_field_ptr-1; /* set prompt data pointer */ + if (asn1r_get_vstr (aCtx, *prompt_ptr)) /* shift prompt data left */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + prompt_ptr++; /* point to where next will go */ + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, input_get_prompt_data); + } + +/************************************************************************/ +/* input_prompt_data_cstr_done */ +/* input request is being decoded: prompt data list constructor done */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID input_prompt_data_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + /* find actual size for request info */ + req_size = sizeof (INPUT_REQ_INFO) + + (sizeof (ST_CHAR *) * req_info->prompt_count); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (INPUT_REQ_INFO *) _mms_dec_info; + ASN1R_TAG_ADD (aCtx, CTX, 3, input_get_timeout); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* input_get_timeout */ +/* input request is being decoded: input timeout was encountered. */ +/************************************************************************/ + +static ST_VOID input_get_timeout (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("input_get_timeou"); + + req_info->timeout_pres = SD_TRUE; /* set input timeout present */ + + if (asn1r_get_u32 (aCtx, &req_info->timeout)) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_input_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the input response. */ +/************************************************************************/ + +ST_RET mp_input_resp (MMSREQ_IND *indptr, INPUT_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_INPUT,indptr, + M_CAST_MK_FUN (_ms_mk_input_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_input_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the input response. */ +/************************************************************************/ + +ST_RET mpl_input_resp (ST_UINT32 invoke_id, INPUT_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_INPUT,invoke_id, + M_CAST_MK_FUN (_ms_mk_input_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_input_resp */ +/* ENCODE an input RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_input_resp (ASN1_ENC_CTXT *aCtx, INPUT_RESP_INFO *info_ptr) + { + asn1r_wr_vstr (aCtx, info_ptr->input_resp); /* encode the input response */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_INPUT,CTX); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsle/rs_jcrea.c b/mmslib/mmsle/rs_jcrea.c new file mode 100644 index 0000000..33c68fd --- /dev/null +++ b/mmslib/mmsle/rs_jcrea.c @@ -0,0 +1,133 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_jcreate.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of create journal. */ +/* It decodes the create journal request (indication) & encodes */ +/* the create journal response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pjou.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static JCREATE_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID jcreate_jname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jcreate_jname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jcreate_jname_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_jcreate_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_jcreate_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Create Journal Request"); + + +/* get storage for request information */ + req_info = (JCREATE_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (JCREATE_REQ_INFO)); + aCtx->asn1r_err_fun = _mms_dec_buf_free; + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, jcreate_jname_cstr); + } + +/************************************************************************/ +/* jcreate_jname_cstr */ +/* create journal request is being decoded: journal name constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jcreate_jname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jcreate_jname_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->jou_name, jcreate_jname_done); + } + +/************************************************************************/ +/* jcreate_jname_done */ +/* create journal request is being decoded: journal name has been */ +/* obtained. */ +/************************************************************************/ + +static ST_VOID jcreate_jname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jcreate_jname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jcreate_jname_cstr_done; + } + +/************************************************************************/ +/* jcreate_jname_cstr_done */ +/* create journal request is being decoded: journal name cstr done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jcreate_jname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_jcreate_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the create journal response. */ +/************************************************************************/ + +ST_RET mp_jcreate_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_CREATE_JOURNAL)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_jcreate_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the create journal response. */ +/************************************************************************/ + +ST_RET mpl_jcreate_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_CREATE_JOURNAL)); + } +#endif diff --git a/mmslib/mmsle/rs_jdele.c b/mmslib/mmsle/rs_jdele.c new file mode 100644 index 0000000..726c46b --- /dev/null +++ b/mmslib/mmsle/rs_jdele.c @@ -0,0 +1,132 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_jdelete.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of delete journal. */ +/* It decodes the delete journal request (indication) & encodes */ +/* the delete journal response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pjou.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static JDELETE_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID jdelete_jname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jdelete_jname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jdelete_jname_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_jdelete_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_jdelete_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Delete Journal Request"); + + +/* get storage for request information */ + req_info = (JDELETE_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (JDELETE_REQ_INFO)); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, jdelete_jname_cstr); + } + +/************************************************************************/ +/* jdelete_jname_cstr */ +/* delete journal request is being decoded: journal name constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jdelete_jname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jdelete_jname_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->jou_name, jdelete_jname_done); + } + +/************************************************************************/ +/* jdelete_jname_done */ +/* delete journal request is being decoded: journal name has been */ +/* obtained. */ +/************************************************************************/ + +static ST_VOID jdelete_jname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jdelete_jname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jdelete_jname_cstr_done; + } + +/************************************************************************/ +/* jdelete_jname_cstr_done */ +/* delete journal request is being decoded: journal name cstr done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jdelete_jname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_jdelete_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the delete journal response. */ +/************************************************************************/ + +ST_RET mp_jdelete_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_DELETE_JOURNAL)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_jdelete_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the delete journal response. */ +/************************************************************************/ + +ST_RET mpl_jdelete_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_DELETE_JOURNAL)); + } +#endif diff --git a/mmslib/mmsle/rs_jinit.c b/mmslib/mmsle/rs_jinit.c new file mode 100644 index 0000000..34acde0 --- /dev/null +++ b/mmslib/mmsle/rs_jinit.c @@ -0,0 +1,260 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_jinit.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of initialize */ +/* journal. It decodes the initialize journal request (indication) */ +/* & encodes the initialize journal response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 09 Remove "thisFileName" */ +/* 08/28/03 EJV 08 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 07 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 03/23/99 MDE 05 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 04 Changes to allow compile under C++ */ +/* 08/15/97 MDE 03 BTOD handling changes */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pjou.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static JINIT_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID jinit_limit_spec_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jinit_le_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jinit_get_le_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID jinit_get_le_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jinit_get_limit_time (ASN1_DEC_CTXT *aCtx); +static ST_VOID jinit_limit_spec_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jinit_jou_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jinit_jn_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jinit_jou_name_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_jinit_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_jinit_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Initialize Journal Request"); + +/* get storage for request information */ + req_info = (JINIT_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (JINIT_REQ_INFO)); + req_info->limit_spec_pres = SD_FALSE; + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, jinit_jou_name_cstr); + } + +/************************************************************************/ +/* jinit_jou_name_cstr */ +/* initialize journal request is being decoded: journal name cstr */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jinit_jou_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jinit_jou_name_cstr"); + _ms_get_mms_objname (aCtx, &req_info->jou_name, jinit_jn_done); + } + +/************************************************************************/ +/* jinit_jn_done */ +/* initialize journal request is being decoded: journal name has been */ +/* obtained. */ +/************************************************************************/ + +static ST_VOID jinit_jn_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jinit_jn_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jinit_jou_name_cstr_done; + } + +/************************************************************************/ +/* jinit_jou_name_cstr_done */ +/* initialize journal request is being decoded: journal name cstr done */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jinit_jou_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, jinit_limit_spec_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* jinit_limit_spec_cstr */ +/* initialize journal request is being decoded: limit specification */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jinit_limit_spec_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jinit_limit_spec_cstr"); + + req_info->limit_spec_pres = SD_TRUE; + + ASN1R_TAG_ADD (aCtx, CTX, 0, jinit_get_limit_time); + } + +/************************************************************************/ +/* jinit_get_limit_time */ +/* initialize journal request is being decoded: limit time was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jinit_get_limit_time (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jinit_get_limit_tim"); + + if (asn1r_get_btod (aCtx, &req_info->limit_time)) /* get limiting time */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 1, jinit_get_le_prim); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, jinit_get_le_cstr); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jinit_limit_spec_cstr_done; + } + +/************************************************************************/ +/* jinit_get_le_prim */ +/* initialize journal request is being decoded: limit entry primitive */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jinit_get_le_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jinit_get_le_prim"); + /* decode limit entry back onto itself */ + + req_info->limit_entry_pres = SD_TRUE; + req_info->limit_entry = aCtx->asn1r_field_ptr; + + if (asn1r_get_octstr (aCtx, req_info->limit_entry)) /* read limit entry */ + asn1r_set_dec_err (aCtx, REQ_UNSPECIFIED); + + req_info->limit_entry_len = aCtx->asn1r_octetcount; + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jinit_limit_spec_cstr_done; + } + +/************************************************************************/ +/* jinit_get_le_cstr */ +/* initialize journal request is being decoded: limit entry cstr */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jinit_get_le_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jinit_get_le_cstr"); + + /* decode limit entry back onto itself */ + req_info->limit_entry_pres = SD_TRUE; + req_info->limit_entry = aCtx->asn1r_field_ptr; + + /* set up done decoding octet cstr destination */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jinit_le_cstr_done; + + /* get limit entry from the received message */ + /* set maximum length to accept entire message */ + asn1r_get_octstr_cstr (aCtx, _mmsdec_msglen, req_info->limit_entry); + } + +/************************************************************************/ +/* jinit_le_cstr_done */ +/* initialize journal request is being decoded: limit entry cstr done */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jinit_le_cstr_done (ASN1_DEC_CTXT *aCtx) + { + req_info->limit_entry_len = aCtx->asn1r_octetcount; /* save limit entry len */ + /* cstr done already set*/ + } + +/************************************************************************/ +/* jinit_limit_spec_cstr_done */ +/* initialize journal request is being decoded: limit specification */ +/* cstr done was encountered. */ +/************************************************************************/ + +static ST_VOID jinit_limit_spec_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_jinit_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the initialize journal response. */ +/************************************************************************/ + +ST_RET mp_jinit_resp (MMSREQ_IND *indptr, JINIT_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_INIT_JOURNAL,indptr, + M_CAST_MK_FUN (_ms_mk_jinit_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_jinit_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the initialize journal response. */ +/************************************************************************/ + +ST_RET mpl_jinit_resp (ST_UINT32 invoke_id, JINIT_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_INIT_JOURNAL,invoke_id, + M_CAST_MK_FUN (_ms_mk_jinit_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_jinit_resp */ +/* ENCODE an initialize journal RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_jinit_resp (ASN1_ENC_CTXT *aCtx, JINIT_RESP_INFO *info_ptr) + { + asn1r_wr_u32 (aCtx, info_ptr->del_entries); /* encode deleted entries */ +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_prim (aCtx, MMSOP_INIT_JOURNAL,CTX); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsle/rs_jread.c b/mmslib/mmsle/rs_jread.c new file mode 100644 index 0000000..b80a7b8 --- /dev/null +++ b/mmslib/mmsle/rs_jread.c @@ -0,0 +1,620 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_jread.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of read journal. */ +/* It decodes the read journal request (indication) & encodes */ +/* the read journal response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/28/03 EJV 07 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 08/15/97 MDE 02 BTOD handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pjou.h" +#include "asn1defs.h" +#include "mem_chk.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static JREAD_REQ_INFO *req_info; + +static ST_CHAR **var_ptr; +static ST_INT max_vars; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID jread_range_stop_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_list_of_var_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_sa_entry_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_range_start_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_range_stop_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_sa_entry_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_entry_spec_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_entry_spec_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_get_time_spec (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_get_var (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_list_of_var_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_get_stop_time (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_get_num_of_ent (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_start_entry_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_get_start_time (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_start_entry_prim (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_start_entry_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_range_start_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_jname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_jname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_jname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_entry_spec_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jread_dec_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_jread_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_jread_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Read Journal Request"); + +#if defined(FIXED_DECBUF) + max_vars = m_sv_max_jread_vars; + req_size = mmsl_dec_info_size; +#else + max_vars = (_mmsdec_msglen/2); + if (m_sv_max_jread_vars && (max_vars > m_sv_max_jread_vars)) + max_vars = m_sv_max_jread_vars; + + req_size = sizeof (JREAD_REQ_INFO) + (max_vars * sizeof (ST_CHAR *)); +#endif + +/* get storage for request information */ + req_info = (JREAD_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + var_ptr = (ST_CHAR **) (req_info + 1); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, jread_jname_cstr); + } + +/************************************************************************/ +/* jread_jname_cstr */ +/* read journal request is being decoded: journal name constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jread_jname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_jname_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->jou_name, jread_jname_done); + } + +/************************************************************************/ +/* jread_jname_done */ +/* read journal request is being decoded: journal name has been */ +/* obtained. */ +/************************************************************************/ + +static ST_VOID jread_jname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_jname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jread_jname_cstr_done; + } + +/************************************************************************/ +/* jread_jname_cstr_done */ +/* read journal request is being decoded: journal name constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jread_jname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, jread_range_start_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, jread_range_stop_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, jread_list_of_var_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, jread_sa_entry_cstr); + + aCtx->asn1r_decode_done_fun = jread_dec_done; /* ok to be done, set done fun */ + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* jread_range_start_cstr */ +/* read journal request is being decoded: range start constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jread_range_start_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_range_start_cstr"); + + req_info->range_start_pres = SD_TRUE; + + ASN1R_TAG_ADD (aCtx, CTX, 0, jread_get_start_time); + ASN1R_TAG_ADD (aCtx, CTX, 1, jread_start_entry_prim); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, jread_start_entry_cstr); + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* jread_get_start_time */ +/* initialize journal request is being decoded: start time was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jread_get_start_time (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_get_start_tim"); + + req_info->start_tag = SD_SUCCESS; /* set start time */ + + if (asn1r_get_btod (aCtx, &req_info->start_time)) /* get start time */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jread_range_start_cstr_done; + } + +/************************************************************************/ +/* jread_start_entry_prim */ +/* read journal request is being decoded: start entry primitive was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jread_start_entry_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_start_entry_prim"); + + req_info->start_tag = SD_TRUE; /* set start entry */ + + /* decode start entry back onto itself */ + req_info->start_entry = aCtx->asn1r_field_ptr; + + if (asn1r_get_octstr (aCtx, req_info->start_entry)) /* read start entry */ + asn1r_set_dec_err (aCtx, REQ_UNSPECIFIED); + + req_info->start_entry_len = aCtx->asn1r_octetcount; + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jread_range_start_cstr_done; + } + +/************************************************************************/ +/* jread_start_entry_cstr */ +/* read journal request is being decoded: start entry constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jread_start_entry_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_start_entry_cstr"); + + req_info->start_tag = SD_TRUE; /* set start entry */ + + /* decode start entry back onto itself */ + req_info->start_entry = aCtx->asn1r_field_ptr; + + /* set up done decoding octet cstr destination */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jread_start_entry_cstr_done; + + /* get start entry from the received message */ + /* set maximum length to accept entire message */ + asn1r_get_octstr_cstr (aCtx, _mmsdec_msglen, req_info->start_entry); + } + +/************************************************************************/ +/* jread_start_entry_cstr_done */ +/* read journal request is being decoded: start entry constructor done */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jread_start_entry_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + req_info->start_entry_len = aCtx->asn1r_octetcount; /* save start entry len */ + + /* set up done decoding start spec cstr dest */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jread_range_start_cstr_done; + } + +/************************************************************************/ +/* jread_range_start_cstr_done */ +/* read journal request is being decoded: range start constructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID jread_range_start_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, jread_range_stop_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, jread_list_of_var_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, jread_sa_entry_cstr); + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* jread_range_stop_cstr */ +/* read journal request is being decoded: range stop constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jread_range_stop_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_range_stop_cstr"); + + req_info->range_stop_pres = SD_TRUE; + + ASN1R_TAG_ADD (aCtx, CTX, 0, jread_get_stop_time); + ASN1R_TAG_ADD (aCtx, CTX, 1, jread_get_num_of_ent); + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* jread_get_stop_time */ +/* initialize journal request is being decoded: ending time was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jread_get_stop_time (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_get_stop_tim"); + + req_info->stop_tag = SD_SUCCESS; /* set ending time */ + + if (asn1r_get_btod (aCtx, &req_info->end_time)) /* get ending time */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jread_range_stop_cstr_done; + } + +/************************************************************************/ +/* jread_get_num_of_ent */ +/* read journal request is being decoded: number of entries was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jread_get_num_of_ent (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_get_num_of_ent"); + + req_info->stop_tag = SD_TRUE; /* set num of entries */ + + if (asn1r_get_i32 (aCtx, &req_info->num_of_entries)) /* read number of entry */ + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jread_range_stop_cstr_done; + } + +/************************************************************************/ +/* jread_range_stop_cstr_done */ +/* read journal request is being decoded: range stop constructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID jread_range_stop_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 4, jread_list_of_var_cstr); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, jread_sa_entry_cstr); + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* jread_list_of_var_cstr */ +/* read journal request is being decoded: list of variables constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jread_list_of_var_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_list_of_var_cstr"); + + req_info->list_of_var_pres = SD_TRUE; + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, jread_get_var); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jread_list_of_var_cstr_done; + } + +/************************************************************************/ +/* jread_get_var */ +/* read journal request is being decoded: variable was encountered. */ +/************************************************************************/ + +static ST_VOID jread_get_var (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_get_var"); + + req_info->num_of_var++; /* increment # of var */ + if (req_info->num_of_var > max_vars) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + /* copy variable back onto itself shifted by one character */ + *var_ptr = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_vstr (aCtx, *var_ptr)) + { /* variable is too ST_INT32 */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + var_ptr++; /* point to where next will go */ + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, jread_get_var); + } + +/************************************************************************/ +/* jread_list_of_var_cstr_done */ +/* read journal request is being decoded: list of variable constructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID jread_list_of_var_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, jread_sa_entry_cstr); + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* jread_sa_entry_cstr */ +/* read journal request is being decoded: start after entry constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jread_sa_entry_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_sa_entry_cstr"); + + req_info->sa_entry_pres = SD_TRUE; + + ASN1R_TAG_ADD (aCtx, CTX, 0, jread_get_time_spec); + } + +/************************************************************************/ +/* jread_get_time_spec */ +/* initialize journal request is being decoded: time specification was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jread_get_time_spec (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_get_time_spec"); + + if (asn1r_get_btod (aCtx, &req_info->time_spec)) /* get time spec */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 1, jread_entry_spec_prim); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, jread_entry_spec_cstr); + } + +/************************************************************************/ +/* jread_entry_spec_prim */ +/* read journal request is being decoded: entry specification prim was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jread_entry_spec_prim (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_entry_spec_prim"); + + /* decode entry spec back onto itself */ + req_info->entry_spec = aCtx->asn1r_field_ptr; + + if (asn1r_get_octstr (aCtx, req_info->entry_spec)) /* read entry spec */ + asn1r_set_dec_err (aCtx, REQ_UNSPECIFIED); + + req_info->entry_spec_len = aCtx->asn1r_octetcount; + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jread_sa_entry_cstr_done; + } + +/************************************************************************/ +/* jread_entry_spec_cstr */ +/* read journal request is being decoded: entry specification cstr */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jread_entry_spec_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jread_entry_spec_cstr"); + + /* decode entry spec back onto itself */ + req_info->entry_spec = aCtx->asn1r_field_ptr; + + /* set up done decoding octet cstr destination */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jread_entry_spec_cstr_done; + + /* get entry spec from the received message */ + /* set maximum length to accept entire message */ + asn1r_get_octstr_cstr (aCtx, _mmsdec_msglen, req_info->entry_spec); + } + +/************************************************************************/ +/* jread_entry_spec_cstr_done */ +/* read journal request is being decoded: entry spec constructor done */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jread_entry_spec_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + req_info->entry_spec_len = aCtx->asn1r_octetcount; /* save entry spec len */ + + /* set up done decoding entry spec cstr dest */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jread_sa_entry_cstr_done; + } + +/************************************************************************/ +/* jread_sa_entry_cstr_done */ +/* read journal request is being decoded: start after entry constructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID jread_sa_entry_cstr_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check2 (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* jread_dec_done */ +/* read journal request is completely done. Any extra storage is */ +/* given back. */ +/************************************************************************/ + +static ST_VOID jread_dec_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + /* find actual size for request info */ + req_size = sizeof (JREAD_REQ_INFO) + + (sizeof (ST_CHAR *) * req_info->num_of_var); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (JREAD_REQ_INFO *) _mms_dec_info; + + _mms_dec_done_ok (aCtx); + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_jread_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the read journal response. */ +/************************************************************************/ + +ST_RET mp_jread_resp (MMSREQ_IND *indptr, JREAD_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_READ_JOURNAL,indptr, + M_CAST_MK_FUN (_ms_mk_jread_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_jread_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the read journal response. */ +/************************************************************************/ + +ST_RET mpl_jread_resp (ST_UINT32 invoke_id, JREAD_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_READ_JOURNAL,invoke_id, + M_CAST_MK_FUN (_ms_mk_jread_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_jread_resp */ +/* ENCODE a read journal RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_jread_resp (ASN1_ENC_CTXT *aCtx, JREAD_RESP_INFO *info_ptr) + { +ST_INT i; +ST_INT jel_size; +JOURNAL_ENTRY **je_list; +JOURNAL_ENTRY **je_list_save; +JOURNAL_ENTRY *je_ptr; +VAR_INFO *vi_ptr; + + if (info_ptr->more_follows) + + { /* not the default */ + asn1r_wr_bool (aCtx, info_ptr->more_follows); + asn1r_fin_prim (aCtx, 1,CTX); /* context tag 1 */ + } + + + + + + /* allocate storage for ec ptrs */ + jel_size = sizeof (JOURNAL_ENTRY *) * (info_ptr->num_of_jou_entry+1); + je_list = (JOURNAL_ENTRY **) chk_calloc (1, jel_size); + je_list_save = je_list; /* save the ptr list pointer */ + /* find first journal entry */ + je_ptr = (JOURNAL_ENTRY *) (info_ptr + 1); + *(je_list) = je_ptr; + for (i = 1; i < info_ptr->num_of_jou_entry; i++) + { /* find ptrs to journal entries */ + if (je_ptr->ent_content.entry_form_tag == 2 && + je_ptr->ent_content.ef.data.list_of_var_pres) + { + vi_ptr = (VAR_INFO *) (je_ptr + 1); + vi_ptr += je_ptr->ent_content.ef.data.num_of_var; + je_ptr = (JOURNAL_ENTRY *) vi_ptr; + } + else + je_ptr++; + + *(++je_list) = je_ptr; + } + + asn1r_strt_constr (aCtx); /* start context tag 0 cstr */ + for (i=0; i < info_ptr->num_of_jou_entry; i++) + { + asn1r_strt_constr (aCtx); /* start journal entry cstr */ + je_ptr = *(je_list--); + asn1r_strt_constr (aCtx); /* start context tag 2 cstr */ + _ms_wr_jou_ent_cont (aCtx, &je_ptr->ent_content); + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* finish context tag 2 cstr */ + asn1r_strt_constr (aCtx); /* start originating ae cstr */ + asn1r_wr_delmnt (aCtx, je_ptr->orig_ae,je_ptr->orig_ae_len); + asn1r_fin_constr (aCtx, 1,CTX,DEF); /* finish context tag 1 cstr */ + asn1r_wr_octstr (aCtx, je_ptr->entry_id, je_ptr->entry_id_len); + asn1r_fin_prim (aCtx, 0,CTX); /* finish context tag 0 */ + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish journal entry cstr */ + } + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish context tag 0 cstr */ + chk_free (je_list_save); /* free the list pointer */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_READ_JOURNAL,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rs_jstat.c b/mmslib/mmsle/rs_jstat.c new file mode 100644 index 0000000..06391d8 --- /dev/null +++ b/mmslib/mmsle/rs_jstat.c @@ -0,0 +1,130 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_jstat.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of report journal */ +/* status. It decodes the report journal status request */ +/* (indication) & encodes the report journal status response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pjou.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static JSTAT_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID jstat_jn_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_jstat_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_jstat_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Report Journal Status Request"); + + +/* get storage for request information */ + req_info = (JSTAT_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (JSTAT_REQ_INFO)); + _ms_get_mms_objname (aCtx, &req_info->jou_name, jstat_jn_done); + } + +/************************************************************************/ +/* jstat_jn_done */ +/* report journal status request is being decoded: journal name has */ +/* been obtained. */ +/************************************************************************/ + +static ST_VOID jstat_jn_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jstat_jn_done"); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_jstat_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the report journal status response. */ +/************************************************************************/ + +ST_RET mp_jstat_resp (MMSREQ_IND *indptr, JSTAT_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_STAT_JOURNAL,indptr, + M_CAST_MK_FUN (_ms_mk_jstat_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_jstat_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the report journal status response. */ +/************************************************************************/ + +ST_RET mpl_jstat_resp (ST_UINT32 invoke_id, JSTAT_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_STAT_JOURNAL,invoke_id, + M_CAST_MK_FUN (_ms_mk_jstat_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_jstat_resp */ +/* ENCODE a report journal status RESPONSE: */ +/************************************************************************/ + +ST_VOID _ms_mk_jstat_resp (ASN1_ENC_CTXT *aCtx, JSTAT_RESP_INFO *info_ptr) + { + asn1r_wr_bool (aCtx, info_ptr->mms_deletable); /* write the deletable param */ + asn1r_fin_prim (aCtx, 1,CTX); + + asn1r_wr_u32 (aCtx, info_ptr->cur_entries); /* encode current entries */ + asn1r_fin_prim (aCtx, 0,CTX); + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_STAT_JOURNAL,CTX,DEF); /* tag = opcode, ctx */ + } diff --git a/mmslib/mmsle/rs_jwrit.c b/mmslib/mmsle/rs_jwrit.c new file mode 100644 index 0000000..2cc4e12 --- /dev/null +++ b/mmslib/mmsle/rs_jwrit.c @@ -0,0 +1,241 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_jwrite.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of write journal. */ +/* It decodes the write journal request (indication) & encodes */ +/* the write journal response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pjou.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static JWRITE_REQ_INFO *req_info; + +static ENTRY_CONTENT *ec_ptr; +static ST_INT max_entries; +static ST_INT max_data_vars; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/* static functions with multiple references */ + +static ST_VOID jwrite_jou_entry_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jwrite_je_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jwrite_list_of_je_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jwrite_list_of_je_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID jwrite_jname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jwrite_jname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID jwrite_jname_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_jwrite_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_jwrite_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Write Journal Request"); + +#if defined(FIXED_DECBUF) + max_entries = m_sv_max_entry_content; + max_data_vars = m_sv_max_data_vars; + req_size = mmsl_dec_info_size; +#else + max_entries = (_mmsdec_msglen/4); + max_data_vars = (_mmsdec_msglen/6); + if (m_sv_max_entry_content && (max_entries > m_sv_max_entry_content)) + max_entries = m_sv_max_entry_content; + if (m_sv_max_data_vars && (max_data_vars > m_sv_max_data_vars)) + max_data_vars = m_sv_max_data_vars; + + req_size = sizeof (JWRITE_REQ_INFO) + + (max_entries * sizeof (ENTRY_CONTENT)) + + (max_data_vars * sizeof (VAR_INFO)); +#endif + +/* get storage for request information */ + req_info = (JWRITE_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + ec_ptr = (ENTRY_CONTENT *) (req_info + 1); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, jwrite_jname_cstr); + } + +/************************************************************************/ +/* jwrite_jname_cstr */ +/* write journal request is being decoded: journal name constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jwrite_jname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jwrite_jname_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->jou_name, jwrite_jname_done); + } + +/************************************************************************/ +/* jwrite_jname_done */ +/* write journal request is being decoded: journal name has been */ +/* obtained. */ +/************************************************************************/ + +static ST_VOID jwrite_jname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jwrite_jname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jwrite_jname_cstr_done; + } + +/************************************************************************/ +/* jwrite_jname_cstr_done */ +/* write journal request is being decoded: journal name cstr done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jwrite_jname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, jwrite_list_of_je_cstr); + } + +/************************************************************************/ +/* jwrite_list_of_je_cstr */ +/* write journal request is being decoded: list of journal entry cstr */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID jwrite_list_of_je_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jwrite_list_of_je_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, jwrite_jou_entry_cstr); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = jwrite_list_of_je_cstr_done; + } + +/************************************************************************/ +/* jwrite_jou_entry_cstr */ +/* write journal request is being decoded: journal entry cstr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID jwrite_jou_entry_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("jwrite_jou_entry_cstr"); + + req_info->num_of_jou_entry++; /* increment # of journal entry */ + if (req_info->num_of_jou_entry > max_entries) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + _ms_get_jou_ent_cont (aCtx, ec_ptr, max_data_vars, jwrite_je_done); + } + +/************************************************************************/ +/* jwrite_je_done */ +/* write journal request is being decoded: journal entry has been */ +/* obtained. */ +/************************************************************************/ + +static ST_VOID jwrite_je_done (ASN1_DEC_CTXT *aCtx) + { +VAR_INFO *vi_ptr; + + MLOG_CDEC0 ("jwrite_je_done"); + + /* point to where next will go */ + if (ec_ptr->entry_form_tag == 2 && ec_ptr->ef.data.list_of_var_pres) + { + vi_ptr = (VAR_INFO *) (ec_ptr + 1); + ec_ptr = (ENTRY_CONTENT *) (vi_ptr + ec_ptr->ef.data.num_of_var); + } + else + ec_ptr++; + + ASN1R_TAG_ADD (aCtx, UNI | CONSTR, SEQ_CODE, jwrite_jou_entry_cstr); + } + +/************************************************************************/ +/* jwrite_list_of_je_cstr_done */ +/* write journal request is being decoded: list of journal entry cstr */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID jwrite_list_of_je_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + /* find actual size for request info */ + req_size = (ST_CHAR *) ec_ptr - (ST_CHAR *) req_info; + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info, req_size); + req_info = (JWRITE_REQ_INFO *) _mms_dec_info; + + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_jwrite_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the write journal response. */ +/************************************************************************/ + +ST_RET mp_jwrite_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_WRITE_JOURNAL)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_jwrite_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the write journal response. */ +/************************************************************************/ + +ST_RET mpl_jwrite_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_WRITE_JOURNAL)); + } +#endif diff --git a/mmslib/mmsle/rs_kill.c b/mmslib/mmsle/rs_kill.c new file mode 100644 index 0000000..183f22d --- /dev/null +++ b/mmslib/mmsle/rs_kill.c @@ -0,0 +1,109 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_kill.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the kill */ +/* operation. It decodes the kill request (indication) and */ +/* encodes the kill response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static KILL_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID kill_get_piname (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_kill_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_kill_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Kill Request"); + + +/* get storage for request information */ + req_info = (KILL_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (KILL_REQ_INFO)); + ASN1R_TAG_ADD (aCtx, CTX, 0, kill_get_piname); + } + +/************************************************************************/ +/* kill_get_piname */ +/* kill request is being decoded: get the program invocation name. */ +/************************************************************************/ + +static ST_VOID kill_get_piname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("kill_get_piname"); + + /* read program invocation name from message */ + if (asn1r_get_identifier (aCtx, req_info->piname)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_kill_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the kill response. */ +/************************************************************************/ + +ST_RET mp_kill_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_KILL)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_kill_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the kill response. */ +/************************************************************************/ + +ST_RET mpl_kill_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_KILL)); + } +#endif diff --git a/mmslib/mmsle/rs_loadd.c b/mmslib/mmsle/rs_loadd.c new file mode 100644 index 0000000..2c19a8b --- /dev/null +++ b/mmslib/mmsle/rs_loadd.c @@ -0,0 +1,288 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_loaddom.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of load domain */ +/* content. It decodes the load domain content request */ +/* (indication) & encodes the load domain content response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static LOADDOM_REQ_INFO *req_info; + +static ST_CHAR **cap_ptr; +static ST_INT max_capabilities; +static ST_INT max_fnames; +static ST_UCHAR *ar_start; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ +static ST_VOID loaddom_fname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID loaddom_fname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID loaddom_get_sharable (ASN1_DEC_CTXT *aCtx); +static ST_VOID loaddom_get_cap (ASN1_DEC_CTXT *aCtx); +static ST_VOID loaddom_cap_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID loaddom_cap_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID loaddom_get_dname (ASN1_DEC_CTXT *aCtx); +static ST_VOID loaddom_third_pty_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID third_pty_cstr_done (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/************************************************************************/ +/* mms_load_domain_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_load_domain_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Load Domain Content Request"); + + +#if defined(FIXED_DECBUF) + max_fnames = m_sv_max_file_names; + max_capabilities = m_sv_max_loadd_cap; + req_size = mmsl_dec_info_size; +#else + max_capabilities = (_mmsdec_msglen/2); + max_fnames = (_mmsdec_msglen/2); + if (m_sv_max_loadd_cap && (max_capabilities > m_sv_max_loadd_cap)) + max_capabilities = m_sv_max_loadd_cap; + if (m_sv_max_file_names && (max_fnames > m_sv_max_file_names)) + max_fnames = m_sv_max_file_names; + req_size = sizeof(LOADDOM_REQ_INFO) + + (max_fnames * sizeof(FILE_NAME)) + + (max_capabilities * sizeof(ST_CHAR *)); +#endif + +/* get storage for request information */ + req_info = (LOADDOM_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + cap_ptr = (ST_CHAR **) (req_info + 1); + ASN1R_TAG_ADD (aCtx, CTX, 0,loaddom_get_dname); + } + +/************************************************************************/ +/* loaddom_get_dname */ +/* load domain content request is being decoded: domain name was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID loaddom_get_dname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("loaddom_get_dname"); + + if (asn1r_get_identifier (aCtx, req_info->dname)) /* read the domain name */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1,loaddom_cap_cstr); + } + +/************************************************************************/ +/* loaddom_cap_cstr */ +/* load domain content request is being decoded: capability list */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID loaddom_cap_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("loaddom_cap_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI,VISTR_CODE,loaddom_get_cap); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = loaddom_cap_cstr_done; + } + +/************************************************************************/ +/* loaddom_get_cap */ +/* load domain content request is being decoded: capability string */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID loaddom_get_cap (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("loaddom_get_cap"); + + req_info->num_of_capab++; /* increment # of capabilities */ + if (req_info->num_of_capab > max_capabilities) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + /* copy capability back onto itself shifted by one character */ + *cap_ptr = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_vstr (aCtx, *cap_ptr)) + { /* capability is too ST_INT32 */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + cap_ptr++; /* point to where next will go */ + + ASN1R_TAG_ADD (aCtx, UNI,VISTR_CODE,loaddom_get_cap); + } + +/************************************************************************/ +/* loaddom_cap_cstr_done */ +/* load domain content request is being decoded: capability list */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID loaddom_cap_cstr_done (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX,2,loaddom_get_sharable); + } + +/************************************************************************/ +/* loaddom_get_sharable */ +/* load domain content request is being decoded: sharable was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID loaddom_get_sharable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("loaddom_get_sharable"); + /* read sharable from the received message */ + if (asn1r_get_bool (aCtx, &(req_info->sharable))) + { /* sharable is too ST_INT32 */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,4,loaddom_fname_cstr); + } + +/************************************************************************/ +/* loaddom_fname_cstr */ +/* load domain content request is being decoded: filename cstr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID loaddom_fname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("loaddom_fname_cstr"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = loaddom_fname_cstr_done; + +/* In the case of a request domain download request the file names are */ +/* put right after the cabability string pointers. The max number of */ +/* these file names is the same worst case as the capability strings. */ + + _ms_get_mms_fname (aCtx, (FILE_NAME *) cap_ptr, max_fnames, &req_info->num_of_fname); + } + +/************************************************************************/ +/* loaddom_fname_cstr_done */ +/* load domain content request is being decoded: file name list */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID loaddom_fname_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + /* find actual size for request info */ + req_size = sizeof (LOADDOM_REQ_INFO) + + (sizeof (ST_CHAR *) * req_info->num_of_capab) + + (sizeof (FILE_NAME) * req_info->num_of_fname); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info, req_size); + req_info = (LOADDOM_REQ_INFO *) _mms_dec_info; + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 5, loaddom_third_pty_cstr); + ar_start = aCtx->asn1r_field_ptr; /* save in case third party rcvd */ + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* loaddom_third_pty_cstr */ +/* load domain content request is being decoded: third party */ +/* cstr was encountered. */ +/************************************************************************/ + +static ST_VOID loaddom_third_pty_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("loaddom_third_pty_cstr"); + + req_info->third_pty_pres = SD_TRUE; /* set third party */ + req_info->third_pty = ar_start; /* save_start */ + *ar_start = '\x30'; /* change tag */ + + if (aCtx->asn1r_elmnt_len) + asn1r_parse_cstr_contents (aCtx, third_pty_cstr_done); + else + aCtx->asn1r_c_done_fun[ aCtx->asn1r_msg_level ] = third_pty_cstr_done; + } + +/************************************************************************/ +/* third_pty_cstr_done */ +/* load domain content request is being decoded: third party */ +/* was encountered and read into req structure. */ +/************************************************************************/ + +static ST_VOID third_pty_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("third_pty_cstr_done"); + + req_info->third_pty_len = aCtx->asn1r_field_ptr - ar_start; + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_loaddom_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the load domain content response. */ +/************************************************************************/ + +ST_RET mp_loaddom_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_LOAD_DOMAIN)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_loaddom_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the load domain content response. */ +/************************************************************************/ + +ST_RET mpl_loaddom_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_LOAD_DOMAIN)); + } +#endif diff --git a/mmslib/mmsle/rs_obtfi.c b/mmslib/mmsle/rs_obtfi.c new file mode 100644 index 0000000..a15225c --- /dev/null +++ b/mmslib/mmsle/rs_obtfi.c @@ -0,0 +1,217 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_obtfile.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the obtain file. */ +/* It decodes the obtain file request (indication) and encodes */ +/* the obtain file response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static OBTFILE_REQ_INFO *reqinfo; + +static ST_INT max_fnames; +static FILE_NAME *fname_idx; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +/************************************************************************/ +/* static functions with multiple references */ +static ST_VOID obtfile_src_fname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID ar_title_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID obtfile_dest_fname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID obtfile_dest_fname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID obtfile_src_fname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID obtfile_ar_title_cstr (ASN1_DEC_CTXT *aCtx); + +static ST_UCHAR *ar_start; + + +/************************************************************************/ +/************************************************************************/ +/* mms_obtain_file_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_obtain_file_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Obtain File Request"); + +#if defined(FIXED_DECBUF) + max_fnames = m_sv_max_file_names; + req_size = mmsl_dec_info_size; +#else + max_fnames = (_mmsdec_msglen/2); + if (m_sv_max_file_names && (max_fnames > m_sv_max_file_names)) + max_fnames = m_sv_max_file_names; + req_size = sizeof (OBTFILE_REQ_INFO) + (max_fnames * sizeof (FILE_NAME)); +#endif + +/* get storage for request information */ + reqinfo = (OBTFILE_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + reqinfo->ar_title_pres = SD_FALSE; /* set default value */ + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, obtfile_ar_title_cstr); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 1, obtfile_src_fname_cstr); + + ar_start = aCtx->asn1r_field_ptr; /* save start of AR constructor */ + } + +/************************************************************************/ +/* obtfile_ar_title_cstr */ +/* obtain file request is being decoded : application title constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID obtfile_ar_title_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("obtfile_ar_title_cstr"); + + reqinfo->ar_title_pres = SD_TRUE; /* set ap title present */ + reqinfo->ar_title = ar_start; /* save start */ + *ar_start = '\x30'; /* change tag */ + + if (aCtx->asn1r_elmnt_len) + asn1r_parse_cstr_contents (aCtx, ar_title_cstr_done); + else /* no contents, call user done function */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = ar_title_cstr_done; + } + +/************************************************************************/ +/* ar_title_cstr_done */ +/* obtain file request is being decoded : application title primitive */ +/* was encountered and read. */ +/************************************************************************/ + +static ST_VOID ar_title_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("ar_title_cstr_done"); + + reqinfo->ar_len = aCtx->asn1r_field_ptr - ar_start; + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,obtfile_src_fname_cstr); + } + +/************************************************************************/ +/* obtfile_src_fname_cstr */ +/* obtain file request is being decoded: source filename cstr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID obtfile_src_fname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("obtfile_src_fname_cstr"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = obtfile_src_fname_cstr_done; + fname_idx = (FILE_NAME *)(reqinfo + 1); + _ms_get_mms_fname (aCtx, fname_idx, max_fnames, &reqinfo->num_of_src_fname); + } + +/************************************************************************/ +/* obtfile_src_fname_cstr_done */ +/* obtain file request is being decoded: source file name list */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID obtfile_src_fname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,obtfile_dest_fname_cstr); + } + +/************************************************************************/ +/* obtfile_dest_fname_cstr */ +/* obtain file request is being decoded: destination filename cstr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID obtfile_dest_fname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("obtfile_dest_fname_cstr"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = obtfile_dest_fname_cstr_done; + fname_idx += reqinfo -> num_of_src_fname; + _ms_get_mms_fname (aCtx, fname_idx, max_fnames, &reqinfo->num_of_dest_fname); + } + +/************************************************************************/ +/* obtfile_dest_fname_cstr_done */ +/* obtain file request is being decoded: destination file name list */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID obtfile_dest_fname_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + /* find actual size for request info */ + req_size = sizeof (OBTFILE_REQ_INFO) + + (sizeof (FILE_NAME) * reqinfo->num_of_src_fname) + + (sizeof (FILE_NAME) * reqinfo->num_of_dest_fname); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + reqinfo = (OBTFILE_REQ_INFO *) _mms_dec_info; + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_obtfile_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the obtain file response. */ +/************************************************************************/ + +ST_RET mp_obtfile_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_OBTAIN_FILE)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_obtfile_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the obtain file response. */ +/************************************************************************/ + +ST_RET mpl_obtfile_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_OBTAIN_FILE)); + } +#endif diff --git a/mmslib/mmsle/rs_outpu.c b/mmslib/mmsle/rs_outpu.c new file mode 100644 index 0000000..9a6b988 --- /dev/null +++ b/mmslib/mmsle/rs_outpu.c @@ -0,0 +1,184 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_output.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the output */ +/* operation. It decodes the output request (indication) and */ +/* encodes the output response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pocs.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static OUTPUT_REQ_INFO *req_info; + +static ST_INT max_data_count; +static ST_CHAR **data_ptr; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID output_get_data (ASN1_DEC_CTXT *aCtx); +static ST_VOID output_data_list_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID output_get_data_list_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID output_get_station_name (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_output_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_output_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Output Request"); + +#if defined(FIXED_DECBUF) + req_size = mmsl_dec_info_size; + max_data_count = m_sv_max_data_count; +#else + max_data_count = _mmsdec_msglen / 2; /* find maximum size */ + if (m_sv_max_data_count && (max_data_count > m_sv_max_data_count)) + max_data_count = m_sv_max_data_count; + req_size = sizeof (OUTPUT_REQ_INFO) + (sizeof (ST_CHAR *) * max_data_count); +#endif + +/* get storage for request information */ + req_info = (OUTPUT_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + data_ptr = (ST_CHAR **) (req_info + 1); + req_info->data_count = 0; + + ASN1R_TAG_ADD (aCtx, CTX, 0, output_get_station_name); + } + +/************************************************************************/ +/* output_get_station_name */ +/* Output request: decode the operator station name */ +/************************************************************************/ + +static ST_VOID output_get_station_name (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("output_get_station_name"); + /* read station name from message */ + if (asn1r_get_identifier (aCtx, req_info->station_name)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, output_get_data_list_cstr); + } + +/************************************************************************/ +/* output_get_data_list_cstr */ +/* Output request: decode the output data constructor */ +/************************************************************************/ + +static ST_VOID output_get_data_list_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("output_get_data_list_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, output_get_data); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = output_data_list_cstr_done; + } + +/************************************************************************/ +/* output_get_data */ +/* Output request: decode the output data */ +/************************************************************************/ + +static ST_VOID output_get_data (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("output_get_data"); + + req_info->data_count++; /* increment output data count */ + if (req_info->data_count > max_data_count) + { /* too many output data strings */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + *data_ptr = (ST_CHAR *) aCtx->asn1r_field_ptr-1; /* set output data pointer */ + if (asn1r_get_vstr (aCtx, *data_ptr)) /* shift output data left */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + data_ptr++; /* point to where next will go */ + + ASN1R_TAG_ADD (aCtx, UNI, VISTR_CODE, output_get_data); + } + +/************************************************************************/ +/* output_data_list_cstr_done */ +/* Output request: output data list constructor done */ +/************************************************************************/ + +static ST_VOID output_data_list_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + /* find actual size for request info */ + req_size = sizeof (OUTPUT_REQ_INFO) + + (sizeof (ST_CHAR *) * req_info->data_count); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (OUTPUT_REQ_INFO *) _mms_dec_info; + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_output_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the output response. */ +/************************************************************************/ + +ST_RET mp_output_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_OUTPUT)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_output_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the output response. */ +/************************************************************************/ + +ST_RET mpl_output_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_OUTPUT)); + } +#endif diff --git a/mmslib/mmsle/rs_rddwn.c b/mmslib/mmsle/rs_rddwn.c new file mode 100644 index 0000000..f5d6efa --- /dev/null +++ b/mmslib/mmsle/rs_rddwn.c @@ -0,0 +1,251 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_rddwn.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of request domain */ +/* download. It decodes the request domain download request */ +/* (indication) & encodes the request domain download response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static RDDWN_REQ_INFO *req_info; + +static ST_CHAR **cap_ptr; +static ST_INT max_capabilities; +static ST_INT max_fnames; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID rddwn_fname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID rddwn_get_sharable (ASN1_DEC_CTXT *aCtx); +static ST_VOID rddwn_get_cap (ASN1_DEC_CTXT *aCtx); +static ST_VOID rddwn_cap_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID rddwn_cap_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID rddwn_get_dname (ASN1_DEC_CTXT *aCtx); +static ST_VOID rddwn_fname_cstr_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_rddwn_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_rddwn_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Request Domain Download Request"); + + +#if defined(FIXED_DECBUF) + max_fnames = m_sv_max_file_names; + max_capabilities = m_sv_max_rqdlnl_cap; + req_size = mmsl_dec_info_size; +#else + max_capabilities = (_mmsdec_msglen/2); + max_fnames = (_mmsdec_msglen/2); + if (m_sv_max_rqdlnl_cap && (max_capabilities > m_sv_max_rqdlnl_cap)) + max_capabilities = m_sv_max_rqdlnl_cap; + if (m_sv_max_file_names && (max_fnames > m_sv_max_file_names)) + max_fnames = m_sv_max_file_names; + req_size = sizeof(RDDWN_REQ_INFO) + + (max_fnames * sizeof(FILE_NAME)) + + (max_capabilities * sizeof(ST_CHAR *)); +#endif + +/* get storage for request information */ + req_info = (RDDWN_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + cap_ptr = (ST_CHAR **) (req_info + 1); + ASN1R_TAG_ADD (aCtx, CTX, 0,rddwn_get_dname); + } + +/************************************************************************/ +/* rddwn_get_dname */ +/* request domain download request is being decoded: domain name */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID rddwn_get_dname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rddwn_get_dname"); + + if (asn1r_get_identifier (aCtx, req_info->dname)) /* read the domain name */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 1, rddwn_cap_cstr); + } + +/************************************************************************/ +/* rddwn_cap_cstr */ +/* request domain download request is being decoded: capability list */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID rddwn_cap_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rddwn_cap_cstr"); + + ASN1R_TAG_ADD (aCtx, UNI,VISTR_CODE,rddwn_get_cap); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = rddwn_cap_cstr_done; + } + +/************************************************************************/ +/* rddwn_get_cap */ +/* request domain download request is being decoded: capability was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID rddwn_get_cap (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rddwn_get_cap"); + + req_info->num_of_capab++; /* increment # of capabilities */ + if (req_info->num_of_capab > max_capabilities) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + /* copy capability back onto itself shifted by one character */ + *cap_ptr = (ST_CHAR *) aCtx->asn1r_field_ptr - 1; + if (asn1r_get_vstr (aCtx, *cap_ptr)) + { /* capability is too ST_INT32 */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + cap_ptr++; /* point to where next will go */ + + ASN1R_TAG_ADD (aCtx, UNI,VISTR_CODE,rddwn_get_cap); + } + +/************************************************************************/ +/* rddwn_cap_cstr_done */ +/* request domain download request is being decoded: capability list */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID rddwn_cap_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX,2,rddwn_get_sharable); + } + +/************************************************************************/ +/* rddwn_get_sharable */ +/* request domain download request is being decoded: sharable was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID rddwn_get_sharable (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rddwn_get_sharable"); + + /* read sharable from the received message */ + if (asn1r_get_bool (aCtx, &(req_info->sharable))) + { /* sharable is too ST_INT32 */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,4,rddwn_fname_cstr); + } + +/************************************************************************/ +/* rddwn_fname_cstr */ +/* request domain download request is being decoded: filename cstr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID rddwn_fname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rddwn_fname_cstr"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = rddwn_fname_cstr_done; + +/* In the case of a request domain download request the file names are */ +/* put right after the cabability string pointers. The max number of */ +/* these file names is the same worst case as the capability strings. */ + + _ms_get_mms_fname (aCtx, (FILE_NAME *) cap_ptr, max_fnames, &req_info->num_of_fname); + } + +/************************************************************************/ +/* rddwn_fname_cstr_done */ +/* request domain download request is being decoded: file name list */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID rddwn_fname_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + /* find actual size for request info */ + req_size = sizeof (RDDWN_REQ_INFO) + + (sizeof (ST_CHAR *) * req_info->num_of_capab) + + (sizeof (FILE_NAME) * req_info->num_of_fname); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (RDDWN_REQ_INFO *) _mms_dec_info; + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_rddwn_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the request domain download response. */ +/************************************************************************/ + +ST_RET mp_rddwn_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_REQ_DOM_DOWN)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_rddwn_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the request domain download response. */ +/************************************************************************/ + +ST_RET mpl_rddwn_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_REQ_DOM_DOWN)); + } +#endif diff --git a/mmslib/mmsle/rs_rdupl.c b/mmslib/mmsle/rs_rdupl.c new file mode 100644 index 0000000..ae8d25b --- /dev/null +++ b/mmslib/mmsle/rs_rdupl.c @@ -0,0 +1,157 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_rdupl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of request domain */ +/* upload. It decodes the request domain upload request */ +/* (indication) & encodes the request domain upload response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------ */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static RDUPL_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : */ +static ST_INT max_fnames; + +static ST_VOID rdupl_fname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID rdupl_get_dname (ASN1_DEC_CTXT *aCtx); +static ST_VOID rdupl_fname_cstr_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_rdupl_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_rdupl_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Request Domain Upload Request"); + +#if defined(FIXED_DECBUF) + max_fnames = m_sv_max_file_names; + req_size = mmsl_dec_info_size; +#else + max_fnames = (_mmsdec_msglen/2); + if (m_sv_max_file_names && (max_fnames > m_sv_max_file_names)) + max_fnames = m_sv_max_file_names; + req_size = sizeof (RDUPL_REQ_INFO) + (max_fnames * sizeof (FILE_NAME)); +#endif + +/* get storage for request information */ + req_info = (RDUPL_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + ASN1R_TAG_ADD (aCtx, CTX, 0,rdupl_get_dname); + } + +/************************************************************************/ +/* rdupl_get_dname */ +/* request domain upload request is being decoded: domain name was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID rdupl_get_dname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rdupl_get_dname"); + + if (asn1r_get_identifier (aCtx, req_info->dname)) /* read the domain name */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,rdupl_fname_cstr); + } + +/************************************************************************/ +/* rdupl_fname_cstr */ +/* request domain upload request is being decoded: filename cstr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID rdupl_fname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rdupl_fname_cstr"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = rdupl_fname_cstr_done; + _ms_get_mms_fname (aCtx, (FILE_NAME *)(req_info + 1), max_fnames, + &req_info->num_of_fname); + } + +/************************************************************************/ +/* rdupl_fname_cstr_done */ +/* request domain upload request is being decoded: file name list */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID rdupl_fname_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + /* find actual size for request info */ + req_size = sizeof (RDUPL_REQ_INFO) + + (sizeof (FILE_NAME) * req_info->num_of_fname); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (RDUPL_REQ_INFO *) _mms_dec_info; + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_rdupl_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the request domain upload response. */ +/************************************************************************/ + +ST_RET mp_rdupl_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_REQ_DOM_UPL)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_rdupl_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the request domain upload response. */ +/************************************************************************/ + +ST_RET mpl_rdupl_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_REQ_DOM_UPL)); + } +#endif diff --git a/mmslib/mmsle/rs_relct.c b/mmslib/mmsle/rs_relct.c new file mode 100644 index 0000000..5d438bd --- /dev/null +++ b/mmslib/mmsle/rs_relct.c @@ -0,0 +1,148 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_relctrl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of relinquish */ +/* semaphore control. It decodes the relinquish control request */ +/* (indication) and encodes the relinquish control response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 08/28/03 EJV 05 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_psem.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static RELCTRL_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID relctrl_sem_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID relctrl_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID relctrl_sem_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID relctrl_get_named_token (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_relctrl_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_relctrl_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Relinquish Control Request"); + req_info = (RELCTRL_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (RELCTRL_REQ_INFO)); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, relctrl_sem_name_cstr); + } + +/************************************************************************/ +/* relctrl_sem_name_cstr */ +/* Decoding relinquish control request: semaphore name constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID relctrl_sem_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("relctrl_sem_name_cstr"); + req_info->named_token_pres = SD_FALSE; /* set default value */ + _ms_get_mms_objname (aCtx, &req_info->sem_name, relctrl_objname_done); + } + +/************************************************************************/ +/* relctrl_objname_done */ +/* Decoding take control request: Semaphore name has been obtained */ +/************************************************************************/ + +static ST_VOID relctrl_objname_done (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = relctrl_sem_name_cstr_done; + } + +/************************************************************************/ +/* relctrl_sem_name_cstr_done */ +/* Decoding relinquish control request: semaphore name contructor done */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID relctrl_sem_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, relctrl_get_named_token ); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* relctrl_get_named_token */ +/* Decoding relinquish control request: named token was encountered. */ +/************************************************************************/ + +static ST_VOID relctrl_get_named_token (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("relctrl_get_named_token"); + + req_info->named_token_pres = SD_TRUE; /* set named token present */ + + /* read named token from received message */ + if (asn1r_get_identifier (aCtx, req_info->named_token)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_relctrl_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the relinquish control response. */ +/************************************************************************/ + +ST_RET mp_relctrl_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_REL_CONTROL)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_relctrl_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the relinquish control response. */ +/************************************************************************/ + +ST_RET mpl_relctrl_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_REL_CONTROL)); + } +#endif diff --git a/mmslib/mmsle/rs_renam.c b/mmslib/mmsle/rs_renam.c new file mode 100644 index 0000000..9d01190 --- /dev/null +++ b/mmslib/mmsle/rs_renam.c @@ -0,0 +1,232 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_rename.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the Rename */ +/* service. It decodes the Rename request (indication) and */ +/* encodes the Rename response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 04/28/00 JRB 04 Lint cleanup */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static RENAME_REQ_INFO *info; + +static ST_VOID rename_ext_objclass (ASN1_DEC_CTXT *aCtx); +static ST_VOID rename_get_objclass (ASN1_DEC_CTXT *aCtx); +#ifdef CS_SUPPORT +static ST_VOID rename_get_cs_objclass (ASN1_DEC_CTXT *aCtx); +static ST_VOID rename_cs_objclass_done (ASN1_DEC_CTXT *aCtx); +#endif +static ST_VOID rename_ext_objclass_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID rename_get_curname (ASN1_DEC_CTXT *aCtx); +static ST_VOID rename_curname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID rename_curname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID rename_get_new_ident (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_rename_req */ +/* This function is called from MMSDEC when the opcode of a request */ +/* PDU for this operation is decoded. Setup state machine function */ +/* pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_rename_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Rename Request"); + + info = (RENAME_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (RENAME_REQ_INFO)); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,rename_ext_objclass); + } + +/************************************************************************/ +/* rename_ext_objclass */ +/* Rename response is being decoded: object class parameter has */ +/* been encountered. */ +/************************************************************************/ + +static ST_VOID rename_ext_objclass (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rename_ext_objclass"); + + ASN1R_TAG_ADD (aCtx, CTX, 0,rename_get_objclass); +#ifdef CS_SUPPORT + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,rename_get_cs_objclass); +#endif + } + +/************************************************************************/ +/* rename_get_objclass */ +/* Rename response is being decoded: object class parameter has */ +/* been encountered. */ +/************************************************************************/ + +static ST_VOID rename_get_objclass (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rename_get_objclass"); + /* read the object class */ + if (asn1r_get_i16 (aCtx, &info->obj.mms_class) || + info->obj.mms_class < 0 || + info->obj.mms_class > 11) + { + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + return; + } + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = rename_ext_objclass_done; + } + +#ifdef CS_SUPPORT +/************************************************************************/ +/* rename_get_cs_objclass */ +/* Rename response is being decoded: CS object class parameter has */ +/* been encountered. The contents here are a ANY, defined by CS. */ +/************************************************************************/ + +static ST_VOID rename_get_cs_objclass (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rename_get_cs_objclass"); + + info->cs_objclass_pres = SD_TRUE; /* set flag for CS object */ + info->obj.cs.len = aCtx->asn1r_elmnt_len; /* save pointer and len */ + info->obj.cs.cs_class = aCtx->asn1r_field_ptr; + + asn1r_parse_next (aCtx, rename_cs_objclass_done); /* ensure valid ASN.1 CS data */ + } + +/************************************************************************/ +/* rename_cs_objclass_done */ +/************************************************************************/ + +static ST_VOID rename_cs_objclass_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rename_cs_objclass_done"); + /* OK for extended object class to be done */ + aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = rename_ext_objclass_done; + } +#endif + +/************************************************************************/ +/* rename_ext_objclass_done */ +/* extendedObjectClass constructor done function. Set up to get Scope */ +/************************************************************************/ + +static ST_VOID rename_ext_objclass_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rename_extobj_class_done"); + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,rename_get_curname); /* get current Name */ + } + +/************************************************************************/ +/* rename_get_curname */ +/* Rename response is being decoded: object name constructor has */ +/* been encountered, set up to get the current name */ +/************************************************************************/ + +static ST_VOID rename_get_curname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rename_get_curname"); + + _ms_get_mms_objname (aCtx, &info->cur_name, rename_curname_done); + } + +/************************************************************************/ +/* rename_curname_done */ +/* rename request is being decoded: current name has been obtained. */ +/************************************************************************/ + +static ST_VOID rename_curname_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rename_curname_done"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = rename_curname_cstr_done; + } + +/************************************************************************/ +/* rename_curname_cstr_done */ +/* rename request is being decoded: current name constr done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID rename_curname_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rename_curname_cstr_done"); + + ASN1R_TAG_ADD (aCtx, CTX,2,rename_get_new_ident); + } + +/************************************************************************/ +/* rename_get_new_ident */ +/* Rename response is being decoded: new identifier parameter was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID rename_get_new_ident (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rename_get_new_ident"); + + if (asn1r_get_identifier (aCtx, info->new_ident)) /* new identifier */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_rename_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the rename response. */ +/************************************************************************/ + +ST_RET mp_rename_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_RENAME)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_rename_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the rename response. */ +/************************************************************************/ + +ST_RET mpl_rename_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_RENAME)); + } +#endif diff --git a/mmslib/mmsle/rs_reset.c b/mmslib/mmsle/rs_reset.c new file mode 100644 index 0000000..0fcdf22 --- /dev/null +++ b/mmslib/mmsle/rs_reset.c @@ -0,0 +1,109 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_reset.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the reset */ +/* operation. It decodes the reset request (indication) and */ +/* encodes the reset response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static RESET_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID reset_get_piname (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_reset_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_reset_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Reset Request"); + + +/* get storage for request information */ + req_info = (RESET_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (RESET_REQ_INFO)); + ASN1R_TAG_ADD (aCtx, CTX, 0, reset_get_piname); + } + +/************************************************************************/ +/* reset_get_piname */ +/* reset request is being decoded: get the program invocation name. */ +/************************************************************************/ + +static ST_VOID reset_get_piname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("reset_get_piname"); + + /* read program invocation name from message */ + if (asn1r_get_identifier (aCtx, req_info->piname)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_reset_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the reset response. */ +/************************************************************************/ + +ST_RET mp_reset_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_RESET)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_reset_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the reset response. */ +/************************************************************************/ + +ST_RET mpl_reset_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_RESET)); + } +#endif diff --git a/mmslib/mmsle/rs_resum.c b/mmslib/mmsle/rs_resum.c new file mode 100644 index 0000000..d6dc3f6 --- /dev/null +++ b/mmslib/mmsle/rs_resum.c @@ -0,0 +1,157 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_resume.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the resume */ +/* operation. It decodes the resume request (indication) and */ +/* encodes the resume response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static RESUME_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID resume_get_arg (ASN1_DEC_CTXT *aCtx); +static ST_VOID resume_get_piname (ASN1_DEC_CTXT *aCtx); +static ST_VOID extern_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_resume_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_resume_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Resume Request"); + + +/* get storage for request information */ + req_info = (RESUME_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (RESUME_REQ_INFO)); + ASN1R_TAG_ADD (aCtx, CTX, 0, resume_get_piname); + } + +/************************************************************************/ +/* resume_get_piname */ +/* resume request is being decoded: get the program invocation name. */ +/************************************************************************/ + +static ST_VOID resume_get_piname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("resume_get_piname"); + + /* read program invocation name from message */ + if (asn1r_get_identifier (aCtx, req_info->piname)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + + ASN1R_TAG_ADD (aCtx, CTX, 1, resume_get_arg); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + +/* If MMS IS, Check for ENCODED string */ +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + _ms_chk_for_extern (aCtx, &req_info->resume_arg_len, + &req_info->resume_arg, + extern_done); + } + +/************************************************************************/ +/* resume_get_arg */ +/* resume request is being decoded: get the resume argument. */ +/************************************************************************/ + +static ST_VOID resume_get_arg (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("resume_get_arg"); + + req_info->resume_arg_pres = SD_TRUE; /* set resume arg pres */ + + /* copy resume argument back onto itself shifted by one ST_CHAR */ + req_info->resume_arg = aCtx->asn1r_field_ptr - 1; + + req_info->resume_arg_type = ARG_TYPE_SIMPLE; + if (asn1r_get_vstr (aCtx, (ST_CHAR *)req_info->resume_arg)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* extern_done */ +/************************************************************************/ + +static ST_VOID extern_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("extern_done"); + + req_info->resume_arg_pres = SD_TRUE; /* set resume arg pres */ + req_info->resume_arg_type = ARG_TYPE_ENCODED; + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_resume_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the resume response. */ +/************************************************************************/ + +ST_RET mp_resume_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_RESUME)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_resume_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the resume response. */ +/************************************************************************/ + +ST_RET mpl_resume_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_RESUME)); + } +#endif diff --git a/mmslib/mmsle/rs_rsent.c b/mmslib/mmsle/rs_rsent.c new file mode 100644 index 0000000..a39dbb5 --- /dev/null +++ b/mmslib/mmsle/rs_rsent.c @@ -0,0 +1,305 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_rsentry.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of report semaphore */ +/* entry status. It decodes the report semaphore entry status */ +/* request (indication) and encodes the report semaphore status */ +/* response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 08 Remove "thisFileName" */ +/* 08/28/03 EJV 07 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_psem.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static RSENTRY_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID rsentry_start_after_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_get_start_after (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_start_after_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_get_state (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_sem_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID rsentry_sem_name_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_rsentry_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_rsentry_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Report Semaphore Entry Status Request"); + + +/* get storage for request information */ + req_info = (RSENTRY_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (RSENTRY_REQ_INFO)); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, rsentry_sem_name_cstr); + } + +/************************************************************************/ +/* rsentry_sem_name_cstr */ +/* Decoding report semaphore entry status request: semaphore name */ +/* constructor was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_sem_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsentry_sem_name_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->sem_name, rsentry_objname_done); + } + +/************************************************************************/ +/* rsentry_objname_done */ +/* Decoding a Report Semaphore Entry Status Request: Semaphore name has */ +/* been obtained. */ +/************************************************************************/ + +static ST_VOID rsentry_objname_done (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = rsentry_sem_name_cstr_done; + } + +/************************************************************************/ +/* rsentry_sem_name_cstr_done */ +/* Decoding report semaphore entry status request: semaphore name */ +/* contructor done was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_sem_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, rsentry_get_state); + } + +/************************************************************************/ +/* rsentry_get_state */ +/* Decoding report semaphore entry status request: semaphore state was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_get_state (ASN1_DEC_CTXT *aCtx) + { +ST_INT16 state; + + MLOG_CDEC0 ("rsentry_get_state"); + + /* read semaphore state from received message */ + if (asn1r_get_i16 (aCtx, &state)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + if ((state < 0) || (state > 2)) /* validate range of state [0..2]*/ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + else + req_info->state = state; /* valid semaphore state */ + + ASN1R_TAG_ADD (aCtx, CTX, 2, rsentry_get_start_after); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, rsentry_start_after_cstr); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* rsentry_get_start_after */ +/* Decoding report semaphore entry status request: entry id to start */ +/* after primitive was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_get_start_after (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsentry_get_start_after"); + + req_info->start_after_pres = SD_TRUE; /* set start after name present */ + + /* decode entry id onto itself, shifted by one character */ + req_info->start_after = aCtx->asn1r_field_ptr - 1; + + /* read entry id from message */ + if (asn1r_get_octstr (aCtx, req_info->start_after)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + req_info->sa_len = aCtx->asn1r_octetcount; /* save entry id length */ + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* rsentry_start_after_cstr */ +/* Decoding report semaphore entry status request: entry id to start */ +/* after constructor was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_start_after_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rsentry_start_after_cstr"); + + req_info->start_after_pres = SD_TRUE; /* set start after name present */ + + /* decode entry id onto itself, shifted by one character */ + req_info->start_after = aCtx->asn1r_field_ptr - 1; + + /* set up where to go when done decoding cstr */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = rsentry_start_after_cstr_done; + + /* read entry id from the received message */ + asn1r_get_octstr_cstr (aCtx, _mmsdec_msglen, req_info->start_after); + } + +/************************************************************************/ +/* rsentry_start_after_cstr_done */ +/* Decoding report semaphore entry status request: entry id to start */ +/* after constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID rsentry_start_after_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + req_info->sa_len = aCtx->asn1r_octetcount; /* save the start after length */ + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_rsentry_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the report pool semaphore entry status */ +/* response. */ +/************************************************************************/ + +ST_RET mp_rsentry_resp (MMSREQ_IND *indptr, RSENTRY_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_REP_SEMENTRY,indptr, + M_CAST_MK_FUN (_ms_mk_rsentry_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_rsentry_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the report pool semaphore entry status response. */ +/************************************************************************/ + +ST_RET mpl_rsentry_resp (ST_UINT32 invoke_id, RSENTRY_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_REP_SEMENTRY,invoke_id, + M_CAST_MK_FUN (_ms_mk_rsentry_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_rsentry_resp */ +/* Construct a report semaphore entry status response. */ +/************************************************************************/ + +ST_VOID _ms_mk_rsentry_resp (ASN1_ENC_CTXT *aCtx, RSENTRY_RESP_INFO *info) + { +SEMAPHORE_ENTRY *entry_ptr; +ST_INT i; + + asn1r_strt_constr (aCtx); /* start the sequence constr */ + + if (!info->more_follows) /* if not default value */ + { + asn1r_wr_bool (aCtx, info->more_follows); /* write more follows indicator */ + asn1r_fin_prim (aCtx, 1,CTX); + } + + asn1r_strt_constr (aCtx); /* start the ctx 0 constr */ + + entry_ptr = (SEMAPHORE_ENTRY *) (info + 1); + entry_ptr += info->num_of_sent - 1; /* point to last sem entry */ + for (i = 0; i < info->num_of_sent; i++) + { + asn1r_strt_constr (aCtx); /* start the sequence constr */ + /* write the entry id */ + if (!entry_ptr->rel_conn_lost) + { /* NOT the default value */ + asn1r_wr_bool (aCtx, entry_ptr->rel_conn_lost); + asn1r_fin_prim (aCtx, 7,CTX); + } + + if (entry_ptr->abrt_on_timeout_pres) + { + asn1r_wr_bool (aCtx, entry_ptr->abrt_on_timeout); + asn1r_fin_prim (aCtx, 6,CTX); + } + + if (entry_ptr->rem_timeout_pres) + { + asn1r_wr_u32 (aCtx, entry_ptr->rem_timeout); + asn1r_fin_prim (aCtx, 5,CTX); + } + + if (entry_ptr->priority != 64) + { /* NOT the default value */ + asn1r_wr_u8 (aCtx, entry_ptr->priority); + asn1r_fin_prim (aCtx, 4,CTX); + } + + if (entry_ptr->named_token_pres) + { + asn1r_wr_vstr (aCtx, entry_ptr->named_token); + asn1r_fin_prim (aCtx, 3,CTX); + } + + asn1r_strt_constr (aCtx); /* start the ctx 1 constr */ + asn1r_wr_delmnt (aCtx, entry_ptr->app_ref,entry_ptr->app_ref_len); + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* finish ctx 1 constructor */ + + asn1r_wr_i8 (aCtx, entry_ptr->entry_class); /* write entry class */ + asn1r_fin_prim (aCtx, 1,CTX); + + asn1r_wr_octstr (aCtx, entry_ptr->entry_id, entry_ptr->ei_len); + asn1r_fin_prim (aCtx, 0,CTX); + + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish sequence constructor */ + entry_ptr--; + } + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish ctx 0 constructor */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_REP_SEMENTRY,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rs_rspoo.c b/mmslib/mmsle/rs_rspoo.c new file mode 100644 index 0000000..efe1917 --- /dev/null +++ b/mmslib/mmsle/rs_rspoo.c @@ -0,0 +1,191 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_rspool.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of report pool */ +/* semaphore status. It decodes the report pool semaphroe status */ +/* request (indication) and encodes the report pool semaphore */ +/* status response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 08 Remove "thisFileName" */ +/* 08/28/03 EJV 07 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_psem.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static RSPOOL_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID rspool_get_start_after (ASN1_DEC_CTXT *aCtx); +static ST_VOID rspool_sem_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID rspool_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID rspool_sem_name_cstr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_rspool_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_rspool_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Report Pool Semaphore Status Request"); + + +/* get storage for request information */ + req_info = (RSPOOL_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (RSPOOL_REQ_INFO)); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 0, rspool_sem_name_cstr); + } + +/************************************************************************/ +/* rspool_sem_name_cstr */ +/* Decoding report semaphore status request: semaphore name constructor */ +/* was encountered. */ +/************************************************************************/ + +static ST_VOID rspool_sem_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rspool_sem_name_cstr"); + + _ms_get_mms_objname (aCtx, &req_info->sem_name, rspool_objname_done); + } + +/************************************************************************/ +/* rspool_objname_done */ +/* Decoding Report Semaphore Status Response: Semaphore name has been */ +/* obtained */ +/************************************************************************/ + +static ST_VOID rspool_objname_done (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = rspool_sem_name_cstr_done; + } + +/************************************************************************/ +/* rspool_sem_name_cstr_done */ +/* Decoding report semaphore status request: semaphore name contructor */ +/* done was encountered. */ +/************************************************************************/ + +static ST_VOID rspool_sem_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, rspool_get_start_after); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* rspool_get_start_after */ +/* Decoding report semaphore status request: application name to start */ +/* after was encountered. */ +/************************************************************************/ + +static ST_VOID rspool_get_start_after (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("rspool_get_start_after"); + + req_info->start_after_pres = SD_TRUE; + + /* read start after name from received message */ + if (asn1r_get_identifier (aCtx, req_info->start_after)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_rspool_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the report pool semaphore status response.*/ +/************************************************************************/ + +ST_RET mp_rspool_resp (MMSREQ_IND *indptr, RSPOOL_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_REP_SEMPOOL,indptr, + M_CAST_MK_FUN (_ms_mk_rspool_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_rspool_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the report pool semaphore status response. */ +/************************************************************************/ + +ST_RET mpl_rspool_resp (ST_UINT32 invoke_id, RSPOOL_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_REP_SEMPOOL,invoke_id, + M_CAST_MK_FUN (_ms_mk_rspool_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_rspool_resp */ +/* Construct a report semaphore status response. */ +/************************************************************************/ + +ST_VOID _ms_mk_rspool_resp (ASN1_ENC_CTXT *aCtx, RSPOOL_RESP_INFO *info) + { +TOKEN_ID *token_ptr; +ST_INT i; + + asn1r_strt_constr (aCtx); /* start the sequence constr */ + + asn1r_wr_bool (aCtx, info->more_follows); /* write more follows indicator */ + asn1r_fin_prim (aCtx, 1,CTX); + + asn1r_strt_constr (aCtx); /* start the ctx 0 constr */ + token_ptr = (TOKEN_ID *) (info + 1); + token_ptr += info->num_of_tokens - 1; /* point to last named token */ + for (i = 0; i < info->num_of_tokens; i++) + { + asn1r_wr_vstr (aCtx, token_ptr->named_token); /* write the named token */ + asn1r_fin_prim (aCtx, token_ptr->token_tag,CTX); + token_ptr--; + } + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish ctx 0 constructor */ + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_REP_SEMPOOL,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rs_rssta.c b/mmslib/mmsle/rs_rssta.c new file mode 100644 index 0000000..de70631 --- /dev/null +++ b/mmslib/mmsle/rs_rssta.c @@ -0,0 +1,138 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_rsstat.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of report semaphore */ +/* status. It decodes the report semaphore status request */ +/* (indication) and encodes the report semaphore status response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_psem.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static RSSTAT_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID rsstat_objname_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_rsstat_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_rsstat_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Report Semaphore Status Request"); + + + /* get storage for request information */ + req_info = (RSSTAT_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (RSSTAT_REQ_INFO)); + _ms_get_mms_objname (aCtx, &req_info->sem_name, rsstat_objname_done); + } + +/************************************************************************/ +/* rsstat_objname_done */ +/* Decoding report semaphore status request: semaphore name obtained */ +/************************************************************************/ + +static ST_VOID rsstat_objname_done (ASN1_DEC_CTXT *aCtx) + { + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_rsstat_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the report semaphore status response. */ +/************************************************************************/ + +ST_RET mp_rsstat_resp (MMSREQ_IND *indptr, RSSTAT_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_REP_SEMSTAT,indptr, + M_CAST_MK_FUN (_ms_mk_rsstat_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_rsstat_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the report semaphore status response. */ +/************************************************************************/ + +ST_RET mpl_rsstat_resp (ST_UINT32 invoke_id, RSSTAT_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_REP_SEMSTAT,invoke_id, + M_CAST_MK_FUN (_ms_mk_rsstat_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_rsstat_resp */ +/* Construct a report semaphore status response. */ +/************************************************************************/ + +ST_VOID _ms_mk_rsstat_resp (ASN1_ENC_CTXT *aCtx, RSSTAT_RESP_INFO *info) + { + asn1r_strt_constr (aCtx); /* start the sequence constr */ + + asn1r_wr_u16 (aCtx, info->num_of_hung); /* write number of hung tokens */ + asn1r_fin_prim (aCtx, 4,CTX); + + asn1r_wr_u16 (aCtx, info->num_of_owned); /* write number of owned tokens */ + asn1r_fin_prim (aCtx, 3,CTX); + + asn1r_wr_u16 (aCtx, info->num_of_tokens); /* write number of tokens */ + asn1r_fin_prim (aCtx, 2,CTX); + + asn1r_wr_i16 (aCtx, info->tclass); /* write the class */ + asn1r_fin_prim (aCtx, 1,CTX); + + asn1r_wr_bool (aCtx, info->mms_deletable); /* write the mms deletable */ + asn1r_fin_prim (aCtx, 0,CTX); + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_REP_SEMSTAT,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rs_start.c b/mmslib/mmsle/rs_start.c new file mode 100644 index 0000000..fb40feb --- /dev/null +++ b/mmslib/mmsle/rs_start.c @@ -0,0 +1,153 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_start.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the start */ +/* operation. It decodes the start request (indication) and */ +/* encodes the start response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* Use global decode info pointer, case via define here */ + +static START_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID start_get_arg (ASN1_DEC_CTXT *aCtx); +static ST_VOID start_get_piname (ASN1_DEC_CTXT *aCtx); +static ST_VOID extern_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_start_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_start_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Start Request"); + req_info = (START_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (START_REQ_INFO)); + ASN1R_TAG_ADD (aCtx, CTX, 0, start_get_piname); + } + +/************************************************************************/ +/* start_get_piname */ +/* start request is being decoded: get the program invocation name. */ +/************************************************************************/ + +static ST_VOID start_get_piname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("start_get_piname"); + + /* read program invocation name from message */ + if (asn1r_get_identifier (aCtx, req_info->piname)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 1, start_get_arg); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + +/* If MMS IS, Check for ENCODED string */ +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + _ms_chk_for_extern (aCtx, &req_info->start_arg_len, + &req_info->start_arg, + extern_done); + } + +/************************************************************************/ +/* start_get_arg */ +/* start request is being decoded: get the start argument. */ +/************************************************************************/ + +static ST_VOID start_get_arg (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("start_get_arg"); + + req_info->start_arg_pres = SD_TRUE; /* set start arg pres */ + + /* copy start argument back onto itself shifted by one ST_CHAR */ + req_info->start_arg = aCtx->asn1r_field_ptr - 1; + + req_info->start_arg_type = ARG_TYPE_SIMPLE; + if (asn1r_get_vstr (aCtx, (ST_CHAR *)req_info->start_arg)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* extern_done */ +/************************************************************************/ + +static ST_VOID extern_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("extern_done"); + + req_info->start_arg_pres = SD_TRUE; /* set start arg pres */ + req_info->start_arg_type = ARG_TYPE_ENCODED; + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_start_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the start response. */ +/************************************************************************/ + +ST_RET mp_start_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_START)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_start_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the start response. */ +/************************************************************************/ + +ST_RET mpl_start_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_START)); + } +#endif diff --git a/mmslib/mmsle/rs_stop.c b/mmslib/mmsle/rs_stop.c new file mode 100644 index 0000000..5c11e77 --- /dev/null +++ b/mmslib/mmsle/rs_stop.c @@ -0,0 +1,108 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_stop.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the stop */ +/* operation. It decodes the stop request (indication) and */ +/* encodes the stop response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pprg.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static STOP_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID stop_get_piname (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_stop_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_stop_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Stop Request"); + + /* get storage for request information */ + req_info = (STOP_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (STOP_REQ_INFO)); + ASN1R_TAG_ADD (aCtx, CTX, 0, stop_get_piname); + } + +/************************************************************************/ +/* stop_get_piname */ +/* stop request is being decoded: get the program invocation name. */ +/************************************************************************/ + +static ST_VOID stop_get_piname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("stop_get_piname"); + + /* read program invocation name from message */ + if (asn1r_get_identifier (aCtx, req_info->piname)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_stop_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the stop response. */ +/************************************************************************/ + +ST_RET mp_stop_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_STOP)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_stop_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the stop response. */ +/************************************************************************/ + +ST_RET mpl_stop_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_STOP)); + } +#endif diff --git a/mmslib/mmsle/rs_store.c b/mmslib/mmsle/rs_store.c new file mode 100644 index 0000000..a24e380 --- /dev/null +++ b/mmslib/mmsle/rs_store.c @@ -0,0 +1,200 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_storedom.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of store domain */ +/* content. It decodes the store domain content request */ +/* (indication) & encodes the store domain content response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 05 Remove "thisFileName" */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static STOREDOM_REQ_INFO *req_info; + +static ST_INT max_fnames; +static ST_UCHAR *ar_start; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +static ST_VOID storedom_fname_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID storedom_fname_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID storedom_get_dname (ASN1_DEC_CTXT *aCtx); +static ST_VOID storedom_third_pty_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID third_pty_cstr_done (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_store_domain_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_store_domain_req (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("Store Domain Content Request"); + +#if defined(FIXED_DECBUF) + max_fnames = m_sv_max_file_names; + req_size = mmsl_dec_info_size; +#else + max_fnames = (_mmsdec_msglen/2); /* get storage for request info */ + if (m_sv_max_file_names && (max_fnames > m_sv_max_file_names)) + max_fnames = m_sv_max_file_names; + req_size = sizeof (STOREDOM_REQ_INFO) + (max_fnames * sizeof (FILE_NAME)); +#endif + +/* get storage for request information */ + req_info = (STOREDOM_REQ_INFO *) _m_get_dec_buf (aCtx, req_size); + ASN1R_TAG_ADD (aCtx, CTX, 0,storedom_get_dname); + } + +/************************************************************************/ +/* storedom_get_dname */ +/* store domain content request is being decoded: domain name was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID storedom_get_dname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("storedom_get_dname"); + + if (asn1r_get_identifier (aCtx, req_info->dname)) /* read the domain name */ + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,storedom_fname_cstr); + } + +/************************************************************************/ +/* storedom_fname_cstr */ +/* store domain content request is being decoded: filename cstr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID storedom_fname_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("storedom_fname_cstr"); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = storedom_fname_cstr_done; + _ms_get_mms_fname (aCtx, (FILE_NAME *)(req_info + 1), max_fnames, + &req_info->num_of_fname); + } + +/************************************************************************/ +/* storedom_fname_cstr_done */ +/* store domain content request is being decoded: file name list */ +/* constructor done was encountered. */ +/************************************************************************/ + +static ST_VOID storedom_fname_cstr_done (ASN1_DEC_CTXT *aCtx) + { +ST_INT req_size; + + MLOG_CDEC0 ("storedom_fname_cstr_done"); + + req_size = sizeof (STOREDOM_REQ_INFO) + + (sizeof (FILE_NAME) * req_info->num_of_fname); + + /* give back unused storage */ + _mms_dec_info = (*m_realloc_os_fun) (_mms_dec_info,req_size); + req_info = (STOREDOM_REQ_INFO *) _mms_dec_info; + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 2, storedom_third_pty_cstr); + ar_start = aCtx->asn1r_field_ptr; /* save in case third party rcvd */ + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* storedom_third_pty_cstr */ +/* store domain content request is being decoded: third party */ +/* cstr was encountered. */ +/************************************************************************/ + +static ST_VOID storedom_third_pty_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("storedom_get_third_pty"); + + req_info->third_pty_pres = SD_TRUE; /* set third party */ + req_info->third_pty = ar_start; /* save_start */ + *ar_start = '\x30'; /* change tag */ + + if (aCtx->asn1r_elmnt_len) + asn1r_parse_cstr_contents (aCtx, third_pty_cstr_done); + else + aCtx->asn1r_c_done_fun[ aCtx->asn1r_msg_level ] = third_pty_cstr_done; + } + +/************************************************************************/ +/* third_pty_cstr_done */ +/* store domain content request is being decoded: third party cstr */ +/* was encountered and read */ +/************************************************************************/ + +static ST_VOID third_pty_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("third_pty_cstr_done"); + + req_info->third_pty_len = aCtx->asn1r_field_ptr - ar_start; + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_storedom_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the store domain content response. */ +/************************************************************************/ + +ST_RET mp_storedom_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_STORE_DOMAIN)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_storedom_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the store domain content response. */ +/************************************************************************/ + +ST_RET mpl_storedom_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_STORE_DOMAIN)); + } +#endif diff --git a/mmslib/mmsle/rs_takec.c b/mmslib/mmsle/rs_takec.c new file mode 100644 index 0000000..ddc8623 --- /dev/null +++ b/mmslib/mmsle/rs_takec.c @@ -0,0 +1,342 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_takectrl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of take semaphore */ +/* control. It decodes the take control request (indication) and */ +/* encodes the take control response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 08 Remove "thisFileName" */ +/* 08/28/03 EJV 07 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 03/23/99 MDE 04 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_psem.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static TAKECTRL_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID takectrl_get_priority (ASN1_DEC_CTXT *aCtx); +static ST_VOID takectrl_get_acc_delay (ASN1_DEC_CTXT *aCtx); +static ST_VOID takectrl_get_ctrl_timeout (ASN1_DEC_CTXT *aCtx); +static ST_VOID takectrl_get_abrt_timeout (ASN1_DEC_CTXT *aCtx); +static ST_VOID takectrl_get_rel_conn_lost (ASN1_DEC_CTXT *aCtx); +static ST_VOID takectrl_app_preempt_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID takectrl_get_named_token (ASN1_DEC_CTXT *aCtx); +static ST_VOID takectrl_sem_name_cstr_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID takectrl_objname_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID takectrl_sem_name_cstr (ASN1_DEC_CTXT *aCtx); +static ST_VOID app_preempt_cstr_done (ASN1_DEC_CTXT *aCtx); + +static ST_UCHAR *ar_start; + + +/************************************************************************/ +/************************************************************************/ +/* mms_takectrl_req */ +/* This function is called from mmsdec when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_takectrl_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Take Control Request"); + + req_info = (TAKECTRL_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (TAKECTRL_REQ_INFO)); + ASN1R_TAG_ADD (aCtx, CTX |CONSTR, 0, takectrl_sem_name_cstr); + } + +/************************************************************************/ +/* takectrl_sem_name_cstr */ +/* Decoding take control request: semaphore name constructor was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID takectrl_sem_name_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("takectrl_sem_name_cstr"); + + /* get storage for request information */ + req_info->priority = MMS_NORM_PRIORITY; + req_info->rel_conn_lost = SD_TRUE; + _ms_get_mms_objname (aCtx, &req_info->sem_name, takectrl_objname_done); + } + +/************************************************************************/ +/* takectrl_objname_done */ +/* Decoding take control request: Semaphore name has been obtained */ +/************************************************************************/ + +static ST_VOID takectrl_objname_done (ASN1_DEC_CTXT *aCtx) + { + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = takectrl_sem_name_cstr_done; + } + +/************************************************************************/ +/* takectrl_sem_name_cstr_done */ +/* Decoding take control request: semaphore name contructor done was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID takectrl_sem_name_cstr_done (ASN1_DEC_CTXT *aCtx) + { + + ASN1R_TAG_ADD (aCtx, CTX, 1, takectrl_get_named_token ); + ASN1R_TAG_ADD (aCtx, CTX, 2, takectrl_get_priority ); + ASN1R_TAG_ADD (aCtx, CTX, 3, takectrl_get_acc_delay ); + ASN1R_TAG_ADD (aCtx, CTX, 4, takectrl_get_ctrl_timeout ); + ASN1R_TAG_ADD (aCtx, CTX, 5, takectrl_get_abrt_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 6, takectrl_get_rel_conn_lost); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 7, takectrl_app_preempt_cstr ); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + ar_start = aCtx->asn1r_field_ptr; + } + +/************************************************************************/ +/* takectrl_get_named_token */ +/* Decoding take control request: named token name was encountered. */ +/************************************************************************/ + +static ST_VOID takectrl_get_named_token (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("takectrl_get_named_token"); + + req_info->named_token_pres = SD_TRUE; /* set named token present */ + + /* read named token from received message */ + if (asn1r_get_identifier (aCtx, req_info->named_token)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 2, takectrl_get_priority ); + ASN1R_TAG_ADD (aCtx, CTX, 3, takectrl_get_acc_delay ); + ASN1R_TAG_ADD (aCtx, CTX, 4, takectrl_get_ctrl_timeout ); + ASN1R_TAG_ADD (aCtx, CTX, 5, takectrl_get_abrt_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 6, takectrl_get_rel_conn_lost); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 7, takectrl_app_preempt_cstr ); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + ar_start = aCtx->asn1r_field_ptr; + } + +/************************************************************************/ +/* takectrl_get_priority */ +/* Take control request: decode the priority */ +/************************************************************************/ + +static ST_VOID takectrl_get_priority (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("takectrl_get_priorit"); + +/* read the priority from the received message */ + if (asn1r_get_u8 (aCtx, &(req_info->priority))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 3, takectrl_get_acc_delay ); + ASN1R_TAG_ADD (aCtx, CTX, 4, takectrl_get_ctrl_timeout ); + ASN1R_TAG_ADD (aCtx, CTX, 5, takectrl_get_abrt_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 6, takectrl_get_rel_conn_lost); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 7, takectrl_app_preempt_cstr ); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + ar_start = aCtx->asn1r_field_ptr; + } + +/************************************************************************/ +/* takectrl_get_acc_delay */ +/* Take control request: decode acceptable delay */ +/************************************************************************/ + +static ST_VOID takectrl_get_acc_delay (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("takectrl_get_acc_dela"); + + req_info->acc_delay_pres = SD_TRUE; /* set acceptable delay present */ + + /* read acceptable delay from message */ + if (asn1r_get_u32 (aCtx, &(req_info->acc_delay))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 4, takectrl_get_ctrl_timeout ); + ASN1R_TAG_ADD (aCtx, CTX, 5, takectrl_get_abrt_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 6, takectrl_get_rel_conn_lost); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 7, takectrl_app_preempt_cstr ); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + ar_start = aCtx->asn1r_field_ptr; + } + +/************************************************************************/ +/* takectrl_get_ctrl_timeout */ +/* Take control request: decode the relinquish timeout */ +/************************************************************************/ + +static ST_VOID takectrl_get_ctrl_timeout (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("takectrl_get_ctrl_timeou"); + + req_info->ctrl_timeout_pres = SD_TRUE; /* set relinquish timeout pres */ + + /* read relinquish timeout from message */ + if (asn1r_get_u32 (aCtx, &(req_info->ctrl_timeout))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 5, takectrl_get_abrt_timeout); + ASN1R_TAG_ADD (aCtx, CTX, 6, takectrl_get_rel_conn_lost); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 7, takectrl_app_preempt_cstr ); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + ar_start = aCtx->asn1r_field_ptr; + } + +/************************************************************************/ +/* takectrl_get_abrt_timeout */ +/* Take control request: decode the relinquish if connection lost */ +/************************************************************************/ + +static ST_VOID takectrl_get_abrt_timeout (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("takectrl_get_abrt_timeout"); + /* read access key from message */ + req_info->abrt_on_timeout_pres = SD_TRUE; + if (asn1r_get_bool (aCtx, &(req_info->abrt_on_timeout))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX, 6, takectrl_get_rel_conn_lost); + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 7, takectrl_app_preempt_cstr ); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + ar_start = aCtx->asn1r_field_ptr; + } + +/************************************************************************/ +/* takectrl_get_rel_conn_lost */ +/* Take control request: decode the relinquish if connection lost */ +/************************************************************************/ + +static ST_VOID takectrl_get_rel_conn_lost (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("takectrl_get_rel_conn_lost"); + /* read access key from message */ + if (asn1r_get_bool (aCtx, &(req_info->rel_conn_lost))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + ASN1R_TAG_ADD (aCtx, CTX | CONSTR, 7, takectrl_app_preempt_cstr ); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + ar_start = aCtx->asn1r_field_ptr; + } + +/************************************************************************/ +/* takectrl_app_preempt_cstr */ +/* Decoding take control request: application to preempt constr was */ +/* encountered. */ +/************************************************************************/ + +static ST_VOID takectrl_app_preempt_cstr (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("takectrl_app_preempt_cstr"); + + req_info->app_preempt_pres = SD_TRUE; /* set app preempt present */ + req_info->app_preempt = ar_start; /* save_start */ + *ar_start = '\x30'; /* change tag */ + + if (aCtx->asn1r_elmnt_len) + asn1r_parse_cstr_contents (aCtx, app_preempt_cstr_done); + else + aCtx->asn1r_c_done_fun[ aCtx->asn1r_msg_level ] = app_preempt_cstr_done; + } + +/************************************************************************/ +/* app_preempt_cstr_done */ +/* Decoding take control request: application preempt was encountered. */ +/************************************************************************/ + +static ST_VOID app_preempt_cstr_done (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("app_preempt_cstr_done"); + + req_info->app_len = aCtx->asn1r_field_ptr - ar_start; + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_takectrl_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the take control response. */ +/************************************************************************/ + +ST_RET mp_takectrl_resp (MMSREQ_IND *indptr, TAKECTRL_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_TAKE_CONTROL,indptr, + M_CAST_MK_FUN (_ms_mk_takectrl_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_takectrl_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the take control response. */ +/************************************************************************/ + +ST_RET mpl_takectrl_resp (ST_UINT32 invoke_id, + TAKECTRL_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_TAKE_CONTROL,invoke_id, + M_CAST_MK_FUN (_ms_mk_takectrl_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_takectrl_resp */ +/* Construct a take control response. */ +/************************************************************************/ + +ST_VOID _ms_mk_takectrl_resp (ASN1_ENC_CTXT *aCtx, TAKECTRL_RESP_INFO *info) + { + if (info->resp_tag == SD_FALSE) + { /* response is NULL */ + asn1r_fin_prim (aCtx, 0,CTX); + } + else if (info->resp_tag == SD_TRUE) + { /* response is a named token */ + asn1r_wr_vstr (aCtx, info->named_token); /* write the named token */ + asn1r_fin_prim (aCtx, 1,CTX); + } + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_TAKE_CONTROL,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmsle/rs_termd.c b/mmslib/mmsle/rs_termd.c new file mode 100644 index 0000000..0d3af60 --- /dev/null +++ b/mmslib/mmsle/rs_termd.c @@ -0,0 +1,156 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_termdown.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of the terminate */ +/* download sequence. It decodes the terminate download sequence */ +/* request (indication) & encodes the terminate download sequence */ +/* response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 08/28/03 EJV 06 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* Del _mms_get_service_err proto(see mmsdefs.h)*/ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 02 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static TERMDOWN_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + +static ST_VOID termdown_get_dname (ASN1_DEC_CTXT *aCtx); +static ST_VOID termdown_get_discarded (ASN1_DEC_CTXT *aCtx); +static ST_VOID termdown_get_discarded_err (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/************************************************************************/ +/* mms_term_download_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_term_download_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Terminate Download Sequence Request"); +/* get storage for the request information */ +/* make big enough to add service error info if req'd */ + + req_info = (TERMDOWN_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (TERMDOWN_REQ_INFO) + sizeof (ERR_INFO)); + req_info->discarded = SD_FALSE; /* set the default value */ + /* read domain name from the received message */ + ASN1R_TAG_ADD (aCtx, CTX,0,termdown_get_dname); + } + +/************************************************************************/ +/* termdown_get_dname */ +/* Terminate download sequence request: decode domain name */ +/************************************************************************/ + +static ST_VOID termdown_get_dname (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("termdown_get_dname"); + + if (asn1r_get_identifier (aCtx, req_info->dname)) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + +#ifndef MMS_LITE + if (mms_chan_info[_mmsdechan].version) /* IS */ +#else + if (mmsl_version) /* IS */ +#endif + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 1, termdown_get_discarded_err); + else /* DIS */ + ASN1R_TAG_ADD (aCtx, CTX, 1, termdown_get_discarded); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* termdown_get_discarded */ +/* Terminate download sequence request: decode discarded flag */ +/************************************************************************/ + +static ST_VOID termdown_get_discarded (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("termdown_get_discarded"); + + /* read discarded flag from the received message */ + if (asn1r_get_bool (aCtx, &(req_info->discarded))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + +/************************************************************************/ +/* termdown_get_discarded_err */ +/* Terminate download sequence request: decode discarded 'error' */ +/************************************************************************/ + +static ST_VOID termdown_get_discarded_err (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("termdown_get_discarded_err"); + +/* set up pointer (already allocated) */ + req_info->err = (ERR_INFO *) (req_info+1); + req_info->discarded = SD_TRUE; + +/* set up to decode error contents, etc.. */ + _mms_get_service_err (aCtx, req_info->err); + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_termdown_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the terminate download sequence response. */ +/************************************************************************/ + +ST_RET mp_termdown_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_TERM_DOWNLOAD)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_termdown_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the terminate download sequence response. */ +/************************************************************************/ + +ST_RET mpl_termdown_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_TERM_DOWNLOAD)); + } +#endif diff --git a/mmslib/mmsle/rs_termu.c b/mmslib/mmsle/rs_termu.c new file mode 100644 index 0000000..2dcd5f7 --- /dev/null +++ b/mmslib/mmsle/rs_termu.c @@ -0,0 +1,95 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_termupl.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of terminate upload */ +/* sequence. It decodes the terminate upload sequence request */ +/* (indication) & encodes the terminate upload sequence response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 06 Remove "thisFileName" */ +/* 08/28/03 EJV 05 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 04 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 03 Added SD_CONST modifiers */ +/* 03/23/99 MDE 02 Changes to decode buffer allocation scheme */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static TERMUPL_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_term_upload_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_term_upload_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Terminate Upload Sequence Request"); + /* get storage for request information */ + req_info = (TERMUPL_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (TERMUPL_REQ_INFO)); + + /* read upload state machine id from received message */ + if (asn1r_get_i32 (aCtx, &(req_info->ulsmid))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_termupl_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the terminate upload sequence response. */ +/************************************************************************/ + +ST_RET mp_termupl_resp (MMSREQ_IND *indptr) + { + return (_mms_send_null_resp (indptr,MMSOP_TERM_UPLOAD)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_termupl_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the terminate upload sequence response. */ +/************************************************************************/ + +ST_RET mpl_termupl_resp (ST_UINT32 invoke_id) + { + return (_mms_fin_null_resp (invoke_id,MMSOP_TERM_UPLOAD)); + } +#endif diff --git a/mmslib/mmsle/rs_uploa.c b/mmslib/mmsle/rs_uploa.c new file mode 100644 index 0000000..3537f39 --- /dev/null +++ b/mmslib/mmsle/rs_uploa.c @@ -0,0 +1,128 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986 - 2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : rs_uploa.c */ +/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains the responder portion of upload segment. */ +/* It decodes the upload segment request (indication) and encodes */ +/* the upload segment response. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 08/28/03 EJV 06 Corr spelling for 'receive'. */ +/* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 07/03/97 MDE 01 Op-specific info buffer handling changes */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +/* 06/09/97 MDE 01 Changed op specific buffer allocation */ +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "asn1defs.h" + +/************************************************************************/ +/* variables global to the DECODE portion : */ + +static UPLOAD_REQ_INFO *req_info; + +/************************************************************************/ +/* variables global to the ENCODE portion : NONE */ + + +/************************************************************************/ +/************************************************************************/ +/* mms_upload_req */ +/* This function is called from MMSDEC when the opcode for this */ +/* operation is decoded. Setup state machine function pointers, etc. */ +/************************************************************************/ + +ST_VOID mms_upload_req (ASN1_DEC_CTXT *aCtx) + { + MLOG_CDEC0 ("Upload Segment Request"); + +/* get storage for request information */ + req_info = (UPLOAD_REQ_INFO *) _m_get_dec_buf (aCtx, sizeof (UPLOAD_REQ_INFO)); + + /* read upload state machine id from received message */ + if (asn1r_get_i32 (aCtx, &(req_info->ulsmid))) + asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); + + _ms_set_cs_check (aCtx); /* check for Companion Standard info */ + } + + +#ifndef MMS_LITE +/************************************************************************/ +/************************************************************************/ +/* mp_upload_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE and send the upload segment response. */ +/************************************************************************/ + +ST_RET mp_upload_resp (MMSREQ_IND *indptr, UPLOAD_RESP_INFO *info_ptr) + { + return (_mms_resp_send (MMSOP_UP_LOAD,indptr, + M_CAST_MK_FUN (_ms_mk_upload_resp), + (ST_CHAR *)info_ptr)); + } + +#else +/************************************************************************/ +/************************************************************************/ +/* mpl_upload_resp */ +/* This function is called from either the application or the virtual */ +/* machine to ENCODE the upload segment response. */ +/************************************************************************/ + +ST_RET mpl_upload_resp (ST_UINT32 invoke_id, UPLOAD_RESP_INFO *info_ptr) + { + return (_mms_resp_fin (MMSOP_UP_LOAD,invoke_id, + M_CAST_MK_FUN (_ms_mk_upload_resp), + (ST_CHAR *)info_ptr)); + } +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _ms_mk_upload_resp */ +/* Construct an upload segment response. */ +/************************************************************************/ + +ST_VOID _ms_mk_upload_resp (ASN1_ENC_CTXT *aCtx, UPLOAD_RESP_INFO *info) + { + if (!info->more_follows) + { /* NOT the default (SD_TRUE) */ + asn1r_wr_bool (aCtx, info->more_follows); /* write more follows flag */ + asn1r_fin_prim (aCtx, 1, CTX); + } + + if (info->load_data_type != LOAD_DATA_CODED) + { + asn1r_wr_octstr (aCtx, info->load_data,info->load_data_len); + asn1r_fin_prim (aCtx, 0,CTX); /* context tag 0 */ + } + else /* CODED data, write as complete ASN.1 EXTERNAL */ + asn1r_wr_delmnt (aCtx, info->load_data,info->load_data_len); + +/* write the context specific explicit tag for this opcode. */ + asn1r_fin_constr (aCtx, MMSOP_UP_LOAD,CTX,DEF); /* tag = opcode, ctx constr */ + } diff --git a/mmslib/mmslib.cpp b/mmslib/mmslib.cpp new file mode 100644 index 0000000..504ee9f --- /dev/null +++ b/mmslib/mmslib.cpp @@ -0,0 +1,13 @@ +#include "mmslib.h" + + +Mmslib::Mmslib() +{ +} +void Mmslib::mmslib_test() +{ + qDebug()<<"mmslib_test_123"; +} + + + diff --git a/mmslib/mmslib.h b/mmslib/mmslib.h new file mode 100644 index 0000000..29cfc56 --- /dev/null +++ b/mmslib/mmslib.h @@ -0,0 +1,13 @@ +#ifndef MMSLIB_H +#define MMSLIB_H +#include + +class Mmslib +{ + +public: + Mmslib(); + void mmslib_test(); +}; + +#endif // MMSLIB_H diff --git a/mmslib/mmslib.pro b/mmslib/mmslib.pro new file mode 100644 index 0000000..f26845a --- /dev/null +++ b/mmslib/mmslib.pro @@ -0,0 +1,500 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2023-06-26T14:33:36 +# +#------------------------------------------------- + +QT -= gui + +TARGET = mmslib +TEMPLATE = lib +CONFIG += staticlib +DEFINES += DEBUG_SISCO MOSI LEAN_T MVL_UCA MMS_LITE TP0_ENABLED +DEFINES += STDTIME_ANSI +DEFINES += S_MT_SUPPORT +DEFINES += S_MT_SUPPORT S_MT_SUPPORT_RXB +#DEFINES += WIN32_LEAN_AND_MEAN + +INCLUDEPATH += ./inc +INCLUDEPATH += ./inc/mmsop_en + + include(fe_common.pri) + +SOURCES += \ + mmslib.cpp \ + asn1/asn1r.c \ + asn1/are_vstr.c \ + asn1/are_utc.c \ + asn1/are_time.c \ + asn1/are_ostr.c \ + asn1/are_objd.c \ + asn1/are_int.c \ + asn1/are_flt.c \ + asn1/are_delm.c \ + asn1/are_btod.c \ + asn1/are_bstr.c \ + asn1/are_bool.c \ + asn1/ard_vstr.c \ + asn1/ard_utc.c \ + asn1/ard_time.c \ + asn1/ard_strn.c \ + asn1/ard_ostr.c \ + asn1/ard_objd.c \ + asn1/ard_int.c \ + asn1/ard_idnt.c \ + asn1/ard_flt.c \ + asn1/ard_delm.c \ + asn1/ard_btod.c \ + asn1/ard_bstr.c \ + asn1/ard_bool.c \ + mem/mem_chks.c \ + mmsl/rs_write.c \ + mmsl/rs_ustat.c \ + mmsl/rs_trige.c \ + mmsl/rs_stat.c \ + mmsl/rs_repee.c \ + mmsl/rs_repec.c \ + mmsl/rs_repea.c \ + mmsl/rs_read.c \ + mmsl/rs_namel.c \ + mmsl/rs_init.c \ + mmsl/rs_info.c \ + mmsl/rs_ident.c \ + mmsl/rs_getvl.c \ + mmsl/rs_getva.c \ + mmsl/rs_getty.c \ + mmsl/rs_getpi.c \ + mmsl/rs_getee.c \ + mmsl/rs_getec.c \ + mmsl/rs_getea.c \ + mmsl/rs_getdo.c \ + mmsl/rs_getcl.c \ + mmsl/rs_evnot.c \ + mmsl/rs_defee.c \ + mmsl/rs_concl.c \ + mmsl/rs_cancl.c \ + mmsl/rs_ackev.c \ + mmsl/rq_write.c \ + mmsl/rq_ustat.c \ + mmsl/rq_trige.c \ + mmsl/rq_stat.c \ + mmsl/rq_repee.c \ + mmsl/rq_repec.c \ + mmsl/rq_repea.c \ + mmsl/rq_read.c \ + mmsl/rq_namel.c \ + mmsl/rq_init.c \ + mmsl/rq_info.c \ + mmsl/rq_ident.c \ + mmsl/rq_getvl.c \ + mmsl/rq_getva.c \ + mmsl/rq_getty.c \ + mmsl/rq_getpi.c \ + mmsl/rq_getee.c \ + mmsl/rq_getec.c \ + mmsl/rq_getea.c \ + mmsl/rq_getdo.c \ + mmsl/rq_getcl.c \ + mmsl/rq_evnot.c \ + mmsl/rq_defee.c \ + mmsl/rq_concl.c \ + mmsl/rq_cancl.c \ + mmsl/rq_ackev.c \ + mmsl/msdataas.c \ + mmsl/ms_tdef4.c \ + mmsl/ms_tdef2.c \ + mmsl/ms_tdef.c \ + mmsl/ms_size.c \ + mmsl/ms_ext.c \ + mmsl/mmsstat.c \ + mmsl/mmslvar.c \ + mmsl/mmsl_fin.c \ + mmsl/mmsinit.c \ + mmsl/mmsdtext.c \ + mmsl/mmsdec.c \ + mmsl/mmsdatat.c \ + mmsl/mmsdata.c \ + mmsl/mmsconcl.c \ + mmsl/mmscancl.c \ + mmsl/mms_tdef.c \ + mmsl/mms_rtaa.c \ + mmsl/mms_rej.c \ + mmsl/mms_err4.c \ + mmsl/mms_err3.c \ + mmsl/mms_err2.c \ + mmsl/mms_err.c \ + mmsl/mms_ced7.c \ + mmsl/mms_ced6.c \ + mmsl/mms_ced5.c \ + mmsl/mms_ced4.c \ + mmsl/mms_ced3.c \ + mmsl/mms_ced.c \ + mmsl/mms_aref.c \ + mmsl/mms_alta.c \ + mmsl/mms_adl.c \ + mmsle/rs_uploa.c \ + mmsle/rs_termu.c \ + mmsle/rs_termd.c \ + mmsle/rs_takec.c \ + mmsle/rs_store.c \ + mmsle/rs_stop.c \ + mmsle/rs_start.c \ + mmsle/rs_rssta.c \ + mmsle/rs_rspoo.c \ + mmsle/rs_rsent.c \ + mmsle/rs_resum.c \ + mmsle/rs_reset.c \ + mmsle/rs_renam.c \ + mmsle/rs_relct.c \ + mmsle/rs_rdupl.c \ + mmsle/rs_rddwn.c \ + mmsle/rs_outpu.c \ + mmsle/rs_obtfi.c \ + mmsle/rs_loadd.c \ + mmsle/rs_kill.c \ + mmsle/rs_jwrit.c \ + mmsle/rs_jstat.c \ + mmsle/rs_jread.c \ + mmsle/rs_jinit.c \ + mmsle/rs_jdele.c \ + mmsle/rs_jcrea.c \ + mmsle/rs_input.c \ + mmsle/rs_initu.c \ + mmsle/rs_initd.c \ + mmsle/rs_getsc.c \ + mmsle/rs_getas.c \ + mmsle/rs_getae.c \ + mmsle/rs_frena.c \ + mmsle/rs_fread.c \ + mmsle/rs_fopen.c \ + mmsle/rs_fdir.c \ + mmsle/rs_fdele.c \ + mmsle/rs_fclos.c \ + mmsle/rs_downl.c \ + mmsle/rs_delvl.c \ + mmsle/rs_delva.c \ + mmsle/rs_delty.c \ + mmsle/rs_delse.c \ + mmsle/rs_delpi.c \ + mmsle/rs_delee.c \ + mmsle/rs_delec.c \ + mmsle/rs_delea.c \ + mmsle/rs_deldo.c \ + mmsle/rs_defvl.c \ + mmsle/rs_defva.c \ + mmsle/rs_defty.c \ + mmsle/rs_defse.c \ + mmsle/rs_defsc.c \ + mmsle/rs_defec.c \ + mmsle/rs_defea.c \ + mmsle/rs_crepi.c \ + mmsle/rs_altee.c \ + mmsle/rs_altec.c \ + mmsle/rq_uploa.c \ + mmsle/rq_termu.c \ + mmsle/rq_termd.c \ + mmsle/rq_takec.c \ + mmsle/rq_store.c \ + mmsle/rq_stop.c \ + mmsle/rq_start.c \ + mmsle/rq_rssta.c \ + mmsle/rq_rspoo.c \ + mmsle/rq_rsent.c \ + mmsle/rq_resum.c \ + mmsle/rq_reset.c \ + mmsle/rq_renam.c \ + mmsle/rq_relct.c \ + mmsle/rq_rdupl.c \ + mmsle/rq_rddwn.c \ + mmsle/rq_outpu.c \ + mmsle/rq_obtfi.c \ + mmsle/rq_loadd.c \ + mmsle/rq_kill.c \ + mmsle/rq_jwrit.c \ + mmsle/rq_jstat.c \ + mmsle/rq_jread.c \ + mmsle/rq_jinit.c \ + mmsle/rq_jdele.c \ + mmsle/rq_jcrea.c \ + mmsle/rq_input.c \ + mmsle/rq_initu.c \ + mmsle/rq_initd.c \ + mmsle/rq_getsc.c \ + mmsle/rq_getas.c \ + mmsle/rq_getae.c \ + mmsle/rq_frena.c \ + mmsle/rq_fread.c \ + mmsle/rq_fopen.c \ + mmsle/rq_fdir.c \ + mmsle/rq_fdele.c \ + mmsle/rq_fclos.c \ + mmsle/rq_downl.c \ + mmsle/rq_delvl.c \ + mmsle/rq_delva.c \ + mmsle/rq_delty.c \ + mmsle/rq_delse.c \ + mmsle/rq_delpi.c \ + mmsle/rq_delee.c \ + mmsle/rq_delec.c \ + mmsle/rq_delea.c \ + mmsle/rq_deldo.c \ + mmsle/rq_defvl.c \ + mmsle/rq_defva.c \ + mmsle/rq_defty.c \ + mmsle/rq_defse.c \ + mmsle/rq_defsc.c \ + mmsle/rq_defec.c \ + mmsle/rq_defea.c \ + mmsle/rq_crepi.c \ + mmsle/rq_altee.c \ + mmsle/rq_altec.c \ + mmsle/mms_ced2.c \ + mmsle/mms_ced1.c \ + mvlu/sclproc.c \ + mvlu/s_write.c \ + mvlu/s_status.c \ + mvlu/s_read.c \ + mvlu/s_obtfi.c \ + mvlu/s_jstat.c \ + mvlu/s_jread.c \ + mvlu/s_jinit.c \ + mvlu/s_info.c \ + mvlu/s_ident.c \ + mvlu/s_getvla.c \ + mvlu/s_getvaa.c \ + mvlu/s_getnam.c \ + mvlu/s_getdom.c \ + mvlu/s_getcl.c \ + mvlu/s_fren.c \ + mvlu/s_fread.c \ + mvlu/s_fopen.c \ + mvlu/s_fdir.c \ + mvlu/s_fdel.c \ + mvlu/s_fclose.c \ + mvlu/s_delvl.c \ + mvlu/s_defvl.c \ + mvlu/s_concl.c \ + mvlu/s_cancel.c \ + mvlu/mvluleaf.c \ + mvlu/mvlu_sbo.c \ + mvlu/mvlu_rt.c \ + mvlu/mvlu_rpt.c \ + mvlu/mvl61850_rpt.c \ + mvlu/mvl61850_ctl.c \ + mvlu/mvl61850.c \ + mvlu/mvl_var.c \ + mvlu/mvl_uca.c \ + mvlu/mvl_type.c \ + mvlu/mvl_typ2.c \ + mvlu/mvl_serv.c \ + mvlu/mvl_send.c \ + mvlu/mvl_objb.c \ + mvlu/mvl_obj.c \ + mvlu/mvl_ijou.c \ + mvlu/mvl_dtyp.c \ + mvlu/mvl_buf.c \ + mvlu/c_write.c \ + mvlu/c_status.c \ + mvlu/c_read.c \ + mvlu/c_obtfi.c \ + mvlu/c_jstat.c \ + mvlu/c_jread.c \ + mvlu/c_jinit.c \ + mvlu/c_info.c \ + mvlu/c_ident.c \ + mvlu/c_getvla.c \ + mvlu/c_getvar.c \ + mvlu/c_getnam.c \ + mvlu/c_getdom.c \ + mvlu/c_fren.c \ + mvlu/c_fread.c \ + mvlu/c_fopen.c \ + mvlu/c_fget.c \ + mvlu/c_fdir.c \ + mvlu/c_fdel.c \ + mvlu/c_fclose.c \ + mvlu/c_delvl.c \ + mvlu/c_defvl.c \ + mvlu/c_concl.c \ + ositcps/tpx_dec.c \ + ositcps/tp4port.c \ + ositcps/tp4_enc.c \ + ositcps/tp0main.c \ + ositcps/tp0callg.c \ + ositcps/tp0calld.c \ + ositcps/tp0_socks.c \ + ositcps/tp0_dec.c \ + ositcps/osicfgx.c \ + ositcps/lean_var.c \ + ositcps/lean_cfg.c \ + ositcps/cospmain.c \ + ositcps/cosp_enc.c \ + ositcps/cosp_dec.c \ + ositcps/coppdcpr.c \ + ositcps/coppdcp.c \ + ositcps/coppdaru.c \ + ositcps/copp_enc.c \ + ositcps/copp_dec.c \ + ositcps/checksum.c \ + ositcps/acse2var.c \ + ositcps/acse2enc.c \ + ositcps/acse2dib.c \ + ositcps/acse2dec.c \ + slog/slogmem.c \ + slog/slogipcs.c \ + slog/sloghex.c \ + slog/slogfil.c \ + slog/slog.c \ + slog/qmem.c \ + ssec0/ssecusr0.c \ + util/time_str.c \ + util/sx_enc.c \ + util/sx_dec.c \ + util/sx_data.c \ + util/sx_axs4d.c \ + util/str_util.c \ + util/stime.c \ + util/stdtime_w32.c \ + util/stdtime_quadlib.c \ + util/stdtime_mms_utctime.c \ + util/stdtime_mms_btime.c \ + util/stdtime.c \ + util/sclstore.c \ + util/sclparse.c \ + util/scl_log.c \ + util/glbsem_unix.c \ + util/glbsem.c \ + util/gensock2.c \ + util/genlists.c \ + util/cfg_util.c + +HEADERS += mmslib.h \ + inc/tp4api.h \ + inc/tp4_log.h \ + inc/tp4_encd.h \ + inc/tp4.h \ + inc/tp0_sock.h \ + inc/time_str.h \ + inc/sysincs.h \ + inc/sx_log.h \ + inc/sx_defs.h \ + inc/sx_arb.h \ + inc/STR_UTIL.H \ + inc/stime.h \ + inc/stdtime_w32.h \ + inc/stdtime_tzrules.h \ + inc/stdtime_timezone_csv.h \ + inc/stdtime_stdint.h \ + inc/stdtime_quadlib.h \ + inc/stdtime_mms_utctime.h \ + inc/stdtime_mms_btime.h \ + inc/stdtime_enum_func.h \ + inc/stdtime_enum_err.h \ + inc/stdtime_endian.h \ + inc/stdtime_config.h \ + inc/stdtime.h \ + inc/ssleLog.h \ + inc/ssec_int.h \ + inc/ssec.h \ + inc/sock_log.h \ + inc/smpval.h \ + inc/smp_usr.h \ + inc/smp_log.h \ + inc/smp.h \ + inc/Smem.h \ + inc/slog.h \ + inc/scrndefs.h \ + inc/scl.h \ + inc/rs_defs.h \ + inc/rs_a.h \ + inc/qmem.h \ + inc/osillc.h \ + inc/ntddosi.h \ + inc/mvl_uca.h \ + inc/mvl_log.h \ + inc/MVL_DEFS.H \ + inc/mvl_acse.h \ + inc/mmslusec.h \ + inc/mmslog.h \ + inc/mmsldefs.h \ + inc/mmsintr2.h \ + inc/mmsefun.h \ + inc/mmsdefs.h \ + inc/mms_vvar.h \ + inc/mms_pvmd.h \ + inc/mms_pvar.h \ + inc/mms_psem.h \ + inc/mms_pprg.h \ + inc/mms_pocs.h \ + inc/mms_pjou.h \ + inc/mms_pfil.h \ + inc/mms_pevn.h \ + inc/mms_perr.h \ + inc/mms_pdom.h \ + inc/mms_pcon.h \ + inc/mms_mp.h \ + inc/mms_log.h \ + inc/mms_err.h \ + inc/mms_dfun.h \ + inc/mms_def2.h \ + inc/mloguser.h \ + inc/memlog.h \ + inc/mem_chk.h \ + inc/llcioctl.h \ + inc/llcio.h \ + inc/lean_a.h \ + inc/gvaldefs.h \ + inc/gse_mgmt.h \ + inc/Goose.h \ + inc/glbtypes.h \ + inc/glbsem.h \ + inc/glbopt.h \ + inc/glberror.h \ + inc/gensock2.h \ + inc/gen_list.h \ + inc/fkeydefs.h \ + inc/ExceptionReport.h \ + inc/ethsub.h \ + inc/ethertyp.h \ + inc/dibmatch.h \ + inc/cosp_usr.h \ + inc/cosp_log.h \ + inc/cosp.h \ + inc/copp_usr.h \ + inc/copp_log.h \ + inc/copp.h \ + inc/conpack.h \ + inc/clnpport.h \ + inc/clnp_usr.h \ + inc/clnp_tnt.h \ + inc/clnp_sta.h \ + inc/clnp_sne.h \ + inc/clnp_log.h \ + inc/clnp_llc.h \ + inc/clnp.h \ + inc/checksum.h \ + inc/cfglog.h \ + inc/cfg_util.h \ + inc/asn1r.h \ + inc/asn1log.h \ + inc/asn1defs.h \ + inc/arg.h \ + inc/adlc_usr.h \ + inc/adlc_sts.h \ + inc/adlc_sm.h \ + inc/adlc_log.h \ + inc/adlc_dsm.h \ + inc/adlc.h \ + inc/acseauth.h \ + inc/acse2usr.h \ + inc/acse2log.h \ + inc/acse2.h \ + inc/mmsop_en/mmsop_en.h +unix:!symbian { + maemo5 { + target.path = /opt/usr/lib + } else { + target.path = /usr/lib + } + INSTALLS += target +} diff --git a/mmslib/mmslib.pro.user b/mmslib/mmslib.pro.user new file mode 100644 index 0000000..2db0e0a --- /dev/null +++ b/mmslib/mmslib.pro.user @@ -0,0 +1,194 @@ + + + + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + true + 1 + true + 0 + true + 0 + 8 + true + 0 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.2.0 MSVC2012 32bit + Desktop Qt 5.2.0 MSVC2012 32bit + qt.520.win32_msvc2012.essentials_kit + 0 + 0 + 0 + + + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + false + + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + 构建 + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + æ¸…ç† + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 1 + + + 0 + 部署 + + ProjectExplorer.BuildSteps.Deploy + + 1 + 在本地部署 + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + + + false + %{buildDir} + 自定义执行档 + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + true + false + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.EnvironmentId + {8291b97e-670a-4766-bc01-067e25c191cc} + + + ProjectExplorer.Project.Updater.FileVersion + 15 + + diff --git a/mmslib/mmslib.pro.user.18 b/mmslib/mmslib.pro.user.18 new file mode 100644 index 0000000..a41dadc --- /dev/null +++ b/mmslib/mmslib.pro.user.18 @@ -0,0 +1,258 @@ + + + + + + EnvironmentId + {5822199d-261c-4d16-b10c-265f684da8a8} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + GBK + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.5.0 MSVC2012 32bit + Desktop Qt 5.5.0 MSVC2012 32bit + qt.55.win32_msvc2012_kit + 1 + 0 + 0 + + D:/pqs_com_client/mmslib + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + 构建 + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + æ¸…ç† + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + D:/pqs_com_client/mmslib + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + 构建 + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + æ¸…ç† + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 2 + + + 0 + 部署 + + ProjectExplorer.BuildSteps.Deploy + + 1 + 在本地部署 + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + + + false + %{buildDir} + 自定义执行档 + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/mmslib/mmslib.pro.user.2.7pre1 b/mmslib/mmslib.pro.user.2.7pre1 new file mode 100644 index 0000000..b3fe979 --- /dev/null +++ b/mmslib/mmslib.pro.user.2.7pre1 @@ -0,0 +1,243 @@ + + + + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + GBK + false + 4 + false + true + 1 + true + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.1.0 MSVC2012 OpenGL 64bit + Desktop Qt 5.1.0 MSVC2012 OpenGL 64bit + qt.510.win64_msvc2012_64_opengl.essentials_kit + 1 + 0 + 0 + + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + 构建 + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + æ¸…ç† + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + D:/pqs_com_client/mmslib/%{JS: Util.asciify("build-mmslib-Desktop_Qt_5_1_0_MSVC2012_OpenGL_64bit-Debug")} + false + + + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + 构建 + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + æ¸…ç† + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + D:/pqs_com_client/mmslib/%{JS: Util.asciify("build-mmslib-Desktop_Qt_5_1_0_MSVC2012_OpenGL_64bit-Release")} + false + + 2 + + + 0 + 部署 + + ProjectExplorer.BuildSteps.Deploy + + 1 + 在本地部署 + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + true + + false + false + false + false + true + 0.01 + 10 + true + 25 + + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 2 + + false + + %{buildDir} + 自定义执行档 + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.EnvironmentId + {5822199d-261c-4d16-b10c-265f684da8a8} + + + ProjectExplorer.Project.Updater.FileVersion + 12 + + diff --git a/mmslib/mmslib.pro.user.3.2-pre1 b/mmslib/mmslib.pro.user.3.2-pre1 new file mode 100644 index 0000000..2a62f1f --- /dev/null +++ b/mmslib/mmslib.pro.user.3.2-pre1 @@ -0,0 +1,247 @@ + + + + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + GBK + false + 4 + false + true + 1 + true + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.2.0 MSVC2012 32bit + Desktop Qt 5.2.0 MSVC2012 32bit + qt.520.win32_msvc2012.essentials_kit + 1 + 0 + 0 + + D:/pqs_com_client/mmslib + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + 构建 + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + æ¸…ç† + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + D:/pqs_com_client/mmslib + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + 构建 + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + æ¸…ç† + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 2 + + + 0 + 部署 + + ProjectExplorer.BuildSteps.Deploy + + 1 + 在本地部署 + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + + + false + %{buildDir} + 自定义执行档 + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + true + false + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.EnvironmentId + {d8c8bb25-44fd-4cdb-9bb3-e12dea660c73} + + + ProjectExplorer.Project.Updater.FileVersion + 15 + + diff --git a/mmslib/mmslib.pro.user.5822199 b/mmslib/mmslib.pro.user.5822199 new file mode 100644 index 0000000..f18f0f8 --- /dev/null +++ b/mmslib/mmslib.pro.user.5822199 @@ -0,0 +1,243 @@ + + + + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + GBK + false + 4 + false + true + 1 + true + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.1.0 MSVC2012 OpenGL 64bit + Desktop Qt 5.1.0 MSVC2012 OpenGL 64bit + qt.510.win64_msvc2012_64_opengl.essentials_kit + 1 + 0 + 0 + + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + 构建 + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + æ¸…ç† + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + D:/pqs_com_client/mmslib/%{JS: Util.asciify("build-mmslib-Desktop_Qt_5_1_0_MSVC2012_OpenGL_64bit-Debug")} + false + + + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + 构建 + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + æ¸…ç† + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + D:/pqs_com_client/mmslib/%{JS: Util.asciify("build-mmslib-Desktop_Qt_5_1_0_MSVC2012_OpenGL_64bit-Release")} + false + + 2 + + + 0 + 部署 + + ProjectExplorer.BuildSteps.Deploy + + 1 + 在本地部署 + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + true + + false + false + false + false + true + 0.01 + 10 + true + 25 + + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 2 + + false + + %{buildDir} + 自定义执行档 + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.EnvironmentId + {5822199d-261c-4d16-b10c-265f684da8a8} + + + ProjectExplorer.Project.Updater.FileVersion + 12 + + diff --git a/mmslib/mmslib.pro.user.5822199.2.7pre1 b/mmslib/mmslib.pro.user.5822199.2.7pre1 new file mode 100644 index 0000000..b3fe979 --- /dev/null +++ b/mmslib/mmslib.pro.user.5822199.2.7pre1 @@ -0,0 +1,243 @@ + + + + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + GBK + false + 4 + false + true + 1 + true + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.1.0 MSVC2012 OpenGL 64bit + Desktop Qt 5.1.0 MSVC2012 OpenGL 64bit + qt.510.win64_msvc2012_64_opengl.essentials_kit + 1 + 0 + 0 + + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + 构建 + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + æ¸…ç† + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + D:/pqs_com_client/mmslib/%{JS: Util.asciify("build-mmslib-Desktop_Qt_5_1_0_MSVC2012_OpenGL_64bit-Debug")} + false + + + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + 构建 + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + æ¸…ç† + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + D:/pqs_com_client/mmslib/%{JS: Util.asciify("build-mmslib-Desktop_Qt_5_1_0_MSVC2012_OpenGL_64bit-Release")} + false + + 2 + + + 0 + 部署 + + ProjectExplorer.BuildSteps.Deploy + + 1 + 在本地部署 + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + true + + false + false + false + false + true + 0.01 + 10 + true + 25 + + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 2 + + false + + %{buildDir} + 自定义执行档 + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.EnvironmentId + {5822199d-261c-4d16-b10c-265f684da8a8} + + + ProjectExplorer.Project.Updater.FileVersion + 12 + + diff --git a/mmslib/mmslib.pro.user.d8c8bb2 b/mmslib/mmslib.pro.user.d8c8bb2 new file mode 100644 index 0000000..36d4d25 --- /dev/null +++ b/mmslib/mmslib.pro.user.d8c8bb2 @@ -0,0 +1,243 @@ + + + + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + GBK + false + 4 + false + true + 1 + true + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.1.0 MSVC2012 OpenGL 64bit + Desktop Qt 5.1.0 MSVC2012 OpenGL 64bit + qt.510.win64_msvc2012_64_opengl.essentials_kit + 1 + 0 + 0 + + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + 构建 + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + æ¸…ç† + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + D:/pqs_com_client/mmslib/%{JS: Util.asciify("build-mmslib-Desktop_Qt_5_1_0_MSVC2012_OpenGL_64bit-Debug")} + false + + + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + 构建 + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + æ¸…ç† + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + D:/pqs_com_client/mmslib/%{JS: Util.asciify("build-mmslib-Desktop_Qt_5_1_0_MSVC2012_OpenGL_64bit-Release")} + false + + 2 + + + 0 + 部署 + + ProjectExplorer.BuildSteps.Deploy + + 1 + 在本地部署 + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + true + + false + false + false + false + true + 0.01 + 10 + true + 25 + + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + + 2 + + false + + %{buildDir} + 自定义执行档 + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.EnvironmentId + {d8c8bb25-44fd-4cdb-9bb3-e12dea660c73} + + + ProjectExplorer.Project.Updater.FileVersion + 12 + + diff --git a/mmslib/mvlu/c_concl.c b/mmslib/mvlu/c_concl.c new file mode 100644 index 0000000..1e0292b --- /dev/null +++ b/mmslib/mvlu/c_concl.c @@ -0,0 +1,160 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : c_concl.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_conclude */ +/* _mvl_process_concl_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/30/06 GLB 16 Integrated porting changes for VMS */ +/* 10/29/02 JRB 15 _mvla_send_concl: on err, set done & result in*/ +/* req_pend. Helps if user doesn't chk return. */ +/* 04/25/02 MDE 14 Added MLOG */ +/* 11/01/01 JRB 13 mvl_wait_req_done now returns ST_RET. */ +/* 03/07/01 JRB 12 Del LOCK on sync functs: caused deadlocks. */ +/* 04/14/00 JRB 11 Lint cleanup. */ +/* 03/08/00 JRB 10 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Don't care numpend_req. Conclude is special. */ +/* 01/21/00 MDE 09 Now use MEM_SMEM for dynamic memory */ +/* 11/22/99 NAV 08 Add maxpend_req support */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 12/08/98 MDE 06 Cleanup on request control handling */ +/* 11/17/98 MDE 05 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 04 Renamed internal functions (prefix '_') */ +/* 11/16/98 MDE 03 Added mvl_concl, mvla_concl, call release */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mvl_defs.h" +#include "mvl_log.h" +#include "mloguser.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/************************************************************************/ + + +/************************************************************************/ +/* mvl_conclude */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_conclude (MVL_NET_INFO *net_info) + { +MVL_REQ_PEND *req_out; + + MVL_LOG_ERR0 ("Warning: Using obsolete function 'mvl_conclude', please use 'mvl_concl'"); + return (mvl_concl (net_info, &req_out)); + } + +#endif + +/************************************************************************/ +/* mvl_concl */ +/************************************************************************/ + +ST_RET mvl_concl (MVL_NET_INFO *net_info, MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_concl (net_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + + +/************************************************************************/ +/* mvla_concl */ +/************************************************************************/ + + +ST_RET mvla_concl (MVL_NET_INFO *net_info, MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req; + + *req_out = req = _mvl_get_req_ctrl (net_info, MMSOP_CONCLUDE); + if (!req) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_concl (net_info, req); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_concl */ +/************************************************************************/ + +ST_RET _mvla_send_concl (MVL_NET_INFO *net_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; +ST_UCHAR _conclude_pdu[2]; + +/* "\x8B\x00" == "\213\000", for old compilers ... */ + _conclude_pdu[0]= (ST_UCHAR) 0x8b; + _conclude_pdu[1]= (ST_UCHAR) 0x00; + +/* We can log here if so desired */ + if ((mms_debug_sel & MMS_LOG_REQ) && ml_log_req_info_fun != NULL) + (*ml_log_req_info_fun) (0, MMSOP_CONCLUDE, NULL); + + rc = _mvl_send_msg (_conclude_pdu, 2, net_info); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Conclude : _mvl_send_msg failed, rc = %x", rc); + req_pend->done = SD_TRUE; /* Helps if user doesn't chk return */ + req_pend->result = rc; + } + /* invoke_id not sent on conclude, but set to -1 just to match up resp.*/ + req_pend->invoke_id = (ST_UINT32) -1; + + return (rc); + } + +/************************************************************************/ +/* _mvl_process_concl_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_concl_conf (MVL_REQ_PEND *req_pend) + { + _mvl_release (req_pend); + } + + diff --git a/mmslib/mvlu/c_defvl.c b/mmslib/mvlu/c_defvl.c new file mode 100644 index 0000000..1c5493c --- /dev/null +++ b/mmslib/mvlu/c_defvl.c @@ -0,0 +1,134 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_defvl.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_defvlist */ +/* mvla_defvlist */ +/* _mvl_process_defvlist_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 14 Enhanced filtered logging */ +/* 11/01/01 JRB 13 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 12 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 11 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 10 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 09 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 08 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 07 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/20/99 NAV 06 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 11/17/98 MDE 04 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/27/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_defvlist */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_defvlist ( + MVL_NET_INFO *net_info, + DEFVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_defvlist (net_info, req_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_defvlist */ +/************************************************************************/ + +ST_RET mvla_defvlist ( + MVL_NET_INFO *net_info, + DEFVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_DEF_VLIST); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_defvlist (net_info, req_info, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + + } + +/************************************************************************/ +/* _mvl_send_defvlist */ +/************************************************************************/ + +ST_RET _mvla_send_defvlist (MVL_NET_INFO *net_info, + DEFVLIST_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; + + /* Build a defvlist request */ + rc = mpl_defvlist (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_defvlist_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_defvlist_conf (MVL_REQ_PEND *req_pend) + { + /* Nothing to do. Common code takes care of setting req_pend->result. */ + } + diff --git a/mmslib/mvlu/c_delvl.c b/mmslib/mvlu/c_delvl.c new file mode 100644 index 0000000..77b85d9 --- /dev/null +++ b/mmslib/mvlu/c_delvl.c @@ -0,0 +1,134 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_delvl.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_delvlist */ +/* mvla_delvlist */ +/* _mvl_process_delvlist_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 14 Enhanced filtered logging */ +/* 11/01/01 JRB 13 mvl_wait_req_done now returns ST_RET. */ +/* 11/01/01 JRB 12 Del LOCK on sync functs: caused deadlocks. */ +/* 09/21/01 JRB 11 Alloc global bufs only once at startup. */ +/* 03/08/00 JRB 10 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 09 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 08 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 07 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/20/99 NAV 06 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 11/17/98 MDE 04 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/27/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_delvlist */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_delvlist ( + MVL_NET_INFO *net_info, + DELVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_delvlist (net_info, req_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_delvlist */ +/************************************************************************/ + +ST_RET mvla_delvlist ( + MVL_NET_INFO *net_info, + DELVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_DEL_VLIST); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_delvlist (net_info, req_info, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_delvlist */ +/************************************************************************/ + +ST_RET _mvla_send_delvlist (MVL_NET_INFO *net_info, + DELVLIST_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; + + /* Build a delvlist request */ + rc = mpl_delvlist (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_delvlist_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_delvlist_conf (MVL_REQ_PEND *req_pend) + { + req_pend->u.delvlist.resp_info = + (DELVLIST_RESP_INFO *) req_pend->event->u.mms.dec_rslt.data_ptr; + } + diff --git a/mmslib/mvlu/c_fclose.c b/mmslib/mvlu/c_fclose.c new file mode 100644 index 0000000..ccee852 --- /dev/null +++ b/mmslib/mvlu/c_fclose.c @@ -0,0 +1,133 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_fclose.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_fclose */ +/* mvla_fclose */ +/* _mvl_process_fclose_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 14 Enhanced filtered logging */ +/* 11/01/01 JRB 13 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 12 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 11 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 10 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 09 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 08 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 07 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/26/99 NAV 06 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 11/17/98 MDE 04 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/27/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_fclose */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_fclose ( + MVL_NET_INFO *net_info, + FCLOSE_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_fclose (net_info, req_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_fclose */ +/************************************************************************/ + +ST_RET mvla_fclose ( + MVL_NET_INFO *net_info, + FCLOSE_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_FILE_CLOSE); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_fclose (net_info, req_info, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_fclose */ +/************************************************************************/ + +ST_RET _mvla_send_fclose (MVL_NET_INFO *net_info, + FCLOSE_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; + + /* Build a fclose request */ + rc = mpl_fclose (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_fclose_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_fclose_conf (MVL_REQ_PEND *req_pend) + { + /* Nothing to do. Common code takes care of setting req_pend->result. */ + } + diff --git a/mmslib/mvlu/c_fdel.c b/mmslib/mvlu/c_fdel.c new file mode 100644 index 0000000..42f4cdd --- /dev/null +++ b/mmslib/mvlu/c_fdel.c @@ -0,0 +1,150 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_fdel.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_fdelete */ +/* mvla_fdelete */ +/* _mvl_process_fdelete_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 14 Enhanced filtered logging */ +/* 11/01/01 JRB 13 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 12 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 11 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 10 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 09 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 08 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 07 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/26/99 NAV 06 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 11/17/98 MDE 04 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/27/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_fdelete */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_fdelete ( + MVL_NET_INFO *net_info, + ST_CHAR *filename, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_fdelete (net_info, filename, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_fdelete */ +/************************************************************************/ + +ST_RET mvla_fdelete ( + MVL_NET_INFO *net_info, + ST_CHAR *filename, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_FILE_DELETE); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_fdelete (net_info, filename, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_fdelete */ +/************************************************************************/ + /* Allocate FDELETE_REQ_INFO with "one" FILE_NAME entry after it. */ + /* If need more than one FILE_NAME, must use "mpl_fdelete". */ +#define FDELETE_REQ_INFO_SIZE (sizeof (FDELETE_REQ_INFO) + (1 * sizeof (FILE_NAME))) + +ST_RET _mvla_send_fdelete (MVL_NET_INFO *net_info, + ST_CHAR *filename, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; +FDELETE_REQ_INFO *req_info; +FILE_NAME *fname_idx; +ST_CHAR fdelete_req_info[FDELETE_REQ_INFO_SIZE]; + + /* Allocate FDELETE_REQ_INFO with "one" FILE_NAME entry after it. */ + /* If need more than one FILE_NAME, must use "mpl_fdelete". */ + req_info = (FDELETE_REQ_INFO *) fdelete_req_info; + + req_info->num_of_fname = 1; + + /* Point to the FILE_NAME structure and fill it in. */ + fname_idx = (FILE_NAME *)(req_info + 1); + fname_idx->fn_len = strlen (filename); + fname_idx->fname = filename; + + /* Build a fdelete request */ + rc = mpl_fdelete (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_fdelete_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_fdelete_conf (MVL_REQ_PEND *req_pend) + { + /* Nothing to do. Common code takes care of setting req_pend->result. */ + } + diff --git a/mmslib/mvlu/c_fdir.c b/mmslib/mvlu/c_fdir.c new file mode 100644 index 0000000..7ef62b8 --- /dev/null +++ b/mmslib/mvlu/c_fdir.c @@ -0,0 +1,231 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_fdir.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_fdir */ +/* mvla_fdir */ +/* _mvl_process_fdir_conf */ +/* */ +/* WARNING: these functions were designed to be as easy as possible to */ +/* use for MOST applications. They will work for any system where */ +/* filenames can be represented as a single NULL terminated string. */ +/* They do NOT support filenames with multiple parts or which contain */ +/* If these features are needed, then the more complicated mpl_fdir */ +/* must be used directly. */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 14 Enhanced filtered logging */ +/* 11/01/01 JRB 13 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 12 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 11 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 10 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 09 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 08 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 07 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/26/99 NAV 06 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 11/17/98 MDE 04 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/27/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_fdir */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_fdir ( + MVL_NET_INFO *net_info, + ST_CHAR *filename, + ST_CHAR *ca_filename, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_fdir (net_info, filename, ca_filename, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_fdir */ +/************************************************************************/ + +ST_RET mvla_fdir ( + MVL_NET_INFO *net_info, + ST_CHAR *filename, + ST_CHAR *ca_filename, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_FILE_DIR); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + req_pend->u.fdir.resp_info = NULL; /* Confirm funct must allocate */ + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_fdir (net_info, filename, ca_filename, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_fdir */ +/************************************************************************/ +/* Allocate FDIR_REQ_INFO with "one" FILE_NAME entry after it. */ +/* If need more than one FILE_NAME, must use "mpl_fdir". */ +#define FDIR_REQ_INFO_SIZE (sizeof (FDIR_REQ_INFO) + (2 * sizeof (FILE_NAME))) + +ST_RET _mvla_send_fdir (MVL_NET_INFO *net_info, + ST_CHAR *filename, + ST_CHAR *ca_filename, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; +FDIR_REQ_INFO *req_info; +FILE_NAME *fname_idx; +ST_CHAR fdir_req_info[FDIR_REQ_INFO_SIZE]; + + req_info = (FDIR_REQ_INFO *) fdir_req_info; + if (filename) + { + req_info->filespec_pres = SD_TRUE; + req_info->num_of_fs_fname = 1; + } + else + { + req_info->filespec_pres = SD_FALSE; + req_info->num_of_fs_fname = 0; + } + + if (ca_filename) + { + req_info->cont_after_pres = SD_TRUE; + req_info->num_of_ca_fname = 1; + } + else + { + req_info->cont_after_pres = SD_FALSE; + req_info->num_of_ca_fname = 0; + } + + /* Point to first FILE_NAME structure. */ + fname_idx = (FILE_NAME *)(req_info + 1); + + if (filename) + { + fname_idx->fn_len = strlen (filename); + fname_idx->fname = filename; + fname_idx++; /* point to next */ + } + + if (ca_filename) + { + fname_idx->fn_len = strlen (ca_filename); + fname_idx->fname = ca_filename; + fname_idx++; /* point to next */ + } + + /* Build a fdir request */ + rc = mpl_fdir (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_fdir_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_fdir_conf (MVL_REQ_PEND *req_pend) + { +FDIR_DIR_ENT *dir_ent; +MVL_DIR_ENT *mvl_dir_ent; +MVL_FDIR_RESP_INFO *mvl_resp_info; +FDIR_RESP_INFO *resp_info; +ST_INT j; +ST_INT info_size; + + resp_info = (FDIR_RESP_INFO *) req_pend->event->u.mms.dec_rslt.data_ptr; + + /* Allocate and fill in "req_pend->u.fdir.resp_info". */ +/* CRITICAL: mvl_free_req_ctrl () must free it. */ + info_size = sizeof (MVL_FDIR_RESP_INFO) + + resp_info->num_dir_ent * sizeof(MVL_DIR_ENT); + req_pend->u.fdir.resp_info = + (MVL_FDIR_RESP_INFO *) M_MALLOC (MSMEM_GEN, info_size); + + mvl_resp_info = req_pend->u.fdir.resp_info; /* Local ptr to it. */ + mvl_resp_info->num_dir_ent = resp_info->num_dir_ent; + mvl_resp_info->more_follows = resp_info->more_follows; + mvl_resp_info->dir_ent = (MVL_DIR_ENT *) (mvl_resp_info + 1); + if (resp_info->num_dir_ent) + { + dir_ent = (FDIR_DIR_ENT *)(resp_info + 1); /* point to first entry */ + mvl_dir_ent = mvl_resp_info->dir_ent; /* point to first entry */ + for (j = 0; j < resp_info->num_dir_ent; j++, mvl_dir_ent++) + { + mvl_dir_ent->fsize = dir_ent->fsize; + mvl_dir_ent->mtimpres = dir_ent->mtimpres; + mvl_dir_ent->mtime = dir_ent->mtime; + + if (_mvl_concat_filename (mvl_dir_ent->filename, dir_ent->num_of_fname, + (FILE_NAME *)(dir_ent + 1), sizeof (mvl_dir_ent->filename))) + { + MVL_LOG_ERR0 ("Error: FileDirectory.Conf: can't process filename"); + req_pend->result = SD_FAILURE; + return; + } + + /* Point to next dir entry. */ + dir_ent = (FDIR_DIR_ENT *) ((ST_CHAR *)dir_ent + sizeof (FDIR_DIR_ENT) + + dir_ent->num_of_fname * sizeof (FILE_NAME)); + } + } + } diff --git a/mmslib/mvlu/c_fget.c b/mmslib/mvlu/c_fget.c new file mode 100644 index 0000000..5b6ba17 --- /dev/null +++ b/mmslib/mvlu/c_fget.c @@ -0,0 +1,460 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2000 - 2000, All Rights Reserved */ +/* */ +/* MODULE NAME : c_fget.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvla_fget */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/03/08 JRB 09 Add static on "u_f*" functions. */ +/* Chk fget_cnf_ptr before using. */ +/* 11/12/07 MDE 08 Use _mvl_getpath for temp file path */ +/* 01/30/06 GLB 07 Integrated porting changes for VMS */ +/* 03/01/04 MDE 06 Free request for fget (file open) error */ +/* 06/17/03 MDE 05 Now use _mvl_tmpnam */ +/* 02/17/03 JRB 04 Del unused includes. */ +/* 07/18/02 JRB 03 Del unused var. */ +/* 03/25/02 MDE 02 Moved error/reject elements outside union */ +/* 06/22/00 GLB 01 Created to do an asynchronous File Get. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +static MVL_REQ_PEND *send_file_open (MVL_NET_INFO *NetInfo, ST_CHAR *src); +static MVL_REQ_PEND *send_file_read (MVL_NET_INFO *NetInfo, + MVL_FGET_REQ_INFO *u_file_info); +static MVL_REQ_PEND *send_file_close (MVL_NET_INFO *NetInfo, + MVL_FGET_REQ_INFO *u_file_info); + +static ST_VOID u_fopen_done (MVL_REQ_PEND *req); +static ST_VOID u_fread_done (MVL_REQ_PEND *req); +static ST_VOID u_fclose_done (MVL_REQ_PEND *req); + +/************************************************************************/ +/* mvla_fget */ +/* Perform an asynchronous file copy */ +/************************************************************************/ +ST_RET mvla_fget ( + MVL_NET_INFO *net_info, + ST_CHAR *srcfilename, + ST_CHAR *destfilename, + MVL_FGET_REQ_INFO *fget_req_info) + { +MVL_REQ_PEND *req_out; +ST_CHAR tmpfile_path[MVL_MAX_TMPFILE_PATH]; + + /* save destination name for rename */ + if (strlen (destfilename) <= MAX_FILE_NAME) + { + strcpy (fget_req_info->destfilename, destfilename); + } + else + { + MVL_LOG_NERR0 ("ERROR: mvla_fget: destination filename save failed "); + return (SD_FAILURE); + } + + /* save source name for returning copy status */ + if (strlen (srcfilename) <= MAX_FILE_NAME) + { + strcpy (fget_req_info->srcfilename, srcfilename); + } + else + { + MVL_LOG_NERR0 ("ERROR: mvla_fget: source filename save failed "); + return (SD_FAILURE); + } + + /* Create a temporary file name to copy into. This prevents partially */ + /* transferred files from hanging around and being accidently used */ + /* Open the created temporary file. Send a file open request for the */ + /* source file specified. */ + + _mvl_getpath (destfilename, tmpfile_path); + + if (_mvl_tmpnam (fget_req_info->tempfilename, tmpfile_path) != SD_SUCCESS || + (fget_req_info->fp = fopen(fget_req_info->tempfilename, "wb")) == NULL || + (req_out = send_file_open (net_info, srcfilename)) == NULL) + { + if (fget_req_info->fp ) + { + MVL_LOG_NERR1 ("ERROR: mvla_fget: fopen (%s) failed ", + fget_req_info->srcfilename); + + if (fclose (fget_req_info->fp)!=0) /* close temporary file */ + { + MVL_LOG_ERR1 ("ERROR: mvla_fget: fclose of temp file (%s) failed ", + fget_req_info->tempfilename); + } + + if (remove (fget_req_info->tempfilename)!=0) /* get rid of temporary file */ + { + MVL_LOG_ERR1 ("ERROR: mvla_fget: remove of temp file (%s) failed ", + fget_req_info->tempfilename); + } + } + else + { /* no temp file created */ + MVL_LOG_NERR0 ("ERROR: mvla_fget: temp file creation failed "); + } + return(SD_FAILURE); + } + else + { + req_out->v = fget_req_info; + return (SD_SUCCESS); + } + + } /* mvla_fget */ + +/************************************************************************/ +/* send_file_open */ +/* Send a file open request to open source file on the other side */ +/************************************************************************/ + +MVL_REQ_PEND *send_file_open (MVL_NET_INFO *NetInfo, ST_CHAR *src) + { +MVL_REQ_PEND *req= NULL; + + if ((mvla_fopen(NetInfo, src, 0, &req)) == SD_SUCCESS) + { + req->u_req_done = u_fopen_done; + } + return (req); + } /* send_file_open */ + +/************************************************************************/ +/* u_fopen_done */ +/* It was indicated that a file open request was made */ +/* Confirm file open response that was received as a result of a request*/ +/************************************************************************/ + +static ST_VOID u_fopen_done( MVL_REQ_PEND *req) +{ + ST_RET ret; + MVL_REQ_PEND *freadreq= NULL; + MVL_FGET_REQ_INFO *fget_req_info; + FOPEN_RESP_INFO *resp_info; + ERR_INFO *err_ptr; + REJECT_RESP_INFO *rej_ptr; + + fget_req_info = (MVL_FGET_REQ_INFO *) req->v; + ret = req->result; + if (ret == SD_SUCCESS) /* open of source file succeeded */ + { + resp_info = req->u.fopen.resp_info; + fget_req_info ->frsmid = resp_info->frsmid; + fget_req_info ->fsize = resp_info->ent.fsize; + if ((freadreq = send_file_read (req->net_info, fget_req_info)) != NULL) + { + freadreq->v = fget_req_info; + } + else + { + MVL_LOG_NERR1 ("ERROR: u_fopen_done: send_file_read (%s) failed ", + fget_req_info->srcfilename); + ret = SD_FAILURE; + + /* stop copy file process and report error to user */ + fget_req_info->fget_done = SD_TRUE; + fget_req_info->fget_error = ret; + if (fget_req_info->fget_cnf_ptr) + (*fget_req_info->fget_cnf_ptr)(fget_req_info); + + } + } /* file open succeeded */ + else + { /* file open failed */ + MVL_LOG_NERR1 ("ERROR: u_fopen_done: mvla_fopen (%s) failed ", + fget_req_info->srcfilename); + + if (req->result==MVL_ERR_CNF_REJ_ERR) + { + rej_ptr = (REJECT_RESP_INFO *) req->event->u.mms.dec_rslt.data_ptr; + MVLU_LOG_FLOW3 ("MMS REJECT \n detected_here = %d \n invoke_known = %d invoke = %d", + req->reject_info->detected_here, + req->reject_info->invoke_known, + req->reject_info->invoke); + + MVLU_LOG_CFLOW3 ("pdu_type = %d \n rej_class = %d \n rej_code = %d", + req->reject_info->pdu_type, + req->reject_info->rej_class, + req->reject_info->rej_code); + } + + if (req->result==MVL_ERR_CNF_ERR_OK) + { + err_ptr = (ERR_INFO *) req->event->u.mms.dec_rslt.data_ptr; + MVLU_LOG_FLOW2 ("MMS ERROR RESPONSE \n class = %d, code = %d", + req->error_info->eclass, + req->error_info->code); + } + + if (fclose (fget_req_info->fp)!=0) /* close temporary file */ + { + MVL_LOG_ERR1 ("ERROR: u_fopen_done: fclose of temp file (%s) failed ", + fget_req_info->tempfilename); + } + + if (remove (fget_req_info->tempfilename)!=0) /* get rid of temporary file */ + MVL_LOG_ERR1 ("ERROR: u_fopen_done: remove of temp file (%s) failed ", + fget_req_info->tempfilename); + + /* stop copy file process and report error to user */ + fget_req_info->fget_done = SD_TRUE; + fget_req_info->fget_error = ret; + if (fget_req_info->fget_cnf_ptr) + (*fget_req_info->fget_cnf_ptr)(fget_req_info); + } /* file open failed */ + + mvl_free_req_ctrl (req); + } /* u_fopen_done */ + +/************************************************************************/ +/* send_file_read */ +/* Send a file read request to copy a block of the source file data */ +/************************************************************************/ + +MVL_REQ_PEND *send_file_read (MVL_NET_INFO *NetInfo, + MVL_FGET_REQ_INFO *fget_req_info) + { + MVL_REQ_PEND *req= NULL; + FREAD_REQ_INFO fread_req; + + fread_req.frsmid = fget_req_info->frsmid; + if ((mvla_fread (NetInfo, &fread_req, &req)) == SD_SUCCESS) + { + req->u_req_done = u_fread_done; + } + + return (req); + } /* send_file_read */ + + +/************************************************************************/ +/* u_fread_done */ +/* Confirm the file read response sent to indicate a read request */ +/************************************************************************/ + +static ST_VOID u_fread_done( MVL_REQ_PEND *req) + { + ST_RET ret; + MVL_REQ_PEND *freadreq= NULL; + MVL_REQ_PEND *fclosereq= NULL; + MVL_FGET_REQ_INFO *fget_req_info; + FREAD_RESP_INFO *resp_info; + + fget_req_info = (MVL_FGET_REQ_INFO *) req->v; + + ret = req->result; + if (ret == SD_SUCCESS) /* read succeeded */ + { + resp_info = req->u.fread.resp_info; + + if ( fwrite (resp_info->filedata, sizeof(ST_CHAR), resp_info->fd_len, fget_req_info->fp) + == (unsigned) resp_info->fd_len ) + { + if ( resp_info->more_follows == SD_TRUE) + { + if ((freadreq = send_file_read (req->net_info, fget_req_info)) != NULL) + { + freadreq->v = fget_req_info; /* if more file data request to read another block */ + } + else + { /* read failed */ + MVL_LOG_NERR1 ("ERROR: u_fread_done: send_file_read (%s) failed ", + fget_req_info->srcfilename); + ret = SD_FAILURE; + + /* stop copy file process and report error to user */ + fget_req_info->fget_done = SD_TRUE; + fget_req_info->fget_error = ret; + if (fget_req_info->fget_cnf_ptr) + (*fget_req_info->fget_cnf_ptr)(fget_req_info); + + } + } /* more file data to be copied */ + else + { /* no more file data to be copied */ + if ((fclosereq = send_file_close (req->net_info, fget_req_info)) != NULL) + { + fclosereq->v = fget_req_info; /* no more file data so send a file close request */ + } + else + { + MVL_LOG_NERR1 ("ERROR: u_fread_done: send_file_close (%s) failed ", + fget_req_info->srcfilename); + ret = SD_FAILURE; + + /* stop copy file process and report error to user */ + fget_req_info->fget_done = SD_TRUE; + fget_req_info->fget_error = ret; + if (fget_req_info->fget_cnf_ptr) + (*fget_req_info->fget_cnf_ptr)(fget_req_info); + + } + } + } /* writing data to temp file succeeded */ + else + { /* write failed */ + MVL_LOG_NERR0 ("ERROR: u_fread_done: fwrite failed "); + ret = SD_FAILURE; + + /* stop copy file process and report error to user */ + fget_req_info->fget_done = SD_TRUE; + fget_req_info->fget_error = ret; + if (fget_req_info->fget_cnf_ptr) + (*fget_req_info->fget_cnf_ptr)(fget_req_info); + + } /* write failed */ + } /* read of data in source file succeeded */ + else + { /* read failed so close and remove temp file */ + MVL_LOG_NERR1 ("ERROR: u_fread_done: mvla_fread (%s) failed ", + fget_req_info->srcfilename); + + if (fclose (fget_req_info->fp)!=0) /* close temporary file */ + { + MVL_LOG_ERR1 ("ERROR: mvla_fget: fclose of temp file (%s) failed ", + fget_req_info->tempfilename); + } + + if (remove (fget_req_info->tempfilename)!=0) /* get rid of temporary file */ + { + MVL_LOG_ERR1 ("ERROR: mvla_fget: remove of temp file (%s) failed ", + fget_req_info->tempfilename); + } + + /* stop copy file process and report error to user */ + fget_req_info->fget_done = SD_TRUE; + fget_req_info->fget_error = ret; + if (fget_req_info->fget_cnf_ptr) + (*fget_req_info->fget_cnf_ptr)(fget_req_info); + + } /* read failed */ + + mvl_free_req_ctrl (req); + } /* u_fread_done */ + +/************************************************************************/ +/* send_file_close */ +/* No more data to read from the source file so send a request to close */ +/* the source file */ +/************************************************************************/ + +MVL_REQ_PEND *send_file_close (MVL_NET_INFO *NetInfo, + MVL_FGET_REQ_INFO *fget_req_info) + { + MVL_REQ_PEND *req= NULL; + FCLOSE_REQ_INFO fclose_req; + + fclose_req.frsmid = fget_req_info->frsmid; + + if ((mvla_fclose (NetInfo, &fclose_req, &req)) == SD_SUCCESS) + { + req->u_req_done = u_fclose_done; + } + + return (req); + } /* send_file_close */ + +/************************************************************************/ +/* u_fclose_done */ +/* Confirm source file closed response */ +/************************************************************************/ + +static ST_VOID u_fclose_done( MVL_REQ_PEND *req) + { + ST_RET ret; + MVL_FGET_REQ_INFO *fget_req_info; + + fget_req_info = (MVL_FGET_REQ_INFO *) req->v; + + ret = req->result; + if (ret == SD_SUCCESS) /* close of source file succeeded */ + { + if (fclose (fget_req_info->fp)!=0) /* close the temporary file */ + { + MVL_LOG_ERR1 ("ERROR: mvla_fget: fclose of temp file (%s) failed ", + fget_req_info->tempfilename); + } + + /* Remove dest file so temp file can be renamed to it. */ + /* NOTE: remove may fail if file did not already exist. */ + remove (fget_req_info->destfilename); + + /* rename the temporary file to become the requested destination file */ + /* use the ANSI rename function if available on your OS */ + /* otherwise use other function appropriate for your system */ + if (rename (fget_req_info->tempfilename, fget_req_info->destfilename)) + { + MVL_LOG_ERR1 ("ERROR: u_fclose_done: rename (%s) failed ", + fget_req_info->tempfilename); + if (remove (fget_req_info->tempfilename)!=0) /* cleanup useless file */ + { + MVL_LOG_ERR1 ("ERROR: u_fclose_done: remove (%s) failed ", + fget_req_info->tempfilename); + } + ret = SD_FAILURE; + + } + else + { + } + + } /* close succeeded */ + else + { /* close failed */ + + MVL_LOG_NERR1 ("ERROR: u_fclose_done: mvla_fclose (%s) failed ", + fget_req_info->srcfilename); + + if (fclose (fget_req_info->fp)!=0) /* close temporary file */ + { + MVL_LOG_ERR1 ("ERROR: mvla_fget: fclose of temp file (%s) failed ", + fget_req_info->tempfilename); + } + + if (remove (fget_req_info->tempfilename)!=0) /* get rid of temporary file */ + { + MVL_LOG_ERR1 ("ERROR: mvla_fget: remove of temp file (%s) failed ", + fget_req_info->tempfilename); + } + } + + /* copy file process complete so report done and status to user */ + fget_req_info->fget_done = SD_TRUE; + fget_req_info->fget_error = ret; + if (fget_req_info->fget_cnf_ptr) + (*fget_req_info->fget_cnf_ptr)(fget_req_info); + + mvl_free_req_ctrl (req); + + } /* end u_fclose_done */ + + diff --git a/mmslib/mvlu/c_fopen.c b/mmslib/mvlu/c_fopen.c new file mode 100644 index 0000000..49b9b4a --- /dev/null +++ b/mmslib/mvlu/c_fopen.c @@ -0,0 +1,158 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_fopen.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_fopen */ +/* mvla_fopen */ +/* _mvl_process_fopen_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 14 Enhanced filtered logging */ +/* 11/01/01 JRB 13 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 12 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 11 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 10 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* Add missing S_LOCK_... */ +/* 01/21/00 MDE 09 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 08 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 07 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/26/99 NAV 06 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 11/17/98 MDE 04 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/27/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_fopen */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_fopen ( + MVL_NET_INFO *net_info, + ST_CHAR *filename, + ST_UINT32 init_pos, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + rc = mvla_fopen (net_info, filename, init_pos, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + else + printf("mvla_fopen(%s) fail...\n",filename); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_fopen */ +/************************************************************************/ + +ST_RET mvla_fopen ( + MVL_NET_INFO *net_info, + ST_CHAR *filename, + ST_UINT32 init_pos, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_FILE_OPEN); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_fopen (net_info, filename, init_pos, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + + return (rc); + } + +/************************************************************************/ +/* _mvla_send_fopen */ +/************************************************************************/ + /* Allocate FOPEN_REQ_INFO with "one" FILE_NAME entry after it. */ + /* If need more than one FILE_NAME, must use "mpl_fopen". */ +#define FOPEN_REQ_INFO_SIZE (sizeof (FOPEN_REQ_INFO) + (1 * sizeof (FILE_NAME))) + +ST_RET _mvla_send_fopen (MVL_NET_INFO *net_info, + ST_CHAR *filename, + ST_UINT32 init_pos, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; +FOPEN_REQ_INFO *req_info; +FILE_NAME *fname_idx; +ST_CHAR fopen_req_info[FOPEN_REQ_INFO_SIZE]; + + /* Allocate FOPEN_REQ_INFO with "one" FILE_NAME entry after it. */ + /* If need more than one FILE_NAME, must use "mpl_fopen". */ + req_info = (FOPEN_REQ_INFO *) fopen_req_info; + + req_info->init_pos = init_pos; + req_info->num_of_fname = 1; + + /* Point to the FILE_NAME structure and fill it in. */ + fname_idx = (FILE_NAME *)(req_info + 1); + fname_idx->fn_len = strlen (filename); + fname_idx->fname = filename; + + /* Build a fopen request */ + rc = mpl_fopen (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_fopen_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_fopen_conf (MVL_REQ_PEND *req_pend) + { + req_pend->u.fopen.resp_info = + (FOPEN_RESP_INFO *) req_pend->event->u.mms.dec_rslt.data_ptr; + } + diff --git a/mmslib/mvlu/c_fread.c b/mmslib/mvlu/c_fread.c new file mode 100644 index 0000000..2fc17fa --- /dev/null +++ b/mmslib/mvlu/c_fread.c @@ -0,0 +1,139 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_fread.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_fread */ +/* mvla_fread */ +/* _mvl_process_fread_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 14 Enhanced filtered logging */ +/* 11/01/01 JRB 13 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 12 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 11 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 10 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 09 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 08 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 07 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/26/99 NAV 06 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 11/17/98 MDE 04 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/27/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_fread */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_fread ( + MVL_NET_INFO *net_info, + FREAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_fread (net_info, req_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_fread */ +/************************************************************************/ + +ST_RET mvla_fread ( + MVL_NET_INFO *net_info, + FREAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_FILE_READ); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_fread (net_info, req_info, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_fread */ +/************************************************************************/ + +ST_RET _mvla_send_fread (MVL_NET_INFO *net_info, + FREAD_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; + + /* Build a fread request */ + rc = mpl_fread (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_fread_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_fread_conf (MVL_REQ_PEND *req_pend) + { + req_pend->u.fread.resp_info = + (FREAD_RESP_INFO *) req_pend->event->u.mms.dec_rslt.data_ptr; + + /* NOTE: This function has the SIGNIFICANT advantage that it avoids */ + /* allocating another buffer and copying the "filedata" which may be */ + /* large. This can be done because the "event" is not freed until the */ + /* user calls "mvl_free_req_ctrl" when they are done with the data. */ + } + diff --git a/mmslib/mvlu/c_fren.c b/mmslib/mvlu/c_fren.c new file mode 100644 index 0000000..782e7ec --- /dev/null +++ b/mmslib/mvlu/c_fren.c @@ -0,0 +1,140 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1999, All Rights Reserved */ +/* */ +/* MODULE NAME : c_fren.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_frename */ +/* mvla_frename */ +/* _mvl_process_frename_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 11 Enhanced filtered logging */ +/* 11/01/01 JRB 10 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 09 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 08 Del LOCK on sync functs: caused deadlocks. */ +/* 01/21/00 MDE 07 Eliminated allocation */ +/* 10/10/99 GLB 06 Created to accomodate file Rename */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 11/17/98 MDE 04 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/27/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_frename */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_frename ( + MVL_NET_INFO *net_info, + ST_CHAR *curfilename, + ST_CHAR *newfilename, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_frename (net_info, curfilename, newfilename, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_frename */ +/************************************************************************/ + +/* Allocate FRENAME_REQ_INFO with 2 FILE_NAME entries after it. */ +/* If need multiple FILE_NAME elements, must use "mpl_frename". */ +#define FRENAME_REQ_INFO_SIZE (sizeof (FRENAME_REQ_INFO) + (2 * sizeof (FILE_NAME))) + +ST_RET mvla_frename ( + MVL_NET_INFO *net_info, + ST_CHAR *curfilename, + ST_CHAR *newfilename, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; +FRENAME_REQ_INFO *req_info; +FILE_NAME *fname_idx; +ST_CHAR frename_req_info[FRENAME_REQ_INFO_SIZE]; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_FILE_RENAME); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + req_info = (FRENAME_REQ_INFO *) frename_req_info; + + req_info->num_of_cur_fname = 1; + req_info->num_of_new_fname = 1; + + /* Point to the FILE_NAME structure and fill in the current FileName */ + fname_idx = (FILE_NAME *)(req_info + 1); + fname_idx->fn_len = strlen (curfilename); + fname_idx->fname = curfilename; + /* move the pointer by 1 name and fill in the new FileName */ + fname_idx++; + fname_idx->fn_len = strlen (newfilename); + fname_idx->fname = newfilename; + + + S_LOCK_COMMON_RESOURCES (); + + /* Build a frename request */ + rc = mpl_frename (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_frename_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_frename_conf (MVL_REQ_PEND *req_pend) + { + /* Nothing to do. Common code takes care of setting req_pend->result. */ + } + diff --git a/mmslib/mvlu/c_getdom.c b/mmslib/mvlu/c_getdom.c new file mode 100644 index 0000000..2ac1b7b --- /dev/null +++ b/mmslib/mvlu/c_getdom.c @@ -0,0 +1,133 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_getdom.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_getdom */ +/* mvla_getdom */ +/* _mvl_process_getdom_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 13 Enhanced filtered logging */ +/* 11/01/01 JRB 12 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 11 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 10 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 09 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 08 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 07 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 06 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/26/99 NAV 05 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 11/17/98 MDE 03 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 02 Renamed internal functions (prefix '_') */ +/* 10/01/98 DWL 01 Created from c_getvar.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_getdom */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_getdom ( + MVL_NET_INFO *net_info, + GETDOM_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_getdom (net_info, req_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_getdom */ +/************************************************************************/ + +ST_RET mvla_getdom ( + MVL_NET_INFO *net_info, + GETDOM_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_GET_DOM_ATTR); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_getdom (net_info, req_info, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_getdom */ +/************************************************************************/ + +ST_RET _mvla_send_getdom (MVL_NET_INFO *net_info, + GETDOM_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; + + /* Build a getdom request */ + rc = mpl_getdom (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_getdom_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_getdom_conf (MVL_REQ_PEND *req_pend) + { + req_pend->u.getdom.resp_info = + (GETDOM_RESP_INFO *) req_pend->event->u.mms.dec_rslt.data_ptr; + } + diff --git a/mmslib/mvlu/c_getnam.c b/mmslib/mvlu/c_getnam.c new file mode 100644 index 0000000..44af194 --- /dev/null +++ b/mmslib/mvlu/c_getnam.c @@ -0,0 +1,133 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_getnam.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_getnam */ +/* mvla_getnam */ +/* _mvl_process_getnam_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 13 Enhanced filtered logging */ +/* 11/01/01 JRB 12 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 11 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 10 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 09 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 08 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 07 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 06 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/20/99 NAV 05 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 11/17/98 MDE 03 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 02 Renamed internal functions (prefix '_') */ +/* 10/01/98 DWL 01 Created from c_getdom.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_getnam */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_getnam ( + MVL_NET_INFO *net_info, + NAMELIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_getnam (net_info, req_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_getnam */ +/************************************************************************/ + +ST_RET mvla_getnam ( + MVL_NET_INFO *net_info, + NAMELIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_GET_NAMLIST); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_getname (net_info, req_info, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_getname */ +/************************************************************************/ + +ST_RET _mvla_send_getname (MVL_NET_INFO *net_info, + NAMELIST_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; + + /* Build a getvar request */ + rc = mpl_namelist (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_getnam_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_getnam_conf (MVL_REQ_PEND *req_pend) + { + req_pend->u.getnam.resp_info = + (NAMELIST_RESP_INFO *) req_pend->event->u.mms.dec_rslt.data_ptr; + } + diff --git a/mmslib/mvlu/c_getvar.c b/mmslib/mvlu/c_getvar.c new file mode 100644 index 0000000..0ca29af --- /dev/null +++ b/mmslib/mvlu/c_getvar.c @@ -0,0 +1,133 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_getvar.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_getvar */ +/* mvla_getvar */ +/* _mvl_process_getvar_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 13 Enhanced filtered logging */ +/* 11/01/01 JRB 12 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 11 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 10 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 09 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 08 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 07 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 06 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/20/99 NAV 05 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 11/17/98 MDE 03 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 02 Renamed internal functions (prefix '_') */ +/* 09/02/98 DWL 01 Created from c_jinit.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_getvar */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_getvar ( + MVL_NET_INFO *net_info, + GETVAR_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_getvar (net_info, req_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_getvar */ +/************************************************************************/ + +ST_RET mvla_getvar ( + MVL_NET_INFO *net_info, + GETVAR_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_GET_VAR); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_getvar (net_info, req_info, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_getvar */ +/************************************************************************/ + +ST_RET _mvla_send_getvar (MVL_NET_INFO *net_info, + GETVAR_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; + + /* Build a getvar request */ + rc = mpl_getvar (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_getvar_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_getvar_conf (MVL_REQ_PEND *req_pend) + { + req_pend->u.getvar.resp_info = + (GETVAR_RESP_INFO *) req_pend->event->u.mms.dec_rslt.data_ptr; + } + diff --git a/mmslib/mvlu/c_getvla.c b/mmslib/mvlu/c_getvla.c new file mode 100644 index 0000000..a9e29b7 --- /dev/null +++ b/mmslib/mvlu/c_getvla.c @@ -0,0 +1,135 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_getvla.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_getvlist */ +/* mvla_getvlist */ +/* _mvl_process_getvlist_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 14 Enhanced filtered logging */ +/* 11/01/01 JRB 13 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 12 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 11 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 10 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 09 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 08 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 07 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/20/99 NAV 06 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 11/17/98 MDE 04 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/27/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_getvlist */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_getvlist ( + MVL_NET_INFO *net_info, + GETVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_getvlist (net_info, req_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_getvlist */ +/************************************************************************/ + +ST_RET mvla_getvlist ( + MVL_NET_INFO *net_info, + GETVLIST_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_GET_VLIST); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_getvlist (net_info, req_info, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_getvist */ +/************************************************************************/ + +ST_RET _mvla_send_getvlist (MVL_NET_INFO *net_info, + GETVLIST_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; + + /* Build a getvlist request */ + rc = mpl_getvlist (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_getvlist_conf */ +/* Set "req_pend->u.getvlist.resp_info" to POINT to response info. */ +/************************************************************************/ + +ST_VOID _mvl_process_getvlist_conf (MVL_REQ_PEND *req_pend) + { + req_pend->u.getvlist.resp_info = + (GETVLIST_RESP_INFO *) req_pend->event->u.mms.dec_rslt.data_ptr; + } + diff --git a/mmslib/mvlu/c_ident.c b/mmslib/mvlu/c_ident.c new file mode 100644 index 0000000..d191a94 --- /dev/null +++ b/mmslib/mvlu/c_ident.c @@ -0,0 +1,115 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : c_ident.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_identify */ +/* mvla_identify */ +/* _mvl_process_ident_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 12 Enhanced filtered logging */ +/* 11/01/01 JRB 11 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 10 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 09 Del LOCK on sync functs: caused deadlocks. */ +/* 01/21/00 MDE 08 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 11/17/98 MDE 06 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 05 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 04 Changes to allow compile under C++ */ +/* 05/22/98 JRB 03 Pass (MVL_REQ_PEND**) to sync function also. */ +/* Do not pass resp info ptr. Confirm sets it. */ +/* 04/16/98 JRB 02 Conf func: Let caller do "common" stuff. */ +/* Always set (*req_out) so user can always free*/ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/************************************************************************/ +/************************************************************************/ +/* mvl_identify */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_identify (MVL_NET_INFO *net_info, MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_identify (net_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_identify */ +/************************************************************************/ + +ST_RET mvla_identify (MVL_NET_INFO *net_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req; + + *req_out = req = _mvl_get_req_ctrl (net_info, MMSOP_IDENTIFY); + if (!req) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + + /* Build a identify request */ + rc = mpl_ident(); + if (rc == SD_SUCCESS) + mpl_req_log (req, NULL); + + rc = _mvl_send_req (net_info, req, rc); + + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_ident_conf */ +/************************************************************************/ +ST_VOID _mvl_process_ident_conf (MVL_REQ_PEND *req_pend) + { + req_pend->u.ident.resp_info = + (IDENT_RESP_INFO *) req_pend->event->u.mms.dec_rslt.data_ptr; + } diff --git a/mmslib/mvlu/c_info.c b/mmslib/mvlu/c_info.c new file mode 100644 index 0000000..a804dfc --- /dev/null +++ b/mmslib/mvlu/c_info.c @@ -0,0 +1,292 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2002, All Rights Reserved */ +/* */ +/* MODULE NAME : c_info.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_info_ind */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/25/04 MDE 16 Tweaked logging */ +/* 10/28/03 JRB 15 Move mvl_free_comm_event call from */ +/* mvl_info_data.. to _mvl_process_info_ind. */ +/* mvl_info_data..: use num_va arg (ignored before)*/ +/* 01/30/02 JRB 14 Del use of stack_sel. */ +/* 06/22/00 MDE 13 Minor log change */ +/* 01/21/00 MDE 12 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 11 Added SD_CONST modifiers */ +/* 04/07/99 MDE 10 Added '#ifdef MVL_INFO_RPT_CLIENT' */ +/* 02/22/99 JRB 09 BUG FIX: Don't access "va" if it is NULL. */ +/* 01/08/99 JRB 08 Use new "bsearch" object model. */ +/* 12/09/98 MDE 07 'mvl_info_rpt_rem_process' now frees event */ +/* 11/16/98 MDE 06 Renamed internal functions (prefix '_') */ +/* 07/10/98 JRB 05 Don't use net_info->rem_vmd for CLACSE, not set.*/ +/* 06/30/98 MDE 04 Added more flexable CLient Info Rpt code */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 02/10/98 MDE 02 Removed NEST_RT_TYPES support */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +#ifdef MVL_INFO_RPT_CLIENT +/************************************************************************/ + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_info_ind */ +/* A info indication has been received, process it and respond */ +/************************************************************************/ +ST_VOID u_mvl_info_rpt_ind (MVL_COMM_EVENT *event); +ST_VOID _mvl_process_info_ind (MVL_COMM_EVENT *event) + { +INFO_REQ_INFO *info_ptr; +VAR_ACC_SPEC *va_spec; + +/* Do a sanity check to make sure the number of data is correct */ + info_ptr = (INFO_REQ_INFO *) event->u.mms.dec_rslt.data_ptr; + va_spec = &info_ptr->va_spec; + if (va_spec->var_acc_tag == VAR_ACC_VARLIST) + { + if (va_spec->num_of_variables != info_ptr->num_of_acc_result) + { + MVL_LOG_NERR2 ("InfoRpt Ind : NumVar (%d) vs. NumAccRslt (%d)mismatch", + va_spec->num_of_variables, info_ptr->num_of_acc_result); + _mvl_free_comm_event (event); /* All done with this event */ + return; + } + } + +/* OK, just give the info report to the user. */ +/* NOTE: User must finish processing the event in u_mvl_info_rpt_ind, */ +/* because it is freed immediately after this function returns. */ + u_mvl_info_rpt_ind (event); + _mvl_free_comm_event (event); /* done with this event, free it */ + } + +/************************************************************************/ +/* mvl_info_data_to_local */ +/************************************************************************/ +/* This function is used to convert Info Report data to local format */ +/* The user supplies a table of variable associations, which speify the */ +/* data type, destination, and pre/post processing functions. */ +/* This function free's the info report resources when the conversion */ +/* are complete. */ + +ST_VOID mvl_info_data_to_local (MVL_COMM_EVENT *event, + ST_INT num_va, + MVL_VAR_ASSOC **info_va) + { +INFO_REQ_INFO *info_ptr; +ST_INT j; +ACCESS_RESULT *ar_ptr; +MVL_VAR_ASSOC *va; +RUNTIME_TYPE *rt; +ST_INT rt_len; + + info_ptr = (INFO_REQ_INFO *) event->u.mms.dec_rslt.data_ptr; + ar_ptr = info_ptr->acc_rslt_list; + for (j = 0; j < num_va; ++j, ++ar_ptr) + { + va = info_va[j]; + if (!va) + { + MVLU_LOG_FLOW1 ("InfoRpt Ind : No VA provided for AccessResult %d, ignoring", j); + continue; + } + + if (ar_ptr->acc_rslt_tag == ACC_RSLT_SUCCESS) + { + + /* Call the preprocessing function for this variable, if it exists */ + if (va->proc && va->proc->pre_info) + (*va->proc->pre_info)(va, event->net_info); + + /* convert data in read buffer to local representation */ + /* and store in local buffer */ + if (mvl_get_runtime (va->type_id, &rt, &rt_len) == SD_SUCCESS) + { + va->result = ms_asn1_to_local (rt, + rt_len, + ar_ptr->va_data.data, + ar_ptr->va_data.len, + (ST_CHAR *) va->data); + + if (va->result != SD_SUCCESS) + { + MVL_LOG_NERR1 ("InfoRpt Ind : Data conversion error for variable '%s'", + va->name); + } + } + else /* bad type ID */ + { + MVL_LOG_NERR1 ("InfoRpt Ind : Bad Type ID '%d'", va->type_id); + va->result = SD_FAILURE; + } + } + else /* access result == failure */ + { + MVL_LOG_NERR0 ("InfoRpt Ind : Access Result == SD_FAILURE"); + va->result = SD_FAILURE; + } + + if ((va->result == SD_SUCCESS) && va->proc && va->proc->post_info) + { + (*va->proc->post_info)(va, event->net_info); + } + } + + } + +/************************************************************************/ +/* mvl_info_rpt_rem_process */ +/************************************************************************/ + +#if defined(MVL_REM_VMD_SUPPORT) + +MVL_VMD_CTRL *(*u_mvl_get_rem_vmd_fun) (MVL_NET_INFO *net_info); + +ST_VOID mvl_info_rpt_rem_process (MVL_COMM_EVENT *event) + { +INFO_REQ_INFO *info_ptr; +ST_INT i; +ST_INT j; +OBJECT_NAME *vobj; +VARIABLE_LIST *vl; +VAR_ACC_SPEC *va_spec; +MVL_VMD_CTRL *rem_vmd; +MVL_VAR_ASSOC **info_va; +ST_INT num_va; +MVL_NVLIST_CTRL *nvlist; +ST_CHAR *name; + +/* To handle information reports, the user must have set up a remote */ +/* VMD object control structure, and the MVL_NET_INFO must reference it. */ + if (event->net_info->rem_vmd) + rem_vmd = (MVL_VMD_CTRL *) event->net_info->rem_vmd; + else + { + if (u_mvl_get_rem_vmd_fun) + rem_vmd = (*u_mvl_get_rem_vmd_fun) (event->net_info); + } + if (!rem_vmd) + { + MVL_LOG_NERR1 ("InfoRpt Ind : No rem_vmd for MVL_NET_INFO 0x%08lx", + event->net_info); + _mvl_free_comm_event (event); /* All done with this event */ + return; + } + +/* We want to get a table of pointers to VARIABLE_ASSOCIATIONS so we */ +/* can convert the received data to local format and tell the user */ +/* about it. */ + + info_ptr = (INFO_REQ_INFO *) event->u.mms.dec_rslt.data_ptr; + va_spec = &info_ptr->va_spec; + if (va_spec->var_acc_tag == VAR_ACC_NAMEDLIST) + { + vobj = &va_spec->vl_name; + for (i = 0; i < rem_vmd->num_nvlist; ++i) + { /* search for the NVL */ + if (!strcmp(rem_vmd->nvlist_tbl[i].name, vobj->obj_name.vmd_spec)) + { + /* Found the named variable list, create the response */ + nvlist = rem_vmd->nvlist_tbl[i]; + info_va = nvlist->entries; + num_va = nvlist->num_of_entries; + break; + } + } + if ((i >= rem_vmd->num_nvlist) || + (num_va != info_ptr->num_of_acc_result)) + { + MVL_LOG_NERR2 ("InfoRpt Ind : NumVar (%d) vs. NumAccRslt (%d)mismatch", + num_va, info_ptr->num_of_acc_result); + + _mvl_free_comm_event (event); /* All done with this event */ + return; + } + } + else if (va_spec->var_acc_tag == VAR_ACC_VARLIST) + { + if (va_spec->num_of_variables != info_ptr->num_of_acc_result) + { + MVL_LOG_NERR2 ("InfoRpt Ind : NumVar (%d) vs. NumAccRslt (%d)mismatch", + va_spec->num_of_variables, info_ptr->num_of_acc_result); + _mvl_free_comm_event (event); /* All done with this event */ + return; + } + + num_va = info_ptr->num_of_acc_result; + info_va = + (MVL_VAR_ASSOC **) M_CALLOC (MSEM_GEN, num_va, sizeof (MVL_VAR_ASSOC *)); + + vl = (VARIABLE_LIST *) (info_ptr + 1); + for (j = 0; j < info_ptr->num_of_acc_result; ++j, ++vl) + { + if (vl->var_spec.var_spec_tag == VA_SPEC_NAMED) + { + vobj = &vl->var_spec.vs.name; + name = vobj->obj_name.vmd_spec; + for (i = 0; i < rem_vmd->num_var_assoc; ++i) + { + if (!strcmp (rem_vmd->var_assoc_tbl[i].name, name)) + { + info_va[j] = rem_vmd->var_assoc_tbl[i]; + break; + } + } + if (i >= rem_vmd->num_var_assoc) + { + MVL_LOG_NERR1 ("InfoRpt Ind : Variable '%s' not found", name); + M_FREE (MSMEM_GEN, info_va); + _mvl_free_comm_event (event); /* All done with this event */ + return; + } + } + else + { + MVL_LOG_NERR0 ("InfoRpt Ind : VA Spec not named"); + M_FREE (MSMEM_GEN, info_va); + _mvl_free_comm_event (event); /* All done with this event */ + return; + } + } + } + + mvl_info_data_to_local (event, num_va, info_va); + M_FREE (MSMEM_GEN, info_va); + _mvl_free_comm_event (event); /* All done with this event */ + } + +#endif /* MVL_REM_VMD_SUPPORT */ + + +/************************************************************************/ +#endif /* MVL_INFO_RPT_CLIENT */ +/************************************************************************/ + diff --git a/mmslib/mvlu/c_jinit.c b/mmslib/mvlu/c_jinit.c new file mode 100644 index 0000000..2edd6d6 --- /dev/null +++ b/mmslib/mvlu/c_jinit.c @@ -0,0 +1,134 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_jinit.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_jinit */ +/* mvla_jinit */ +/* _mvl_process_jinit_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 14 Enhanced filtered logging */ +/* 11/01/01 JRB 13 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 12 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 11 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 10 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 09 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 08 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 07 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/26/99 NAV 06 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 11/17/98 MDE 04 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/27/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_jinit */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_jinit ( + MVL_NET_INFO *net_info, + JINIT_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_jinit (net_info, req_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_jinit */ +/************************************************************************/ + +ST_RET mvla_jinit ( + MVL_NET_INFO *net_info, + JINIT_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_INIT_JOURNAL); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_jinit (net_info, req_info, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_jinit */ +/************************************************************************/ + +ST_RET _mvla_send_jinit (MVL_NET_INFO *net_info, + JINIT_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; + + /* Build a jinit request */ + rc = mpl_jinit (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_jinit_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_jinit_conf (MVL_REQ_PEND *req_pend) + { + req_pend->u.jinit.resp_info = + (JINIT_RESP_INFO *) req_pend->event->u.mms.dec_rslt.data_ptr; + } + diff --git a/mmslib/mvlu/c_jread.c b/mmslib/mvlu/c_jread.c new file mode 100644 index 0000000..3916cef --- /dev/null +++ b/mmslib/mvlu/c_jread.c @@ -0,0 +1,202 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_jread.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_jread */ +/* mvla_jread */ +/* _mvl_process_jread_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 15 Enhanced filtered logging */ +/* 11/01/01 JRB 14 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 13 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 12 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 11 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 10 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 09 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 08 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 11/03/99 NAV 07 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 11/17/98 MDE 05 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 04 Renamed internal functions (prefix '_') */ +/* 10/09/98 JRB 03 Chg MVL_CLI_JOURNAL_ENTRY to MVL_JOURNAL_ENTRY,*/ +/* just like server (entry_id is now array */ +/* instead of pointer). */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/27/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_jread */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_jread ( + MVL_NET_INFO *net_info, + JREAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_jread (net_info, req_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_jread */ +/************************************************************************/ + +ST_RET mvla_jread ( + MVL_NET_INFO *net_info, + JREAD_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_READ_JOURNAL); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + req_pend->u.jread.resp_info = NULL; /* Confirm funct must allocate */ + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_jread (net_info, req_info, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_jread */ +/************************************************************************/ + +ST_RET _mvla_send_jread (MVL_NET_INFO *net_info, + JREAD_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; + + /* Build a jread request */ + rc = mpl_jread (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_jread_conf */ +/* Set "req_pend->u.jread.resp_info" to POINT to response info. */ +/************************************************************************/ + +ST_VOID _mvl_process_jread_conf (MVL_REQ_PEND *req_pend) + { +JREAD_RESP_INFO *jread_resp; +JOURNAL_ENTRY *jou_entry; + +MVL_JREAD_RESP_INFO *mvl_jread_resp; +MVL_JOURNAL_ENTRY *mvl_jou_entry; +ST_INT j; +ST_INT info_size; + + jread_resp = (JREAD_RESP_INFO *) req_pend->event->u.mms.dec_rslt.data_ptr; + + info_size = sizeof (MVL_JREAD_RESP_INFO) + + jread_resp->num_of_jou_entry * sizeof (MVL_JOURNAL_ENTRY); + + /* Allocate and fill in "req_pend->u.jread.resp_info". */ + /* CRITICAL: mvl_free_req_ctrl () must free it. */ + req_pend->u.jread.resp_info = + (MVL_JREAD_RESP_INFO *) M_CALLOC (MSMEM_GEN, 1, info_size); + mvl_jread_resp = req_pend->u.jread.resp_info; /* Local ptr to it. */ + mvl_jread_resp->num_of_jou_entry = jread_resp->num_of_jou_entry; + mvl_jread_resp->more_follows = jread_resp->more_follows; + mvl_jread_resp->jou_entry = (MVL_JOURNAL_ENTRY *) (mvl_jread_resp + 1); + if (mvl_jread_resp->num_of_jou_entry) + { + jou_entry = (JOURNAL_ENTRY *)(jread_resp + 1); /* point to first.*/ + mvl_jou_entry = mvl_jread_resp->jou_entry; /* point to first.*/ + for (j = 0; j < jread_resp->num_of_jou_entry; j++) + { + mvl_jou_entry->entry_id_len = jou_entry->entry_id_len; + memcpy (mvl_jou_entry->entry_id, jou_entry->entry_id, jou_entry->entry_id_len); + if (ms_asn1_to_appref (&mvl_jou_entry->orig_app, jou_entry->orig_ae, + jou_entry->orig_ae_len)) + { + MVL_LOG_ERR0 ("Error: ReadJournal-Resp: orig_app decode failed"); + } + memcpy (&mvl_jou_entry->occur_time, &jou_entry->ent_content.occur_time, + sizeof (MMS_BTOD)); + mvl_jou_entry->entry_form_tag = jou_entry->ent_content.entry_form_tag; + if (mvl_jou_entry->entry_form_tag == 2) /* DATA */ + { + mvl_jou_entry->ef.data.event_pres = jou_entry->ent_content.ef.data.event_pres; + memcpy (&mvl_jou_entry->ef.data.evcon_name, + &jou_entry->ent_content.ef.data.evcon_name, sizeof (OBJECT_NAME)); + mvl_jou_entry->ef.data.cur_state = jou_entry->ent_content.ef.data.cur_state; + mvl_jou_entry->ef.data.list_of_var_pres = jou_entry->ent_content.ef.data.list_of_var_pres; + if (mvl_jou_entry->ef.data.list_of_var_pres) + { + mvl_jou_entry->ef.data.num_of_var = jou_entry->ent_content.ef.data.num_of_var; + mvl_jou_entry->ef.data.list_of_var = (VAR_INFO *)(jou_entry + 1); + } + } + else /* MUST BE ANNOTATION */ + { + mvl_jou_entry->ef.annotation = jou_entry->ent_content.ef.annotation; + } + + /* Point to next src and dst entry. */ + jou_entry++; + if (mvl_jou_entry->entry_form_tag == 2 && /* DATA */ + mvl_jou_entry->ef.data.list_of_var_pres) + jou_entry = (JOURNAL_ENTRY *) ( ((ST_CHAR *)jou_entry) + + mvl_jou_entry->ef.data.num_of_var * sizeof (VAR_INFO)); + mvl_jou_entry++; + } /* end "loop" */ + } /* end "if num_of_jou_entry" */ + } + diff --git a/mmslib/mvlu/c_jstat.c b/mmslib/mvlu/c_jstat.c new file mode 100644 index 0000000..aaa4bce --- /dev/null +++ b/mmslib/mvlu/c_jstat.c @@ -0,0 +1,134 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_jstat.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_jstat */ +/* mvla_jstat */ +/* _mvl_process_jstat_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 14 Enhanced filtered logging */ +/* 11/01/01 JRB 13 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 12 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 11 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 10 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 09 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 08 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 07 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 11/03/99 NAV 06 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 11/17/98 MDE 04 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 03/27/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_jstat */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_jstat ( + MVL_NET_INFO *net_info, + JSTAT_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_jstat (net_info, req_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_jstat */ +/************************************************************************/ + +ST_RET mvla_jstat ( + MVL_NET_INFO *net_info, + JSTAT_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_STAT_JOURNAL); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_jstat (net_info, req_info, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_jstat */ +/************************************************************************/ + +ST_RET _mvla_send_jstat (MVL_NET_INFO *net_info, + JSTAT_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; + + /* Build a jstat request */ + rc = mpl_jstat (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_jstat_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_jstat_conf (MVL_REQ_PEND *req_pend) + { + req_pend->u.jstat.resp_info = + (JSTAT_RESP_INFO *) req_pend->event->u.mms.dec_rslt.data_ptr; + } + diff --git a/mmslib/mvlu/c_obtfi.c b/mmslib/mvlu/c_obtfi.c new file mode 100644 index 0000000..3fcbde4 --- /dev/null +++ b/mmslib/mvlu/c_obtfi.c @@ -0,0 +1,135 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1999, All Rights Reserved */ +/* */ +/* MODULE NAME : c_obtfi.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_obtfile */ +/* mvla_obtfile */ +/* _mvl_process_obtfile_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 06 Enhanced filtered logging */ +/* 11/01/01 JRB 05 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 04 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 03 Del LOCK on sync functs: caused deadlocks. */ +/* 01/21/00 MDE 02 Eliminated an allocation */ +/* 10/14/99 GLB 01 Created to add Obtain File function */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_obtfile */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_obtfile ( + MVL_NET_INFO *net_info, + ST_CHAR *srcfilename, + ST_CHAR *destfilename, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_obtfile (net_info, srcfilename, destfilename, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_obtfile */ +/************************************************************************/ + + /* Allocate OBTFILE_REQ_INFO with "two" FILE_NAME entries after it. */ + /* If need multiple FILE_NAME elements, must use "mpl_frename". */ +#define OBTFILE_REQ_INFO_SIZE (sizeof (OBTFILE_REQ_INFO) + (2 * sizeof (FILE_NAME))) + +ST_RET mvla_obtfile ( + MVL_NET_INFO *net_info, + ST_CHAR *srcfilename, + ST_CHAR *destfilename, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; +OBTFILE_REQ_INFO *req_info; +FILE_NAME *fname_idx; +ST_CHAR obtfile_req_info[OBTFILE_REQ_INFO_SIZE]; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_OBTAIN_FILE); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + req_info = (OBTFILE_REQ_INFO *) obtfile_req_info; + + req_info->ar_title_pres = SD_FALSE; + req_info->num_of_src_fname = 1; + req_info->num_of_dest_fname = 1; + + /* Point to the FILE_NAME structure and fill in the current FileName */ + fname_idx = (FILE_NAME *)(req_info + 1); + fname_idx->fn_len = strlen (srcfilename); + fname_idx->fname = srcfilename; + /* move the pointer by 1 name and fill in the new FileName */ + fname_idx++; + fname_idx->fn_len = strlen (destfilename); + fname_idx->fname = destfilename; + + + S_LOCK_COMMON_RESOURCES (); + + /* Build a frename request */ + rc = mpl_obtfile (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvl_process_obtfile_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_obtfile_conf (MVL_REQ_PEND *req_pend) + { + /* Nothing to do. Common code takes care of setting req_pend->result. */ + } + diff --git a/mmslib/mvlu/c_read.c b/mmslib/mvlu/c_read.c new file mode 100644 index 0000000..fd8fbd5 --- /dev/null +++ b/mmslib/mvlu/c_read.c @@ -0,0 +1,243 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2004, All Rights Reserved */ +/* */ +/* MODULE NAME : c_read.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_read_variables */ +/* mvla_read_variables */ +/* _mvl_process_read_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 20 Enhanced filtered logging */ +/* 08/09/04 JRB 19 Log if type_id invalid. */ +/* 11/01/01 JRB 18 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 17 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 16 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 15 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 14 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 13 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 12 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/20/99 NAV 11 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 10 Added SD_CONST modifiers */ +/* 12/08/98 MDE 09 Added client alternate access support */ +/* 11/17/98 MDE 08 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 07 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 06 Minor lint cleanup */ +/* 06/15/98 MDE 05 Changes to allow compile under C++ */ +/* 05/22/98 JRB 04 Pass (MVL_REQ_PEND**) to sync function also. */ +/* 04/16/98 JRB 03 Conf func: Let caller do "common" stuff. */ +/* Always set (*req_out) so user can always free*/ +/* 02/10/98 MDE 02 Removed NEST_RT_TYPES support */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_read_variables (MVL_NET_INFO *net_info, + READ_REQ_INFO *read_info, + ST_INT num_data, + MVL_READ_RESP_PARSE_INFO *parse_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_read_variables (net_info, read_info, num_data, parse_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ + +ST_RET mvla_read_variables (MVL_NET_INFO *net_info, + READ_REQ_INFO *read_info, + ST_INT num_data, + MVL_READ_RESP_PARSE_INFO *parse_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_READ); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + req_pend->u.rd.parse_info = parse_info; + req_pend->u.rd.num_data = num_data; + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_read_variables (net_info, read_info, num_data, parse_info, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_read_variables */ +/************************************************************************/ + +ST_RET _mvla_send_read_variables (MVL_NET_INFO *net_info, + READ_REQ_INFO *read_info, + ST_INT num_data, + MVL_READ_RESP_PARSE_INFO *parse_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; +VARIABLE_LIST *vl; +ST_INT i; + +#if defined(MVL_AA_SUPP) + if (read_info->va_spec.var_acc_tag == VAR_ACC_VARLIST) + { + vl = (VARIABLE_LIST *) (read_info + 1); + for (i = 0; i < num_data; ++i, ++vl) + { + if (parse_info[i].alt_acc_pres == SD_TRUE) + { + rc = _mvl_get_asn1_aa (parse_info[i].alt_acc, vl); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR0 ("Error creating ASN.1 encoded Alternate Access"); + return (SD_FAILURE); + } + } + } + } +#endif + + /* Build a read request */ + rc = mpl_read (read_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, read_info); + +#if defined(MVL_AA_SUPP) + _m_free_aa_asn1_buf (); +#endif + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ + +ST_VOID _mvl_process_read_conf (MVL_REQ_PEND *req) + { +ST_INT i; +RUNTIME_TYPE *rt; +ST_INT rt_len; +READ_RESP_INFO *read_info; +ACCESS_RESULT *ar_ptr; +MVL_READ_RESP_PARSE_INFO *parse_table; +ST_INT num_variables; +ST_BOOLEAN packed_save; + + read_info = (READ_RESP_INFO *) req->event->u.mms.dec_rslt.data_ptr; + ar_ptr = read_info->acc_rslt_list; + + /* retrieve parse information */ + parse_table = req->u.rd.parse_info; + num_variables = req->u.rd.num_data; + + /* just a sanity check */ + if (num_variables != read_info->num_of_acc_result) + { + MVL_LOG_NERR0 ("Read Confirmation : num var != num result"); + req->result = SD_FAILURE; + return; + } + + /* For each variable returned in the read response ... */ + + for (i = 0; i < num_variables; ++i, ++ar_ptr, ++parse_table) + { /* check for successfull read of this variable */ + if (ar_ptr->acc_rslt_tag == ACC_RSLT_SUCCESS) + { + /* convert data in read buffer to local representation */ + /* and store in local buffer */ + + if (mvl_get_runtime (parse_table->type_id,&rt, &rt_len) == SD_SUCCESS) + { + if (parse_table->descr_arr) + { + mvl_mod_arr_size (rt, parse_table->arr_size); + } +#if defined(MVL_AA_SUPP) + if (parse_table->alt_acc_pres == SD_TRUE && + parse_table->alt_acc_type_aa == SD_FALSE) + { + packed_save = m_alt_acc_packed; + m_alt_acc_packed = parse_table->alt_acc_data_packed; + parse_table->result = ms_asn1_to_local_aa (rt, rt_len, + parse_table->alt_acc, + ar_ptr->va_data.data, + ar_ptr->va_data.len, + (ST_CHAR *) parse_table->dest); + m_alt_acc_packed = packed_save; + } + else /* No alternate access */ + { + parse_table->result = ms_asn1_to_local (rt, rt_len, + ar_ptr->va_data.data, + ar_ptr->va_data.len, + (ST_CHAR *) parse_table->dest); + + } +#else /* We don't support alternate access */ + parse_table->result = ms_asn1_to_local (rt, rt_len, + ar_ptr->va_data.data, + ar_ptr->va_data.len, + (ST_CHAR *) parse_table->dest); + +#endif /* #if defined(MVL_AA_SUPP) */ + } + else /* bad type ID */ + { + MVL_LOG_NERR2 ("Read Confirmation : type_id %d invalid for variable #%d", parse_table->type_id, i); + parse_table->result = SD_FAILURE; + } + } + else /* access result == failure */ + parse_table->result = SD_FAILURE; + } /* for each variable */ + } + diff --git a/mmslib/mvlu/c_status.c b/mmslib/mvlu/c_status.c new file mode 100644 index 0000000..9a8fa4e --- /dev/null +++ b/mmslib/mvlu/c_status.c @@ -0,0 +1,133 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : c_status.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_status */ +/* mvla_status */ +/* _mvl_process_status_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 13 Enhanced filtered logging */ +/* 11/01/01 JRB 12 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 11 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 10 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 09 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 08 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 07 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 06 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/20/99 NAV 05 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 11/17/98 MDE 03 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 02 Renamed internal functions (prefix '_') */ +/* 10/05/98 DWL 01 Created from c_getnam.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* mvl_status */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_status ( + MVL_NET_INFO *net_info, + STATUS_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_status (net_info, req_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_status */ +/************************************************************************/ + +ST_RET mvla_status ( + MVL_NET_INFO *net_info, + STATUS_REQ_INFO *req_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_STATUS); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + S_LOCK_COMMON_RESOURCES (); + rc = _mvla_send_status (net_info, req_info, req_pend); + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_status */ +/************************************************************************/ + +ST_RET _mvla_send_status (MVL_NET_INFO *net_info, + STATUS_REQ_INFO *req_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; + + /* Build a getvar request */ + rc = mpl_status (req_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, req_info); + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + + } +/************************************************************************/ +/* _mvl_process_status_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_status_conf (MVL_REQ_PEND *req_pend) + { + req_pend->u.status.resp_info = + (STATUS_RESP_INFO *) req_pend->event->u.mms.dec_rslt.data_ptr; + } + diff --git a/mmslib/mvlu/c_write.c b/mmslib/mvlu/c_write.c new file mode 100644 index 0000000..e2204bd --- /dev/null +++ b/mmslib/mvlu/c_write.c @@ -0,0 +1,322 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2002, All Rights Reserved */ +/* */ +/* MODULE NAME : c_write.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_write_variables */ +/* mvla_write_variables */ +/* _mvl_process_write_conf */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 24 Enhanced filtered logging */ +/* 01/30/06 GLB 23 Integrated porting changes for VMS */ +/* 07/16/02 JRB 22 Skip memmove to front of asn1_buf. */ +/* Make sure num vars matches num data. */ +/* _mvla_send..: Del unused args, make static. */ +/* 03/06/02 JRB 21 Add S_UNLOCK.. before ALL returns. */ +/* 02/25/02 MDE 20 Now get max PDU size from mvl_cfg_info */ +/* 01/02/02 JRB 19 Converted to use ASN1R (re-entrant ASN1) */ +/* 11/01/01 JRB 18 mvl_wait_req_done now returns ST_RET. */ +/* 09/21/01 JRB 17 Alloc global bufs only once at startup. */ +/* 03/07/01 JRB 16 Del LOCK on sync functs: caused deadlocks. */ +/* 03/08/00 JRB 15 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* Del mvl_free_req_ctrl call. User must call. */ +/* Del invoke_id, numpend_req: see mvl_send_req.*/ +/* 01/21/00 MDE 14 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 13 Use '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 12 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/20/99 NAV 11 Add maxpend_req support to aynsc functions */ +/* 09/13/99 MDE 10 Added SD_CONST modifiers */ +/* 03/05/99 MDE 09 Fixed NVL write pointer arithmatic problem */ +/* 12/08/98 MDE 08 Added client alternate access support */ +/* 11/17/98 MDE 07 Now use MVL_ERR_COMM_SERVE_ACTIVE error code */ +/* Use MVL_SYNC_REQ_INTERFACE */ +/* 11/16/98 MDE 06 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 05 Changes to allow compile under C++ */ +/* 05/22/98 JRB 04 Pass (MVL_REQ_PEND**) to sync function also. */ +/* 04/16/98 JRB 03 Conf func: Let caller do "common" stuff. */ +/* Always set (*req_out) so user can always free*/ +/* 02/10/98 MDE 02 Removed NEST_RT_TYPES support */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mvl_acse.h" +#include "mvl_log.h" + + +static ST_RET _mvla_send_write_variables (MVL_NET_INFO *net_info, + WRITE_REQ_INFO *write_info, + MVL_REQ_PEND *req_pend); +static ST_RET w_get_asn1_data (MVL_WRITE_REQ_INFO *w_info, + ST_UCHAR *asn1_dest_buffer, + ST_INT asn1_buffer_len, + ST_INT *asn1_len_out); + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/************************************************************************/ +/************************************************************************/ +/* mvl_write_variables */ +/************************************************************************/ + +#if defined(MVL_SYNC_REQ_INTERFACE) + +ST_RET mvl_write_variables (MVL_NET_INFO *net_info, + WRITE_REQ_INFO *write_info, + ST_INT num_data, + MVL_WRITE_REQ_INFO *w_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; + + if (_mvl_comm_serve_active == SD_TRUE) + { + MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); + return (MVL_ERR_COMM_SERVE_ACTIVE); + } + + rc = mvla_write_variables (net_info, write_info, num_data, w_info, req_out); + if (rc == SD_SUCCESS) + rc = mvl_wait_req_done (*req_out); + return (rc); + } + +#endif + +/************************************************************************/ +/* mvla_write_variables */ +/************************************************************************/ + +ST_RET mvla_write_variables (MVL_NET_INFO *net_info, + WRITE_REQ_INFO *write_info, + ST_INT num_data, + MVL_WRITE_REQ_INFO *w_info, + MVL_REQ_PEND **req_out) + { +ST_RET rc; +MVL_REQ_PEND *req_pend; +VARIABLE_LIST *vl_ptr; +VAR_ACC_DATA *va_ptr; +ST_UCHAR *asn1_buf; +ST_INT asn1_len; +ST_INT asn1_buf_left; +ST_INT i; + + *req_out = req_pend = _mvl_get_req_ctrl (net_info, MMSOP_WRITE); + if (!req_pend) + return (MVL_ERR_REQ_CONTROL); + + req_pend->u.wr.w_info = w_info; + req_pend->u.wr.num_data = num_data; + + S_LOCK_COMMON_RESOURCES (); + +/* Make the write request operation specific data structure */ +/* NOTE: Number of vars MUST match number of data. To be sure, */ +/* overwrite values user entered. */ + write_info->num_of_data = num_data; + write_info->va_spec.num_of_variables = num_data; /* only used if VARLIST*/ + + vl_ptr = (VARIABLE_LIST *) (write_info+1); + if (write_info->va_spec.var_acc_tag == VAR_ACC_NAMEDLIST) + write_info->va_data = (VAR_ACC_DATA *) (write_info + 1); + else + write_info->va_data = (VAR_ACC_DATA *) (vl_ptr + + write_info->va_spec.num_of_variables); + va_ptr = write_info->va_data; + +/* encode the data */ + asn1_buf = (ST_UCHAR *) M_MALLOC (MSMEM_ASN1_DATA_ENC, mvl_cfg_info->max_msg_size); + asn1_buf_left = mvl_cfg_info->max_msg_size; + for (i = 0; i < num_data; ++i, vl_ptr++, va_ptr++, w_info++) + { + rc = w_get_asn1_data(w_info,asn1_buf,asn1_buf_left,&asn1_len); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Write : w_get_asn1_data failed, ret = %x", rc); + S_UNLOCK_COMMON_RESOURCES (); + return(rc); + } + else + { + /* Data encoded at end of asn1_buf. Adjust len so next data */ + /* encodes before this data. Save ptr and len. */ + asn1_buf_left -= asn1_len; /* adjust buffer control vars */ + va_ptr->len = asn1_len; + va_ptr->data = asn1_buf + asn1_buf_left; +#if defined(MVL_AA_SUPP) + if (w_info->alt_acc_pres) + { + rc = _mvl_get_asn1_aa (w_info[i].alt_acc, vl_ptr); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR0 ("Error creating ASN.1 encoded Alternate Access"); + S_UNLOCK_COMMON_RESOURCES (); + return (SD_FAILURE); + } + } +#endif + } + } + + rc = _mvla_send_write_variables (net_info, write_info, req_pend); + M_FREE (MSMEM_ASN1_DATA_ENC, asn1_buf); + + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* _mvla_send_write_variables */ +/************************************************************************/ + +static ST_RET _mvla_send_write_variables (MVL_NET_INFO *net_info, + WRITE_REQ_INFO *write_info, + MVL_REQ_PEND *req_pend) + { +ST_RET rc; + + /* Build a write request */ + rc = mpl_write (write_info); + if (rc == SD_SUCCESS) + mpl_req_log (req_pend, write_info); + +#if defined(MVL_AA_SUPP) + _m_free_aa_asn1_buf (); +#endif + + rc = _mvl_send_req (net_info, req_pend, rc); + return (rc); + } + +/************************************************************************/ +/* w_get_asn1_data */ +/************************************************************************/ +/* This function is to provide ASN.1 encoded data, given the variable */ +/* list element. */ + +static ST_RET w_get_asn1_data (MVL_WRITE_REQ_INFO *wr_info, + ST_UCHAR *asn1_dest_buffer, + ST_INT asn1_buffer_len, + ST_INT *asn1_len_out) + { +RUNTIME_TYPE *rt; +ST_INT num_rt; +ST_RET rc; +ST_UCHAR *asn1_start; +ST_INT asn1_len; +ST_BOOLEAN packed_save; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + rc = mvl_get_runtime (wr_info->type_id,&rt, &num_rt); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Get ASN1 Data : mvl_get_runtime failed, rc = %x", rc); + return (rc); /* bad type id */ + } + +/* Check to see if this is an array with variable number of elements */ +/* and modify the size if necessary - */ + + if (wr_info->arr) + mvl_mod_arr_size (rt, wr_info->num_el); + +/* First we need to initialize the ASN.1 encode tools, then do the */ +/* encode */ + + asn1r_strt_asn1_bld (aCtx, asn1_dest_buffer, asn1_buffer_len); + +#if defined(MVL_AA_SUPP) + if (wr_info->alt_acc_pres && + wr_info->alt_acc_type_aa == SD_FALSE) + { + packed_save = m_alt_acc_packed; + m_alt_acc_packed = wr_info->alt_acc_data_packed; + rc = ms_local_to_asn1_aa (aCtx, rt, num_rt, wr_info->alt_acc, + (ST_CHAR *) wr_info->local_data); + m_alt_acc_packed = packed_save; + } + else + rc = ms_local_to_asn1 (aCtx, rt, num_rt, (ST_CHAR *) wr_info->local_data); +#else + rc = ms_local_to_asn1 (aCtx, rt, num_rt, (ST_CHAR *) wr_info->local_data); +#endif /* #if defined(MVL_AA_SUPP) */ + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Get ASN1 Data : ms_local_to_asn1 failed, rc = %x", rc); + return (rc); /* bad type id */ + } + +/* When the ASN.1 encode is complete, 'asn1_field_ptr' points 1 byte ahead */ +/* of the start of the message. The ASN.1 message is build from back to */ +/* front, so that is now we calculate the length of the PDU */ + + asn1_start = aCtx->asn1r_field_ptr+1; + asn1_len = (asn1_dest_buffer + asn1_buffer_len) - asn1_start; + *asn1_len_out = asn1_len; + return (rc); + } + +/************************************************************************/ +/* _mvl_process_write_conf */ +/************************************************************************/ + +ST_VOID _mvl_process_write_conf (MVL_REQ_PEND *req) + { +ST_INT i; +WRITE_RESP_INFO *write_info; +WRITE_RESULT *wr_rslt; +ST_INT num_variables; +MVL_WRITE_REQ_INFO *w_info; + + write_info = (WRITE_RESP_INFO *) req->event->u.mms.dec_rslt.data_ptr; + wr_rslt = (WRITE_RESULT *) (write_info+1); + + /* retrieve output information */ + w_info = req->u.wr.w_info; + num_variables = req->u.wr.num_data; + + /* just a sanity check */ + if (num_variables != write_info->num_of_result) + { + req->result = SD_FAILURE; + return; + } + + /* For each variable returned in the write response ... */ + + for (i=0; i < num_variables; i++, wr_rslt++, w_info++) + { /* check for successful write of this variable */ + if (wr_rslt->resp_tag == WR_RSLT_SUCCESS) + w_info->result = SD_SUCCESS; + else /* bad type ID */ + w_info->result = SD_FAILURE; + } /* for each variable */ + } + diff --git a/mmslib/mvlu/mvl61850.c b/mmslib/mvlu/mvl61850.c new file mode 100644 index 0000000..31a4639 --- /dev/null +++ b/mmslib/mvlu/mvl61850.c @@ -0,0 +1,1177 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2002-2006 All Rights Reserved */ +/* */ +/* MODULE NAME : mvl61850.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Code to support IEC-61850 Reporting as a Server. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl61850_rcb_chk_state */ +/* mvl61850_urcb_rpt_send */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/05/08 JRB 31 Increment ConfRev if DatSet is written. */ +/* 07/22/08 JRB 30 Add mvl61850_objref_create. */ +/* 06/30/08 JRB 29 For Ed2, return different EntryID/TimeOfEntry*/ +/* values if RptEna=FALSE or TRUE. */ +/* 05/15/08 JRB 28 Use NEW mvl61850_integrity_timeout. */ +/* 05/06/08 JRB 27 Fix memory leak after "PDU size" error. */ +/* 04/15/08 JRB 26 Don't call mvlu_rpt_va_change for GI */ +/* (save "reason" later when scan completes). */ +/* 02/29/08 JRB 25 Allow VMD_SPEC DatSet for URCB or BRCB. */ +/* Allow AA_SPEC DatSet for URCB, but ONLY if */ +/* RCB is reserved (Resv=TRUE). */ +/* Set changed_flags for Integrity BEFORE loop. */ +/* chk_seg_needed: allow longer (129) RptID, etc*/ +/* 03/16/07 JRB 24 mvlu_gi_wr_ind: Chk that this client reserved URCB.*/ +/* 03/07/07 JRB 23 Use mvlu_get_leaf_val_int_any for Beh$stVal. */ +/* 02/28/07 JRB 22 mvlu_gi_wr_ind: allow write only if RCB is */ +/* enabled; if TrgOps.GI=FALSE, allow write but */ +/* DO NOT generate a report. */ +/* 02/13/07 JRB 21 mvl61850_get_rcb: del unused net_info arg. */ +/* Use new _rcb_writable. */ +/* 12/20/06 JRB 20 PurgeBuf only if DatSet val changed (tissue 322)*/ +/* Allow Beh$stVal to be INT8 (Enum) or INT32 */ +/* (for Tissues 120, 146, 171, 234). */ +/* 10/30/06 JRB 19 Use new mvl_vmd_* object handling functions. */ +/* 08/09/06 JRB 18 Moved most 61850 Rpt code to mvl61850_rpt.c */ +/* Chg mvl61850_rcb_build to mvl61850_urcb_rpt_send*/ +/* & use only for URCB (new functs handle BRCB).*/ +/* Use new mvlu_rpt_ready, mvl61850_mk_dataref, */ +/* mvl61850_rcb_cleanup. */ +/* Use new mvl61850_mk_rptid to generate RptID */ +/* in RPT if RptID is NULL in RCB. */ +/* Allow GI write only if TrgOp GI bit=1. */ +/* Del mvl_enc_va_data, use new ms_local_to_asn1_2.*/ +/* Add mvl61850_datset_wr_ind to allow DatSet write.*/ +/* Store EntryID everywhere as Ostring8. */ +/* Fix type for all ObjectReference (Vstring129).*/ +/* Use mvl61850_get_rcb to find the RCB. */ +/* 07/11/05 JRB 17 BUG FIX: Set cur_bufsize=0 after PurgeBuf write.*/ +/* Set BufOvfl=SD_FALSE after PurgeBuf write */ +/* (not clear in 61850, but passes KEMA test). */ +/* 07/08/05 JRB 16 For URCB, ignore BUFOVFL, ENTRYID bits in */ +/* OptFlds to conform to 61850-8-1. */ +/* 06/27/05 JRB 15 mvlu_entryid_rd_ind: return lastSentEntryID. */ +/* Old code returned "last queued" EntryID. */ +/* 06/27/05 JRB 14 _mvlu_get_rd_rcb: add (MVLU_RPT_CLIENT **) arg*/ +/* 05/16/05 JRB 13 Set failure=ARE_TEMP_UNAVAIL when trying to */ +/* write RCB elements while RptEna=TRUE. */ +/* Del mvlu_sqnum_int16u_wr.. (not writable). */ +/* 05/04/05 JRB 12 Call u_mvlu_rpt_time_get just once BEFORE */ +/* main loop in ..rcb_build so that each */ +/* segmented report has the same time stamp. */ +/* 01/19/05 JRB 11 Add mvl61850_beh_stval_rd_ind. */ +/* 08/20/04 JRB 10 Increment EntryID before encoding rpt, */ +/* so EntryID encoded in rpt matches EntryID */ +/* stored in BUFLIST_ENTRY struct. */ +/* 08/06/04 EJV 09 mvlu_entryid_wr_ind: add typecast. */ +/* 06/30/04 JRB 08 Add mvlu_sqnum_int16u_rd(wr)_ind_fun & use */ +/* SqNumInt16u instead of SqNum for BRCB. */ +/* Chg RptID type to vstring65. */ +/* Del SCL parsing functions: */ +/* mvl61850_ln_create_start, mvl61850_do_create,*/ +/* mvl61850_da_create, mvl61850_ln_create_finish,*/ +/* & mvl61850_ln_destroy. New SCL standard */ +/* makes these obsolete. */ +/* 03/18/04 JRB 07 Fix dataref in reports by adding scope. */ +/* 12/17/03 JRB 06 61850-8-1 FDIS changes: */ +/* Add ConfRev to rpt if enabled by OptFlds. */ +/* Move SubSeqNum, MoreSegmentsFollow to just */ +/* before inclusion bitstring. */ +/* Save TimeofEntry in "basrcb". */ +/* Add mvlu_timeofentry_rd_ind. */ +/* 07/09/03 JRB 05 Del assert in mvlu_gi_scan_done so GI works */ +/* for URCB too. */ +/* 04/14/03 JRB 04 Eliminate compiler warnings. */ +/* 04/04/03 JRB 03 Fix integrity/GI scan code so multiple */ +/* concurrent scans don't corrupt one another. */ +/* 03/13/03 JRB 02 Add URCB support: rename/rearrange some things*/ +/* Add code for 61850 dynamic type creation. */ +/* Trigger Intg Rpt ONLY by setting IntgPd!=0. */ +/* Trigger GI ONLY by writing GI!=0. */ +/* Move bstrcpy, bvstrcpy to "asn1r.c". */ +/* Fix report segmenting (see chk_seg_needed). */ +/* 12/15/02 JRB 01 Created */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "mvl_uca.h" +#include "mvl_log.h" +#include "mvl_acse.h" /* need mvl_cfg_info */ + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +static ST_RET fill_asn1_len_array (MVLU_RPT_CLIENT *rptClient, + MVL_NVLIST_CTRL *dsNvl, + ST_INT *asn1_len_array); + +/****** + * mvl61850_rcb_chk_state + * Check RCB state and build/send report if necessary. This function works for + * BRCB or URCB. + */ +ST_VOID mvl61850_rcb_chk_state (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + ST_DOUBLE timeNow) + { + /* If URCB enabled or BRCB enabled ONCE, chk Integrity period & triggers.*/ + if (rptClient->basrcb.RptEna + || (rptClient->rpt_ctrl->rcb_type == RCB_TYPE_IEC_BRCB + && rptClient->rpt_ctrl->brcbCtrl.enabled_once)) + { + /* Chk for Integrity Period timeout. */ + /* NOTE: use mvl61850_integrity_timeout (mvlu_integrity_timeout is */ + /* only for UCA). */ + mvl61850_integrity_timeout (rptClient, timeNow); + + /* Chk for other triggers. */ + /* NOTE: numTrgs ONLY incremented if changes matched the TrgOps. */ + if (rptClient->numTrgs > 0) + { + /* If BufTim disabled (=0) OR BufTim expired, send report now. */ + if (rptClient->basrcb.BufTim == 0 || timeNow > rptClient->buf_time_done) + { + MVLU_LOG_FLOW1 ("Non-Integrity report for client %08lx", rptClient); + mvlu_rpt_ready (rptClient, MVLU_RPT_TYPE_RBE); /* send or queue rpt*/ + } + } + } /* end if rpt enabled at least once */ + return; + } + +/************************************************************************/ +/* mvlu_gi_scan_va_done */ +/* This function is called by 'mvlu_rd_prim_done' when all "leaf" */ +/* functions for a VA have been completed (i.e. data ready for this VA).*/ +/************************************************************************/ + +ST_VOID mvlu_gi_scan_va_done (MVL_IND_PEND *indCtrl, + MVL_VAR_ASSOC *va) + { + ST_INT data_size; + /* CRITICAL: DO NOT call mvlu_rpt_va_change. rptClient->reasons_data */ + /* will be set in mvlu_gi_scan_done when scan completes. */ + data_size = mvl_type_ctrl[va->type_id].data_size; + memcpy (va->last_data, va->data, data_size); + } + +/************************************************************************/ +/* mvlu_gi_scan_done */ +/* Same as "_mvlu_rpt_scan_done" except arg is (MVL_IND_PEND *) */ +/* instead of (MVLU_RPT_SCAN_CTRL *). */ +/* */ +/* This function is called when the gi scan is complete. */ +/* (i.e. 'mvlu_rd_prim_done' has been called for all "leafs" of all */ +/* variables in the report). Everything is ready to build a report, */ +/* so build it now. */ +/************************************************************************/ + +ST_RET mvlu_gi_scan_done (MVL_IND_PEND *indCtrl) + { +ST_RET retCode; +MVLU_RPT_CLIENT *rptClient; +ST_INT j; + + /* Get "rptClient", saved in "indCtrl" when scan initialized. */ + rptClient = (MVLU_RPT_CLIENT *) indCtrl->usr_ind_ctrl; + + /* Set "reason" for each variable of Dataset now. */ + for (j = 0; j < rptClient->rpt_ctrl->dsNvl->num_of_entries; j++) + rptClient->reasons_data[j] = MVLU_TRGOPS_GI; + + /* Assume this is a BRCB or URCB. Should never get here otherwise. */ + + /* Build the report. */ + retCode = mvlu_rpt_ready (rptClient, MVLU_RPT_TYPE_INTEGRITY_OR_GI); + + if (retCode != SD_SUCCESS) + MVLU_LOG_FLOW1 ("GI report send failed: err=0x%X", retCode); + + mvlu_integrity_scan_destroy (indCtrl); /* destroy temporary struct*/ + return (retCode); + } + +/************************************************************************/ +/* mvl61850_urcb_rpt_send */ +/* Set up all info needed to build an Information Report for a URCB, */ +/* then call "mvl_info_variables" to encode/send it. */ +/************************************************************************/ +ST_RET mvl61850_urcb_rpt_send (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + ST_INT rpt_type) + { +MVL_NVLIST_CTRL *dsNvl; +MVL_NVLIST_CTRL *rptNvl; +MVL_VAR_ASSOC *va; +ST_INT j; /* loop counter */ +ST_RET retCode; +ST_INT sendIndex; +ST_INT sendIndexSave; /* save index before data, compare after data */ +ST_UINT8 *optFlds; +MVLU_BASRCB *basrcb; +ST_INT incSize; /* num bytes for inclusion bitstring */ +MVL_VAR_ASSOC *tmp_va_arr; /* alloc array of structs */ +ST_INT tmp_va_arr_size; /* num of entries in tmp_va_arr */ +MVL_VAR_ASSOC *tmp_va; /* current entry in tmp_va_arr */ +/* For Segmented reports, all segments are generated by this function, + * so these parameters can be local variables. + */ +ST_INT cur_va_index, next_va_index; /* indices into dsNvl va array */ +ST_BOOLEAN segNeeded; /* If TRUE, segmenting needed */ +ST_UINT16 SubSeqNum = 0; +ST_BOOLEAN MoreSegmentsFollow; +ST_CHAR *tmp_dataref_buf; +ST_CHAR tmpRptID [MVL61850_MAX_RPTID_LEN+1]; +ST_INT *asn1_len_array; /* array of ASN.1 lengths, one for each var (allocated)*/ + + basrcb = &rptClient->basrcb; + + optFlds = basrcb->OptFlds.data_1; + dsNvl = rptCtrl->dsNvl; + rptNvl = &rptCtrl->rptNvl; + + incSize = BSTR_NUMBITS_TO_NUMBYTES(dsNvl->num_of_entries); + + MVLU_LOG_FLOW1 ("Building IEC-61850 URCB Report, MVL_NET_INFO %08lx", rptClient->netInfo); + + /* Need tmp va's for options, array of data_refs, array of reasons_data.*/ + tmp_va_arr_size = MVLU_MAX_RPT_OPTS + (dsNvl->num_of_entries * 2); + tmp_va_arr = M_CALLOC (MSMEM_GEN, sizeof (MVL_VAR_ASSOC), tmp_va_arr_size); + + /* Need tmp buffer for datarefs. One buffer for all. */ + /* Allow max len plus NULL for each dataref. */ + tmp_dataref_buf = M_CALLOC (MSMEM_GEN, (MVL61850_MAX_OBJREF_LEN+1), dsNvl->num_of_entries); + + asn1_len_array = M_CALLOC (MSMEM_GEN, rptCtrl->dsNvl->num_of_entries, sizeof(ST_INT)); + + assert (rptCtrl->dsNvl->num_of_entries); /* must be >0 entries */ + + /* Call user function to get report time. Called here before loop */ + /* so that all segmented reports get the same time stamp. */ + u_mvlu_rpt_time_get (&basrcb->TimeofEntry); + + /* Fill in "asn1_len_array", needed later by "chk_seg_needed". */ + if (fill_asn1_len_array (rptClient, rptCtrl->dsNvl, asn1_len_array)!=SD_SUCCESS) + { + /* NOTE: This should NEVER fail, but if it does, just log it. */ + /* Real encode will almost certainly fail later. */ + MVL_LOG_ERR0 ("Cannot calculate ASN.1 length for Unbuffered Report."); + } + + /* If this is Integrity (or GI) report, just set all inclusion bits.*/ + if (rpt_type == MVLU_RPT_TYPE_INTEGRITY_OR_GI) + memset (rptClient->changed_flags, 0xff, incSize); + + for (cur_va_index = 0, next_va_index = 0; + next_va_index < rptCtrl->dsNvl->num_of_entries; + cur_va_index = next_va_index, SubSeqNum++) + { /* BEGIN MAIN LOOP */ + tmp_va = tmp_va_arr; /* start loop pointing to first entry */ + sendIndex = 0; /* start with first rptNvl->entries. */ + + /* Prepares a UCA Report NVL to be sent, based on the */ + /* options, data, and inclusion bitstring in the rptCtrl. After this*/ + /* function completes, the rptCtrl->rptNvl is ready to be sent. */ + + /* CRITICAL: asn1_len_array must be filled in before call to chk_seg_needed.*/ + segNeeded = chk_seg_needed (rptClient, asn1_len_array, cur_va_index, &next_va_index); + + +/* + printf("urcb:segNeeded=%d num=%d va_index = %d->%d\r\n", + segNeeded,rptCtrl->dsNvl->num_of_entries,cur_va_index, next_va_index); +*/ + + if (next_va_index - cur_va_index == 0) + { + MVL_LOG_ERR0 ("MMS PDU size too small to fit ANY variables in IEC-61850 Report. Report not sent."); + retCode = SD_FAILURE; + break; /* break out of loop so normal cleanup occurs. */ + } + + /* We will create a NVL to send, using the dsNvl as a model ... */ + + /* RptID and OptFlds are always the first 2 entries in the Rpt NVL. */ + + /* Add RptID to Report. */ + tmp_va->type_id = rptCtrl->rpt_typeids.vstring65; + if (basrcb->RptID [0] == '\0') + { /* RptID not set in RCB, so construct it. */ + mvl61850_mk_rptid (rptCtrl, tmpRptID, MVL61850_MAX_RPTID_LEN); + tmp_va->data = tmpRptID; + } + else + tmp_va->data = basrcb->RptID; + MVLU_LOG_CFLOW1 (" RptID='%s", tmp_va->data); /* log before tmp_va++*/ + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + + /* Add OptFlds to Report. */ + tmp_va->type_id = rptCtrl->rpt_typeids.bvstring10; + tmp_va->data = &basrcb->OptFlds; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + MVLU_LOG_CFLOW2 (" OptFld = 0x%02x 0x%02x", basrcb->OptFlds.data_1[0], + basrcb->OptFlds.data_1[1]); /* 10 bit bstr (2 bytes) */ + + /* Add optional RCB vars to NVL, depending on OptFlds. */ + + /* The following optional vars are controlled by the same OptFlds bits, + * are of the same type, and are in the same order as in UCA, so that + * UCA clients can decode reports if only these options are used. + */ + + if (BSTR_BIT_GET(optFlds, OPTFLD_BITNUM_SQNUM)) + { + /* NOTE: 61850-7-2 says SqNum in Report is INT16U, but we encode + * INT8U from URCB. ASN.1 encodes same either way, so client + * may decode as INT16U if needed. + */ + tmp_va->type_id = rptCtrl->rpt_typeids.int8u; + tmp_va->data = &basrcb->SqNum; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + MVLU_LOG_CFLOW1 (" SqNum : %u", (unsigned) basrcb->SqNum); + } + if (BSTR_BIT_GET(optFlds, OPTFLD_BITNUM_TIMESTAMP)) + { + MVLU_LOG_CFLOW2 (" RptTim : %lums, %lu days", + basrcb->TimeofEntry.ms, basrcb->TimeofEntry.day); + + tmp_va->type_id = rptCtrl->rpt_typeids.btime6; + tmp_va->data = &basrcb->TimeofEntry; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + if (BSTR_BIT_GET(optFlds, OPTFLD_BITNUM_DATSETNAME)) + { + /* UCA called it OutDat instead of DataSetName. Value is same. */ + MVLU_LOG_CFLOW1 (" DataSetName : %s", basrcb->DatSetNa); + tmp_va->type_id = rptCtrl->rpt_typeids.vstring129; /*ObjectReference*/ + tmp_va->data = basrcb->DatSetNa; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + + /* The following optional vars are NOT supported by UCA. The OptFlds bits + * must never be set by UCA clients, and the corresponding data + * must NOT be sent to UCA clients. + */ + + /* For URCB, ignore BUFOVFL bit in OptFlds. */ + /* For URCB, ignore ENTRYID bit in OptFlds. */ + + /* Add "ConfRev" if enabled by "OptFlds". */ + if (BSTR_BIT_GET(optFlds, OPTFLD_BITNUM_CONFREV)) + { + tmp_va->type_id = rptCtrl->rpt_typeids.int32u; + tmp_va->data = &basrcb->ConfRev; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + + if (segNeeded) + { + /* Set appropriate bit in OptFlds. */ + /* NOTE: this bit only for output. Never used as input. */ + BSTR_BIT_SET_ON (optFlds,OPTFLD_BITNUM_SUBSEQNUM); + + tmp_va->type_id = rptCtrl->rpt_typeids.int16u; + tmp_va->data = &SubSeqNum; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + + if (next_va_index < rptCtrl->dsNvl->num_of_entries) + MoreSegmentsFollow = SD_TRUE; + else + MoreSegmentsFollow = SD_FALSE; + + tmp_va->type_id = rptCtrl->rpt_typeids.mmsbool; + tmp_va->data = &MoreSegmentsFollow; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + else + { + BSTR_BIT_SET_OFF (optFlds,OPTFLD_BITNUM_SUBSEQNUM); + } + + /* Add inclusion bitstring. */ + tmp_va->type_id = rptCtrl->inclusion_typeid; + if (segNeeded) + { + /* just set the bits included in this segment. */ + memset (rptClient->segmented_inclusion, 0, incSize); /* start clean */ + for (j = cur_va_index; j < next_va_index; ++j) + { + if (BSTR_BIT_GET (rptClient->changed_flags, j)) + BSTR_BIT_SET_ON (rptClient->segmented_inclusion, j); + } + tmp_va->data = rptClient->segmented_inclusion; + } + else + tmp_va->data = rptClient->changed_flags; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + + /* If data-Ref enabled, go through inclusion_data to decide what to send*/ + if (BSTR_BIT_GET(optFlds, OPTFLD_BITNUM_DATAREF)) + { + for (j = cur_va_index; j < next_va_index; ++j) + { + if (BSTR_BIT_GET (rptClient->changed_flags, j)) + { + tmp_va->type_id = rptCtrl->rpt_typeids.vstring129; /*ObjectReference*/ + /* point to right part of tmp buffer & construct dataref */ + tmp_va->data = &tmp_dataref_buf [j * (MVL61850_MAX_OBJREF_LEN+1)]; + + mvl61850_mk_dataref (dsNvl->entries[j], &dsNvl->va_scope[j], + tmp_va->data, MVL61850_MAX_OBJREF_LEN); + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + } + } + + /* HERE'S DATA: Go through inclusion_data to decide what to send */ + sendIndexSave = sendIndex; /* save index before data included */ + for (j = cur_va_index; j < next_va_index; ++j) + { + if (BSTR_BIT_GET (rptClient->changed_flags, j)) + { + va = dsNvl->entries[j]; + MVLU_LOG_CFLOW3 (" Including variable %d ('%s'), reason=0x%02X", + j, va->name, rptClient->reasons_data[j]); + rptNvl->entries[sendIndex++] = va; + /* va->data already points to latest data. No need to copy data.*/ + } + } + assert (sendIndex>sendIndexSave); /* make sure SOME data included */ + + /* If "reason" enabled, go through inclusion_data to decide what to send*/ + if (BSTR_BIT_GET(optFlds, OPTFLD_BITNUM_REASON)) + { + for (j = cur_va_index; j < next_va_index; ++j) + { + if (BSTR_BIT_GET (rptClient->changed_flags, j)) + { + /* Don't need BVSTR here, because size is fixed. */ + tmp_va->type_id = rptCtrl->rpt_typeids.bstr6; + tmp_va->data = &rptClient->reasons_data[j]; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + } + } + rptNvl->num_of_entries = sendIndex; + assert (rptNvl->num_of_entries <= rptCtrl->maxNumRptVars); /* past end of array?*/ + assert ((tmp_va-tmp_va_arr) <= tmp_va_arr_size); /* past end of array?*/ + + /* Encode the InformationReport and send it. */ + retCode = mvl_info_variables (rptClient->netInfo, /* URCB: encode & send*/ + &rptClient->rpt_ctrl->rptNvl, + SD_FALSE); /* FALSE means "send as NVL" */ + /* If send fails, just log it. Try to send other segments anyway.*/ + if (retCode) + MVL_LOG_ERR1 ("Sending IEC-61850 Unbuffered Report failed: err=0x%X", retCode); + } /* END MAIN LOOP */ + + /* Increment seq number for next rpt. */ + basrcb->SqNum++; /* used only for URCB */ + + /* Reset reasons, etc. to prepare for new report triggers. */ + mvl61850_rcb_cleanup (rptClient); /* prepare for next RPT. */ + if (retCode != SD_SUCCESS) + MVLU_LOG_FLOW1 ("Report Build failed: err=0x%X", retCode); + M_FREE (MSMEM_GEN, tmp_va_arr); + M_FREE (MSMEM_GEN, tmp_dataref_buf); + M_FREE (MSMEM_GEN, asn1_len_array); + return (retCode); + } + +/****** + * chk_seg_needed + * Check if segmenting is needed. + * Set (*next_va_index) = first va to send in "next" report. + * RETURN: SD_FALSE if segmenting NOT needed. + * SD_TRUE if segmenting IS needed. + */ +ST_BOOLEAN chk_seg_needed (MVLU_RPT_CLIENT *rptClient, + ST_INT *asn1_len_array, + ST_INT cur_va_index, /* input arg */ + ST_INT *next_va_index) /* output arg */ + { +ST_INT negotiatedPduSize; +ST_INT unusedSize; +ST_INT num_entries; +ST_INT loopIndex; +ST_BOOLEAN segNeeded; + + negotiatedPduSize = rptClient->netInfo->max_pdu_size; + +/*negotiatedPduSize = 2*1024;*/ + + num_entries = rptClient->rpt_ctrl->dsNvl->num_of_entries; + + /* Subtract overhead from max "negotiated" PDU size. */ + /* Very verbose, but most data are constants so compiler should simplify.*/ + unusedSize = negotiatedPduSize + - 32 /* InfoRpt overhead (ROUGH estimate) */ + - 131 /* RptID (Vstring129) */ + - 5 /* OptFlds (Bstring10) */ + - 4 /* SqNum (Int16) */ + - 131 /* DataSetNam (Vstring129) */ + - 3 /* BufOvfl (Boolean) */ + - 8 /* TimeOfEntry (Btime6) */ + - 4 /* SubSeqNum (Int16) */ + - 3 /* MoreSegFoll (Boolean) */ + -10 /* EntryID (Ostring8) */ + -(3+num_entries/8) /* Inclusion Bitstring */ + ; + + /* In a loop, check if each var fits in the Report. */ + for (loopIndex = cur_va_index; loopIndex < num_entries; ++loopIndex) + { + /* Subtract space needed for this var. */ + /* If len==0, this var must not be included in the report, so skip it.*/ + if (asn1_len_array[loopIndex]) + { /* this var should be included in rpt. Check for space. */ + unusedSize -= 131; /* DataRef (Vstring129) */ + unusedSize -= 4; /* ReasonForInclusion (Bstring4?) */ + unusedSize -= asn1_len_array[loopIndex]; /* Data */ + } + if (unusedSize < 0) + break; /* cannot fit this va. Break out of loop. */ + } + /* When loop ends, "loopIndex" is index to first variable of "next" report.*/ + + *next_va_index = loopIndex; + if (cur_va_index == 0 && (*next_va_index) == num_entries) + segNeeded = SD_FALSE; /* All fit in one PDU (no segmenting) */ + else + segNeeded = SD_TRUE; + return (segNeeded); + } + +/************************************************************************/ +/* mvlu_confrev_rd_ind */ +/* NOTE: confrev write funct should be something like u_no_write_allowed*/ +/************************************************************************/ +ST_VOID mvlu_confrev_rd_ind (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +ST_UINT32 *dest; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + /* Only for 61850, so use mvl61850_get_rcb to find the RCB. */ + rcb = mvl61850_get_rcb (mvluRdVaCtrl->rdVaCtrl->va->base_va, + mvluRdVaCtrl->rt, + NULL); + if (rcb != NULL) + { + dest = (ST_UINT32 *) mvluRdVaCtrl->primData; + *dest = rcb->ConfRev; + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_purgebuf_rd_ind */ +/************************************************************************/ +ST_VOID mvlu_purgebuf_rd_ind (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +ST_BOOLEAN *dest; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + /* Only for 61850, so use mvl61850_get_rcb to find the RCB. */ + rcb = mvl61850_get_rcb (mvluRdVaCtrl->rdVaCtrl->va->base_va, + mvluRdVaCtrl->rt, + NULL); + if (rcb != NULL) + { + dest = (ST_BOOLEAN *) mvluRdVaCtrl->primData; + *dest = 0; /* no data stored. ALWAYS return 0 */ + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_gi_rd_ind */ +/************************************************************************/ +ST_VOID mvlu_gi_rd_ind (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +ST_BOOLEAN *dest; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + /* Only for 61850, so use mvl61850_get_rcb to find the RCB. */ + rcb = mvl61850_get_rcb (mvluRdVaCtrl->rdVaCtrl->va->base_va, + mvluRdVaCtrl->rt, + NULL); + if (rcb != NULL) + { + dest = (ST_BOOLEAN *) mvluRdVaCtrl->primData; + *dest = 0; /* no data stored. ALWAYS return 0 */ + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + + +/************************************************************************/ +/* mvlu_entryid_rd_ind */ +/************************************************************************/ +ST_VOID mvlu_entryid_rd_ind (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +MVLU_BASRCB *rcb; +ST_RET rc; +MVLU_RPT_CLIENT *rptClient; /* can access all rpt info from this struct.*/ +BUFLIST_ENTRY *entry; + + rc = SD_FAILURE; + + /* Only for 61850, so use mvl61850_get_rcb to find the RCB. */ + rcb = mvl61850_get_rcb (mvluRdVaCtrl->rdVaCtrl->va->base_va, + mvluRdVaCtrl->rt, + &rptClient); + if (rcb != NULL) + { +#if 1 /* NOTE: Ed2 says to return different value if RptEna=FALSE or TRUE.*/ + if (rptClient->basrcb.RptEna==0) + { + entry = (BUFLIST_ENTRY *) list_find_last ((DBL_LNK *) rptClient->rpt_ctrl->brcbCtrl.rpt_list); + if (entry == NULL) /* empty list, return all 0 */ + memset (mvluRdVaCtrl->primData, 0, 8); + else + memcpy (mvluRdVaCtrl->primData, entry->EntryID, 8); + } + else + memcpy (mvluRdVaCtrl->primData, rptClient->rpt_ctrl->brcbCtrl.lastSentEntryID, 8); +#else /* old way (before Ed2) */ + memcpy (mvluRdVaCtrl->primData, rptClient->rpt_ctrl->brcbCtrl.lastSentEntryID, 8); +#endif + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_timeofentry_rd_ind */ +/************************************************************************/ + +ST_VOID mvlu_timeofentry_rd_ind (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +MVLU_BASRCB *rcb; +ST_RET rc; +MVLU_RPT_CLIENT *rptClient; /* can access all rpt info from this struct.*/ +BUFLIST_ENTRY *entry; + + rc = SD_FAILURE; + /* Only for 61850, so use mvl61850_get_rcb to find the RCB. */ + rcb = mvl61850_get_rcb (mvluRdVaCtrl->rdVaCtrl->va->base_va, + mvluRdVaCtrl->rt, + &rptClient); + if (rcb != NULL) + { +#if 1 /* NOTE: Ed2 says to return different value if RptEna=FALSE or TRUE.*/ + if (rptClient->basrcb.RptEna==0) + { + entry = (BUFLIST_ENTRY *) list_find_last ((DBL_LNK *) rptClient->rpt_ctrl->brcbCtrl.rpt_list); + if (entry == NULL) /* empty list */ + { /* Empty buffer. Return all 0. */ + MMS_BTIME6 *btime = (MMS_BTIME6 *)mvluRdVaCtrl->primData; + btime->ms = 0; + btime->day = 0; + } + else + memcpy (mvluRdVaCtrl->primData, &entry->TimeOfEntry, sizeof (MMS_BTIME6)); + } + else + memcpy (mvluRdVaCtrl->primData, &rptClient->rpt_ctrl->brcbCtrl.lastSentTimeOfEntry, sizeof (MMS_BTIME6)); +#else /* old way (before Ed2) */ + memcpy (mvluRdVaCtrl->primData, &rcb->TimeofEntry, sizeof (MMS_BTIME6)); +#endif + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_purgebuf_wr_ind */ +/************************************************************************/ +ST_VOID mvlu_purgebuf_wr_ind (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +ST_BOOLEAN newval; /* val to write to RptEna */ +MVLU_BASRCB *rcb; +MVLU_RPT_CLIENT *rptClient; +ST_RET rc; + + rc = SD_FAILURE; + /* Only for 61850, so use mvl61850_get_rcb to find the RCB. */ + rcb = mvl61850_get_rcb (mvluWrVaCtrl->wrVaCtrl->va->base_va, + mvluWrVaCtrl->rt, + &rptClient); + if (_rcb_writable (rcb, rptClient, mvluWrVaCtrl)) + { /* rcb found and NOT enabled */ + rc = SD_SUCCESS; /* allow write */ + newval = *(ST_BOOLEAN *) mvluWrVaCtrl->primData; + + /* If the client is enabling the Purge, dump rpts_sent & rpts_queued */ + if (newval != 0) /* any non-zero val means "enable" */ + { + /* this function does just what we want. */ + mvl61850_brcb_rpt_lists_clean (&rptClient->rpt_ctrl->brcbCtrl); + /*renxiaobao 61850 µÚ¶þ°æÐÞ¸Ä*/ + memset(rcb->EntryID,0,8); + } + + /* NOTE: don't actually change any value because PurgeBuf is */ + /* automatically set back to 0 when Purge is complete. */ + } + else + mvluWrVaCtrl->wrVaCtrl->failure = ARE_TEMP_UNAVAIL; + mvlu_wr_prim_done (mvluWrVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_gi_wr_ind */ +/************************************************************************/ +ST_VOID mvlu_gi_wr_ind (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +ST_BOOLEAN newval; /* val to write to RptEna */ +MVLU_BASRCB *rcb; +MVLU_RPT_CLIENT *rptClient; +ST_RET rc; + + rc = SD_FAILURE; + /* Only for 61850, so use mvl61850_get_rcb to find the RCB. */ + rcb = mvl61850_get_rcb (mvluWrVaCtrl->wrVaCtrl->va->base_va, + mvluWrVaCtrl->rt, + &rptClient); + + /* Check all condtions. If all conditions right, set rc=SD_SUCCESS to allow write.*/ + if (rcb != NULL) + { + /* RCB must be enabled. */ + /* NOTE: this is only RCB attribute that is writable when RCB enabled.*/ + if (rptClient->basrcb.RptEna) + { + if (rptClient->rpt_ctrl->rcb_type == RCB_TYPE_IEC_URCB) + { + /* URCB must be reserved by this clint. RCB is enabled, so it */ + /* must already be reserved. Just make sure reserved by this client.*/ + if (rptClient->netInfo == mvluWrVaCtrl->indCtrl->event->net_info) + rc = SD_SUCCESS; /* allow write */ + else + MVLU_LOG_FLOW1 ("Write of GI for RptID='%s' FAILED because RCB reserved by another client", + rcb->RptID); + } + else /* RCB_TYPE_IEC_BRCB */ + rc = SD_SUCCESS; /* allow write */ + } + else + MVLU_LOG_FLOW1 ("Write of GI for RptID='%s' FAILED because RCB not enabled", + rcb->RptID); + } + + if (rc == SD_SUCCESS) + { + newval = *(ST_BOOLEAN *) mvluWrVaCtrl->primData; + + /* If client is enabling the GI & TrgOps.GI=TRUE, start GI scan.*/ + if (newval != 0 /* any non-zero val means "enable" */ + && BSTR_BIT_GET(rcb->TrgOps.data, TRGOPS_BITNUM_GENERAL_INTERROGATION) != 0) + mvlu_integrity_scan_read (rptClient, + mvlu_gi_scan_va_done, + mvlu_gi_scan_done); /* begin GI scan*/ + else if(newval != 0) rc = SD_FAILURE; /*renxiaobao add 20180731*/ + + /* NOTE: don't actually change any value because GI is automatically*/ + /* set back to 0 when GI is complete. */ + } + else /* for any error, return TEMP_UNAVAIL */ + mvluWrVaCtrl->wrVaCtrl->failure = ARE_TEMP_UNAVAIL; + mvlu_wr_prim_done (mvluWrVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_entryid_wr_ind */ +/************************************************************************/ +ST_VOID mvlu_entryid_wr_ind (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +MVLU_BASRCB *rcb; +MVLU_RPT_CLIENT *rptClient; +ST_RET rc; + + rc = SD_FAILURE; + /* Only for 61850, so use mvl61850_get_rcb to find the RCB. */ + rcb = mvl61850_get_rcb (mvluWrVaCtrl->wrVaCtrl->va->base_va, + mvluWrVaCtrl->rt, + &rptClient); + if (_rcb_writable (rcb, rptClient, mvluWrVaCtrl)) + { + /* NOTE: primData points to EntryID as Ostring8. */ + rc = mvl61850_brcb_rpt_set_entryid (rptClient, (ST_UCHAR *) mvluWrVaCtrl->primData); + } + else + mvluWrVaCtrl->wrVaCtrl->failure = ARE_TEMP_UNAVAIL; + mvlu_wr_prim_done (mvluWrVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_sqnum_int16u_rd_ind_fun */ +/* Same as mvlu_sqnum_rd_ind_fun except uses SqNumInt16u */ +/* (UINT16 instead of UINT8). */ +/************************************************************************/ + +ST_VOID mvlu_sqnum_int16u_rd_ind_fun (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +ST_UINT16 *dest; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + /* Only for 61850, so use mvl61850_get_rcb to find the RCB. */ + rcb = mvl61850_get_rcb (mvluRdVaCtrl->rdVaCtrl->va->base_va, + mvluRdVaCtrl->rt, + NULL); + if (rcb != NULL) + { + dest = (ST_UINT16 *) mvluRdVaCtrl->primData; + *dest = rcb->SqNumInt16u; + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvl61850_beh_stval_rd_ind */ +/************************************************************************/ +ST_VOID mvl61850_beh_stval_rd_ind (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +MVL_VAR_ASSOC *base_var; +MVL_VAR_ASSOC *lln0_var; +ST_RET retcode = SD_SUCCESS; +ST_INT32 mod_stval; /* ST$Mod$stVal from this LN */ +ST_INT32 lln0mod_stval; /* ST$Mod$stVal from LLN0 */ +ST_INT32 beh_stval; /* ST$Beh$stVal from this LN (computed) */ +MVL_DOM_CTRL *dom; +ST_INT j; + + base_var = mvluRdVaCtrl->rdVaCtrl->va->base_va; + + /* Get value of "ST$Mod$stVal" in this LN. */ + retcode = mvlu_get_leaf_val_int_any (base_var, "ST$Mod$stVal", &mod_stval); + + if (retcode == SD_SUCCESS) + { + /* Get value of "ST$Mod$stVal" in LLN0 of the same domain. */ + lln0_var = NULL; /* assume it's not found */ + assert (mvluRdVaCtrl->rdVaCtrl->va_scope.scope == DOM_SPEC); + dom = mvluRdVaCtrl->rdVaCtrl->va_scope.dom; + for (j = 0; j < dom->num_var_assoc; j++) + { + /* Use "strstr" because name may have prefix and suffix*/ + if (strstr (dom->var_assoc_tbl[j]->name, "LLN0") != NULL) + { + lln0_var = dom->var_assoc_tbl[j]; + break; /* found it. stop looping */ + } + } + if (lln0_var) + retcode = mvlu_get_leaf_val_int_any (lln0_var, "ST$Mod$stVal", &lln0mod_stval); + else + retcode = SD_FAILURE; + } + + if (retcode == SD_SUCCESS) + { /* both successful. combine results. */ + switch (lln0mod_stval) + { + case 1: + if (mod_stval > 0 && mod_stval <= 5) + beh_stval = mod_stval; + else + beh_stval = 0; /* Mod is illegal, so set Beh to illegal value too*/ + break; + + case 2: + switch (mod_stval) + { + case 1: + case 2: + beh_stval = 2; break; + case 3: + case 4: + beh_stval = 4; break; + case 5: + beh_stval = 5; break; + default: + beh_stval = 0; break; /* Mod is illegal, so set Beh to illegal value too*/ + } + break; + + case 3: + switch (mod_stval) + { + case 1: + beh_stval = 3; break; + case 2: + beh_stval = 4; break; + case 3: + beh_stval = 3; break; + case 4: + beh_stval = 4; break; + case 5: + beh_stval = 5; break; + default: + beh_stval = 0; break; /* Mod is illegal, so set Beh to illegal value too*/ + } + break; + + case 4: + switch (mod_stval) + { + case 1: + case 2: + case 3: + case 4: + beh_stval = 4; break; + case 5: + beh_stval = 5; break; + default: + beh_stval = 0; break; /* Mod is illegal, so set Beh to illegal value too*/ + } + break; + + case 5: + if (mod_stval > 0 && mod_stval <= 5) + beh_stval = 5; + else + beh_stval = 0; /* Mod is illegal, so set Beh to illegal value too*/ + break; + + default: + beh_stval = 0; /* LLNO Mod is illegal, so set Beh to illegal value too*/ + break; + } /* end outer switch */ + } + + if (retcode == SD_SUCCESS) + { + /* Convert data to configured type (INT8, INT16, or INT32). */ + if (mvluRdVaCtrl->rt->u.p.el_len == 1) + *(ST_INT8 *) mvluRdVaCtrl->primData = (ST_INT8) beh_stval; /* copy data */ + else if (mvluRdVaCtrl->rt->u.p.el_len == 2) + *(ST_INT16 *) mvluRdVaCtrl->primData = (ST_INT16) beh_stval; /* copy data */ + else if (mvluRdVaCtrl->rt->u.p.el_len == 4) + *(ST_INT32 *) mvluRdVaCtrl->primData = beh_stval; /* copy data */ + else + retcode = SD_FAILURE; /* unsupported len. Should never happen.*/ + } + mvlu_rd_prim_done (mvluRdVaCtrl, retcode); + } + +/************************************************************************/ +/* mvl61850_datset_wr_ind */ +/* Try to change IEC 61850 Report Dataset. */ +/* NOTE: for IEC 61850 only (not for UCA). */ +/************************************************************************/ +ST_VOID mvl61850_datset_wr_ind (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +MVLU_BASRCB *rcb; +ST_RET retCode; +ST_CHAR tmpbuf [MVL61850_MAX_OBJREF_LEN+1]; +OBJECT_NAME nvl_oname; +MVLU_RPT_CLIENT *rptClient; +MVL_NVLIST_CTRL *nvl; +ST_BOOLEAN do_purge = SD_FALSE; /* Chg to SD_TRUE if Purge Buffer required*/ +ST_INT16 failure = ARE_TEMP_UNAVAIL; /* use on err if no other value set*/ + + retCode = SD_FAILURE; + /* Only for 61850, so use mvl61850_get_rcb to find the RCB. */ + rcb = mvl61850_get_rcb (mvluWrVaCtrl->wrVaCtrl->va->base_va, + mvluWrVaCtrl->rt, + &rptClient); + if (_rcb_writable (rcb, rptClient, mvluWrVaCtrl)) + { + if (strcmp (rcb->DatSetNa, mvluWrVaCtrl->primData) == 0) + { + retCode = SD_SUCCESS; /* Same val written. Nothing to do but allow it*/ + } + else if (mvluWrVaCtrl->primData[0] == '\0') + { /* client wrote empty string, and it was NOT already empty */ + mvl61850_rpt_dataset_destroy (rptClient->rpt_ctrl); + rcb->ConfRev++; /* DatSet changed. Must increment ConfRev. */ + retCode = SD_SUCCESS; + } + else if (strlen ((ST_CHAR *) mvluWrVaCtrl->primData) > MVL61850_MAX_OBJREF_LEN) + { + failure = ARE_OBJ_VALUE_INVALID; + } + else + { + /* strtok modifies input buffer, so copy to local buffer first. */ + strcpy (tmpbuf, (ST_CHAR *) mvluWrVaCtrl->primData); + if (tmpbuf[0] == '@') + { /* AA-Specific Dataset */ + nvl_oname.obj_name.vmd_spec = &tmpbuf[1]; /*extract NVL name*/ + nvl_oname.object_tag = AA_SPEC; + } + else if (tmpbuf[0] == '/') + { /* VMD-Specific Dataset */ + nvl_oname.obj_name.vmd_spec = &tmpbuf[1]; /*extract NVL name*/ + nvl_oname.object_tag = VMD_SPEC; + } + else + { /* must be Domain-Specific Dataset */ + nvl_oname.domain_id = strtok (tmpbuf, "/"); /*extract dom name*/ + nvl_oname.obj_name.vmd_spec = strtok (NULL, ""); /*extract NVL name*/ + nvl_oname.object_tag = DOM_SPEC; + } + + /* If DatSet name is illegal, fail.*/ + if (nvl_oname.obj_name.vmd_spec == NULL) /* strtok failed*/ + { + MVL_LOG_ERR1 ("DatSet name '%s' is invalid. Cannot write it to RCB.", + (ST_CHAR *) mvluWrVaCtrl->primData); + failure = ARE_OBJ_VALUE_INVALID; + } + else if (nvl_oname.object_tag == AA_SPEC && + rptClient->rpt_ctrl->rcb_type == RCB_TYPE_IEC_BRCB) + { + MVL_LOG_ERR1 ("Writing AA-Specific DatSet '%s' to BRCB is NEVER allowed.", + (ST_CHAR *) mvluWrVaCtrl->primData); + failure = ARE_OBJ_VALUE_INVALID; + } + else if (nvl_oname.object_tag == AA_SPEC && + rptClient->rpt_ctrl->rcb_type == RCB_TYPE_IEC_URCB && + rptClient->basrcb.Resv == 0) + { + MVL_LOG_ERR1 ("Writing AA-Specific DatSet '%s' to URCB not allowed because URCB is not reserved.", + (ST_CHAR *) mvluWrVaCtrl->primData); + failure = ARE_OBJ_VALUE_INVALID; + } + else + { + nvl = mvl_vmd_find_nvl (&mvl_vmd, &nvl_oname, + mvluWrVaCtrl->indCtrl->event->net_info); /* for AA_SPEC*/ + if (nvl) + { + if (rptClient->rpt_ctrl->rcb_type == RCB_TYPE_IEC_BRCB) + do_purge = SD_TRUE; /* BRCB & val changed, must purge buffer*/ + /* Replace "dataset". */ + /* NOTE: If dataset was empty, destroy function does nothing. */ + mvl61850_rpt_dataset_destroy (rptClient->rpt_ctrl); + retCode = mvl61850_rpt_dataset_create (rptClient->rpt_ctrl, nvl); + /* WARNING: if create fails, old dataset is lost.*/ + if (retCode) + { + MVL_LOG_ERR1 ("DatSet change failed. RCB DatSet '%s' is no longer valid.", rcb->DatSetNa); + /* Old DatSet is no longer valid, so clear it.*/ + rcb->DatSetNa[0] = '\0'; + } + /* Even if create failed, DatSet changed (to NULL) so inc ConfRev.*/ + rcb->ConfRev++; /* DatSet changed. Must increment ConfRev.*/ + /*renxiaobao 61850 µÚ¶þ°æÐÞ¸Ä*/ + memset(rcb->EntryID,0,8); + } + } + } + } + + if (do_purge) + mvl61850_brcb_rpt_lists_clean (&rptClient->rpt_ctrl->brcbCtrl); + + if (retCode != SD_SUCCESS) + mvluWrVaCtrl->wrVaCtrl->failure = failure; + + mvlu_wr_prim_done (mvluWrVaCtrl, retCode); + } + +/************************************************************************/ +/* fill_asn1_len_array */ +/* Compute the ASN.1 encoded len for each var in a rpt dataset. */ +/************************************************************************/ +static ST_RET fill_asn1_len_array (MVLU_RPT_CLIENT *rptClient, + MVL_NVLIST_CTRL *dsNvl, /* rpt dataset */ + ST_INT *asn1_len_array) /* array of ASN.1 lengths, one for each var*/ + /* array filled in by this function */ + { +ST_UCHAR *tmp_asn1_buf; /* temporary ASN.1 buffer (allocated) */ +ST_INT tmp_asn1_buf_size = mvl_cfg_info->max_msg_size; /* reasonable size*/ +ST_INT j; +ST_RET retCode=SD_SUCCESS; /* assume success */ + + /* Alloc tmp ASN.1 buffer. Use it for each encode in this loop. */ + tmp_asn1_buf = chk_malloc (tmp_asn1_buf_size); + for (j = 0; j < dsNvl->num_of_entries; ++j) + { + if (rptClient->reasons_data[j]) /* this var should be included in rpt */ + { + ST_UCHAR *asn1_ptr; + MVL_TYPE_CTRL *type_ctrl = dsNvl->entries[j]->type_ctrl; + + retCode = ms_local_to_asn1_2 (type_ctrl->rt, type_ctrl->num_rt, + dsNvl->entries[j]->data, /* CRITICAL: use data from var*/ + tmp_asn1_buf, + tmp_asn1_buf_size, + &asn1_ptr, /* function sets asn1_ptr (not needed here)*/ + &asn1_len_array[j]); /* function sets len at this ptr*/ + if (retCode) + { + /* Should NEVER fail, but if so, don't continue with other vars.*/ + break; + } + } + } /* end loop */ + chk_free (tmp_asn1_buf); + return (retCode); + } + +/************************************************************************/ +/* mvl61850_objref_create */ +/* Create the ObjectReference for this Object. */ +/* objRef must point to buffer of at least [MVL61850_MAX_OBJREF_LEN+1] char*/ +/************************************************************************/ +ST_RET mvl61850_objref_create (ST_CHAR *objName, + MVL_SCOPE *objScope, + ST_CHAR *objRef) /* ptr to ObjectReference */ + { + switch (objScope->scope) + { + case VMD_SPEC: + strcpy (objRef, "/"); + break; + + case DOM_SPEC: + strcpy (objRef, objScope->dom->name); + strcat (objRef, "/"); + break; + + case AA_SPEC: + strcpy (objRef,"@/"); + break; + } + + /* Scope in place, now append the name of the Object. */ + if (strlen(objRef) + strlen(objName) > MVL61850_MAX_OBJREF_LEN) + { /* should NEVER happen */ + MVL_LOG_ERR0 ("Can't generate ObjectReference (too long)"); + objRef [0] = '\0'; /* return empty string */ + return (SD_FAILURE); + } + strcat (objRef, objName); + return (SD_SUCCESS); + } + diff --git a/mmslib/mvlu/mvl61850_ctl.c b/mmslib/mvlu/mvl61850_ctl.c new file mode 100644 index 0000000..3ae9943 --- /dev/null +++ b/mmslib/mvlu/mvl61850_ctl.c @@ -0,0 +1,811 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2004-2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mvl61850_ctl.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* IEC 61850 Control Model Server functions. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl61850_sbo_create_sboname */ +/* mvl61850_ctl_chk_sbo */ +/* mvl61850_ctl_chk_sbow */ +/* mvl61850_ctl_chk_state */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/23/08 JRB 17 Fix creation of CntrlObj string again. */ +/* Fix CntrlObj size (129 char) in TDL. */ +/* Send AddCause=3(select-failed) if already selected*/ +/* 07/02/08 JRB 16 Repl cmd_executing w/ ctlState (more flexible)*/ +/* Make sure SBO name <= MVL61850_MAX_OBJREF_LEN.*/ +/* Fix CntrlObj string. Del unused var. */ +/* 05/14/08 JRB 15 mvl61850_ctl_req_done: first chk (va!=NULL). */ +/* 05/08/08 JRB 14 Handle sboClass=operate-many. For sbo-with- */ +/* enhanced-sec, don't unselect until CmdTerm. */ +/* 05/08/08 JRB 13 mvl61850_ctl_chk_state: set LastApplError. */ +/* 05/06/08 JRB 12 Don't allow re-select until after command or */ +/* sboTimeout (use new getSboCtrl function). */ +/* Set default Error/AddCause if not already set*/ +/* 03/03/08 JRB 11 Add mvl61850_ctl_req_done & fix it to NOT send*/ +/* LastApplError for Oper if normal security. */ +/* Find and save sboClass to use later. */ +/* 02/26/07 JRB 10 initSboCtrl: add use_ms_timer arg. */ +/* 02/21/07 JRB 09 Fix comment. */ +/* 11/21/06 JRB 08 Add mvl61850_ctl_lastapplerror_send. */ +/* 10/30/06 JRB 07 Use new mvl_vmd_* object handling functions. */ +/* Fix check that ALL of Oper and ONLY Oper is */ +/* being written. */ +/* 04/17/06 JRB 06 Do NOT create LastApplError var at startup, */ +/* but create temporary var only when needed. */ +/* 09/12/05 JRB 05 Add mvl61850_ctl_chk_sbow. */ +/* Add NERR log if Loc$stVal==TRUE. */ +/* Chk ctlModel before SBO read or SBOw write. */ +/* 07/11/05 JRB 04 Add mvl61850_ctl_command_termination. */ +/* Add mvl61850_ctl_lastapplerror_create. */ +/* 03/28/05 JRB 03 Don't allow SBO read if Loc$stVal==TRUE. */ +/* 01/27/05 JRB 02 Del unused variable. */ +/* 12/10/04 JRB 01 New. Moved 61850 Control code from mvlu_sbo.c*/ +/* to this module. */ +/* Add mvl61850_ctl_chk_sbo, mvl61850_ctl_chk_state.*/ +/* Del leaf funct mvl61850_sbo_select_rd_ind. */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "mmsdefs.h" +#include "mvl_uca.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/************************************************************************/ +/* getSboCtrl */ +/* RETURNS: pointer to a structure from the global pool "sbo_pool" */ +/* (same pool used by "initSboCtrl" for UCA controls). */ +/* NOTE: On error, this function returns NULL. If LastApplError!=NULL, */ +/* it also sets the Error and AddCause members of LastApplError. */ +/************************************************************************/ +static MVL_SBO_CTRL *getSboCtrl (MVL_NET_INFO *net_info, + ST_CHAR *sbo_name, + ST_INT8 ctlModel, + ST_UINT32 sboTimeout, + ST_INT8 sboClass, + MVL61850_LAST_APPL_ERROR *LastApplError) +{ + ST_INT i; + MVL_SBO_CTRL *sboCtrl; + /* Stop now if name is too long (strcpy later would not be safe). */ + if (strlen (sbo_name) >= sizeof (sboCtrl->sbo_var)) + { + /* should NEVER happen */ + MVL_LOG_ERR1 ("Error finding IEC 61850 Control object '%s'. Name too long",sbo_name); + return (NULL); + } + /* See if the element is already selected. */ + sboCtrl = sbo_pool; + for (i = 0; i < MAX_NUM_SBO_PEND; ++i, ++sboCtrl) + { + if (sboCtrl->in_use == SD_TRUE && !strcmp (sboCtrl->sbo_var, sbo_name)) + { + /* Already selected. Do not allow re-select until after timeout. */ + /* DEBUG: change this to use defines for Error and AddCause? */ + if (LastApplError != NULL) + { + LastApplError->Error = 1; /* Unknown */ + if (sboCtrl->ctlState > MVL61850_CTLSTATE_UNSELECTED) + LastApplError->AddCause = 12; /* Command-already-in-execution */ + else + LastApplError->AddCause = 3; /* Select-failed */ + } + return (NULL); + } + } + /* The protected element is not selected, find unused SBO control */ + sboCtrl = sbo_pool; + for (i = 0; i < MAX_NUM_SBO_PEND; ++i, ++sboCtrl) + { + if (sboCtrl->in_use == SD_FALSE) + break; + } + if (i >= MAX_NUM_SBO_PEND) + { + if (LastApplError != NULL) + { + LastApplError->Error = 1; /* Unknown */ + LastApplError->AddCause = 0; /* Unknown */ + } + return (NULL); + } + /* Found available SBO control, set the parameters. */ + memset (sboCtrl, 0, sizeof (MVL_SBO_CTRL)); /* start w/ clean struct*/ + sboCtrl->in_use = SD_TRUE; + sboCtrl->use_ms_timer = SD_TRUE; /* ALWAYS "ms" timer for 61850 */ + sboCtrl->expire_time_ms = sGetMsTime () + sboTimeout; + sboCtrl->net_info = net_info; + /* NOTE: sbo_name length checked above, so this strcpy is safe. */ + strcpy (sboCtrl->sbo_var, sbo_name); + sboCtrl->ctlModel = ctlModel; + sboCtrl->sboClass = sboClass; + return (sboCtrl); + } +/************************************************************************/ +/* mvl61850_sbo_create_sboname */ +/* Creates a name to return when an IEC 61850 SBO attribute is read. */ +/* sboName must point to buffer of at least [MVL61850_MAX_OBJREF_LEN+1] char*/ +/* NOTE: this name may also be passed to "mvlu_sbo_chk_state" */ +/* to find the correct MVL_SBO_CTRL struct. */ +/************************************************************************/ +ST_VOID mvl61850_sbo_create_sboname (MVL_VAR_ASSOC *va, MVL_SCOPE *va_scope, + ST_CHAR *sboName) + { +ST_CHAR *tmp_ptr; /* use to find last '$' in var name */ + +/* Create ObjectReference for this variable. */ + if (mvl61850_objref_create (va->name, va_scope, sboName) != SD_SUCCESS) + { /* should NEVER happen */ + MVL_LOG_ERR0 ("Can't generate SBO ObjectReference"); + sboName [0] = '\0'; /* return empty string */ + return; + } + +/* Replace end of var name with name of protected element (Oper). */ +/* Var name may end with Oper, SBO, Cancel, etc. Replace with "Oper". */ +/* This is a waste if it already ends with "Oper", but it takes more */ +/* code to check. */ + if ((tmp_ptr = strrchr (sboName, '$')) != NULL && /* find last '$'*/ + tmp_ptr - sboName + 5 <= MVL61850_MAX_OBJREF_LEN) /* room for Oper*/ + strcpy (tmp_ptr+1, "Oper"); /* Write name of protected element (Oper) AFTER it.*/ + else + { /* should NEVER happen */ + MVL_LOG_ERR1 ("Can't generate SBO ObjectReference from '%s' (too long to replace last comp with 'Oper')", sboName); + sboName [0] = '\0'; /* return empty string */ + } + } + +/************************************************************************/ +/* mvl61850_mkname_ctlmodel */ +/* Generate the "flattened" name of the "ctlModel" attribute that */ +/* corresponds to the attribute passed as "var_name" arg. */ +/* The var_name arg should always be of the following form: */ +/* LNodeName$CO$yyy$Oper */ +/* LNodeName$CO$yyy$SBO, etc. */ +/* This funct generates a name like this ("LNodeName$" stripped off): */ +/* CF$yyy$ctlModel */ +/************************************************************************/ +ST_RET mvl61850_mkname_ctlmodel (ST_CHAR *var_name, ST_CHAR *flatname, size_t flatname_len) + { +ST_RET retcode = SD_FAILURE; +ST_CHAR *firstdollar; /* ptr to first '$' in var name */ +ST_CHAR *lastdollar; /* ptr to last '$' in var name */ +ST_INT prefixlen; /* len of first half of generated string */ +ST_CHAR *suffix = "ctlModel"; + + firstdollar = strchr (var_name, '$'); /* find first '$' */ + lastdollar = strrchr (var_name, '$'); /* find last '$' */ + if (firstdollar && lastdollar) + { + prefixlen = lastdollar - firstdollar; + if (prefixlen + strlen (suffix) <= flatname_len) + { + strcpy (flatname, firstdollar+1); /* Copy text after first '$'*/ + strncpy (flatname, "CF", 2); /* Replace CO at start with CF */ + strcpy (flatname + prefixlen, suffix); /* Write new suffix after last '$'*/ + retcode = SD_SUCCESS; + } + } + return (retcode); + } + +/************************************************************************/ +/* mvl61850_mkname_sbotimeout */ +/* Generate the "flattened" name of the "sboTimeout" attribute that */ +/* corresponds to the attribute passed as "var_name" arg. */ +/* The var_name arg should always be of the following form: */ +/* LNodeName$CO$yyy$SBO */ +/* This funct generates a name like this ("LNodeName$" stripped off): */ +/* CF$yyy$sboTimeout */ +/************************************************************************/ +ST_RET mvl61850_mkname_sbotimeout (ST_CHAR *var_name, ST_CHAR *flatname, size_t flatname_len) + { +ST_CHAR *firstdollar; /* ptr to first '$' in var name */ +ST_CHAR *lastdollar; /* ptr to last '$' in var name */ +ST_INT prefixlen; /* len of first half of generated string */ +ST_CHAR *suffix = "sboTimeout"; /* replacement text to put after last '$'*/ +ST_RET retcode = SD_FAILURE; + + firstdollar = strchr (var_name, '$'); /* find first '$' */ + lastdollar = strrchr (var_name, '$'); /* find last '$' */ + if (firstdollar && lastdollar) + { + prefixlen = lastdollar - firstdollar; + if (prefixlen + strlen (suffix) <= flatname_len) /* room to replace*/ + { + strcpy (flatname, firstdollar+1); /* Copy text after first '$'*/ + strncpy (flatname, "CF", 2); /* Replace CO at start with CF */ + strcpy (flatname + prefixlen, suffix); /* Write new suffix after last '$'*/ + retcode = SD_SUCCESS; + } + } + return (retcode); + } + +/************************************************************************/ +/* mvl61850_mkname_sboclass */ +/* Generate the "flattened" name of the "sboClass" attribute that */ +/* corresponds to the attribute passed as "var_name" arg. */ +/* The var_name arg should always be of the following form: */ +/* LNodeName$CO$yyy$SBO */ +/* This funct generates a name like this ("LNodeName$" stripped off): */ +/* CF$yyy$sboClass */ +/************************************************************************/ +ST_RET mvl61850_mkname_sboclass (ST_CHAR *var_name, ST_CHAR *flatname, size_t flatname_len) + { +ST_CHAR *firstdollar; /* ptr to first '$' in var name */ +ST_CHAR *lastdollar; /* ptr to last '$' in var name */ +ST_INT prefixlen; /* len of first half of generated string */ +ST_CHAR *suffix = "sboClass"; /* replacement text to put after last '$'*/ +ST_RET retcode = SD_FAILURE; + + firstdollar = strchr (var_name, '$'); /* find first '$' */ + lastdollar = strrchr (var_name, '$'); /* find last '$' */ + if (firstdollar && lastdollar) + { + prefixlen = lastdollar - firstdollar; + if (prefixlen + strlen (suffix) <= flatname_len) /* room to replace*/ + { + strcpy (flatname, firstdollar+1); /* Copy text after first '$'*/ + strncpy (flatname, "CF", 2); /* Replace CO at start with CF */ + strcpy (flatname + prefixlen, suffix); /* Write new suffix after last '$'*/ + retcode = SD_SUCCESS; + } + } + return (retcode); + } + +/************************************************************************/ +/* mvl61850_sboclass_find */ +/* Find the corresponding 'sboClass' attribute for this variable and */ +/* read its current value. */ +/************************************************************************/ +static ST_INT8 mvl61850_sboclass_find (MVL_VAR_ASSOC *va) + { +ST_CHAR sboClassName [MAX_IDENT_LEN+1]; /* "CF$...$sboClass" */ +ST_INT8 sboClass; + if (mvl61850_mkname_sboclass (va->name, sboClassName, MAX_IDENT_LEN) != SD_SUCCESS || + mvlu_get_leaf_val_int8 (va->base_va, sboClassName, &sboClass) != SD_SUCCESS) + sboClass = MVL61850_SBOCLASS_OPERATE_ONCE; /* set default value */ + return (sboClass); + } + +/************************************************************************/ +/* mvl61850_ctl_chk_sbo */ +/* This function should be called from "leaf" function when IEC 61850 */ +/* "SBO" attribute is being read (i.e. performing Control Model 'Select'*/ +/* Service). It checks if client is allowed to perform 'Select'. */ +/* If 'Select' allowed, it reserves a MVL_SBO_CTRL struct and returns */ +/* a ptr to it. */ +/* RETURNS: ptr to struct if successful (sbo_var member of struct */ +/* contains name to send in read response). */ +/* NULL if failed. */ +/* CRITICAL: if return is NOT NULL & caller decides not to allow */ +/* 'Select', must pass this ptr to mvlu_sbo_ctrl_free. */ +/************************************************************************/ +MVL_SBO_CTRL *mvl61850_ctl_chk_sbo (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +MVL_VAR_ASSOC *va; +ST_CHAR sboName[MVL61850_MAX_OBJREF_LEN+1]; +MVL_SBO_CTRL *sboCtrl = NULL; +ST_CHAR *lastdollar; /* ptr to last '$' in var name */ +/* Init sboTimeout=0. If ..$CF$..$sboTimeout==0, or not found, set to default val.*/ +ST_UINT32 sboTimeout = 0; /* SBO timeout value. */ +ST_CHAR sboTimeoutName [MAX_IDENT_LEN+1]; /* "CF$...$sboTimeout" */ +ST_BOOLEAN loc_stval; +ST_INT8 sboClass; + +/* First take care of timeout housekeeping */ + mvlu_sbo_chk_timers (); + +/* find the name of the attribute being selected */ + va = mvluRdVaCtrl->rdVaCtrl->va; + +/* Check value of "ST$Loc$stVal". */ + if (mvlu_get_leaf_val_boolean (va->base_va, "ST$Loc$stVal", &loc_stval)!=SD_SUCCESS) + loc_stval = SD_FALSE; /* if can't read ST$Loc$stVal, assume FALSE*/ + if (loc_stval) + { + MVL_LOG_NERR1 ("Reading of '%s' not allowed: Local mode is set.", va->name); + return (NULL); /* error return */ + } + +/* Only perform "Select" if SBO is ONLY attribute being read. */ +/* Check this by seeing if variable name ends with "$SBO". */ +/* Point to where "$SBO" should be, then see if it's there. */ + lastdollar = strrchr (va->name, '$'); /* find last '$' */ + if (lastdollar != NULL && strcmp (lastdollar+1, "SBO") == 0) + { + ST_INT8 ctlModel; + ST_CHAR flatname [MAX_IDENT_LEN + 1]; /* attribute to find */ + + /* Generate "ctlModel" leaf name and try to read its value. */ + /* CRITICAL: this only works if va->name checked first (i.e. it ends in "$SBO")*/ + if (mvl61850_mkname_ctlmodel (va->name, flatname, MAX_IDENT_LEN) != SD_SUCCESS + || mvlu_get_leaf_val_int8 (va->base_va, flatname, &ctlModel) != SD_SUCCESS) + ctlModel = MVL61850_CTLMODEL_STATUS_ONLY; /* can't read ctlModel. assume status-only*/ + + if (ctlModel != MVL61850_CTLMODEL_SBO_NORMAL) + { + MVL_LOG_NERR3 ("Reading of '%s' not allowed: ctlModel=%d, expected ctlModel=%d (sbo-with-normal-security)", + va->name, ctlModel, MVL61850_CTLMODEL_SBO_NORMAL); + return (NULL); /* error return */ + } + +/* Create sboName from var name. */ + //mvl61850_sbo_create_sboname (va, &mvluRdVaCtrl->rdVaCtrl->va_scope, sboName);//lnk±àÒëɾ³ý£¬Ô­Ç°ÖóÌÐòδʹÓà + +/* Find "sboTimeout" value. */ + if (mvl61850_mkname_sbotimeout (va->name, sboTimeoutName, MAX_IDENT_LEN) != SD_SUCCESS || + mvlu_get_leaf_val_uint32 (va->base_va, sboTimeoutName, &sboTimeout) != SD_SUCCESS || + sboTimeout==0) /* ..$CF$..$sboTimeout==0, or not found */ + sboTimeout = SBO_SELECT_TIMEOUT; /* set timeout to default val */ + +/* Find "sboClass" value. */ + sboClass = mvl61850_sboclass_find (va); + +/* Get a SBO control element */ + sboCtrl = getSboCtrl (mvluRdVaCtrl->indCtrl->event->net_info,sboName, + ctlModel, sboTimeout, sboClass, + NULL); /* LastApplError not used*/ + } + + return (sboCtrl); + } + +/************************************************************************/ +/* mvl61850_ctl_chk_sbow */ +/* This function should be called from "leaf" function when IEC 61850 */ +/* an attribute inside the "SBOw" structure is being written */ +/* (i.e. performing Control Model 'Select' Service for */ +/* sbo-with-enhanced-security). */ +/* It checks if client is allowed to perform 'Select'. */ +/* If 'Select' allowed, it reserves a MVL_SBO_CTRL struct and returns */ +/* a ptr to it. */ +/* RETURNS: ptr to struct if successful (sbo_var member of struct */ +/* contains name to send in read response). */ +/* NULL if failed. */ +/* CRITICAL: if return is NOT NULL & caller decides not to allow */ +/* 'Select', caller must pass this ptr to mvlu_sbo_ctrl_free. */ +/* NOTE: this is very similar to mvl61850_ctl_chk_sbo, but it is used */ +/* when writing "SBOw" instead of when reading "SBO". */ +/************************************************************************/ +MVL_SBO_CTRL *mvl61850_ctl_chk_sbow (MVLU_WR_VA_CTRL *mvluWrVaCtrl) +{ + MVL_VAR_ASSOC *va; + ST_CHAR sboName[MVL61850_MAX_OBJREF_LEN+1]; + MVL_SBO_CTRL *sboCtrl = NULL; + ST_CHAR *lastdollar; /* ptr to last '$' in var name */ + /* Init sboTimeout=0. If ..$CF$..$sboTimeout==0, or not found, set to default val.*/ + ST_UINT32 sboTimeout = 0; /* SBO timeout value. */ + ST_CHAR sboTimeoutName [MAX_IDENT_LEN+1]; /* "CF$...$sboTimeout" */ + ST_BOOLEAN loc_stval; + ST_INT8 sboClass; + + /* First take care of timeout housekeeping */ + mvlu_sbo_chk_timers (); + va = mvluWrVaCtrl->wrVaCtrl->va; + /* Check value of "ST$Loc$stVal". */ + if (mvlu_get_leaf_val_boolean (va->base_va, "ST$Loc$stVal", &loc_stval)!=SD_SUCCESS) + { + loc_stval = SD_FALSE; /* if can't read ST$Loc$stVal, assume FALSE*/ + } + if (loc_stval) + { + /* renxiaobao ¿ØÖÆ*/ + mvluWrVaCtrl->wrVaCtrl->LastApplError.Error = 1; /* Unknown */ + mvluWrVaCtrl->wrVaCtrl->LastApplError.AddCause = Blocked_CB; /* Blocked-by-switching-hierarchy */ + MVL_LOG_NERR1 ("Writing of '%s' not allowed: Local mode is set.", va->name); + return (NULL); /* error return */ + } + /* Only perform "Select" if entire SBOw is written & nothing else.*/ + /* Check this by seeing if variable name ends with "$SBOw". */ + /* Point to where "$SBOw" should be, then see if it's there. */ + lastdollar = strrchr (va->name, '$'); /* find last '$' */ + if (lastdollar != NULL && strcmp (lastdollar+1, "SBOw") == 0) + { + ST_INT8 ctlModel; + ST_CHAR flatname [MAX_IDENT_LEN + 1]; /* attribute to find */ + /* Generate "ctlModel" leaf name and try to read its value. */ + /* CRITICAL: this only works if va->name checked first (i.e. it ends in "$SBOw")*/ + if (mvl61850_mkname_ctlmodel (va->name, flatname, MAX_IDENT_LEN) != SD_SUCCESS + || mvlu_get_leaf_val_int8 (va->base_va, flatname, &ctlModel) != SD_SUCCESS) + { + ctlModel = MVL61850_CTLMODEL_STATUS_ONLY; /* can't read ctlModel. assume status-only*/ + } + /*renxiaobao ¿ØÖÆ + // if (ctlModel != MVL61850_CTLMODEL_SBO_ENHANCED)*/ + if ((ctlModel != MVL61850_CTLMODEL_SBO_ENHANCED)&&(ctlModel != MVL61850_CTLMODEL_SBO_NORMAL)) + { + /* renxiaobao ¿ØÖÆ*/ + mvluWrVaCtrl->wrVaCtrl->LastApplError.Error = 1; /* Unknown */ + mvluWrVaCtrl->wrVaCtrl->LastApplError.AddCause = Blocked_by_Mode; /* Blocked-by-Mode */ + MVL_LOG_NERR3 ("Writing of '%s' not allowed: ctlModel=%d, expected ctlModel=%d (sbo-with-enhanced-security)", + va->name, ctlModel, MVL61850_CTLMODEL_SBO_ENHANCED); + return (NULL); + } + /* Create sboName from var name. */ + /* NOTE: the sboName is not really used for "SBOw", but the "initSboCtrl"*/ + /* function (originally written only for "SBO") needs it. */ + //mvl61850_sbo_create_sboname (va, &mvluWrVaCtrl->wrVaCtrl->va_scope, sboName);//lnk±àÒëɾ³ý£¬Ô­Ç°ÖóÌÐòδʹÓà + /* Find "sboTimeout" value. */ + if (mvl61850_mkname_sbotimeout (va->name, sboTimeoutName, MAX_IDENT_LEN) != SD_SUCCESS || + mvlu_get_leaf_val_uint32 (va->base_va, sboTimeoutName, &sboTimeout) != SD_SUCCESS || + sboTimeout==0) /* ..$CF$..$sboTimeout==0, or not found */ + { + /*renxiaobao ¿ØÖÆ*/ + sboTimeout = SBO_SELECT_TIMEOUT*1000; /* set timeout to default val */ + } + /* Find "sboClass" value. */ + sboClass = mvl61850_sboclass_find (va); + /* Get a SBO control element */ + sboCtrl = getSboCtrl (mvluWrVaCtrl->indCtrl->event->net_info, sboName, + ctlModel, sboTimeout, sboClass, + &mvluWrVaCtrl->wrVaCtrl->LastApplError); + } + return (sboCtrl); +} +/************************************************************************/ +/* mvl61850_ctl_chk_state */ +/* Check ctlModel, etc. to determine if control is right type & */ +/* in right state. */ +/* RETURNS: SD_SUCCESS if OK to perform Operate command. */ +/* SD_FAILURE if NOT OK (also sets appropriate Error and */ +/* AddCause members of LastApplError). */ +/************************************************************************/ +ST_RET mvl61850_ctl_chk_state (MVLU_WR_VA_CTRL *mvluWrVaCtrl) +{ + MVL_VAR_ASSOC *base_var = mvluWrVaCtrl->wrVaCtrl->va->base_va; + ST_INT8 ctlModel; + ST_BOOLEAN loc_stval; + ST_CHAR flatname [MAX_IDENT_LEN + 1]; /* attribute to find */ + ST_CHAR *lastdollar; /* ptr to last '$' in var name */ + MVL61850_LAST_APPL_ERROR *LastApplError; + + /* renxiaobao 5.3°æ±¾ÐÞ¸Ä*/ + /* Send this DAE in the MMS Write response on any error. If the Write */ + /* succeeds, this value is ignored (i.e. not sent). */ + mvluWrVaCtrl->wrVaCtrl->failure = ARE_OBJ_ACCESS_DENIED; + + LastApplError = &mvluWrVaCtrl->wrVaCtrl->LastApplError; + /* Only allow "Operate" if writing ALL of "Oper" and ONLY "Oper". */ + /* Check this by seeing if variable name ends with "$Oper". */ + /* Point to where "$Oper" should be, then see if it's there. */ + lastdollar = strrchr (mvluWrVaCtrl->wrVaCtrl->va->name, '$'); /* find last '$'*/ + if (lastdollar == NULL || strcmp (lastdollar+1, "Oper") != 0) + { + /* LastApplError not sent in this case, so don't bother setting it. */ + return (SD_FAILURE); /* ERROR: not writing ALL of Oper and ONLY Oper.*/ + } + /* Check value of "ST$Loc$stVal". */ + if (mvlu_get_leaf_val_boolean (base_var, "ST$Loc$stVal", &loc_stval)!=SD_SUCCESS) + { + loc_stval = SD_FALSE; /* if can't read ST$Loc$stVal, assume FALSE*/ + } + if (loc_stval == SD_FALSE) + { + /* Generate "ctlModel" leaf name and try to read its value. */ + if (mvl61850_mkname_ctlmodel (mvluWrVaCtrl->wrVaCtrl->va->name, flatname, MAX_IDENT_LEN) != SD_SUCCESS + || mvlu_get_leaf_val_int8 (base_var, flatname, &ctlModel) != SD_SUCCESS) + { + ctlModel = MVL61850_CTLMODEL_STATUS_ONLY; /* can't read ctlModel. assume status-only*/ + } + if (ctlModel == MVL61850_CTLMODEL_DIRECT_NORMAL||ctlModel == MVL61850_CTLMODEL_DIRECT_ENHANCED) + { + /* This is Direct control. */ + /* OK. Nothing else to check. Continue to successful return. */ + } + else if (ctlModel == MVL61850_CTLMODEL_SBO_NORMAL||ctlModel == MVL61850_CTLMODEL_SBO_ENHANCED) + { + /* This is SBO control. */ + /* Chk sboCtrl (set by startElWrites if client writing "Oper"). */ + if (!mvluWrVaCtrl->wrVaCtrl->sboCtrl) + { + LastApplError->Error = 1; /* Unknown*/ + LastApplError->AddCause = 3; /* Select-failed*/ + return (SD_FAILURE); + } + } + else + { + /* ctlModel="status-only" or invalid. */ + LastApplError->Error = 1; /* Unknown*/ + LastApplError->AddCause = 8; /* Blocked-by-mode*/ + return (SD_FAILURE); + } + } /* end "if (loc_stval == SD_FALSE)" (i.e. "remote" mode) */ + else + { /* loc_stval == SD_TRUE (i.e. "local" mode) */ + LastApplError->Error = 1; /* Unknown*/ + LastApplError->AddCause = 8; /* Blocked-by-mode*/ + return (SD_FAILURE); + } + /* Passed all checks. Allow the control operation. */ + return (SD_SUCCESS); + } +/************************************************************************/ +/* mvl61850_ctl_command_termination */ +/* Called by user to send "Command Termination" request for controls */ +/* with "Enhanced Security". */ +/************************************************************************/ +ST_RET mvl61850_ctl_command_termination (MVL_NET_INFO *net_info, ST_CHAR *oper_ref, + ST_RET status, MVL61850_LAST_APPL_ERROR *last_appl_error) + { +OBJECT_NAME nvl_obj; /* NVL object name */ +MVL_NVLIST_CTRL *nvlist_ctrl; +ST_INT num_var; +OBJECT_NAME var_obj[2]; /* array of var object names (1 or 2 depending on status)*/ +MVL_VAR_ASSOC *last_appl_var = NULL; /* var assoc for "LastApplError"*/ +ST_RET ret; +ST_CHAR oper_ref_local[MAX_IDENT_LEN+1]; /* local copy of oper_ref arg */ +MVL_SBO_CTRL *sboCtrl; /* ptr to SBO control if this is SBO */ + + ret = SD_SUCCESS; /* assume success */ + + /* Create tmp NVL used only for building this rpt. */ + nvl_obj.object_tag = VMD_SPEC; + nvl_obj.obj_name.vmd_spec = "tmp_nvl_for_rpt"; + + /* Fill in var_obj array. */ + num_var = 0; + if (status != SD_SUCCESS) + { /* On error, include "LastApplError" in report. */ + ST_INT type_id; + /* Create temporary VMD_SPEC "LastApplError" variable. */ + /* If this fails, mvl_vmd_nvl_add will also fail later. */ + type_id = mvl_typename_to_typeid ("LastApplErrorType"); + if (type_id >= 0) + { + var_obj[num_var].object_tag = VMD_SPEC; + var_obj[num_var].obj_name.vmd_spec = "LastApplError"; + /* NOTE: last_appl_error points to temporary data. This var must be deleted before returning*/ + last_appl_var = mvl_vmd_var_add (&mvl_vmd, &var_obj[num_var], + NULL, /* (MVL_NET_INFO *) */ + type_id, + last_appl_error, /* data ptr (saved in var->data) */ + NULL, /* (MVL_VAR_PROC *) */ + SD_FALSE); /* DO NOT copy the var name */ + } + num_var++; + } + /* Add this control object (LN$FC$xxx$Oper) to "var_obj". */ + var_obj[num_var].object_tag = DOM_SPEC; /* ALWAYS Domain specific*/ + /* strtok modifies input buffer, so copy oper_ref to local buffer first. */ + strcpy (oper_ref_local, oper_ref); + var_obj[num_var].domain_id = strtok (oper_ref_local, "/"); /*extract dom name*/ + var_obj[num_var].obj_name.vmd_spec = strtok (NULL, ""); + if (var_obj[num_var].obj_name.vmd_spec == NULL) + { + MVL_LOG_ERR1 ("Invalid ControlObjectReference '%s', cannot send CommandTermination", oper_ref); + ret = SD_FAILURE; + } + else + { + num_var++; + + nvlist_ctrl = mvl_vmd_nvl_add (&mvl_vmd, &nvl_obj, NULL, /* net_info: not needed*/ + num_var, var_obj, SD_TRUE); /* copy name */ + + /* Now send report */ + if (nvlist_ctrl) + { + ret = mvl_info_variables (net_info, nvlist_ctrl, SD_TRUE); /* listOfVariables*/ + mvl_vmd_nvl_remove (&mvl_vmd, &nvl_obj, NULL); /* done with tmp NVL */ + } + else + ret = SD_FAILURE; + } + /* If temporary "LastApplError" var created, destroy it now. */ + if (last_appl_var) + mvl_vmd_var_remove (&mvl_vmd, &var_obj[0], NULL); /* always first in "var_obj" array*/ + + sboCtrl = mvlu_sbo_chk_state (oper_ref, net_info); + if (sboCtrl != NULL + && sboCtrl->ctlModel == MVL61850_CTLMODEL_SBO_ENHANCED) + { + /* ctlModel=sbo-with-enhanced-security. If sboClass=operate-once, */ + /* "unselect" now (i.e. free sboCtrl), else go back to READY state. */ + if (sboCtrl->sboClass == MVL61850_SBOCLASS_OPERATE_ONCE) + mvlu_sbo_ctrl_free (sboCtrl); /* like "UNSELECTED" state*/ + else + sboCtrl->ctlState = MVL61850_CTLSTATE_READY; + } + return (ret); + } + +/************************************************************************/ +/* mvl61850_ctl_lastapplerror_create */ +/* Create type to use later when "temporary" LastApplError var created. */ +/************************************************************************/ +ST_RET mvl61850_ctl_lastapplerror_create () + { +ST_RET retcode = SD_SUCCESS; +ST_CHAR *LastApplErrorTdl = "{\ + (CntrlObj)Vstring129,\ + (Error)Byte,\ + (Origin){(orCat)Byte,(orIdent)OVstring64},\ + (ctlNum)Ubyte,\ + (AddCause)Byte}"; + + /* Maybe this type was already created. If it does NOT exist, create it.*/ + if (mvl_typename_to_typeid ("LastApplErrorType") < 0) + { + if (mvl_type_id_create_from_tdl ("LastApplErrorType",LastApplErrorTdl) < 0) + retcode = SD_FAILURE; /* create failed */ + } + return (retcode); + } + +/************************************************************************/ +/* mvl61850_ctl_lastapplerror_send */ +/* Called by user to send "LastApplError" information report. */ +/************************************************************************/ +ST_RET mvl61850_ctl_lastapplerror_send (MVL_NET_INFO *net_info, + MVL61850_LAST_APPL_ERROR *last_appl_error) + { +OBJECT_NAME nvl_obj; /* NVL object name */ +MVL_NVLIST_CTRL *nvlist_ctrl; +ST_INT num_var; +OBJECT_NAME var_obj; /* temporary var object name */ +MVL_VAR_ASSOC *last_appl_var = NULL; /* var assoc for "LastApplError"*/ +ST_RET ret; +ST_INT type_id; + + ret = SD_SUCCESS; /* assume success */ + + /* Create tmp NVL used only for building this rpt. */ + nvl_obj.object_tag = VMD_SPEC; + nvl_obj.obj_name.vmd_spec = "tmp_nvl_for_rpt"; + + /* Fill in var_obj. */ + num_var = 1; + /* Create temporary VMD_SPEC "LastApplError" variable. */ + /* If this fails, mvl_vmd_nvl_add will also fail later. */ + type_id = mvl_typename_to_typeid ("LastApplErrorType"); + if (type_id >= 0) + { + var_obj.object_tag = VMD_SPEC; + var_obj.obj_name.vmd_spec = "LastApplError"; + /* NOTE: last_appl_error points to temporary data. This var must be deleted before returning*/ + last_appl_var = mvl_vmd_var_add (&mvl_vmd, &var_obj, + NULL, /* (MVL_NET_INFO *) */ + type_id, + last_appl_error, /* data ptr (saved in var->data) */ + NULL, /* (MVL_VAR_PROC *) */ + SD_FALSE); /* DO NOT copy the var name */ + + nvlist_ctrl = mvl_vmd_nvl_add (&mvl_vmd, &nvl_obj, NULL, /* net_info: not needed*/ + num_var, &var_obj, SD_TRUE); /* copy name */ + + /* Now send report */ + if (nvlist_ctrl) + { + ret = mvl_info_variables (net_info, nvlist_ctrl, SD_TRUE); /* listOfVariables*/ + mvl_vmd_nvl_remove (&mvl_vmd, &nvl_obj, NULL); /* done with tmp NVL */ + } + else + ret = SD_FAILURE; + } + else + ret = SD_FAILURE; + + /* If temporary "LastApplError" var created, destroy it now. */ + if (last_appl_var) + mvl_vmd_var_remove (&mvl_vmd, &var_obj, NULL); + + if (ret != SD_SUCCESS) + MVL_LOG_ERR0 ("Error sending LastApplError"); + return (ret); + } + +/************************************************************************/ +/* mvl61850_ctl_req_done */ +/* Do some necessary cleanup IF the MMS Write request represents an IEC */ +/* 61850 control request. */ +/* NOTE: For any other MMS Write request, this function does nothing. */ +/************************************************************************/ +ST_VOID mvl61850_ctl_req_done (MVLAS_WR_VA_CTRL *wrVaCtrl, MVL_NET_INFO *net_info) + + { +ST_INT8 ctlModel; +ST_BOOLEAN send_lastappl = SD_FALSE; +ST_CHAR flatname [MAX_IDENT_LEN+1]; +ST_CHAR *lastdollar; /* ptr to last '$' in variable name */ +MVL_SBO_CTRL *sboCtrl; /* ptr to SBO control if this is SBO */ + + /* CRITICAL: make sure variable was found before doing anything else. */ + if (wrVaCtrl->va == NULL) + return; /* var not found. Do nothing. */ + + lastdollar = strrchr (wrVaCtrl->va->name, '$'); /* find last '$'*/ + + /* If Write failed, and Var is IEC 61850 Oper, Cancel, or SBOw, */ + /* must also send InformationReport containing LastApplError. */ + if (wrVaCtrl->resp_tag == WR_RSLT_FAILURE) + { + /* Var name must end in $Oper, $Cancel, or $SBOw. */ + if (lastdollar != NULL) + { + /* Send LastApplError if writing Cancel or SBOw. */ + if (strcmp (lastdollar+1, "Cancel") == 0 || + strcmp (lastdollar+1, "SBOw") == 0) + send_lastappl = SD_TRUE; + /* Send LastApplError if writing Oper AND Enhanced security. */ + else if (strcmp (lastdollar+1, "Oper") == 0) + { + /* Generate "ctlModel" leaf name like "CF$...$ctlModel" from */ + /* variable name "...$Oper" and try to read its value. */ + if (mvl61850_mkname_ctlmodel (wrVaCtrl->va->name, flatname, MAX_IDENT_LEN) != SD_SUCCESS + || mvlu_get_leaf_val_int8 (wrVaCtrl->va->base_va, flatname, &ctlModel) != SD_SUCCESS) + ctlModel = MVL61850_CTLMODEL_STATUS_ONLY; /* can't read ctlModel. assume status-only*/ + /*renxiaobao ¿ØÖÆ + //if (ctlModel == MVL61850_CTLMODEL_DIRECT_ENHANCED || + // ctlModel == MVL61850_CTLMODEL_SBO_ENHANCED) */ + send_lastappl = SD_TRUE; + } + if (send_lastappl) + { + /* Construct & send LastApplError info report.*/ + + /* Fill in "LastApplError" structure. */ + /* This function builds a string in "CntrlObj". */ + /* If it fails, the string is empty. */ +#if 1 + mvl61850_objref_create (wrVaCtrl->va->name, &wrVaCtrl->va_scope, wrVaCtrl->LastApplError.CntrlObj); +#else /* OLD WAY (similar but CntrlObj always ended in '$Oper'). */ + //mvl61850_sbo_create_sboname (wrVaCtrl->va, &wrVaCtrl->va_scope, wrVaCtrl->LastApplError.CntrlObj);//lnk±àÒëɾ³ý£¬Ô­Ç°ÖóÌÐòδʹÓà +#endif + /* Other members (Error, AddCause, Origin, ctlNum) already set by leaf functions.*/ + + /* If Error/AddCause not set yet, set default values. */ + if (wrVaCtrl->LastApplError.Error == 0) + { + wrVaCtrl->LastApplError.Error = 1; /* Unknown */ + wrVaCtrl->LastApplError.AddCause = 0; /* Unknown */ + } + mvl61850_ctl_lastapplerror_send (net_info, &wrVaCtrl->LastApplError); + } + } + } + /* Do special cleanup for IEC 61850 SBO controls. */ + /* If wrVaCtrl->sboCtrl != NULL, this var is SBO Oper or Cancel */ + /* (see startElWrites), so do appropriate SBO cleanup. */ + /* If this is a Cancel request, or if ctlModel=sbo-with-normal-security*/ + /* AND sboClass=operate-once, we must "unselect" the control */ + /* (i.e. free "sboCtrl"). */ + sboCtrl = wrVaCtrl->sboCtrl; + if (sboCtrl != NULL) + { + if (strcmp (lastdollar+1, "Cancel") == 0 + || (sboCtrl->ctlModel == MVL61850_CTLMODEL_SBO_NORMAL + && sboCtrl->sboClass == MVL61850_SBOCLASS_OPERATE_ONCE) ) + { + /* NOTE: for sbo-with-enhanced-security, this is done AFTER CommandTerm.*/ + mvlu_sbo_ctrl_free (sboCtrl); + wrVaCtrl->sboCtrl = NULL; /* reset this so free not done twice.*/ + } + } + } + diff --git a/mmslib/mvlu/mvl61850_rpt.c b/mmslib/mvlu/mvl61850_rpt.c new file mode 100644 index 0000000..5065bc6 --- /dev/null +++ b/mmslib/mvlu/mvl61850_rpt.c @@ -0,0 +1,1367 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2006-2006 All Rights Reserved */ +/* */ +/* MODULE NAME : mvl61850_rpt.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Code to support IEC 61850 Reporting as a Server. */ +/* */ +/* BUFFERING OF REPORTS: */ +/* For Buffered Report Controls, buffering is automatic (no user */ +/* intervention). For each BRCB, all reports are stored in a linked */ +/* list "rpt_list". Also, "rpt_list_next" points to the next report to */ +/* send. If all reports have been sent, rpt_list_next==NULL. */ +/* */ +/* The maximum number of bytes to store in the buffer is a */ +/* user-configurable parameter. When the maximum number of bytes is */ +/* exceeded, the oldest report in the buffer is discarded. */ +/* */ +/* The standard SISCO linked list functions are used for buffering. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl61850_brcb_rpt_save */ +/* mvl61850_brcb_rpt_send */ +/* mvl61850_brcb_rpt_lists_clean */ +/* mvl61850_brcb_client_service */ +/* mvl61850_urcb_client_service */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/30/08 JRB 10 For Ed2, save lastSentTimeOfEntry for BRCB. */ +/* Resync to oldest if all 0 written to EntryID.*/ +/* 06/04/08 JRB 09 Start buffering on power-up if DatSet attr */ +/* references existing DataSet (for 61850-7-2 Ed2)*/ +/* 05/15/08 JRB 08 Add mvl61850_integrity_timeout for 61850 only*/ +/* (does NOT scan data, just sends current data)*/ +/* 05/06/08 JRB 07 Fix memory leak after "PDU size" error. */ +/* 02/29/08 JRB 06 Create correct AA_SPEC or VMD_SPEC DatSet. */ +/* Reset cur_va_index, SubSeqNum when all_seg_done*/ +/* so retransmission starts with first va. */ +/* If dsNvl==NULL, do not service RCB. */ +/* 02/13/07 JRB 05 mvl61850_get_rcb: del unused net_info arg. */ +/* Use scan_rate to control scan timing. */ +/* Save TimeofEntry in "basrcb". */ +/* 11/30/06 JRB 04 Fix *_brcb_entryid_init so user can call it. */ +/* 10/10/06 JRB 03 Add mvl61850_rpt_ctrl_destroy_all. */ +/* 08/18/06 JRB 02 Disable debug printing. Clean up comments. */ +/* 08/09/06 JRB 01 New. Moved most 61850 Rpt code to here */ +/* with following changes: */ +/* New RPT functions just for 61850 (not UCA): */ +/* mvl61850_create_rpt_ctrl, mvl61850_free_rpt_ctrl,*/ +/* mvl61850_rpt_service. */ +/* Chg BRCB code to save "raw" data in buffer */ +/* and encode rpt only when sending. */ +/* Chg to one rpt list with ptr to next to send.*/ +/* ..urcb_client_service: First chk if connected.*/ +/* Put start time in first 4 bytes of EntryID. */ +/* When GI rpt buffered, discard old GI rpt. */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "mvl_acse.h" /* need mvl_cfg_info */ +#include "mvl_uca.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/* DEBUG: IEC 61850 is not clear about exactly how to handle "BufOvfl", + * so the code in this module implements the following: + * 1. If client writes EntryID & the value can't be found in the buffer, + * BufOvfl is set, an error is returned, and the oldest buffer entry will + * be sent next (see mvl61850_brcb_rpt_set_entryid). + * 2. If entry found but discarded before RptEna, + * BufOvfl is set, and the oldest buffer entry will + * be sent next (see buflist_discard_old). + * 3. If entries lost while connected, set BufOvfl (see buflist_discard_old). + * 4. After one report sent with BufOvfl, clear it + * (see mvl61850_brcb_client_service). + */ + +/************************************************************************/ +/* print macros for debugging */ +/************************************************************************/ +#if 0 /* DEBUG: enable to see queue activity. */ +/* Use function here (too complex for macro). */ +ST_VOID print_queues(MVL61850_BRCB_CTRL *brcbCtrl) + { + BUFLIST_ENTRY *entry; + printf ("REPORT BUFFER ('.'=rpt, '+'=next_to_send)"); + for (entry = brcbCtrl->rpt_list; + entry != NULL; + entry = (BUFLIST_ENTRY *) list_get_next (brcbCtrl->rpt_list, entry)) + { + if (entry == brcbCtrl->rpt_list_next) + putchar('+'); + else + putchar('.'); + } + putchar('\n'); + } +#define print_msg0(fmt) printf (fmt) +#define print_msg1(fmt,a) printf (fmt,a) +#else +#define print_queues(brcbCtrl) +#define print_msg0(fmt) +#define print_msg1(fmt,a) +#endif + +/************************************************************************/ +/* mvl61850_mk_rptid */ +/* Construct RptID from info in rptCtrl. */ +/* RETURNS: SD_SUCCESS or SD_FAILURE */ +/* Also on error, put a NULL string in RptID & log error. */ +/************************************************************************/ +ST_RET mvl61850_mk_rptid (MVLU_RPT_CTRL *rptCtrl, ST_CHAR *RptID, size_t max_len) + { +ST_RET retcode; + + /* If domname + '/' + basrcb_name will fit in RptID, then write it. */ + if (strlen (rptCtrl->dsNvl->nvl_scope.dom->name) + strlen (rptCtrl->basrcb_name) + 1 <= max_len) + { + sprintf (RptID, "%s/%s", rptCtrl->dsNvl->nvl_scope.dom->name, + rptCtrl->basrcb_name); + retcode = SD_SUCCESS; + } + else + { + MVL_LOG_ERR0 ("Cannot construct RptID (too long)"); /* should NEVER happen*/ + RptID [0] = '\0'; /* return empty RptID */ + retcode = SD_FAILURE; + } + return (retcode); + } + +/************************************************************************/ +/* mvl61850_mk_dataref */ +/************************************************************************/ +ST_VOID mvl61850_mk_dataref (MVL_VAR_ASSOC *va, MVL_SCOPE *va_scope, + ST_CHAR *databuf, ST_INT maxlen) + { + if (va_scope->scope == DOM_SPEC) + { + strcpy (databuf, va_scope->dom->name); + strcat (databuf, "/"); + } + else if (va_scope->scope == VMD_SPEC) + strcpy (databuf, "/"); + else /* must be AA_SPEC */ + strcpy (databuf, "@"); + strncat (databuf, va->name, maxlen - strlen (databuf)); + } + +/************************************************************************/ +/* mvl61850_rcb_cleanup */ +/* Cleanup RPT info to prepare for next report. */ +/************************************************************************/ +ST_VOID mvl61850_rcb_cleanup (MVLU_RPT_CLIENT *rptClient) + { +MVL_NVLIST_CTRL *dsNvl; +ST_INT incSize; /* num bytes for inclusion bitstring */ + dsNvl = rptClient->rpt_ctrl->dsNvl; + incSize = BSTR_NUMBITS_TO_NUMBYTES(dsNvl->num_of_entries); + /* Reset reasons, etc. to prepare for new report triggers. */ + memset (rptClient->reasons_data, 0, dsNvl->num_of_entries); + memset (rptClient->changed_flags, 0, incSize); + rptClient->numTrgs = 0; + } + +/************************************************************************/ +/* mvl61850_brcb_rpt_set_entryid */ +/************************************************************************/ +ST_RET mvl61850_brcb_rpt_set_entryid (MVLU_RPT_CLIENT *rptClient, ST_UCHAR *EntryID) + { +BUFLIST_ENTRY *entry; +BUFLIST_ENTRY *foundEntry = NULL; /* matching entry, assume NULL (not found)*/ +MVL61850_BRCB_CTRL *brcbCtrl; +ST_RET retcode = SD_FAILURE; /* assume failure */ +ST_UCHAR all_zero[8]={0,0,0,0,0,0,0,0}; + + /* Assume this is a BRCB. Should never get here otherwise. */ + assert (rptClient->rpt_ctrl->rcb_type == RCB_TYPE_IEC_BRCB); + brcbCtrl = &rptClient->rpt_ctrl->brcbCtrl; + + /* Is client writing all 0? */ + if (memcmp (all_zero, EntryID, 8) == 0) + { /* special case. Just resync to oldest rpt in buffer */ + brcbCtrl->rpt_list_next = brcbCtrl->rpt_list; /* oldest */ + return (SD_SUCCESS); /* this can never fail*/ + } + + /* Search "sent" list for this ID. */ + /* If "rpt_list_next != NULL" start search there. */ + /* If "rpt_list_next == NULL" start search at end of list. */ + if (brcbCtrl->rpt_list_next) + entry = brcbCtrl->rpt_list_next; + else + entry = (BUFLIST_ENTRY *) list_find_last ((DBL_LNK *) brcbCtrl->rpt_list); + for ( ; + entry != NULL; + entry = (BUFLIST_ENTRY *) list_find_prev ((DBL_LNK *) brcbCtrl->rpt_list, (DBL_LNK *) entry)) + { + + if (memcmp (entry->EntryID, EntryID, 8) == 0) + { + foundEntry = entry; + break; + } + } + /* If matching entry found, just point to next one. */ + if (foundEntry) + { + brcbCtrl->rpt_list_next = list_get_next (brcbCtrl->rpt_list, entry); + retcode = SD_SUCCESS; + } + else + { /* not found, point to "oldest" rpt */ + if((entry = brcbCtrl->rpt_list_next)) + printf("next_entry =%02x%02x%02x%02x%02x%02x%02x%02x\n\r",entry->EntryID[0],entry->EntryID[1],entry->EntryID[2], + entry->EntryID[3],entry->EntryID[4],entry->EntryID[5],entry->EntryID[6],entry->EntryID[7]); + if((entry = (BUFLIST_ENTRY *) list_find_last ((DBL_LNK *) brcbCtrl->rpt_list))) + printf("last_entry=%02x%02x%02x%02x%02x%02x%02x%02x\n\r",entry->EntryID[0],entry->EntryID[1],entry->EntryID[2], + entry->EntryID[3],entry->EntryID[4],entry->EntryID[5],entry->EntryID[6],entry->EntryID[7]); + printf("find_entry=%02x%02x%02x%02x%02x%02x%02x%02x\n\r",EntryID[0],EntryID[1],EntryID[2],EntryID[3], + EntryID[4],EntryID[5],EntryID[6],EntryID[7]); + + brcbCtrl->rpt_list_next = brcbCtrl->rpt_list; /* oldest */ + brcbCtrl->BufOvfl = SD_TRUE; /* overflow occurred */ + } + + return (retcode); + } + +/************************************************************************/ +/* fill_asn1_len_array */ +/* Compute the ASN.1 encoded len for each var in a rpt dataset, and */ +/* fill in "bufEntry->asn1_len_array". */ +/************************************************************************/ +static ST_RET fill_asn1_len_array ( + BUFLIST_ENTRY *bufEntry, + MVL_NVLIST_CTRL *dsNvl) /* rpt dataset */ + { +ST_UCHAR *tmp_asn1_buf; /* temporary ASN.1 buffer (allocated) */ +ST_INT tmp_asn1_buf_size = mvl_cfg_info->max_msg_size; /* reasonable size*/ +ST_INT j; +ST_RET retCode=SD_SUCCESS; /* assume success */ + + tmp_asn1_buf = chk_malloc (tmp_asn1_buf_size); + for (j = 0; j < dsNvl->num_of_entries; ++j) + { + if (bufEntry->var_data[j].reason_for_incl != 0) + { /* this var should be included in rpt */ + ST_UCHAR *asn1_ptr; + MVL_TYPE_CTRL *type_ctrl = dsNvl->entries[j]->type_ctrl; + + retCode = ms_local_to_asn1_2 (type_ctrl->rt, type_ctrl->num_rt, + bufEntry->var_data[j].data_ptr, /* CRITICAL: use data from buffer entry*/ + tmp_asn1_buf, + tmp_asn1_buf_size, + &asn1_ptr, /* function sets asn1_ptr (not needed here)*/ + &bufEntry->asn1_len_array[j]); /* function sets len at this ptr*/ + if (retCode) + { + /* Should NEVER fail, but if so, don't continue with other vars.*/ + break; + } + } + } /* end loop */ + chk_free (tmp_asn1_buf); + return (retCode); + } + +/************************************************************************/ +/* buflist_entry_create */ +/* Allocate and initialize BUFLIST_ENTRY and add it to list. */ +/* Also update brcbCtrl->cur_bufsize & brcbCtrl->rpt_count. */ +/************************************************************************/ +BUFLIST_ENTRY *buflist_entry_create (MVLU_RPT_CLIENT *rptClient) + { +BUFLIST_ENTRY *bufEntry; +MVL_NVLIST_CTRL *dsNvl = rptClient->rpt_ctrl->dsNvl; +ST_INT j; +int num; +MVL61850_BRCB_CTRL *brcbCtrl = &rptClient->rpt_ctrl->brcbCtrl; + + bufEntry = (BUFLIST_ENTRY *) chk_calloc (1, sizeof (BUFLIST_ENTRY)); + bufEntry->num_var = dsNvl->num_of_entries; + /* Use calloc so start out with all data_ptr=NULL & all reason_for_incl=0.*/ + bufEntry->var_data = (VAR_DATA *) chk_calloc (bufEntry->num_var, + sizeof (VAR_DATA)); + bufEntry->asn1_len_array = chk_calloc (dsNvl->num_of_entries, sizeof(ST_INT)); + + for (j = 0; j < bufEntry->num_var; j++) + { + /* Check "reason for inclusion". */ + if (rptClient->reasons_data[j] != 0) + { /* this var must be in the report */ + ST_INT data_len; + MVL_VAR_ASSOC *var_assoc = dsNvl->entries[j]; + MVL_TYPE_CTRL *type_ctrl = dsNvl->entries[j]->type_ctrl; + VAR_DATA *var_data = &bufEntry->var_data[j]; + + /* Find data_len */ + data_len = type_ctrl->data_size; + + brcbCtrl->cur_bufsize += data_len; /* update buffer size*/ + var_data->data_len = data_len; + var_data->data_ptr = chk_malloc (data_len); + memcpy (var_data->data_ptr, var_assoc->data, data_len); + /* Save "reason for inclusion". */ + var_data->reason_for_incl = rptClient->reasons_data[j]; + } + } + + /* Fill in other entry data. */ + /* Point to last 4 bytes of Ostring, cast to INT32 & increment.*/ +#ifdef WIN32 + num = ((int)rptClient->basrcb.EntryID[7]<<0 )+ + ((int)rptClient->basrcb.EntryID[6]<<8 )+ + ((int)rptClient->basrcb.EntryID[5]<<16)+ + ((int)rptClient->basrcb.EntryID[4]<<24); + num++; + rptClient->basrcb.EntryID[7] = (ST_UCHAR)(num>>0); + rptClient->basrcb.EntryID[6] = (ST_UCHAR)(num>>8); + rptClient->basrcb.EntryID[5] = (ST_UCHAR)(num>>16); + rptClient->basrcb.EntryID[4] = (ST_UCHAR)(num>>24); +#else + ++(*(ST_INT32 *)(&rptClient->basrcb.EntryID[4])); +#endif + /* Then copy to bufEntry. */ + memcpy (bufEntry->EntryID, rptClient->basrcb.EntryID, 8); + /* Call user function to get report time. */ + u_mvlu_rpt_time_get (&bufEntry->TimeOfEntry); + /* Copy report time to RCB. */ + memcpy (&rptClient->basrcb.TimeofEntry, &bufEntry->TimeOfEntry, sizeof (MMS_BTIME6)); + + /* Fill in "bufEntry->asn1_len_array", needed later by "chk_seg_needed". */ + if (fill_asn1_len_array (bufEntry, dsNvl)!=SD_SUCCESS) + { + /* NOTE: This should NEVER fail, but if it does, just log it. */ + /* Real encode will almost certainly fail later. */ + MVL_LOG_ERR0 ("Cannot calculate ASN.1 length for Buffered Report."); + } + + /* Add entry to list. */ + list_add_last (&brcbCtrl->rpt_list, bufEntry); + brcbCtrl->rpt_count++; /* Update list count */ + + /* If next ptr is NULL (all old rpts sent), point to this new entry.*/ + if (brcbCtrl->rpt_list_next == NULL) + brcbCtrl->rpt_list_next = bufEntry; + + return (bufEntry); + } + +/************************************************************************/ +/* buflist_entry_destroy */ +/* Remove BUFLIST_ENTRY from list and free it. */ +/* Also update brcbCtrl->cur_bufsize & brcbCtrl->rpt_count. */ +/************************************************************************/ +ST_VOID buflist_entry_destroy (MVL61850_BRCB_CTRL *brcbCtrl, BUFLIST_ENTRY *entry) + { +ST_INT j; + if (entry == brcbCtrl->rpt_list_next) + { + /* Deleting next rpt to send. */ + /* CRITICAL: must fix up next to send. */ + brcbCtrl->rpt_list_next = list_get_next (brcbCtrl->rpt_list, entry); + } + + list_unlink (&brcbCtrl->rpt_list, entry); /* remove rpt from list */ + brcbCtrl->rpt_count--; /* update list count */ + /* Free all in reverse order. */ + for (j = 0; j < entry->num_var; j++) + { + VAR_DATA *var_data = &entry->var_data[j]; + if (var_data->data_ptr) + { + chk_free (var_data->data_ptr); + brcbCtrl->cur_bufsize -= var_data->data_len; /* update buffer size*/ + } + } + chk_free (entry->asn1_len_array); + chk_free (entry->var_data); + chk_free (entry); + } + +/************************************************************************/ +/* buflist_discard_old_gi */ +/* Search for old GI report in buffer, and delete it. */ +/************************************************************************/ +ST_VOID buflist_discard_old_gi (MVL61850_BRCB_CTRL *brcbCtrl) + { +BUFLIST_ENTRY *entry; + for (entry = brcbCtrl->rpt_list; + entry != NULL; + entry = list_get_next (brcbCtrl->rpt_list, entry)) + { + /* For GI rpt, "reason_for_incl" for all vars is MVLU_TRGOPS_GI, */ + /* so just check reason for first var. */ + if (entry->var_data[0].reason_for_incl == MVLU_TRGOPS_GI) + { + /* Remove entry from list and free it. */ + buflist_entry_destroy (brcbCtrl, entry); + break; /* never more than one GI, so stop looping now */ + } + } + } + +/************************************************************************/ +/* buflist_discard_old */ +/* If memory usage exceeds buffer size, remove oldest reports from list */ +/* until memory usage is reduced. */ +/************************************************************************/ +ST_VOID buflist_discard_old (MVL61850_BRCB_CTRL *brcbCtrl) + { +BUFLIST_ENTRY *entry; + while (brcbCtrl->cur_bufsize > brcbCtrl->brcb_bufsize) + { + entry = brcbCtrl->rpt_list; /* find first on list */ + if (entry != NULL) + { + if (entry == brcbCtrl->rpt_list_next) + { + /* Deleting next rpt to send (i.e. rpts are being lost). */ + /* Set BufOvfl flag. */ + brcbCtrl->BufOvfl = SD_TRUE; + brcbCtrl->rpts_lost_count++; /* keep a count of lost reports */ + } + /* Remove entry from list and free it. */ + buflist_entry_destroy (brcbCtrl, entry); + } + else + { /* This error should never happen. Buffer is much too small.*/ + MVL_LOG_ERR0 ("Report buffer size too small to store any reports."); + } + } /* end loop */ + } + +/************************************************************************/ +/* mvl61850_brcb_rpt_lists_clean */ +/* Delete and destroy all entries on the buffered report linked list */ +/* for this BRCB. */ +/************************************************************************/ +ST_VOID mvl61850_brcb_rpt_lists_clean (MVL61850_BRCB_CTRL *brcbCtrl) + { +BUFLIST_ENTRY *entry; + /* Loop removing first entry from list. */ + while ((entry = brcbCtrl->rpt_list) != NULL) + buflist_entry_destroy (brcbCtrl, entry); /* removes it from list*/ + + assert (brcbCtrl->rpt_list_next == NULL); /* if list empty, this must be NULL*/ + + if (brcbCtrl->rpt_count != 0 || brcbCtrl->cur_bufsize != 0) + { + MVL_LOG_ERR2 ("ERROR removing buffered reports from list (count=%d, bufsize=%d). Possible memory leak.", + brcbCtrl->rpt_count, brcbCtrl->cur_bufsize); + brcbCtrl->rpt_count = 0; /* reset count */ + brcbCtrl->cur_bufsize = 0; /* reset buffer size */ + } + brcbCtrl->BufOvfl = SD_FALSE; /* Clear BufOvfl flag */ + brcbCtrl->rpt_list_next = NULL; /* CRITICAL: must not point to deleted entry*/ + } + +/************************************************************************/ +/* mvl61850_brcb_rpt_save */ +/* For BRCB, just buffer the raw data in a linked list to be encoded */ +/* and sent later (see mvl61850_brcb_rpt_send). */ +/************************************************************************/ +ST_RET mvl61850_brcb_rpt_save (MVLU_RPT_CLIENT *rptClient) + { + /* If this is GI rpt, discard previous GI rpt from buffer before */ + /* saving new one in buffer. */ + if (rptClient->reasons_data[0] == MVLU_TRGOPS_GI) + buflist_discard_old_gi (&rptClient->rpt_ctrl->brcbCtrl); + + buflist_entry_create (rptClient); /* add rpt to buffer */ + + /* If buffer is full, discard oldest reports until not full. */ + buflist_discard_old (&rptClient->rpt_ctrl->brcbCtrl); + mvl61850_rcb_cleanup (rptClient); /* prepare for next RPT. */ + return (SD_SUCCESS); + } + +/************************************************************************/ +/* mvl61850_brcb_rpt_send */ +/* Encode and send a Buffered Report (possibly in multiple segments). */ +/* NOTE: This is similar to mvl61850_urcb_rpt_send. The main difference */ +/* is that it gets most data from the BUFLIST_ENTRY struct. */ +/* NOTE: DOES NOT use rptClient->reasons_data, rptClient->changed_flags,*/ +/* rptClient->numTrgs. Use "reason_for_incl" from BUFLIST_ENTRY */ +/* to construct inclusion bitstring. */ +/************************************************************************/ +ST_RET mvl61850_brcb_rpt_send (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + BUFLIST_ENTRY *bufEntry, + ST_BOOLEAN *all_seg_done) + { +MVL_NVLIST_CTRL *dsNvl; +MVL_NVLIST_CTRL *rptNvl; +MVL_VAR_ASSOC *va; +ST_INT j; /* loop counter */ +ST_RET retCode; +ST_INT sendIndex; +ST_INT sendIndexSave; /* save index before data, compare after data */ +ST_UINT8 *optFlds; +MVLU_BASRCB *basrcb; +ST_INT incSize; /* num bytes for inclusion bitstring */ +MVL_VAR_ASSOC *tmp_va_arr; /* alloc array of structs */ +ST_INT tmp_va_arr_size; /* num of entries in tmp_va_arr */ +MVL_VAR_ASSOC *tmp_va; /* current entry in tmp_va_arr */ +/* For Segmented reports, all segments are generated by this function, + * so these parameters can be local variables. + */ +ST_INT next_va_index; /* index into dsNvl va array */ +ST_BOOLEAN segNeeded; /* If TRUE, segmenting needed */ +ST_BOOLEAN MoreSegmentsFollow; +ST_CHAR *tmp_dataref_buf; +ST_CHAR tmpRptID [MVL61850_MAX_RPTID_LEN+1]; + + + retCode = SD_SUCCESS; /* assume success. Change if error detected.*/ + *all_seg_done = SD_FALSE; /* initialize flag */ + + basrcb = &rptClient->basrcb; + + optFlds = basrcb->OptFlds.data_1; + dsNvl = rptCtrl->dsNvl; + rptNvl = &rptCtrl->rptNvl; + + incSize = BSTR_NUMBITS_TO_NUMBYTES(dsNvl->num_of_entries); + + MVLU_LOG_FLOW1 ("Building IEC-61850 BRCB Report, MVL_NET_INFO %08lx", rptClient->netInfo); + + /* Need tmp va's for options, array of data_refs, array of dataset vars,*/ + /* array of reason_for_incl. */ + tmp_va_arr_size = MVLU_MAX_RPT_OPTS + (dsNvl->num_of_entries * 3); + tmp_va_arr = M_CALLOC (MSMEM_GEN, sizeof (MVL_VAR_ASSOC), tmp_va_arr_size); + + /* Need tmp buffer for datarefs. One buffer for all. */ + /* Allow max len plus NULL for each dataref. */ + tmp_dataref_buf = M_CALLOC (MSMEM_GEN, (MVL61850_MAX_OBJREF_LEN+1), dsNvl->num_of_entries); + + assert (rptCtrl->dsNvl->num_of_entries); /* must be >0 entries */ + + /* MAIN LOOP */ + /* Start with "bufEntry->cur_va_index" and "bufEntry->SubSeqNum".*/ + /* Usually they are both 0, but if segmenting occurs and buffers were */ + /* not available to send all segments, they indicate what is next. */ + for (next_va_index = bufEntry->cur_va_index; + next_va_index < rptCtrl->dsNvl->num_of_entries; + bufEntry->cur_va_index = next_va_index, bufEntry->SubSeqNum++) + { /* BEGIN MAIN LOOP */ + if (retCode) + break; /* something failed in this loop or earlier loop, so stop now.*/ + + /* If buffers not available, break out of loop. */ + /* Use cur_va_index, SubSeqNum in bufEntry as starting point */ + /* next time this function is called. */ + if (mvl_ureq_bufs_avail (rptClient->netInfo) <= 0) /* stack bufs avail to send rpt */ + break; + + tmp_va = tmp_va_arr; /* start loop pointing to first entry */ + sendIndex = 0; /* start with first rptNvl->entries. */ + + /* Prepare a Report NVL to be sent, based on the */ + /* options, data, and inclusion bitstring in the rptCtrl. */ + + /* CRITICAL: asn1_len_array must be filled in before call to chk_seg_needed.*/ + segNeeded = chk_seg_needed (rptClient, bufEntry->asn1_len_array, bufEntry->cur_va_index, &next_va_index); + + if (next_va_index - bufEntry->cur_va_index == 0) + { + MVL_LOG_ERR0 ("MMS PDU size too small to fit ANY variables in IEC-61850 Report. Report not sent."); + retCode = SD_FAILURE; + break; /* break out of loop so normal cleanup occurs. */ + } + + /* We will create a NVL to send, using the dsNvl as a model ... */ + + /* RptID and OptFlds are always the first 2 entries in the Rpt NVL. */ + + /* Get RptID from RCB (OK because changing it causes PurgeBuf). */ + tmp_va->type_id = rptCtrl->rpt_typeids.vstring65; + if (basrcb->RptID [0] == '\0') + { /* RptID not set in RCB, so construct it. */ + mvl61850_mk_rptid (rptCtrl, tmpRptID, MVL61850_MAX_RPTID_LEN); + tmp_va->data = tmpRptID; + } + else + tmp_va->data = basrcb->RptID; + MVLU_LOG_CFLOW1 (" RptID='%s", tmp_va->data); /* log before tmp_va++*/ + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + + /* Get OptFlds from RCB (OK because changing it causes PurgeBuf). */ + tmp_va->type_id = rptCtrl->rpt_typeids.bvstring10; + tmp_va->data = &basrcb->OptFlds; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + MVLU_LOG_CFLOW2 (" OptFld = 0x%02x 0x%02x", basrcb->OptFlds.data_1[0], + basrcb->OptFlds.data_1[1]); /* 10 bit bstr (2 bytes) */ + + /* Add optional RCB vars to NVL, depending on OptFlds. */ + + /* Get SqNum from RCB. */ + if (BSTR_BIT_GET(optFlds, OPTFLD_BITNUM_SQNUM)) + { + assert (rptCtrl->rcb_type == RCB_TYPE_IEC_BRCB); + /* SqNum in BRCB is INT16U */ + tmp_va->type_id = rptCtrl->rpt_typeids.int16u; + tmp_va->data = &basrcb->SqNumInt16u; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + MVLU_LOG_CFLOW1 (" SqNum : %u", (unsigned) basrcb->SqNumInt16u); + } + + /* Get TimeofEntry from BUFLIST_ENTRY. */ + if (BSTR_BIT_GET(optFlds, OPTFLD_BITNUM_TIMESTAMP)) + { + MVLU_LOG_CFLOW2 (" RptTim : %lums, %lu days", + bufEntry->TimeOfEntry.ms, bufEntry->TimeOfEntry.day); + + tmp_va->type_id = rptCtrl->rpt_typeids.btime6; + tmp_va->data = &bufEntry->TimeOfEntry; /* use time saved in buffer*/ + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + + /* Get DatSet from RCB (OK because changing it causes PurgeBuf). */ + if (BSTR_BIT_GET(optFlds, OPTFLD_BITNUM_DATSETNAME)) + { + /* UCA called it OutDat instead of DatSet. Value is same. */ + MVLU_LOG_CFLOW1 (" DatSet : %s", basrcb->DatSetNa); + tmp_va->type_id = rptCtrl->rpt_typeids.vstring129; /*ObjectReference*/ + tmp_va->data = basrcb->DatSetNa; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + + /* Get BufOvfl. */ + if (BSTR_BIT_GET(optFlds, OPTFLD_BITNUM_BUFOVFL)) + { + tmp_va->type_id = rptCtrl->rpt_typeids.mmsbool; + tmp_va->data = &rptCtrl->brcbCtrl.BufOvfl; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + + /* Get EntryID from BUFLIST_ENTRY. */ + if (BSTR_BIT_GET(optFlds, OPTFLD_BITNUM_ENTRYID)) + { + /* NOTE: EntryID only incremented when RPT buffered. */ + /* Copied to bufEntry->EntryID after incrementing. */ + tmp_va->type_id = rptCtrl->rpt_typeids.ostring8; + tmp_va->data = bufEntry->EntryID; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + + /* Add "ConfRev" if enabled by "OptFlds". */ + if (BSTR_BIT_GET(optFlds, OPTFLD_BITNUM_CONFREV)) + { + tmp_va->type_id = rptCtrl->rpt_typeids.int32u; + tmp_va->data = &basrcb->ConfRev; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + + if(segNeeded) + printf("brcb:segNeeded=%d num=%d va_index = %d->%d\r\n", + segNeeded,rptCtrl->dsNvl->num_of_entries,bufEntry->cur_va_index, next_va_index); + + if (segNeeded) + { + /* Set appropriate bit in OptFlds. */ + /* NOTE: this bit only for output. Never used as input. */ + BSTR_BIT_SET_ON (optFlds,OPTFLD_BITNUM_SUBSEQNUM); + + tmp_va->type_id = rptCtrl->rpt_typeids.int16u; + tmp_va->data = &bufEntry->SubSeqNum; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + + if (next_va_index < rptCtrl->dsNvl->num_of_entries) + MoreSegmentsFollow = SD_TRUE; + else + MoreSegmentsFollow = SD_FALSE; + + tmp_va->type_id = rptCtrl->rpt_typeids.mmsbool; + tmp_va->data = &MoreSegmentsFollow; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + else + { + BSTR_BIT_SET_OFF (optFlds,OPTFLD_BITNUM_SUBSEQNUM); + } + + /* Construct inclusion bitstring using "reason_for_incl" in BUFLIST_ENTRY. */ + tmp_va->type_id = rptCtrl->inclusion_typeid; + /* just set the bits included in this segment. */ + memset (rptClient->segmented_inclusion, 0, incSize); /* start clean */ + for (j = bufEntry->cur_va_index; j < next_va_index; ++j) + { + if (bufEntry->var_data[j].reason_for_incl) + BSTR_BIT_SET_ON (rptClient->segmented_inclusion, j); + } + tmp_va->data = rptClient->segmented_inclusion; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + + /* If data-Ref enabled, go through inclusion_data to decide what to send*/ + if (BSTR_BIT_GET(optFlds, OPTFLD_BITNUM_DATAREF)) + { + for (j = bufEntry->cur_va_index; j < next_va_index; ++j) + { + if (bufEntry->var_data[j].reason_for_incl) + { /* include dataRef for this variable */ + tmp_va->type_id = rptCtrl->rpt_typeids.vstring129; /*ObjectReference*/ + /* point to right part of tmp buffer & construct dataref */ + tmp_va->data = &tmp_dataref_buf [j * (MVL61850_MAX_OBJREF_LEN+1)]; + mvl61850_mk_dataref (dsNvl->entries[j], &dsNvl->va_scope[j], + tmp_va->data, MVL61850_MAX_OBJREF_LEN); + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + } + } + + /* HERE'S DATA: Go through inclusion_data to decide what to send */ + sendIndexSave = sendIndex; /* save index before data included */ + for (j = bufEntry->cur_va_index; j < next_va_index; ++j) + { + if (bufEntry->var_data[j].reason_for_incl) + { /* include this variable */ + va = dsNvl->entries[j]; + tmp_va->data = bufEntry->var_data[j].data_ptr; /* buffered data*/ + tmp_va->type_id = va->type_id; + MVLU_LOG_CFLOW3 (" Including variable %d ('%s'), reason_for_incl=0x%02X", + j, va->name, bufEntry->var_data[j].reason_for_incl); + rptNvl->entries[sendIndex++] = tmp_va++; + } + } + assert (sendIndex>sendIndexSave); /* make sure SOME data included */ + + /* If "reason" enabled, go through inclusion_data to decide what to send*/ + if (BSTR_BIT_GET(optFlds, OPTFLD_BITNUM_REASON)) + { + for (j = bufEntry->cur_va_index; j < next_va_index; ++j) + { + if (bufEntry->var_data[j].reason_for_incl) + { /* include reason for this variable */ + /* Don't need BVSTR here, because size is fixed. */ + tmp_va->type_id = rptCtrl->rpt_typeids.bstr6; + tmp_va->data = &bufEntry->var_data[j].reason_for_incl; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + } + } + rptNvl->num_of_entries = sendIndex; + assert (rptNvl->num_of_entries <= rptCtrl->maxNumRptVars); /* past end of array?*/ + assert ((tmp_va-tmp_va_arr) <= tmp_va_arr_size); /* past end of array?*/ + + /* Encode the InformationReport and send it. */ + retCode = mvl_info_variables (rptClient->netInfo, + rptNvl, + SD_FALSE); /* FALSE means "send as NVL" */ + } /* END MAIN LOOP */ + + /* Did we send all segments of this report? */ + if (retCode == SD_SUCCESS && bufEntry->cur_va_index == rptCtrl->dsNvl->num_of_entries) + { + *all_seg_done = SD_TRUE; /* YES: Set flag */ + /* CRITICAL: Reset these to be ready for retransmit later. */ + bufEntry->cur_va_index = 0; + bufEntry->SubSeqNum = 0; + } + + M_FREE (MSMEM_GEN, tmp_va_arr); + M_FREE (MSMEM_GEN, tmp_dataref_buf); + return (retCode); + } + +/************************************************************************/ +/* mvl61850_brcb_enable_all */ +/* Start buffering all buffered reports. */ +/************************************************************************/ +ST_VOID mvl61850_brcb_enable_all () + { +MVLU_RPT_CTRL *rptCtrl; + + for (rptCtrl = mvl61850_rpt_ctrl_list; + rptCtrl != NULL; + rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvl61850_rpt_ctrl_list, rptCtrl)) + { + if (rptCtrl->rcb_type == RCB_TYPE_IEC_BRCB) + rptCtrl->brcbCtrl.enabled_once = SD_TRUE; + } + } + +/************************************************************************/ +/* mvl61850_brcb_entryid_init */ +/* Set initial value of EntryID for this BRCB. EntryID must point to */ +/* an 8 byte octet string. */ +/************************************************************************/ +ST_VOID mvl61850_brcb_entryid_init (MVLU_RPT_CTRL *rptCtrl, ST_UINT8 *EntryID) + { + memcpy (rptCtrl->only_client.basrcb.EntryID, EntryID, 8); + } + +/************************************************************************/ +/* mvl61850_rpt_change_scan_va_done */ +/* Used by code that scans for dchg, qchg, dupd changes. */ +/* This function is called by 'mvlu_rd_prim_done' when all "leaf" */ +/* functions for a VA have been completed (i.e. data ready for this VA).*/ +/************************************************************************/ +void mvlu_log_va_change (MVL_VAR_ASSOC *va, ST_UCHAR reason, ST_VOID *new_data); +ST_VOID mvl61850_rpt_change_scan_va_done (MVL_IND_PEND *indCtrl, + MVL_VAR_ASSOC *va) + { + /* If "rpt_reason" set by ANY leaf function, call mvlu_rpt_va_change. */ + if (va->rpt_reason) + { + mvlu_rpt_va_change (va, va->rpt_reason, NULL); + /*renxiaobao ÈÕÖ¾ + //mvlu_log_va_change (va, va->rpt_reason, NULL);*/ + } + } + +/************************************************************************/ +/* mvl61850_rpt_change_scan_done */ +/* Used by code that scans for dchg, qchg, dupd changes. */ +/* This function is called when the scan is complete. */ +/* (i.e. 'mvlu_rd_prim_done' has been called for all "leafs" of all */ +/* variables in the report). Everything is ready to build a report, */ +/* so build it now. */ +/* CRITICAL: when all done, this function must free the temporary */ +/* MVL_IND_PEND struct by calling "mvlu_integrity_scan_destroy". */ +/************************************************************************/ +ST_RET mvl61850_rpt_change_scan_done (MVL_IND_PEND *indCtrl) + { +ST_RET retCode = SD_SUCCESS; /* nothing to fail here */ + + /* NOTE: not much to do here. DO NOT send reports. */ + /* mvlu_rpt_service chks numTrgs & BufTim & sends when needed. */ + + /* CRITICAL: free the temporary MVL_IND_PEND struct. */ + mvlu_integrity_scan_destroy (indCtrl); + return (retCode); + } + +/************************************************************************/ +/* mvl61850_rpt_change_scan */ +/* Scan all IEC 61850 Report Datasets for dchg, qchg, dupd. */ +/************************************************************************/ +/*renxiaobao ±¨¸æ*/ +ST_VOID mvl61850_rpt_change_scan (char *dom,char CHG) +/*ST_VOID mvl61850_rpt_change_scan (ST_VOID)*/ + { +MVLU_RPT_CTRL *rptCtrl; +MVL_NVLIST_CTRL *dsNvl; +ST_INT j; +ST_DOUBLE timeNow; +short rpt_num=0; + + /* Reset "already_scanned=SD_FALSE" for each NVL. */ + /* Reset it for every NVL, even if not enabled (faster). */ + for(rptCtrl = mvl61850_rpt_ctrl_list; + rptCtrl!= NULL; + rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvl61850_rpt_ctrl_list, rptCtrl)) + { + if(dom&&strcmp(rptCtrl->dsNvl->va_scope->dom->name,dom)) continue; + dsNvl = rptCtrl->dsNvl; + if (dsNvl) /* dsNvl might be NULL */ + { + dsNvl->already_scanned = SD_FALSE; + } + rpt_num++; + } + if(!rpt_num) return; + timeNow = sGetMsTime (); /* get time just once. Use it in loop. */ + /* Loop through all Report NVLs to scan for data changes. */ + /* Set already_scanned=SD_TRUE for each NVL. If same NVL used in another */ + /* Report, do NOT rescan it. */ + for(rptCtrl = mvl61850_rpt_ctrl_list; + rptCtrl!= NULL; + rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvl61850_rpt_ctrl_list, rptCtrl)) + { + if(dom&&strcmp(rptCtrl->dsNvl->va_scope->dom->name,dom)) continue; + /* If scan_rate > 0, check timer. If not, go ahead and scan now. */ + /* NOTE: if scan_rate is too small, there may be extra delay between scans.*/ + if(CHG) + { + if (timeNow >= rptCtrl->next_scan_start) + rptCtrl->next_scan_start = timeNow + rptCtrl->scan_rate; + } + else if (rptCtrl->scan_rate > 0) + { /* check timer to see if it's time to scan */ + if (timeNow < rptCtrl->next_scan_start) + continue; /* DO NOT scan now. Skip to next rptCtrl */ + else + rptCtrl->next_scan_start = timeNow + rptCtrl->scan_rate; + } + dsNvl = rptCtrl->dsNvl; + if (dsNvl!=NULL && dsNvl->already_scanned==SD_FALSE) /* dsNvl might be NULL*/ + { /* This NVL not yet scanned. */ + /* If URCB enabled or BRCB enabled ONCE, start scan.*/ + if( rptCtrl->only_client.basrcb.RptEna||(rptCtrl->rcb_type == RCB_TYPE_IEC_BRCB&& + rptCtrl->brcbCtrl.enabled_once)) + { + /* Initialize "rpt_reason=0" for all variables. May be changed */ + /* in leaf functions. Checked in mvl61850_rpt_change_scan_va_done. */ + for (j = 0; j < dsNvl->num_of_entries; j++) + dsNvl->entries[j]->rpt_reason = 0; + + /* This is NOT an Integrity scan, but mvlu_integrity_scan_read */ + /* does what we need if the right callback functions passed to it. */ + /* Scan for dchg, qchg, dupd. */ + /* This function "begins" the scan. When the scan is */ + /* complete, "mvl61850_rpt_change_scan_done" is called to build the */ + /* the report. If ALL "leaf" functions are synchronous, */ + /* "mvl61850_rpt_change_scan_done" is called BEFORE this function returns.*/ + /* CRITICAL: this function allocates a temporary MVL_IND_PEND */ + /* which must be freed by mvl61850_rpt_change_scan_done. */ + mvlu_integrity_scan_read (&rptCtrl->only_client, + mvl61850_rpt_change_scan_va_done, + mvl61850_rpt_change_scan_done); + dsNvl->already_scanned = SD_TRUE; /* this NVL scanned. Don't scan again for another RCB*/ + } + } + } + } +/************************************************************************/ +/* mvl61850_get_rcb */ +/* Find IEC 61850 RCB (URCB or BRCB). */ +/* NOTE: Caller can access MVLU_RPT_CTRL, if needed, by using "rpt_ctrl"*/ +/* member of MVLU_RPT_CLIENT. */ +/************************************************************************/ +MVLU_BASRCB *mvl61850_get_rcb (MVL_VAR_ASSOC *baseVa, + RUNTIME_TYPE *rt, + MVLU_RPT_CLIENT **rptClientOut) + { +MVLU_RPT_CTRL *rptCtrl; +MVLU_BASRCB *rcb = NULL; /* ptr to be returned */ + + /* Find the associated Report Control, using this RT as a key */ + for (rptCtrl = mvl61850_rpt_ctrl_list; + rptCtrl != NULL; + rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvl61850_rpt_ctrl_list, rptCtrl)) + { + if (rptCtrl->base_va == baseVa && + (rt > rptCtrl->rcbRtHead) && + (rt <= rptCtrl->rcbRtHead + rptCtrl->rcbRtHead->u.str.num_rt_blks)) + { + if (rptCtrl->rcb_type != RCB_TYPE_UCA) + { + rcb = &rptCtrl->only_client.basrcb; + if (rptClientOut != NULL) /* set optional ptr */ + *rptClientOut = &rptCtrl->only_client; /* always EXACTLY one client*/ + } + break; /* rptCtrl is set. Just need to return it. */ + } + } + /* rcb will be NULL if rptCtrl NOT found or NOT 61850 */ + return (rcb); + } + +/************************************************************************/ +/* mvl61850_rpt_dataset_create */ +/* Create IEC 61850 Report Control Block resources for a dataset. */ +/* Assumes EXACTLY one client per rptCtrl (see rptCtrl->only_client). */ +/************************************************************************/ +ST_RET mvl61850_rpt_dataset_create (MVLU_RPT_CTRL *rptCtrl, + MVL_NVLIST_CTRL *dsNvl) + { +RUNTIME_TYPE *incRt; +ST_RET rc; +ST_INT numDsVars; +ST_INT changed_flags_size; +ST_INT allocSize; + + if (rptCtrl->dsNvl) + { /* dsNvl already set. Must call mvl61850_rpt_dataset_destroy first*/ + MVL_LOG_ERR0 ("Report Dataset already exists. Must destroy it before creating new one."); + return (SD_FAILURE); + } + + if (dsNvl == NULL) + return (SD_SUCCESS); /* this is allowed, but no need to do anything*/ + + numDsVars = dsNvl->num_of_entries; + + /* NOTE: RptID (in MVLU_BASRCB struct) might be empty (0 length string).*/ + /* If so, a string will be constructed each time a report is built */ + /* (see "mvlu_mk_rptid" function). */ + +/* Alloc the entries table; allow for RptID, OptFlds, SqNum, RptTim, */ +/* DatSet, BufOvfl, EntryID, ConfRev, */ +/* SubSeqNum, MoreSegmentsFollow, & InclusionBitstring plus ARRAYS of */ +/* dataRefs, values, and Reasons. */ +/* "assert" later if "maxNumRptVars" exceeded. */ +/* Allow (3 * numDsVars) to handle arrays of dataRef, value, and reason.*/ + rptCtrl->maxNumRptVars = MVLU_MAX_RPT_OPTS + (3 * numDsVars); + + rptCtrl->rptNvl.entries = (MVL_VAR_ASSOC **) M_CALLOC (MSMEM_GEN, rptCtrl->maxNumRptVars, + sizeof (MVL_VAR_ASSOC *)); + + /* NOTE: The "rptNvl->entries" array is not filled in and + * and "rptNvl->num_of_entries" is not set + * until a Report is being built. + */ + + /* We need to create a Runtime Type for the inclusion bitstring */ + incRt = &rptCtrl->incRt; + incRt->el_tag = RT_BIT_STRING; + incRt->el_size = BSTR_NUMBITS_TO_NUMBYTES(numDsVars); + incRt->offset_to_last = incRt->el_size; + /*renxiaobao 5.3°æ±¾ÐÞ¸Ä*/ + /*incRt->u.p.el_len = (ST_RTINT) numDsVars;*/ + incRt->u.p.el_len = numDsVars; + rc = mvlu_add_rt_type (&rptCtrl->incRt, 1, &rptCtrl->inclusion_typeid); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR0 ("Error - could not add temp RT type"); + return (SD_FAILURE); + } + +/* That's all we can do ahead of time for the RPT variable associations */ + +/* Set a bit of the data for the BASRCB */ + if (dsNvl->nvl_scope.scope == AA_SPEC) + sprintf (rptCtrl->only_client.basrcb.DatSetNa, "@%s", dsNvl->name); + else if (dsNvl->nvl_scope.scope == VMD_SPEC) + sprintf (rptCtrl->only_client.basrcb.DatSetNa, "/%s", dsNvl->name); + else + sprintf (rptCtrl->only_client.basrcb.DatSetNa, "%s/%s", + dsNvl->nvl_scope.dom->name, dsNvl->name); + + /* Alloc one buf for reasons_data, changed_flags, segmented_inclusion.*/ + /* Free this buf in mvl61850_rpt_dataset_destroy. */ + changed_flags_size = BSTR_NUMBITS_TO_NUMBYTES(numDsVars); + allocSize = (numDsVars * sizeof (ST_UINT8)) + /* reasons_data */ + (2 * changed_flags_size); /* changed_flags & segmented_inclusion*/ + rptCtrl->only_client.reasons_data = chk_calloc (1, allocSize); + rptCtrl->only_client.changed_flags = rptCtrl->only_client.reasons_data + numDsVars; + rptCtrl->only_client.segmented_inclusion = rptCtrl->only_client.changed_flags + changed_flags_size; + + rptCtrl->dsNvl = dsNvl; /* now save new dataset */ + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* mvl61850_rpt_dataset_destroy */ +/* Destroy resources created by mvl61850_rpt_dataset_create. */ +/************************************************************************/ +ST_VOID mvl61850_rpt_dataset_destroy (MVLU_RPT_CTRL *rptCtrl) + { + if (rptCtrl->dsNvl != NULL) + { /* if dsNvl is already NULL, do nothing */ + chk_free (rptCtrl->only_client.reasons_data); + rptCtrl->only_client.basrcb.DatSetNa[0] = '\0'; /* clear DatSet */ + + rptCtrl->maxNumRptVars = 0; + + M_FREE (MSMEM_GEN, rptCtrl->rptNvl.entries); + + /* Free the Runtime Type for the inclusion bitstring */ + mvlu_free_rt_type (rptCtrl->inclusion_typeid); + rptCtrl->dsNvl = NULL; + } + return; + } + +/************************************************************************/ +/* mvl61850_create_rpt_ctrl */ +/* Create IEC 61850 Report Control Block. */ +/* Similar to UCA function "mvlu_create_rpt_ctrl", but just for 61850. */ +/* Only one client per RCB (see "only_client" param). */ +/* The "dsNvl" arg may be NULL. If so, the RCB may not be enabled until */ +/* it is set. */ +/* NOTE: Does not support UCA Reports (see assert checking "rcb_type"). */ +/************************************************************************/ +MVLU_RPT_CTRL *mvl61850_create_rpt_ctrl (ST_CHAR *basrcbName, + MVL_NVLIST_CTRL *dsNvl, /* may be NULL */ + MVL_VAR_ASSOC *base_va, + ST_INT rcb_type, + ST_INT buftim_action, /* MVLU_RPT_BUFTIM_* */ + ST_INT brcb_bufsize, /* for BRCB only */ + ST_UINT32 ConfRev) /* for BRCB/URCB only */ + + { +MVLU_RPT_CTRL *rptCtrl; +ST_INT rptCtrlSize; +ST_INT numRt; +ST_RET status; /* SD_SUCCESS if everything worked */ + + assert (rcb_type != RCB_TYPE_UCA); /* DO NOT use this funct for UCA rpts*/ + + /* If any rpt_ctrl created, disconnect function ptr must be set. */ + _mvlu_rpt_disconnect_rcvd_fun = _mvlu_rpt_disconnect_rcvd; + + /* Allocate MVLU_RPT_CTRL struct. Allow extra space after struct to */ + /* store basrcbName. */ + rptCtrlSize = sizeof (MVLU_RPT_CTRL) + strlen (basrcbName) + 1; + rptCtrl = (MVLU_RPT_CTRL *) M_CALLOC (MSMEM_GEN, 1, rptCtrlSize); + + rptCtrl->basrcb_name = (ST_CHAR *) (rptCtrl + 1); /*point after struct*/ + strcpy (rptCtrl->basrcb_name, basrcbName); + + /* Initialize structure members. */ + rptCtrl->base_va = base_va; + rptCtrl->rcb_type = rcb_type; + rptCtrl->buftim_action = buftim_action; + + rptCtrl->brcbCtrl.brcb_bufsize = brcb_bufsize; /* ONLY for IEC BRCB*/ + + rptCtrl->rptNvl.name = "RPT"; /* Report NVL name ALWAYS = "RPT"*/ + + rptCtrl->only_client.basrcb.ConfRev = ConfRev; + rptCtrl->only_client.basrcb.OptFlds.len_1 = 10; /* bitstring len*/ + rptCtrl->only_client.basrcb.TrgOps.len = 6; /* bitstring len*/ + + rptCtrl->only_client.rpt_ctrl = rptCtrl; /* client struct needs ptr back to rptCtrl*/ + + /* For BRCB, set the initial "EntryID" value. */ + /* Put current time in first 4 bytes, 0 in last 4 bytes. */ + if (rcb_type == RCB_TYPE_IEC_BRCB) + { + ST_INT32 tmp[2]; + tmp [0] = (ST_INT32) time (NULL); + /*renxiaobao ±¨¸æ*/ + tmp [0] = 0; + tmp [1] = 0; + mvl61850_brcb_entryid_init (rptCtrl, (ST_UINT8 *) tmp); + } + + /* The following initializations could fail, so we set & check "status".*/ + + /* Find the runtime type of the RCB and save it in rptCtrl->rcbRtHead.*/ + /* Used by leaf functions to find the correct rptCtrl. */ + /* If successful, this function sets "rptCtrl->rcbRtHead" & "numRt". */ + status = mvlu_rpt_rcb_type_find (base_va->type_id, basrcbName, &rptCtrl->rcbRtHead, &numRt); + + if (status == SD_SUCCESS) + { + if (mvlu_rpt_find_typeids (&rptCtrl->rpt_typeids)) + { + MVL_LOG_ERR0 ("Cannot find Report Control Block types"); + status = SD_FAILURE; + } + } + + /* mvl61850_rpt_dataset_create initializes everything related to dsNvl. */ + if (status == SD_SUCCESS) + status = mvl61850_rpt_dataset_create (rptCtrl, dsNvl); + + if (status == SD_SUCCESS) + { +#if 1 /* IEC 61850-7-2 Ed2 says to start buffering on power-up if */ + /* DatSet attribute references an existing DataSet. */ + if (dsNvl != NULL && rptCtrl->rcb_type == RCB_TYPE_IEC_BRCB) + rptCtrl->brcbCtrl.enabled_once = SD_TRUE; /* starts buffering */ +#endif + list_add_last((ST_VOID **) &mvl61850_rpt_ctrl_list, (ST_VOID *) rptCtrl); + } + else + { + M_FREE (MSMEM_GEN, rptCtrl); /* clean up */ + rptCtrl = NULL; /* set error return value */ + } + return (rptCtrl); + } + +/************************************************************************/ +/* mvl61850_free_rpt_ctrl */ +/* Free a MVLU_RPT_CTRL allocated by 'mvl61850_create_rpt_ctrl'. */ +/************************************************************************/ + +ST_VOID mvl61850_free_rpt_ctrl (MVLU_RPT_CTRL *rptCtrl) + { + assert (rptCtrl->rcb_type != RCB_TYPE_UCA); + +/* Take it off the report control list */ + list_unlink ((ST_VOID **) &mvl61850_rpt_ctrl_list, (ST_VOID *) rptCtrl); + + mvl61850_rpt_dataset_destroy (rptCtrl); + +/* BRCB may contain large lists of reports sent or queued. */ + if (rptCtrl->rcb_type == RCB_TYPE_IEC_BRCB) + mvl61850_brcb_rpt_lists_clean (&rptCtrl->brcbCtrl); + + M_FREE (MSMEM_GEN, rptCtrl); + } + +/************************************************************************/ +/* mvl61850_brcb_client_service */ +/* Check the BRCB state and perform appropriate actions. */ +/************************************************************************/ +ST_VOID mvl61850_brcb_client_service (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + ST_DOUBLE timeNow) + { +BUFLIST_ENTRY *entry; +ST_BOOLEAN all_seg_done; /* SD_TRUE if done sending all segments */ +ST_RET retCode; + + /* Check BRBC state and, if necessary, encode AND queue up report. */ + mvl61850_rcb_chk_state (rptCtrl, rptClient, timeNow); + + /* Now, examine BRCB state and send report if necessary. + * If connected, reports are enabled, reports are queued, AND stack buffers + * are available, send a report. + */ + if (rptClient->netInfo && /* connected */ + rptClient->basrcb.RptEna && /* rpts enabled */ + rptCtrl->brcbCtrl.rpt_list_next) /* rpts queued & not all sent*/ + { + if (mvl_ureq_bufs_avail (rptClient->netInfo) > 0) /* stack bufs avail to send rpt */ + { + /* Encode and send next buffered report. */ + entry = rptCtrl->brcbCtrl.rpt_list_next; /* this is next one to send*/ + retCode = mvl61850_brcb_rpt_send (rptCtrl, rptClient, entry, &all_seg_done); + if (retCode != SD_SUCCESS) + MVL_LOG_ERR1 ("Sending IEC-61850 Buffered Report failed: err=0x%X", retCode); + + /* If error OR done sending all segments of this rpt, */ + /* point to next rpt on list (NULL if all sent) & update SqNum */ + if (retCode != SD_SUCCESS || + all_seg_done) /* done sending all segments of this report. */ + { /* point to next rpt on the list (NULL if all sent) */ + rptCtrl->brcbCtrl.rpt_list_next = list_get_next (rptCtrl->brcbCtrl.rpt_list, entry); + memcpy (rptCtrl->brcbCtrl.lastSentEntryID, entry->EntryID, 8); /* save last sent EntryID*/ + memcpy (&rptCtrl->brcbCtrl.lastSentTimeOfEntry, &entry->TimeOfEntry, sizeof (MMS_BTIME6)); + print_queues (&rptCtrl->brcbCtrl); /* just for debug */ + /* Increment seq number for next rpt. */ + rptClient->basrcb.SqNumInt16u++; /* used only for BRCB */ + /* Only one report should be sent with BufOvfl TRUE; clear it now.*/ + rptCtrl->brcbCtrl.BufOvfl = SD_FALSE; + } + } + else + print_msg0 ("STACK BUFFERS NOT AVAILABLE TO SEND REPORT\n"); + } + return; + } + +/************************************************************************/ +/* mvl61850_urcb_client_service */ +/* Check the URCB state and perform appropriate actions. */ +/************************************************************************/ +int urcb_netInfo_pri=0; +ST_VOID mvl61850_urcb_client_service (MVLU_RPT_CTRL *rptCtrl, + MVLU_RPT_CLIENT *rptClient, + ST_DOUBLE timeNow) + { + /* Must be connected to send Unbuffered reports. */ + if (rptClient->netInfo!=NULL) + { + /* if(urcb_netInfo_pri) + printf("rptClient->netInfo=%d\r\n ",rptClient->netInfo);*/ + /* If no buffers are available to send unbuffered reports, don't waste time + * checking timers, scanning, etc. + */ + if (mvl_ureq_bufs_avail (rptClient->netInfo) <= 0) /* stack bufs avail to send rpt */ + print_msg0 ("STACK BUFFERS NOT AVAILABLE TO SEND REPORT\n"); + else + /* Check URBC state and, if necessary, encode AND send report. */ + mvl61850_rcb_chk_state (rptCtrl, rptClient, timeNow); + } + return; + } + +/************************************************************************/ +/* mvl61850_rpt_service */ +/* Perform servicing for all IEC 61850 Report Control Blocks. */ +/* Scanning for changes (dchg, qchg, etc) is automatic */ +/* (see mvl61850_rpt_change_scan). */ +/************************************************************************/ + +ST_VOID mvl61850_rpt_service (char *dom,char CHG) + { +MVLU_RPT_CTRL *rptCtrl; +ST_DOUBLE timeNow; + +/* Scan all report data for changes (dchg, qchg, dupd). */ + mvl61850_rpt_change_scan (dom,CHG); +/* See if it is time to send reports */ + timeNow = sGetMsTime (); + for (rptCtrl = mvl61850_rpt_ctrl_list; + rptCtrl != NULL; + rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvl61850_rpt_ctrl_list, rptCtrl)) + { + if(dom&&strcmp(rptCtrl->dsNvl->va_scope->dom->name,dom)) continue; + /* NOTE: if DatSet is NULL, don't need to do anything for this rptCtrl.*/ + if (rptCtrl->dsNvl==NULL) + continue; + /* Only one client (rptCtrl->only_client). */ + if (rptCtrl->rcb_type == RCB_TYPE_IEC_BRCB) + mvl61850_brcb_client_service (rptCtrl, &rptCtrl->only_client, timeNow); + else + { + /*assert (rptCtrl->rcb_type == RCB_TYPE_IEC_URCB);*/ /* must be IEC_URCB*/ + mvl61850_urcb_client_service (rptCtrl, &rptCtrl->only_client, timeNow); + } + } + } +/************************************************************************/ +/* mvl61850_rpt_ctrl_destroy_all */ +/* Destroy all 61850 report controls. */ +/************************************************************************/ +ST_VOID mvl61850_rpt_ctrl_destroy_all () + { +MVLU_RPT_CTRL *rptCtrl; + /* Use list_find_last to avoid calling list_unlink twice. */ + while ((rptCtrl = (MVLU_RPT_CTRL *) list_find_last ((DBL_LNK *)mvl61850_rpt_ctrl_list)) != NULL) + { + mvl61850_free_rpt_ctrl (rptCtrl); /* this also unlinks it from list*/ + } + } + +/************************************************************************/ +/* mvl61850_integrity_timeout */ +/* NOTE: For IEC 61850 only. For UCA, use mvlu_integrity_timeout. */ +/* If Integrity period timeout occurred, send Integrity Report. */ +/* NOTE: data scan already done at start of mvl61850_rpt_service. */ +/* No need to rescan data. Just send the data from the data scan. */ +/* RETURNS: SD_TRUE if IntgPd is set and timeout occurred */ +/* SD_FALSE otherwise */ +/************************************************************************/ +ST_RET mvl61850_integrity_timeout (MVLU_RPT_CLIENT *rptClient, ST_DOUBLE timeNow) + { +ST_RET retVal; +ST_INT j; +ST_RET readyRet; /* return code from mvlu_rpt_ready */ + + if (rptClient->basrcb.IntgPd != 0 + && BSTR_BIT_GET (rptClient->basrcb.TrgOps.data, TRGOPS_BITNUM_INTEGRITY) /* enabled*/ + && timeNow > rptClient->next_integ_rpt_time) /* timeout occurred*/ + { + MVLU_LOG_FLOW1 ("IEC 61850 Report Integrity Period timeout for client %08lx",rptClient); + /* Send last buffered entry (due to BufTm buffering) BEFORE this integrity report.*/ + if (rptClient->numTrgs > 0) + { + /* send or queue report */ + mvlu_rpt_ready (rptClient, MVLU_RPT_TYPE_RBE); + } + + /* Set "reason" for each variable of Dataset now. */ + for (j = 0; j < rptClient->rpt_ctrl->dsNvl->num_of_entries; j++) + rptClient->reasons_data[j] = MVLU_TRGOPS_INTEGRITY; + + /* send or queue rpt */ + readyRet = mvlu_rpt_ready (rptClient, MVLU_RPT_TYPE_INTEGRITY_OR_GI); + + if (readyRet != SD_SUCCESS) + MVLU_LOG_FLOW1 ("IEC 61850 Integrity report could not be sent or queued: err=0x%X", readyRet); + + /* set time for next integrity report */ + rptClient->next_integ_rpt_time = sGetMsTime () + + (ST_DOUBLE) rptClient->basrcb.IntgPd; + retVal = SD_TRUE; + } + else + retVal = SD_FALSE; + return (retVal); + } + + diff --git a/mmslib/mvlu/mvl_buf.c b/mmslib/mvlu/mvl_buf.c new file mode 100644 index 0000000..5cda7d0 --- /dev/null +++ b/mmslib/mvlu/mvl_buf.c @@ -0,0 +1,24 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_buf.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/23/99 MDE 04 Deleted contents, file is obsolete */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +/* OBSOLETE FILE */ diff --git a/mmslib/mvlu/mvl_dtyp.c b/mmslib/mvlu/mvl_dtyp.c new file mode 100644 index 0000000..ac51d61 --- /dev/null +++ b/mmslib/mvlu/mvl_dtyp.c @@ -0,0 +1,532 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2005, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_dtyp.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/19/05 JRB 08 Use mvlu_trim_branch_name from mvl_uca.c */ +/* 12/19/02 JRB 07 Use ms_comp_name_find, ms_comp_name_pres. */ +/* 11/19/02 RKR 06 Corrected size in cardinality function */ +/* 02/27/02 JRB 05 Del unneeded prototypes & includes. */ +/* 12/04/01 RKR 04 ported to QNX cleaned up errors and warnings */ +/* 11/09/01 RKR 03 resorted the num_rt_blks */ +/* 01/21/00 MDE 02 Now use MEM_SMEM for dynamic memory */ +/* 10/05/99 RKR 01 Created */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mms_pvmd.h" +#include "mms_err.h" +#include "mms_pcon.h" +#include "mvl_log.h" +#include "mvl_defs.h" +#include "mvl_uca.h" /* need mvlu_trim_branch_name */ +#include "asn1defs.h" +#include "stime.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +static ST_UCHAR *create_bitstring (ST_INT num); +static ST_VOID set_bit ( ST_UCHAR *bptr, ST_INT i); +static ST_BOOLEAN ismember( ST_UCHAR *bptr, + ST_INT n); +static ST_VOID reSortRT (RUNTIME_TYPE *rt, ST_INT numRt); +static ST_VOID add_to_branch_name (ST_CHAR *branch_name, SD_CONST ST_CHAR *SD_CONST sub_branch_name); + +static ST_INT cardinality (ST_UCHAR *bptr, ST_INT size); +static ST_VOID calc_offset_to_last (RUNTIME_TYPE *rt); + +ST_VOID mvl_print_type( ST_CHAR *base_name, ST_INT typeIdIn); +#ifndef __ECOS +ST_BOOLEAN u_mvl_rt_element_supported (RUNTIME_TYPE *rt, + ST_CHAR *element_name, + ST_RTREF *ui, ST_CHAR *handle); +#endif +ST_VOID adjRtBlks( RUNTIME_TYPE *derived_type_table, ST_INT derived_count); + +/************************************************************************/ +/* mvl_derive_new_type */ +/************************************************************************/ + +ST_RET mvl_derive_new_type (ST_CHAR *base_name, ST_INT typeIdIn, ST_INT *typeIdOut, ST_CHAR *handle) + { +ST_RET ret; +ST_RTREF rtrefs; +ST_UCHAR *membership; + + ret = mvl_derive_type_members (base_name, typeIdIn, &membership, &rtrefs, handle ); + mvl_print_derived_type (base_name, typeIdIn, membership, rtrefs); + ret = mvl_add_derived_type (base_name, typeIdIn, membership, rtrefs, typeIdOut); + return (ret); + } + +/************************************************************************/ +/* mvl_derive_type_members */ +/************************************************************************/ + +ST_RET mvl_derive_type_members (ST_CHAR *base_name, ST_INT typeIdIn, + ST_UCHAR **membership, ST_RTREF *rtrefs, ST_CHAR *handle) + { +ST_RET ret = SD_FAILURE; +RUNTIME_TYPE *rt; +ST_INT num_rt; +ST_BOOLEAN exists; +ST_CHAR element_name[MAX_IDENT_LEN+1]; +ST_CHAR branch_name[MAX_IDENT_LEN+1]; +ST_RTREF *user_info; +ST_INT i; +ST_RTREF ui; /* let the user pass back widget of unknown purpose */ +ST_UCHAR *bptr; + + ret = mvl_get_runtime (typeIdIn, &rt, &num_rt); + if (ret != SD_SUCCESS) + { + MVL_LOG_NERR1 ("TypeId %d not found",typeIdIn); + return (ret); + } + + bptr = create_bitstring (num_rt); + *membership = bptr; + user_info = (ST_RTREF *) M_CALLOC (MSMEM_GEN, num_rt, sizeof(ST_RTREF *)); + *rtrefs = user_info; + + for (i=0; i highestSortNum) + highestSortNum = rt[i].mvluTypeInfo.sortedNum; + } + + newSortNum = 1; + +/* compress the sort numbers */ + + for (prevSortNum = 1; prevSortNum <= highestSortNum; ++prevSortNum) + { + for (i = 0; i < numRt; ++i) + { + if (rt[i].mvluTypeInfo.sortedNum == prevSortNum) + { + rt[i].mvluTypeInfo.sortedNum = newSortNum; + ++newSortNum; + break; + } + } + } + } +/************************************************************************/ +/* adjRtBlks */ +/************************************************************************/ + +ST_VOID adjRtBlks( RUNTIME_TYPE *derived_type_table, ST_INT derived_count) + { +RUNTIME_TYPE *nested[ASN1_MAX_LEVEL]; +ST_INT i; +ST_INT curNestLevel; +RUNTIME_TYPE *start_rt_blk; +RUNTIME_TYPE *rt_ptr; +ST_INT num_rt; + + curNestLevel = 0; + + rt_ptr = derived_type_table; + for (i=0; iel_tag == RT_STR_START) || + (rt_ptr->el_tag == RT_ARR_START)) + { + nested[curNestLevel] = rt_ptr; /* remember where we started */ + curNestLevel++; + } + else if ((rt_ptr->el_tag == RT_STR_END) || + (rt_ptr->el_tag == RT_ARR_END)) + { + curNestLevel--; + start_rt_blk = nested[curNestLevel]; + num_rt = (rt_ptr - start_rt_blk - 1); /* figure out how many in between */ + + /*if (start_rt_blk->u.str.num_rt_blks != num_rt) + { + printf ("\n adjusting %s, was %d, is now %d", + ms_comp_name_find(start_rt_blk), + start_rt_blk->u.str.num_rt_blks, + num_rt); + }*/ + + start_rt_blk->u.str.num_rt_blks = num_rt; + rt_ptr->u.str.num_rt_blks = num_rt; + } + } + } + +/************************************************************************/ +/* add_to_branch_name */ +/************************************************************************/ + +static ST_VOID add_to_branch_name (ST_CHAR *branch_name, SD_CONST ST_CHAR *SD_CONST sub_branch_name) + { + sprintf( branch_name, "%s$%s", branch_name, sub_branch_name); + } + +/************************************************************************/ +/* create_bitstring */ +/************************************************************************/ +static ST_UCHAR *create_bitstring (ST_INT n) + { +ST_INT i,j; +ST_UCHAR *s; + + i = n / ( sizeof( ST_UCHAR ) * 8 ); + j = n % ( sizeof( ST_UCHAR ) * 8 ); + + if (j) + i++; /* allocate an extra byte if string len ! a multiple of 8 */ + + s = (ST_UCHAR *)M_CALLOC (MSMEM_GEN, i, sizeof( ST_UCHAR)); + return(s); + + } + +/************************************************************************/ +/* set_bit */ +/************************************************************************/ +static ST_VOID set_bit (ST_UCHAR *s, ST_INT n) + { +ST_INT i,j; +ST_UCHAR k = 0x01; /* mask */ + + i = n / ( sizeof( ST_UCHAR ) * 8 ); + j = n % ( sizeof( ST_UCHAR ) * 8 ); + s[ i ] = s[ i ] | ( k << j ); + } + +/************************************************************************/ +/* ismember */ +/* This function returns 1 if element n belongs to Set s, 0 otherwise. */ +/************************************************************************/ + +static ST_BOOLEAN ismember( ST_UCHAR *bptr, + ST_INT n) + { +ST_INT i,j; +ST_UCHAR k = 0x01; /* mask */ + + i = n / ( sizeof( ST_UCHAR ) * 8 ); + j = n % ( sizeof( ST_UCHAR ) * 8 ); + return( bptr[ i ] & ( k << j )); + } + +/************************************************************************/ +/* cardinality */ +/************************************************************************/ + +static ST_INT cardinality (ST_UCHAR *bptr, ST_INT size) + { +ST_INT i, j, s, r, card; +ST_CHAR temp; + + s = size / ( sizeof( ST_UCHAR ) * 8 ); + r = size % ( sizeof( ST_UCHAR ) * 8 ); + + if (r) + s++; + card=0; + for ( i = 0; i < s; i++ ) + { + for ( j = 0; j < 8 * sizeof( ST_UCHAR ); j++ ) + { + temp = 0x01; + temp = temp << j; + if ( temp & bptr[ i ] ) + card++; + } + } + return( card ); + } + +/************************************************************************/ +/* calc_offset_to_last */ +/************************************************************************/ +/* This function would not be needed except that the UCA structure */ +/* handling needs to know the size of each subelement too ... */ + +static ST_VOID calc_offset_to_last (RUNTIME_TYPE *rt) + { +ST_INT numUcaRt; + + if (rt->el_tag == RT_ARR_END || rt->el_tag == RT_STR_END) + { + return; + } + + if (rt->el_tag == RT_STR_START) + numUcaRt = rt->u.str.num_rt_blks+2; + else if (rt->el_tag == RT_ARR_START) + numUcaRt = rt->u.arr.num_rt_blks+2; + else + numUcaRt = 1; + +/* Now we can find the size of this element and it's associates */ + rt->offset_to_last = ms_get_blocked_length (rt, numUcaRt); + } + + diff --git a/mmslib/mvlu/mvl_ijou.c b/mmslib/mvlu/mvl_ijou.c new file mode 100644 index 0000000..e71f813 --- /dev/null +++ b/mmslib/mvlu/mvl_ijou.c @@ -0,0 +1,601 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_ijou.c */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* Functions to automatically build a ReadJournal response, */ +/* assuming the Journal is modeled as a linked list of journal */ +/* entries. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* u_mvl_start_jread */ +/* u_mvl_get_next_jread_entry */ +/* u_mvl_free_jread_entry */ +/* u_mvl_end_jread */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 04/14/00 JRB 06 Lint cleanup. */ +/* 01/21/00 MDE 05 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 10/29/98 JRB 02 Delete unnecessary includes. */ +/* 10/09/98 JRB 01 Created */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mvl_defs.h" + +/************************************************************************/ +/* All the functions below, used for building the ReadJournal response, */ +/* assume the Journal is modeled as a linked list of journal entries. */ +/* They use SISCO functions to search the linked list. The user code */ +/* must use the same linked list functions to add journal entries to */ +/* the linked list (or remove them from the linked list). */ +/************************************************************************/ + +/************************************************************************/ +/* Static functions for building the JREAD response. */ +/************************************************************************/ +static MVL_JOURNAL_ENTRY *find_je_start_time_forward (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo); +static MVL_JOURNAL_ENTRY *find_je_start_time_backward (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo); + +static MVL_JOURNAL_ENTRY *find_je_start_entry (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo); + +static MVL_JOURNAL_ENTRY *find_je_stop_forward (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo, + MVL_JOURNAL_ENTRY *start_je); +static MVL_JOURNAL_ENTRY *find_je_stop_backward (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo, + MVL_JOURNAL_ENTRY *start_je); + +static MVL_JOURNAL_ENTRY *find_je_start_after_forward (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo, + MVL_JOURNAL_ENTRY *start_je, + MVL_JOURNAL_ENTRY *stop_je); +static MVL_JOURNAL_ENTRY *find_je_start_after_backward (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo, + MVL_JOURNAL_ENTRY *start_je, + MVL_JOURNAL_ENTRY *stop_je); + +ST_BOOLEAN check_je_list_of_var (JREAD_REQ_INFO *reqInfo, + MVL_JOURNAL_ENTRY *je); + +/************************************************************************/ +/* Global variables for building the JREAD response. */ +/************************************************************************/ +MVL_JOURNAL_ENTRY *je_array [MAX_JREAD_RESP_ENTRIES]; /* array or pointers*/ +ST_INT je_array_index; /* index into "je_array" */ +ST_INT je_array_num_entries; /* # of entries in "je_array" */ +ST_BOOLEAN jread_more_follows; +MVL_JOURNAL_ENTRY *stop_je; /* journal entry to stop with. */ + /* NOT INCLUDED in response. */ + +/************************************************************************/ +/************************************************************************/ +ST_RET u_mvl_start_jread (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo, + MVL_JREAD_BUF_CTRL *bufCtrl, + ST_VOID **usrHandleOut) + { +MVL_JOURNAL_ENTRY *je; +MVL_JOURNAL_ENTRY *start_je =jCtrl->entries; /* First entry that passes*/ + /* "Range Start Spec." */ +ST_BOOLEAN backwards = SD_FALSE; +ST_INT k; + + /* Init global variables. */ + je_array_index = 0; + je_array_num_entries = 0; + jread_more_follows = SD_TRUE; /* Assume "more_follows". */ + + if (reqInfo->range_start_pres + && reqInfo->start_tag == 0 /* Use Starting time */ + && reqInfo->start_time.form != MMS_BTOD6) + { + printf ("\nERROR: ReadJournal request Starting Time illegal. Must be Btime6."); + return (SD_FAILURE); + } + if (reqInfo->range_stop_pres + && reqInfo->stop_tag == 0 /* Use Stop time */ + && reqInfo->end_time.form != MMS_BTOD6) + { + printf ("\nERROR: ReadJournal request End Time illegal. Must be Btime6."); + return (SD_FAILURE); + } + if (reqInfo->sa_entry_pres + && reqInfo->time_spec.form != MMS_BTOD6) + { + printf ("\nERROR: ReadJournal request Time Specification illegal. Must be Btime6."); + return (SD_FAILURE); + } + + /* If "Number of Entries" is used and is negative, do reverse order. */ + if (reqInfo->range_stop_pres + && reqInfo->stop_tag != 0 /* Use "Number of Entries" */ + && reqInfo->num_of_entries < 0) /* Negative */ + backwards = SD_TRUE; /* return entries in reverse order */ + + /* Process "Range Start Specification" */ + if (reqInfo->range_start_pres) + { + if (reqInfo->start_tag == 0) /* Use Starting time */ + { + if (reqInfo->range_stop_pres && reqInfo->stop_tag == 0) + { /* Use "Ending Time" */ + if (reqInfo->start_time.day > reqInfo->end_time.day || + (reqInfo->start_time.day == reqInfo->end_time.day && + reqInfo->start_time.ms > reqInfo->end_time.ms) ) + { /* Start time > End time */ + backwards = SD_TRUE; /* return entries in reverse order */ + } + } + + if (backwards) + { + /* Set "start_je" to the first entry with time <= start time. */ + /* Could be NULL if no entry found. */ + start_je = find_je_start_time_backward (jCtrl, reqInfo); + } + else + { + /* Set "start_je" to the first entry with time >= start time. */ + /* Could be NULL if no entry found. */ + start_je = find_je_start_time_forward (jCtrl, reqInfo); + } + if (start_je == NULL) + return (SD_SUCCESS); /* None found. Return 0 entries */ + } + else /* Use "Starting Entry" */ + { + start_je = find_je_start_entry (jCtrl, reqInfo); + if (start_je == NULL) + return (SD_FAILURE); /* If no match, must send Negative resp.*/ + + if (reqInfo->range_stop_pres && reqInfo->stop_tag == 0) + { /* Use "Ending Time" */ + if (start_je->occur_time.day > reqInfo->end_time.day || + (start_je->occur_time.day == reqInfo->end_time.day && + start_je->occur_time.ms > reqInfo->end_time.ms) ) + { /* Entry time > End time */ + backwards = SD_TRUE; /* return entries in reverse order */ + } + } + } + } /* End processing "Range Start Specification". */ + else + start_je = jCtrl->entries; + + + /* Process "Range Stop Specification" */ + /* Set "stop_je" pointing to first entry past the "stop spec". */ + if (backwards) + { /* Search BACKWARD thru linked list */ + stop_je = find_je_stop_backward (jCtrl, reqInfo, start_je); + } + else + { /* Search FORWARD thru linked list */ + stop_je = find_je_stop_forward (jCtrl, reqInfo, start_je); + } + + /* Process "Entry to Start After" */ + if (reqInfo->sa_entry_pres) + { /* "Entry to Start After" specified. */ + /* Scan linked list for "Start After Entry" and "Start After Time", */ + /* up to "Range Stop", if specified. */ + /* Adjust "start_entry" accordingly. */ + if (backwards) + { /* Search BACKWARD thru linked list */ + start_je = find_je_start_after_backward (jCtrl, reqInfo, start_je, stop_je); + } + else + { /* Search FORWARD thru linked list */ + start_je = find_je_start_after_forward (jCtrl, reqInfo, start_je, stop_je); + } /* End "Search FORWARD thru linked list" */ + } + else + ; /* "Entry to Start After" NOT specified. Do nothing. */ + /* End processing of "Entry to Start After" */ + + /* Now find all entries that pass the "List of Variables" filter */ + /* and add them to an array of Journal entries to send in response. */ + if (backwards) + { + for (je = start_je; + je != stop_je; + je = (MVL_JOURNAL_ENTRY *) list_find_prev ((DBL_LNK *) jCtrl->entries, (DBL_LNK *) je)) + { + if (je_array_num_entries >= MAX_JREAD_RESP_ENTRIES) + break; /* Assume still more entries. */ + + /* If "List of Variables" specified, check if this entry matches.*/ + if (check_je_list_of_var (reqInfo, je)) + je_array[je_array_num_entries++] = je; /* Matched. */ + } /* end "for" */ + } + else + { /* "!backwards" */ + for (je = start_je; + je != stop_je; + je = (MVL_JOURNAL_ENTRY *) list_get_next (jCtrl->entries, je)) + { + if (je_array_num_entries >= MAX_JREAD_RESP_ENTRIES) + break; /* Assume still more entries. */ + + /* If "List of Variables" specified, check if this entry matches.*/ + if (check_je_list_of_var (reqInfo, je)) + je_array[je_array_num_entries++] = je; /* Matched. */ + } /* end "for" */ + } /* End "!backwards" */ + if (je == stop_je) /* End of linked list. */ + jread_more_follows = SD_FALSE; /* No more entries */ + +/* We need to tell MVL how many entries and variables we have */ + bufCtrl->numVarInfo = 0; + bufCtrl->numUsrEntries = je_array_num_entries; + for (k = 0; k < je_array_num_entries; k++) + { + je = je_array [k]; + if (je->entry_form_tag == JE_FORM_DATA && je->ef.data.list_of_var_pres) + { /* entry form is 'data' */ + bufCtrl->numVarInfo += je->ef.data.num_of_var; + } + } + +/* By default, MVL assumes "u_mvl_get_next_jread_entry" returns a */ +/* pointer (*mvlJeDest) to persistent data. */ +/* This is a valid assumption for the linked list implementation */ +/* in this sample code. If you cannot point to persistent data, */ +/* you must compile the MVL library and this code with */ +/* MVL_JREAD_*_DYNAMIC defined and adjust the allocation to allow */ +/* MVL enough space to copy the data. */ + +#if defined (MVL_JREAD_ENTRYID_DYNAMIC) + bufCtrl->entryIdBuf = M_MALLOC (MSMEM_GEN, 1000); +#endif +#if defined (MVL_JREAD_VARTAG_DYNAMIC) + bufCtrl->varTagBuf = M_MALLOC (MSMEM_GEN, 1000); +#endif +#if defined (MVL_JREAD_ANNOTATION_DYNAMIC) + bufCtrl->annotationBuf = M_MALLOC (MSMEM_GEN, 1000); +#endif + + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +ST_RET u_mvl_get_next_jread_entry (MVL_JOURNAL_CTRL *jCtrl, + ST_VOID *usrHandle, + ST_BOOLEAN *moreFollowsOut, + MVL_JOURNAL_ENTRY **mvlJeDest) + { + if (je_array_index >= je_array_num_entries) + return (SD_FAILURE); /* Should never happen. */ + + /* If last in "je_array", use "real more_follows value". */ + if (je_array_index + 1 == je_array_num_entries) + *moreFollowsOut = jread_more_follows; + else + *moreFollowsOut = SD_TRUE; /* Not last in array, so always more. */ + + *mvlJeDest = je_array[je_array_index]; + je_array_index++; /* Increment array index to next entry. */ + return (SD_SUCCESS); + } + +/************************************************************************/ + +ST_VOID u_mvl_free_jread_entry (MVL_JOURNAL_CTRL *jCtrl, + ST_VOID *usrHandle, + MVL_JOURNAL_ENTRY *mvlJe) + { + } + +/************************************************************************/ + +ST_VOID u_mvl_end_jread (MVL_JOURNAL_CTRL *jCtrl, + ST_VOID *usrHandle, + MVL_JREAD_BUF_CTRL *bufCtrl, + JREAD_REQ_INFO *reqInfo) + { + +/* Free up buffers allocated in "u_mvl_start_jread". */ +#if defined (MVL_JREAD_ENTRYID_DYNAMIC) + M_FREE (MSMEM_GEN, bufCtrl->entryIdBuf); +#endif +#if defined (MVL_JREAD_VARTAG_DYNAMIC) + M_FREE (MSMEM_GEN, bufCtrl->varTagBuf); +#endif +#if defined (MVL_JREAD_ANNOTATION_DYNAMIC) + M_FREE (MSMEM_GEN, bufCtrl->annotationBuf); +#endif + } + +/************************************************************************/ +/************************************************************************/ +static MVL_JOURNAL_ENTRY *find_je_start_time_forward (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo) + { +MVL_JOURNAL_ENTRY *je; + + for (je = jCtrl->entries; + je != NULL; + je = (MVL_JOURNAL_ENTRY *) list_get_next (jCtrl->entries, je)) + { /* Search entire linked list */ + if (je->occur_time.day > reqInfo->start_time.day || + (je->occur_time.day == reqInfo->start_time.day && + je->occur_time.ms >= reqInfo->start_time.ms) ) + break; /* entry time >= start time. Start here. */ + } /* End "for" loop for time spec */ + return (je); /* May be NULL if not found. */ + } + +/************************************************************************/ +/************************************************************************/ +static MVL_JOURNAL_ENTRY *find_je_start_time_backward (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo) + { +MVL_JOURNAL_ENTRY *je; + + for (je = (MVL_JOURNAL_ENTRY *) list_find_last ((DBL_LNK *) jCtrl->entries); + je != NULL; + je = (MVL_JOURNAL_ENTRY *) list_find_prev ((DBL_LNK *) jCtrl->entries, (DBL_LNK *) je)) + { /* Search entire linked list */ + if (je->occur_time.day < reqInfo->start_time.day || + (je->occur_time.day == reqInfo->start_time.day && + je->occur_time.ms <= reqInfo->start_time.ms) ) + break; /* entry time <= start time. Start here. */ + } /* End "for" loop for time spec */ + return (je); /* May be NULL if not found. */ + } + +/************************************************************************/ +/************************************************************************/ +static MVL_JOURNAL_ENTRY *find_je_start_entry (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo) + { +MVL_JOURNAL_ENTRY *je; + for (je = jCtrl->entries; + je != NULL; + je = (MVL_JOURNAL_ENTRY *) list_get_next (jCtrl->entries, je)) + { + if (je->entry_id_len == reqInfo->start_entry_len && + !memcmp (je->entry_id, reqInfo->start_entry, je->entry_id_len)) + return (je); /* entry id == Starting Entry. Start here. */ + } /* End "for" loop for "Starting Entry" */ + return (NULL); + } + +/************************************************************************/ +/************************************************************************/ +static MVL_JOURNAL_ENTRY *find_je_stop_forward (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo, + MVL_JOURNAL_ENTRY *start_je) + { +MVL_JOURNAL_ENTRY *je; +MVL_JOURNAL_ENTRY *stop_je; +ST_INT num_entries; + + + if (reqInfo->range_stop_pres) + { + for (je = start_je, num_entries = 0; + je != NULL; + je = (MVL_JOURNAL_ENTRY *) list_get_next (jCtrl->entries, je), + num_entries++) + { + if (reqInfo->stop_tag == 0) + { /* Use "Ending Time" */ + if (je->occur_time.day > reqInfo->end_time.day || + (je->occur_time.day == reqInfo->end_time.day && + je->occur_time.ms > reqInfo->end_time.ms) ) + { /* Entry time > End time */ + break; /* Found it. Done. */ + } + } + else + { /* Use "Number of entries" */ + if (num_entries >= reqInfo->num_of_entries) + break; /* Found it. Done. */ + } + } /* end "for" */ + stop_je = je; /* May be NULL if not found. */ + } + else + stop_je = NULL; /* No stop spec. Set to NULL (i.e. end of list) */ + + return (stop_je); + } + +/************************************************************************/ +/************************************************************************/ +static MVL_JOURNAL_ENTRY *find_je_stop_backward (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo, + MVL_JOURNAL_ENTRY *start_je) + { +MVL_JOURNAL_ENTRY *je; +MVL_JOURNAL_ENTRY *stop_je; +ST_INT num_entries; + + if (reqInfo->range_stop_pres) + { + for (je = start_je, num_entries = 0; + je != NULL; + je = (MVL_JOURNAL_ENTRY *) list_find_prev ((DBL_LNK *) jCtrl->entries, (DBL_LNK *) je), + num_entries++) + { + if (reqInfo->stop_tag == 0) + { /* Use "Ending Time" */ + if (je->occur_time.day < reqInfo->end_time.day || + (je->occur_time.day == reqInfo->end_time.day && + je->occur_time.ms < reqInfo->end_time.ms) ) + { /* Entry time < End time */ + break; /* Found it. Done. */ + } + } + else + { /* Use "Number of entries" ("0 -" converts neg to pos) */ + if (num_entries >= (0 - reqInfo->num_of_entries) ) + break; /* Found it. Done. */ + } + } /* end "for" */ + stop_je = je; /* May be NULL if not found. */ + } + else + stop_je = NULL; /* No stop spec. Set to NULL (i.e. end of list) */ + + return (stop_je); + } + +/************************************************************************/ +/************************************************************************/ +static MVL_JOURNAL_ENTRY *find_je_start_after_forward (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo, + MVL_JOURNAL_ENTRY *start_je, + MVL_JOURNAL_ENTRY *stop_je) + { +MVL_JOURNAL_ENTRY *je; +MVL_JOURNAL_ENTRY *start_after_entry_je=NULL; /* First entry that passes*/ + /* "Start After Entry Spec."*/ +MVL_JOURNAL_ENTRY *start_after_time_je=NULL; /* First entry that passes*/ + /* "Start After Time Spec."*/ + + /* The variables "start_after_entry_je" and/or "start_after_time_je"*/ + /* will be set to non-NULL values if they are found. */ + /* If one of them is found, adjust "start_entry" accordingly. */ + for (je = start_je; + je != stop_je; + je = (MVL_JOURNAL_ENTRY *) list_get_next (jCtrl->entries, je)) + { + /* Check for matching "entry_spec" */ + if (je->entry_id_len == reqInfo->entry_spec_len && + !memcmp (je->entry_id, reqInfo->entry_spec, je->entry_id_len)) + { /* entry spec matches */ + start_after_entry_je = je; + break; /* Done checking. */ + } + + /* If haven't found matching "entry_spec" yet, check "time_spec". */ + if (start_after_time_je == NULL) + { /* "time_spec" match not found yet. */ + if (je->occur_time.day > reqInfo->time_spec.day || + (je->occur_time.day == reqInfo->time_spec.day && + je->occur_time.ms > reqInfo->time_spec.ms) ) + { /* entry time > time spec. */ + /* Save this but keep checking for matching "entry_spec". */ + start_after_time_je = je; /* DO NOT "break" */ + } + } + } /* end "for" */ + + /* If found match on Start After Entry, start with NEXT entry. */ + /* If only found match on Start After Time, start with THAT entry.*/ + if (start_after_entry_je) + start_je = (MVL_JOURNAL_ENTRY *) list_get_next (jCtrl->entries, + start_after_entry_je); + else if (start_after_time_je) + start_je = start_after_time_je; + else + start_je = NULL; /* Didn't find either. Return 0 entries.*/ + return (start_je); + } + +/************************************************************************/ +/************************************************************************/ +static MVL_JOURNAL_ENTRY *find_je_start_after_backward (MVL_JOURNAL_CTRL *jCtrl, + JREAD_REQ_INFO *reqInfo, + MVL_JOURNAL_ENTRY *start_je, + MVL_JOURNAL_ENTRY *stop_je) + { +MVL_JOURNAL_ENTRY *je; +MVL_JOURNAL_ENTRY *start_after_entry_je=NULL; /* First entry that passes*/ + /* "Start After Entry Spec."*/ +MVL_JOURNAL_ENTRY *start_after_time_je=NULL; /* First entry that passes*/ + /* "Start After Time Spec."*/ + + /* The variables "start_after_entry_je" and/or "start_after_time_je" */ + /* will be set to non-NULL values if they are found. */ + /* If one of them is found, adjust "start_entry" accordingly. */ + for (je = start_je; + je != stop_je; + je = (MVL_JOURNAL_ENTRY *) list_find_prev ((DBL_LNK *) jCtrl->entries, (DBL_LNK *) je)) + { + /* Check for matching "entry_spec" */ + if (je->entry_id_len == reqInfo->entry_spec_len && + !memcmp (je->entry_id, reqInfo->entry_spec, je->entry_id_len)) + { /* entry spec matches */ + start_after_entry_je = je; + break; /* Done checking. */ + } + + /* If haven't found matching "entry_spec" yet, check "time_spec". */ + if (start_after_time_je == NULL) + { /* "time_spec" match not found yet. */ + if (je->occur_time.day < reqInfo->time_spec.day || + (je->occur_time.day == reqInfo->time_spec.day && + je->occur_time.ms < reqInfo->time_spec.ms) ) + { /* entry time < time spec. */ + /* Save this but keep checking for matching "entry_spec". */ + start_after_time_je = je; /* DO NOT "break" */ + } + } + } /* end "for" */ + + /* If found match on Start After Entry, start with NEXT entry. */ + /* If only found match on Start After Time, start with THAT entry.*/ + if (start_after_entry_je) + start_je = (MVL_JOURNAL_ENTRY *) list_find_prev ((DBL_LNK *) jCtrl->entries, + (DBL_LNK *) start_after_entry_je); + else if (start_after_time_je) + start_je = start_after_time_je; + else + start_je = NULL; /* Didn't find either. Return 0 entries.*/ + return (start_je); + } + +/************************************************************************/ +/************************************************************************/ +ST_BOOLEAN check_je_list_of_var (JREAD_REQ_INFO *reqInfo, + MVL_JOURNAL_ENTRY *je) + { +ST_BOOLEAN retcode = SD_FALSE; /* No match. */ +ST_INT j, k; +ST_CHAR **list_of_var; + + if (reqInfo->list_of_var_pres) + { + list_of_var = (ST_CHAR **) (reqInfo + 1); + + if (je->entry_form_tag == JE_FORM_DATA + && je->ef.data.list_of_var_pres) + { + for (j = 0; j < reqInfo->num_of_var; j++) + { + for (k = 0; k < je->ef.data.num_of_var; k++) + { + if (!strcmp (je->ef.data.list_of_var[k].var_tag, list_of_var [j])) + retcode = SD_TRUE; /* Matched. */ + } /* end "for" loop */ + } /* end "for" loop */ + } + } /* End "if (reqInfo->list_of_var_pres)" */ + else + { /* No "List of Variables" to check. This one must be OK.*/ + retcode = SD_TRUE; /* Just as good as a match. */ + } + return (retcode); + } + diff --git a/mmslib/mvlu/mvl_obj.c b/mmslib/mvlu/mvl_obj.c new file mode 100644 index 0000000..34c57e9 --- /dev/null +++ b/mmslib/mvlu/mvl_obj.c @@ -0,0 +1,1131 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 2005, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_obj.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_vmd_dom_add */ +/* mvl_vmd_var_add */ +/* mvl_vmd_nvl_add */ +/* mvl_vmd_jou_add */ +/* mvl_vmd_dom_remove */ +/* mvl_vmd_var_remove */ +/* mvl_vmd_nvl_remove */ +/* mvl_vmd_jou_remove */ +/* mvl_nvl_create */ +/* mvl_nvl_destroy */ +/* mvl_vmd_create */ +/* mvl_vmd_destroy */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/26/08 JRB 28 mvl_vmd_destroy: do NOT free var->data (do */ +/* not know if it was allocated). */ +/* Check var or NVL is deletable before delete. */ +/* mvl_vmd_dom_remove: remove dom objects first.*/ +/* mvl_dom_destroy: do NOT remove dom objects. */ +/* Add mvl_var_add_alloc, mvl_var_create_alloc. */ +/* Add mvl_var_create_derived. */ +/* Remove unused functions. */ +/* 02/21/07 JRB 27 Fix funct names in this module header. */ +/* 12/04/06 JRB 26 mvl_vmd_destroy: add arg to specify which VMD*/ +/* and DO NOT destroy all rpt_ctrl (let user). */ +/* 10/30/06 JRB 25 Add vmd_ctrl arg to several functions & chg */ +/* prefix from "mvl_" to "mvl_vmd_". */ +/* Add vmd_ctrl, net_info args to mvl_nvl_create.*/ +/* Check that (net_info!=NULL) before using it. */ +/* Move "*_delete" to mvl_objb.c with other */ +/* insert/delete functions. */ +/* Add mvl_vmd_create. */ +/* 08/09/06 JRB 24 Free "last_data" only in mvl_var_destroy. */ +/* Save type_ctrl in MVL_VAR_ASSOC. */ +/* mvl_vmd_destroy: free mvl61850_rpt_ctrl_list.*/ +/* 01/30/06 GLB 23 Integrated porting changes for VMS */ +/* 10/25/05 EJV 22 Fix "last_data" memory leaks: alloc only if */ +/* last_data==NULL, free only if last_data!=NULL.*/ +/* 09/22/05 JRB 21 mvl_vmd_destroy: del VMD-spec vars, NVLs too.*/ +/* 06/29/05 CRM 20 Add mvl_vmd_destroy. */ +/* 06/27/05 JRB 19 Alloc "va->last_data" in mvl_nvl_create & */ +/* free it in mvl_nvl_destroy so special NVL */ +/* functs not needed for IEC/UCA reports. */ +/* 06/27/05 JRB 18 mvl_var_create: chk type. */ +/* 04/27/05 CRM 17 Added code to free dom->jou_tbl in */ +/* mvl_dom_destroy */ +/* 06/04/04 JRB 16 mvl_var_create: if (data), set use_static_data.*/ +/* 10/03/03 JRB 15 mvl_nvl_add: set nvl_scope in MVL_NVLIST_CTRL*/ +/* mvl_nvl_add/mvl_var_add: chk for valid dom first*/ +/* 02/25/02 MDE 14 Now get max PDU size from mvl_cfg_info */ +/* 01/23/02 EJV 13 Added journals to domain: */ +/* mvl_init_dom - added max_num_jou param */ +/* mvl_dom_resize - added max_num_jou param */ +/* mvl_dom_create - added max_num_jou param */ +/* mvl_dom_add - added max_num_jou param */ +/* mvl_clear_dom_objs -added code for journals*/ +/* mvl_jou_delete - added DOM_SPEC case */ +/* 10/25/00 JRB 12 Del u_mvl funct ptrs. Call functs directly. */ +/* Control with #ifdefs. */ +/* 04/14/00 JRB 11 Move sort & compare code to mvl_objb.c */ +/* 04/12/00 MDE 10 Moved AA resize code to mvl_acse.c */ +/* 01/21/00 MDE 09 Now use MEM_SMEM for dynamic memory */ +/* 09/15/99 JRB 08 Mv mvl_obj_nosort to mvl_objb.c for DOS link */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 09/07/99 MDE 06 Changed MVL_VA_SCOPE to MVL_SCOPE */ +/* 07/12/99 MDE 05 Fixed problem 'destroying' dom w/NVL or VAR */ +/* 04/07/99 MDE 04 Logging improvements */ +/* 03/18/99 MDE 03 Enhanced dynamic object facilities */ +/* 01/20/99 JRB 02 Reduce # of functions. Chg names and args. */ +/* Call new "mvl_???_insert" functions. */ +/* Add ..nvl_remove, ..nvl_create, ..nvl_destroy*/ +/* 11/18/98 MDE 01 Created */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mvl_acse.h" +#include "mvl_log.h" +#if defined(MVL_UCA) +#include "mvl_uca.h" /* need "MVLU_RPT_*" */ +#endif + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +ST_VOID (*u_mvl_dom_destroy) (MVL_DOM_CTRL *dom); +ST_VOID (*u_mvl_var_destroy)(MVL_VAR_ASSOC *va); +ST_VOID (*u_mvl_nvl_destroy) (MVL_NVLIST_CTRL *nvl); +ST_VOID (*u_mvl_jou_destroy) (MVL_JOURNAL_CTRL *jou); + +/************************************************************************/ +/* SCOPE RESIZING FUNCTIONS */ +/************************************************************************/ +/************************************************************************/ +/* mvl_vmd_resize */ +/************************************************************************/ + +ST_VOID mvl_vmd_resize (ST_INT max_num_dom, ST_INT max_num_var, + ST_INT max_num_nvl, ST_INT max_num_jou) + { + if (max_num_dom < mvl_vmd.num_dom) + { + MVL_LOG_NERR0 ("Resizing VMD: new max DOM is less than current"); + max_num_dom = mvl_vmd.num_dom; + } + if (max_num_var < mvl_vmd.num_var_assoc) + { + MVL_LOG_NERR0 ("Resizing VMD: new max VA is less than current"); + max_num_var = mvl_vmd.num_var_assoc; + } + if (max_num_nvl < mvl_vmd.num_nvlist) + { + MVL_LOG_NERR0 ("Resizing VMD: new max NVL is less than current"); + max_num_nvl = mvl_vmd.num_nvlist; + } + if (max_num_jou < mvl_vmd.num_jou) + { + MVL_LOG_NERR0 ("Resizing VMD: new max JOU is less than current"); + max_num_jou = mvl_vmd.num_jou; + } + + _mvl_resize_ptr_tbl (&(mvl_vmd.max_num_dom), + (ST_VOID ***)&(mvl_vmd.dom_tbl), max_num_dom); + _mvl_resize_ptr_tbl (&(mvl_vmd.max_num_var_assoc), + (ST_VOID ***)&(mvl_vmd.var_assoc_tbl), max_num_var); + _mvl_resize_ptr_tbl (&(mvl_vmd.max_num_nvlist), + (ST_VOID ***)&(mvl_vmd.nvlist_tbl), max_num_nvl); + _mvl_resize_ptr_tbl (&(mvl_vmd.max_num_jou), + (ST_VOID ***)&(mvl_vmd.jou_tbl), max_num_jou); + } + +/************************************************************************/ +/* mvl_dom_resize */ +/************************************************************************/ + +ST_VOID mvl_dom_resize (MVL_DOM_CTRL *dom, ST_INT max_num_var, + ST_INT max_num_nvl, ST_INT max_num_jou) + { + if (max_num_var < dom->num_var_assoc) + { + MVL_LOG_NERR0 ("Resizing Domain: new max VA is less than current"); + max_num_var = dom->num_var_assoc; + } + if (max_num_nvl < dom->num_nvlist) + { + MVL_LOG_NERR0 ("Resizing Domain: new max NVL is less than current"); + max_num_nvl = dom->num_nvlist; + } + if (max_num_jou < dom->num_jou) + { + MVL_LOG_NERR0 ("Resizing Domain: new max JOU is less than current"); + max_num_jou = dom->num_jou; + } + + _mvl_resize_ptr_tbl (&(dom->max_num_var_assoc), + (ST_VOID ***)&(dom->var_assoc_tbl), max_num_var); + _mvl_resize_ptr_tbl (&(dom->max_num_nvlist), + (ST_VOID ***)&(dom->nvlist_tbl), max_num_nvl); + _mvl_resize_ptr_tbl (&(dom->max_num_jou), + (ST_VOID ***)&(dom->jou_tbl), max_num_jou); + } + +/************************************************************************/ +/* _mvl_resize_ptr_tbl */ +/************************************************************************/ + +ST_VOID _mvl_resize_ptr_tbl (ST_INT *p_max_num, + ST_VOID ***p_ptr_tbl, ST_INT new_size) + { + +/* See if something needs to be done at all */ + if (*p_max_num == new_size) + return; + +/* See if the table is going away altogether */ + if (new_size != 0) + { + if (*p_max_num != 0) + *p_ptr_tbl = (ST_VOID **) M_REALLOC (MSMEM_GEN, *p_ptr_tbl, (new_size * sizeof (ST_VOID *))); + else /* We did not have a table, but need one now */ + *p_ptr_tbl = (ST_VOID **) M_CALLOC (MSMEM_GEN, new_size, sizeof (ST_VOID *)); + } + else + { /* If we had a table, we need to free it */ + if (*p_max_num != 0) + M_FREE (MSMEM_GEN, *p_ptr_tbl); + } + *p_max_num = new_size; + } + +/************************************************************************/ +/* mvl_nvl_remove_all */ +/* Remove all VMD-Specific NVLs & Domain-Specific NVLs in this VMD. */ +/* CRITICAL: Use "mvl_vmd_nvl_remove". It makes sure it is safe to */ +/* remove each NVL. */ +/* RETURNS: SD_SUCCESS or SD_FAILURE */ +/************************************************************************/ +ST_RET mvl_nvl_remove_all (MVL_VMD_CTRL *vmd_ctrl) + { +ST_INT didx; +MVL_DOM_CTRL *dom; + + /* Destroy VMD-Specific NVLs. */ + while (vmd_ctrl->num_nvlist) + { + MVL_NVLIST_CTRL *nvl; + OBJECT_NAME obj; + nvl = vmd_ctrl->nvlist_tbl[vmd_ctrl->num_nvlist-1]; /* point to last nvl*/ + obj.obj_name.vmd_spec = nvl->name; + obj.object_tag = VMD_SPEC; + if (mvl_vmd_nvl_remove (vmd_ctrl, &obj, NULL) != SD_SUCCESS) + { + MVL_LOG_ERR1 ("Error removing VMD-specific NVL='%s'", nvl->name); + return (SD_FAILURE); + } + } + + /* Destroy Domain-Specific NVLs in all domains. */ + for (didx = 0; didx < vmd_ctrl->num_dom; didx++) + { + dom = vmd_ctrl->dom_tbl [didx]; + while (dom->num_nvlist) + { + MVL_NVLIST_CTRL *nvl; + OBJECT_NAME obj; + nvl = dom->nvlist_tbl[dom->num_nvlist-1]; /* point to last nvl*/ + obj.obj_name.item_id = nvl->name; + obj.domain_id = dom->name; + obj.object_tag = DOM_SPEC; + if (mvl_vmd_nvl_remove (vmd_ctrl, &obj, NULL) != SD_SUCCESS) + { + MVL_LOG_ERR2 ("Error removing NVL='%s' in domain '%s'", nvl->name, dom->name); + return (SD_FAILURE); + } + } + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/* mvl_var_in_nvl */ +/* Is this var used in this NVL? */ +/************************************************************************/ +ST_BOOLEAN mvl_var_in_nvl (MVL_NVLIST_CTRL *nvl, MVL_VAR_ASSOC *var) + { +ST_INT vidx; +MVL_VAR_ASSOC *nvl_var; /* variable used in a NVL */ + + for (vidx = 0; vidx < nvl->num_of_entries; vidx++) + { + nvl_var = nvl->entries[vidx]; + if (nvl_var == var || nvl_var->base_va == var) + { /* This variable (or a variable derived from it) is used in the NVL. */ + return(SD_TRUE); + } + } + return (SD_FALSE); /* This variable is NOT used in the NVL. */ + } +/************************************************************************/ +/* mvl_var_deletable */ +/* Is this var deletable (i.e. NOT referenced by other objects)? */ +/************************************************************************/ +ST_BOOLEAN mvl_var_deletable (MVL_VMD_CTRL *vmd_ctrl, MVL_VAR_ASSOC *var) + { +ST_INT didx, nvlidx; +MVL_DOM_CTRL *dom; +MVL_NVLIST_CTRL *nvl; + assert (var->base_va == NULL); /* DEBUG: these are always base variables.*/ + + /* Make sure var is not used in any VMD-specific NVL. */ + for (nvlidx = 0; nvlidx < vmd_ctrl->num_nvlist; ++nvlidx) + { + nvl = vmd_ctrl->nvlist_tbl[nvlidx]; + if (mvl_var_in_nvl (nvl, var)) + { + MVL_LOG_ERR2 ("Variable=%s cannot be deleted because it is used in VMD-specific NVL=%s", + var->name, nvl->name); + return(SD_FALSE); + } + } + + /* Make sure var is not used in any Domain-specific NVL in any Domain. */ + for (didx = 0; didx < vmd_ctrl->num_dom; didx++) + { + dom = vmd_ctrl->dom_tbl [didx]; + for (nvlidx = 0; nvlidx < dom->num_nvlist; nvlidx++) + { + nvl = dom->nvlist_tbl[nvlidx]; + if (mvl_var_in_nvl (nvl, var)) + { + MVL_LOG_ERR2 ("Variable=%s cannot be deleted because it is used in Domain-specific NVL=%s", + var->name, nvl->name); + return(SD_FALSE); + } + } + } + return (SD_TRUE); /* ok to delete it */ + } +/************************************************************************/ +/* mvl_nvl_deletable */ +/* Is this NVL deletable (i.e. NOT referenced by other objects)? */ +/************************************************************************/ +ST_BOOLEAN mvl_nvl_deletable (MVL_VMD_CTRL *vmd_ctrl, MVL_NVLIST_CTRL *nvl) + { +#if defined(MVL_UCA) /* check for IEC 61850 or UCA RCBs using this NVL*/ +MVLU_RPT_CTRL *rptCtrl; + + /* NOTE: the flag "nvl->mms_deletable" is only used by the MMS service*/ + /* DeleteNamedVariableList, not to prevent MVL from deleting this NVL.*/ + + /* See if NVL is used in any IEC 61850 Report Control Block. */ + //lnk编译修改:原å‰ç½®ç¨‹åºæœªä½¿ç”¨ + /*for (rptCtrl = mvl61850_rpt_ctrl_list; + rptCtrl != NULL; + rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvl61850_rpt_ctrl_list, rptCtrl)) + { + if (rptCtrl->dsNvl == nvl) + { + MVL_LOG_ERR1 ("NVL='%s' cannot be deleted because it is used in a IEC 61850 Report Control Block", + nvl->name); + return (SD_FALSE); + } + }*/ + /* See if NVL is used in any UCA Report Control Block. */ + //lnk编译修改:原å‰ç½®ç¨‹åºæœªä½¿ç”¨ + /*for (rptCtrl = mvlu_rpt_ctrl_list; + rptCtrl != NULL; + rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvlu_rpt_ctrl_list, rptCtrl)) + { + if (rptCtrl->dsNvl == nvl) + { + MVL_LOG_ERR1 ("NVL='%s' cannot be deleted because it is used in a UCA Report Control Block", + nvl->name); + return (SD_FALSE); + } + }*/ +#endif /* defined(MVL_UCA) */ + /* NOTE: if not MVL_UCA, nothing to check. */ + return (SD_TRUE); /* ok to delete it */ + } + +/************************************************************************/ +/************************************************************************/ +/* DOMAIN */ +/************************************************************************/ +/************************************************************************/ +/* mvl_vmd_dom_add */ +/* Add a domain. Allocate, fill in, and insert into table. */ +/************************************************************************/ + +MVL_DOM_CTRL *mvl_vmd_dom_add (MVL_VMD_CTRL *vmd_ctrl, ST_CHAR *name, ST_INT max_num_var, + ST_INT max_num_nvl, ST_INT max_num_jou, + ST_BOOLEAN copy_name) + { +MVL_DOM_CTRL *dom; + + dom = mvl_dom_create (name, max_num_var, max_num_nvl, max_num_jou, copy_name); + +/* Insert it in table. */ + if (mvl_vmd_dom_insert (vmd_ctrl, dom)) + { /* Failed. */ + M_FREE (MSMEM_GEN, dom); + return (NULL); + } + + return (dom); + } + +/************************************************************************/ +/* mvl_dom_create */ +/************************************************************************/ + +MVL_DOM_CTRL *mvl_dom_create (ST_CHAR *name, ST_INT max_num_var, + ST_INT max_num_nvl, ST_INT max_num_jou, + ST_BOOLEAN copy_name) + { +MVL_DOM_CTRL *dom; + +/* Allocate object and fill in "name". */ + if (copy_name) + { + dom = (MVL_DOM_CTRL *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_DOM_CTRL) + + strlen (name) + 1); + dom->name = (ST_CHAR *) (dom+1); + strcpy (dom->name, name); /* copy name */ + } + else + { + dom = (MVL_DOM_CTRL *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_DOM_CTRL)); + dom->name = name; /* point to user buffer */ + } + +/* Allocate the pointer tables */ + mvl_dom_resize (dom, max_num_var, max_num_nvl, max_num_jou); + return (dom); + } + +/************************************************************************/ +/* mvl_dom_cleanup */ +/* Remove all objects (NVLs, variables, journals) from this domain. */ +/* CRITICAL: Use "*_remove" functions. They make sure it is safe to */ +/* remove each object. */ +/************************************************************************/ + +ST_RET mvl_dom_cleanup (MVL_VMD_CTRL *vmd_ctrl, MVL_DOM_CTRL *dom) + { +ST_INT i; + + if (dom->foundry_objects) + { + MVL_LOG_NERR1 ("Cannot remove objects from domain '%s' because Foundry objects present", dom->name); + return (SD_FAILURE); + } + + /* Remove all NVL from this domain. Stop on first error. */ + while (dom->num_nvlist) + { + MVL_NVLIST_CTRL *nvl; + OBJECT_NAME obj; + nvl = dom->nvlist_tbl[dom->num_nvlist-1]; /* point to last nvl*/ + obj.obj_name.item_id = nvl->name; + obj.domain_id = dom->name; + obj.object_tag = DOM_SPEC; + if (mvl_vmd_nvl_remove (vmd_ctrl, &obj, NULL) != SD_SUCCESS) + { + MVL_LOG_ERR2 ("Error removing NVL='%s' from domain='%s'", + nvl->name, dom->name); + return (SD_FAILURE); + } + } + + /* Remove all variables from this domain. Stop on first error. */ + while (dom->num_var_assoc > 0) + { + MVL_VAR_ASSOC *var; + OBJECT_NAME obj; + var = dom->var_assoc_tbl[dom->num_var_assoc-1]; /* point to last var*/ + obj.obj_name.item_id = var->name; + obj.domain_id = dom->name; + obj.object_tag = DOM_SPEC; + if (mvl_vmd_var_remove (vmd_ctrl, &obj, NULL) != SD_SUCCESS) + { + MVL_LOG_ERR2 ("Error removing variable='%s' from domain='%s'", + var->name, dom->name); + return (SD_FAILURE); + } + } + +/* Delete the Journal control table. */ +/* DEBUG: Should use mvl_vmd_jou_remove here but it can't fail, so */ +/* using mvl_jou_destroy is just as good for now. */ + if (dom->max_num_jou) + { + for (i = 0; i < dom->num_jou; ++i) + mvl_jou_destroy (dom->jou_tbl[i]); + } + dom->num_jou = 0; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* mvl_vmd_dom_remove */ +/************************************************************************/ + +ST_RET mvl_vmd_dom_remove (MVL_VMD_CTRL *vmd_ctrl, ST_CHAR *dom_name) + { +MVL_DOM_CTRL *dom; +ST_RET retcode = SD_FAILURE; + + dom = mvl_vmd_find_dom (vmd_ctrl, dom_name); + if (dom != NULL) + { + /* Remove all objects in domain before delete/destroy.*/ + retcode = mvl_dom_cleanup (vmd_ctrl, dom); + if (retcode) + MVL_LOG_ERR1 ("Error removing objects from domain, so cannot remove domain '%s'", + dom->name); + else + { /* cleanup successful */ + /* NOTE: this delete should never fail because we already found it.*/ + dom = mvl_vmd_dom_delete (vmd_ctrl, dom_name); + if (dom != NULL) + mvl_dom_destroy (dom); /* cannot fail. retcode already = SD_SUCCESS*/ + else + retcode = SD_FAILURE; /* delete failed. Should never happen */ + } + } + return (retcode); + } + +/************************************************************************/ +/* mvl_dom_destroy */ +/* NOTE: this assumes all objects already removed from domain. */ +/************************************************************************/ + +ST_VOID mvl_dom_destroy (MVL_DOM_CTRL *dom) + { + if (u_mvl_dom_destroy != NULL) + (*u_mvl_dom_destroy)(dom); + + if (dom->max_num_var_assoc != 0) + M_FREE (MSMEM_GEN, dom->var_assoc_tbl); + + if (dom->max_num_nvlist != 0) + M_FREE (MSMEM_GEN, dom->nvlist_tbl); + + if (dom->max_num_jou != 0) + M_FREE (MSMEM_GEN, dom->jou_tbl); + + M_FREE (MSMEM_GEN, dom); + } + +/************************************************************************/ +/**** VARIABLE ASSOCIATIONS */ +/************************************************************************/ +/* mvl_vmd_var_add */ +/* Add a variable association. Allocate, fill in, and insert into table.*/ +/* NOT RECOMMENDED: use mvl_var_add_alloc. */ +/************************************************************************/ + +MVL_VAR_ASSOC *mvl_vmd_var_add (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, MVL_NET_INFO *net_info, + ST_INT type_id, + ST_VOID *data, + MVL_VAR_PROC *proc, + ST_BOOLEAN copy_name) + { +MVL_VAR_ASSOC *va; +MVL_DOM_CTRL *dom = NULL; + +/* Find domain, if necessary, before allocating anything. */ + if (obj->object_tag==DOM_SPEC && (dom = mvl_vmd_find_dom (vmd_ctrl, obj->domain_id)) == NULL) + { + MVL_LOG_ERR2 ("Error creating VAR '%s': domain '%s' not found", + obj->obj_name.vmd_spec, obj->domain_id); + return (NULL); + } + + va = mvl_var_create (obj, type_id, data, proc, copy_name); + +/* Insert it in table. */ + if (va) + { + if (mvl_vmd_var_insert (vmd_ctrl, va, obj, net_info)) + { /* Failed. */ + mvl_var_destroy (va); /* destroy var just created */ + return (NULL); + } + } + + return (va); + } + +/************************************************************************/ +/* mvl_var_create */ +/* NOT RECOMMENDED: use mvl_var_create_alloc. */ +/************************************************************************/ + +MVL_VAR_ASSOC *mvl_var_create (OBJECT_NAME *obj, ST_INT type_id, + ST_VOID *data, MVL_VAR_PROC *proc, + ST_BOOLEAN copy_name) + { +MVL_VAR_ASSOC *va; +MVL_TYPE_CTRL *type_ctrl; + + type_ctrl = mvl_type_ctrl_find (type_id); + if (type_ctrl == NULL) + { + MVL_LOG_ERR0 ("Cannot create variable (type_id invalid)."); + return (NULL); + } + +/* Allocate object and fill in "name". */ + if (copy_name) + { + va = (MVL_VAR_ASSOC *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_VAR_ASSOC) + + strlen (obj->obj_name.vmd_spec) + 1); + va->name = (ST_CHAR *) (va+1); + strcpy (va->name, obj->obj_name.vmd_spec); /* copy name */ + } + else + { + va = (MVL_VAR_ASSOC *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_VAR_ASSOC)); + va->name = obj->obj_name.vmd_spec; /* point to user buffer */ + } + +/* Fill in rest of object. */ + va->type_id = type_id; + va->type_ctrl = type_ctrl; /* don't need to call mvl_get_runtime */ + /* to get type details. */ + va->data = data; +#if defined(MVL_UCA) +/* If caller set the data ptr (!=NULL), assume they want to use static data.*/ + if (data!=NULL) + va->use_static_data = SD_TRUE; +#endif + va->proc = proc; + return (va); + } + +/************************************************************************/ +/* mvl_var_add_alloc */ +/* Add a variable association. Allocate, fill in, and insert into table.*/ +/************************************************************************/ +MVL_VAR_ASSOC *mvl_var_add_alloc (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info, + ST_INT type_id, + MVL_VAR_PROC *proc) + { +MVL_VAR_ASSOC *va; +MVL_DOM_CTRL *dom = NULL; + +/* Find domain, if necessary, before allocating anything. */ + if (obj->object_tag==DOM_SPEC && (dom = mvl_vmd_find_dom (vmd_ctrl, obj->domain_id)) == NULL) + { + MVL_LOG_ERR2 ("Error creating VAR '%s': domain '%s' not found", + obj->obj_name.vmd_spec, obj->domain_id); + return (NULL); + } + + va = mvl_var_create_alloc (obj->obj_name.vmd_spec, type_id, proc); + +/* Insert it in table. */ + if (va) + { + if (mvl_vmd_var_insert (vmd_ctrl, va, obj, net_info)) + { /* Failed. */ + mvl_var_destroy (va); /* destroy var just created */ + return (NULL); + } + } + return (va); + } + +/************************************************************************/ +/* mvl_var_create_alloc */ +/* Create a new variable. ALWAYS allocate a buffer for */ +/* the data (buffer is automatically freed when variable is destroyed). */ +/* CRITICAL: DO NOT use for "derived" variables. Instead use */ +/* mvl_var_create_derived. */ +/************************************************************************/ +MVL_VAR_ASSOC *mvl_var_create_alloc (ST_CHAR *name, + ST_INT type_id, + MVL_VAR_PROC *proc) + { +MVL_VAR_ASSOC *va; +MVL_TYPE_CTRL *type_ctrl; + + type_ctrl = mvl_type_ctrl_find (type_id); + if (type_ctrl == NULL) + { + MVL_LOG_ERR0 ("Cannot create variable (type_id invalid)."); + return (NULL); + } + + /* Allocate one buffer for MVL_VAR_ASSOC plus "data" plus "name". */ + va = (MVL_VAR_ASSOC *) chk_calloc (1, + sizeof (MVL_VAR_ASSOC) /* space for struct*/ + + type_ctrl->data_size /* space for "data"*/ + + strlen (name) + 1); /* space for "name"*/ + + /* Set data ptr right after MVL_VAR_ASSOC struct. */ + /* NOTE: data is before name so alignment should be good for any data.*/ + va->data = (va+1); + /* Set name ptr right after data. */ + va->name = ((ST_CHAR *) (va->data)) + type_ctrl->data_size; + + strcpy (va->name, name); /* copy name */ + + /* Fill in rest of object. */ + va->type_id = type_id; + va->type_ctrl = type_ctrl; /* save for easy access later. */ + + va->use_static_data = SD_TRUE; /* always SD_TRUE */ + + va->proc = proc; + return (va); + } + +/************************************************************************/ +/* mvl_var_create_derived */ +/* Create a "derived" variable. */ +/* NOTE: Structure member "proc" always set to NULL. */ +/* Structure member "data" points inside base variable. */ +/************************************************************************/ + +MVL_VAR_ASSOC *mvl_var_create_derived (ST_CHAR *name, + ST_INT type_id, + MVL_VAR_ASSOC *baseVa, /* base variable from which to derive */ + ST_INT offset_from_base, + ST_RTINT prim_num) + { +MVL_VAR_ASSOC *va; +MVL_TYPE_CTRL *type_ctrl; + + type_ctrl = mvl_type_ctrl_find (type_id); + if (type_ctrl == NULL) + { + MVL_LOG_ERR0 ("Cannot create variable (type_id invalid)."); + return (NULL); + } + +/* Allocate object and fill in "name". */ + va = (MVL_VAR_ASSOC *) chk_calloc (1, sizeof (MVL_VAR_ASSOC) + + strlen (name) + 1); + va->name = (ST_CHAR *) (va+1); + strcpy (va->name, name); /* copy name */ + +/* Fill in rest of object. */ + va->type_id = type_id; + va->type_ctrl = type_ctrl; /* save for easy access later. */ + + /* va->proc = NULL (due to calloc above) */ + + /* Set special "va" elements only for derived variables. */ + va->base_va = baseVa; + va->user_info = baseVa->user_info; + + /* Save offset_from_base & prim_num passed as arguments. */ + va->offset_from_base = offset_from_base; + va->prim_num = prim_num; + + if (va->base_va->use_static_data) + va->data = (((ST_CHAR *) va->base_va->data) + va->offset_from_base); + /* else caller must set va->data. */ + + return (va); + } + +/************************************************************************/ +/* mvl_vmd_var_remove */ +/************************************************************************/ + +ST_RET mvl_vmd_var_remove (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, MVL_NET_INFO *net_info) + { +MVL_VAR_ASSOC *va; + + /* First find it & make sure it is deletable. */ + va = mvl_vmd_find_var (vmd_ctrl, obj, net_info); + if (va == NULL || mvl_var_deletable (vmd_ctrl, va) == SD_FALSE) + { + MVL_LOG_ERR1 ("Error deleting variable='%s': not found or not deletable.", + obj->obj_name.vmd_spec); + return (SD_FAILURE); + } + + va = mvl_vmd_var_delete (vmd_ctrl, obj, net_info); + if (va == NULL) + return (SD_FAILURE); + + mvl_var_destroy (va); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* mvl_var_destroy */ +/************************************************************************/ + +ST_VOID mvl_var_destroy (MVL_VAR_ASSOC *va) + { + if (u_mvl_var_destroy != NULL) + (*u_mvl_var_destroy)(va); + + /* "last_data" may have been allocated if this var used in NVL. */ + if (va->last_data) + chk_free (va->last_data); + /* renxiaobao 日志 + if (va->last_log_data) + chk_free (va->last_log_data);*/ + M_FREE (MSMEM_GEN, va); + } + + +/************************************************************************/ +/**** NAMED VARIABLE LISTS */ +/************************************************************************/ +/* mvl_vmd_nvl_add */ +/* Add a Named Variable List. Allocate, fill in, and insert into table. */ +/************************************************************************/ + +MVL_NVLIST_CTRL *mvl_vmd_nvl_add (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *nvl_obj, MVL_NET_INFO *net_info, + ST_INT num_var, + OBJECT_NAME *var_obj, /* array of var names */ + ST_BOOLEAN copy_name) + { +MVL_NVLIST_CTRL *nvl; +MVL_DOM_CTRL *dom = NULL; + +/* Find domain, if necessary, before allocating anything. */ + if (nvl_obj->object_tag==DOM_SPEC && (dom = mvl_vmd_find_dom (vmd_ctrl, nvl_obj->domain_id)) == NULL) + { + MVL_LOG_ERR2 ("Error creating NVL '%s': domain '%s' not found", + nvl_obj->obj_name.vmd_spec, nvl_obj->domain_id); + return (NULL); + } + +/* Allocate it AND fill it in. */ + nvl = mvl_nvl_create (vmd_ctrl, nvl_obj->obj_name.vmd_spec, num_var, var_obj, net_info, copy_name); + if (nvl == NULL) + return (NULL); + +/* Add scope info to "nvl". */ + nvl->nvl_scope.scope = nvl_obj->object_tag; + nvl->nvl_scope.dom = dom; /* NOTE: NULL if not DOM_SPEC (see above) */ + +/* Insert it in table. */ + if (mvl_vmd_nvl_insert (vmd_ctrl, nvl, nvl_obj, net_info)) + { /* Failed. */ + mvl_nvl_destroy (nvl); + return (NULL); + } + + return (nvl); + } + +/************************************************************************/ +/* mvl_nvl_create */ +/************************************************************************/ +/* Given a list of MMS object names, create a MVL Named Variable List. */ +/* This can include both configured and MVLU manufactured variables */ +/* Use 'mvl_nvl_destroy' to free this NVL. */ + +MVL_NVLIST_CTRL *mvl_nvl_create (MVL_VMD_CTRL *vmd_ctrl, + ST_CHAR *nvlName, + ST_INT numNames, + OBJECT_NAME *var_obj, /* array of var obj names*/ + MVL_NET_INFO *net_info, /* where to find var_obj*/ + /* if it is AA_SPEC */ + ST_BOOLEAN copy_name) + { +MVL_NVLIST_CTRL *nvl; +ST_INT j; + +/* Allocate object and fill in "name". */ + if (copy_name) + { + nvl = (MVL_NVLIST_CTRL *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_NVLIST_CTRL) + + strlen (nvlName) + 1); + nvl->name = (ST_CHAR *) (nvl+1); + strcpy (nvl->name, nvlName); /* copy name */ + } + else + { + nvl = (MVL_NVLIST_CTRL *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_NVLIST_CTRL)); + nvl->name = nvlName; /* point to user buffer */ + } + +/* Fill in rest of object. */ + + nvl->entries = (MVL_VAR_ASSOC **) M_CALLOC (MSMEM_GEN, numNames, + sizeof (MVL_VAR_ASSOC *)); + nvl->va_scope = (MVL_SCOPE *) M_CALLOC (MSMEM_GEN, numNames, + sizeof (MVL_SCOPE)); + nvl->num_of_entries = numNames; + + for (j = 0; j < nvl->num_of_entries; ++j, ++var_obj) + { + MVL_VAR_ASSOC *var; + if ((nvl->entries[j] = var = _mvl_objname_to_va (vmd_ctrl, net_info, MMSOP_INFO_RPT, + var_obj, &nvl->va_scope[j], SD_FALSE, NULL, NULL)) == NULL) + { + MVL_LOG_ERR2 ("Error creating NVL '%s': member variable '%s' not found", + nvlName, var_obj->obj_name.vmd_spec); + mvl_nvl_destroy (nvl); + return (NULL); + } + else + { +#if defined(MVL_UCA) + /* Alloc buffer for last data (used for IEC/UCA reports). */ + if (!var->last_data) + var->last_data = chk_calloc (1, mvl_type_ctrl[var->type_id].data_size); + /*renxiaobao 日志 + if (!var->last_log_data) + var->last_log_data = chk_calloc (1, mvl_type_ctrl[var->type_id].data_size);*/ +#endif + } + } + + return (nvl); + } + + +/************************************************************************/ +/* mvl_vmd_nvl_remove */ +/* Remove a Named Variable List. Delete it from table and "destroy" it. */ +/************************************************************************/ + +ST_RET mvl_vmd_nvl_remove (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, MVL_NET_INFO *net_info) + { +MVL_NVLIST_CTRL *nvl; + +/* First find it & make sure it is deletable. */ + nvl = mvl_vmd_find_nvl (vmd_ctrl, obj, net_info); + if (nvl == NULL || mvl_nvl_deletable (vmd_ctrl, nvl) == SD_FALSE) + { + MVL_LOG_ERR1 ("Error deleting NVL='%s': not found or not deletable.", + obj->obj_name.vmd_spec); + return (SD_FAILURE); + } + +/* Delete it from table. */ + if ((nvl = mvl_vmd_nvl_delete (vmd_ctrl, obj, net_info)) == NULL) + return (SD_FAILURE); /* nvl not found */ + +/* Destroy it. */ + mvl_nvl_destroy (nvl); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* mvl_nvl_destroy */ +/************************************************************************/ +/* Free a MVL Named Variable List created by 'mvl_nvl_create' */ + +ST_VOID mvl_nvl_destroy (MVL_NVLIST_CTRL *nvl) + { +MVL_VAR_ASSOC *va; +ST_INT i; + + if (u_mvl_nvl_destroy != NULL) + (*u_mvl_nvl_destroy)(nvl); + +/* Free up any manufactured variables */ + for (i = 0; i < nvl->num_of_entries; ++i) + { + va = nvl->entries[i]; +#if defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS) +/* NOTE: "va" may be NULL if mvl_nvl_create failed while adding entries.*/ + if (va && va->va_to_free == va) + { + //u_mvl_free_va (MMSOP_INFO_RPT, va, NULL);//lnk编译删除,原å‰ç½®ç¨‹åºæœªä½¿ç”¨ + } +#endif + } + + M_FREE (MSMEM_GEN, nvl->entries); + M_FREE (MSMEM_GEN, nvl->va_scope); + M_FREE (MSMEM_GEN, nvl); + } + +/************************************************************************/ +/**** JOURNALS */ +/************************************************************************/ +/* mvl_vmd_jou_add */ +/* Add a Journal. Allocate, fill in, and insert into table. */ +/************************************************************************/ + +MVL_JOURNAL_CTRL *mvl_vmd_jou_add (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, MVL_NET_INFO *net_info, + ST_BOOLEAN copy_name) + { +MVL_JOURNAL_CTRL *jou; + + jou = mvl_jou_create (obj, net_info, copy_name); + if (mvl_vmd_jou_insert (vmd_ctrl, jou, obj, net_info)) + { /* Failed. */ + M_FREE (MSMEM_GEN, jou); + return (NULL); + } + return (jou); + } + +/************************************************************************/ +/* mvl_jou_create */ +/************************************************************************/ + +MVL_JOURNAL_CTRL *mvl_jou_create (OBJECT_NAME *obj, MVL_NET_INFO *net_info, + ST_BOOLEAN copy_name) + { +MVL_JOURNAL_CTRL *jou; + +/* Allocate object and fill in "name". */ + if (copy_name) + { + jou = (MVL_JOURNAL_CTRL *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_JOURNAL_CTRL) + + strlen (obj->obj_name.vmd_spec) + 1); + jou->name = (ST_CHAR *) (jou+1); + strcpy (jou->name, obj->obj_name.vmd_spec); /* copy name */ + } + else + { + jou = (MVL_JOURNAL_CTRL *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_JOURNAL_CTRL)); + jou->name = obj->obj_name.vmd_spec; /* point to user buffer */ + } + + return (jou); + } + +/************************************************************************/ +/* mvl_vmd_jou_remove */ +/************************************************************************/ + +ST_RET mvl_vmd_jou_remove (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, MVL_NET_INFO *net_info) + { +MVL_JOURNAL_CTRL *jou; + + jou = mvl_vmd_jou_delete (vmd_ctrl, obj, net_info); + if (jou == NULL) + return (SD_FAILURE); + + mvl_jou_destroy (jou); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* mvl_jou_destroy */ +/************************************************************************/ + +ST_VOID mvl_jou_destroy (MVL_JOURNAL_CTRL *jou) + { + if (u_mvl_jou_destroy != NULL) + (*u_mvl_jou_destroy)(jou); + + M_FREE (MSMEM_GEN, jou); + } + +/************************************************************************/ +/* mvl_vmd_create */ +/* Create a new VMD with empty object arrays. */ +/* Use "mvl_vmd_destroy" to destroy the VMD. */ +/************************************************************************/ +MVL_VMD_CTRL *mvl_vmd_create (ST_INT max_num_dom, + ST_INT max_num_var, + ST_INT max_num_nvl, + ST_INT max_num_journal) + { +MVL_VMD_CTRL *vmd_ctrl = chk_calloc (1, sizeof (MVL_VMD_CTRL)); + + vmd_ctrl->max_num_var_assoc = max_num_var; + if (vmd_ctrl->max_num_var_assoc) + vmd_ctrl->var_assoc_tbl = (MVL_VAR_ASSOC **) chk_calloc ( + vmd_ctrl->max_num_var_assoc, sizeof (MVL_VAR_ASSOC *)); + + vmd_ctrl->max_num_nvlist = max_num_nvl; + if (vmd_ctrl->max_num_nvlist) + vmd_ctrl->nvlist_tbl = (MVL_NVLIST_CTRL **) chk_calloc ( + vmd_ctrl->max_num_nvlist, sizeof (MVL_NVLIST_CTRL *)); + + vmd_ctrl->max_num_dom = max_num_dom; + if (vmd_ctrl->max_num_dom) + vmd_ctrl->dom_tbl = (MVL_DOM_CTRL **) chk_calloc ( + vmd_ctrl->max_num_dom, sizeof (MVL_DOM_CTRL *)); + + vmd_ctrl->max_num_jou = max_num_journal; + if (vmd_ctrl->max_num_jou) + vmd_ctrl->jou_tbl = (MVL_JOURNAL_CTRL **) chk_calloc ( + vmd_ctrl->max_num_jou, sizeof (MVL_JOURNAL_CTRL *)); + + return (vmd_ctrl); + }; + +/************************************************************************/ +/* mvl_vmd_destroy */ +/* Destroy all objects in this VMD. */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +ST_RET mvl_vmd_destroy (MVL_VMD_CTRL *vmd_ctrl) + { +ST_RET ret; +ST_INT j; +MVL_DOM_CTRL *dom; + + ret = SD_SUCCESS; /* default ret val: returned if LD linked list empty.*/ + + /* Remove all NVL from this VMD and from all Domains before deleting */ + /* Domains. NVLs might reference vars in other domains. */ + /* CRITICAL: Must be done first, or vars can't be destroyed later. */ + ret = mvl_nvl_remove_all (vmd_ctrl); + if (ret) + { + MVL_LOG_ERR0 ("Error destroying VMD: failed removing all NVL."); + return (ret); + } + + /* Delete VMD-Specific Variables. */ + for (j = 0; j < vmd_ctrl->num_var_assoc; ++j) + mvl_var_destroy (vmd_ctrl->var_assoc_tbl[j]); + vmd_ctrl->num_var_assoc = 0; + + /* Delete Domains (always VMD-Specific). */ + while ((dom = mvl_vmd_dom_find_last (vmd_ctrl)) != NULL) + { + ret = mvl_vmd_dom_remove (vmd_ctrl, dom->name); + + if (ret != SD_SUCCESS) + break; + } + + /* Destroy all types for this VMD. */ + if (ret == SD_SUCCESS) + ret = mvl_vmd_type_id_destroy_all (vmd_ctrl); + + /* Finally, free the tables and the VMD itself (allocated by mvl_vmd_create).*/ + /* NOTE: can't do this for "mvl_vmd" because it was created by Foundry.*/ + if (vmd_ctrl != &mvl_vmd) + { + if (vmd_ctrl->var_assoc_tbl) + chk_free (vmd_ctrl->var_assoc_tbl); + if (vmd_ctrl->nvlist_tbl) + chk_free (vmd_ctrl->nvlist_tbl); + if (vmd_ctrl->dom_tbl) + chk_free (vmd_ctrl->dom_tbl); + if (vmd_ctrl->jou_tbl) + chk_free (vmd_ctrl->jou_tbl); + chk_free (vmd_ctrl); + } + + return (ret); + } + + diff --git a/mmslib/mvlu/mvl_objb.c b/mmslib/mvlu/mvl_objb.c new file mode 100644 index 0000000..1587438 --- /dev/null +++ b/mmslib/mvlu/mvl_objb.c @@ -0,0 +1,755 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999 - 2002, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_objb.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Functions for maintaining arrays of "generic objects" */ +/* using "bsearch". */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_obj_insert */ +/* mvl_obj_delete */ +/* mvl_obj_find */ +/* mvl_obj_find_key */ +/* mvl_vmd_dom_insert */ +/* mvl_vmd_var_insert */ +/* mvl_vmd_nvl_insert */ +/* mvl_vmd_jou_insert */ +/* mvl_vmd_dom_delete */ +/* mvl_vmd_var_delete */ +/* mvl_vmd_nvl_delete */ +/* mvl_vmd_jou_delete */ +/* mvl_vmd_find_dom */ +/* mvl_vmd_find_var */ +/* mvl_vmd_find_nvl */ +/* mvl_vmd_find_jou */ +/* mvl_vmd_dom_find_last */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/01/07 JRB 14 Fix function names in module header. */ +/* 10/30/06 JRB 13 Add vmd_ctrl arg to several functions & chg */ +/* prefix from "mvl_" to "mvl_vmd_". */ +/* Also add net_info arg to "mvl_vmd_find_*" */ +/* so global _mvl_curr_net_info not needed. */ +/* Move all obj delete functs from mvl_obj.c to here.*/ +/* 01/30/06 GLB 12 Integrated porting changes for VMS */ +/* 04/11/05 CRM 11 Added mvl_dom_find_last */ +/* 11/11/04 MDE 10 Check for 0 elements before calling bsearch */ +/* 01/23/02 EJV 09 Added journals to domain: */ +/* mvl_jou_insert - added DOM_SPEC case */ +/* mvl_find_jou - added DOM_SPEC case */ +/* mvl_sort_objs - added qsort dom->jou_tbl */ +/* 04/14/00 JRB 08 Move sort & compare code FROM mvl_obj.c to */ +/* here and make it ANSI compatible. */ +/* 04/10/00 JRB 07 Fix usage of bsearch to be ANSI compatible. */ +/* 09/15/99 JRB 06 Move mvl_obj_nosort here for DOS link */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 09/07/99 MDE 04 Changed MVL_VA_SCOPE to MVL_SCOPE, added */ +/* scope to MVL_NVLIST_CTRL */ +/* 04/07/99 MDE 03 Logging improvements */ +/* 03/18/99 MDE 02 Enhanced dynamic object facilities */ +/* 01/15/99 JRB 01 Created */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "mvl_defs.h" +#include "mvl_log.h" + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +ST_BOOLEAN mvl_obj_nosort; + +/************************************************************************/ +/* Local functions. */ +/************************************************************************/ +int _mvl_obj_compare (const void *obj1, const void *obj2); + +/************************************************************************/ +/* Static variables. */ +/************************************************************************/ +/* NONE */ + +/************************************************************************/ +/* mvl_obj_insert */ +/* NOTE: newElement should point to a "real" structure that has already */ +/* been allocated. This allows this function to work without */ +/* caring about the size of the "real" structure. */ +/* This function just adds the ptr to the array of ptrs. */ +/************************************************************************/ + +ST_RET mvl_obj_insert (MVL_OBJ **elementTable, + ST_INT *numElement, + ST_INT maxElement, + MVL_OBJ *newElement) + { +MVL_OBJ **key; + + if (*numElement >= maxElement) + { + MVL_LOG_ERR2 ("ERROR inserting '%s' object. Max num %d exceeded.", + newElement->name, maxElement); + return (SD_FAILURE); /* No more room in array. */ + } + +/* Check to see if we are bulk updating, and put at end if so */ + if (mvl_obj_nosort || (*numElement == 0)) + { + elementTable [(*numElement)++] = newElement; /* Add to end of array */ + } + else + { + /* Make sure it's not already in array. Can't have duplicates. */ + if (*numElement) + key = (MVL_OBJ **) bsearch (&newElement, elementTable, *numElement, + sizeof (MVL_OBJ *), _mvl_obj_compare); + else + key = NULL; + + if (key != NULL) + { + MVL_LOG_ERR1 ("ERROR inserting '%s' object. Duplicate.", + newElement->name); + return (SD_FAILURE); /* Already in array. */ + } + /* Add to array and resort. */ + elementTable [(*numElement)++] = newElement; /* Add to end of array */ + qsort (elementTable, *numElement, sizeof (MVL_OBJ *), _mvl_obj_compare); + } + + return (SD_SUCCESS); + } + + +/************************************************************************/ +/* mvl_obj_delete */ +/************************************************************************/ + +MVL_OBJ *mvl_obj_delete (MVL_OBJ **elementTable, + ST_INT *numElement, + ST_CHAR *itemName) + { +MVL_OBJ *el; +MVL_OBJ **foundElement; +MVL_OBJ **destElement; +MVL_OBJ **endElement; + +/* Locate the element of interest. We get a pointer into the array of */ +/* element pointers if it is found. */ + + foundElement = mvl_obj_find_key (elementTable, *numElement, itemName); + if (!foundElement) + return (NULL); + el = *foundElement; + +/* OK, now just move up the remaining pointers */ +/* Array was sorted before, so it will still be sorted. */ + destElement = foundElement; + endElement = elementTable + *numElement; + while (++destElement < endElement) + *(destElement-1) = *destElement; + + --(*numElement); + +/* Return the element for further work */ + return (el); + } + +/************************************************************************/ +/* mvl_obj_find */ +/* This function is used to locate an element that is referenced in a */ +/* sorted table of element pointers. */ +/************************************************************************/ + +MVL_OBJ *mvl_obj_find (MVL_OBJ **elementTable, + ST_INT numElement, + ST_CHAR *itemName) + { +MVL_OBJ **key; + + /* First find just the "key". */ + key = mvl_obj_find_key (elementTable, numElement, itemName); + + /* If key != NULL, return "*key", else return NULL. */ + if (key) /* "key" is pointer to pointer to structure. */ + return (*key); /* "*key" is pointer to structure. */ + + return (NULL); /* Not found!! */ + } + +/************************************************************************/ +/* mvl_obj_find_key */ +/* This function is used to locate an element that is referenced in a */ +/* sorted table of element pointers. */ +/* This function only finds the key. Convenient for delete function. */ +/************************************************************************/ + +MVL_OBJ **mvl_obj_find_key (MVL_OBJ **elementTable, + ST_INT numElement, + ST_CHAR *itemName) + { +MVL_OBJ **key; +MVL_OBJ TmpObj; /* Temporary object to search for. */ +MVL_OBJ *pTmpObj; /* ptr to temp object. */ + + if (numElement == 0) + return (NULL); + +/* Create a element from the itemName, such that a pointer to the */ +/* element pointer can be passed to the search function. */ + TmpObj.name = itemName; + pTmpObj = &TmpObj; + + if (numElement) + key = (MVL_OBJ **) bsearch (&pTmpObj, elementTable, numElement, + sizeof (MVL_OBJ *), _mvl_obj_compare); + else + key = NULL; + + return (key); + } + +/************************************************************************/ +/* mvl_vmd_dom_insert */ +/************************************************************************/ +ST_RET mvl_vmd_dom_insert (MVL_VMD_CTRL *vmd_ctrl, MVL_DOM_CTRL *dom) + { +/* Domain can only be VMD_SPEC, so this one is easy. */ + return (mvl_obj_insert ((MVL_OBJ **) vmd_ctrl->dom_tbl, + &vmd_ctrl->num_dom, vmd_ctrl->max_num_dom, + (MVL_OBJ *) dom)); + } + +/************************************************************************/ +/* mvl_vmd_var_insert */ +/************************************************************************/ +ST_RET mvl_vmd_var_insert (MVL_VMD_CTRL *vmd_ctrl, MVL_VAR_ASSOC *va, OBJECT_NAME *obj, + MVL_NET_INFO *net_info) /* Only used if AA_SPEC */ + { +ST_RET retcode = SD_FAILURE; +MVL_DOM_CTRL *dom; +MVL_AA_OBJ_CTRL *aa_objs; + + switch (obj->object_tag) + { + case VMD_SPEC: + retcode = mvl_obj_insert ((MVL_OBJ **) vmd_ctrl->var_assoc_tbl, + &vmd_ctrl->num_var_assoc, vmd_ctrl->max_num_var_assoc, + (MVL_OBJ *) va); + break; + + case DOM_SPEC: + if ((dom = mvl_vmd_find_dom (vmd_ctrl, obj->domain_id))) + retcode = mvl_obj_insert ((MVL_OBJ **) dom->var_assoc_tbl, + &dom->num_var_assoc, dom->max_num_var_assoc, + (MVL_OBJ *) va); + else + { + MVL_LOG_NERR1 ("Insert var: Domain '%s' not found", obj->domain_id); + } + break; + + case AA_SPEC: + if (net_info) + { + aa_objs = net_info->aa_objs; + retcode = mvl_obj_insert ((MVL_OBJ **) aa_objs->var_assoc_tbl, + &aa_objs->num_var_assoc, aa_objs->max_num_var_assoc, + (MVL_OBJ *) va); + } + else + MVL_LOG_ERR0 ("Association not known. Cannot insert Application Association-specific variable."); + break; + + default: + MVL_LOG_ERR1 ("Illegal scope for '%s'", obj->obj_name.vmd_spec); + break; + } + return (retcode); + } + +/************************************************************************/ +/* mvl_vmd_nvl_insert */ +/************************************************************************/ +ST_RET mvl_vmd_nvl_insert (MVL_VMD_CTRL *vmd_ctrl, MVL_NVLIST_CTRL *nvl, OBJECT_NAME *obj, + MVL_NET_INFO *net_info) /* Only used if AA_SPEC */ + { +ST_RET retcode = SD_FAILURE; +MVL_DOM_CTRL *dom; +MVL_AA_OBJ_CTRL *aa_objs; + + switch (obj->object_tag) + { + case VMD_SPEC: + retcode = mvl_obj_insert ((MVL_OBJ **) vmd_ctrl->nvlist_tbl, + &vmd_ctrl->num_nvlist, vmd_ctrl->max_num_nvlist, + (MVL_OBJ *) nvl); + nvl->nvl_scope.scope = VMD_SPEC; + break; + + case DOM_SPEC: + if ((dom = mvl_vmd_find_dom (vmd_ctrl, obj->domain_id))) + retcode = mvl_obj_insert ((MVL_OBJ **) dom->nvlist_tbl, + &dom->num_nvlist, dom->max_num_nvlist, + (MVL_OBJ *) nvl); + else + { + MVL_LOG_NERR1 ("Insert NVL: Domain '%s' not found", obj->domain_id); + } + nvl->nvl_scope.scope = DOM_SPEC; + nvl->nvl_scope.dom = dom; + break; + + case AA_SPEC: + if (net_info) + { + aa_objs = net_info->aa_objs; + retcode = mvl_obj_insert ((MVL_OBJ **) aa_objs->nvlist_tbl, + &aa_objs->num_nvlist, aa_objs->max_num_nvlist, + (MVL_OBJ *) nvl); + nvl->nvl_scope.scope = AA_SPEC; + } + else + MVL_LOG_ERR0 ("Association not known. Cannot insert Application Association-specific NVL."); + break; + + default: + MVL_LOG_ERR1 ("Illegal scope for '%s'", obj->obj_name.vmd_spec); + break; + } + return (retcode); + } + +/************************************************************************/ +/* mvl_vmd_jou_insert */ +/************************************************************************/ +ST_RET mvl_vmd_jou_insert (MVL_VMD_CTRL *vmd_ctrl, MVL_JOURNAL_CTRL *jou, OBJECT_NAME *obj, + MVL_NET_INFO *net_info) /* Only used if AA_SPEC */ + { +ST_RET retcode = SD_FAILURE; +MVL_AA_OBJ_CTRL *aa_objs; +MVL_DOM_CTRL *dom; + + switch (obj->object_tag) + { + case VMD_SPEC: + retcode = mvl_obj_insert ((MVL_OBJ **) vmd_ctrl->jou_tbl, + &vmd_ctrl->num_jou, vmd_ctrl->max_num_jou, + (MVL_OBJ *) jou); + break; + + case AA_SPEC: + if (net_info) + { + aa_objs = net_info->aa_objs; + retcode = mvl_obj_insert ((MVL_OBJ **) aa_objs->jou_tbl, + &aa_objs->num_jou, aa_objs->max_num_jou, + (MVL_OBJ *) jou); + } + else + MVL_LOG_ERR0 ("Association not known. Cannot insert Application Association-specific journal."); + break; + + case DOM_SPEC: + dom = mvl_vmd_find_dom (vmd_ctrl, obj->domain_id); + if (dom) + retcode = mvl_obj_insert ((MVL_OBJ **) dom->jou_tbl, + &dom->num_jou, dom->max_num_jou, (MVL_OBJ *) jou); + else + { + MVL_LOG_NERR1 ("Insert journal: Domain '%s' not found", obj->domain_id); + } + break; + + default: + /* NOTE: DOM_SPEC illegal for journals. */ + MVL_LOG_ERR1 ("Illegal scope for '%s'", obj->obj_name.vmd_spec); + break; + } + return (retcode); + } + +/************************************************************************/ +/* mvl_vmd_dom_delete */ +/************************************************************************/ +MVL_DOM_CTRL *mvl_vmd_dom_delete (MVL_VMD_CTRL *vmd_ctrl, ST_CHAR *dom_name) + { +MVL_DOM_CTRL *dom; + + dom = (MVL_DOM_CTRL *) mvl_obj_delete ((MVL_OBJ **) vmd_ctrl->dom_tbl, + &vmd_ctrl->num_dom, dom_name); + return (dom); + } + + +/************************************************************************/ +/* mvl_vmd_var_delete */ +/************************************************************************/ +MVL_VAR_ASSOC *mvl_vmd_var_delete (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, + MVL_NET_INFO *net_info) /* Only used if AA_SPEC */ + { +MVL_VAR_ASSOC *va; +MVL_DOM_CTRL *dom; +MVL_AA_OBJ_CTRL *aa_objs; +ST_CHAR *name; + + va = NULL; + name = obj->obj_name.vmd_spec; /* We know this is a union ... */ + switch (obj->object_tag) + { + case VMD_SPEC: + va = (MVL_VAR_ASSOC *) mvl_obj_delete ((MVL_OBJ **) vmd_ctrl->var_assoc_tbl, + &vmd_ctrl->num_var_assoc, name); + break; + + case DOM_SPEC: + if ((dom = mvl_vmd_find_dom (vmd_ctrl, obj->domain_id))) + va = (MVL_VAR_ASSOC *) mvl_obj_delete ((MVL_OBJ **) dom->var_assoc_tbl, + &dom->num_var_assoc, name); + else + { + MVL_LOG_NERR1 ("Delete var: Domain '%s' not found", obj->domain_id); + } + break; + + case AA_SPEC: + if (net_info) + { + aa_objs = net_info->aa_objs; + va = (MVL_VAR_ASSOC *) mvl_obj_delete ((MVL_OBJ **) aa_objs->var_assoc_tbl, + &aa_objs->num_var_assoc, name); + } + else + MVL_LOG_ERR0 ("Association not known. Cannot delete Application Association-specific variable."); + break; + + default: + MVL_LOG_ERR1 ("Illegal scope for '%s'", name); + break; + } + return (va); + } + +/************************************************************************/ +/* mvl_vmd_nvl_delete */ +/************************************************************************/ +MVL_NVLIST_CTRL *mvl_vmd_nvl_delete (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, + MVL_NET_INFO *net_info) /* Only used if AA_SPEC */ + { +MVL_NVLIST_CTRL *nvl = NULL; +MVL_DOM_CTRL *dom; +MVL_AA_OBJ_CTRL *aa_objs; +ST_CHAR *name; + + name = obj->obj_name.vmd_spec; /* We know this is a union ... */ + + switch (obj->object_tag) + { + case VMD_SPEC: + nvl = (MVL_NVLIST_CTRL *) mvl_obj_delete ((MVL_OBJ **) vmd_ctrl->nvlist_tbl, + &vmd_ctrl->num_nvlist, name); + break; + + case DOM_SPEC: + if ((dom = mvl_vmd_find_dom (vmd_ctrl, obj->domain_id))) + nvl = (MVL_NVLIST_CTRL *) mvl_obj_delete ((MVL_OBJ **) dom->nvlist_tbl, + &dom->num_nvlist, name); + else + { + MVL_LOG_NERR1 ("Delete NVL: Domain '%s' not found", obj->domain_id); + } + break; + + case AA_SPEC: + if (net_info) + { + aa_objs = net_info->aa_objs; + nvl = (MVL_NVLIST_CTRL *) mvl_obj_delete ((MVL_OBJ **) aa_objs->nvlist_tbl, + &aa_objs->num_nvlist, name); + } + else + MVL_LOG_ERR0 ("Association not known. Cannot delete Application Association-specific NVL."); + break; + + default: + MVL_LOG_ERR1 ("Illegal scope for '%s'", name); + break; + } + return (nvl); + } + +/************************************************************************/ +/* mvl_vmd_jou_delete */ +/************************************************************************/ +MVL_JOURNAL_CTRL *mvl_vmd_jou_delete (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, + MVL_NET_INFO *net_info) /* Only used if AA_SPEC */ + { +MVL_JOURNAL_CTRL *jou; +MVL_AA_OBJ_CTRL *aa_objs; +MVL_DOM_CTRL *dom; +ST_CHAR *name; + + jou = NULL; + name = obj->obj_name.vmd_spec; /* We know this is a union ... */ + switch (obj->object_tag) + { + case VMD_SPEC: + jou = (MVL_JOURNAL_CTRL *) mvl_obj_delete ((MVL_OBJ **) vmd_ctrl->jou_tbl, + &vmd_ctrl->num_jou, name); + break; + + case AA_SPEC: + if (net_info) + { + aa_objs = net_info->aa_objs; + jou = (MVL_JOURNAL_CTRL *) mvl_obj_delete ((MVL_OBJ **) aa_objs->jou_tbl, + &aa_objs->num_jou, name); + } + else + MVL_LOG_ERR0 ("Association not known. Cannot delete Application Association-specific journal."); + break; + + case DOM_SPEC: + dom = mvl_vmd_find_dom (vmd_ctrl, obj->domain_id); + if (dom) + jou = (MVL_JOURNAL_CTRL *) mvl_obj_delete ((MVL_OBJ **) dom->jou_tbl, + &dom->num_jou, name); + else + { + MVL_LOG_NERR1 ("Delete journal: Domain '%s' not found", obj->domain_id); + } + break; + + default: + MVL_LOG_ERR1 ("Illegal scope for '%s'", name); + break; + } + return (jou); + } + +/************************************************************************/ +/* mvl_vmd_find_dom */ +/************************************************************************/ + +MVL_DOM_CTRL *mvl_vmd_find_dom (MVL_VMD_CTRL *vmd_ctrl, ST_CHAR *name) + { +MVL_DOM_CTRL *result; + + result = (MVL_DOM_CTRL *) mvl_obj_find ((MVL_OBJ **) vmd_ctrl->dom_tbl, + vmd_ctrl->num_dom, name); + return(result); + } + +/************************************************************************/ +/* mvl_vmd_dom_find_last */ +/* Find the last domain. */ +/************************************************************************/ +MVL_DOM_CTRL *mvl_vmd_dom_find_last (MVL_VMD_CTRL *vmd_ctrl) + { +MVL_DOM_CTRL *dom; + + if (vmd_ctrl->num_dom > 0) + dom = vmd_ctrl->dom_tbl [vmd_ctrl->num_dom-1]; + else + dom = NULL; /* no more dynamically created domains. */ + return (dom); + } + +/************************************************************************/ +/* mvl_vmd_find_var */ +/* This function finds the 'variable association' for a particular var */ +/* name. */ +/************************************************************************/ + +MVL_VAR_ASSOC *mvl_vmd_find_var (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info) /* Only used if AA_SPEC */ + { +MVL_DOM_CTRL *dom; +MVL_AA_OBJ_CTRL *aa; +ST_CHAR *name; + + name = obj->obj_name.vmd_spec; /* We know this is a union ... */ + + switch (obj->object_tag) + { + case VMD_SPEC : + return ((MVL_VAR_ASSOC *) mvl_obj_find ((MVL_OBJ **) vmd_ctrl->var_assoc_tbl, + vmd_ctrl->num_var_assoc, name)); + case DOM_SPEC : + dom = mvl_vmd_find_dom (vmd_ctrl, obj->domain_id); + if (dom) + return ((MVL_VAR_ASSOC *) mvl_obj_find ((MVL_OBJ **) dom->var_assoc_tbl, + dom->num_var_assoc, name)); + else + { + MVL_LOG_NERR1 ("Find Va: Domain '%s' not found", obj->domain_id); + } + break; + + case AA_SPEC : + if (net_info) + { + aa = (MVL_AA_OBJ_CTRL *) net_info->aa_objs; + return ((MVL_VAR_ASSOC *) mvl_obj_find ((MVL_OBJ **) aa->var_assoc_tbl, + aa->num_var_assoc, name)); + } + else + MVL_LOG_ERR0 ("Association not known. Cannot find Application Association-specific variable."); + break; + + default: + MVL_LOG_ERR1 ("Illegal scope for '%s'", name); + break; + } + return (NULL); + } + +/************************************************************************/ +/* mvl_vmd_find_nvl */ +/************************************************************************/ + +MVL_NVLIST_CTRL *mvl_vmd_find_nvl (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info) /* Only used if AA_SPEC */ + { +MVL_DOM_CTRL *dom; +MVL_AA_OBJ_CTRL *aa; +ST_CHAR *name; + +/* Get the NVL name. We know this is a union ... */ + name = obj->obj_name.vmd_spec; + + switch (obj->object_tag) + { + case VMD_SPEC : + return ((MVL_NVLIST_CTRL *) mvl_obj_find ((MVL_OBJ **) vmd_ctrl->nvlist_tbl, + vmd_ctrl->num_nvlist, name)); + case DOM_SPEC : + dom = mvl_vmd_find_dom (vmd_ctrl, obj->domain_id); + if (dom) + return ((MVL_NVLIST_CTRL *) mvl_obj_find ((MVL_OBJ **) dom->nvlist_tbl, + dom->num_nvlist, name)); + else + { + MVL_LOG_NERR1 ("Find NVL: Domain '%s' not found", obj->domain_id); + } + break; + + case AA_SPEC : + if (net_info) + { + aa = (MVL_AA_OBJ_CTRL *) net_info->aa_objs; + return ((MVL_NVLIST_CTRL *) mvl_obj_find ((MVL_OBJ **) aa->nvlist_tbl, + aa->num_nvlist, name)); + } + else + MVL_LOG_ERR0 ("Association not known. Cannot find Application Association-specific NVL."); + break; + + default: + MVL_LOG_ERR1 ("Illegal scope for '%s'", name); + break; + } + return (NULL); + } + +/************************************************************************/ +/* mvl_vmd_find_jou */ +/* This function finds the 'journal control' corresponding to 'obj'. */ +/************************************************************************/ + +MVL_JOURNAL_CTRL *mvl_vmd_find_jou (MVL_VMD_CTRL *vmd_ctrl, + OBJECT_NAME *obj, + MVL_NET_INFO *net_info) /* Only used if AA_SPEC */ + { +MVL_AA_OBJ_CTRL *aa_objs; +MVL_DOM_CTRL *dom; +ST_CHAR *name; + + name = obj->obj_name.vmd_spec; /* We know this is a union ... */ + + switch (obj->object_tag) + { + case VMD_SPEC : + return ((MVL_JOURNAL_CTRL *) mvl_obj_find ((MVL_OBJ **) vmd_ctrl->jou_tbl, + vmd_ctrl->num_jou, name)); + break; + + case AA_SPEC : + if (net_info) + { + aa_objs = (MVL_AA_OBJ_CTRL *) net_info->aa_objs; + return ((MVL_JOURNAL_CTRL *) mvl_obj_find ((MVL_OBJ **) aa_objs->jou_tbl, + aa_objs->num_jou, name)); + } + else + MVL_LOG_ERR0 ("Association not known. Cannot find Application Association-specific journal."); + break; + + case DOM_SPEC : + dom = mvl_vmd_find_dom (vmd_ctrl, obj->domain_id); + if (dom) + return ((MVL_JOURNAL_CTRL *) mvl_obj_find ((MVL_OBJ **) dom->jou_tbl, + dom->num_jou, name)); + else + { + MVL_LOG_NERR1 ("Find journal: Domain '%s' not found", obj->domain_id); + } + break; + + default: + /* NOTE: DOM_SPEC is illegal for Journals. */ + MVL_LOG_ERR1 ("Illegal scope for '%s'", name); + break; + } + return (NULL); + } + +/************************************************************************/ +/* mvl_sort_objs */ +/************************************************************************/ +ST_VOID mvl_sort_objs (ST_VOID) + { +ST_INT i; +MVL_DOM_CTRL *dom; + + mvl_obj_nosort = SD_FALSE; + + qsort (mvl_vmd.dom_tbl, mvl_vmd.num_dom, sizeof (MVL_OBJ *), _mvl_obj_compare); + qsort (mvl_vmd.var_assoc_tbl, mvl_vmd.num_var_assoc, sizeof (MVL_OBJ *), _mvl_obj_compare); + qsort (mvl_vmd.nvlist_tbl, mvl_vmd.num_nvlist, sizeof (MVL_OBJ *), _mvl_obj_compare); + qsort (mvl_vmd.jou_tbl, mvl_vmd.num_jou, sizeof (MVL_OBJ *), _mvl_obj_compare); + + for (i = 0; i < mvl_vmd.num_dom; ++i) + { + dom = mvl_vmd.dom_tbl[i]; + qsort (dom->var_assoc_tbl, dom->num_var_assoc, sizeof (MVL_OBJ *), _mvl_obj_compare); + qsort (dom->nvlist_tbl, dom->num_nvlist, sizeof (MVL_OBJ *), _mvl_obj_compare); + qsort (dom->jou_tbl, dom->num_jou, sizeof (MVL_OBJ *), _mvl_obj_compare); + } + } + +/************************************************************************/ +/* _mvl_obj_compare */ +/************************************************************************/ +int _mvl_obj_compare (const void *obj1, const void *obj2) + { +const MVL_OBJ **mvl_obj1 = (const MVL_OBJ **) obj1; +const MVL_OBJ **mvl_obj2 = (const MVL_OBJ **) obj2; + return (strcmp ((*mvl_obj1)->name, (*mvl_obj2)->name)); + } diff --git a/mmslib/mvlu/mvl_send.c b/mmslib/mvlu/mvl_send.c new file mode 100644 index 0000000..74cb991 --- /dev/null +++ b/mmslib/mvlu/mvl_send.c @@ -0,0 +1,176 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2002, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_send.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/14/06 MDE 17 Log PDU when too large */ +/* 05/01/03 MDE 16 Added buffer depletion logging _mvl_send_req */ +/* 10/29/02 JRB 15 _mvl_send_req: on err, set done & result in */ +/* req_pend. Helps if user doesn't chk return. */ +/* 07/10/02 JRB 14 _mvl_send_req: call mvl_req_bufs_avail. */ +/* 07/09/02 MDE 13 Add maxpend_ind support */ +/* 01/30/02 JRB 12 Del use of stack_sel. */ +/* 09/21/01 JRB 11 Alloc global bufs only once at startup. */ +/* 05/15/00 MDE 10 Added MMS statistics */ +/* 03/08/00 JRB 09 _mvl_send_req: chk conn_active, */ +/* chk & set numpend_req, set invoke_id. */ +/* 01/21/00 MDE 08 Now use MEM_SMEM for dynamic memory */ +/* 10/28/99 RKR 07 Modified _mvl_send_resp_i */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 12/09/98 JRB 05 Don't exceed negotiated PDU size. */ +/* Change all NERR log macros to ERR. */ +/* Free enc buf before _mvl_send_err_f. */ +/* 11/16/98 MDE 04 Renamed internal functions (prefix '_') */ +/* 11/16/98 MDE 03 Don't free request control if send error */ +/* 05/14/98 JRB 02 Add _mvl_send_resp_i function. */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mvl_defs.h" +#include "mvl_log.h" + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* _mvl_send_resp_i */ +/* This function sends a response and frees the MVL_IND_PEND. */ +/************************************************************************/ + +ST_VOID _mvl_send_resp_i (MVL_IND_PEND *indCtrl, ST_RET build_rc) + { +MVL_NET_INFO *net_info; + + net_info = indCtrl->event->net_info; + _mvl_send_resp (indCtrl->event, build_rc); + list_unlink(&(net_info->pend_ind),indCtrl); + --net_info->numpend_ind; + M_FREE (MSMEM_IND_CTRL, indCtrl); + } + +/************************************************************************/ +/* _mvl_send_resp */ +/************************************************************************/ + +ST_VOID _mvl_send_resp (MVL_COMM_EVENT *event, ST_RET build_rc) + { +ST_RET rc; + + if (build_rc != SD_SUCCESS) + { /* Free encode buf before "_mvl_send_err_f" because it allocs new buf.*/ + MVL_LOG_ERR1 ("Response build error: rc = 0x%X", build_rc); + _mvl_send_err_f (event,7,2); + ++mvl_mms_statistics.serverRespErr; + } + else if (mmsl_msg_len > event->net_info->max_pdu_size) + { /* Free encode buf before "_mvl_send_err_f" because it allocs new buf.*/ + MVL_LOG_ERR2 ("Response build error: exceeds negotiated PDU size %d %d",mmsl_msg_len, event->net_info->max_pdu_size); + printf("Response build error: exceeds negotiated PDU size %d %d\n",mmsl_msg_len, event->net_info->max_pdu_size); + _mvl_send_err_f (event,4,3); /* Don't exceed negotiated PDU size. */ + ++mvl_mms_statistics.serverRespErr; + } + else + { + rc = _mvl_send_msg (mmsl_msg_start,mmsl_msg_len,event->net_info); + if (rc != SD_SUCCESS) + { + MVL_LOG_ERR1 ("_mvl_send_msg error, rc = %x", rc); + } + else + ++mvl_mms_statistics.serverRespOk; + + _mvl_free_comm_event (event); /* done with this event */ + } + } + + + + +/************************************************************************/ +/* _mvl_send_req */ +/************************************************************************/ + +ST_RET _mvl_send_req (MVL_NET_INFO *net_info, + MVL_REQ_PEND *req_pend, ST_RET build_rc) + { +ST_RET rc; +ST_INT bufsAvail; + + if (build_rc != SD_SUCCESS) + { + MVL_LOG_ERR1 ("Request build error, rc = %x", build_rc); + rc = build_rc; + } + else if (net_info->conn_active == SD_FALSE) + { /* Check conn_active before using net_info */ + MVL_LOG_ERR0 ("Request send error: disconnected"); + rc = MVL_ERR_CNF_DISCONNECTED; + } + else if (mmsl_msg_len > net_info->max_pdu_size) + { + MVL_LOG_ERR0 ("Request build error: exceeds negotiated PDU size"); + printf("Request build error: exceeds negotiated PDU size"); + rc = ASN1E_PDU_TOO_BIG; + } +#ifdef WIN32 + else if (net_info->numpend_req >=(net_info->maxpend_req*4)) +#else + else if (net_info->numpend_req >= net_info->maxpend_req) +#endif + { + MVL_LOG_ERR1 ("Too many requests outstanding (0x%08lx)", net_info); + rc = MVL_ERR_REQ_PEND_COUNT; + } + else if ((bufsAvail = mvl_req_bufs_avail (net_info)) <= 0) + { + MVL_LOG_ERR2 ("Not enough ACSE bufs to send confirmed request (%d, 0x%08lx)", bufsAvail, net_info); + rc = MVL_ERR_REQ_PEND_COUNT; + } + else + { + rc = _mvl_send_msg (mmsl_msg_start,mmsl_msg_len,net_info); + if (rc != SD_SUCCESS) + { + MVL_LOG_ERR1 ("_mvl_send_msg error, rc = %x", rc); + } + else + ++mvl_mms_statistics.clientReq; + } + if (rc == SD_SUCCESS) + { + /* mmsl_invoke_id already incremented on encode, so subtract one. */ + req_pend->invoke_id = mmsl_invoke_id - 1; + net_info->numpend_req++; + } + else + { + req_pend->done = SD_TRUE; + req_pend->result = rc; + } + return (rc); + } + diff --git a/mmslib/mvlu/mvl_serv.c b/mmslib/mvlu/mvl_serv.c new file mode 100644 index 0000000..3426e0d --- /dev/null +++ b/mmslib/mvlu/mvl_serv.c @@ -0,0 +1,1069 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2005, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_serv.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/24/08 MDE 63 Added _mvl_persist_aa_objs */ +/* 05/20/08 JRB 62 Fix handling of MMSCNCLERR (Conclude ERROR). */ +/* 04/22/08 JRB 61 Move "active" chk inside semaphore lock. */ +/* Del unused MVLULOG_TIMING. */ +/* 03/05/08 JRB 60 Call _mvl_clear_aa_objs in ..net_req_done */ +/* 10/04/07 MDE 59 Tweaked LOGCFG_VALUE_GROUP/LOGCFGX_VALUE_MAP */ +/* 04/09/07 MDE 58 Enhanced filtered logging */ +/* 10/30/06 JRB 57 Del _mvl_curr_net_info, _mvl_curr_usr_ind_ctrl.*/ +/* 08/03/07 NAV 56 mvl_msg_rcvd - return after sending reject */ +/* 01/30/06 GLB 55 Integrated porting changes for VMS */ +/* 09/08/05 JRB 54 _mvl_send_reject: set rej_info->pdu_type, */ +/* send right class/code on request decode err. */ +/* Remove duplicate log msg. */ +/* 07/13/05 MDE 52 Improved reject handlng, add u_mvl_reject_ind*/ +/* 08/08/05 JRB 52 Init mvl_debug_sel = MVLLOG_ERR. */ +/* 06/02/05 JRB 51 Fix _mvl_send_reject for INVALID-PDU. */ +/* 05/24/05 EJV 50 Add mvlLogMaskMapCtrl for parsing logcfg.xml */ +/* 09/07/04 JRB 49 _mvl_get_req_ctrl: ret NULL if net_info==NULL*/ +/* 07/28/03 MDE 48 Yet another tweak to mvl_ureq_bufs_avail */ +/* 05/05/03 MDE 47 Yet another tweak to mvl_ureq_bufs_avail */ +/* 05/01/03 MDE 46 Added high water logging to (u)req_bufs_avail*/ +/* 04/28/03 JRB 45 Fix computations in mvl_(u)req_bufs_avail. */ +/* 07/09/02 JRB 44 Add mvl_(u)req_bufs_avail functions. */ +/* 07/09/02 MDE 43 Add maxpend_ind support */ +/* 05/21/02 MDE 42 Check PDU len before decoding */ +/* 05/13/02 MDE 41 Added 'skip' arg to _mvl_set_net_req_done */ +/* 05/01/02 MDE 40 Fixed conclude logging */ +/* 04/05/02 MDE 39 Added MLOG logging */ +/* 03/25/02 MDE 38 Moved error/reject elements outside union */ +/* 11/07/01 JRB 37 mvl_wait_req_done return "req->result". */ +/* 09/21/01 JRB 36 Alloc global bufs only once at startup. */ +/* 07/31/01 MDE 35 Added mvl_conn_filtered_logging */ +/* 02/22/01 GLB 34 Added: MVLULOG_DEBUG, MVLULOG_TIMING */ +/* 11/20/00 MDE 33 Fixed lockup - abort with requests out */ +/* 10/25/00 JRB 32 Del global link list of MVL_REQ_PEND. Add one*/ +/* for each conn. Save list ptr in MVL_NET_INFO.*/ +/* Del _mvl_free_req_pend function. */ +/* 10/25/00 JRB 31 Del ind & conf funct ptrs. Call directly. */ +/* Mv mvl_ind_rcvd, mvl_conf_rcvd to mvlop_en.c */ +/* so "conditional compilation" can be used. */ +/* 05/15/00 MDE 30 Added statistics */ +/* 05/12/00 RKR 29 Worked on mvl_send_reject */ +/* 04/14/00 JRB 28 Lint cleanup. */ +/* 03/08/00 JRB 27 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* mvl_free_req_ctrl chk result before freeing. */ +/* 01/21/00 MDE 26 Now use MEM_SMEM for dynamic memory */ +/* 11/24/99 MDE 25 Del indCtrl from link list for info reports */ +/* 11/19/99 NAV 24 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/20/99 NAV 23 Additions for maxpend_req support */ +/* 11/03/99 RKR 22 Changed reject and error confirm results */ +/* 11/02/99 RKR 21 Fixed a leak when a reject is received */ +/* 10/28/99 RKR 20 Added mvl_clr_ind_que */ +/* 10/06/99 GLB 19 Added changes to accomodate file rename */ +/* 09/13/99 MDE 18 Added SD_CONST modifiers */ +/* 04/01/99 MDE 17 Changes to decode buffer allocation scheme */ +/* 03/03/99 MDE 16 Changed 'mvl_max_req_pend' to 10000 */ +/* 12/08/98 MDE 15 Cleanup on request control handling */ +/* 11/16/98 MDE 14 Renamed internal functions (prefix '_') */ +/* 11/16/98 MDE 13 Cleanup, conclude changes, removed simple */ +/* request control, renamed concat_filename */ +/* 10/08/98 MDE 12 Migrated to updated SLOG interface */ +/* 10/01/98 DWL 11 Added get domain attributes client */ +/* Added get name list client */ +/* Added get status client */ +/* 09/21/98 MDE 10 Minor lint cleanup */ +/* 06/15/98 MDE 09 Changes to allow compile under C++ */ +/* 05/13/98 JRB 08 Set req->result=CNF_REJ_ERR in mvl_reject_rcvd*/ +/* Add _mplas_err_resp & _mvl_concat_filename. */ +/* 04/21/98 MDE 07 Added service logging */ +/* 04/15/98 JRB 06 mvl_conf_rcvd: do all common processing, */ +/* pass req_pend to all "ml_*_conf_proc". */ +/* Add client support for more services. */ +/* Free comm_event, etc. from mvl_free_req_ctrl */ +/* Init "result" in _mvl_get_req_ctrl. */ +/* Add _mvl_conf_reject, _mvl_ind_reject. */ +/* 02/10/98 MDE 05 Added get domain attributes server */ +/* 12/22/97 MDE 04 Changed 'mvl_comm_serve' to report activity */ +/* 12/12/97 MDE 03 _mvl_send_reject now returns ST_VOID */ +/* 12/10/97 MDE 02 Added JREAD/JINIT */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "mmsdefs.h" +#include "mms_err.h" +#include "mvl_defs.h" +#include "mvl_log.h" +#include "mloguser.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +ST_UINT mvl_debug_sel = MVLLOG_ERR; +#ifdef DEBUG_SISCO +SD_CONST ST_CHAR *SD_CONST _mvllog_err_logstr = "MVLLOG_ERR"; +SD_CONST ST_CHAR *SD_CONST _mvllog_nerr_logstr = "MVLLOG_NERR"; +SD_CONST ST_CHAR *SD_CONST _mvllog_acse_logstr = "MVLLOG_ACSE"; +SD_CONST ST_CHAR *SD_CONST _mvllog_acsedata_logstr = "MVLLOG_ACSEDATA"; +SD_CONST ST_CHAR *SD_CONST _mvlulog_flow_logstr = "MVLULOG_FLOW"; +SD_CONST ST_CHAR *SD_CONST _mvlulog_debug_logstr = "MVLULOG_DEBUG"; + +LOGCFGX_VALUE_MAP mvlLogMaskMaps[] = + { + {"MVLLOG_ERR", MVLLOG_ERR, &mvl_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Error"}, + {"MVLLOG_NERR", MVLLOG_NERR, &mvl_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Notice"}, + {"MVLLOG_ACSE", MVLLOG_ACSE, &mvl_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "ACSE"}, + {"MVLLOG_ACSEDATA", MVLLOG_ACSEDATA, &mvl_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "ACSEData"}, + {"MVLULOG_FLOW", MVLULOG_FLOW, &mvl_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Flow"}, + {"MVLULOG_DEBUG", MVLULOG_DEBUG, &mvl_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Debug"} + }; + +LOGCFG_VALUE_GROUP mvlLogMaskMapCtrl = + { + {NULL,NULL}, + "MvlLogMasks", /* Parent Tag */ + sizeof(mvlLogMaskMaps)/sizeof(LOGCFGX_VALUE_MAP), + mvlLogMaskMaps + }; +#endif /* DEBUG_SISCO */ + +ST_BOOLEAN mvl_conn_filtered_logging; + +ST_BOOLEAN _mvl_persist_aa_objs; + +/************************************************************************/ +/* User defined function, called repetitively by MVL client functions */ +/* while waiting for confirm. If this function returns SD_TRUE, the */ +/* request will timeout and return SD_FAILURE. */ + +ST_BOOLEAN (*u_mvl_check_timeout)(ST_VOID); + +/************************************************************************/ +/* These functions are used internally by mvl_comm_serve () */ + +static ST_VOID mvl_msg_rcvd (MVL_COMM_EVENT *event); +static ST_VOID mvl_error_rcvd (MVL_COMM_EVENT *event); +static ST_VOID mvl_reject_rcvd (MVL_COMM_EVENT *event); + +static ST_VOID _mvl_send_reject_net_info (MVL_NET_INFO *net_info, + REJECT_RESP_INFO *rej_info); + +/************************************************************************/ +/************************************************************************/ +/* mvl_comm_serve */ +/* General MMS communication service */ +/************************************************************************/ + +ST_BOOLEAN _mvl_comm_serve_active; + +ST_BOOLEAN mvl_comm_serve () + { +MVL_COMM_EVENT *event; +ST_BOOLEAN activityFlag; + + + S_LOCK_COMMON_RESOURCES (); + /* Check for re-entrancy. This must be inside the lock so only one */ + /* thread is accessing the global "_mvl_comm_serve_active". */ + if (_mvl_comm_serve_active) + { + MVL_LOG_ERR0 ("Error: mvl_comm_serve re-entered"); + S_UNLOCK_COMMON_RESOURCES (); /* unlock sem before return */ + return (SD_FALSE); + } + _mvl_comm_serve_active = SD_TRUE; +/* Call the network service routine, see if it has anything for us */ +/* to deal with */ + activityFlag = _mvl_net_service (&event); + if (event) + { + switch (event->event_type) + { + case MMS_MSG_RCVD : + mvl_msg_rcvd (event); + break; + + default : + _mvl_free_comm_event (event); /* All done with this event */ + break; + } + } + _mvl_comm_serve_active = SD_FALSE; + S_UNLOCK_COMMON_RESOURCES (); + return (activityFlag); + } + +/************************************************************************/ +/* mvl_msg_rcvd */ +/* This function is called by mvl_comm_serve when a MMS message */ +/* has been received. */ +/************************************************************************/ + +static ST_VOID mvl_msg_rcvd (MVL_COMM_EVENT *event) + { +MMSDEC_INFO *rslt; +MVL_REQ_PEND *req_pend; +ST_INT pdu_len; + + rslt = &event->u.mms.dec_rslt; + pdu_len = event->u.mms.pdu_len; + + +/* Verify that the message is less than or equal to negiotiated */ + if (pdu_len > event->net_info->max_pdu_size) + { + MVL_LOG_NERR2 ("MMS PDU too long: %d rxd, %d max", + pdu_len, event->net_info->max_pdu_size); + printf("MMS PDU too long: %d rxd, %d max", + pdu_len, event->net_info->max_pdu_size); + _mvl_send_reject (event); + return; + } + +/* some kind of message was received, need to decode and act on it */ + _ms_mms_decode (event->u.mms.pdu, pdu_len, rslt); + rslt->data_ptr = _mms_dec_info; + + if (rslt->err_code == NO_DECODE_ERR) + { + switch (rslt->type) + { + case MMSREQ : + /* We can log here if so desired */ + if ((mms_debug_sel & MMS_LOG_IND) && ml_log_ind_info_fun != NULL) + { + if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable) + (*ml_log_ind_info_fun) (rslt->id, rslt->op, rslt->data_ptr); + } + mvl_ind_rcvd (event); + break; + case MMSUNREQ : + /* We can log here if so desired */ + if ((mms_debug_sel & MMS_LOG_IND) && ml_log_unsol_ind_info_fun != NULL) + { + if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable) + (*ml_log_unsol_ind_info_fun) (rslt->op, rslt->data_ptr); + } + mvl_ind_rcvd (event); + break; + + case MMSRESP : + /* We can log here if so desired */ + if ((mms_debug_sel & MMS_LOG_CONF) && ml_log_conf_info_fun != NULL) + { + if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable) + (*ml_log_conf_info_fun) (rslt->id, rslt->op, rslt->data_ptr); + } + mvl_conf_rcvd (event); + break; + + + case MMSREJECT : + /* We can log here if so desired */ + if ((mms_debug_sel & MMS_LOG_CONF) && ml_log_reject_recv_fun != NULL) + { + if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable) + (*ml_log_reject_recv_fun) (rslt->data_ptr); + } + mvl_reject_rcvd (event); + break; + + case MMSERROR : + if ((mms_debug_sel & MMS_LOG_CONF) && ml_log_error_conf_fun != NULL) + { + if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable) + (*ml_log_error_conf_fun) (rslt->id, rslt->data_ptr); + } + mvl_error_rcvd (event); + break; + + case MMSCNCLERR : + if ((mms_debug_sel & MMS_LOG_CONF) && ml_log_error_conf_fun != NULL) + { + if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable) + (*ml_log_error_conf_fun) (rslt->id, rslt->data_ptr); + } + /* Find Conclude request sent on this connection & mark it as failed.*/ + req_pend = _mvl_find_req_ctrl (event->net_info, + MMSOP_CONCLUDE, (ST_UINT32) -1); + if (!req_pend) + { /* this should almost never fail. */ + MVL_LOG_ERR0 ("Negative Conclude Confirm received: Error finding request control"); + _mvl_free_comm_event (event); /* All done with this event */ + return; + } + req_pend->done = SD_TRUE; + req_pend->result = SD_FAILURE; + break; + + case MMSCNCLRESP : + /* We can log here if so desired */ + if ((mms_debug_sel & MMS_LOG_CONF) && ml_log_conf_info_fun != NULL) + { + if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable) + (*ml_log_conf_info_fun) (rslt->id, MMSOP_CONCLUDE, NULL); + } + req_pend = _mvl_find_req_ctrl (event->net_info, + MMSOP_CONCLUDE, (ST_UINT32) -1); + if (!req_pend) + { + MVL_LOG_NERR1 ("%s Confirmation : mvl_find_req_ctrl failed", + mms_op_string [event->u.mms.dec_rslt.op]); + _mvl_free_comm_event (event); /* All done with this event */ + return; + } + req_pend->event = event; + mvl_concl_conf_rcvd (req_pend); + break; + + case MMSCNCLREQ : + /* We can log here if so desired */ + if ((mms_debug_sel & MMS_LOG_IND) && ml_log_ind_info_fun != NULL) + { + if (mvl_conn_filtered_logging == SD_FALSE || event->net_info->log_enable) + (*ml_log_ind_info_fun) (rslt->id, MMSOP_CONCLUDE, NULL); + } + mvl_concl_ind_rcvd (event); + break; + +/* Unexpected PDU types */ + case MMSCANREQ : + /* We can log here if so desired */ + if ((mms_debug_sel & MMS_LOG_IND) && ml_log_ind_info_fun != NULL) + (*ml_log_ind_info_fun) (rslt->id, rslt->op, rslt->data_ptr); + mvl_cancel_ind_rcvd (event); + break; + + case MMSCANRESP : + MVL_LOG_NERR0 ("Unexpected MMS PDU type received: Cancel Response"); + _mvl_send_reject (event); + break; + + case MMSCANERR : + MVL_LOG_NERR0 ("Unexpected MMS PDU type received: Cancel Error"); + _mvl_send_reject (event); + break; + + case MMSINITREQ : + MVL_LOG_NERR0 ("Unexpected MMS PDU type received: Initiate Request"); + _mvl_send_reject (event); + break; + + case MMSINITRESP : + MVL_LOG_NERR0 ("Unexpected MMS PDU type received: Initiate Response"); + _mvl_send_reject (event); + break; + + case MMSINITERR : + MVL_LOG_NERR0 ("Unexpected MMS PDU type received: Initiate Error"); + _mvl_send_reject (event); + break; + + case UNKNOWNTYPE : + MVL_LOG_NERR0 ("Unexpected MMS PDU type received: Unknown"); + _mvl_send_reject (event); + break; + + default : + MVL_LOG_NERR1 ("Unexpected MMS PDU type received: %d", rslt->type); + _mvl_send_reject (event); + break; + } + } + else /* Error in decoding, need to reject the message */ + { + MVL_LOG_NERR0 ("MMS PDU decode error, sending reject"); + + /* If this was a confirmed response, try to match the request */ + req_pend = NULL; + if (rslt->dec_level >= 2 && rslt->type == MMSRESP) + { + req_pend = _mvl_find_req_ctrl (event->net_info, -1, rslt->id); + if (req_pend != NULL) + { + req_pend->event = event; + req_pend->reject_info = event->u.mms.dec_rslt.data_ptr = + (REJECT_RESP_INFO *) chk_calloc (1, sizeof (REJECT_RESP_INFO)); + event->u.mms.dec_rslt.data_pres = SD_TRUE; + + req_pend->reject_info->detected_here = SD_TRUE; + req_pend->reject_info->invoke_known = SD_TRUE; + req_pend->reject_info->invoke = rslt->id; + req_pend->reject_info->pdu_type = MMSRESP; + req_pend->reject_info->rej_class = MMS_REJ_CLASS_CONFIRMED_RESPONSE_PDU; + req_pend->reject_info->rej_code = MMS_REJ_CODE_CONFIRMED_RESPONSE_PDU_OTHER; + + _mvl_send_reject_net_info (event->net_info, req_pend->reject_info); + + _mvl_set_req_done (req_pend, MVL_ERR_CNF_REJ_ERR); + + } + else + { + MVL_LOG_CNERR0 ("Could not match confirmed request"); + } + } + + if (req_pend == NULL) + _mvl_send_reject (event); + } + } + +/************************************************************************/ +ST_VOID mvl_clr_ind_que (MVL_NET_INFO *net_info) + { +MVL_IND_PEND *pend_ind; +MVL_IND_PEND *next_ind; + +/* look at all the pending indications attached to this MVL_NET_INFO */ +/* unlink them, and deallocate them. */ + + pend_ind = net_info->pend_ind; + while(pend_ind!=NULL) + { + next_ind = (MVL_IND_PEND *) list_get_next(net_info->pend_ind,pend_ind); + list_unlink(&(net_info->pend_ind),pend_ind); + --net_info->numpend_ind; + + _mvl_free_comm_event (pend_ind->event); + + M_FREE (MSMEM_IND_CTRL, pend_ind); + pend_ind = next_ind; + } + } + +/************************************************************************/ +/* mvl_error_rcvd */ +/************************************************************************/ + +static ST_VOID mvl_error_rcvd (MVL_COMM_EVENT *event) + { +MVL_REQ_PEND *req; +ST_UINT32 id; +ST_INT op; + + ++mvl_mms_statistics.clientReqErr; + event->net_info->numpend_req--; + + id = event->u.mms.dec_rslt.id; + op = event->u.mms.dec_rslt.op; + + req = _mvl_find_req_ctrl (event->net_info, -1, id); + if (!req) + { + MVL_LOG_NERR0 ("Error Received : mvl_find_req_ctrl failed"); + _mvl_free_comm_event (event); /* All done with this event */ + return; + } + req->event = event; + req->error_info = (ERR_INFO *) req->event->u.mms.dec_rslt.data_ptr; + _mvl_set_req_done (req, MVL_ERR_CNF_ERR_OK); + } + +/************************************************************************/ +/* mvl_reject_rcvd */ +/************************************************************************/ + +static ST_VOID mvl_reject_rcvd (MVL_COMM_EVENT *event) + { +REJECT_RESP_INFO *info; +MVL_REQ_PEND *req; +ST_BOOLEAN freeCommEvent; +MVL_NET_INFO *netInfo; + + ++mvl_mms_statistics.rejectsRcvd; + netInfo = event->net_info; + netInfo->numpend_req--; + freeCommEvent = SD_TRUE; + + info = (REJECT_RESP_INFO *) event->u.mms.dec_rslt.data_ptr; + MVL_LOG_NERR2 ("Reject Received: class %d, code %d", + info->rej_class, info->rej_code); + +/* If the other node rejected our confirmed request, need to match it */ + if (info->rej_class == MMS_REJ_CLASS_CONFIRMED_REQUEST_PDU) + { + if (info->invoke_known) + { + req = _mvl_find_req_ctrl (netInfo, -1, info->invoke); + if (!req) + { + MVL_LOG_CNERR0 ("Could not match confirmed request"); + return; + } + req->event = event; + req->reject_info = + (REJECT_RESP_INFO *) req->event->u.mms.dec_rslt.data_ptr; + _mvl_set_req_done (req, MVL_ERR_CNF_REJ_ERR); + freeCommEvent = SD_FALSE; + } + } + +/* Let the user know about this */ + u_mvl_reject_ind (netInfo, info); + + if (freeCommEvent) + _mvl_free_comm_event (event); /* All done with this event */ + } + +/************************************************************************/ +/************************************************************************/ +/* This table is used to select reject class given MMS pdu type */ +/* PDU type is the index into this table */ +/************************************************************************/ + +SD_CONST ST_INT16 pdutype_to_reject_class[14] = + { + 1, /* confirmed request */ + 2, /* confirmed response */ + 3, /* confirmed error */ + 4, /* unconfirmed */ + 5, /* reject */ + 6, /* cancel request */ + 7, /* cancel response */ + 8, /* cancel error */ + 0, /* initiate req - not used */ + 0, /* initiate resp - not used */ + 0, /* initiate error - not used */ + 9, /* conclude request */ + 10, /* conclude response */ + 11 /* conclude error */ + }; + +/************************************************************************/ +/* _mvl_ind_reject */ +/* Send reject for Indication. */ +/************************************************************************/ + +ST_VOID _mvl_ind_reject (MVL_IND_PEND *ind_pend) + { +MVL_NET_INFO *net_info; + + net_info = ind_pend->event->net_info; + _mvl_send_reject (ind_pend->event); + list_unlink(&(net_info->pend_ind),ind_pend); + --net_info->numpend_ind; + + M_FREE (MSMEM_IND_CTRL, ind_pend); + } + +/************************************************************************/ +/* _mvl_conf_reject */ +/* Send reject for Confirmation. */ +/************************************************************************/ + +ST_VOID _mvl_conf_reject (MVL_REQ_PEND *req_pend) + { + _mvl_send_reject (req_pend->event); + req_pend->event = NULL; /* so mvl_free_req_ctrl doesn't try to */ + /* free it again. */ + req_pend->result = SD_FAILURE;/* Let user know it failed. */ + } + +/************************************************************************/ +/* _mvl_send_reject */ +/* This is a simple minded reject send function. If the PDU type isd */ +/* known, send a reject of the appropriate class with code == OTHER. */ +/* This is not always exactly right per the MMS service document, but */ +/* will be OK for now. */ +/************************************************************************/ + +ST_VOID _mvl_send_reject (MVL_COMM_EVENT *event) + { +ST_RET rc; +REJECT_RESP_INFO rej_info; +MMSDEC_INFO *rslt; + + S_LOCK_COMMON_RESOURCES (); + rej_info.detected_here = SD_TRUE; + rej_info.invoke_known = SD_FALSE; + rslt = &event->u.mms.dec_rslt; + if (rslt->dec_level > 0) /* If we at least know the type of PDU */ + { + rej_info.pdu_type = rslt->type; + /* If this was unrecognized confirmed request, set appropriate reject class/code. */ + if (rslt->dec_level >= 2 && rslt->type == MMSREQ && rslt->err_code==REQ_UNREC_SERV) + { + rej_info.rej_class = MMS_REJ_CLASS_CONFIRMED_REQUEST_PDU; + rej_info.rej_code = MMS_REJ_CODE_CONFIRMED_REQUEST_PDU_UNRECOGNIZED_SERVICE; + } + else + { /* set correct class, but just set code to "OTHER" (0). */ + rej_info.rej_class = pdutype_to_reject_class[rslt->type]; + rej_info.rej_code = 0; + } + + if ((rslt->dec_level >= 2) && /* if invoke ID known, use it */ + (rslt->type == MMSREQ || rslt->type == MMSRESP)) + { + rej_info.invoke_known = SD_TRUE; + rej_info.invoke = rslt->id; + } + } + else + { + rej_info.pdu_type = UNKNOWNTYPE; + rej_info.rej_class = MMS_REJ_CLASS_PDU_ERROR; + rej_info.rej_code = MMS_REJ_CODE_PDU_ERROR_INVALID_PDU; + } + + rc = mpl_reject_resp (&rej_info); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Sending Reject : mpl_reject_resp failed, ret = %x", rc); + } + else + { /* build was OK, send it */ + rc = _mvl_send_msg (mmsl_msg_start,mmsl_msg_len, event->net_info); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Sending Reject : _mvl_send_msg failed, ret = %x", rc); + } + else + ++mvl_mms_statistics.rejectsSent; + } + +/* Tell the user all about it ... */ + u_mvl_reject_ind (event->net_info, &rej_info); + + _mvl_free_comm_event (event); /* All done with this event */ + S_UNLOCK_COMMON_RESOURCES (); + } + + +/************************************************************************/ +/* _mvl_send_reject_net_info */ +/************************************************************************/ + +static ST_VOID _mvl_send_reject_net_info (MVL_NET_INFO *net_info, + REJECT_RESP_INFO *rej_info) + + { +ST_RET rc; + + S_LOCK_COMMON_RESOURCES (); + rc = mpl_reject_resp (rej_info); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Sending Reject : mpl_reject_resp failed, ret = %x", rc); + } + else + { /* build was OK, send it */ + rc = _mvl_send_msg (mmsl_msg_start,mmsl_msg_len, net_info); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Sending Reject : _mvl_send_msg failed, ret = %x", rc); + } + else + ++mvl_mms_statistics.rejectsSent; + } + +/* Tell the user all about it ... */ + u_mvl_reject_ind (net_info, rej_info); + + S_UNLOCK_COMMON_RESOURCES (); + } + + +/************************************************************************/ +/* _mplas_err_resp */ +/* This function sends an error response and frees the MVL_IND_PEND */ +/* and the MVL_COMM_EVENT. */ +/************************************************************************/ + +ST_RET _mplas_err_resp (MVL_IND_PEND *indCtrl, ST_INT16 eClass, ST_INT16 code) + { +ST_RET rc; +MVL_NET_INFO *net_info; + + net_info = indCtrl->event->net_info; + rc = _mvl_send_err_f (indCtrl->event, eClass, code); + list_unlink(&(net_info->pend_ind),indCtrl); + --net_info->numpend_ind; + + M_FREE (MSMEM_IND_CTRL, indCtrl); + ++mvl_mms_statistics.serverRespErr; + return (rc); + } + +/************************************************************************/ +/* _mvl_send_err_f */ +/* This function sends an error response and frees the MVL_COMM_EVENT. */ +/************************************************************************/ + +ST_RET _mvl_send_err_f (MVL_COMM_EVENT *event, ST_INT16 eClass, ST_INT16 code) + { +ST_RET rc; + + rc = _mvl_send_error (event, eClass, code); + _mvl_free_comm_event (event); /* All done with this event */ + return (rc); + } + +/************************************************************************/ +/* _mvl_send_error */ +/* This function is used to send an error response to a confirmed */ +/* request PDU. */ +/************************************************************************/ + +ST_RET _mvl_send_error (MVL_COMM_EVENT *event, ST_INT16 eClass, ST_INT16 code) + { +ST_RET rc; + + S_LOCK_COMMON_RESOURCES (); + rc = mpl_err_resp (event->u.mms.dec_rslt.op, + event->u.mms.dec_rslt.id, + eClass,code); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Sending Error : mpl_err_resp failed, ret = %x", rc); + } + else + { /* build was OK, send it */ + rc = _mvl_send_msg (mmsl_msg_start,mmsl_msg_len,event->net_info); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Sending Error : _mvl_send_msg failed, ret = %x", rc); + } + else + ++mvl_mms_statistics.serverRespErr; + } + S_UNLOCK_COMMON_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* mvl_wait_req_done */ +/* RETURNS: SD_SUCCESS or MVL error code */ +/************************************************************************/ + +ST_RET mvl_wait_req_done (MVL_REQ_PEND *req) + { + while (req->done == SD_FALSE) /* wait forever until done */ + { + if (u_mvl_check_timeout) + { + if ((*u_mvl_check_timeout)()) + { + req->result = MVL_ERR_USR_TIMEOUT; + MVL_LOG_NERR0 ("Wait Request Done : u_mvl_check_timeout timed out"); + break; + } + } + mvl_comm_serve (); /* service communications */ + } + return (req->result); + } + +/************************************************************************/ +/************************************************************************/ +/* Outstanding MMS request control handling functions */ +/************************************************************************/ + + +/************************************************************************/ +/* _mvl_get_req_ctrl */ +/************************************************************************/ + +MVL_REQ_PEND *_mvl_get_req_ctrl (MVL_NET_INFO *net_info, ST_INT16 op) + { +MVL_REQ_PEND *req; + + if (net_info == NULL) + { + MVL_LOG_NERR0 ("_mvl_get_req_ctrl error: connection invalid"); + return (NULL); + } + req = (MVL_REQ_PEND *) M_CALLOC (MSMEM_REQ_CTRL, 1, sizeof (MVL_REQ_PEND)); + S_LOCK_COMMON_RESOURCES (); + list_add_last(&net_info->req_pend_list, req); + + req->invoke_id = mmsl_invoke_id; + req->op = op; + req->done = SD_FALSE; + req->result = SD_SUCCESS; + req->net_info = net_info; + req->u_req_done = NULL; + req->event = NULL; + S_UNLOCK_COMMON_RESOURCES (); + return (req); + } + +/************************************************************************/ +/* _mvl_find_req_ctrl */ +/************************************************************************/ + +MVL_REQ_PEND *_mvl_find_req_ctrl (MVL_NET_INFO *net_info, + ST_INT op, ST_UINT32 id) + { +MVL_REQ_PEND *req; + + S_LOCK_COMMON_RESOURCES (); + req = net_info->req_pend_list; /* start at head of linked list */ + while (req != NULL) /* look through whole list */ + { + if (req->net_info == net_info && + req->invoke_id == id) + { + if (req->op == op || op == -1) + break; /* return a pointer to it */ + } + req = (MVL_REQ_PEND *) list_get_next (net_info->req_pend_list, req); + } + + S_UNLOCK_COMMON_RESOURCES (); + return (req); + } + +/************************************************************************/ +/* _mvl_set_net_req_done */ +/************************************************************************/ + +ST_VOID _mvl_set_net_req_done (MVL_REQ_PEND *skip, + MVL_NET_INFO *net_info, ST_RET result) + { +MVL_REQ_PEND *req; +MVL_REQ_PEND *next; + + req = net_info->req_pend_list; /* start at head of linked list */ + while (req != NULL) /* look through whole list */ + { + /* CRITICAL: get NEXT entry BEFORE calling _mvl_set_req_done */ + /* because it may remove THIS entry from the linked list. */ + next = (MVL_REQ_PEND *) list_get_next (net_info->req_pend_list, req); + if (req->done != SD_TRUE) + { + if (req != skip) + _mvl_set_req_done (req, result); + } + req = next; + } + + /* CRITICAL: Destroy all AA_SPEC objects on this connection. */ + /* This is a good place to do this because this function is */ + /* called on Abort.req, Abort.ind, Release.ind, or Release.cnf */ + + if (!_mvl_persist_aa_objs) + _mvl_clear_aa_objs (net_info->aa_objs); + } + + +/************************************************************************/ +/* _mvl_set_req_done */ +/************************************************************************/ + +ST_VOID _mvl_set_req_done (MVL_REQ_PEND *req, ST_RET result) + { + req->result = result; + req->done = SD_TRUE; + + if (req->u_req_done) /* Call the user done function */ + (*req->u_req_done)(req); + } + +/************************************************************************/ +/* mvl_free_req_ctrl */ +/************************************************************************/ + +ST_VOID mvl_free_req_ctrl (MVL_REQ_PEND *pend_req) + { + + + if (pend_req) + { + S_LOCK_COMMON_RESOURCES (); + + + + if (pend_req->event) + _mvl_free_comm_event (pend_req->event); + + + /* Free up extra stuff for some services. */ + /* NOTE: on error or reject the union (pend_req->u) is overwritten */ + /* so "normal" resp_info is not valid. DON'T try to free it. */ + if (pend_req->op == MMSOP_FILE_DIR && + pend_req->result != MVL_ERR_CNF_REJ_ERR && /* !reject */ + pend_req->result != MVL_ERR_CNF_ERR_OK && /* !error */ + pend_req->u.fdir.resp_info != NULL) + { /* Only do this if it was allocated (see confirm function) */ + M_FREE (MSMEM_GEN, pend_req->u.fdir.resp_info); + } + if (pend_req->op == MMSOP_READ_JOURNAL && + pend_req->result != MVL_ERR_CNF_REJ_ERR && /* !reject */ + pend_req->result != MVL_ERR_CNF_ERR_OK && /* !error */ + pend_req->u.jread.resp_info != NULL) + { /* Only do this if it was allocated (see confirm function) */ + M_FREE (MSMEM_GEN, pend_req->u.jread.resp_info); + } + + list_unlink (&pend_req->net_info->req_pend_list, pend_req); + M_FREE (MSMEM_REQ_CTRL, pend_req); + S_UNLOCK_COMMON_RESOURCES (); + } + + } + +/************************************************************************/ +/************************************************************************/ +/* mvl_init_glb_vars */ +/************************************************************************/ +/* For use when global variables cannot be initialized at compile time */ + +#if defined(NO_GLB_VAR_INIT) + +ST_VOID mvl_init_glb_vars (ST_VOID) + { + m_init_glb_vars (); + _mvlop_en_init () + } +#endif + +/************************************************************************/ +/* _mvl_concat_filename */ +/************************************************************************/ +ST_RET _mvl_concat_filename (ST_CHAR *good_name, + ST_INT num_of_fname, + FILE_NAME *fname_arr, + ST_INT max_len) /* size of array to fill in (i.e. good_name) */ + { +ST_INT j; +ST_INT total_len; + + for (j = 0, total_len = 0; j < num_of_fname; j++) + total_len += fname_arr[j].fn_len; + + if (total_len + 1 > max_len) /* Must leave room for NULL */ + return (SD_FAILURE); + + for (j = 0, total_len = 0; j < num_of_fname; j++) + { + memcpy (&good_name [total_len], fname_arr[j].fname, fname_arr[j].fn_len); + total_len += fname_arr[j].fn_len; + } + good_name [total_len] = '\x00'; /* add NULL terminator */ + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* _mvl_calloc_os */ +/************************************************************************/ + +ST_VOID *_mvl_calloc_os (ST_UINT num, ST_UINT size) + { + return (M_CALLOC (MSMEM_DEC_OS_INFO, 1, size)); + } + +/************************************************************************/ +/* _mvl_realloc_os */ +/************************************************************************/ + +ST_VOID *_mvl_realloc_os (ST_VOID *old, ST_UINT new_size) + { + return (M_REALLOC (MSMEM_DEC_OS_INFO, old,new_size)); + } + +/************************************************************************/ +/* _mvl_free_os */ +/************************************************************************/ + +ST_VOID _mvl_free_os (ST_VOID *buf) + { + M_FREE (MSMEM_DEC_OS_INFO, buf); + } + +/************************************************************************/ +/* mvl_req_bufs_avail */ +/* Return number of buffers available for sending "confirmed" requests. */ +/************************************************************************/ + +ST_INT mvlLowWaterAvail = 50; +ST_INT mvlLowWaterReqAvail = 50; +ST_INT mvlLowWaterUReqAvail = 50; + +ST_INT mvl_req_bufs_avail (MVL_NET_INFO *net_info) + { +ST_INT avail; + + avail = a_buffers_avail (net_info->acse_conn_id); + if (avail < mvlLowWaterAvail) + { + mvlLowWaterAvail = avail; + MVLU_LOG_DEBUG1 ("Low water 'buffers available': %d", mvlLowWaterAvail); + } + + /* Must have enough buffers avail to respond to max num of indications.*/ + /* Doesn't matter how many indications are currently pending because */ + /* at any momemt could get a bunch of indications and must ALWAYS */ + /* have buffers available to respond to the maximum. */ + + avail -= net_info->maxpend_ind; + + if (avail < mvlLowWaterReqAvail) + { + mvlLowWaterReqAvail = avail; + MVLU_LOG_DEBUG1 ("Low water 'Req buffers available': %d", mvlLowWaterReqAvail); + } + return (avail); + } + +/************************************************************************/ +/* mvl_ureq_bufs_avail */ +/* Return number of buffers available for sending "unconfirmed" reqs */ +/************************************************************************/ + +ST_INT mvl_ureq_bufs_avail (MVL_NET_INFO *net_info) + { +ST_INT avail; + + avail = a_buffers_avail (net_info->acse_conn_id); + if (avail < mvlLowWaterAvail) + { + mvlLowWaterAvail = avail; + MVLU_LOG_DEBUG1 ("Low water 'buffers available': %d", mvlLowWaterAvail); + } + + /* Must have enough buffers avail to respond to max num of indications.*/ + /* Doesn't matter how many indications are currently pending because */ + /* at any momemt could get a bunch of indications and must ALWAYS */ + /* have buffers available to respond to the maximum. */ + + /* Because we don't know when response buffers are release by SUIC, */ + /* we always assume that we must be able to send the max resp at any */ + /* time. This means that when there really ARE max resp pend in SUIC */ + /* we reserve twice as many as we need ... */ + + avail -= (net_info->maxpend_ind * 2); /* reserve maximum */ + + /* Must have enough buffers avail to send max num of "confirmed" reqs.*/ + /* Doesn't matter how many requests are currently pending because */ + /* at any momemt could get a bunch of confirms and may want to send */ + /* new requests. So, we need to have buffers reserved for the max. */ + avail -= (net_info->maxpend_req); + + if (avail < mvlLowWaterUReqAvail) + { + mvlLowWaterUReqAvail = avail; + MVLU_LOG_DEBUG1 ("Low water 'UReq buffers' available': %d", mvlLowWaterUReqAvail); + } + return (avail); + } + diff --git a/mmslib/mvlu/mvl_typ2.c b/mmslib/mvlu/mvl_typ2.c new file mode 100644 index 0000000..371e2b8 --- /dev/null +++ b/mmslib/mvlu/mvl_typ2.c @@ -0,0 +1,322 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2000 - 2000, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_typ2.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Dynamic type creation/destruction functions. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* mvl_type_id_create */ +/* mvl_type_id_destroy */ +/* mvl_type_id_create_from_tdl */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/11/07 JRB 12 mvl_type_id_destroy2: Reset struct to all 0. */ +/* 11/22/06 JRB 11 mvl_type_id_create_from_tdl: clean up on err.*/ +/* 10/30/06 JRB 10 Replace static mvl_type_id_create2 with */ +/* extern mvl_vmd_type_id_create which has */ +/* vmd_ctrl arg. */ +/* Add "mvl_vmd_type_id_destroy(_all)". */ +/* Add mvl_type_count. */ +/* 01/30/06 GLB 09 Integrated porting changes for VMS */ +/* 04/11/05 CRM 08 Added mvl_type_id_destroy_all_dyn */ +/* 03/14/05 CRM 07 Replaced _mvlu_num_dyn_types variable with */ +/* mvl_max_dyn.types. */ +/* 06/29/04 JRB 06 Add mvl_type_id_create_from_tdl. */ +/* 09/18/03 JRB 05 mvl_type_id_create: Allow type_name==NULL. */ +/* 03/13/03 JRB 04 Use static funcs mvl_type_id_create2/destroy2.*/ +/* In create2, make sure name not already used. */ +/* Call mvlu_proc_rt_type for UCA types. */ +/* MVL_TYPE_CTRL: type_name is now array, copy to it*/ +/* 11/11/02 JRB 03 Use NEW ms_runtime_create/destroy (new args).*/ +/* 09/05/00 JRB 02 Use mvl_get_runtime_dyn to find runtime type.*/ +/* 09/05/00 JRB 01 Created. Moved code here from "mvl_type.c". */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mvl_defs.h" +#include "mvl_log.h" +#include "mvl_uca.h" /* need mvlu_proc_rt_type proto */ + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* Static function prototypes. */ +/************************************************************************/ +static RUNTIME_CTRL *mvl_type_id_destroy2 (ST_INT typeId); + +/************************************************************************/ +/* mvl_type_id_create */ +/* RETURNS: */ +/* Type Id (or -1 on error) */ +/* NOTE: Use "mvl_type_id_destroy" to destroy this object. */ +/************************************************************************/ +ST_INT mvl_type_id_create (ST_CHAR *type_name, ST_UCHAR *asn1_data, ST_UINT asn1_len) + { +RUNTIME_CTRL *rt_ctrl; +ST_INT TypeId = -1; /* assume failure */ + + rt_ctrl = ms_runtime_create (asn1_data, asn1_len, + (UINT_MAX/sizeof(RUNTIME_TYPE))-100); + if (rt_ctrl) + { /* "runtime create" successful, do "step 2". */ + TypeId = mvl_vmd_type_id_create (&mvl_vmd, /* assume global VMD */ + type_name, rt_ctrl); + if (TypeId < 0) /* "step 2" failed, so destroy runtime just created.*/ + ms_runtime_destroy (rt_ctrl); + } + return (TypeId); + } + +/************************************************************************/ +/* mvl_type_id_destroy */ +/* Destroy object created by "mvl_type_id_create". */ +/************************************************************************/ +ST_VOID mvl_type_id_destroy (ST_INT TypeId) + { +RUNTIME_CTRL *rt_ctrl; + rt_ctrl = mvl_type_id_destroy2 (TypeId); /* remove it from list */ + if (rt_ctrl) + ms_runtime_destroy (rt_ctrl); /* destroy it */ + else + { +#ifndef WIN32 + MVL_LOG_ERR1 ("mvl_type_id_destroy error: TypeId %d not dynamically created", TypeId); +#endif + } + } + +/************************************************************************/ +/* mvl_type_id_destroy_all_dyn */ +/* Destroy dynamic type ids. */ +/************************************************************************/ +ST_RET mvl_type_id_destroy_all_dyn () + { +ST_INT j; +ST_INT type_id_first_dyn; /* type_id of first dynamic type */ + + /* Loop through all dynamic types. */ + type_id_first_dyn = mvl_num_types - mvl_max_dyn.types; + for (j = type_id_first_dyn; j < mvl_num_types; j++) + { + if (mvl_type_ctrl[j].num_rt != 0) /* != 0 indicates this type_id used.*/ + mvl_type_id_destroy (j); /* destroy it. */ + } + return (SD_SUCCESS); /* at present, no way to fail. */ + } + +/************************************************************************/ +/* mvl_vmd_type_id_create */ +/* Second step of creating type_id. */ +/* RETURNS: */ +/* Type Id (or -1 on error) */ +/************************************************************************/ +ST_INT mvl_vmd_type_id_create (MVL_VMD_CTRL *vmd_ctrl, ST_CHAR *type_name, RUNTIME_CTRL *rt_ctrl) + { +ST_INT typeId; +MVL_TYPE_CTRL *type_ctrl; /* ptr to current array element */ + + assert (vmd_ctrl); /* VMD must be valid */ + + /* This assertion fails if the global array mvl_type_ctrl is not initialized + * To avoid this, create dynamic types ONLY AFTER "mvl_init_type_ctrl" + * (in Foundry output "c" file) is called. + */ + assert (mvl_type_ctrl); /* make sure type control initialized */ + + /* If named, make sure name not too long & name not already used. */ + if (type_name!=NULL) + { + if (strlen (type_name) >= sizeof (type_ctrl->type_name)) + return (-1); /* type_name exceeds max allowed size */ + + for (typeId = 0; typeId < mvl_num_types; ++typeId) + { + type_ctrl = &mvl_type_ctrl[typeId]; /* ptr to array elem*/ + if (type_ctrl->num_rt!=0 && type_ctrl->type_name!=NULL + && strcmp (type_ctrl->type_name, type_name) == 0) + { + MVL_LOG_ERR1 ("Type creation error: name '%s' already in use", type_name); + return (-1); /* FAILED: name in use */ + } + } + } + +#if defined (MVL_UCA) /* do post-processing for UCA types. */ + //if (mvlu_proc_rt_type (type_name, rt_ctrl, NULL))//lnk编译修改,原å‰ç½®ç¨‹åºæœªä½¿ç”¨ + if (0)//lnk编译修改,原å‰ç½®ç¨‹åºæœªä½¿ç”¨ + return (-1); /* FAILED: return invalid typeId */ +#endif /* MVL_UCA */ + + /* Just search for a unused slot */ + for (typeId = mvl_num_types - mvl_max_dyn.types; typeId < mvl_num_types; ++typeId) + { + type_ctrl = &mvl_type_ctrl[typeId]; /* ptr to array elem*/ + if (type_ctrl->num_rt == 0) + { + if (type_name) + strcpy (type_ctrl->type_name, type_name); /* size checked above */ + else + type_ctrl->type_name[0] = '\0'; /* unnamed type */ + type_ctrl->rt_ctrl = rt_ctrl; /* no other func sets this*/ + type_ctrl->rt = rt_ctrl->rt_first; + type_ctrl->num_rt = rt_ctrl->rt_num; + type_ctrl->data_size = rt_ctrl->rt_first->offset_to_last; + type_ctrl->vmd_ctrl = vmd_ctrl; /* save ptr to VMD using this type*/ + return (typeId); + } + } + MVL_LOG_ERR0 ("mvl_type_id_create error: type array full"); + return (-1); /* error, no slots available. Return invalid typeId. */ + } + +/************************************************************************/ +/* mvl_type_id_destroy2 */ +/* Second step of destroying type_id. */ +/* Remove type from array, return pointer to it. */ +/* NOTE: uses mvl_type_ctrl_find_dyn to make sure it's "dynamic" type. */ +/************************************************************************/ +static RUNTIME_CTRL *mvl_type_id_destroy2 (ST_INT typeId) + { +MVL_TYPE_CTRL *type_ctrl; +RUNTIME_CTRL *rt_ctrl = NULL; /* assume failure */ + + type_ctrl = mvl_type_ctrl_find_dyn (typeId); + if (type_ctrl) + { /* save ptr to type, then remove it from array */ + rt_ctrl = type_ctrl->rt_ctrl; + /* Reset the structure to all 0 so it is ready to be reused. */ + /* NOTE: this should be a type created by mvl_vmd_type_id_create */ + /* so rt_ctrl and vmd_ctrl should be set (not NULL). */ + /* NOTE: this clears num_rt which indicates unused array entry. */ + memset (type_ctrl, 0, sizeof (MVL_TYPE_CTRL)); + } + return (rt_ctrl); + } + +/************************************************************************/ +/* mvl_type_id_create_from_tdl */ +/************************************************************************/ +ST_INT mvl_type_id_create_from_tdl (ST_CHAR *type_name, ST_CHAR *tdl) + { +ST_UCHAR *asn1_buf; /* tmp ASN.1 buffer. Alloc & free here. */ +ST_INT asn1_len; +ST_INT type_id; +RUNTIME_CTRL *rt_ctrl; + + /* Allocate minimum of 2000 bytes, more for long TDL. */ + /* NOTE: may want to increase mininum to reduce memory fragmentation. */ + asn1_len = max (2000, (2 * strlen (tdl))); /* initial len. Changed by ms_mk_asn1_type*/ + asn1_buf = (ST_UCHAR *) chk_malloc (asn1_len); + + if ((rt_ctrl = ms_tdl_to_runtime (tdl, asn1_buf, asn1_len)) == NULL) + { + MVL_LOG_ERR0 ("ms_tdl_to_runtime error"); + type_id = -1; /* error */ + } + else + { + /* Create MVL type_id. This function also performs post-processing */ + /* on "rt_ctrl". */ + type_id = mvl_vmd_type_id_create (&mvl_vmd, /* assume global VMD */ + type_name, rt_ctrl); + if (type_id < 0) + ms_runtime_destroy (rt_ctrl); /* clean up on error */ + } + + if (type_id < 0) + MVL_LOG_ERR2 ("mvl_type_id_create_from_tdl: type creation failed for '%s', TDL=%s.", type_name, tdl); + + chk_free (asn1_buf); + return (type_id); + } + +/************************************************************************/ +/* mvl_vmd_type_id_destroy */ +/* Destroy type id, but only if it belongs to this VMD. */ +/************************************************************************/ +ST_RET mvl_vmd_type_id_destroy (MVL_VMD_CTRL *vmd_ctrl, ST_INT type_id) + { + assert (vmd_ctrl); /* VMD must be valid */ + if (mvl_type_ctrl[type_id].num_rt != 0 /* != 0 indicates this type_id used.*/ + && mvl_type_ctrl[type_id].vmd_ctrl == vmd_ctrl) /* VMD matches */ + { + mvl_type_id_destroy (type_id); /* destroy it. */ + return (SD_SUCCESS); + } + else + return (SD_FAILURE); + } +/************************************************************************/ +/* mvl_vmd_type_id_destroy_all */ +/* Destroy all type ids for this VMD. */ +/************************************************************************/ +ST_RET mvl_vmd_type_id_destroy_all (MVL_VMD_CTRL *vmd_ctrl) + { +ST_INT type_id; +ST_INT num_destroyed = 0; + + /* Try to destroy all types. If VMD doesn't match, destroy fails. */ + /* Count how many times destroy succeeds. */ + for (type_id = mvl_num_types - mvl_max_dyn.types; type_id < mvl_num_types; type_id++) + { + if (mvl_vmd_type_id_destroy (vmd_ctrl, type_id) == SD_SUCCESS) + num_destroyed++; + } + MVLU_LOG_FLOW1 ("Number of types destroyed for this VMD=%d", num_destroyed); + return (SD_SUCCESS); /* at present, no way to fail. */ + } + +/************************************************************************/ +/* mvl_type_count */ +/* Return the current number of types in use. */ +/************************************************************************/ +ST_INT mvl_type_count () + { +ST_INT type_id; +ST_INT count = 0; + + /* Try to destroy all types. If VMD doesn't match, destroy fails. */ + /* Count how many times destroy succeeds. */ + for (type_id = 0; type_id < mvl_num_types; type_id++) + { + if (mvl_type_ctrl[type_id].num_rt != 0) /* != 0 indicates this type_id used.*/ + count++; + } + return (count); + } +/************************************************************************/ +/* mvl_vmd_type_ctrl_find */ +/* Find type_ctrl for this type id, but only if it belongs to this VMD. */ +/************************************************************************/ +MVL_TYPE_CTRL *mvl_vmd_type_ctrl_find (MVL_VMD_CTRL *vmd_ctrl, ST_INT type_id) + { + assert (vmd_ctrl); /* VMD must be valid */ + if (mvl_type_ctrl[type_id].num_rt != 0 /* != 0 indicates this type_id used.*/ + && mvl_type_ctrl[type_id].vmd_ctrl == vmd_ctrl) /* VMD matches */ + { + return (&mvl_type_ctrl[type_id]); + } + else + return (NULL); /* not found or doesn't belong to this VMD. */ + } + diff --git a/mmslib/mvlu/mvl_type.c b/mmslib/mvlu/mvl_type.c new file mode 100644 index 0000000..48666cd --- /dev/null +++ b/mmslib/mvlu/mvl_type.c @@ -0,0 +1,266 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_type.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/11/07 JRB 17 mvlu_free_rt_type: Reset structure to all 0. */ +/* 02/07/06 JRB 16 Log if max types exceeded. */ +/* 03/14/05 CRM 15 Add mvl_max_dyn global struct & replace */ +/* _mvlu_num_dyn_types with "mvl_max_dyn.types".*/ +/* 09/18/03 JRB 14 mvl_get_runtime: chk for valid num_rt. */ +/* 03/13/03 JRB 13 Add mvl_type_ctrl_find_dyn. */ +/* Del mvlu_add_rt_type_x (not needed). */ +/* 11/27/02 MDE 12 Added mvlu_add_rt_type_x, */ +/* mvl_typeid_to_typename, */ +/* mvl_typename_to_typeid */ +/* 10/28/02 JRB 11 Del mvl_mk_rt_from_asn1, use ms_runtime_create*/ +/* 10/06/00 MDE 10 Added _mvlu_num_dyn_types */ +/* 09/05/00 JRB 09 Move mvl_type_id_* to new module. */ +/* Add mvl_get_runtime_dyn. */ +/* mvl_type_ctrl_find chk for "in use". */ +/* 07/13/00 JRB 08 Add Dynamic type creation functions: */ +/* mvl_type_id_create, mvl_type_id_destroy, */ +/* mvl_type_ctrl_find. */ +/* Move these functs from mvl_uca.c to here: */ +/* mvlu_add_rt_type, mvlu_free_rt_type. */ +/* 04/14/00 JRB 07 Del SD_CONST from mvl_get_runtime. */ +/* 01/21/00 MDE 06 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 11/16/98 MDE 04 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 03 Minor lint cleanup */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mvl_defs.h" +#include "mvl_log.h" + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* The user may set this to a positive value prior to calling */ +/* 'mvl_init_mms_objs' to control the number allowed */ + +MVL_MAX_DYN mvl_max_dyn; + +/************************************************************************/ +/************************************************************************/ +/* mvl_mod_arr_size */ +/* TYPE HANDLING */ +/* This function modifies the size of an array runtime element */ +/************************************************************************/ + +ST_VOID mvl_mod_arr_size (RUNTIME_TYPE *rt, ST_RTINT num_elmnts) + { +ST_INT size_per_el; + +/* Adjust the total size of the type, using scaling */ + size_per_el = rt->offset_to_last/rt->u.arr.num_elmnts; + rt->offset_to_last = size_per_el * num_elmnts; + +/* Now set the number of elements as desired */ + rt->u.arr.num_elmnts = num_elmnts; + rt += (rt->u.arr.num_rt_blks + 1); + rt->u.arr.num_elmnts = num_elmnts; + } + +/************************************************************************/ +/* mvl_get_runtime */ +/* This function returns runtime type information given the type id */ +/************************************************************************/ + +ST_RET mvl_get_runtime (ST_INT type_id, + RUNTIME_TYPE **rt_out, + ST_INT *num_rt_out) + { +MVL_TYPE_CTRL *type_ctrl = &mvl_type_ctrl[type_id]; /* ptr to array elem*/ + + if (type_id >= 0 && + type_id < mvl_num_types && + type_ctrl->num_rt > 0) + { + /* Cast "rt" to remove SD_CONST. */ + *rt_out = (RUNTIME_TYPE *) type_ctrl->rt; + *num_rt_out = type_ctrl->num_rt; + return (SD_SUCCESS); + } + return (MVL_ERR_RUNTIME_TYPE_ID); + } + +/************************************************************************/ +/* mvl_get_runtime_dyn */ +/* This function returns runtime type information given the type id. */ +/* It is the same as "mvl_get_runtime" except it only SUCCEEDS if the */ +/* type was dynamically created. */ +/************************************************************************/ + +ST_RET mvl_get_runtime_dyn (ST_INT type_id, + RUNTIME_TYPE **rt_out, + ST_INT *num_rt_out) + { +MVL_TYPE_CTRL *type_ctrl = &mvl_type_ctrl[type_id]; /* ptr to array elem*/ + + if (type_id >= mvl_num_types - mvl_max_dyn.types && /* dynamic type */ + type_id < mvl_num_types && + type_ctrl->num_rt > 0) + { + /* Cast "rt" to remove SD_CONST. */ + *rt_out = (RUNTIME_TYPE *) type_ctrl->rt; + *num_rt_out = type_ctrl->num_rt; + return (SD_SUCCESS); + } + return (MVL_ERR_RUNTIME_TYPE_ID); + } + +/************************************************************************/ +/* mvl_type_ctrl_find */ +/* Find the type ctrl structure corresponding to the type id. */ +/* RETURNS: ptr to type ctrl structure (NULL on error) */ +/* NOTE: Use "mvl_get_runtime*" if only the runtime type is needed. */ +/************************************************************************/ +MVL_TYPE_CTRL *mvl_type_ctrl_find (ST_INT TypeId) + { +MVL_TYPE_CTRL *type_ctrl; + + if (TypeId < 0 || + TypeId >= mvl_num_types || + mvl_type_ctrl[TypeId].num_rt == 0) /* Array entry not in use.*/ + type_ctrl = NULL; + else + type_ctrl = &mvl_type_ctrl [TypeId]; + return (type_ctrl); + } + +/************************************************************************/ +/* mvl_type_ctrl_find_dyn */ +/* Find the type ctrl structure corresponding to the type id. */ +/* For "dynamic" types ONLY. */ +/* RETURNS: ptr to type ctrl structure (NULL on error) */ +/************************************************************************/ +MVL_TYPE_CTRL *mvl_type_ctrl_find_dyn (ST_INT TypeId) + { +MVL_TYPE_CTRL *type_ctrl; + + if (TypeId < mvl_num_types - mvl_max_dyn.types) + type_ctrl = NULL; /* NOT dynamic. Return error*/ + else + type_ctrl = mvl_type_ctrl_find (TypeId); /* COULD BE dynamic, find it*/ + return (type_ctrl); + } + + +/************************************************************************/ +/* mvl_typeid_to_typename */ +/************************************************************************/ +ST_CHAR *mvl_typeid_to_typename (ST_INT type_id) + { + if (type_id >= 0 && type_id < mvl_num_types) + return (mvl_type_ctrl[type_id].type_name); + + return ("unknown"); + } + +/************************************************************************/ +/* mvl_typename_to_typeid */ +/************************************************************************/ + +ST_INT mvl_typename_to_typeid (ST_CHAR *type_id_string) + { +ST_INT i; +MVL_TYPE_CTRL *type_ctrl; + + for (i = 0; i < mvl_num_types; ++i) + { + type_ctrl = &mvl_type_ctrl[i]; + if (mvl_type_ctrl[i].num_rt != 0 && + mvl_type_ctrl[i].type_name != NULL && + !strcmp (mvl_type_ctrl[i].type_name, type_id_string)) + { + return (i); + } + } + return (-1); + } + + +/************************************************************************/ +/************************************************************************/ +/* MVLU UTILITY FUNCTIONS */ +/************************************************************************/ +/************************************************************************/ +/* mvlu_add_rt_type */ +/************************************************************************/ +/* This function adds a RT type to the 'mvl_type_ctrl' table and */ +/* returns ther type id for the new entry. */ +MVL_TYPE_CTRL *temp_type_ctrl; +ST_RET mvlu_add_rt_type (RUNTIME_TYPE *rt, ST_INT numRt, ST_INT *typeIdOut) + { +ST_INT i; +ST_INT mvlu_type_id_base; + + /* Just search for a unused slot */ + mvlu_type_id_base = mvl_num_types - mvl_max_dyn.types; + for (i = mvlu_type_id_base; i < mvl_num_types; ++i) + { + if (mvl_type_ctrl[i].num_rt == 0) + { + mvl_type_ctrl[i].rt = rt; + mvl_type_ctrl[i].num_rt = numRt; + mvl_type_ctrl[i].data_size = rt->offset_to_last; + mvl_type_ctrl[i].type_name[0] = '\0'; /* name unknown */ + *typeIdOut = i; + temp_type_ctrl =&mvl_type_ctrl[i]; + return (SD_SUCCESS); + } + } + MVL_LOG_ERR1 ("Cannot add Runtime Type. Maximum number '%d' exceeded", mvl_num_types); + return (SD_FAILURE); + } + +/************************************************************************/ +/* mvlu_free_rt_type */ +/************************************************************************/ +/* This function free's slot in the 'mvl_type_ctrl' table, so that it */ +/* will be available for future use by mvlu_add_rt_type */ + +ST_VOID mvlu_free_rt_type (ST_INT typeId) + { +MVL_TYPE_CTRL *type_ctrl; + if (typeId >= mvl_num_types - mvl_max_dyn.types) + { + /* Reset the structure to all 0 so it is ready to be reused. */ + /* NOTE: this should be a type created by mvlu_add_rt_type */ + /* so rt_ctrl and vmd_ctrl should be NULL. */ + /* NOTE: this clears num_rt which indicates unused array entry. */ + type_ctrl = &mvl_type_ctrl[typeId]; + memset (type_ctrl, 0, sizeof (MVL_TYPE_CTRL)); + } + } + + diff --git a/mmslib/mvlu/mvl_uca.c b/mmslib/mvlu/mvl_uca.c new file mode 100644 index 0000000..8234fe0 --- /dev/null +++ b/mmslib/mvlu/mvl_uca.c @@ -0,0 +1,2688 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998-2005, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mvl_uca.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Special read/write processing functions for UCA and */ +/* IEC 61850 objects. */ +/* */ +/* NOTE: define MVL61850_CTL_DISABLE to avoid calling user functions */ +/* (u_mvl61850_ctl_oper_*) if 61850 Controls not needed. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/27/09 JRB 70 Don't send write resp until ind is done. */ +/* Don't allow write if any leaf unwritable. */ +/* Call user func at start/end of complex write.*/ +/* 01/07/09 JRB 69 Del S_LOCK for OPC_CLIENT in u_mvl_read_ind */ +/* (already locked by mvl_comm_serve). */ +/* 06/30/08 JRB 68 Repl cmd_executing w/ ctlState (more flexible)*/ +/* Do SBO Ctrl checks only if Oper/Cancel is */ +/* ONLY structure being written. */ +/* Fix sboName buffer size. */ +/* 05/06/08 JRB 67 Set new cmd_executing flag. */ +/* 03/03/08 JRB 66 Call mvl61850_ctl_req_done to do what's needed*/ +/* when IEC 61850 control request completes. */ +/* 02/18/08 JRB 65 Use new mvl_var_create_derived function. */ +/* 02/07/08 JRB 64 Fix alignment of ptr passed to mvlu_clone.. */ +/* 12/18/07 MDE 63 Fixed lastDollar crash for IOS */ +/* 11/12/07 MDE 62 Changed MMSOP_RDWR_USR_HANDLED to _RD_ */ +/* 07/20/07 JRB 61 getGnlVarNames: fix crash when flatname */ +/* too long; add return code & check it. */ +/* 05/09/07 JRB 60 Fix alt_acc arg passed to mvlu_find_component*/ +/* Fix log macro args. */ +/* 04/30/07 JRB 59 Fix to work with RUNTIME_TYPE change. */ +/* 04/17/07 JRB 58 Fix calc of offset_from_base & prim_num */ +/* to work for Alt Access on arrays (corrects */ +/* primData, prim_num, and prim_offset_base */ +/* passed to leaf functions). */ +/* mvlu_find_struct_comp: add args to compute */ +/* offset & prim_num. */ +/* 03/07/07 JRB 57 Add mvlu_get_leaf_val_int_any. */ +/* 11/21/06 JRB 56 Send LastApplError if write of Oper, etc fails.*/ +/* 10/30/06 JRB 55 Use new mvl_vmd_* object handling functions. */ +/* mvlu_find_base_va: add args. */ +/* u_mvl_get_va_aa: add args. */ +/* u_gnl_ind_*: add net_info arg to */ +/* elim use of global var "_mvl_curr_net_info". */ +/* u_mvl_get_va_aa: do not set va->usr_ind_ctrl */ +/* (done by calling functions). */ +/* 10/26/06 JRB 54 Del unused local vars. */ +/* 09/27/06 MDE 53 Added MMSOP_RD_USR_HANDLED for IOS */ +/* 09/13/06 JRB 52 mvlu_find_comp_type: allow non-dynamic types.*/ +/* 08/09/06 JRB 51 Del u_mvl_get_nvl, u_mvl_free_nvl functions */ +/* (not needed with new improved Foundry). */ +/* Use "mvl_var_create/destroy" so all variables*/ +/* created/destroyed in one place. */ +/* 07/24/06 JRB 50 Chg some common ERR logs to FLOW. */ +/* 03/27/06 JRB 49 Add more mvlu_get_leaf_* functions. */ +/* 07/29/05 MDE 48 Fixed static data use for write handling */ +/* 07/11/05 JRB 47 Call user fcts (u_mvl61850_ctl_oper_*) if */ +/* !defined (MVL61850_CTL_DISABLE). */ +/* 01/19/05 JRB 46 u_gnl_ind_* return (-1) on error. */ +/* 12/09/04 JRB 45 init_prim_info_recursive: fix ARR_END handling.*/ +/* init_prim_info_arr: simplify & ret ST_VOID. */ +/* Add mvlu_find_comp_type, mvlu_get_leaf_val*. */ +/* Chg trim_branch_name to global mvlu_trim_.. */ +/* & simplify it using strrchr. */ +/* 09/20/04 JRB 44 startElWrites: if writing "Oper" or "Cancel" */ +/* struct, check SBO state. */ +/* mvlu_wr_prim_done call mvlu_sbo_ctrl_free. */ +/* 06/29/04 JRB 43 Del global var mvluUseStaticData, instead use*/ +/* use_static_data flag in MVL_VAR_ASSOC for Read.*/ +/* NEVER use static data for Write. */ +/* startElReads, etc: add prim_info arg. */ +/* Del elmntOffset, use prim_info->prim_offset. */ +/* 11/24/03 JRB 42 getGnlVarNames: fix prefix len by using */ +/* MAX_IDENT_LEN, chk overflow BEFORE writing, */ +/* & add logging & asserts. */ +/* 09/18/03 JRB 41 Allow alt acc on array of "nested" structures*/ +/* Add some debug logging & extra comments. */ +/* 05/02/03 JRB 40 switch(rt->el_tag): Use default for most cases*/ +/* 04/04/03 JRB 39 Fix integrity/GI scan code so multiple */ +/* concurrent scans don't corrupt one another. */ +/* 12/20/02 JRB 38 Moved mvlu_set_leaf_param to mvluleaf.c */ +/* 12/12/02 JRB 37 Use usr_resp_fun ptr to call scan done funcs.*/ +/* 12/09/02 MDE 36 Made mvlu_find_uca_var global */ +/* 11/27/02 MDE 35 Addded leaf indication handlers */ +/* Addded mvlu_find_rt_leaf */ +/* Addded mvlu_set_leaf_param */ +/* 11/29/01 MDE 34 Added GOOSE function pointer */ +/* 11/14/01 EJV 33 Added support for new MMS type UtcTime: */ +/* 11/13/01 MDE 32 Added GOOSE scan support */ +/* 05/21/01 MDE 31 Cleaned up memory allocation for SMEM */ +/* 10/25/00 JRB 30 Del u_mvl & u_gnl funct ptrs. Call directly. */ +/* Del mvlu_install (no longer needed). */ +/* 08/18/00 JRB 29 Don't clear va_to_free. Need value later. */ +/* mvlu_free_nvl free va->va_to_free only if */ +/* it was allocated by mvlu_get_nvl. */ +/* 08/18/00 RKR 28 Added rt fields to MVLU_ typedefs */ +/* 07/13/00 JRB 27 Cleanup ms_comp_na.. chg for MVL_XNAME. */ +/* 07/13/00 JRB 26 Use new ms_comp_name_find to get comp names. */ +/* 07/13/00 JRB 25 Move these functs to mvl_type.c: */ +/* mvlu_add_rt_type, mvlu_free_rt_type. */ +/* 06/21/00 MDE 24 Now copy base VA user_info to new VA */ +/* 05/15/00 MDE 23 Now filder out too-long variable names */ +/* 04/14/00 JRB 22 Lint cleanup. */ +/* 04/05/00 RKR 21 Made MVL_XNAME a compile time option */ +/* 04/03/00 RKR 20 Added the xName to UCA Rd and Wr Ind funs */ +/* 03/30/00 RKR 19 Passed the expanded UCA var name to ind fun */ +/* 01/21/00 MDE 18 Now use MEM_SMEM for dynamic memory */ +/* 12/20/99 MDE 17 Fix getArrAARtType to return SUCCESS/FAIL */ +/* 11/03/99 JRB 16 Fix GetNameList if CA name = base var name. */ +/* 09/30/99 EJV 15 Added slog macro to mvlu_rd_prim_done */ +/* 09/13/99 MDE 14 Added SD_CONST modifiers */ +/* 09/07/99 MDE 13 Revised and enhanced the UCA report system */ +/* 06/04/99 MDE 12 Now allow arrays as base VA type, other */ +/* minor changes to VA processing */ +/* 06/04/99 MDE 11 Fixed memory leak for nested array alt acc */ +/* 04/07/99 MDE 10 Logging improvements (fixed wrong AA log too)*/ +/* 03/09/99 JRB 12 Fix illegal free of gnlNameBuf. */ +/* 02/22/99 JRB 11 BUG FIX: Always start with clean "arrCtrl". */ +/* 01/08/99 JRB 10 Use new "bsearch" object model. Don't use */ +/* "_UCA_" prefix on va and nvl names. */ +/* 12/11/98 MDE 09 Removed scope references from VA */ +/* 11/17/98 MDE 08 Made mvlu_get_va_aa alloc space for name */ +/* 11/16/98 MDE 07 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 06 Uninitialized ptr fix, Minor lint cleanup */ +/* 08/11/98 MDE 05 Added UCA variable array support */ +/* 07/13/98 MDE 04 Mixed scope NVL fixes, data alignment fix */ +/* 06/29/98 MDE 03 Added report function pointers */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 01/02/98 MDE 01 New */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mvl_uca.h" +#include "mvl_log.h" + +#if defined(MVL_UCA) /* This entire module is only valid for UCA. */ + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/* PRIM_INFO struct: extra info about primitive. */ +typedef struct + { + ST_UINT prim_num; /* index to data */ + ST_UINT prim_offset; /* mem offset from start of var */ + ST_UINT prim_offset_base; /* mem offset from start of "base" var */ + } PRIM_INFO; /* extra info about primitive */ + +/************************************************************************/ + +static ST_VOID mvluDefGetVaDataBufFun (ST_INT service, MVL_VAR_ASSOC *va, + ST_INT size); +static ST_VOID mvluDefFreeVaDataBufFun (ST_INT service, MVL_VAR_ASSOC *va); + +/************************************************************************/ +/* Read/Write leaf indication override handlers */ + +ST_VOID (*u_mvlu_leaf_rd_ind_fun)(MVLU_RD_VA_CTRL *mvluRdVaCtrl); +ST_VOID (*u_mvlu_leaf_wr_ind_fun)(MVLU_WR_VA_CTRL *mvluWrVaCtrl); + +/************************************************************************/ +/* STATIC VARIABLES, LOCAL DEFINES */ + +/* GNL Variables */ +static ST_CHAR *gnlNameBuf; +static ST_CHAR *currGnlNamePos; + +/* Index to "u_no_write_allowed" function. It is set to correct value */ +/* at startup by calling "mvlu_find_wr_ind_fun_index" (one time). */ +static ST_RTINT idx_u_no_write_allowed = -2; /* start with illegal val*/ + +#define _OBJ_NAME_CLONE_NAME_SIZE (65) +#define _OBJ_NAME_CLONE_SIZE (sizeof(OBJECT_NAME)+(2 * _OBJ_NAME_CLONE_NAME_SIZE)) + +/************************************************************************/ +/* STATIC FUNCTIONS */ + +ST_RET mvlu_find_component ( + ST_CHAR *flatname, /* flattened name (e.g. ST$Mod$stVal) */ + ALT_ACCESS *alt_acc, + RUNTIME_TYPE **rtIo, + ST_INT *numRtIo, + ST_INT *offset_io, + ST_RTINT *prim_num_io); + +static ST_RET mvlu_find_struct_comp (ST_CHAR *compName, + RUNTIME_TYPE **rtIo, ST_INT *numRtIo, + ST_INT *offset_io, + ST_RTINT *prim_num_io); + +static ST_VOID mvlu_handle_alt_acc (OBJECT_NAME *obj, ALT_ACCESS *alt_acc, + MVL_ARR_CTRL *arrCtrl); +static ST_RET getArrAARtType (MVL_ARR_CTRL *arrCtrl, + RUNTIME_TYPE **pRt, ST_INT *pNumRt); +static ST_VOID cloneArrAA (ALT_ACC_EL *arrAa, ALT_ACCESS *dest); + +static ST_VOID mvlu_find_base_va (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, MVL_NET_INFO *net_info, MVL_VAR_ASSOC **vaOut); + +ST_RET getGnlVarNames (MVL_VAR_ASSOC *va, ST_CHAR *caPtr, + ST_CHAR **dest, ST_INT maxNames, + ST_INT *numNames, ST_BOOLEAN *moreFollowsOut); +static ST_VOID mvlu_clone_objname (OBJECT_NAME *dest, OBJECT_NAME *src); + +static ST_VOID startArrRds (MVL_IND_PEND *indCtrl, MVLAS_READ_CTRL *rdCtrl, + MVLAS_RD_VA_CTRL *rdVaCtrl, RUNTIME_TYPE *rt, PRIM_INFO *prim_info); +static ST_VOID startElReads (MVL_IND_PEND *indCtrl, MVLAS_READ_CTRL *rdCtrl, + MVLAS_RD_VA_CTRL *rdVaCtrl, + RUNTIME_TYPE *rt, ST_INT rt_num, PRIM_INFO *prim_info); +static ST_VOID startArrWrs (MVL_IND_PEND *indCtrl, MVLAS_WRITE_CTRL *wrCtrl, + MVLAS_WR_VA_CTRL *wrVaCtrl, RUNTIME_TYPE *rt, PRIM_INFO *prim_info); +static ST_VOID startElWrites (MVL_IND_PEND *indCtrl, MVLAS_WRITE_CTRL *wrCtrl, + MVLAS_WR_VA_CTRL *wrVaCtrl, + RUNTIME_TYPE *rt, ST_INT rt_num, PRIM_INFO *prim_info); +static ST_INT countPrimEl (MVL_VAR_ASSOC *va, RUNTIME_TYPE *rt, ST_INT rt_num); + +static ST_RET chk_var_writable (RUNTIME_TYPE *rt, ST_INT rt_num); +static ST_RET chk_write_resp_ready (MVL_IND_PEND *indCtrl); +static ST_VOID set_write_resp_dae (MVLAS_WR_VA_CTRL *wrVaCtrl, + ST_INT16 dae); /* DataAccessError code */ + +/************************************************************************/ +/* Global function pointers. May be set by user. */ +/************************************************************************/ +/* This function pointer called BEFORE all write leaf functions. */ +/* NOTE: called only for complex variables (struct or array). */ +ST_RET (*u_mvl_wr_ind_var_start)(MVL_IND_PEND *indCtrl, + MVLAS_WR_VA_CTRL *wrVaCtrl); /* current var in list of var */ + +/* This function pointer called AFTER all write leaf functions. */ +/* NOTE: called only for complex variables (struct or array). */ +ST_RET (*u_mvl_wr_ind_var_end)(MVL_IND_PEND *indCtrl, + MVLAS_WR_VA_CTRL *wrVaCtrl); /* current var in list of var */ + +/************************************************************************/ +/* init_prim_info */ +/* Initialize PRIM_INFO struct using info saved in MVL_VAR_ASSOC. */ +/************************************************************************/ +ST_RET init_prim_info (MVL_VAR_ASSOC *va, PRIM_INFO *prim_info) + { + /* Just use values computed earlier & saved in va. */ + prim_info->prim_num = va->prim_num; + prim_info->prim_offset = 0; + prim_info->prim_offset_base = va->offset_from_base; + return (SD_SUCCESS); + } + + +/************************************************************************/ +/************************************************************************/ +/* MANUFACTURED VARIABLE RESOLUTION FUNCTIONS */ +/************************************************************************/ +/* u_mvl_get_va_aa */ +/************************************************************************/ +/* This function is called from MVL when it is unable to find a */ +/* configured MMS server variable for a READ, WRITE, or GET VARIABLE */ +/* ACCESS ATTRIBUTES indication. */ + +MVL_VAR_ASSOC *u_mvl_get_va_aa (MVL_VMD_CTRL *vmd_ctrl, ST_INT service, OBJECT_NAME *obj, + MVL_NET_INFO *netInfo, + ST_BOOLEAN alt_access_pres, + ALT_ACCESS *alt_acc, + ST_BOOLEAN *alt_access_done_out) + { +ST_CHAR *name; +MVL_VAR_ASSOC *va; +MVL_VAR_ASSOC *baseVa; +ST_RET rc; +OBJECT_NAME *objClone; /*ptr to OBJECT_NAME plus 2 name strings*/ +/* Space for OBJECT_NAME struct plus 2 name strings. */ +/* objClone will point to this, passed to mvlu_clone_objname. */ +/* CRITICAL: Must be a struct so alignment is correct. */ +struct + { + ST_CHAR bytearray[_OBJ_NAME_CLONE_SIZE]; + } objNameBuf; +RUNTIME_TYPE *baseRt; +ST_INT numBaseRt; +RUNTIME_TYPE *ucaRt; +ST_INT numUcaRt; +ST_CHAR *subStart; +ST_INT subTypeId; +MVL_ARR_CTRL arrCtrl; +ST_CHAR *flatname; /* flattened variable name (for mvlu_find_component)*/ +RUNTIME_TYPE *comp_rt; /* set by mvlu_find_component */ +ST_INT comp_num_rt; /* set by mvlu_find_component */ +ST_INT offset_from_base; /* set by mvlu_find_component */ +ST_RTINT prim_num; /* set by mvlu_find_component */ + +/* Make a working copy of the variable name (mvlu_handle_alt_acc may change it) */ + objClone = (OBJECT_NAME *) (&objNameBuf); + mvlu_clone_objname (objClone, obj); + +/* We will handle any alternate access here, by creating the UCA from */ +/* variable name. */ + memset (&arrCtrl, 0, sizeof (MVL_ARR_CTRL)); /* start with clean "arrCtrl"*/ + if (alt_access_pres) + { + mvlu_handle_alt_acc (objClone, alt_acc, &arrCtrl); + *alt_access_done_out = SD_TRUE; + } + +/* We need to find the base type for this variable */ + mvlu_find_base_va (vmd_ctrl, objClone, netInfo, &baseVa); + if (baseVa == NULL) + { + MVL_LOG_NERR1 ("Could not resolve UCA variable '%s'", objClone->obj_name.vmd_spec); + return (NULL); + } + + /* Use mvlu_find_component to compute offset_from_base & prim_num. */ + /* Look for '$' in name. If found, point after it, else use NULL. */ + flatname = strstr (obj->obj_name.vmd_spec, "$"); + if (flatname != NULL) + flatname++; /* point after the '$' */ + /* Start with base variable RUNTIME_TYPE. */ + rc = mvl_get_runtime (baseVa->type_id, &comp_rt, &comp_num_rt); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Could not get RT type for type id %d", baseVa->type_id); + return (NULL); + } + offset_from_base = 0; + prim_num = 0; + /* NOTE: mvlu_find_component changes comp_rt, comp_num_rt, */ + /* offset_from_base, prim_num. */ + /* NOTE: offset_from_base, prim_num different for each array elem.*/ + /* CRITICAL: mvlu_find_component expects alt_acc=NULL if Alt Access */ + /* Spec NOT present. Make sure "alt_acc" is set correctly. */ + if (!alt_access_pres) + alt_acc = NULL; /* CRITICAL */ + rc = mvlu_find_component (flatname, alt_acc, + &comp_rt, &comp_num_rt, &offset_from_base, &prim_num); + if (rc) + return (NULL); /* if this fails, stop now. */ + +/* Now resolve this variable's type given it's name and the base */ +/* type. */ + rc = mvl_get_runtime (baseVa->type_id, &baseRt, &numBaseRt); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Could not get RT type for type id %d", baseVa->type_id); + return (NULL); + } + ucaRt = baseRt; + numUcaRt = numBaseRt; + +/* Check to see if this is for base var... name has no embedded '$' */ +/* If is a derived variable we need to create from the variable name */ +/* 'path' and runtime type. */ + name = objClone->obj_name.vmd_spec; /* We know this is a union ... */ + subStart = strstr (name,"$"); /* Skip the outer (base) name */ + if (subStart) + { + /* This is a derived variable, and we have the base UCA variable */ + /* Using the base runtime table and the variable name, we can get the */ + /* subset type for this variable */ + + ++subStart; + rc = mvlu_find_uca_var (&ucaRt, &numUcaRt, subStart); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Error - could not find subcomponent '%s'", subStart); + return (NULL); + } + } + + +/* If this is an alternate access on an array, we need to copy the */ +/* RT type so we can modify the number of elements and total size */ + if (arrCtrl.arrAltAccPres == SD_TRUE) + { + rc = getArrAARtType (&arrCtrl, &ucaRt, &numUcaRt); + if (rc != SD_SUCCESS) + { + M_FREE (MSMEM_MVLU_AA, arrCtrl.alt_acc.aa); + return (NULL); + } + } + + /* Make sure type computed matches what mvlu_find_component computed. */ + /* DEBUG: delete these before release? */ + assert (comp_num_rt == numUcaRt); + assert (comp_rt->el_tag == ucaRt->el_tag); + assert (comp_rt->mvluTypeInfo.prim_count == ucaRt->mvluTypeInfo.prim_count); + +/* OK, now we have the sub-runtime type, go ahead and create a temp */ +/* RT type and variable association. */ + rc = mvlu_add_rt_type (ucaRt, numUcaRt, &subTypeId); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR0 ("Error - could not add temp RT type"); + return (NULL); + } + +/* Create "derived" variable from baseVa. */ +/* NOTE: This var is NOT added to list so its name is NOT sent */ +/* in GetNameList responses. */ + va = mvl_var_create_derived (objClone->obj_name.vmd_spec, subTypeId, + baseVa, + offset_from_base, + prim_num); + +/* CRITICAL: If use_static_data==SD_FALSE, mvl_var_create_derived could */ +/* not set "va->data". Must call this function to allocate it. */ +/* NOTE: Since this code executes every time a variable is accessed, */ +/* it requires MANY more allocations when use_static_data==SD_FALSE. */ + if (baseVa->use_static_data==SD_FALSE) + mvluDefGetVaDataBufFun (service, va, ucaRt->offset_to_last); + +#if defined(MVLU_USE_REF) + va->ref = ucaRt->mvluTypeInfo.ref; +#endif + +/* Copy the array AA information */ + memcpy (&va->arrCtrl, &arrCtrl, sizeof (MVL_ARR_CTRL)); + va->arrCtrl.curr_index = arrCtrl.low_index; + +/* Good work, we are done here. */ + return (va); + } + +/************************************************************************/ +/* getArrAARtType */ +/************************************************************************/ + +static ST_RET getArrAARtType (MVL_ARR_CTRL *arrCtrl, + RUNTIME_TYPE **pRt, ST_INT *pNumRt) + { +ST_INT numRt; +ST_INT i, j; +RUNTIME_TYPE *rt; +RUNTIME_TYPE *endRt; +RUNTIME_TYPE *newRt; +ALT_ACCESS *alt_acc; +ALT_ACC_EL *alt_acc_el; /* ptr to current entry in alt acc array */ +ST_INT nest_level = 0; + + rt = *pRt; + numRt = *pNumRt; + +/* Check to see if further nesting with this AA selection ... */ + if (arrCtrl->nested == SD_FALSE) + { + /* If just one element, need to lose the outer array */ + if (arrCtrl->num_elmnts == 1) + { + numRt -= 2; + ++rt; + } + } + else /* Further nesting is requested, let's do it! */ + { + /* We only support a single drill down AA */ + if (arrCtrl->num_elmnts > 1) + { + MVL_LOG_NERR0 ("AA resolution problem - multiple elements and nested"); + return (SD_FAILURE); + } + numRt -= 2; + ++rt; + + /* OK, we now need to find the type of the component ... */ + alt_acc = &arrCtrl->alt_acc; + /* Only support AA_COMP and AA_COMP_NEST for now. */ + /* If AA_COMP_NEST is used, this is recursive process. */ + for (j=0; j < alt_acc->num_aa; j++) + { + alt_acc_el = &alt_acc->aa[j]; + if (alt_acc_el->sel_type == AA_COMP || alt_acc_el->sel_type == AA_COMP_NEST) + { + if (alt_acc_el->sel_type == AA_COMP_NEST) + nest_level++; + /* find this component name within the current RUNTIME_TYPE array*/ + for (i = 0; i < numRt; ++i, ++rt) + { + if (!strcmp (alt_acc_el->u.component, ms_comp_name_find (rt))) + break; + } + if (i >= numRt) + { + MVL_LOG_NERR1 ("AA resolution problem - could not find component '%s'", + alt_acc_el->u.component); + return (SD_FAILURE); + } + if (rt->el_tag == RT_STR_START) + numRt = rt->u.str.num_rt_blks+2; + else if (rt->el_tag == RT_ARR_START) + numRt = rt->u.arr.num_rt_blks+2; + else + numRt = 1; + } + else if (alt_acc_el->sel_type == AA_END_NEST) + nest_level--; + else + { + MVL_LOG_NERR0 ("AA resolution problem - complex nested AA on array"); + return (SD_FAILURE); + } + } /* end "for" loop */ + if (nest_level != 0) + { + MVL_LOG_NERR0 ("AA resolution problem - invalid nesting"); + return (SD_FAILURE); + } + } + +/* OK, now copy the runtime type elements into a new one so we can fool */ +/* with it. */ + newRt = (RUNTIME_TYPE *) M_MALLOC (MSMEM_DYN_RT, numRt * sizeof (RUNTIME_TYPE)); + memcpy (newRt, rt, numRt * sizeof (RUNTIME_TYPE)); + +/* Adjust the total size of the type, using scaling */ + if (arrCtrl->num_elmnts > 1) + { + newRt->offset_to_last = rt[1].offset_to_last * arrCtrl->num_elmnts; + +/* Now set the number of elements as desired */ + newRt->u.arr.num_elmnts = arrCtrl->num_elmnts; + endRt = newRt + (newRt->u.arr.num_rt_blks + 1); + endRt->u.arr.num_elmnts = arrCtrl->num_elmnts; + +/* We don't want end of array padding */ + endRt->el_size = 0; + } + + *pRt = newRt; + *pNumRt = numRt; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* mvlu_handle_alt_acc */ +/************************************************************************/ +/* Here we deal with an alternate access. We will simply add the */ +/* sub-name components to the base name to create a fully qualified UCA */ +/* sub-var name */ +/* Of course, this only handles the most simple form of alternate */ +/* access correctly ... */ + +static ST_VOID mvlu_handle_alt_acc (OBJECT_NAME *obj, ALT_ACCESS *alt_acc, + MVL_ARR_CTRL *arrCtrl) + { +ST_INT i; +ST_CHAR *name; +ST_BOOLEAN done; + + name = obj->obj_name.vmd_spec; /* We know this is a union ... */ + arrCtrl->nested = SD_FALSE; + done = SD_FALSE; + for (i = 0; i < alt_acc->num_aa && !done; ++i) + { + switch (alt_acc->aa[i].sel_type) + { + case AA_COMP : + case AA_COMP_NEST : + strcat (name, "$"); + strcat (name, alt_acc->aa[i].u.component); + break; + + case AA_INDEX_NEST : + arrCtrl->nested = SD_TRUE; + cloneArrAA (&alt_acc->aa[i], &arrCtrl->alt_acc); + /* Lets fall through into common code ... */ + case AA_INDEX : + arrCtrl->arrAltAccPres = SD_TRUE; + arrCtrl->low_index = (ST_RTINT) alt_acc->aa[i].u.index; + arrCtrl->num_elmnts = 1; + done = SD_TRUE; + break; + + case AA_INDEX_RANGE_NEST : + arrCtrl->nested = SD_TRUE; + cloneArrAA (&alt_acc->aa[i], &arrCtrl->alt_acc); + /* Lets fall through into common code ... */ + case AA_INDEX_RANGE : + arrCtrl->arrAltAccPres = SD_TRUE; + arrCtrl->low_index = (ST_RTINT) alt_acc->aa[i].u.ir.low_index; + arrCtrl->num_elmnts = (ST_RTINT) alt_acc->aa[i].u.ir.num_elmnts; + done = SD_TRUE; + break; + + case AA_ALL: + case AA_ALL_NEST : + arrCtrl->nested = SD_TRUE; + cloneArrAA (&alt_acc->aa[i], &arrCtrl->alt_acc); + arrCtrl->arrAltAccPres = SD_TRUE; + arrCtrl->low_index = 0; + arrCtrl->num_elmnts = 0; /* 'all' flag */ + done = SD_TRUE; + break; + + case AA_END_NEST : + done = SD_TRUE; + break; + + default: + MVL_LOG_NERR1 ("Error: Invalid alt access sel_type = %d", + alt_acc->aa[i].sel_type); + break; + } + } + } + +/************************************************************************/ +/* cloneArrAA */ +/************************************************************************/ + +static ST_VOID cloneArrAA (ALT_ACC_EL *arrAa, ALT_ACCESS *dest) + { +ST_INT elCount; +ST_INT nestLevel; +ALT_ACC_EL *aaEl; + +/* First let's count how many we need */ + nestLevel = 0; + elCount = 0; + aaEl = arrAa + 1; + while (SD_TRUE) + { + if (nestLevel == 0 && aaEl->sel_type == AA_END_NEST) + break; + + ++elCount; + if (aaEl->sel_type == AA_COMP_NEST || + aaEl->sel_type == AA_INDEX_NEST || + aaEl->sel_type == AA_INDEX_RANGE_NEST || + aaEl->sel_type == AA_ALL_NEST) + { + ++nestLevel; + } + if (aaEl->sel_type == AA_END_NEST) + { + --nestLevel; + } + ++aaEl; + } + +/* OK, now just calloc and copy the nested alternate access */ + if (elCount) + { + dest->num_aa = elCount; + dest->aa = (ALT_ACC_EL *) M_MALLOC (MSMEM_MVLU_AA, elCount * sizeof (ALT_ACC_EL)); + memcpy (dest->aa, arrAa+1, elCount * sizeof (ALT_ACC_EL)); + } + else + { + MVL_LOG_NERR0 ("Nested AA construction problem"); + } + } + +/************************************************************************/ +/* mvlu_find_base_va */ +/************************************************************************/ +/* This function takes a MMS variable name and determines the type ID */ +/* for the base type for the variable. This is done here by */ +/* extracting the name root then looking for a configured variable */ +/* of that name. */ +static ST_VOID mvlu_find_base_va (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, MVL_NET_INFO *net_info, MVL_VAR_ASSOC **vaOut) + { +MVL_VAR_ASSOC *va; +ST_CHAR *p; +ST_CHAR *name; +OBJECT_NAME *objClone; /*ptr to OBJECT_NAME plus 2 name strings*/ +/* Space for OBJECT_NAME struct plus 2 name strings. */ +/* objClone will point to this, passed to mvlu_clone_objname. */ +/* CRITICAL: Must be a struct so alignment is correct. */ +struct + { + ST_CHAR bytearray[_OBJ_NAME_CLONE_SIZE]; + } objNameBuf; + + objClone = (OBJECT_NAME *) (&objNameBuf); + mvlu_clone_objname (objClone, obj); + name = objClone->obj_name.vmd_spec; /* We know this is a union ... */ + +/* See if this variable name has embedded '$', and if so wack it so */ +/* that we have the base name to work with. */ + p = strstr (name,"$"); + if (p) + *p = 0; + + va = mvl_vmd_find_var (vmd_ctrl, objClone, net_info); + if (va && (va->flags & MVL_VAR_FLAG_UCA) == 0) + va = NULL; /* Found va but not UCA variable, so don't return it. */ + *vaOut = va; + } + +/************************************************************************/ +/* mvlu_find_uca_var */ +/************************************************************************/ +/* This function searches a runtime type for the given UCA variable */ +/* name. It does this by breaking the UCA name into its components */ +/* and then finding the name in the current level of the runtime type. */ + +ST_RET mvlu_find_uca_var (RUNTIME_TYPE **rtIo, ST_INT *numRtIo, + ST_CHAR *varName) + { +ST_CHAR nameBuf[MAX_IDENT_LEN+1]; +ST_CHAR *nameToFind; +ST_CHAR *compEnd,*arr; +ST_BOOLEAN nameDone; +ST_RET ret; +ST_INT offset=0; /* mvlu_find_struct_comp needs it but not used */ +ST_RTINT prim_num=0; /* mvlu_find_struct_comp needs it but not used */ + +/* Note that varName does not have the base name prefix */ + strcpy (nameBuf, varName); + nameToFind = nameBuf; + nameDone = SD_FALSE; + while (nameDone == SD_FALSE) + { + /* Isolate the component name for this level, removing subcomp names */ + compEnd = strstr (nameToFind, "$"); + if (compEnd != NULL) + *compEnd = 0; + else /* This is the last nest level */ + nameDone = SD_TRUE; + /*renxiaobao Êý×é*/ + arr = strstr (nameToFind, "["); + if (arr != NULL) + *arr = 0; + + /* Find the component name in the current runtime type nest level */ + ret = mvlu_find_struct_comp (nameToFind, rtIo, numRtIo, &offset, &prim_num); + if (ret == SD_FAILURE) + { + /* Many things can cause this so just use FLOW Logging. */ + MVLU_LOG_FLOW2 ("Could not find name component %s from name %s", + nameToFind, varName); + return (SD_FAILURE); + } + + /* OK, we now have found the component in the runtime type, and our */ + /* runtime pointer and numRt reflect the sub-runtime type. */ + /* next component. */ + + /* Prepare to find the next level component name */ + nameToFind = compEnd+1; + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/* mvlu_find_struct_comp */ +/************************************************************************/ +/* This function searches a structure runtime type for the given */ +/* component name at the outer level. */ +/* NOTE: modifies (*rtIo), (*numRtIo), (*offset_io), (*prim_num_io). */ + +static ST_RET mvlu_find_struct_comp (ST_CHAR *compName, + RUNTIME_TYPE **rtIo, ST_INT *numRtIo, + ST_INT *offset_io, + ST_RTINT *prim_num_io) + { +RUNTIME_TYPE *rt; +RUNTIME_TYPE *endRt; +ST_BOOLEAN foundRt; + + foundRt = SD_FALSE; + rt = *rtIo; + endRt = rt + *numRtIo; + /* renxiaobao Êý×é*/ + if (rt->el_tag == RT_ARR_START) + { + ++rt; + } + if (rt->el_tag != RT_STR_START) + { + MVL_LOG_NERR0 ("Find struct comp: First RT is not structure start"); + return (SD_FAILURE); + } + ++rt; /* Skip the structure start */ + + while (rt < endRt) + { + if (!strcmp (compName, ms_comp_name_find (rt))) + { + *rtIo = rt; + foundRt = SD_TRUE; + } + switch (rt->el_tag) + { + case RT_STR_START : + if (foundRt == SD_TRUE) + { + *numRtIo = rt->u.str.num_rt_blks+2; + return (SD_SUCCESS); + } + /* Not found yet. */ + *offset_io += rt->offset_to_last; /* adjust offset */ + *prim_num_io += rt->mvluTypeInfo.prim_count; /* adjust prim_num*/ + rt += rt->u.str.num_rt_blks+2; /* Skip the structure contents */ + break; + + case RT_ARR_START : + if (foundRt == SD_TRUE) + { + *numRtIo = rt->u.arr.num_rt_blks+2; + return (SD_SUCCESS); + } + /* Not found yet. */ + *offset_io += rt->offset_to_last; /* adjust offset */ + *prim_num_io += rt->mvluTypeInfo.prim_count; /* adjust prim_num*/ + rt += rt->u.arr.num_rt_blks+1; /* Skip the array contents */ + break; + + case RT_STR_END : + case RT_ARR_END : + ++rt; + break; + + default: + if (foundRt == SD_TRUE) + { + *numRtIo = 1; + return (SD_SUCCESS); + } + /* Not found yet. */ + *offset_io += rt->offset_to_last; /* adjust offset */ + *prim_num_io += rt->mvluTypeInfo.prim_count; /* adjust prim_num*/ + ++rt; + break; + } + } + return (SD_FAILURE); + } + +/************************************************************************/ +/* u_mvl_free_va */ +/************************************************************************/ +/* MVL calls this function when it is through with it. We will free */ +/* the data buffer, and then the VA (unless it was a base VA). */ + +ST_VOID u_mvl_free_va (ST_INT service, MVL_VAR_ASSOC *va, + MVL_NET_INFO *netInfo) + { +RUNTIME_TYPE *ucaRt; +ST_INT numUcaRt; +ST_RET rc; + +/* If "va->data" was allocated, free it now. */ + if (va->base_va->use_static_data==SD_FALSE) + mvluDefFreeVaDataBufFun(service, va); + +/* If this was not a 'base' VA, free the derived type */ + if ( (va->flags & MVL_VAR_FLAG_UCA) == 0) + { + + /* See if we allocated the runtime type ... */ + if (va->arrCtrl.arrAltAccPres == SD_TRUE) + { + rc = mvl_get_runtime (va->type_id, &ucaRt, &numUcaRt); + if (rc == SD_SUCCESS) + M_FREE (MSMEM_DYN_RT, ucaRt); + else + { + MVL_LOG_NERR0 ("Error: internal error"); + } + if (va->arrCtrl.nested == SD_TRUE) + M_FREE (MSMEM_MVLU_AA, va->arrCtrl.alt_acc.aa); + } + + mvlu_free_rt_type (va->type_id); + mvl_var_destroy (va); + } + } + +/************************************************************************/ +/************************************************************************/ +/* MANUFACTURED VARIABLE_LIST RESOLUTION FUNCTIONS */ +/************************************************************************/ +/* u_mvl_get_nvl, u_mvl_free_nvl functions deleted (no longer needed). */ +/* They were only needed because Foundry could not find the variables */ +/* for the NVL to set "vl->entries". But new improved Foundry */ +/* generates code like the following (only done once at startup, */ +/* so it is much more efficient): */ +/* + * varObjName.obj_name.vmd_spec = "DI$Name"; + * varObjName.object_tag = DOM_SPEC; + * varObjName.domain_id = mvl_vmd.dom_tbl[6]->name; + * vl->entries [0] = u_mvl_get_va_aa (MMSOP_INFO_RPT, &varObjName, NULL, SD_FALSE, NULL, NULL); + */ + +/************************************************************************/ +/************************************************************************/ +/* GET NAMELIST HELPER FUNCTIONS */ +/* These functions are necessary because MVL does not know about our */ +/* manufactured variables and variable lists. We will fill in part of */ +/* the namelist response data structure. */ +/************************************************************************/ +/************************************************************************/ +/* u_gnl_ind_vars */ +/************************************************************************/ + +ST_INT u_gnl_ind_vars (MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames) + { +ST_INT i; +ST_INT numRespNames; +ST_CHAR caBuf[100]; +ST_CHAR *caPtr; +ST_CHAR *p; +ST_INT numVa; +ST_INT v; +MVL_VAR_ASSOC **va; +MVL_AA_OBJ_CTRL *aa; +MVL_DOM_CTRL *domCtrl; + + + gnlNameBuf = (ST_CHAR *) M_CALLOC (MSMEM_MVLU_GNL, 1, maxNames * (MAX_IDENT_LEN +1)); + +/* Start by finding the VA that we should start with */ +/* Get the variable associations in the selected scope */ + numVa = 0; + if (req_info->objscope == VMD_SPEC) + { + numVa = mvl_vmd.num_var_assoc; + va = mvl_vmd.var_assoc_tbl; + } + else if (req_info->objscope == DOM_SPEC) + { + domCtrl = mvl_vmd_find_dom (&mvl_vmd, req_info->dname); + if (domCtrl) + { + numVa = domCtrl->num_var_assoc; + va = domCtrl->var_assoc_tbl; + } + else + { + MVL_LOG_NERR1 ("GetNameList variables: Domain '%s' not found", req_info->dname); + *moreFollowsOut = SD_FALSE; + return (-1); /* error. This triggers error response */ + } + } + else /* AA_SPEC */ + { + aa = (MVL_AA_OBJ_CTRL *) net_info->aa_objs; + if (aa) + { + numVa = aa->num_var_assoc; + va = aa->var_assoc_tbl; + } + else + { + *moreFollowsOut = SD_FALSE; + return (-1); /* error. This triggers error response */ + } + } + +/* Take care of the 'continue after' business as necessary. Note that */ +/* we will only look at the base name. */ + i = 0; + if (req_info->cont_after_pres) + { + caPtr = req_info->continue_after; + strcpy (caBuf, req_info->continue_after); + p = strstr (caBuf,"$"); + if (p) + *p = 0; + + while (i < numVa) + { + p = va[i]->name; + v = strcmp (caBuf, p); + if (v == 0) /* Exact match */ + break; + + if (v < 0) /* CA is less than real VA name */ + { + if (i > 0) /* Start with the previous VA */ + --i; + break; + } + ++i; /* We have not found our place yet ... */ + } + } + else + caPtr = NULL; + + *moreFollowsOut = SD_FALSE; + + currGnlNamePos = gnlNameBuf; + +/* OK, va[i] is where we start putting together our names */ + for (numRespNames = 0; numRespNames < maxNames && i < numVa; ++i) + { + ST_INT j; + ST_INT numRespNamesStart = numRespNames; /* save count modified by fct*/ + if (getGnlVarNames (va[i], caPtr, &ptr[numRespNames], + maxNames, &numRespNames, moreFollowsOut) != SD_SUCCESS) + return (-1); /* error response will be sent */ + + MVLU_LOG_DEBUG0 ("Names returned from getGnlVarNames"); + for (j = numRespNamesStart; jflags & MVL_VAR_FLAG_UCA) == 0) + { + ++(*numNames); + dest[0] = va->name; + return (SD_SUCCESS); + } + + memset (namePrefix, 0, sizeof(namePrefix)); + strcpy (namePrefix[0], va->name); + +/* First we need to find the starting 'sortedNum', based on the CA name */ + nameCount = *numNames; + startSortedNum = 1; + if (caPtr != NULL) + { + baseIndexOffset = 0; + /* CA name could be base name, or derived name. */ + if (strcmp (caPtr, va->name) == 0) + { /* CA name equals base name. Start with next name AFTER base. */ + startSortedNum = 1; + } + else if ((subStart = strstr (caPtr,"$")) == NULL) /* Skip the base name*/ + { + MVL_LOG_ERR1 ("Problem finding sub-type in '%s'", caPtr); + return (SD_FAILURE); + } + else + { + rc = mvl_get_runtime (va->type_id, &ucaRt, &numUcaRt); + ++subStart; + rc = mvlu_find_uca_var (&ucaRt, &numUcaRt, subStart); + if (rc == SD_SUCCESS) + startSortedNum = ucaRt->mvluTypeInfo.sortedNum + 1; + } + } + else /* No continue after, we need to include the base name */ + { + dest[0] = va->name; + ++nameCount; + baseIndexOffset = 1; + --maxNames; + } + maxRetNames = maxNames - *numNames; + maxSortedNum = startSortedNum + maxRetNames - 1; + +/* OK, now we start doing the real thing. Derive names for this */ +/* type, put them into the dest array. */ +/* We will save those elements with 'sortedNum' between */ +/* 'startSortedNum' and 'maxSortedNum' */ + + compress = SD_FALSE; + rc = mvl_get_runtime (va->type_id, &ucaRt, &numUcaRt); + + /* This code assumes all UCA vars are structs, so first tag must be RT_STR_START*/ + /* DEBUG: change this to "assert"? */ + if (ucaRt->el_tag != RT_STR_START) + MVL_LOG_ERR1 ("IEC/UCA type (type_id=%d) is not a struct. Cannot derive variable names for GetNameList response.", + va->type_id); + + nestLevel = 0; + for (i = 0; i < numUcaRt; ++i, ++ucaRt) + { + sortedNum = ucaRt->mvluTypeInfo.sortedNum; + comp_name = ms_comp_name_find (ucaRt); + if (strlen (comp_name) && + sortedNum >= startSortedNum && sortedNum <= maxSortedNum) + { + /* Chk len is legal BEFORE writing (need room for 2 strings + '$'.*/ + if (strlen (namePrefix[nestLevel]) + strlen (comp_name) + 1 <= MAX_IDENT_LEN) + { + sprintf (nameBuf, "%s$%s", namePrefix[nestLevel], comp_name); + strLen = strlen (nameBuf); + assert (strLen <= MAX_IDENT_LEN); /* if this fails, len chk in "if" is wrong*/ + dest[sortedNum-startSortedNum+baseIndexOffset] = currGnlNamePos; + strcpy (currGnlNamePos, nameBuf); + currGnlNamePos += strLen +1; + ++nameCount; + } + else + { + /* NOTE: should never happen if len checked in _mvlu_save_rt_uca_name at startup.*/ + MVL_LOG_ERR2 ("GetNameList error: Derived variable name '%s$%s' too long", + namePrefix[nestLevel], comp_name); + compress = SD_TRUE; + } + } + + if (ucaRt->el_tag == RT_STR_START) + { + comp_name = ms_comp_name_find (ucaRt); + if (strlen (comp_name)) + { + /* Chk len is legal BEFORE writing (need room for 2 strings + '$').*/ + if (strlen (namePrefix[nestLevel]) + strlen (comp_name) + 1 <= MAX_IDENT_LEN) + { + ++nestLevel; + assert (nestLevel < MAX_NEST_LEVEL); + assert (nestLevel > 0); + strcpy (namePrefix[nestLevel], namePrefix[nestLevel-1]); + strcat (namePrefix[nestLevel], "$"); + strcat (namePrefix[nestLevel], comp_name); + } + else + { + /* NOTE: should never happen if len checked in _mvlu_save_rt_uca_name at startup.*/ + MVL_LOG_ERR2 ("GetNameList error: Flattened variable name too long for struct '%s$%s'", + namePrefix[nestLevel], comp_name); + MVL_LOG_CERR0 ("Flattened name of struct and all lower components cannot be returned"); + compress=SD_TRUE; + /* Skip to end of struct */ + i += (ucaRt->u.str.num_rt_blks + 1); + ucaRt += (ucaRt->u.str.num_rt_blks + 1); + } + } + } + else if (ucaRt->el_tag == RT_STR_END) + --nestLevel; + else if (ucaRt->el_tag == RT_ARR_START) + { /* Skip the array elements */ + /* There is no way to create UCA names for objects inside an */ + /* array, so skip over the array. */ + i += (ucaRt->u.arr.num_rt_blks + 1); + ucaRt += (ucaRt->u.arr.num_rt_blks + 1); + } + + if (sortedNum > maxSortedNum) + *moreFollowsOut = SD_TRUE; + + } + + /* DEBUG: at this point loop, 'nestLevel' should equal (-1). This may */ + /* sound strange, but nestLevel NOT incremented on first RT_STR_START,*/ + /* so last RT_STR_END makes it -1. Add assert here? */ + + /* If we had to skip one or more names, we need to eliminate the */ + /* holes in the name pointer table. */ + if (compress == SD_TRUE) + { + get = 0; + put = 0; + numNewNames = nameCount - *numNames; + while (put < numNewNames) + { + if (dest[get] != NULL) + dest[put++] = dest[get]; + ++get; + } + } + + *numNames = nameCount; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* u_gnl_done */ +/************************************************************************/ +/* This function is called after MVL has send the MMS response to a */ +/* GET_NAME_LIST indication. We will clean up memory resources. */ + +ST_VOID u_gnl_done (ST_INT16 mms_class, + NAMELIST_RESP_INFO *resp_info) + { + if (mms_class == MMS_CLASS_VAR) + M_FREE (MSMEM_MVLU_GNL, gnlNameBuf); + } + +/************************************************************************/ +/************************************************************************/ +/* u_gnl_ind_nvls */ +/************************************************************************/ + +ST_INT u_gnl_ind_nvls (MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames) + { +ST_INT v; +ST_INT i; +ST_INT num_obj; +MVL_AA_OBJ_CTRL *aa; +MVL_NVLIST_CTRL **vl; +MVL_DOM_CTRL *domCtrl; +ST_INT startIndex; +ST_INT numObjLeft; +ST_INT numRetNames; +ST_CHAR *name; + +/* First get the number of objects and pointer to the object table */ + num_obj = 0; + if (req_info->objscope == VMD_SPEC) + { + num_obj = mvl_vmd.num_nvlist; + vl = mvl_vmd.nvlist_tbl; + } + else if (req_info->objscope == DOM_SPEC) + { + domCtrl = mvl_vmd_find_dom (&mvl_vmd, req_info->dname); + if (domCtrl) + { + num_obj = domCtrl->num_nvlist; + vl = domCtrl->nvlist_tbl; + } + else + { + MVL_LOG_NERR1 ("GetNameList NVL: Domain '%s' not found", req_info->dname); + *moreFollowsOut = SD_FALSE; + return (-1); /* error. This triggers error response */ + } + } + else /* AA_SPEC */ + { + aa = (MVL_AA_OBJ_CTRL *) net_info->aa_objs; + if (aa) + { + num_obj = aa->num_nvlist; + vl = aa->nvlist_tbl; + } + else + { + *moreFollowsOut = SD_FALSE; + return (-1); /* error. This triggers error response */ + } + } + + if (num_obj) + { + /* Take care of the 'continue after' business if necessary */ + startIndex = 0; + if (req_info->cont_after_pres) + { + while (startIndex < num_obj) + { + name = vl[startIndex]->name; + v = strcmp (req_info->continue_after, name); + if (v == 0) + { + ++startIndex; /* Index to the next one */ + break; + } + if (v < 0) + break; + + ++startIndex; /* We have not found our place yet ... */ + } + } + + numObjLeft = num_obj-startIndex; + numRetNames = min(numObjLeft, maxNames); + if (numRetNames < numObjLeft) + *moreFollowsOut = SD_TRUE; + + /* Now make the list for the response */ + for (i = 0; i < numRetNames; ++i, ++ptr) + *ptr = vl[startIndex+i]->name; + + return (numRetNames); + } + return (0); + } + +/************************************************************************/ +/************************************************************************/ +/* mvlu_clone_objname */ +/************************************************************************/ +/* This function 'clones' a MMS OBJECT_NAME structure, which means that */ +/* it must allocate the various storage elements as required. Note */ +/* that the name storage allocation is 65, to give calling routines */ +/* room to work. */ + +static ST_VOID mvlu_clone_objname (OBJECT_NAME *dest, OBJECT_NAME *src) + { + memset (dest, 0, _OBJ_NAME_CLONE_SIZE); + dest->object_tag = src->object_tag; + dest->obj_name.vmd_spec = (ST_CHAR *) (dest + 1); + strcpy (dest->obj_name.vmd_spec, src->obj_name.vmd_spec); + if (src->object_tag == DOM_SPEC) + { + dest->domain_id = dest->obj_name.vmd_spec + _OBJ_NAME_CLONE_NAME_SIZE; + strcpy (dest->domain_id, src->domain_id); + } + } + +/************************************************************************/ +/************************************************************************/ +/* MVLU READ/WRITE HANDLERS */ +/************************************************************************/ + +static ST_VOID mvluDefAsyncWrIndFun (struct mvlu_wr_va_ctrl *mvluWrVaCtrl); +static ST_VOID mvluDefAsyncRdIndFun (struct mvlu_rd_va_ctrl *mvluRdVaCtrl); + +/* Function pointers for non-UCA variable handling */ +ST_VOID(*mvluAsyncRdIndFun)(struct mvlu_rd_va_ctrl *mvluRdVaCtrl) = + mvluDefAsyncRdIndFun; +ST_VOID(*mvluAsyncWrIndFun)(struct mvlu_wr_va_ctrl *mvluWrVaCtrl) = + mvluDefAsyncWrIndFun; + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* mvl_read_ind */ +/************************************************************************/ + +ST_VOID u_mvl_read_ind (MVL_IND_PEND *indCtrl) + { +MVLAS_READ_CTRL *rdCtrl; +MVLAS_RD_VA_CTRL *rdVaCtrl; +MVL_VAR_ASSOC *va; +MVLU_RD_VA_CTRL *mvluRdVaCtrl; +ST_INT i; +ST_INT numVar; +RUNTIME_TYPE *rt; +ST_INT numRt; +PRIM_INFO prim_info; + + rdCtrl = &indCtrl->u.rd; + numVar = rdCtrl->numVar; + +/* First we will go through each variable being read and count the */ +/* primitive elelemts. */ + + rdVaCtrl = rdCtrl->vaCtrlTbl; + for (i = 0; i < numVar; ++i, ++rdVaCtrl) + { + va = rdVaCtrl->va; + if (va) /* VA was resolved, we can deal with it */ + { + mvl_get_runtime (va->type_id, &rt, &numRt); + rdVaCtrl->acc_rslt_tag = ACC_RSLT_SUCCESS; + rdVaCtrl->numPrimDataDone = 0; + if (va->base_va != NULL) /* UCA variable handling ... */ + { + rdVaCtrl->numPrimData = countPrimEl (va, rt, numRt); + } + else + rdVaCtrl->numPrimData = 1; + } + else + rdVaCtrl->numPrimData = 1; + } + +/* Now we will go through each var being read and invoke the rdInd */ +/* function for it. */ + + rdVaCtrl = rdCtrl->vaCtrlTbl; + for (i = 0; i < numVar; ++i, ++rdVaCtrl) + { + va = rdVaCtrl->va; + if (va) /* VA was resolved, we can deal with it */ + { + + /* The VA's data pointer is valid, as is the type ID. */ + /* We want to call the handlers for all primitive level functions */ + /* for this data type */ + + if (va->base_va != NULL) /* UCA variable handling ... */ + { + mvl_get_runtime (va->type_id, &rt, &numRt); + + /* Initialize prim_info struct. */ + if (init_prim_info (va, &prim_info)) + { /* Failed. Can't process this var. Skip to next var in list*/ + MVL_LOG_ERR1 ("init_prim_info failed for 'Read' of variable '%s'", va->name); + rdVaCtrl->acc_rslt_tag = ACC_RSLT_FAILURE; + continue; /* skip to next variable */ + } + + startElReads (indCtrl, rdCtrl, rdVaCtrl, rt, numRt, &prim_info); + } + else /* Non-UCA variable handling ... */ + { + mvluRdVaCtrl = (MVLU_RD_VA_CTRL *) M_CALLOC (MSMEM_MVLU_VA_CTRL, 1, + sizeof (MVLU_RD_VA_CTRL)); + mvluRdVaCtrl->primData = (ST_CHAR *) va->data; + mvluRdVaCtrl->indCtrl = indCtrl; + mvluRdVaCtrl->rdVaCtrl = rdVaCtrl; + (*mvluAsyncRdIndFun)(mvluRdVaCtrl); + } + } + else /* VA not found, let it be done */ + { + mvluRdVaCtrl = (MVLU_RD_VA_CTRL *) M_CALLOC (MSMEM_MVLU_VA_CTRL, 1, + sizeof (MVLU_RD_VA_CTRL)); + mvluRdVaCtrl->indCtrl = indCtrl; + mvluRdVaCtrl->rdVaCtrl = rdVaCtrl; + mvlu_rd_prim_done (mvluRdVaCtrl, SD_SUCCESS); + } + } + } + +/************************************************************************/ +/* mvlu_trim_branch_name */ +/* Find last '$' in name and replace it with NULL. */ +/************************************************************************/ + +ST_VOID mvlu_trim_branch_name (ST_CHAR *branch_name) + { +ST_CHAR *ptr; + if ((ptr = strrchr (branch_name, '$')) != NULL) /* find last '$'*/ + *ptr = 0; /* replace '$' with NULL */ + return; + } + +/************************************************************************/ +/* startElReads */ +/************************************************************************/ + +static ST_VOID startElReads (MVL_IND_PEND *indCtrl, MVLAS_READ_CTRL *rdCtrl, + MVLAS_RD_VA_CTRL *rdVaCtrl, + RUNTIME_TYPE *rt, ST_INT rt_num, PRIM_INFO *prim_info) + { +ST_INT i; +MVLU_RD_VA_CTRL *mvluRdVaCtrl; +ST_RTINT rdIndFunIndex; +ST_UCHAR el_tag; +ST_INT el_size; +ST_RTINT num_rt_blks; +#if defined(MVL_XNAME) +ST_CHAR element_name[MAX_IDENT_LEN+1]; +ST_CHAR branch_name[MAX_IDENT_LEN+1]; +MVL_VAR_ASSOC *va; +ST_CHAR *comp_name; +#endif + +#if defined(MVL_XNAME) + va = rdVaCtrl->va; + element_name[0]=0; + strcpy (branch_name,va->name); + +/* if this is a substructure we need to trim back one level of the name */ +/* because the first rt element will be the name of the component */ +/* already part of the va->name */ + + if ((rt_num > 1) && (strstr (branch_name,"$"))) + { + mvlu_trim_branch_name (branch_name); + } +#endif + + for (i = 0; i < rt_num; ++i, ++rt) + { + +#if defined(MVL_XNAME) + if (rt_num > 1) + { + comp_name = ms_comp_name_find (rt); + if (strlen (comp_name)) + { + if ((rt->el_tag == RT_STR_START)) + { + strcat (branch_name, "$"); + strcat (branch_name, comp_name); + strcpy (element_name, branch_name); + } + else + { + element_name[0]=0; + strcat (element_name, branch_name); + strcat (element_name, "$"); + strcat (element_name, comp_name); + } + } + + if (rt->el_tag == RT_STR_END) + { + strcpy (element_name, branch_name); + mvlu_trim_branch_name (branch_name); + } + } + else + { /* only one element in the RT table assume it's a primitive */ + strcpy (element_name, branch_name); + } +#endif + + el_tag = rt->el_tag; + num_rt_blks = rt->u.arr.num_rt_blks; + el_size = rt->el_size; + + if (ms_is_rt_prim (rt) == SD_TRUE) + { + rdIndFunIndex = rt->mvluTypeInfo.rdIndFunIndex; + if (u_mvlu_leaf_rd_ind_fun != NULL || + //(rdIndFunIndex >= 0 && rdIndFunIndex < mvluNumRdFunEntries))//lnk±àÒëÐ޸ģ¬Ô­Ç°ÖóÌÐòδʹÓà + 0)//lnk±àÒëÐ޸ģ¬Ô­Ç°ÖóÌÐòδʹÓà + { + mvluRdVaCtrl = (MVLU_RD_VA_CTRL *) M_CALLOC (MSMEM_MVLU_VA_CTRL, 1, + sizeof (MVLU_RD_VA_CTRL)); + mvluRdVaCtrl->rt = rt; +#if defined(MVL_XNAME) + strcpy (mvluRdVaCtrl->xName, element_name); +#endif + mvluRdVaCtrl->primData = (ST_CHAR *) rdVaCtrl->va->data + + prim_info->prim_offset; + mvluRdVaCtrl->indCtrl = indCtrl; + mvluRdVaCtrl->rdVaCtrl = rdVaCtrl; +#if defined(MVLU_USE_REF) + mvluRdVaCtrl->primRef = rt->mvluTypeInfo.ref; +#endif + mvluRdVaCtrl->prim_num = prim_info->prim_num; + mvluRdVaCtrl->prim_offset_base = prim_info->prim_offset_base; + if (u_mvlu_leaf_rd_ind_fun == NULL) + {}//(*mvluRdFunInfoTbl[rdIndFunIndex].fun_ptr)(mvluRdVaCtrl);//lnk±àÒëɾ³ý£¬Ô­Ç°ÖóÌÐòδʹÓà + else + (*u_mvlu_leaf_rd_ind_fun)(mvluRdVaCtrl); + } + else + rdVaCtrl->acc_rslt_tag = ACC_RSLT_FAILURE; + prim_info->prim_num++; + } + + if (el_tag == RT_ARR_START) + { + startArrRds (indCtrl, rdCtrl, rdVaCtrl, rt, prim_info); + i += (num_rt_blks + 1); + rt += (num_rt_blks + 1); + } + else + { + prim_info->prim_offset += el_size; + prim_info->prim_offset_base += el_size; + } + } + } + +/************************************************************************/ +/* startArrRds */ +/************************************************************************/ + +static ST_VOID startArrRds (MVL_IND_PEND *indCtrl, MVLAS_READ_CTRL *rdCtrl, + MVLAS_RD_VA_CTRL *rdVaCtrl, RUNTIME_TYPE *rt, PRIM_INFO *prim_info) + { +ST_RTINT i; +MVL_VAR_ASSOC *va; +ST_INT numRt; +/* DEBUG: To allow bigger arrays, must chg type of these two vars */ +/* & va->arrCtrl.low_index & va->arrCtrl.curr_index. */ +ST_RTINT low_index; +ST_RTINT num_elmnts; + + numRt = rt->u.arr.num_rt_blks+2; + va = rdVaCtrl->va; + + if (va->arrCtrl.arrAltAccPres == SD_TRUE) + { + low_index = va->arrCtrl.low_index; + num_elmnts = va->arrCtrl.num_elmnts; + } + else + { + low_index = 0; + num_elmnts = (ST_RTINT) rt->u.arr.num_elmnts; + } + +/* Let's check to see if the client is selecting a sub-object ... */ + prim_info->prim_offset += rt->el_size; + prim_info->prim_offset_base += rt->el_size; + for (i = 0; i < num_elmnts; ++i) + { + va->arrCtrl.curr_index = low_index + i; + startElReads (indCtrl, rdCtrl, rdVaCtrl, rt+1, numRt-2, prim_info); + } + prim_info->prim_offset += (rt+numRt-1)->el_size; + prim_info->prim_offset_base += (rt+numRt-1)->el_size; + } + +/************************************************************************/ +/* mvlu_rd_prim_done */ +/************************************************************************/ +/* The user calls this function acynchronously when the primitive data */ +/* has been put in the 'primData' buffer. */ + +ST_VOID mvlu_rd_prim_done (MVLU_RD_VA_CTRL *mvluRdVaCtrl, ST_RET rc) + { +MVL_IND_PEND *indCtrl; +MVLAS_READ_CTRL *rdCtrl; +MVLAS_RD_VA_CTRL *rdVaCtrl; +ST_INT i; + + rdVaCtrl = mvluRdVaCtrl->rdVaCtrl; + + if (rc != SD_SUCCESS) + { +/* DEBUG LIZ: added logging why read failed */ + MVL_LOG_NERR2 ("Read failed for UCA variable '%s' rc=%d", + rdVaCtrl->va->name, rc); + rdVaCtrl->acc_rslt_tag = ACC_RSLT_FAILURE; + } + + ++rdVaCtrl->numPrimDataDone; + if (rdVaCtrl->numPrimDataDone == rdVaCtrl->numPrimData) + { + /* All primitives for "one" variable are complete. */ + indCtrl = mvluRdVaCtrl->indCtrl; + + if (indCtrl->scan_va_done_fun) + (*indCtrl->scan_va_done_fun)(indCtrl, rdVaCtrl->va); + + /* If all primitives for all variables are complete, respond now */ + rdCtrl = &indCtrl->u.rd; + rdVaCtrl = rdCtrl->vaCtrlTbl; + for (i = 0; i < rdCtrl->numVar; ++i, ++rdVaCtrl) + { + if (rdVaCtrl->numPrimDataDone != rdVaCtrl->numPrimData) + break; + } + if (i == rdCtrl->numVar) + { + if (indCtrl->op != MMSOP_READ) + { /* Not normal read. Do special processing. */ + if (indCtrl->usr_resp_fun) + { /* If user set custom resp fun, call it. */ + (*indCtrl->usr_resp_fun) (indCtrl); + } + } + else + mvlas_read_resp (indCtrl); + } + } + M_FREE (MSMEM_MVLU_VA_CTRL, mvluRdVaCtrl); + } + +/************************************************************************/ +/* mvluDefAsyncRdIndFun */ +/************************************************************************/ + +static ST_VOID mvluDefAsyncRdIndFun (struct mvlu_rd_va_ctrl *mvluRdVaCtrl) + { + mvlu_rd_prim_done (mvluRdVaCtrl, SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* u_mvl_write_ind */ +/* NOTE: "indCtrl" is freed when "mvlas_write_resp" is called to send */ +/* response. To assure "indCtrl" is valid until the end of this function,*/ +/* the "ind_funct_done" flag is used to indicate if this function */ +/* is done. It is accessible in all lower level functions. */ +/* At end of this function, if response ready, "mvlas_write_resp" is */ +/* called & indCtrl is freed (all done). If response NOT ready, this */ +/* flag is set to (SD_TRUE), then "mvlu_wr_prim_done" will call */ +/* "mvlas_write_resp" later when response is ready. */ +/************************************************************************/ + +ST_VOID u_mvl_write_ind (MVL_IND_PEND *indCtrl) + { +MVLAS_WRITE_CTRL *wrCtrl; +MVLAS_WR_VA_CTRL *wrVaCtrl; +MVL_VAR_ASSOC *va; +MVLU_WR_VA_CTRL *mvluWrVaCtrl; +ST_INT i; +ST_INT numVar; +RUNTIME_TYPE *rt; +ST_INT numRt; +PRIM_INFO prim_info; + + /* NOTE: (indCtrl->u.wr.ind_funct_done==SD_FALSE) because indCtrl calloced.*/ + /* Changed to SD_TRUE only when this function completes. */ + /* Checked in "mvlu_wr_prim_done" funct. */ + + wrCtrl = &indCtrl->u.wr; + numVar = wrCtrl->numVar; + +/* First we will go through each variable being written and count the */ +/* primitive elelemts. */ + wrVaCtrl = wrCtrl->vaCtrlTbl; + + for (i = 0; i < numVar; ++i, ++wrVaCtrl) + { + va = wrVaCtrl->va; + if (va) /* VA was resolved, we can look it over */ + { + mvl_get_runtime (va->type_id, &rt, &numRt); + wrVaCtrl->resp_tag = WR_RSLT_SUCCESS; + wrVaCtrl->numPrimDataDone = 0; + if (va->base_va != NULL) /* UCA variable handling ... */ + wrVaCtrl->numPrimData = countPrimEl (va, rt, numRt); + else + wrVaCtrl->numPrimData = 1; + } + else + wrVaCtrl->numPrimData = 1; + } + +/* Now we will go through each var being written and invoke the wrInd */ +/* function for it. */ + + wrVaCtrl = wrCtrl->vaCtrlTbl; + for (i = 0; i < numVar; ++i, ++wrVaCtrl) + { + va = wrVaCtrl->va; + if (va) /* VA was resolved, we can look it over */ + { + /* The VA's data pointer is valid, as is the type ID. */ + /* We want to call the handlers for all primitive level functions */ + /* for this data type */ + if (va->base_va != NULL) /* UCA variable handling ... */ + { + mvl_get_runtime (va->type_id, &rt, &numRt); + + if (chk_var_writable (rt, numRt)) + { /* This var NOT writable. Set error & skip to next var. */ + set_write_resp_dae (wrVaCtrl, ARE_OBJ_ACCESS_DENIED); + continue; /* skip to next variable */ + } + + /* Initialize prim_info struct. */ + if (init_prim_info (va, &prim_info)) + { /* Failed. Can't process this var. Skip to next var in list*/ + MVL_LOG_ERR1 ("init_prim_info failed for 'Write' of variable '%s'", va->name); + set_write_resp_dae (wrVaCtrl, ARE_OBJ_ACCESS_DENIED); + continue; /* skip to next variable */ + } + + /* If this is struct (or array), user function pointer !=NULL, */ + /* and function returns error, do not allow write. */ + if (numRt > 1 /* must be struct or array */ + && u_mvl_wr_ind_var_start != NULL + && (*u_mvl_wr_ind_var_start)(indCtrl, wrVaCtrl) != SD_SUCCESS) + { /* This var NOT writable. Set error & skip to next var. */ + set_write_resp_dae (wrVaCtrl, ARE_OBJ_ACCESS_DENIED); + continue; /* skip to next variable */ + } + + startElWrites (indCtrl, wrCtrl,wrVaCtrl, rt, numRt, &prim_info); + + /* If this is struct (or array), user function pointer !=NULL, */ + /* and function returns error, do not allow write. */ + /* CAUTION: If error is detected here, must make sure that leaf */ + /* functions did NOT write any data. */ + if (numRt > 1 /* must be struct or array */ + && u_mvl_wr_ind_var_end != NULL + && (*u_mvl_wr_ind_var_end)(indCtrl, wrVaCtrl) != SD_SUCCESS) + { /* This var NOT writable. Set error & skip to next var. */ + set_write_resp_dae (wrVaCtrl, ARE_OBJ_ACCESS_DENIED); + continue; /* skip to next variable */ + } + } + else /* Non-UCA variable handling ... */ + { + mvluWrVaCtrl = (MVLU_WR_VA_CTRL *) M_CALLOC (MSMEM_MVLU_VA_CTRL, 1, + sizeof (MVLU_WR_VA_CTRL)); + mvluWrVaCtrl->primData = (ST_CHAR *) va->data; + mvluWrVaCtrl->indCtrl = indCtrl; + mvluWrVaCtrl->wrVaCtrl = wrVaCtrl; + (*mvluAsyncWrIndFun)(mvluWrVaCtrl); + } + } + else + { + mvluWrVaCtrl = (MVLU_WR_VA_CTRL *) M_CALLOC (MSMEM_MVLU_VA_CTRL, 1, + sizeof (MVLU_WR_VA_CTRL)); + mvluWrVaCtrl->indCtrl = indCtrl; + mvluWrVaCtrl->wrVaCtrl = wrVaCtrl; + mvlu_wr_prim_done (mvluWrVaCtrl, SD_SUCCESS); + } + } + /* If response is ready (i.e. all synchronous leafs), send it now. */ + /* If not, just set flag (SD_TRUE) & mvlu_wr_prim_done will send resp.*/ + if (chk_write_resp_ready (indCtrl) == SD_SUCCESS) + mvlas_write_resp (indCtrl); /* sends resp & frees indCtrl */ + else + indCtrl->u.wr.ind_funct_done = SD_TRUE; /* this funct is done */ + } + +/************************************************************************/ +/* startElWrites */ +/* NOTE: Resp NOT sent while in this function (see ind_funct_done flag).*/ +/* Therefore, indCtrl is valid throughout this function */ +/* (i.e. it is NOT freed). */ +/************************************************************************/ + +static ST_VOID startElWrites (MVL_IND_PEND *indCtrl, MVLAS_WRITE_CTRL *wrCtrl, + MVLAS_WR_VA_CTRL *wrVaCtrl, + RUNTIME_TYPE *rt, ST_INT rt_num, PRIM_INFO *prim_info) + { +ST_INT i; +MVLU_WR_VA_CTRL *mvluWrVaCtrl; +ST_RTINT wrIndFunIndex; +ST_UCHAR el_tag; +ST_INT el_size; +ST_RTINT num_rt_blks; +#if defined(MVL_XNAME) +ST_CHAR element_name[MAX_IDENT_LEN+1]; +ST_CHAR branch_name[MAX_IDENT_LEN+1]; +MVL_VAR_ASSOC *va; +ST_CHAR *comp_name; +#endif +ST_CHAR sboName[MVL61850_MAX_OBJREF_LEN+1]; +RUNTIME_TYPE *rt_first; /* to save ptr to first before incrementing */ + +#if !defined(MVL61850_CTL_DISABLE) + ST_INT oper_nest_level = 0; +#endif + +#if defined(MVL_XNAME) + va = wrVaCtrl->va; + element_name[0]=0; + strcpy (branch_name,va->name); + +/* if this is a substructure we need to trim back one level of the name */ +/* because the first rt element will be the name of the component */ +/* already part of the va->name */ + + if ((rt_num > 1) && (strstr (branch_name, "$"))) + { + mvlu_trim_branch_name (branch_name); + } +#endif + + rt_first = rt; /* save first for comparison */ + for (i = 0; i < rt_num; ++i, ++rt) + { +#if defined(MVL_XNAME) + if (rt_num > 1) /* is this a collection of elements? */ + { + comp_name = ms_comp_name_find (rt); + if (strlen (comp_name)) + { + if ((rt->el_tag == RT_STR_START)) + { + strcat (branch_name, "$"); + strcat (branch_name, comp_name); + strcpy (element_name, branch_name); + } + else + { + element_name[0]=0; + strcat (element_name, branch_name); + strcat (element_name, "$"); + strcat (element_name, comp_name); + } + } + + if (rt->el_tag == RT_STR_END) + { + strcpy (element_name, branch_name); + mvlu_trim_branch_name (branch_name); + } + } + else + { /* only one element in the RT table assume it's a primitive */ + strcpy (element_name, branch_name); + } +#endif + + el_tag = rt->el_tag; + num_rt_blks = rt->u.arr.num_rt_blks; + el_size = rt->el_size; + + /* Do some special stuff for IEC 61850 SBO controls. */ + /* If this comp is start of struct & comp name is "Oper" or "Cancel",*/ + /* check SBO state. */ + /* NOTE: must be writing "Oper" or "Cancel" struct and ONLY the struct.*/ + if (rt == rt_first && /* this is first element */ + rt->el_tag == RT_STR_START && /* it is a struct */ + (strcmp (ms_comp_name_find(rt), "Oper") == 0 || strcmp (ms_comp_name_find(rt), "Cancel") == 0)) + { + /* Check "Select" timeouts for ALL SBO controls. */ + //mvlu_sbo_chk_timers ();//lnk±àÒëɾ³ý£¬²»Ó°Ïì¿Í»§¶Ë + /* Chk SBO state. Save in wrVaCtrl->sboCtrl (NULL if "Select" not done).*/ + //mvl61850_sbo_create_sboname (wrVaCtrl->va, &wrVaCtrl->va_scope, sboName);//lnk±àÒëɾ³ý£¬²»Ó°Ïì¿Í»§¶Ë + //wrVaCtrl->sboCtrl = mvlu_sbo_chk_state (sboName, indCtrl->event->net_info);//lnk±àÒëÐ޸쬲»Ó°Ïì¿Í»§¶Ë + wrVaCtrl->sboCtrl = NULL;//lnk±àÒëÐ޸쬲»Ó°Ïì¿Í»§¶Ë + } + +#if !defined(MVL61850_CTL_DISABLE) + if (rt->el_tag == RT_STR_START) + { + /* only increment this if this is "Oper" or already inside "Oper". */ + if (oper_nest_level>0) + oper_nest_level++; + else if (strcmp (ms_comp_name_find(rt), "Oper") == 0) + { + if (wrVaCtrl->sboCtrl) + wrVaCtrl->sboCtrl->ctlState = MVL61850_CTLSTATE_READY; + //u_mvl61850_ctl_oper_begin (sboName);//lnk±àÒëɾ³ý£¬²»Ó°Ïì¿Í»§¶Ë + oper_nest_level++; + } + } + if (rt->el_tag == RT_STR_END) + { + if (oper_nest_level>0) + { + if (--oper_nest_level==0) + { + /* All leaf functs have been called for "Oper" struct.*/ + /*renxiaobao ¿ØÖÆ*/ + /*u_mvl61850_ctl_oper_end (indCtrl->event->net_info, sboName, wrVaCtrl->va->base_va);*/ + } + } + } +#endif /* !defined(MVL61850_CTL_DISABLE) */ + + if (ms_is_rt_prim (rt) == SD_TRUE) + { + wrIndFunIndex = rt->mvluTypeInfo.wrIndFunIndex; + if (u_mvlu_leaf_wr_ind_fun != NULL || + //(wrIndFunIndex >= 0 && wrIndFunIndex < mvluNumWrFunEntries))//lnk±àÒëÐ޸ģ¬Ô­Ç°ÖóÌÐòδʹÓà + 0) + { + mvluWrVaCtrl = (MVLU_WR_VA_CTRL *) M_CALLOC (MSMEM_MVLU_VA_CTRL, 1, + sizeof (MVLU_WR_VA_CTRL)); +#if defined(MVL_XNAME) + strcpy (mvluWrVaCtrl->xName, element_name); +#endif + mvluWrVaCtrl->primData = (ST_CHAR *) wrVaCtrl->va->data + + prim_info->prim_offset; + mvluWrVaCtrl->indCtrl = indCtrl; + mvluWrVaCtrl->wrVaCtrl = wrVaCtrl; + mvluWrVaCtrl->rt = rt; +#if defined(MVLU_USE_REF) + mvluWrVaCtrl->primRef = rt->mvluTypeInfo.ref; +#endif + mvluWrVaCtrl->prim_num = prim_info->prim_num; + mvluWrVaCtrl->prim_offset_base = prim_info->prim_offset_base; + if (u_mvlu_leaf_wr_ind_fun == NULL) + {}//(*mvluWrFunInfoTbl[wrIndFunIndex].fun_ptr)(mvluWrVaCtrl);//lnk±àÒëɾ³ý£¬Ô­Ç°ÖóÌÐòδʹÓà + else + (*u_mvlu_leaf_wr_ind_fun)(mvluWrVaCtrl); + } + else + wrVaCtrl->resp_tag = WR_RSLT_FAILURE; + prim_info->prim_num++; + } + + if (el_tag == RT_ARR_START) + { + startArrWrs (indCtrl, wrCtrl, wrVaCtrl, rt, prim_info); + i += (num_rt_blks + 1); + rt += (num_rt_blks + 1); + } + else + { + prim_info->prim_offset += el_size; + prim_info->prim_offset_base += el_size; + } + } + } + +/************************************************************************/ +/* startArrWrs */ +/************************************************************************/ + +static ST_VOID startArrWrs (MVL_IND_PEND *indCtrl, MVLAS_WRITE_CTRL *wrCtrl, + MVLAS_WR_VA_CTRL *wrVaCtrl, RUNTIME_TYPE *rt, PRIM_INFO *prim_info) + { +ST_RTINT i; +MVL_VAR_ASSOC *va; +ST_INT numRt; +/* DEBUG: To allow bigger arrays, must chg type of these two vars */ +/* & va->arrCtrl.low_index & va->arrCtrl.curr_index. */ +ST_RTINT low_index; +ST_RTINT num_elmnts; + + numRt = rt->u.arr.num_rt_blks+2; + va = wrVaCtrl->va; + + if (va->arrCtrl.arrAltAccPres == SD_TRUE) + { + low_index = va->arrCtrl.low_index; + num_elmnts = va->arrCtrl.num_elmnts; + } + else + { + low_index = 0; + num_elmnts = (ST_RTINT) rt->u.arr.num_elmnts; + } + +/* Let's check to see if the client is selecting a sub-object ... */ + prim_info->prim_offset += rt->el_size; + prim_info->prim_offset_base += rt->el_size; + for (i = 0; i < num_elmnts; ++i) + { + va->arrCtrl.curr_index = low_index + i; + startElWrites (indCtrl, wrCtrl, wrVaCtrl, rt+1, numRt-2, prim_info); + } + prim_info->prim_offset += (rt+numRt-1)->el_size; + prim_info->prim_offset_base += (rt+numRt-1)->el_size; + } + +/************************************************************************/ +/* mvlu_wr_prim_done */ +/************************************************************************/ +/* The user calls this function acynchronously when the primitive data */ +/* has been put in the 'primData' buffer. */ + +ST_VOID mvlu_wr_prim_done (MVLU_WR_VA_CTRL *mvluWrVaCtrl, ST_RET rc) + { +MVLAS_WR_VA_CTRL *wrVaCtrl; + + wrVaCtrl = mvluWrVaCtrl->wrVaCtrl; + if (rc != SD_SUCCESS) + wrVaCtrl->resp_tag = WR_RSLT_FAILURE; + + ++wrVaCtrl->numPrimDataDone; + if (wrVaCtrl->numPrimDataDone == wrVaCtrl->numPrimData) + { /* all prims done for this variable */ + MVL_IND_PEND *indCtrl = mvluWrVaCtrl->indCtrl; + +#if !defined(MVL61850_CTL_DISABLE) + //mvl61850_ctl_req_done (wrVaCtrl, indCtrl->event->net_info);//lnk±àÒëɾ³ý£¬Ô­Ç°ÖóÌÐòδʹÓà +#endif /* !defined(MVL61850_CTL_DISABLE) */ + + /* Response "usually" sent from u_mvl_write_ind. If it finished */ + /* without sending resp AND resp is ready now, send it. */ + if (indCtrl->u.wr.ind_funct_done /* ind funct completed */ + && chk_write_resp_ready(indCtrl)==SD_SUCCESS) /* resp ready */ + mvlas_write_resp (indCtrl); /* send resp */ + } + M_FREE (MSMEM_MVLU_VA_CTRL, mvluWrVaCtrl); + } + + +/************************************************************************/ +/* mvluDefAsyncWrIndFun */ +/************************************************************************/ + +static ST_VOID mvluDefAsyncWrIndFun (struct mvlu_wr_va_ctrl *mvluWrVaCtrl) + { + mvlu_wr_prim_done (mvluWrVaCtrl, SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* countPrimEl */ +/************************************************************************/ + +static ST_INT countPrimEl (MVL_VAR_ASSOC *va, RUNTIME_TYPE *rt, ST_INT rt_num) + { +ST_INT i; +ST_INT num_elmnts; +ST_INT numPrimData; +ST_INT subElCount; + + numPrimData = 0; + for (i = 0; i < rt_num; ++i, ++rt) + { + if (ms_is_rt_prim (rt) == SD_TRUE) + ++numPrimData; + if (rt->el_tag == RT_ARR_START) + { + subElCount = countPrimEl (va, rt+1, rt->u.arr.num_rt_blks); + + if (va->arrCtrl.arrAltAccPres == SD_FALSE) + num_elmnts = rt->u.arr.num_elmnts; + else + num_elmnts = va->arrCtrl.num_elmnts; + + numPrimData += (subElCount * num_elmnts); + + i += (rt->u.arr.num_rt_blks + 1); + rt += (rt->u.arr.num_rt_blks + 1); + } + } + return (numPrimData); + } + +/************************************************************************/ +/* mvluDefGetVaDataBufFun */ +/* NOTE: only called when va->base_va->use_static_data==SD_FALSE. */ +/************************************************************************/ + +static ST_VOID mvluDefGetVaDataBufFun (ST_INT service, + MVL_VAR_ASSOC *va, ST_INT size) + { + if (service == MMSOP_READ || service == MMSOP_WRITE || + service == MMSOP_INFO_RPT || service == MMSOP_RD_USR_HANDLED) + { + va->data = M_MALLOC (MSMEM_MVLU_VA_DATA, size); + } + } + +/************************************************************************/ +/* mvluDefFreeVaDataBufFun */ +/* NOTE: only called when va->base_va->use_static_data==SD_FALSE. */ +/************************************************************************/ + +static ST_VOID mvluDefFreeVaDataBufFun (ST_INT service, MVL_VAR_ASSOC *va) + { + if (service == MMSOP_READ || service == MMSOP_WRITE || + service == MMSOP_INFO_RPT || service == MMSOP_RD_USR_HANDLED) + { + M_FREE (MSMEM_MVLU_VA_DATA, va->data); + } + } + +/************************************************************************/ +/* mvlu_find_rt_leaf */ +/************************************************************************/ + +RUNTIME_TYPE *mvlu_find_rt_leaf (ST_INT type_id, ST_CHAR *leafName) + { +RUNTIME_TYPE *rt; +ST_INT numRt; +ST_RET ret; + + ret = mvl_get_runtime (type_id, &rt, &numRt); + if (ret != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Could not get RT type for type id %d", type_id); + return (NULL); + } + + ret = mvlu_find_uca_var (&rt, &numRt, leafName); + if (ret != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Could not find leaf '%s'", leafName); + return (NULL); + } + + if (numRt != 1) + { /* See if this is an array with a single primitive element */ + if (rt->el_tag == RT_ARR_START && numRt == 3) + return (rt+1); + + MVL_LOG_NERR1 ("'%s' is a branch, not a leaf", leafName); + return (NULL); + } + + + return (rt); + } + +/************************************************************************/ +/* mvlu_find_comp_type */ +/* Arguments: */ +/* base_type_id type ID for top level variable */ +/* flatname flattened component name with top level var */ +/* name (Logical Node) stripped off. */ +/* sub_rt_type Ptr to (RUNTIME_TYPE *) to be filled in. */ +/* sub_rt_num Ptr to "count" to be filled in. */ +/************************************************************************/ +ST_RET mvlu_find_comp_type (ST_INT base_type_id, ST_CHAR *flatname, + RUNTIME_TYPE **sub_rt_type, /* out */ + ST_INT *sub_rt_num) /* out */ + { +MVL_TYPE_CTRL *base_type_ctrl; +ST_RET ret; + + base_type_ctrl = mvl_type_ctrl_find (base_type_id); + if (base_type_ctrl) + { + *sub_rt_type = base_type_ctrl->rt; + *sub_rt_num = base_type_ctrl->num_rt; + ret = mvlu_find_uca_var (sub_rt_type, sub_rt_num, flatname); + } + else + ret = SD_FAILURE; + + /* NOTE: don't log error here. Caller may often pass invalid names. */ + return (ret); + } + +/************************************************************************/ +/* mvlu_get_leaf_val_int8 */ +/* Get leaf data value for type ST_INT8. */ +/* Arguments: */ +/* base_va base variable (i.e. logical node) */ +/* flatname flattened leaf name (e.g. ST$Mod$stVal) */ +/* data ptr to data written by this function */ +/* RETURNS: SD_SUCCESS or SD_FAILURE */ +/************************************************************************/ +ST_RET mvlu_get_leaf_val_int8 (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_INT8 *data) + { +RUNTIME_TYPE *comp_rt_type; /* first rt_type of component */ +ST_INT comp_rt_num; /* num of rt_types in component */ +ST_RET ret = SD_FAILURE; + + /* Find the attribute type. */ + if (mvlu_find_comp_type (base_va->type_id, + flatname, /* flattened name */ + &comp_rt_type, /* ptr to val set by function */ + &comp_rt_num) /* ptr to val set by function */ + == SD_SUCCESS) + { + if (comp_rt_type->el_tag == RT_INTEGER && comp_rt_type->u.p.el_len == 1) + { /* must be INT8 */ + *data = *(ST_INT8 *)((ST_CHAR *) base_va->data + comp_rt_type->mvluTypeInfo.offSet); + ret = SD_SUCCESS; + } + else + MVL_LOG_ERR1 ("Invalid type for '%s' attribute. Cannot use it.", flatname); + } + else + MVLU_LOG_FLOW2 ("Cannot find '%s' attribute in this variable '%s'", + flatname, base_va->name); + return (ret); + } +/************************************************************************/ +/* mvlu_get_leaf_val_int32 */ +/* Get leaf data value for type ST_INT32. */ +/* Arguments: */ +/* base_va base variable (i.e. logical node) */ +/* flatname flattened leaf name (e.g. ST$Mod$stVal) */ +/* data ptr to data written by this function */ +/* RETURNS: SD_SUCCESS or SD_FAILURE */ +/************************************************************************/ +ST_RET mvlu_get_leaf_val_int32 (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_INT32 *data) + { +RUNTIME_TYPE *comp_rt_type; /* first rt_type of component */ +ST_INT comp_rt_num; /* num of rt_types in component */ +ST_RET ret = SD_FAILURE; + + /* Find the attribute type. */ + if (mvlu_find_comp_type (base_va->type_id, + flatname, /* flattened name */ + &comp_rt_type, /* ptr to val set by function */ + &comp_rt_num) /* ptr to val set by function */ + == SD_SUCCESS) + { + if (comp_rt_type->el_tag == RT_INTEGER && comp_rt_type->u.p.el_len == 4) + { /* must be INT32 */ + *data = *(ST_INT32 *)((ST_CHAR *) base_va->data + comp_rt_type->mvluTypeInfo.offSet); + ret = SD_SUCCESS; + } + else + MVL_LOG_ERR1 ("Invalid type for '%s' attribute. Cannot use it.", flatname); + } + else + MVLU_LOG_FLOW2 ("Cannot find '%s' attribute in this variable '%s'", + flatname, base_va->name); + return (ret); + } +/************************************************************************/ +/* mvlu_get_leaf_val_int_any */ +/* Get leaf value for any signed integer. Cast value to ST_INT32. */ +/************************************************************************/ +ST_RET mvlu_get_leaf_val_int_any (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_INT32 *data) + { +RUNTIME_TYPE *comp_rt_type; /* first rt_type of component */ +ST_INT comp_rt_num; /* num of rt_types in component */ +ST_CHAR *raw_data; /* ptr to data. May be any integer size */ +ST_INT8 tmp_int8; /* Used to get val as INT8, then cast to INT32 */ +ST_INT16 tmp_int16; /* Used to get val as INT16, then cast to INT32 */ +ST_RET retcode = SD_SUCCESS; + + /* Find the attribute type. */ + if (mvlu_find_comp_type (base_va->type_id, + flatname, /* flattened name */ + &comp_rt_type, /* ptr to val set by function */ + &comp_rt_num) /* ptr to val set by function */ + == SD_SUCCESS) + { + raw_data = (ST_CHAR *) base_va->data + comp_rt_type->mvluTypeInfo.offSet; + if (comp_rt_type->el_tag == RT_INTEGER) + { + if (comp_rt_type->u.p.el_len == 1) /* INT8 */ + { + tmp_int8 = *(ST_INT8 *) raw_data; + *data = (ST_INT32) tmp_int8; + } + else if (comp_rt_type->u.p.el_len == 2) /* INT16 */ + { + tmp_int16 = *(ST_INT16 *) raw_data; + *data = (ST_INT32) tmp_int16; + } + else if (comp_rt_type->u.p.el_len == 4) /* INT32 */ + { + *data = *(ST_INT32 *) raw_data; + } + else + { + MVL_LOG_ERR2 ("Unsupported integer size for '%s' attribute in variable '%s'", + flatname, base_va->name); + retcode = SD_FAILURE; + } + } + else + { + MVL_LOG_ERR2 ("Invalid type for '%s' attribute in variable '%s'. Cannot get value.", + flatname, base_va->name); + retcode = SD_FAILURE; + } + } + else + { + MVLU_LOG_FLOW2 ("Cannot find '%s' attribute in variable '%s'", + flatname, base_va->name); + retcode = SD_FAILURE; + } + return (retcode); + } +/************************************************************************/ +/* mvlu_get_leaf_val_uint32 */ +/* Get leaf data value for type ST_UINT32. */ +/* Arguments: */ +/* base_va base variable (i.e. logical node) */ +/* flatname flattened leaf name (e.g. ST$Mod$stVal) */ +/* data ptr to data written by this function */ +/* RETURNS: SD_SUCCESS or SD_FAILURE */ +/************************************************************************/ +ST_RET mvlu_get_leaf_val_uint32 (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_UINT32 *data) + { +RUNTIME_TYPE *comp_rt_type; /* first rt_type of component */ +ST_INT comp_rt_num; /* num of rt_types in component */ +ST_RET ret = SD_FAILURE; + + /* Find the attribute type. */ + if (mvlu_find_comp_type (base_va->type_id, + flatname, /* flattened name */ + &comp_rt_type, /* ptr to val set by function */ + &comp_rt_num) /* ptr to val set by function */ + == SD_SUCCESS) + { + if (comp_rt_type->el_tag == RT_UNSIGNED && comp_rt_type->u.p.el_len == 4) + { /* must be UINT32 */ + *data = *(ST_UINT32 *)((ST_CHAR *) base_va->data + comp_rt_type->mvluTypeInfo.offSet); + ret = SD_SUCCESS; + } + else + MVL_LOG_ERR1 ("Invalid type for '%s' attribute. Cannot use it.", flatname); + } + else + MVLU_LOG_FLOW2 ("Cannot find '%s' attribute in this variable '%s'", + flatname, base_va->name); + return (ret); + } +/************************************************************************/ +/* mvlu_get_leaf_val_boolean */ +/* Get leaf data value for type ST_BOOLEAN. */ +/* Arguments: */ +/* base_va base variable (i.e. logical node) */ +/* flatname flattened leaf name (e.g. ST$Mod$stVal) */ +/* data ptr to data written by this function */ +/* RETURNS: SD_SUCCESS or SD_FAILURE */ +/************************************************************************/ +ST_RET mvlu_get_leaf_val_boolean (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, ST_BOOLEAN *data) + { +RUNTIME_TYPE *comp_rt_type; /* first rt_type of component */ +ST_INT comp_rt_num; /* num of rt_types in component */ +ST_RET ret = SD_FAILURE; + + /* Find the attribute type. */ + if (mvlu_find_comp_type (base_va->type_id, + flatname, /* flattened name */ + &comp_rt_type, /* ptr to val set by function */ + &comp_rt_num) /* ptr to val set by function */ + == SD_SUCCESS) + { + if (comp_rt_type->el_tag == RT_BOOL) + { /* must be BOOLEAN */ + *data = *(ST_BOOLEAN *)((ST_CHAR *) base_va->data + comp_rt_type->mvluTypeInfo.offSet); + ret = SD_SUCCESS; + } + else + MVL_LOG_ERR1 ("Invalid type for '%s' attribute. Cannot use it.", flatname); + } + else + MVLU_LOG_FLOW2 ("Cannot find '%s' attribute in this variable '%s'", + flatname, base_va->name); + return (ret); + } +/************************************************************************/ +/* mvlu_get_leaf_val_bvstring */ +/* Get leaf data value for type MMS_BVSTRING. */ +/* Arguments: */ +/* base_va base variable (i.e. logical node) */ +/* flatname flattened leaf name (e.g. ST$Mod$stVal) */ +/* data ptr to data written by this function */ +/* RETURNS: SD_SUCCESS or SD_FAILURE */ +/************************************************************************/ +ST_RET mvlu_get_leaf_val_bvstring (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, + MMS_BVSTRING *data, ST_INT max_num_bits) + { +RUNTIME_TYPE *comp_rt_type; /* first rt_type of component */ +ST_INT comp_rt_num; /* num of rt_types in component */ +ST_RET ret = SD_FAILURE; +ST_INT num_bytes; + + /* Find the attribute type. */ + if (mvlu_find_comp_type (base_va->type_id, + flatname, /* flattened name */ + &comp_rt_type, /* ptr to val set by function */ + &comp_rt_num) /* ptr to val set by function */ + == SD_SUCCESS) + { + /* NOTE: for Bvstring, el_len is negative. */ + if (comp_rt_type->el_tag == RT_BIT_STRING && comp_rt_type->u.p.el_len < 0 + && abs (comp_rt_type->u.p.el_len) <= max_num_bits) + { + num_bytes = 2 + (abs (comp_rt_type->u.p.el_len) + 7)/8; + memcpy (data, (ST_CHAR *)base_va->data + comp_rt_type->mvluTypeInfo.offSet, num_bytes); + ret = SD_SUCCESS; + } + else + MVL_LOG_ERR1 ("Invalid type for '%s' attribute. Cannot use it.", flatname); + } + else + MVLU_LOG_FLOW2 ("Cannot find '%s' attribute in this variable '%s'", + flatname, base_va->name); + return (ret); + } +/************************************************************************/ +/* mvlu_get_leaf_data_ptr */ +/* Get leaf data pointer (for any type of leaf). */ +/* Arguments: */ +/* base_va base variable (i.e. logical node) */ +/* flatname flattened leaf name (e.g. ST$Mod$stVal) */ +/* rt_type ptr to ptr to type (function sets "*rt_type") */ +/* RETURNS: pointer to leaf data (NULL on error) */ +/************************************************************************/ +ST_VOID *mvlu_get_leaf_data_ptr (MVL_VAR_ASSOC *base_va, ST_CHAR *flatname, RUNTIME_TYPE **rt_type) + { +RUNTIME_TYPE *comp_rt_type; /* first rt_type of component */ +ST_INT comp_rt_num; /* num of rt_types in component */ +ST_VOID *data; + + /* Find the attribute type. */ + if (mvlu_find_comp_type (base_va->type_id, + flatname, /* flattened name */ + &comp_rt_type, /* ptr to val set by function */ + &comp_rt_num) /* ptr to val set by function */ + == SD_SUCCESS) + { + data = ((ST_CHAR *) base_va->data + comp_rt_type->mvluTypeInfo.offSet); + *rt_type = comp_rt_type; + } + else + { + data = NULL; + MVLU_LOG_FLOW2 ("Cannot find '%s' attribute in this variable '%s'", + flatname, base_va->name); + } + return (data); + } + +/************************************************************************/ +/* mvlu_find_component */ +/* Find a lower level variable by processing "flattened" variable name */ +/* AND/OR Alternate Access. */ +/* NOTE: Similar to "mvlu_find_uca_var" but handles Alternate Access too.*/ +/************************************************************************/ +ST_RET mvlu_find_component ( + ST_CHAR *flatname, /* flattened name (e.g. ST$Mod$stVal) */ + ALT_ACCESS *alt_acc, /* NULL if Alt Access Spec not present */ + RUNTIME_TYPE **rtIo, + ST_INT *numRtIo, + ST_INT *offset_io, + ST_RTINT *prim_num_io) + { +ST_RET ret; +ST_INT aa_idx; /* index to next alternate access element */ +RUNTIME_TYPE *rt_type; +ST_CHAR nameBuf[MAX_IDENT_LEN+1]; +ST_CHAR *nameToFind; +ST_CHAR *compEnd; +ST_BOOLEAN nameDone; + + /* Deal with "flattened" naming first (i.e. fake Alternate Access). */ + if (flatname != NULL) + { + strcpy (nameBuf, flatname); /* copy so we can modify it */ + nameToFind = nameBuf; + nameDone = SD_FALSE; + while (nameDone == SD_FALSE) + { + /* Isolate the component name for this level, removing subcomp names */ + compEnd = strstr (nameToFind, "$"); + if (compEnd != NULL) + *compEnd = 0; + else /* This is the last nest level */ + nameDone = SD_TRUE; + + /* Find the component name in the current runtime type nest level */ + /* NOTE: this modifies (*rtIo), (*numRtIo), (*offset_io), (*prim_num_io).*/ + ret = mvlu_find_struct_comp (nameToFind, rtIo, numRtIo, offset_io, prim_num_io); + if (ret == SD_FAILURE) + { + /* Many things can cause this so just use FLOW Logging. */ + MVLU_LOG_FLOW2 ("Could not find name component %s from name %s", + nameToFind, flatname); + return (SD_FAILURE); + } + + /* OK, we now have found the component in the runtime type, and our */ + /* runtime pointer and numRt reflect the sub-runtime type. */ + /* next component. */ + + /* Prepare to find the next level component name */ + nameToFind = compEnd+1; + } /* end while */ + } /* end if (flatname != NULL)*/ + + /* Now deal with real alternate access. */ + if (alt_acc != NULL) + { + for (aa_idx = 0; aa_idx < alt_acc->num_aa; aa_idx++) + { + ALT_ACC_EL *next_el; + ST_CHAR *comp_name; /* component name (used only if AA_COMP..)*/ + ST_INT arr_index; /* array index (used only if AA_INDEX..)*/ + + next_el = &alt_acc->aa[aa_idx]; + switch (next_el->sel_type) + { + case AA_COMP : + case AA_COMP_NEST : + comp_name = next_el->u.component; + /* Find the component name in the current runtime type nest level */ + ret = mvlu_find_struct_comp (comp_name, rtIo, numRtIo, offset_io, prim_num_io); + if (ret == SD_FAILURE) + { + /* Many things can cause this so just use FLOW Logging. */ + MVLU_LOG_FLOW1 ("Could not find name component %s", comp_name); + return (SD_FAILURE); + } + break; + case AA_INDEX_NEST : + case AA_INDEX : + case AA_INDEX_RANGE_NEST : + case AA_INDEX_RANGE : + rt_type = *rtIo; + if (rt_type->el_tag != RT_ARR_START) + { + MVL_LOG_ERR1 ("Specified array index on non-array component %s", comp_name); + return (SD_FAILURE); + } + /* If Array index range, just need low index for this computation.*/ + if (next_el->sel_type== AA_INDEX_RANGE_NEST || + next_el->sel_type== AA_INDEX_RANGE) + arr_index = next_el->u.ir.low_index; + else + arr_index = next_el->u.index; + *offset_io += rt_type->el_size; /* ARR_START size (usually 0)*/ + /* Multiply array element size by array index. */ + /* offset_to_last in next rt_type contains array element size.*/ + *offset_io += (rt_type+1)->offset_to_last * arr_index; + *prim_num_io += (rt_type+1)->mvluTypeInfo.prim_count * arr_index; + *rtIo = rt_type + 1; /* point to array elem */ + *numRtIo-=2; + break; + case AA_END_NEST : + break; /* just ignore these */ + default: + MVL_LOG_ERR1 ("Alternate access type '%d' not supported", next_el->sel_type); + return (SD_FAILURE); + } + + /* OK, we now have found the component in the runtime type, and our */ + /* runtime pointer and numRt reflect the sub-runtime type. */ + } + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/* chk_var_writable */ +/* Check if EVERY leaf in this variable is writable. If so, variable */ +/* is writable. */ +/* RETURNS: SD_SUCCESS if variable is writable */ +/* SD_FAILURE if variable is NOT writable */ +/************************************************************************/ +static ST_RET chk_var_writable (RUNTIME_TYPE *rt, ST_INT rt_num) + { +ST_INT j; + + /* DEBUG: This mode is almost never used. */ + /* 1 leaf function for all leafs. Assume all leafs writable. */ + if (u_mvlu_leaf_wr_ind_fun) + { + return (SD_SUCCESS); /* var is writable */ + } + + /* Find index to "u_no_write_allowed" function & save in static var. */ + /* This calls "mvlu_find.." only once, the first time through here. */ + /* NOTE: if not found, idx will be -1. If found, idx will be >= 0. */ + if (idx_u_no_write_allowed == -2) /* not yet initialized */ + {idx_u_no_write_allowed = -1;}//idx_u_no_write_allowed = mvlu_find_wr_ind_fun_index ("u_no_write_allowed");//lnk±àÒëÐ޸ģ¬Ô­Ç°ÖóÌÐòδʹÓà + if (idx_u_no_write_allowed < 0) + return (SD_SUCCESS); /* funct not found. Assume var is writable*/ + + /* Loop through type def to see if ANY leaf is unwritable. */ + for (j = 0; j < rt_num; ++j, ++rt) + { + if (ms_is_rt_prim (rt) + && rt->mvluTypeInfo.wrIndFunIndex == idx_u_no_write_allowed) + { + return (SD_FAILURE); /* var not writable */ + } + } + return (SD_SUCCESS); /* var is writable */ + } + +/************************************************************************/ +/* chk_write_resp_ready */ +/* Check if everything ready to send Write response. */ +/* RETURNS: SD_SUCCESS if ready */ +/* SD_FAILURE if NOT ready */ +/************************************************************************/ +static ST_RET chk_write_resp_ready (MVL_IND_PEND *indCtrl) + { +MVLAS_WRITE_CTRL *wrCtrl; +MVLAS_WR_VA_CTRL *wrVaCtrl; /* current var in list of var */ +ST_INT i; +ST_BOOLEAN retcode; + + wrCtrl = &indCtrl->u.wr; + + /* If all primitives for all variables are complete, ready to send resp.*/ + wrVaCtrl = wrCtrl->vaCtrlTbl; + for (i = 0; i < wrCtrl->numVar; ++i, ++wrVaCtrl) + { + if (wrVaCtrl->numPrimDataDone != wrVaCtrl->numPrimData) + break; /* prims NOT done for this var */ + } + if (i == wrCtrl->numVar) + retcode = SD_SUCCESS; /* ready to send response. */ + else + retcode = SD_FAILURE; /* not ready */ + return (retcode); + } +/************************************************************************/ +/* set_write_resp_dae */ +/* Set MMS Write Response DataAccessError for this variable. */ +/************************************************************************/ +static ST_VOID set_write_resp_dae (MVLAS_WR_VA_CTRL *wrVaCtrl, + ST_INT16 dae) /* MMS DataAccessError code */ + { + wrVaCtrl->resp_tag = WR_RSLT_FAILURE; + wrVaCtrl->failure = dae; + wrVaCtrl->numPrimDataDone = wrVaCtrl->numPrimData; /* pretend like all prim done*/ + } + +/************************************************************************/ +#endif /* defined(MVL_UCA) */ +/************************************************************************/ + diff --git a/mmslib/mvlu/mvl_var.c b/mmslib/mvlu/mvl_var.c new file mode 100644 index 0000000..531ee99 --- /dev/null +++ b/mmslib/mvlu/mvl_var.c @@ -0,0 +1,400 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2002, All Rights Reserved */ +/* */ +/* MODULE NAME : mvl_var.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/30/06 JRB 31 Use new mvl_vmd_* object handling functions. */ +/* _mvl_objname_to_va: add args. */ +/* u_mvl_get_va_aa: add args. */ +/* Elim use of global var "_mvl_curr_net_info". */ +/* 01/30/06 GLB 30 Integrated porting changes for VMS */ +/* 02/27/04 MDE 29 Log message correct */ +/* 03/13/03 JRB 28 Add mvl_scope_set function. */ +/* 12/12/02 JRB 27 Add net_info arg to mvl_get_va_asn1... and */ +/* elim it's use of global _mvl_curr_net... */ +/* 02/25/02 MDE 26 Now get max PDU size from mvl_cfg_info */ +/* 01/02/02 JRB 25 Converted to use ASN1R (re-entrant ASN1) */ +/* 10/25/00 JRB 24 Del u_mvl funct ptrs. Call functs directly. */ +/* Control with #ifdefs. */ +/* 08/17/00 JRB 23 Don't clear va_to_free. Need value later. */ +/* 03/08/00 JRB 22 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ +/* 01/21/00 MDE 21 Now use MEM_SMEM for dynamic memory */ +/* 01/21/00 MDE 20 Add '_mvl_get_req_buf' for MVL_REQ_BUF_EN.. */ +/* 11/19/99 NAV 19 Add #ifdef MVL_REQ_BUF_ENABLED */ +/* 10/22/99 NAV 18 Add a few utilities to copy structs */ +/* 09/13/99 MDE 17 Added SD_CONST modifiers */ +/* 09/07/99 MDE 16 Changed MVL_VA_SCOPE to MVL_SCOPE */ +/* 01/20/99 JRB 15 Del mvl_find_*. Use new "bsearch" versions. */ +/* Del _mvl_skip_uca_prefix (use va->flags). */ +/* Del _mvl_destroy_nvl_ent.. (see mvl_nvl_de..)*/ +/* 12/11/98 MDE 14 Removed scope references from VA */ +/* 12/08/98 MDE 13 Added client alternate access support */ +/* 11/16/98 MDE 12 Added '_mvl_destroy_nvl_entries' */ +/* 11/16/98 MDE 11 Renamed internal functions (prefix '_') */ +/* 11/10/98 MDE 10 Added 'mvl_get_va_asn1_data' (was in s_read) */ +/* 09/21/98 MDE 09 Minor lint cleanup */ +/* 07/21/98 MDE 08 Moved 'mvl_insert_nvlist' to mvl_dnvl.c */ +/* 07/13/98 MDE 07 Fixed mvl_insert_nvlist bug when adding 1st */ +/* 06/30/98 MDE 06 Corrected insert order for "_UCA_" names */ +/* 06/15/98 MDE 05 Changes to allow compile under C++ */ +/* 06/05/98 MDE 04 Added 'mvl_insert_nvlist' */ +/* 01/06/98 RWM 03 Added Binary Search Capability */ +/* 12/12/97 MDE 02 Moved mvl_vmd to rt_types.c */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mvl_acse.h" +#include "mvl_log.h" + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/* _mvl_objname_to_va */ +/************************************************************************/ + +MVL_VAR_ASSOC *_mvl_objname_to_va (MVL_VMD_CTRL *vmd_ctrl, + MVL_NET_INFO *net_info, + ST_INT service, + OBJECT_NAME *obj, + MVL_SCOPE *va_scope_out, + ST_BOOLEAN alt_access_pres, + ALT_ACCESS *alt_acc, + ST_BOOLEAN *alt_access_done_out) + { +MVL_VAR_ASSOC *va; + +/* By default, we don't modify the VA to handle alternate access */ + if (alt_access_done_out != NULL) + *alt_access_done_out = SD_FALSE; + +/* Let's find the variable association */ + va = mvl_vmd_find_var (vmd_ctrl, obj, net_info); + if ((!va) || (va->flags & MVL_VAR_FLAG_UCA)) + { + /* Could not find variable association, see if we can manufacture it */ +#if defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS) + /* May be able to manufacture it */ + va = u_mvl_get_va_aa (vmd_ctrl, service, obj, net_info, + alt_access_pres, alt_acc, + alt_access_done_out); + if (va != NULL) /* Manufactured it, set flag ... */ + va->va_to_free = va; +#endif /* defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS) */ + } + +/* OK, assuming we have the VA, set it's scope appropriately */ + if (va && va_scope_out) + { + va_scope_out->scope = obj->object_tag; + if (va_scope_out->scope == DOM_SPEC) + { + va_scope_out->dom = mvl_vmd_find_dom (vmd_ctrl, obj->domain_id); + if (va_scope_out->dom == NULL) + { + MVL_LOG_NERR1 ("Warning : Variable object references non-existant domain '%s'", + obj->domain_id); + } + } + } + return (va); + } + +/************************************************************************/ +/* mvl_scope_set */ +/* Use the OBJECT_NAME info to set the scope for any MMS object. */ +/* This function fills in the struct pointed to by mvl_scope_out. */ +/************************************************************************/ +ST_VOID mvl_scope_set (OBJECT_NAME *obj, MVL_SCOPE *mvl_scope_out) + { + mvl_scope_out->scope = obj->object_tag; + if (mvl_scope_out->scope == DOM_SPEC) + { + mvl_scope_out->dom = mvl_vmd_find_dom (&mvl_vmd, obj->domain_id); + if (mvl_scope_out->dom == NULL) + MVL_LOG_NERR1 ("Warning : MMS object references nonexistent domain '%s'", + obj->domain_id); + } + } + +/************************************************************************/ +/* mvl_get_va_asn1_data */ +/************************************************************************/ + +ST_RET mvl_get_va_asn1_data (MVL_NET_INFO *net_info, MVL_VAR_ASSOC *va, + ST_BOOLEAN alt_access_pres, + ALT_ACCESS *alt_acc, + ST_UCHAR *asn1_dest_buffer, + ST_INT asn1_buffer_len, + ST_INT *asn1_len_out) + { +RUNTIME_TYPE *rt; +ST_INT num_rt; +ST_RET rc; +ST_UCHAR *asn1_start; +ST_INT asn1_len; +ST_INT aa_mode; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + aa_mode = MVL_USE_UNPACKED_AA; + if (va->proc && va->proc->pre_read_aa) + { + rc = (*va->proc->pre_read_aa)(&va, alt_access_pres, alt_acc, + net_info, &aa_mode); + + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Read: pre_read_aa returned %d", rc); + return (SD_FAILURE); + } + } + + rc = mvl_get_runtime (va->type_id, &rt, &num_rt); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Read: mvl_get_runtime failed, rc = %x", rc); + return (rc); /* bad type id */ + } + +/* If we got here, we have a valid runtime and have resolved local */ +/* data pointer and size. Go ahead and build the ASN.1 data element. */ + +/* First we need to initialize the ASN.1 encode tools, then do the */ +/* encode */ + asn1r_strt_asn1_bld (aCtx, asn1_dest_buffer, asn1_buffer_len); + +#if defined(MVL_AA_SUPP) + if (alt_access_pres == SD_FALSE || aa_mode == MVL_USE_NO_AA) + { + rc = ms_local_to_asn1 (aCtx, rt, num_rt, (ST_CHAR *) va->data); + } + else + { + if (aa_mode == MVL_USE_PACKED_AA) + m_alt_acc_packed = SD_TRUE; + else + m_alt_acc_packed = SD_FALSE; + + rc = ms_local_to_asn1_aa (aCtx, rt, num_rt, alt_acc, (ST_CHAR *) va->data); + } +#else + rc = ms_local_to_asn1 (aCtx, rt, num_rt, (ST_CHAR *) va->data); +#endif + +/* When the ASN.1 encode is complete, 'asn1_field_ptr' points 1 byte ahead */ +/* of the start of the message. The ASN.1 message is build from back to */ +/* front, so that is now we calculate the length of the PDU */ + if (rc == SD_SUCCESS) + { + asn1_start = aCtx->asn1r_field_ptr+1; + asn1_len = (asn1_dest_buffer + asn1_buffer_len) - asn1_start; + memmove (asn1_dest_buffer,asn1_start,asn1_len); + *asn1_len_out = asn1_len; + + if (va->proc && va->proc->post_read_aa) + { + (*va->proc->post_read_aa)(va, alt_access_pres, alt_acc, + net_info); + } + } + else + { + MVL_LOG_NERR1 ("Local to ASN1 data conversion error: 0x%04x", rc); + } + return (rc); + } + + +/************************************************************************/ +/************************************************************************/ +#if defined(MVL_AA_SUPP) +/************************************************************************/ + +/************************************************************************/ +/************************************************************************/ +/* _mvl_get_asn1_aa */ +/************************************************************************/ + +ST_RET _mvl_get_asn1_aa (ALT_ACCESS *alt_acc, VARIABLE_LIST *vl) + { +ST_UCHAR *aa_buf; +ST_INT aa_buf_size; +ST_UCHAR *asn1_start; +ST_INT asn1_len; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + aa_buf = _m_get_aa_asn1_buf (&aa_buf_size); + asn1r_strt_asn1_bld (aCtx, aa_buf, aa_buf_size); + if (ms_aa_to_asn1 (aCtx, alt_acc)) + { + _m_free_aa_asn1_buf (); + return (SD_FAILURE); + } + else + { + asn1_start = aCtx->asn1r_field_ptr+1; + asn1_len = (aa_buf + aa_buf_size) - asn1_start; + vl->alt_access.len = asn1_len; + vl->alt_access.data = asn1_start; + vl->alt_access_pres = SD_TRUE; + _m_set_aa_asn1_buf_end (asn1_start -1); + } + return (SD_SUCCESS); + } + +/************************************************************************/ + +static ST_UCHAR *aa_buffer_head; +static ST_UCHAR *aa_buffer_end; + +/************************************************************************/ +/* _m_get_aa_asn1_buf */ +/************************************************************************/ + +ST_UCHAR *_m_get_aa_asn1_buf (ST_INT *size_out) + { +ST_UCHAR *ret; + + if (!aa_buffer_head) + { + aa_buffer_head = (ST_UCHAR *) M_MALLOC (MSMEM_AA_ENCODE, mvl_cfg_info->max_msg_size); + aa_buffer_end = aa_buffer_head + mvl_cfg_info->max_msg_size -1; + } + + *size_out = aa_buffer_end - aa_buffer_head + 1; + ret = aa_buffer_head; + return (ret); + } + +/************************************************************************/ +/* _m_set_aa_asn1_buf_end */ +/************************************************************************/ + +ST_VOID _m_set_aa_asn1_buf_end (ST_UCHAR *new_end) + { + aa_buffer_end = new_end; + } + +/************************************************************************/ +/* _m_free_aa_asn1_buf */ +/************************************************************************/ + +ST_VOID _m_free_aa_asn1_buf (ST_VOID) + { + if (aa_buffer_head) + { + M_FREE (MSMEM_AA_ENCODE, aa_buffer_head); + aa_buffer_head = NULL; + } + } + +#endif /* #if defined(MVL_AA_SUPP) */ + + +/************************************************************************/ +/* mvl_get_descr_local_addr */ +/* DESCRIBED VARIABLE ASSOCIATION */ +/* Addresses are in the form : */ +/* "baseaddr:xxx" */ +/* where xxx is the element offset from the base address. */ +/************************************************************************/ + +/************************************************************************/ +#if defined (MVL_DESCR_SUPP) +/************************************************************************/ + +ST_RET mvl_get_descr_local_addr (VAR_ACC_ADDR *addr, + RUNTIME_TYPE *rt, + ST_INT num_rt, + ST_CHAR **data_out, + ST_INT *data_size_out) + { +ST_INT i; +MVL_DESCR_ADDR_ASSOC *d; +ST_INT base_name_len; +ST_INT offset; +ST_INT num_offset; +ST_INT num_elmnts; + +/* We only support symbolic addresses */ + if (addr->addr_tag != SYM_ADDR) + { + MVL_LOG_NERR0 ("Get Described Local Address : Only Symbolic Addresses are supported"); + return (MVL_ERR_NOT_SYM_ADDR); + } + +/* Find the matching described variable association */ + d = mvl_vmd.descr_addr_assoc_tbl; + for (i = 0; i < mvl_vmd.num_descr_addr; ++i, ++d) + { + base_name_len = strlen (d->base_name); + if (!strncmp (d->base_name, addr->addr.sym_addr, base_name_len)) + { + /* Check for offset from base element */ + if (base_name_len == strlen (addr->addr.sym_addr)) + offset = 0; + else + { + num_offset = atoi (&addr->addr.sym_addr[base_name_len + 1]); + if (num_offset) /* :1 is first element */ + num_offset--; + offset = d->data_size * num_offset; + } + + if (rt->el_tag != RT_ARR_START) /* if not array */ + { + *data_out = (ST_CHAR *) d->data + offset; + *data_size_out = d->data_size; + return (SD_SUCCESS); + } + else /* this is an array */ + { + num_elmnts = rt->u.arr.num_elmnts; /* get number of elements */ + if (num_elmnts + num_offset > d->max_elmnts) + { + MVL_LOG_NERR0 ("Get Described Local Address : Invalid array element count"); + return (MVL_ERR_ARRAY_ELEMENT_CNT); + } + + *data_out = (ST_CHAR *) d->data + offset; + *data_size_out = d->data_size * num_elmnts; + return (SD_SUCCESS); + } + break; + } + } + MVL_LOG_NERR0 ("Get Described Local Address : Could not get Local Address"); + return (MVL_ERR_LOCAL_ADDRESS); + } +/************************************************************************/ +#endif /* #if defined (MVL_DESCR_SUPP) */ +/************************************************************************/ + diff --git a/mmslib/mvlu/mvlu_rpt.c b/mmslib/mvlu/mvlu_rpt.c new file mode 100644 index 0000000..8c8efbc --- /dev/null +++ b/mmslib/mvlu/mvlu_rpt.c @@ -0,0 +1,2570 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 2006, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mvlu_rpt.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/08/08 JRB 62 mvlu_create_rpt_ctrl: clarify args. */ +/* 04/15/08 JRB 61 Don't call mvlu_rpt_va_change for Integrity */ +/* (save "reason" later when scan completes). */ +/* mvl61850_brcb_handle_rptena_wr: fix retCode. */ +/* mvlu_rptena_wr..: Fix warning newval not set.*/ +/* 03/04/08 JRB 60 Remove AA_SPEC DatSet from RCB on disconnect */ +/* or when 0 written to Resv. */ +/* 03/16/07 JRB 59 Fix Resv init in ..urcb_handle_rptena_wr. */ +/* 02/28/07 JRB 58 DO NOT PurgeBuf when OptFlds is changed. */ +/* PurgeBuf when RptID, DatSet, BufTm, TrgOps, */ +/* or IntgPd is changed (tissue 322 final text).*/ +/* 02/13/07 JRB 57 mvl61850_get_rcb: del unused net_info arg. */ +/* Chk net_info before trying to find UCA RCB. */ +/* Add _rcb_writable & use it. */ +/* 12/20/06 JRB 56 PurgeBuf only if val changed (tissue 322). */ +/* PurgeBuf also when BufTm written. */ +/* 10/30/06 JRB 55 Use new mvl_vmd_* object handling functions. */ +/* u_mvl_get_va_aa: add args. */ +/* Add mvlu_rpt_ctrl_destroy_all */ +/* 09/13/06 JRB 54 mvlu_rpt_find_typeids: simplify. */ +/* 08/09/06 JRB 53 If report buffered because of BufTm, send it */ +/* BEFORE any Integrity report. */ +/* 08/09/06 JRB 52 mvlu_create_rpt_ctrl, mvlu_free_rpt_ctrl, */ +/* mvlu_rpt_service now ONLY for UCA (for 61850,*/ +/* use new functions in mvl61850_rpt.c). */ +/* Del brcb_enable_allowed (not needed now that */ +/* segmenting done only when sending). */ +/* Reset SqNum=0 when BRCB enabled. */ +/* PurgeBuf when DatSet,OptFlds,TrgOps,IntgPd */ +/* or RptID written. */ +/* Reserve BRCB only when RptEna written (chged */ +/* mvlu_get_wr_rcb, mvlu_rptena_wr_ind_fun). */ +/* mvlu_rpt_find_typeids: create if not found. */ +/* Add mvlu_rpt_ready, mvlu_rpt_rcb_type_find. */ +/* Chg some static functs to extern. */ +/* 07/27/05 JRB 51 mvlu_optflds_wr..: use rcb_type to figure */ +/* out which bits are writable. */ +/* 06/27/05 JRB 50 brcb_enable_allowed: reset netInfo on error. */ +/* 06/27/05 JRB 49 Simplify allocation by deleting all use of */ +/* MVLU_RPT_VA_CTRL & va->mvl_internal & moving */ +/* last_data to MVL_VAR_ASSOC struct. */ +/* Del mvlu_rpt_nvl_add/destroy, use mvl_nvl_add*/ +/* Del unused mvlu_resolve_uca_nvl. */ +/* 06/27/05 JRB 48 _mvlu_get_rd_rcb: add (MVLU_RPT_CLIENT **) arg*/ +/* 05/24/05 CRM 47 Added mvlu_rpt_destroy_scan_ctrl */ +/* 05/16/05 JRB 46 Set failure=ARE_TEMP_UNAVAIL when trying to */ +/* write RCB elements while RptEna=TRUE. */ +/* 05/09/05 JRB 45 Chk Integrity bit in TrgOps, as we did */ +/* BEFORE change on 03/13/03 (61850 requires it)*/ +/* 08/16/04 JRB 44 Reset SqNum when URCB is enabled. */ +/* 07/20/04 JRB 43 ..chk_reason: make sure OLD data sent in */ +/* first rpt when 2nd change detected. */ +/* 07/07/04 JRB 42 ..chk_reason: for URCB or BRCB, call */ +/* mvl61850_rcb_build (NOT mvlu_send_report). */ +/* 07/06/04 JRB 41 Add client for BRCB only when needed, */ +/* allows BRCB initial values to be set first. */ +/* Add mvlu_rpt_create_scan_ctrl2. */ +/* 06/29/04 JRB 40 mvlu_rpt_nvl_add: alloc new buffer for */ +/* va->data ONLY if use_static_data==FALSE. */ +/* 12/17/03 JRB 39 61850-8-1 FDIS changes: */ +/* Increase num bits in OptFlds to 10 for ConfRev.*/ +/* Find type RTYP_INT32U for ConfRev. */ +/* 05/02/03 JRB 38 switch(rt->el_tag): Use default for most cases*/ +/* 04/17/03 JRB 37 Add & use mvlu_setup_scan_read. */ +/* 04/04/03 JRB 36 mvlu_rpt_va_change: save data at END of funct*/ +/* 04/04/03 JRB 35 Fix integrity/GI scan code so multiple */ +/* concurrent scans don't corrupt one another. */ +/* 03/13/03 JRB 34 Add URCB support including Resv. */ +/* Chg OptFlds back to 8 bits for UCA (9 for IEC).*/ +/* Trigger Intg Rpt ONLY by setting IntgPd!=0. */ +/* Increment SqNum after each report. */ +/* Chg names in rpt_typeids struct (clearer). */ +/* Fix _mvlu_rpt_find_rpt_va to set scope. */ +/* Use tmp_va_arr for all rptNvl options. */ +/* Simplify mvlu_rpt_va_change. */ +/* Use domain name for NVL, not VA, in RptId string.*/ +/* Chg TrgOps to Bvstring. */ +/* 12/16/02 JRB 33 Chg args to mvlu_create_rpt_ctrl. */ +/* Add mvlu_integrity_scan_* functions. */ +/* Move some init/cleanup INTO mvlu_send_report.*/ +/* Don't allow write of RCB if RptEna=TRUE. */ +/* Use mvl_internal to AVOID conflict w/ user_info.*/ +/* Write default RptID once in mvlu_create_rpt_ctrl*/ +/* Start "automatic" scan when IntgPd expires. */ +/* Use BSTR_BIT.. macros to access bitstring bits*/ +/* Del buffer chain code. */ +/* Del rptTim*, call usr func u_mvlu_rpt_time_get*/ +/* Del outDat*, use basrcb->DatSetNa (same string)*/ +/* Init OptFlds.len_1=8. Chg optflds_wr_ind_fun.*/ +/* Del *typeId globals, use mvlu_rpt_find_typeids*/ +/* Use BSTR_NUMBITS_TO_.. */ +/* 12/09/02 MDE 32 Removed need for primRef for reports */ +/* 03/29/02 JRB 31 Fix crash if _mvl_objname_to_va returns NULL.*/ +/* 12/12/01 MDE 30 Include mvl_defs.h instead of mvl_acse.h */ +/* 11/26/01 EJV 29 Added support for new MMS type UtcTime. */ +/* 08/30/01 JRB 28 Fix "..sqnum_rd.." (chg UINT16 to UINT8). */ +/* 12/21/00 JRB 27 Del return in main loop of mvlu_rpt_va_change*/ +/* 10/25/00 JRB 26 Del u_mvl funct ptrs. Call functs directly. */ +/* 09/08/00 JRB 25 Default to 10 second scan period. */ +/* 07/13/00 JRB 24 Use new ms_comp_name_find to get comp names. */ +/* 07/11/00 MDE 23 Changed seqNum to sqNum, made INT8U */ +/* 05/01/00 JRB 22 Lint cleanup (uninitialized var). */ +/* 03/10/00 JRB 21 Copy va_scope to appropriate structures. */ +/* 03/07/00 MDE 20 Fixed integrity report problem */ +/* 01/21/00 MDE 19 Now use MEM_SMEM for dynamic memory */ +/* 09/27/99 NAV 18 Set OutData data for report */ +/* 09/13/99 MDE 17 Added SD_CONST modifiers */ +/* 09/07/99 MDE 16 Revised and enhanced the UCA report system */ +/* 05/04/99 JRB 15 Fixed several write indication functions. */ +/* 03/18/99 MDE 14 Changed for runtime connection limits */ +/* 01/21/99 JRB 13 Del mvlu_create_nvl, mvlu_destroy_nvl. Call */ +/* mvl_nvl_create, mvl_nvl_destroy instead. */ +/* 12/11/98 MDE 12 Removed scope references from VA */ +/* 11/16/98 MDE 11 Now use '_mvl_destroy_nvl_entries' */ +/* 11/16/98 MDE 10 Renamed internal functions (prefix '_') */ +/* 10/01/98 MDE 09 Changes to MVLU_RPT_CTRL rcb allocation */ +/* 09/21/98 MDE 08 Minor lint cleanup */ +/* 09/16/98 MDE 07 Moved RD/WR functions here from rdwrind.c */ +/* 08/11/98 MDE 06 Changed 'mvlu_create_rpt_ctrl' parameters */ +/* 07/13/98 MDE 05 We now use our own report control */ +/* 06/29/98 MDE 04 Moved report function pointers to mvl_uca.c */ +/* 06/22/98 MDE 03 SeqNum now ST_UINT16 */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 01/02/98 MDE 01 New */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mvl_uca.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/* These variables must be set by the user application, and select the */ +/* types to be used by the elements listed below. */ + +MVLU_RPT_CTRL *mvlu_rpt_ctrl_list; +MVLU_RPT_CTRL *mvl61850_rpt_ctrl_list; /* List of only 61850 RCBs. */ +MVLU_RPT_SCAN_CTRL *mvlu_rpt_scan_list; + +/************************************************************************/ + +static MVLU_RPT_CLIENT *_mvlu_add_rpt_client (MVLU_RPT_CTRL *rptCtrl, + MVL_NET_INFO *netInfo); +static ST_VOID _mvlu_free_rpt_client (MVLU_RPT_CLIENT *rptClient); + +static ST_VOID _mvlu_rpt_client_service (MVLU_RPT_CLIENT *rptClient, + ST_DOUBLE timeNow); + +static ST_VOID _mvlu_rpt_va_reads_done (MVL_IND_PEND *indCtrl, + MVL_VAR_ASSOC *va); + +static ST_VOID _mvlu_get_rcb (MVL_VAR_ASSOC *baseVa, + RUNTIME_TYPE *rt, + MVL_NET_INFO *netInfo, + MVLU_RPT_CTRL **rptCtrlOut, + MVLU_RPT_CLIENT **rptClientOut); + +static ST_RET _mvlu_count_rpt_var (RUNTIME_TYPE *rt, ST_INT numRt, + ST_INT *numRptVarOut, ST_INT *nameSizeOut); + +static ST_RET _mvlu_fill_rpt_var (ST_CHAR *baseName, ST_CHAR *domName, + RUNTIME_TYPE *rt, ST_INT numRt, + ST_INT numObjNames, OBJECT_NAME *objNames, + ST_CHAR **nameBufPtr); + +static ST_VOID _mvlu_rpt_va_chk_reason (MVLU_RPT_CLIENT *rptClient, + MVL_VAR_ASSOC *va, + ST_INT entry_num, + ST_UCHAR reason); + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* REPORT DATASET HANDLING */ +/************************************************************************/ +/************************************************************************/ + +/************************************************************************/ +/* mvlu_derive_rpt_ds */ +/************************************************************************/ + +MVL_NVLIST_CTRL *mvlu_derive_rpt_ds (ST_CHAR *domName, ST_CHAR *nvlName, + ST_INT numNodes, ST_CHAR **nodeNames) + { +MVL_NVLIST_CTRL *nvl; +OBJECT_NAME nvlObjName; +OBJECT_NAME *objNames; +ST_RET rc; +ST_INT numDsVar; +ST_CHAR *nameBuf; + + + rc = mvlu_derive_ds_va_names (domName, numNodes, nodeNames, + &numDsVar, &objNames, &nameBuf); + if (rc != SD_SUCCESS) + return (NULL); + + +/* Create the DataSet NVL */ + nvlObjName.object_tag = DOM_SPEC; + nvlObjName.domain_id = domName; + nvlObjName.obj_name.item_id = nvlName; + +/* Add the DataSet NVL to the MVL data structures */ + nvl = mvl_vmd_nvl_add (&mvl_vmd, + &nvlObjName, /* NVL "object name" */ + NULL, /* MVL_NET_INFO not used */ + numDsVar, /* num of variables */ + objNames, /* array of var "object names" */ + SD_TRUE); /* copy nvl name to new nvl. */ + + M_FREE (MSMEM_GEN, nameBuf); + M_FREE (MSMEM_GEN, objNames); + return (nvl); + } + +/************************************************************************/ +/************************************************************************/ + + +typedef struct + { + MVL_VAR_ASSOC *nodeVa; + ST_INT num_rpt_var; + RUNTIME_TYPE *rt; + ST_INT numRt; + } _MVLU_RPT_DS_NODE_INFO; + +ST_RET mvlu_derive_ds_va_names (ST_CHAR *domName, + ST_INT numNodes, ST_CHAR **nodeNames, + ST_INT *numObjNamesOut, + OBJECT_NAME **objNameTblOut, + ST_CHAR **nameBufOut) + { +OBJECT_NAME nodeObjName; +OBJECT_NAME *objNames; +OBJECT_NAME *objNameDest; +_MVLU_RPT_DS_NODE_INFO *nodeInfoTbl; +MVL_VAR_ASSOC *nodeVa; +RUNTIME_TYPE *rt; +ST_INT numRt; +ST_INT i; +ST_RET rc; +ST_INT numNodeVar; +ST_INT numDsVar; +ST_INT nameSize; +ST_CHAR *nameBuf; +ST_CHAR *nameDest; + + nodeInfoTbl = (_MVLU_RPT_DS_NODE_INFO *) + M_CALLOC (MSMEM_GEN, numNodes, sizeof (_MVLU_RPT_DS_NODE_INFO)); + + numDsVar = 0; + nameSize = 0; + +/* Find each node VA */ + for (i = 0; i < numNodes; ++i) + { + nodeObjName.object_tag = DOM_SPEC; + nodeObjName.domain_id = domName; + nodeObjName.obj_name.item_id = nodeNames[i]; + + nodeVa = u_mvl_get_va_aa (&mvl_vmd, + MMSOP_MVLU_RPT_VA, + &nodeObjName, NULL, + SD_FALSE, NULL, NULL); + nodeInfoTbl[i].nodeVa = nodeVa; + if (nodeVa == NULL) + { + MVL_LOG_NERR1 ("Error: Report node %s not found", nodeNames[i]); + return (SD_FAILURE); + } + + rc = mvl_get_runtime (nodeVa->type_id, &rt, &numRt); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR0 ("Error: Runtime type not found"); + return (SD_FAILURE); + } + nodeInfoTbl[i].rt = rt; + nodeInfoTbl[i].numRt = numRt; + + numNodeVar = 0; + rc = _mvlu_count_rpt_var (rt, numRt, &numNodeVar, &nameSize); + if (rc != SD_SUCCESS) + return (SD_FAILURE); + + numDsVar += numNodeVar; + nodeInfoTbl[i].num_rpt_var = numNodeVar; + + /* the name buffer must add "base$" for each name */ + nameSize += (numDsVar * (strlen (nodeVa->name) + 1)); + } + + objNames = (OBJECT_NAME *) M_CALLOC (MSMEM_GEN, numDsVar, sizeof (OBJECT_NAME)); + nameBuf = M_CALLOC (MSMEM_GEN, 1, nameSize); + objNameDest = objNames; + nameDest = nameBuf; + for (i = 0; i < numNodes; ++i) + { + nodeVa = nodeInfoTbl[i].nodeVa; + rt = nodeInfoTbl[i].rt; + numRt = nodeInfoTbl[i].numRt; + rc = _mvlu_fill_rpt_var (nodeVa->name, domName, rt, numRt, + nodeInfoTbl[i].num_rpt_var, + objNameDest, &nameDest); + + objNameDest += nodeInfoTbl[i].num_rpt_var; + } + + *numObjNamesOut = numDsVar; + *objNameTblOut = objNames; + *nameBufOut = nameBuf; + + M_FREE (MSMEM_GEN, nodeInfoTbl); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _mvlu_count_rpt_var */ +/************************************************************************/ + +static ST_RET _mvlu_count_rpt_var (RUNTIME_TYPE *rt, ST_INT numRt, + ST_INT *numRptVarOut, ST_INT *nameSizeOut) + { +ST_INT numRptVar; +ST_INT nameSize; +RUNTIME_TYPE *lastRt; +ST_CHAR *comp_name; /* Component name */ + + if (numRt <= 2 || rt->el_tag != RT_STR_START) + { + MVL_LOG_NERR0 ("Error: Not structure, or no structure elements"); + return (SD_FAILURE); + } + + ++rt; + numRt -= 2; + lastRt = rt + numRt; + numRptVar = 0; + nameSize = 0; + while (rt <= lastRt) + { + switch (rt->el_tag) + { + case RT_STR_END : + case RT_ARR_END : + break; + + default: + ++numRptVar; + comp_name = ms_comp_name_find (rt); + if (strlen (comp_name) == 0) + { + MVL_LOG_ERR0 ("Error: unnamed structure component"); + return (SD_FAILURE); + } + nameSize += (strlen (comp_name) + 1); + break; + } + + if (rt->el_tag == RT_STR_START) + rt += rt->u.str.num_rt_blks + 1; /* Skip the structure contents */ + + if (rt->el_tag == RT_ARR_START) + rt += rt->u.arr.num_rt_blks; /* Skip the array contents */ + + ++rt; + } + + *numRptVarOut += numRptVar; + *nameSizeOut += nameSize; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _mvlu_fill_rpt_var */ +/************************************************************************/ + +static ST_RET _mvlu_fill_rpt_var (ST_CHAR *baseName, ST_CHAR *domName, + RUNTIME_TYPE *rt, ST_INT numRt, + ST_INT numObjNames, OBJECT_NAME *objNames, + ST_CHAR **nameBufPtr) + { +ST_INT dsDvCount; +RUNTIME_TYPE *lastRt; +ST_CHAR *nameBuf; +ST_CHAR *comp_name; /* Component name */ + + nameBuf = *nameBufPtr; + + ++rt; + numRt -= 2; + + dsDvCount = 0; + lastRt = rt + numRt; + while (rt <= lastRt) + { + switch (rt->el_tag) + { + case RT_STR_END : + case RT_ARR_END : + break; + + default: + comp_name = ms_comp_name_find (rt); + if (strlen (comp_name) == 0) + { + MVL_LOG_ERR0 ("Error: unnamed structure component"); + return (SD_FAILURE); + } + sprintf (nameBuf, "%s$%s", baseName, comp_name); + objNames[dsDvCount].object_tag = DOM_SPEC; + objNames[dsDvCount].domain_id = domName; + objNames[dsDvCount].obj_name.item_id = nameBuf; + ++dsDvCount; + nameBuf += (strlen (nameBuf) + 1); + break; + } + + if (rt->el_tag == RT_STR_START) + rt += rt->u.str.num_rt_blks + 1; /* Skip the structure contents */ + + if (rt->el_tag == RT_ARR_START) + rt += rt->u.arr.num_rt_blks; /* Skip the array contents */ + + ++rt; + } + + if (dsDvCount != numObjNames) + { + MVL_LOG_ERR0 ("Internal Error: dsDvCount misnatch"); + return (SD_FAILURE); + } + + *nameBufPtr = nameBuf; + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* REPORT CONTROL HANDLING */ +/************************************************************************/ +/************************************************************************/ +/* mvlu_create_rpt_ctrl */ +/************************************************************************/ +/* Create a UCA Report Control (use mvl61850_create_rpt_ctrl for 61850).*/ +/* This function creates a RPT NVL data structure and associated */ +/* control data to handle UCA report activity. */ + +/* Note that the 'dsNvl' can be created by 'mvlu_create_rpt_nvl', */ +/* created by 'u_mvl_get_nvl', or can be configured. The NVL */ +/* must be completely resolved; that is, all VA must have a valid data */ +/* pointer, name, and type_id. */ +/* NOTE: The args brcb_bufsize and ConfRev were added once for IEC 61850*/ +/* support, but now this function is ONLY for UCA, so they are ignored.*/ + +MVLU_RPT_CTRL *mvlu_create_rpt_ctrl (ST_CHAR *basrcbName, + MVL_NVLIST_CTRL *dsNvl, + MVL_VAR_ASSOC *base_va, + ST_INT rcb_type, + ST_INT buftim_action, + ST_INT brcb_bufsize, /* ignored */ + ST_UINT32 ConfRev) /* ignored */ + + { +MVLU_RPT_CTRL *rptCtrl; +MVL_NVLIST_CTRL *rptNvl; +RUNTIME_TYPE *incRt; +ST_RET rc; +ST_INT i; +ST_INT numDsVars; +ST_INT rptCtrlSize; +ST_INT inc_size; +RUNTIME_TYPE *rcbHead; +ST_INT numRt; + +/* This funct only works for UCA. For IEC 61850, call mvl61850_create_rpt_ctrl*/ + assert (rcb_type == RCB_TYPE_UCA); + +/* Find the runtime type of the RCB (saved later in rptCtrl). */ +/* If successful, this function sets "rcbHead" & "numRt". */ + if (mvlu_rpt_rcb_type_find (base_va->type_id, basrcbName, &rcbHead, &numRt)) + return (NULL); /* error already logged. */ + +/* Alloc report control large enough to contain the inclusion BS data */ +/* and reasons VA's (they depend on the number of VA in the report) */ + numDsVars = dsNvl->num_of_entries; + inc_size = BSTR_NUMBITS_TO_NUMBYTES(numDsVars); + rptCtrlSize = sizeof (MVLU_RPT_CTRL) + + strlen (basrcbName) + 1; + + rptCtrl = (MVLU_RPT_CTRL *) M_CALLOC (MSMEM_GEN, 1, rptCtrlSize); + +/* Set the variable size element pointers */ + rptCtrl->basrcb_name = (ST_CHAR *) (rptCtrl + 1); + strcpy (rptCtrl->basrcb_name, basrcbName); + +/* Initialize the Report Control data elements */ + rptCtrl->dsNvl = dsNvl; + rptCtrl->base_va = base_va; + rptCtrl->rcbRtHead = rcbHead; + +/* If domname + '/' + basrcb_name will fit in RptID, then write it. */ + if (strlen (dsNvl->nvl_scope.dom->name) + strlen (rptCtrl->basrcb_name) + 1 + < sizeof (rptCtrl->common_basrcb.RptID)) + { + sprintf (rptCtrl->common_basrcb.RptID, "%s/%s", + dsNvl->nvl_scope.dom->name, + rptCtrl->basrcb_name); + if (rcb_type == RCB_TYPE_UCA) + { /* replace $ with '.'. Only for UCA. */ + for (i = 0; i < (ST_INT) strlen (rptCtrl->common_basrcb.RptID); ++i) + { + if (rptCtrl->common_basrcb.RptID[i] == '$') + rptCtrl->common_basrcb.RptID[i] = '.'; + } + } + } + else + { + MVL_LOG_ERR0 ("mvlu_create_rpt_ctrl RptID too long"); + M_FREE (MSMEM_GEN, rptCtrl); + return (NULL); + } + + rptCtrl->rcb_type = rcb_type; + rptCtrl->buftim_action = buftim_action; + if (mvlu_rpt_find_typeids (&rptCtrl->rpt_typeids)) + { + MVL_LOG_ERR0 ("mvlu_create_rpt_ctrl error finding base types"); + M_FREE (MSMEM_GEN, rptCtrl); + return (NULL); + } + +/* Create the RPT NVL control element, used to send the actual reports */ + rptNvl = &rptCtrl->rptNvl; + rptNvl->name = "RPT"; + +/* Alloc the entries table; allow for RptID, OptFlds, SqNum, RptTim, */ +/* OutDat (61850 calls it DatSetName), BufOvfl, EntryID, ConfRev, */ +/* SubSeqNum, MoreSegmentsFollow, & InclusionBitstring plus ARRAYS of */ +/* dataRefs, values, and Reasons. */ +/* "assert" later if "maxNumRptVars" exceeded. */ +/* Allow (3 * numDsVars) to handle arrays of dataRef, value, and reason.*/ + rptCtrl->maxNumRptVars = MVLU_MAX_RPT_OPTS + (3 * numDsVars); + + rptNvl->entries = (MVL_VAR_ASSOC **) M_CALLOC (MSMEM_GEN, rptCtrl->maxNumRptVars, + sizeof (MVL_VAR_ASSOC *)); + + /* NOTE: The "rptNvl->entries" array is not filled in and + * and "rptNvl->num_of_entries" is not set + * until a Report is being built. + */ + + /* We need to create a Runtime Type for the inclusion bitstring */ + incRt = &rptCtrl->incRt; + incRt->el_tag = RT_BIT_STRING; + incRt->el_size = BSTR_NUMBITS_TO_NUMBYTES(numDsVars); + incRt->offset_to_last = incRt->el_size; + incRt->u.p.el_len = (ST_RTINT) numDsVars; + rc = mvlu_add_rt_type (&rptCtrl->incRt, 1, &rptCtrl->inclusion_typeid); + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR0 ("Error - could not add temp RT type"); + M_FREE (MSMEM_GEN, rptCtrl); + return (NULL); + } + +/* That's all we can do ahead of time for the RPT variable associations */ + +/* Set a bit of the data for the common BASRCB */ + sprintf (rptCtrl->common_basrcb.DatSetNa, "%s/%s", + dsNvl->nvl_scope.dom->name, dsNvl->name); + + if (rcb_type == RCB_TYPE_UCA) + { + rptCtrl->common_basrcb.OptFlds.len_1 = 8; + rptCtrl->common_basrcb.TrgOps.len = 8; + } + else + { + rptCtrl->common_basrcb.OptFlds.len_1 = 10; + rptCtrl->common_basrcb.TrgOps.len = 6; + } + + rptCtrl->common_basrcb.TrgOps.data[0] = MVLU_TRGOPS_DATA; + +/* Put it on the list */ + list_add_last((ST_VOID **) &mvlu_rpt_ctrl_list, (ST_VOID *) rptCtrl); + return (rptCtrl); + } + +/************************************************************************/ +/* mvlu_free_rpt_ctrl */ +/************************************************************************/ +/* This function is used to free a MVLU_RPT_CTRL allocated by */ +/* 'mvlu_create_rpt_ctrl' */ + +ST_VOID mvlu_free_rpt_ctrl (MVLU_RPT_CTRL *rptCtrl) + { +MVLU_RPT_CLIENT *rptClient; + +/* This funct only works for UCA. For IEC 61850, call mvl61850_free_rpt_ctrl*/ + assert (rptCtrl->rcb_type == RCB_TYPE_UCA); + +/* Take it off the report control list */ + list_unlink ((ST_VOID **) &mvlu_rpt_ctrl_list, (ST_VOID *) rptCtrl); + +/* Free up the dynamic type used for the inclusion bitstring type */ + mvlu_free_rt_type (rptCtrl->inclusion_typeid); + +/* Destroy all clients for this rptCtrl */ +/* NOTE: list_get_first removes the entry from the linked list. */ + while ((rptClient = (MVLU_RPT_CLIENT *) list_get_first (&rptCtrl->rpt_client_list))!=NULL) + _mvlu_free_rpt_client (rptClient); /* free client */ + +/* Now the rest of the report control */ + M_FREE (MSMEM_GEN, rptCtrl->rptNvl.entries); + M_FREE (MSMEM_GEN, rptCtrl); + } + +/************************************************************************/ +/************************************************************************/ +/* REPORT CONTROL SERVICING */ +/************************************************************************/ +/************************************************************************/ +/* mvlu_rpt_service */ +/************************************************************************/ + +ST_VOID mvlu_rpt_service () + { +MVLU_RPT_CTRL *rptCtrl; +MVLU_RPT_CLIENT *rptClient; +ST_DOUBLE timeNow; + +/* Do Report VA Scans */ + mvlu_rpt_va_scan (); + +/* See if it is time to send reports */ + timeNow = sGetMsTime (); + for (rptCtrl = mvlu_rpt_ctrl_list; + rptCtrl != NULL; + rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvlu_rpt_ctrl_list, rptCtrl)) + { + assert (rptCtrl->rcb_type == RCB_TYPE_UCA); /* must be UCA URCB*/ + /* Loop through linked list of clients for UCA.*/ + for (rptClient = rptCtrl->rpt_client_list; + rptClient != NULL; + rptClient = (MVLU_RPT_CLIENT *) list_get_next (rptCtrl->rpt_client_list, rptClient)) + { + _mvlu_rpt_client_service (rptClient, timeNow); + } + } + } + +/************************************************************************/ +/* mvlu_rpt_va_scan */ +/************************************************************************/ + +ST_VOID mvlu_rpt_va_scan () + { +MVLU_RPT_SCAN_CTRL *scanCtrl; +ST_DOUBLE timeNow; + + timeNow = sGetMsTime (); + scanCtrl = mvlu_rpt_scan_list; + while (scanCtrl != NULL) /* look through whole list */ + { + if (scanCtrl->enable == SD_TRUE) + { + if (timeNow >= scanCtrl->next_scan_start) + { + if (scanCtrl->num_va_read_pend == 0) + { + scanCtrl->next_scan_start += scanCtrl->scan_period; + mvlu_rpt_scan_read (scanCtrl); + } + else + scanCtrl->saturated = SD_TRUE; + } + } + scanCtrl = (MVLU_RPT_SCAN_CTRL *) list_get_next (mvlu_rpt_scan_list, scanCtrl); + } + } + +/************************************************************************/ +/* mvlu_rpt_scan_read */ +/************************************************************************/ + +ST_VOID mvlu_rpt_scan_read (MVLU_RPT_SCAN_CTRL *scanCtrl) + { +MVLAS_READ_CTRL *rdCtrl; +MVLAS_RD_VA_CTRL *vaCtrl; +MVL_IND_PEND *indCtrl; +ST_INT i; + + if (scanCtrl->num_va_read_pend == 0) + { + scanCtrl->num_va_read_pend = scanCtrl->num_scan_va; + scanCtrl->num_va_changes = 0; + + indCtrl = &scanCtrl->indCtrl; + rdCtrl = &indCtrl->u.rd; + rdCtrl->numVar = 0; + vaCtrl = rdCtrl->vaCtrlTbl; + + for (i = 0; i < scanCtrl->num_scan_va; ++i) + { + vaCtrl->va = scanCtrl->scan_va[i]; + memcpy (&vaCtrl->va_scope, &scanCtrl->scan_va_scope[i], sizeof(MVL_SCOPE)); + ++vaCtrl; + ++rdCtrl->numVar; + } + + /* OK, now fire off the read indication functions */ + /* (*u_mvlu_report_reads_done_fun) will be invoked when all are ready */ + u_mvl_read_ind (indCtrl); + } + else + scanCtrl->saturated = SD_TRUE; + } + +/************************************************************************/ +/* _mvlu_rpt_va_reads_done */ +/************************************************************************/ +/* This function is called by 'mvlu_rd_prim_done' when all primitive */ +/* read indication functions for a VA have been completed. This means */ +/* that the data is ready to be sent for this VA. */ + +static ST_VOID _mvlu_rpt_va_reads_done (MVL_IND_PEND *indCtrl, + MVL_VAR_ASSOC *va) + { +MVLU_RPT_SCAN_CTRL *scanCtrl; +ST_INT data_size; + +/* Do some housekeeping */ + scanCtrl = (MVLU_RPT_SCAN_CTRL *) indCtrl->usr_ind_ctrl; + --scanCtrl->num_va_read_pend; + +/* Let's see if the data has changed */ + data_size = mvl_type_ctrl[va->type_id].data_size; + if (memcmp (va->last_data, va->data, data_size) != 0) + { + MVLU_LOG_FLOW1 ("Report VA Scan detected change for rpt VA '%s'", + va->name); + mvlu_rpt_va_change (va, MVLU_TRGOPS_DATA, NULL); + ++scanCtrl->num_va_changes; + } + } + +/************************************************************************/ +/* _mvlu_rpt_client_service */ +/************************************************************************/ + +static ST_VOID _mvlu_rpt_client_service (MVLU_RPT_CLIENT *rptClient, + ST_DOUBLE timeNow) + { +MVLU_RPT_CTRL *rptCtrl; +MVLU_BASRCB *basrcb; +MVL_NVLIST_CTRL *dsNvl; +ST_RET rc; +ST_BOOLEAN sendRbe; +ST_INT incSize; + + basrcb = &rptClient->basrcb; + +/* Let's see if the report is enabled */ + if (basrcb->RptEna == SD_FALSE) /* treat any non-zero as TRUE */ + return; + +/* Make sure we can send one if we want to ... */ + if (a_buffers_avail (rptClient->netInfo->acse_conn_id) <= 0) + return; + +/* Reporting is enabled, let's see if it is time to send the report */ + rptCtrl = rptClient->rpt_ctrl; + dsNvl = rptCtrl->dsNvl; + incSize = BSTR_NUMBITS_TO_NUMBYTES(dsNvl->num_of_entries); + +/* First, see if Integrity scan is enabled, and if so if time to send */ +/* This function checks time & if necessary, starts integrity scan. */ + mvlu_integrity_timeout (rptClient, timeNow); + +/* Check for RBE enable */ +/* NOTE: numTrgs ONLY incremented if changes matched the TrgOps */ +/* for this client. See mvlu_rpt_va_change. */ + if (rptClient->numTrgs > 0) + { + /* RBE is enabled, see if a RBE Period is selected ... */ + if (basrcb->RBEPd != 0) + { + if (timeNow > rptClient->next_rbe_rpt_time) + { + /* OK, send the report! */ + MVLU_LOG_FLOW1 ("UCA Report RBE Period timeout for client %08lx", + rptClient); + rc = mvlu_send_report (rptClient, MVLU_RPT_TYPE_RBE); + + rptClient->next_rbe_rpt_time = timeNow + (ST_DOUBLE) basrcb->RBEPd; + return; + } + } + else /* NO RBE Period is selected, send right away, subject */ + { /* to BufTime and Trgs parameters */ + + /* If neither constraint is in place, send immediately, otherwise */ + /* we must exceed one or both constraints before sending */ + + if (basrcb->Trgs == 0 && basrcb->BufTim == 0) + sendRbe = SD_TRUE; + else + sendRbe = SD_FALSE; + + if (basrcb->Trgs != 0) + { + if (rptClient->numTrgs >= basrcb->Trgs) + sendRbe = SD_TRUE; + } + if (basrcb->BufTim != 0) + { + if (timeNow > rptClient->buf_time_done) + sendRbe = SD_TRUE; + } + + /* OK, send the report! */ + if (sendRbe == SD_TRUE) + { + MVLU_LOG_FLOW1 ("UCA Report RBE for client %08lx", rptClient); + rc = mvlu_send_report (rptClient, MVLU_RPT_TYPE_RBE); + return; + } + } + } + } + +/************************************************************************/ +/************************************************************************/ +/* mvlu_rpt_va_change */ +/* CRITICAL: this function does not save the data in "va->data" until */ +/* the very end, because depending on RCB state, it may first need to */ +/* send a report with the previous data (see _mvlu_rpt_va_chk_reason). */ +/************************************************************************/ + +ST_VOID mvlu_rpt_va_change (MVL_VAR_ASSOC *va, ST_UCHAR reason, + ST_VOID *new_data) + { +MVLU_RPT_CTRL *rptCtrl; +MVLU_RPT_CLIENT *rptClient; +ST_INT va_index; +ST_INT data_size; + + MVLU_LOG_FLOW2 ("Report VA '%s' change, reason=0x%02X", va->name, reason); + + data_size = mvl_type_ctrl[va->type_id].data_size; + + /* If reason is Integrity or GI, do nothing (handled elsewhere). */ + if ((reason & (MVLU_TRGOPS_INTEGRITY | MVLU_TRGOPS_GI)) != 0) + return; + + /* Check all UCA RCBs. */ + for (rptCtrl = mvlu_rpt_ctrl_list; + rptCtrl != NULL; + rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvlu_rpt_ctrl_list, rptCtrl)) + { /* see if someone is interested */ + assert (rptCtrl->rcb_type == RCB_TYPE_UCA); /* this loop only for UCA*/ + va_index = mvlu_rpt_get_va_index (rptCtrl, va); + if (va_index >= 0) + { + MVLU_LOG_CFLOW1 ("VA is member of report NVL '%s'", rptCtrl->dsNvl->name); + for (rptClient = rptCtrl->rpt_client_list; + rptClient != NULL; + rptClient = (MVLU_RPT_CLIENT *) list_get_next (rptCtrl->rpt_client_list, rptClient)) + { + /* If enabled, chk "reason" (i.e. compare to TrgOps, etc.)*/ + if (rptClient->basrcb.RptEna) + { + _mvlu_rpt_va_chk_reason (rptClient, va, va_index, reason); + } + else + MVLU_LOG_CFLOW0 ("VA change ignored: Report not enabled"); + } + } + } + + /* Check all IEC 61850 RCBs. */ + for (rptCtrl = mvl61850_rpt_ctrl_list; + rptCtrl != NULL; + rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvl61850_rpt_ctrl_list, rptCtrl)) + { /* see if someone is interested */ + assert (rptCtrl->rcb_type != RCB_TYPE_UCA); /* this loop only for 61850*/ + va_index = mvlu_rpt_get_va_index (rptCtrl, va); + if (va_index >= 0) + { + MVLU_LOG_CFLOW1 ("VA is member of report NVL '%s'", rptCtrl->dsNvl->name); + rptClient = &rptCtrl->only_client; /* only one client */ + /* If enabled, or this is IEC BRCB & it was enabled ONCE, chk "reason".*/ + if (rptClient->basrcb.RptEna + || (rptCtrl->rcb_type == RCB_TYPE_IEC_BRCB + && rptCtrl->brcbCtrl.enabled_once)) + { + _mvlu_rpt_va_chk_reason (rptClient, va, va_index, reason); + } + else + MVLU_LOG_CFLOW0 ("VA change ignored: Report not enabled"); + } + } + +/* If the user is passing us the data, need to save it ... */ + if (new_data != NULL) + { + MVLU_LOG_CFLOW0 ("Saving report VA data"); + memcpy (va->data, new_data, data_size); + } + +/* Now copy the data into the buffer chain */ +/* NOTE: Multiple datasets may reference the same variable, but each */ +/* creates its own "va", so each gets its own copy of "last_data". */ + memcpy (va->last_data, va->data, data_size); /* save data for next compare */ + } + +/************************************************************************/ +/* _mvlu_rpt_va_chk_reason */ +/************************************************************************/ +static ST_VOID _mvlu_rpt_va_chk_reason (MVLU_RPT_CLIENT *rptClient, + MVL_VAR_ASSOC *va, + ST_INT va_index, + ST_UCHAR reason) + { +ST_INT data_size; +ST_VOID *new_data; /* temp copy of new data while sending old data*/ + + if ((reason & (MVLU_TRGOPS_DATA | MVLU_TRGOPS_QUALITY | MVLU_TRGOPS_FREEZE)) != 0) + { + /* If this "reason" is enabled in TrgOps, process it. */ + if ((rptClient->basrcb.TrgOps.data[0] & reason) != 0) + { + if (rptClient->basrcb.BufTim != 0) + { + /* If this is first change for "ANY" VA, start BufTim timer. */ + if (rptClient->numTrgs == 0) + { /* First va change. Start BufTim timer. */ + rptClient->buf_time_done = sGetMsTime () + + (ST_DOUBLE) rptClient->basrcb.BufTim; + MVLU_LOG_CFLOW1 ("Setting buffer Time Done = %06.3fs", + rptClient->buf_time_done/1000); + } + + /* If change already detected for "THIS" VA & buftim_action = SEND_NOW, send report.*/ + if (BSTR_BIT_GET (rptClient->changed_flags, va_index) + && rptClient->rpt_ctrl->buftim_action == MVLU_RPT_BUFTIM_SEND_NOW) + { + /* Send report now with last data, then process new data.*/ + /* Report is built using "va->data", so must copy old data */ + /* to "va->data" until after first rpt built. */ + data_size = mvl_type_ctrl[va->type_id].data_size; + new_data = chk_malloc (data_size); /* alloc buf to save new data*/ + memcpy (new_data, va->data, data_size); /* save new data */ + memcpy (va->data, va->last_data, data_size); /* restore old data*/ + + MVLU_LOG_CFLOW0 ("Second change for this VA before BufTim. Sending Report with first change. Restarting BufTim."); + /* send or queue rpt */ + mvlu_rpt_ready (rptClient, MVLU_RPT_TYPE_RBE); + rptClient->buf_time_done = sGetMsTime () + + (ST_DOUBLE) rptClient->basrcb.BufTim; + + /* Put back new data in "va->data". */ + memcpy (va->data, new_data, data_size); /* restore new data */ + chk_free (new_data); + } + } /* end "if (..BufTim != 0)" */ + + /* Set numTrgs, changed_flags, reasons_data */ + ++rptClient->numTrgs; + MVLU_LOG_CFLOW1 ("Number Triggers is now %d", (int) rptClient->numTrgs); + BSTR_BIT_SET_ON (rptClient->changed_flags, va_index); + rptClient->reasons_data[va_index] = reason; + } /* end "if client TrgOps matches reason" */ + else + MVLU_LOG_CFLOW0 ("VA change ignored: Reason doesn't match TrgOps"); + } + else if ((reason & (MVLU_TRGOPS_INTEGRITY | MVLU_TRGOPS_GI)) != 0) + { + assert (0); /* Should never get here (see mvlu_rpt_va_change). */ + } + else + { + assert (0); /* Unrecognized TRGOPS. */ + } + } + +/************************************************************************/ +/* mvlu_rpt_get_va_index */ +/************************************************************************/ +/* Given a MVL report control and an associated VA, find the index of */ +/* the Va. This index is then used for manipulating the inclusion bits, */ +/* read bits, and reason codes. */ + +ST_INT mvlu_rpt_get_va_index (MVLU_RPT_CTRL *rptCtrl, MVL_VAR_ASSOC *va) + { +ST_INT i; +MVL_NVLIST_CTRL *dsNvl; + + dsNvl = rptCtrl->dsNvl; + + if (dsNvl!=NULL) /* NOTE: dsNvl may be NULL */ + { + for (i = 0; i < dsNvl->num_of_entries; ++i) + { + if (dsNvl->entries[i] == va) + { + return (i); + } + } + } + return (-1); + } + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* SENDING REPORTS */ +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* mvlu_send_report */ +/************************************************************************/ + +ST_RET mvlu_send_report (MVLU_RPT_CLIENT *rptClient, ST_INT rpt_type) + { +MVLU_RPT_CTRL *rptCtrl; +MVL_NET_INFO *netInfo; +MVL_NVLIST_CTRL *dsNvl; +MVL_NVLIST_CTRL *rptNvl; +MVL_VAR_ASSOC *va; +ST_INT i; +ST_RET rc; +ST_INT sendIndex = 0; +ST_INT sendIndexSave; /* save index before data, compare after data */ +ST_UINT8 optFld; +MVLU_BASRCB *basrcb; +ST_INT incSize; /* num bytes for inclusion bitstring */ +MVL_VAR_ASSOC *tmp_va_arr; /* alloc array of structs */ +ST_INT tmp_va_arr_size; /* num of entries in tmp_va_arr */ +MVL_VAR_ASSOC *tmp_va; /* current entry in tmp_va_arr */ +MMS_BTIME6 TimeOfEntry; /* Time this report generated. */ + + rptCtrl = rptClient->rpt_ctrl; + netInfo = rptClient->netInfo; + basrcb = &rptClient->basrcb; + + optFld = basrcb->OptFlds.data_1[0]; + dsNvl = rptCtrl->dsNvl; + rptNvl = &rptCtrl->rptNvl; + + incSize = BSTR_NUMBITS_TO_NUMBYTES(dsNvl->num_of_entries); + + MVLU_LOG_FLOW1 ("Sending UCA Report, MVL_NET_INFO %08lx", rptClient->netInfo); + + /* Need tmp va's for options plus array of reasons_data. */ + tmp_va_arr_size = MVLU_MAX_RPT_OPTS + dsNvl->num_of_entries; + tmp_va_arr = M_CALLOC (MSMEM_GEN, sizeof (MVL_VAR_ASSOC), tmp_va_arr_size); + tmp_va = tmp_va_arr; /* start out pointing to first entry */ + +/* Prepares a UCA Report NVL to be sent, based on the */ +/* options, data, and inclusion bitstring in the rptCtrl. After this */ +/* function completes, the rptCtrl->rptNvl is ready to be sent. */ + +/* If this is Integrity report, just set all inclusion bits. */ + if (rpt_type == MVLU_RPT_TYPE_INTEGRITY_OR_GI) + memset (rptClient->changed_flags, 0xff, incSize); + +/* We will create a NVL to send, using the dsNvl as a model ... */ + + /* RptID and OptFlds are always the first 2 entries in the Rpt NVL. */ + tmp_va->type_id = rptCtrl->rpt_typeids.vstring32; + tmp_va->data = basrcb->RptID; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + MVLU_LOG_CFLOW1 (" RptID='%s", basrcb->RptID); + + tmp_va->type_id = rptCtrl->rpt_typeids.bvstring8; + tmp_va->data = &basrcb->OptFlds; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + MVLU_LOG_CFLOW1 (" OptFld = 0x%02x", (int) optFld); + + if (optFld & MVLU_SQNUM_MASK) + { + tmp_va->type_id = rptCtrl->rpt_typeids.int8u; + tmp_va->data = &basrcb->SqNum; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + MVLU_LOG_CFLOW1 (" SqNum : %u", (unsigned) basrcb->SqNum); + } + if (optFld & MVLU_RPTTIM_MASK) + { + /* Call user function to get report time. */ + u_mvlu_rpt_time_get (&TimeOfEntry); + + MVLU_LOG_CFLOW2 (" RptTim : %lums, %lu days", + TimeOfEntry.ms, TimeOfEntry.day); + + tmp_va->type_id = rptCtrl->rpt_typeids.btime6; + tmp_va->data = &TimeOfEntry; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + if (optFld & MVLU_OUTDAT_MASK) + { + /* OutDat is same as DatSetNa */ + MVLU_LOG_CFLOW1 (" OutDat : %s", basrcb->DatSetNa); + tmp_va->type_id = rptCtrl->rpt_typeids.vstring65; /* Obj Ref */ + tmp_va->data = basrcb->DatSetNa; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + + /* Add inclusion bitstring. */ + tmp_va->type_id = rptCtrl->inclusion_typeid; + tmp_va->data = rptClient->changed_flags; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + +/* Now go through the inclusion bitstring and figure out what to send */ + sendIndexSave = sendIndex; /* save index before data included */ + for (i = 0; i < dsNvl->num_of_entries; ++i) + { + if (BSTR_BIT_GET (rptClient->changed_flags, i)) + { + va = dsNvl->entries[i]; + MVLU_LOG_CFLOW3 (" Including variable %d ('%s'), reason=0x%02X", + i, va->name, rptClient->reasons_data[i]); + rptNvl->entries[sendIndex++] = va; + + /* va->data already points to latest data. Done with this va. */ + } + } + assert (sendIndex>sendIndexSave); /* make sure SOME data included */ + + if (optFld & MVLU_REASONS_MASK) + { + for (i = 0; i < dsNvl->num_of_entries; ++i) + { + if (BSTR_BIT_GET (rptClient->changed_flags, i)) + { + /* Don't need BVSTR here, because size is fixed. */ + tmp_va->type_id = rptCtrl->rpt_typeids.bstr8; + tmp_va->data = &rptClient->reasons_data[i]; + rptNvl->entries[sendIndex++] = tmp_va++; /* set entry & point to next*/ + } + } + } + rptNvl->num_of_entries = sendIndex; + assert (rptNvl->num_of_entries <= rptCtrl->maxNumRptVars); /* past end of array?*/ + assert ((tmp_va-tmp_va_arr) <= tmp_va_arr_size); /* past end of array?*/ + + rc = mvl_info_variables (rptClient->netInfo, &rptClient->rpt_ctrl->rptNvl, SD_FALSE); + + basrcb->SqNum++; /* Increment seq number for next rpt. */ + + /* Reset reasons, etc. to prepare for new report triggers. */ + memset (rptClient->reasons_data, 0, dsNvl->num_of_entries); + memset (rptClient->changed_flags, 0, incSize); + rptClient->numTrgs = 0; + M_FREE (MSMEM_GEN, tmp_va_arr); + return (rc); + } + +/************************************************************************/ +/************************************************************************/ +/* _mvlu_rpt_disconnect_rcvd */ +/************************************************************************/ + +ST_VOID _mvlu_rpt_disconnect_rcvd (MVL_NET_INFO *netInfo) + { +MVLU_RPT_CTRL *rptCtrl; +MVLU_RPT_CLIENT *rptClient; + + /* Loop through list of UCA RCBs. */ + for (rptCtrl = mvlu_rpt_ctrl_list; + rptCtrl != NULL; + rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvlu_rpt_ctrl_list, rptCtrl)) + { + assert (rptCtrl->rcb_type == RCB_TYPE_UCA); + /* Loop through list of clients. */ + for (rptClient = rptCtrl->rpt_client_list; + rptClient != NULL; + rptClient = (MVLU_RPT_CLIENT *) list_get_next (rptCtrl->rpt_client_list, rptClient)) + { + if (rptClient->netInfo == netInfo) + { + list_unlink ((ST_VOID **) &rptCtrl->rpt_client_list, (ST_VOID *) rptClient); + _mvlu_free_rpt_client (rptClient); + break; /* one client per connection */ + } + } + } + + /* Loop through list of IEC 61850 RCBs (URCB or BRCB). */ + for (rptCtrl = mvl61850_rpt_ctrl_list; + rptCtrl != NULL; + rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvl61850_rpt_ctrl_list, rptCtrl)) + { + assert (rptCtrl->rcb_type != RCB_TYPE_UCA); + rptClient = &rptCtrl->only_client; /* only one client */ + if (rptClient->netInfo == netInfo) + { /* Reset RCB parameters. */ + rptClient->netInfo = NULL; + rptClient->basrcb.RptEna = SD_FALSE; + rptClient->basrcb.Resv = SD_FALSE; /* Ignored for BRCB */ + /* If RCB DatSet is AA_SPEC, remove it (i.e. cleanup & set DatSet=""). */ + if (rptCtrl->dsNvl != NULL && rptCtrl->dsNvl->nvl_scope.scope == AA_SPEC) + mvl61850_rpt_dataset_destroy (rptCtrl); + } + } + } + +/************************************************************************/ +/************************************************************************/ +/* MVLU REPORT SCAN CONTROL */ +/************************************************************************/ +/************************************************************************/ +/* mvlu_rpt_create_scan_ctrl2 */ +/* DEBUG: pass "enable" as additional arg? */ +/* DEBUG: delete older "mvlu_rpt_create_scan_ctrl" function? */ +/************************************************************************/ + +MVLU_RPT_SCAN_CTRL *mvlu_rpt_create_scan_ctrl2 ( + MVL_NVLIST_CTRL *nvl, + ST_RET (*scan_done_fun) (struct mvl_ind_pend *ind_pend), + ST_UINT report_scan_rate) /* report scan rate (millisec) */ + { +MVLU_RPT_SCAN_CTRL *scanCtrl; +ST_INT scanCtrlSize; +ST_INT numScanVa = nvl->num_of_entries; +ST_INT j; + + scanCtrlSize = sizeof (MVLU_RPT_SCAN_CTRL) + + (numScanVa * sizeof (MVLAS_RD_VA_CTRL)) + + (numScanVa * sizeof (MVL_SCOPE)) + + (numScanVa * sizeof (MVL_VAR_ASSOC *)); + + scanCtrl = (MVLU_RPT_SCAN_CTRL *) M_CALLOC (MSMEM_GEN, 1, scanCtrlSize); + scanCtrl->scan_va = (MVL_VAR_ASSOC **) (scanCtrl + 1); + scanCtrl->num_scan_va = numScanVa; + /* Point after array of (MVL_VAR_ASSOC *) */ + scanCtrl->scan_va_scope = (MVL_SCOPE *) (scanCtrl->scan_va + numScanVa); + + scanCtrl->indCtrl.event = &scanCtrl->commEvent; + scanCtrl->commEvent.event_type = MVLU_RPT_COMM_EVENT; + scanCtrl->indCtrl.op = MMSOP_MVLU_RPT_VA; + /* Point after array of (MVL_SCOPE) */ + scanCtrl->indCtrl.u.rd.vaCtrlTbl = + (MVLAS_RD_VA_CTRL *) (scanCtrl->scan_va_scope + numScanVa); + + scanCtrl->indCtrl.scan_va_done_fun = _mvlu_rpt_va_reads_done; + + scanCtrl->indCtrl.usr_ind_ctrl = scanCtrl; + + /* Fill in other structure elements from args passed. */ + for (j = 0; j < nvl->num_of_entries; ++j) + scanCtrl->scan_va[j]= nvl->entries[j]; + memcpy (scanCtrl->scan_va_scope, nvl->va_scope, + nvl->num_of_entries * sizeof (MVL_SCOPE)); + scanCtrl->enable = SD_TRUE; /* ALWAYS enable */ + /* Optional user function to be called when each scan completes. */ + scanCtrl->indCtrl.usr_resp_fun = scan_done_fun; + scanCtrl->scan_period = (ST_DOUBLE) report_scan_rate; + + list_add_last((ST_VOID **) &mvlu_rpt_scan_list, (ST_VOID *) scanCtrl); + return (scanCtrl); + } + +/************************************************************************/ +/* mvlu_rpt_create_scan_ctrl */ +/************************************************************************/ + +MVLU_RPT_SCAN_CTRL *mvlu_rpt_create_scan_ctrl (ST_INT numScanVa) + { +MVLU_RPT_SCAN_CTRL *scanCtrl; +ST_INT scanCtrlSize; + + scanCtrlSize = sizeof (MVLU_RPT_SCAN_CTRL) + + (numScanVa * sizeof (MVLAS_RD_VA_CTRL)) + + (numScanVa * sizeof (MVL_SCOPE)) + + (numScanVa * sizeof (MVL_VAR_ASSOC *)); + + scanCtrl = (MVLU_RPT_SCAN_CTRL *) M_CALLOC (MSMEM_GEN, 1, scanCtrlSize); + scanCtrl->scan_va = (MVL_VAR_ASSOC **) (scanCtrl + 1); + scanCtrl->num_scan_va = numScanVa; + /* Point after array of (MVL_VAR_ASSOC *) */ + scanCtrl->scan_va_scope = (MVL_SCOPE *) (scanCtrl->scan_va + numScanVa); + + scanCtrl->indCtrl.event = &scanCtrl->commEvent; + scanCtrl->commEvent.event_type = MVLU_RPT_COMM_EVENT; + scanCtrl->indCtrl.op = MMSOP_MVLU_RPT_VA; + /* Point after array of (MVL_SCOPE) */ + scanCtrl->indCtrl.u.rd.vaCtrlTbl = + (MVLAS_RD_VA_CTRL *) (scanCtrl->scan_va_scope + numScanVa); + + scanCtrl->indCtrl.scan_va_done_fun = _mvlu_rpt_va_reads_done; + + scanCtrl->indCtrl.usr_ind_ctrl = scanCtrl; + scanCtrl->scan_period = 10000; /* Default to 10 second scan period*/ + + list_add_last((ST_VOID **) &mvlu_rpt_scan_list, (ST_VOID *) scanCtrl); + return (scanCtrl); + } +/************************************************************************/ +/* mvlu_rpt_destroy_scan_ctrl */ +/* This function destroys a MVLU_RPT_SCAN_CTRL created by */ +/* 'mvlu_rpt_create_scan_ctrl' */ +/************************************************************************/ +ST_VOID mvlu_rpt_destroy_scan_ctrl (MVLU_RPT_SCAN_CTRL *scanCtrl) + { + /* Take it off the scan control list */ + list_unlink ((ST_VOID **) &mvlu_rpt_scan_list, (ST_VOID *) scanCtrl); + M_FREE (MSMEM_GEN, scanCtrl); + } + + +/************************************************************************/ +/************************************************************************/ +/* BASRCB READ/WRITE HANDLERS */ +/************************************************************************/ + +/************************************************************************/ +/* _mvlu_get_rcb */ +/************************************************************************/ + +static ST_VOID _mvlu_get_rcb (MVL_VAR_ASSOC *baseVa, + RUNTIME_TYPE *rt, + MVL_NET_INFO *netInfo, + MVLU_RPT_CTRL **rptCtrlOut, + MVLU_RPT_CLIENT **rptClientOut) + { +MVLU_RPT_CTRL *rptCtrl; +MVLU_RPT_CLIENT *rptClient; + + *rptCtrlOut = NULL; + *rptClientOut = NULL; + + /* Find the associated Report Control, using this RT as a key */ + rptCtrl = mvlu_rpt_ctrl_list; + while (rptCtrl != NULL) /* look through whole list */ + { + if (rptCtrl->base_va == baseVa && + (rt > rptCtrl->rcbRtHead) && + (rt <= rptCtrl->rcbRtHead + rptCtrl->rcbRtHead->u.str.num_rt_blks)) + { + *rptCtrlOut = rptCtrl; + break; + } + rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvlu_rpt_ctrl_list, rptCtrl); + } + if (*rptCtrlOut == NULL) + { + MVL_LOG_NERR0 ("Warning: could not find report control"); + return; + } + + /* Report Control found. */ + assert (rptCtrl->rcb_type == RCB_TYPE_UCA); /* must be UCA URCB*/ + + /* Now see if this connection has an active client */ + rptClient = rptCtrl->rpt_client_list; + while (rptClient != NULL) /* look through whole list */ + { + if (rptClient->netInfo == netInfo) + break; /* return a pointer to it */ + + rptClient = (MVLU_RPT_CLIENT *) list_get_next (rptCtrl->rpt_client_list, rptClient); + } + *rptClientOut = rptClient; + } + + +/************************************************************************/ +/* _mvlu_get_rd_rcb */ +/* NOTE: Caller can access MVLU_RPT_CTRL, if needed, by using "rpt_ctrl"*/ +/* member of MVLU_RPT_CLIENT. */ +/************************************************************************/ +MVLU_BASRCB *_mvlu_get_rd_rcb (MVLU_RD_VA_CTRL *mvluRdVaCtrl, + MVLU_RPT_CLIENT **rptClientOut) + { +MVLU_RPT_CTRL *rptCtrl; +MVLU_RPT_CLIENT *rptClient; +MVLU_BASRCB *rcb; + + /* Try to find 61850 RCB first. If found, return it. */ + if ((rcb = mvl61850_get_rcb (mvluRdVaCtrl->rdVaCtrl->va->base_va, + mvluRdVaCtrl->rt, + rptClientOut)) != NULL) + return (rcb); + + /* Could not find 61850 RCB, so now try to find UCA RCB. */ + + /* NOTE: Need net_info to find correct UCA RCB, so if it's not */ + /* known, give up now. This problem can occur if user includes*/ + /* RCB element in a Report DataSet (not supported for UCA). */ + if (mvluRdVaCtrl->indCtrl->event == NULL || + mvluRdVaCtrl->indCtrl->event->net_info == NULL) + return (NULL); /* don't know the connection, so can't find UCA RCB.*/ + + _mvlu_get_rcb (mvluRdVaCtrl->rdVaCtrl->va->base_va, + mvluRdVaCtrl->rt, + mvluRdVaCtrl->indCtrl->event->net_info, + &rptCtrl, + &rptClient); + + if (rptClientOut != NULL) + *rptClientOut = rptClient; + +/* If we have a report client, use it's BASRCB */ + if (rptClient != NULL) + return (&rptClient->basrcb); + +/* If not, and the report control was found, use the commom data */ + if (rptCtrl != NULL) + return (&rptCtrl->common_basrcb); + +/* Whoops, could not find the report control at all */ + return (NULL); + } + +/************************************************************************/ +/* _mvlu_get_wr_rcb */ +/* NOTE: Caller can access MVLU_RPT_CTRL, if needed, by using "rpt_ctrl"*/ +/* member of MVLU_RPT_CLIENT. */ +/************************************************************************/ +MVLU_BASRCB *_mvlu_get_wr_rcb (MVLU_WR_VA_CTRL *mvluWrVaCtrl, + MVLU_RPT_CLIENT **rptClientOut) + { +MVLU_RPT_CTRL *rptCtrl; +MVLU_RPT_CLIENT *rptClient; +MVL_NET_INFO *netInfo; +MVLU_RPT_CLIENT *foundClient=NULL; /* If correct Client found, */ + /* this is set to point to it. */ +MVLU_BASRCB *rcb; + + /* Try to find 61850 RCB first. If found, return it. */ + if ((rcb = mvl61850_get_rcb (mvluWrVaCtrl->wrVaCtrl->va->base_va, + mvluWrVaCtrl->rt, + rptClientOut)) != NULL) + return (rcb); + +/* Find the associated Report Control */ + netInfo = mvluWrVaCtrl->indCtrl->event->net_info; + _mvlu_get_rcb (mvluWrVaCtrl->wrVaCtrl->va->base_va, + mvluWrVaCtrl->rt, + netInfo, + &rptCtrl, + &rptClient); + + if (rptClient) /* if Client was found, */ + foundClient = rptClient; /* use it */ + else if (rptCtrl) /* else if rptCtrl was found, */ + foundClient = _mvlu_add_rpt_client (rptCtrl, netInfo); /* add client, use it*/ + + /* Set caller's ptr. */ + if (rptClientOut != NULL) + *rptClientOut = foundClient; + + /* If client found, return its basrcb, else return NULL. */ + return (foundClient ? (&foundClient->basrcb) : NULL); + } +/************************************************************************/ +/* _rcb_writable */ +/* Check if an RCB element is writable at this moment. */ +/* NOTE: Special RCB elements may require additional checking. */ +/* RETURNS: SD_TRUE if writable, SD_FALSE if NOT writable. */ +/************************************************************************/ +ST_RET _rcb_writable (MVLU_BASRCB *rcb, MVLU_RPT_CLIENT *rptClient, + MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +ST_RET writable; + + writable = SD_FALSE; /* assume NOT writable. Change if conditions correct.*/ + + /* First, the "rcb" must be valid (!=NULL), and NOT enabled. */ + if (rcb != NULL && rcb->RptEna == 0) + { /* if rcb is valid, rptClient must also be valid */ + assert (rptClient != NULL); + if (rptClient->rpt_ctrl->rcb_type == RCB_TYPE_IEC_URCB) + { /* if not reserved OR reserved by us, allow write. */ + if (rcb->Resv == 0 || rptClient->netInfo == mvluWrVaCtrl->indCtrl->event->net_info) + writable = SD_TRUE; + } + else /* rcb_type == RCB_TYPE_IEC_BRCB or RCB_TYPE_UCA */ + { /* nothing else to check, allow write. */ + writable = SD_TRUE; + } + } + return (writable); + } + +/************************************************************************/ +/* _mvlu_add_rpt_client */ +/************************************************************************/ + +static MVLU_RPT_CLIENT *_mvlu_add_rpt_client (MVLU_RPT_CTRL *rptCtrl, + MVL_NET_INFO *netInfo) + { +MVLU_RPT_CLIENT *rptClient; +ST_INT rptClientSize; +ST_INT numDsVars; +ST_INT changed_flags_size; + + assert (rptCtrl->rcb_type == RCB_TYPE_UCA); /* this funct only for UCA*/ +/* Alloc report control client enough to contain the reasons and */ +/* changed_flags data */ + numDsVars = rptCtrl->dsNvl->num_of_entries; + changed_flags_size = BSTR_NUMBITS_TO_NUMBYTES(numDsVars); + rptClientSize = sizeof (MVLU_RPT_CLIENT) + + (numDsVars * sizeof (ST_UINT8)) + /* reasons_data */ + 2 * changed_flags_size; /* changed_flags & segmented_inclusion */ + + rptClient = M_CALLOC (MSMEM_GEN, 1, rptClientSize); + rptClient->rpt_ctrl = rptCtrl; + rptClient->netInfo = netInfo; + memcpy (&rptClient->basrcb, &rptCtrl->common_basrcb, sizeof (MVLU_BASRCB)); + rptClient->reasons_data = (ST_UINT8 *) (rptClient + 1); + rptClient->changed_flags = (ST_UINT8 *) (rptClient->reasons_data + numDsVars); + rptClient->segmented_inclusion = rptClient->changed_flags + changed_flags_size; + + list_add_last((ST_VOID **) &rptCtrl->rpt_client_list, (ST_VOID *) rptClient); + ++rptCtrl->num_rpt_clients; + + _mvlu_rpt_disconnect_rcvd_fun = _mvlu_rpt_disconnect_rcvd; + return (rptClient); + } + +/************************************************************************/ +/* _mvlu_free_rpt_client */ +/************************************************************************/ + +static ST_VOID _mvlu_free_rpt_client (MVLU_RPT_CLIENT *rptClient) + { + M_FREE (MSMEM_GEN, rptClient); + } + +/************************************************************************/ +/************************************************************************/ +/* mvlu_rptid_rd_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_rptid_rd_ind_fun (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +ST_CHAR *dest; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + + rcb = _mvlu_get_rd_rcb (mvluRdVaCtrl, NULL); + if (rcb != NULL) + { + dest = (ST_CHAR *) mvluRdVaCtrl->primData; + strcpy (dest, rcb->RptID); + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_rptena_rd_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_rptena_rd_ind_fun (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +ST_BOOLEAN *dest; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + rcb = _mvlu_get_rd_rcb (mvluRdVaCtrl, NULL); + if (rcb != NULL) + { + dest = (ST_BOOLEAN *) mvluRdVaCtrl->primData; + *dest = rcb->RptEna; + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_resv_rd_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_resv_rd_ind_fun (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +ST_BOOLEAN *dest; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + rcb = _mvlu_get_rd_rcb (mvluRdVaCtrl, NULL); + if (rcb != NULL) + { + dest = (ST_BOOLEAN *) mvluRdVaCtrl->primData; + *dest = rcb->Resv; + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_datsetna_rd_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_datsetna_rd_ind_fun (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +ST_CHAR *dest; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + rcb = _mvlu_get_rd_rcb (mvluRdVaCtrl, NULL); + if (rcb != NULL) + { + assert (strlen(rcb->DatSetNa) <= (size_t)abs(mvluRdVaCtrl->rt->u.p.el_len)); + dest = mvluRdVaCtrl->primData; + strcpy (dest, rcb->DatSetNa); + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_optflds_rd_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_optflds_rd_ind_fun (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + rcb = _mvlu_get_rd_rcb (mvluRdVaCtrl, NULL); + if (rcb != NULL) + { + assert (rcb->OptFlds.len_1 <= sizeof(rcb->OptFlds.data_1)*8); + bvstrcpy ((MMS_BVSTRING *) mvluRdVaCtrl->primData, + (MMS_BVSTRING *) &rcb->OptFlds); + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_buftim_rd_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_buftim_rd_ind_fun (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +ST_UINT32 *dest; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + rcb = _mvlu_get_rd_rcb (mvluRdVaCtrl, NULL); + if (rcb != NULL) + { + dest = (ST_UINT32 *) mvluRdVaCtrl->primData; + *dest = rcb->BufTim; + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_trgs_rd_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_trgs_rd_ind_fun (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +ST_UINT16 *dest; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + rcb = _mvlu_get_rd_rcb (mvluRdVaCtrl, NULL); + if (rcb != NULL) + { + dest = (ST_UINT16 *) mvluRdVaCtrl->primData; + *dest = rcb->Trgs; + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_sqnum_rd_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_sqnum_rd_ind_fun (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +ST_UINT8 *dest; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + rcb = _mvlu_get_rd_rcb (mvluRdVaCtrl, NULL); + if (rcb != NULL) + { + dest = (ST_UINT8 *) mvluRdVaCtrl->primData; + *dest = rcb->SqNum; + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_trgops_rd_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_trgops_rd_ind_fun (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + rcb = _mvlu_get_rd_rcb (mvluRdVaCtrl, NULL); + if (rcb != NULL) + { + assert (rcb->TrgOps.len <= sizeof(rcb->TrgOps.data)*8); + bvstrcpy ((MMS_BVSTRING *) mvluRdVaCtrl->primData, + (MMS_BVSTRING *) &rcb->TrgOps); + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_rbepd_rd_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_rbepd_rd_ind_fun (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +ST_UINT32 *dest; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + rcb = _mvlu_get_rd_rcb (mvluRdVaCtrl, NULL); + if (rcb != NULL) + { + dest = (ST_UINT32 *) mvluRdVaCtrl->primData; + *dest = rcb->RBEPd; + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_intgpd_rd_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_intgpd_rd_ind_fun (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +ST_UINT32 *dest; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + rcb = _mvlu_get_rd_rcb (mvluRdVaCtrl, NULL); + if (rcb != NULL) + { + dest = (ST_UINT32 *) mvluRdVaCtrl->primData; + *dest = rcb->IntgPd; + rc = SD_SUCCESS; + } + mvlu_rd_prim_done (mvluRdVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_rptid_wr_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_rptid_wr_ind_fun (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +ST_CHAR *src; +MVLU_BASRCB *rcb; +ST_RET rc; +MVLU_RPT_CLIENT *rptClient; +ST_BOOLEAN do_purge = SD_FALSE; /* Chg to SD_TRUE if Purge Buffer required*/ + + rc = SD_FAILURE; + rcb = _mvlu_get_wr_rcb (mvluWrVaCtrl, &rptClient); + if (_rcb_writable (rcb, rptClient, mvluWrVaCtrl)) + { + src = mvluWrVaCtrl->primData; + if (rptClient->rpt_ctrl->rcb_type == RCB_TYPE_IEC_BRCB + && strcmp (rcb->RptID, src)) + do_purge = SD_TRUE; /* BRCB & val changed, must purge buffer*/ + strcpy (rcb->RptID, src); + rc = SD_SUCCESS; + } + else + mvluWrVaCtrl->wrVaCtrl->failure = ARE_TEMP_UNAVAIL; + + if (do_purge) + mvl61850_brcb_rpt_lists_clean (&rptClient->rpt_ctrl->brcbCtrl); + + mvlu_wr_prim_done (mvluWrVaCtrl, rc); + } + +/************************************************************************/ +/* mvl61850_brcb_handle_rptena_wr */ +/* Process "RptEna" write for 61850 BRCB. */ +/************************************************************************/ +ST_RET mvl61850_brcb_handle_rptena_wr (MVLU_RPT_CLIENT *rptClient, MVLU_BASRCB *rcb, + MVL_NET_INFO *net_info, ST_BOOLEAN newval) + { +ST_RET retCode; + if (rptClient->netInfo == NULL || + rptClient->netInfo == net_info) + { /* BRCB not enabled, or already enabled by us, so allow write.*/ + retCode = SD_SUCCESS; /* allow write */ + if (newval != 0) + { /* trying to enable */ + rptClient->rpt_ctrl->brcbCtrl.enabled_once = SD_TRUE; + rptClient->netInfo = net_info; /* reserve BRCB */ + rcb->SqNumInt16u = 0; /* reset SqNum */ + /*renxiaobao 61850 µÚ¶þ°æÐÞ¸Ä*/ + /*ʹÄܺóµÄµÚÒ»¸ö±¨ÎÄÖÃÒç³öλ*/ + rptClient->rpt_ctrl->brcbCtrl.BufOvfl = SD_TRUE; + } + else + { /* trying to disable */ + rptClient->netInfo = NULL; /* release BRCB reservation */ + } + } + else + { /* RCB reserved by someone else */ + retCode = SD_FAILURE; /* DO NOT allow write */ + } + return (retCode); + } +/************************************************************************/ +/* mvl61850_urcb_handle_rptena_wr */ +/* Process "RptEna" write for 61850 URCB. */ +/************************************************************************/ +ST_RET mvl61850_urcb_handle_rptena_wr (MVLU_RPT_CLIENT *rptClient, MVLU_BASRCB *rcb, + MVL_NET_INFO *net_info, ST_BOOLEAN newval) + { +ST_RET retCode; + if (rptClient->netInfo == NULL || + rptClient->netInfo == net_info) + { /* RCB not reserved, or reserved by us */ + retCode = SD_SUCCESS; /* allow write */ + if (newval != 0) + { /* enabling RCB */ + if (rcb->Resv == 0) /* If URCB not reserved yet, */ + rcb->Resv = 1; /* reserve it now. */ + rcb->SqNum = 0; /* reset SqNum for URCB only */ + rptClient->netInfo = net_info; /* reserve RCB */ + } + /* If newval==0, do nothing (just allow write). RCB not released until Resv set to 0.*/ + } + else + { /* RCB reserved by someone else */ + retCode = SD_FAILURE; /* DO NOT allow write */ + } + return (retCode); + } + +/************************************************************************/ +/* mvlu_rptena_wr_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_rptena_wr_ind_fun (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +ST_BOOLEAN newval; /* val to write to RptEna */ +MVLU_BASRCB *rcb; +MVLU_RPT_CLIENT *rptClient; +ST_RET rc; +MVL_NET_INFO *net_info; /* current connection info */ + + newval = *(ST_BOOLEAN *) mvluWrVaCtrl->primData; + net_info = mvluWrVaCtrl->indCtrl->event->net_info; + + rc = SD_FAILURE; + rcb = _mvlu_get_wr_rcb (mvluWrVaCtrl, &rptClient); + if (rcb != NULL) + { + /* CRITICAL: don't allow enable if dataSet not set (dsNvl==NULL). */ + if (newval != 0 && rptClient->rpt_ctrl->dsNvl == NULL) + { /* Just log it. rc already set.*/ + MVL_LOG_NERR0 ("Cannot enable RCB with NULL DataSet."); + } + else + { + switch (rptClient->rpt_ctrl->rcb_type) + { + case RCB_TYPE_IEC_BRCB: + rc = mvl61850_brcb_handle_rptena_wr (rptClient, rcb, net_info, newval); + break; + case RCB_TYPE_IEC_URCB: + rc = mvl61850_urcb_handle_rptena_wr (rptClient, rcb, net_info, newval); + break; + default: /* must be UCA URCB */ + rc = SD_SUCCESS; /* ALWAYS allow write for URCB */ + if (newval != 0) /* enabling RCB */ + rcb->SqNum = 0; /* reset SqNum for URCB only */ + break; + } + } + } + + /* If allowing write, store new value. */ + if (rc == SD_SUCCESS) + rcb->RptEna = newval; + else /* for any error, return TEMP_UNAVAIL */ + mvluWrVaCtrl->wrVaCtrl->failure = ARE_TEMP_UNAVAIL; + + mvlu_wr_prim_done (mvluWrVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_resv_wr_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_resv_wr_ind_fun (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +MVLU_BASRCB *rcb; +MVLU_RPT_CLIENT *rptClient; +ST_RET rc = SD_FAILURE; + + /* Only for 61850, so use mvl61850_get_rcb, not mvlu_get_wr_rcb. */ + rcb = mvl61850_get_rcb (mvluWrVaCtrl->wrVaCtrl->va->base_va, + mvluWrVaCtrl->rt, + &rptClient); + if (rcb != NULL) + { + assert (rptClient->rpt_ctrl->rcb_type == RCB_TYPE_IEC_URCB); + if (rptClient->netInfo == NULL || + rptClient->netInfo == mvluWrVaCtrl->indCtrl->event->net_info) + { /* RCB not reserved, or reserved by us, so allow write.*/ + rc = SD_SUCCESS; /* allow write */ + rcb->Resv = *(ST_BOOLEAN *) mvluWrVaCtrl->primData; + if (rcb->Resv != 0) + rptClient->netInfo = mvluWrVaCtrl->indCtrl->event->net_info; /* reserve RCB */ + else + { + /* If RCB DatSet is AA_SPEC, remove it (i.e. cleanup & set DatSet=""). */ + if (rptClient->rpt_ctrl->dsNvl != NULL && + rptClient->rpt_ctrl->dsNvl->nvl_scope.scope == AA_SPEC) + mvl61850_rpt_dataset_destroy (rptClient->rpt_ctrl); + rptClient->netInfo = NULL; /* unreserve RCB*/ + } + } + /* else rc=SD_FAILURE already set */ + } + + if (rc != SD_SUCCESS) + mvluWrVaCtrl->wrVaCtrl->failure = ARE_TEMP_UNAVAIL; + + mvlu_wr_prim_done (mvluWrVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_optflds_wr_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_optflds_wr_ind_fun (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +MVLU_BASRCB *rcb; +ST_RET rc; +MMS_BVSTRING *bvstr; +ST_INT numbits; +MVLU_RPT_CLIENT *rptClient; + + rc = SD_FAILURE; + rcb = _mvlu_get_wr_rcb (mvluWrVaCtrl, &rptClient); + if (_rcb_writable (rcb, rptClient, mvluWrVaCtrl)) + { + /* Use 'rcb_type' to figure out how many bits are writable. */ + ST_INT rcb_type = rptClient->rpt_ctrl->rcb_type; + + bvstr = (MMS_BVSTRING *) mvluWrVaCtrl->primData; + /* NOTE: don't change OptFlds.len_1. May only be writing a few */ + /* bits, but want to send ALL bits in read response or Info Rpt. */ + + if (rcb_type == RCB_TYPE_UCA) + { + numbits = min (bvstr->len, 5); /* 5 bits writable. Ignore higher bits.*/ + bstrcpy (rcb->OptFlds.data_1, bvstr->data, numbits); + } + else + { /* must be either IEC_URCB or IEC_BRCB */ + numbits = min (bvstr->len, 9); /* 9 bits writable. Ignore higher bits.*/ + /*renxiaobao 61850 µÚ¶þ°æÐÞ¸Ä*/ + if(bstrcmp (rcb->OptFlds.data_1, bvstr->data, numbits)) + memset(rcb->EntryID,0,8); + /*end*/ + bstrcpy (rcb->OptFlds.data_1, bvstr->data, numbits); + if (rcb_type == RCB_TYPE_IEC_URCB) + { /* 61850-8-1 says to ignore buffer-overflow, entryID bits, so clear them*/ + BSTR_BIT_SET_OFF (rcb->OptFlds.data_1, OPTFLD_BITNUM_BUFOVFL); + BSTR_BIT_SET_OFF (rcb->OptFlds.data_1, OPTFLD_BITNUM_ENTRYID); + } + + } + rc = SD_SUCCESS; + } + else + mvluWrVaCtrl->wrVaCtrl->failure = ARE_TEMP_UNAVAIL; + + mvlu_wr_prim_done (mvluWrVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_buftim_wr_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_buftim_wr_ind_fun (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +ST_UINT32 *src; +MVLU_BASRCB *rcb; +ST_RET rc; +MVLU_RPT_CLIENT *rptClient; +ST_BOOLEAN do_purge = SD_FALSE; /* Chg to SD_TRUE if Purge Buffer required*/ + + rc = SD_FAILURE; + rcb = _mvlu_get_wr_rcb (mvluWrVaCtrl, &rptClient); + if (_rcb_writable (rcb, rptClient, mvluWrVaCtrl)) + { + src = (ST_UINT32 *) mvluWrVaCtrl->primData; + if (rptClient->rpt_ctrl->rcb_type == RCB_TYPE_IEC_BRCB + && rcb->BufTim != *src) + { + do_purge = SD_TRUE; /* BRCB & val changed, must purge buffer*/ + /*renxiaobao 61850 µÚ¶þ°æÐÞ¸Ä*/ + memset(rcb->EntryID,0,8); + } + rcb->BufTim = *src; + rc = SD_SUCCESS; + } + else + mvluWrVaCtrl->wrVaCtrl->failure = ARE_TEMP_UNAVAIL; + + if (do_purge) + mvl61850_brcb_rpt_lists_clean (&rptClient->rpt_ctrl->brcbCtrl); + + mvlu_wr_prim_done (mvluWrVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_trgs_wr_ind_fun */ +/* NOTE: for UCA RCB only. */ +/************************************************************************/ + +ST_VOID mvlu_trgs_wr_ind_fun (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +ST_UINT16 *src; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + rcb = _mvlu_get_wr_rcb (mvluWrVaCtrl, NULL); + if (rcb != NULL && rcb->RptEna == SD_FALSE) /* if enabled, can't write*/ + { + src = (ST_UINT16 *) mvluWrVaCtrl->primData; + rcb->Trgs = *src; + rc = SD_SUCCESS; + } + else + mvluWrVaCtrl->wrVaCtrl->failure = ARE_TEMP_UNAVAIL; + + mvlu_wr_prim_done (mvluWrVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_sqnum_wr_ind_fun */ +/* NOTE: for UCA RCB only. In IEC 61850 RCB, SqNum may not be written. */ +/************************************************************************/ + +ST_VOID mvlu_sqnum_wr_ind_fun (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +ST_UINT8 *src; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + rcb = _mvlu_get_wr_rcb (mvluWrVaCtrl, NULL); + if (rcb != NULL && rcb->RptEna == SD_FALSE) /* if enabled, can't write*/ + { + src =(ST_UINT8 *) mvluWrVaCtrl->primData; + rcb->SqNum = *src; + rc = SD_SUCCESS; + } + else + mvluWrVaCtrl->wrVaCtrl->failure = ARE_TEMP_UNAVAIL; + + mvlu_wr_prim_done (mvluWrVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_trgops_wr_ind_fun */ +/************************************************************************/ +extern int rcb_TrgOps_wr_check(char *rpt_id,char wr_data); +ST_VOID mvlu_trgops_wr_ind_fun (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +MVLU_BASRCB *rcb; +ST_RET rc; +MMS_BVSTRING *bvstr; +MVLU_RPT_CLIENT *rptClient; +ST_BOOLEAN do_purge = SD_FALSE; /* Chg to SD_TRUE if Purge Buffer required*/ + + rc = SD_FAILURE; + rcb = _mvlu_get_wr_rcb (mvluWrVaCtrl, &rptClient); + if (_rcb_writable (rcb, rptClient, mvluWrVaCtrl)) + { + bvstr = (MMS_BVSTRING *) mvluWrVaCtrl->primData; + /* NOTE: don't change TrgOps.len. May only be writing a few */ + /* bits, but want to send ALL bits in read response or Info Rpt. */ + + /* assert (bvstr->len <= (sizeof (rcb->TrgOps.data)*8));*/ + if (rptClient->rpt_ctrl->rcb_type == RCB_TYPE_IEC_BRCB + && bstrcmp (rcb->TrgOps.data, bvstr->data, bvstr->len)) + { + do_purge = SD_TRUE; /* BRCB & val changed, must purge buffer*/ + /*renxiaobao 61850 µÚ¶þ°æÐÞ¸Ä*/ + memset(rcb->EntryID,0,8); + } + if(rcb_TrgOps_wr_check(rptClient->rpt_ctrl->common_basrcb.RptID,bvstr->data[0])) + bstrcpy (rcb->TrgOps.data, bvstr->data, bvstr->len); + + + + rc = SD_SUCCESS; + } + else + mvluWrVaCtrl->wrVaCtrl->failure = ARE_TEMP_UNAVAIL; + + if (do_purge) + mvl61850_brcb_rpt_lists_clean (&rptClient->rpt_ctrl->brcbCtrl); + + mvlu_wr_prim_done (mvluWrVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_rbepd_wr_ind_fun */ +/* NOTE: for UCA RCB only. */ +/************************************************************************/ + +ST_VOID mvlu_rbepd_wr_ind_fun (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +ST_UINT32 *src; +MVLU_BASRCB *rcb; +ST_RET rc; + + rc = SD_FAILURE; + rcb = _mvlu_get_wr_rcb (mvluWrVaCtrl, NULL); + if (rcb != NULL && rcb->RptEna == SD_FALSE) /* if enabled, can't write*/ + { + src = (ST_UINT32 *) mvluWrVaCtrl->primData; + rcb->RBEPd = *src; + rc = SD_SUCCESS; + } + else + mvluWrVaCtrl->wrVaCtrl->failure = ARE_TEMP_UNAVAIL; + + mvlu_wr_prim_done (mvluWrVaCtrl, rc); + } + +/************************************************************************/ +/* mvlu_intgpd_wr_ind_fun */ +/************************************************************************/ + +ST_VOID mvlu_intgpd_wr_ind_fun (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +ST_UINT32 *src; +MVLU_BASRCB *rcb; +ST_RET rc; +MVLU_RPT_CLIENT *rptClient; +ST_BOOLEAN do_purge = SD_FALSE; /* Chg to SD_TRUE if Purge Buffer required*/ + + rc = SD_FAILURE; + rcb = _mvlu_get_wr_rcb (mvluWrVaCtrl, &rptClient); + if (_rcb_writable (rcb, rptClient, mvluWrVaCtrl)) + { + src = (ST_UINT32 *) mvluWrVaCtrl->primData; + if (rptClient->rpt_ctrl->rcb_type == RCB_TYPE_IEC_BRCB + && rcb->IntgPd != *src) + { + do_purge = SD_TRUE; /* BRCB & val changed, must purge buffer*/ + /*renxiaobao 61850 µÚ¶þ°æÐÞ¸Ä*/ + rptClient->next_integ_rpt_time = 0; /* reset timer */ + memset(rcb->EntryID,0,8); + } + rcb->IntgPd = *src; + rc = SD_SUCCESS; + } + else + mvluWrVaCtrl->wrVaCtrl->failure = ARE_TEMP_UNAVAIL; + + if (do_purge) + mvl61850_brcb_rpt_lists_clean (&rptClient->rpt_ctrl->brcbCtrl); + + mvlu_wr_prim_done (mvluWrVaCtrl, rc); + } + +/************************************************************************/ +/************************************************************************/ +/* For backward compatibility ... do not use */ +ST_VOID mvlu_seqnum_rd_ind_fun (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { + mvlu_sqnum_rd_ind_fun (mvluRdVaCtrl); + } +ST_VOID mvlu_seqnum_wr_ind_fun (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { + mvlu_sqnum_wr_ind_fun (mvluWrVaCtrl); + } + +/* + * mvlu_integrity_scan_destroy + * Free data allocated by mvlu_integrity_scan_read. + */ +ST_VOID mvlu_integrity_scan_destroy (MVL_IND_PEND *indCtrl) + { + M_FREE (MSMEM_GEN, indCtrl); + } + +/* + * mvlu_integrity_scan_read + * This function "BEGINS" the scan of ALL data for one Report DataSet (NVL). + * It is called automatically when an Integrity Report or a + * General Interrogation Report needs to be sent. This is much more + * efficient than constantly scanning. + * - It allocates & initializes a temporary MVL_IND_PEND structure. + * - It calls "u_mvl_read_ind" to begin the scan. + * - The scan may complete synchronously or asynchronously. + * - When the scan completes, the funct pointed to by "scan_done_fun" arg + * is called to build the report and cleanup. + * CRITICAL: Function pointed to by "scan_done_fun" must call + * "mvlu_integrity_scan_destroy" to free temporary MVL_IND_PEND struct. + */ + +ST_VOID mvlu_integrity_scan_read (MVLU_RPT_CLIENT *rptClient, + ST_VOID (*scan_va_done_fun)(MVL_IND_PEND *indCtrl, + MVL_VAR_ASSOC *va), + ST_RET (*scan_done_fun)(MVL_IND_PEND *indCtrl) + ) + { +MVL_IND_PEND *indCtrl; + + /* Create a simulated read indication for the DataSet NVL. */ + indCtrl = mvlu_setup_scan_read (rptClient->rpt_ctrl->dsNvl, + scan_va_done_fun, scan_done_fun); + + indCtrl->usr_ind_ctrl = rptClient; /* Save rptClient */ + + /* OK, now fire off the read indication functions. */ + u_mvl_read_ind (indCtrl); + } + +/** + * mvlu_setup_scan_read + * This function sets up the scan of ALL data for one NVL. + * It allocates & initializes a temporary MVL_IND_PEND structure for a + * simulated read indication. + * RETURNS: (MVL_IND_PEND *) + */ + +MVL_IND_PEND *mvlu_setup_scan_read (MVL_NVLIST_CTRL *nvl, + ST_VOID (*scan_va_done_fun)(MVL_IND_PEND *indCtrl, + MVL_VAR_ASSOC *va), + ST_RET (*scan_done_fun)(MVL_IND_PEND *indCtrl) + ) + { +MVLAS_RD_VA_CTRL *vaCtrl; +MVL_IND_PEND *indCtrl; +ST_INT j; + +/* Allocate space for MVL_IND_PEND & array of MVLAS_RD_VA_CTRL. */ + indCtrl = M_CALLOC (MSMEM_GEN, 1, + sizeof (MVL_IND_PEND) + + nvl->num_of_entries * sizeof (MVLAS_RD_VA_CTRL)); + + indCtrl->u.rd.numVar = nvl->num_of_entries; + indCtrl->op = MMSOP_MVLU_RPT_VA; /* indicates this is not normal read*/ + + indCtrl->u.rd.vaCtrlTbl = (MVLAS_RD_VA_CTRL *)(indCtrl+1);/*point after indCtrl*/ + + for (j = 0, vaCtrl = indCtrl->u.rd.vaCtrlTbl; + j < nvl->num_of_entries; + j++, vaCtrl++) + { + vaCtrl->va = nvl->entries[j]; + memcpy (&vaCtrl->va_scope, &nvl->va_scope[j], sizeof(MVL_SCOPE)); + } + + /* Save funct ptr. Called from "mvlu_rd_prim_done" when scan of ONE va complete.*/ + indCtrl->scan_va_done_fun = scan_va_done_fun; + + /* Save funct ptr. Called from "mvlu_rd_prim_done" when scan complete.*/ + indCtrl->usr_resp_fun = scan_done_fun; /* CRITICAL: */ + + return (indCtrl); + } + +/************************************************************************/ +/* mvlu_integrity_scan_va_done */ +/* This function is called by 'mvlu_rd_prim_done' when all "leaf" */ +/* functions for a VA have been completed (i.e. data ready for this VA).*/ +/************************************************************************/ + +ST_VOID mvlu_integrity_scan_va_done (MVL_IND_PEND *indCtrl, + MVL_VAR_ASSOC *va) + { + ST_INT data_size; + /* CRITICAL: DO NOT call mvlu_rpt_va_change. rptClient->reasons_data */ + /* will be set in mvlu_integrity_scan_done when scan completes. */ + data_size = mvl_type_ctrl[va->type_id].data_size; + memcpy (va->last_data, va->data, data_size); + } + +/************************************************************************/ +/* mvlu_integrity_scan_done */ +/* Same as "_mvlu_rpt_scan_done" except arg is (MVL_IND_PEND *) */ +/* instead of (MVLU_RPT_SCAN_CTRL *). */ +/* */ +/* This function is called when the integrity scan is complete. */ +/* (i.e. 'mvlu_rd_prim_done' has been called for all "leafs" of all */ +/* variables in the report). Everything is ready to build a report, */ +/* so build it now. */ +/************************************************************************/ + +ST_RET mvlu_integrity_scan_done (MVL_IND_PEND *indCtrl) + { +ST_RET retCode; +MVLU_RPT_CLIENT *rptClient; +ST_INT j; + + /* Get "rptClient", saved in "indCtrl" when scan initialized. */ + rptClient = (MVLU_RPT_CLIENT *) indCtrl->usr_ind_ctrl; + + /* Set "reason" for each variable of Dataset now. */ + for (j = 0; j < rptClient->rpt_ctrl->dsNvl->num_of_entries; j++) + rptClient->reasons_data[j] = MVLU_TRGOPS_INTEGRITY; + + /* send or queue rpt */ + retCode = mvlu_rpt_ready (rptClient, MVLU_RPT_TYPE_INTEGRITY_OR_GI); + + if (retCode != SD_SUCCESS) + MVLU_LOG_FLOW1 ("Integrity report send failed: err=0x%X", retCode); + + /* set time for next integrity report */ + rptClient->next_integ_rpt_time = sGetMsTime () + + (ST_DOUBLE) rptClient->basrcb.IntgPd; + rptClient->integ_scan_in_progress = SD_FALSE; + mvlu_integrity_scan_destroy (indCtrl); /* destroy temporary struct*/ + return (retCode); + } + +/************************************************************************/ +/* find_or_create_typeid */ +/* Try to find the type_id. If that fails, try to create it. */ +/************************************************************************/ +ST_INT find_or_create_typeid (ST_CHAR *type_name, ST_CHAR *tdl) + { +ST_INT type_id; + if ((type_id = mvl_typename_to_typeid (type_name)) < 0) /* find */ + type_id = mvl_type_id_create_from_tdl (type_name, tdl); /* create*/ + return (type_id); + } + +/************************************************************************/ +/* mvlu_rpt_find_typeids */ +/* Find or create ALL types needed to encode reports. */ +/* These types may have been defined in the ODF file and created by */ +/* Foundry or may have been created by an earlier call to this function.*/ +/* RETURNS: SD_SUCCESS if ALL types found or created */ +/* SD_FAILURE if ANY type could not be found or created. */ +/************************************************************************/ +ST_RET mvlu_rpt_find_typeids (MVLU_RPT_TYPEIDS *rpt_typeids) + { +ST_RET retCode = SD_FAILURE; /* assume FAILURE for now */ +ST_CHAR *type_name; /* name of type to be found */ + + /* stop on any error */ + do + { /* "one-time" loop: just to have something to break out of */ + if ((rpt_typeids->mmsbool = find_or_create_typeid (type_name = "RTYP_BOOL", "Bool")) < 0) + break; + if ((rpt_typeids->bstr6 = find_or_create_typeid (type_name = "RTYP_BSTR6", "Bstring6")) < 0) + break; + if ((rpt_typeids->bstr8 = find_or_create_typeid (type_name = "RTYP_BSTR8", "Bstring8")) < 0) + break; + if ((rpt_typeids->bvstring6 = find_or_create_typeid (type_name = "RTYP_BVSTR6", "Bvstring6")) < 0) + break; + if ((rpt_typeids->bvstring8 = find_or_create_typeid (type_name = "RTYP_BVSTR8", "Bvstring8")) < 0) + break; + if ((rpt_typeids->bvstring10 = find_or_create_typeid (type_name = "RTYP_BVSTR10", "Bvstring10")) < 0) + break; + if ((rpt_typeids->btime6 = find_or_create_typeid (type_name = "RTYP_BTIME6", "Btime6")) < 0) + break; + if ((rpt_typeids->int8u = find_or_create_typeid (type_name = "RTYP_INT8U", "Ubyte")) < 0) + break; + if ((rpt_typeids->int16u = find_or_create_typeid (type_name = "RTYP_INT16U", "Ushort")) < 0) + break; + if ((rpt_typeids->int32u = find_or_create_typeid (type_name = "RTYP_INT32U", "Ulong")) < 0) + break; + if ((rpt_typeids->ostring8 = find_or_create_typeid (type_name = "RTYP_OSTR8", "Ostring8")) < 0) + break; + if ((rpt_typeids->vstring32 = find_or_create_typeid (type_name = "RTYP_VSTR32", "Vstring32")) < 0) + break; + if ((rpt_typeids->vstring65 = find_or_create_typeid (type_name = "RTYP_VSTR65", "Vstring65")) < 0) + break; + if ((rpt_typeids->vstring129 = find_or_create_typeid (type_name = "RTYP_VSTR129", "Vstring129")) < 0) + break; + + retCode = SD_SUCCESS; /* If we get here, all were successful */ + } while (0); /* end of "one-time" loop */ + + if (retCode) + MVL_LOG_ERR1 ("Can't find or create type '%s'", type_name); + return (retCode); /* If ANY find failed, SD_FAILURE is returned */ + } + +/************************************************************************/ +/* mvlu_integrity_timeout */ +/* Check for Integrity period timeout. If timeout occurred, start */ +/* integrity scan. */ +/* RETURNS: SD_TRUE if IntgPd is set and timeout occurred */ +/* SD_FALSE otherwise */ +/************************************************************************/ +ST_RET mvlu_integrity_timeout (MVLU_RPT_CLIENT *rptClient, ST_DOUBLE timeNow) + { +ST_RET ret; + + if (rptClient->basrcb.IntgPd != 0 + && BSTR_BIT_GET (rptClient->basrcb.TrgOps.data, TRGOPS_BITNUM_INTEGRITY) /* enabled*/ + && (!rptClient->integ_scan_in_progress) + && timeNow > rptClient->next_integ_rpt_time) + { + MVLU_LOG_FLOW1 ("UCA Report Integrity Period timeout for client %08lx", + rptClient); + + /* Send last buffered entry (due to BufTm buffering) BEFORE this integrity report.*/ + if (rptClient->numTrgs > 0) + { /* send or queue report */ + mvlu_rpt_ready (rptClient, MVLU_RPT_TYPE_RBE); + } + + /* Set scan_in_progress flag so new scan can't start before last + * scan finished. Clear flag in "mvlu_integrity_scan_done". + */ + rptClient->integ_scan_in_progress = SD_TRUE; + + /* This function "begins" the integrity scan. When the scan is + * complete, "mvlu_integrity_scan_done" is called to build the + * the report. If ALL "leaf" functions are synchronous, + * "mvlu_integrity_scan_done" is called BEFORE this function returns. + */ + mvlu_integrity_scan_read (rptClient, + mvlu_integrity_scan_va_done, + mvlu_integrity_scan_done); + ret = SD_TRUE; + } + else + ret = SD_FALSE; + return (ret); + } + +/************************************************************************/ +/* mvlu_rpt_rcb_type_find */ +/* Find the runtime type of the RCB and save it in *rcbHeadOut & *numRtOut.*/ +/************************************************************************/ +ST_RET mvlu_rpt_rcb_type_find (ST_INT type_id, ST_CHAR *basrcbName, + RUNTIME_TYPE **rcbHeadOut, ST_INT *numRtOut) + { +ST_RET ret = SD_FAILURE; +ST_CHAR *ptr; + + ptr = strstr (basrcbName, "$"); + if (ptr) + { + ++ptr; /* Skip the '$' */ + if (mvlu_find_comp_type (type_id, ptr, rcbHeadOut, numRtOut) == SD_SUCCESS) + { + if ((*rcbHeadOut)->el_tag == RT_STR_START) + ret = SD_SUCCESS; /* only path to success */ + else + MVL_LOG_NERR1 ("'%s' is not a structure", basrcbName); + } + else + MVL_LOG_NERR1 ("Could not find type for component '%s'", basrcbName); + } + else + MVL_LOG_NERR1 ("Invalid BASRCB name: %s", basrcbName); + + return (ret); + } + +/************************************************************************/ +/* mvlu_rpt_ready */ +/* Report is ready to send or save in "buffer". */ +/* Check the RCB type and call appropriate function. */ +/************************************************************************/ +ST_RET mvlu_rpt_ready (MVLU_RPT_CLIENT *rptClient, ST_INT rpt_type) + { +ST_RET retCode; + switch (rptClient->rpt_ctrl->rcb_type) + { + case RCB_TYPE_UCA: + retCode = mvlu_send_report (rptClient, rpt_type); + break; + case RCB_TYPE_IEC_BRCB: + retCode = mvl61850_brcb_rpt_save (rptClient); /* save rpt in buffer*/ + break; + case RCB_TYPE_IEC_URCB: + retCode = mvl61850_urcb_rpt_send (rptClient->rpt_ctrl, rptClient, rpt_type); + break; + default: + retCode = SD_FAILURE; /* should never happen */ + break; + } + return (retCode); + } + +/************************************************************************/ +/* mvlu_rpt_ctrl_destroy_all */ +/* Destroy all UCA report controls. */ +/************************************************************************/ +ST_VOID mvlu_rpt_ctrl_destroy_all () + { +MVLU_RPT_CTRL *rptCtrl; +MVLU_RPT_SCAN_CTRL *scanCtrl; + /* Use list_find_last to avoid calling list_unlink twice. */ + while ((scanCtrl = (MVLU_RPT_SCAN_CTRL *) list_find_last ((DBL_LNK *)mvlu_rpt_scan_list)) != NULL) + { + mvlu_rpt_destroy_scan_ctrl (scanCtrl); /* this also unlinks it from list*/ + } + + /* Use list_find_last to avoid calling list_unlink twice. */ + while ((rptCtrl = (MVLU_RPT_CTRL *) list_find_last ((DBL_LNK *)mvlu_rpt_ctrl_list)) != NULL) + { + mvlu_free_rpt_ctrl (rptCtrl); /* this also unlinks it from list*/ + } + } + diff --git a/mmslib/mvlu/mvlu_rt.c b/mmslib/mvlu/mvlu_rt.c new file mode 100644 index 0000000..c032332 --- /dev/null +++ b/mmslib/mvlu/mvlu_rt.c @@ -0,0 +1,422 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2001, All Rights Reserved */ +/* */ +/* MODULE NAME : mvlu_rt.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* main */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/18/08 JRB 11 We allow up to 15 char LNName (sclparse.c), */ +/* so max flatname must be MAX_IDENT_LEN-15. */ +/* 07/20/07 JRB 10 Flatnames must be shorter to add LNName later*/ +/* 11/22/06 JRB 09 Free bufs if _mvlu_build_uca_name_tbl fails. */ +/* 01/30/06 GLB 09 Integrated porting changes for VMS */ +/* 03/11/04 GLB 08 Added "#ifdef DEBUG_SISCO" for "thisFileName" */ +/* 09/18/03 JRB 07 Allow array of structures. */ +/* DON'T allow array of arrays (return error). */ +/* 05/02/03 JRB 06 switch(rt->el_tag): Use default for most cases*/ +/* 04/29/03 JRB 05 Chg several functions to return ST_RET. */ +/* 04/24/03 JRB 04 Use MAX_IDENT_LEN define. */ +/* 03/13/03 JRB 03 mvlu_proc_rt_type: Chg to use RUNTIME_CTRL. */ +/* MVLU_UCA_NAME_CTRL: Chg ucaName member from */ +/* ptr to array (saves allocs). */ +/* 12/11/02 JRB 02 Use new mvl_uca.h */ +/* 11/14/02 MDE 01 New module, extracted fo_uca.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "gen_list.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mem_chk.h" +#include "mvl_uca.h" + +/************************************************************************/ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/* STATIC VARIABLES */ + +#define MAX_PREFIX_LEN 200 +#define MAX_NEST_LEVEL 50 +static ST_CHAR *namePrefix[MAX_NEST_LEVEL]; +static ST_INT nestLevel; + + +/************************************************************************/ +/* STATIC FUNCTIONS */ + +static ST_RET _mvlu_set_rt_sort_num (ST_CHAR *typeName, + RUNTIME_TYPE *rt, ST_INT numRt, + MVLU_UCA_NAME_CTRL **ucaNamesOut); +static ST_VOID _mvlu_set_rt_size (RUNTIME_TYPE *rt) ; +static ST_VOID _mvlu_set_rt_offset (RUNTIME_TYPE *rt, ST_INT numRt); +static ST_RET _mvlu_build_uca_name_tbl (RUNTIME_TYPE *rt, ST_INT rt_num, + MVLU_UCA_NAME_CTRL *mvluFoundryInfo); +static ST_RET _mvlu_save_rt_uca_name (ST_INT nestLevel, RUNTIME_TYPE *rt, + MVLU_UCA_NAME_CTRL *mvluFoundryInfo); +static ST_VOID _mvlu_sort_uca_names (MVLU_UCA_NAME_CTRL *ucaNames, + RUNTIME_TYPE *rt, ST_INT numRt); + +/************************************************************************/ +/************************************************************************/ +/* mvlu_proc_rt_type */ +/************************************************************************/ + +ST_RET mvlu_proc_rt_type (ST_CHAR *typeName, RUNTIME_CTRL *rt_ctrl, + MVLU_UCA_NAME_CTRL **ucaNamesOut) + { +RUNTIME_TYPE *rt; +ST_INT i; +ST_RET ret; + +/* Set the sortedNum for each RT element */ + ret = _mvlu_set_rt_sort_num (typeName, rt_ctrl->rt_first, rt_ctrl->rt_num, ucaNamesOut); + if (ret) + return(ret); /* don't bother continuing */ + +/* Find the offset of the data for each RT within the type */ + _mvlu_set_rt_offset (rt_ctrl->rt_first, rt_ctrl->rt_num); + +/* Find the size of each RT within the type */ + rt = rt_ctrl->rt_first; + for (i = 0; i < rt_ctrl->rt_num; ++i, ++rt) + _mvlu_set_rt_size (rt); + + return (ret); + } + +/************************************************************************/ +/************************************************************************/ +/* _mvlu_set_rt_size */ +/************************************************************************/ +/* This function would not be needed except that the UCA structure */ +/* handling needs to know the size of each subelement too ... */ + +static ST_VOID _mvlu_set_rt_size (RUNTIME_TYPE *rt) + { +ST_INT numUcaRt; +ST_INT blockedLen; + + if (rt->el_tag == RT_ARR_END || rt->el_tag == RT_STR_END) + { + return; + } + + if (rt->el_tag == RT_STR_START) + numUcaRt = rt->u.str.num_rt_blks+2; + else if (rt->el_tag == RT_ARR_START) + numUcaRt = rt->u.arr.num_rt_blks+2; + else + numUcaRt = 1; + +/* Now we can find the size of this element and it's associates */ + blockedLen = ms_get_blocked_length (rt, numUcaRt); + rt->offset_to_last = blockedLen; + } + +/************************************************************************/ +/************************************************************************/ +/* _mvlu_set_rt_offset */ +/************************************************************************/ + +static ST_VOID _mvlu_set_rt_offset (RUNTIME_TYPE *rt, ST_INT numRt) + { +ST_INT data_offset; +SD_CONST RUNTIME_TYPE *rt_end; +ST_INT arr_loops[ASN1_MAX_LEVEL]; +ST_BOOLEAN arr_el_set[ASN1_MAX_LEVEL]; +ST_INT arr_loop_level; + + arr_loop_level = 0; + rt_end = rt + numRt; /* end block */ + data_offset = 0; + +/* Traverse the RT type as though we were doing a ASN.1 to LOCAL */ + while (rt < rt_end) + { + if (rt->el_tag == RT_ARR_END) /* treat case of array ending */ + { + if (--arr_loops[arr_loop_level] > 0)/* if need to do next ar elmnt*/ + { + rt -= rt->u.arr.num_rt_blks; /* mv rt to start of arr */ + continue; + } + else + --arr_loop_level; + } + if (arr_loop_level == 0 || arr_el_set[arr_loop_level] == SD_FALSE) + { + rt->mvluTypeInfo.offSet = data_offset; /* Set the offset */ + /* renxiaobao Êý×é*/ + /*arr_el_set[arr_loop_level] = SD_TRUE;*/ + } + + data_offset += rt->el_size; /* Offset for next */ + + if (rt->el_tag == RT_ARR_START) /* Set up array looping */ + { + ++arr_loop_level; + arr_loops[arr_loop_level] = rt->u.arr.num_elmnts; + arr_el_set[arr_loop_level] = SD_FALSE; + } + rt++; /* point to next runtime element */ + } + } + + +/************************************************************************/ +/************************************************************************/ +/* _mvlu_set_rt_sort_num */ +/************************************************************************/ + +static ST_RET _mvlu_set_rt_sort_num (ST_CHAR *typeName, + RUNTIME_TYPE *rt, ST_INT numRt, + MVLU_UCA_NAME_CTRL **ucaNamesOut) + { +MVLU_UCA_NAME_CTRL *ucaNames; +ST_INT i; + + ucaNames = (MVLU_UCA_NAME_CTRL *) chk_calloc (numRt, sizeof (MVLU_UCA_NAME_CTRL)); + nestLevel = 0; + +/* Derive the UCA names within this type */ + namePrefix[0] = (ST_CHAR *) chk_calloc (1, MAX_PREFIX_LEN); + if (typeName != NULL) + strcpy (namePrefix[0], typeName); + + if (_mvlu_build_uca_name_tbl (rt, numRt, ucaNames)) + { + chk_free(ucaNames); + chk_free(namePrefix[0]); + return (SD_FAILURE); /* don't bother continuing */ + } + +/* Now sort the UCA names within the type */ + _mvlu_sort_uca_names (ucaNames, rt, numRt); + + for (i = 0; i < MAX_NEST_LEVEL; ++i) + { + if (namePrefix[i] != NULL) + { + chk_free (namePrefix[i]); + namePrefix[i] = NULL; + } + } + if (ucaNamesOut == NULL) + chk_free (ucaNames); + else + *ucaNamesOut = ucaNames; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _mvlu_build_uca_name_tbl */ +/* Start with retCode=SD_SUCCESS. If any call to _mvlu_save_rt_uca_name */ +/* fails, set retCode=SD_FAILURE. Do not return immediately because we */ +/* want to log as many problems as possible first. */ +/************************************************************************/ + +static ST_RET _mvlu_build_uca_name_tbl (RUNTIME_TYPE *rt, ST_INT rt_num, + MVLU_UCA_NAME_CTRL *ucaNames) + { +ST_INT i; +ST_RET retCode=SD_SUCCESS; + + nestLevel = 0; + for (i = 0; i < rt_num; ++i, ++rt) + { + ucaNames[i].rtIndex = i; + ucaNames[i].rt = rt; + switch (rt->el_tag) + { + case RT_STR_START : + if (ms_comp_name_pres(rt)) + { + if (_mvlu_save_rt_uca_name (nestLevel, rt, &ucaNames[i])) + retCode = SD_FAILURE; /*continue but eventually return this*/ + + ++nestLevel; + if (namePrefix[nestLevel] == NULL) + namePrefix[nestLevel] = (ST_CHAR *) chk_calloc (1, MAX_PREFIX_LEN); + + strcpy (namePrefix[nestLevel], namePrefix[nestLevel-1]); + strcat (namePrefix[nestLevel], "$"); + strcat (namePrefix[nestLevel], ms_comp_name_find(rt)); + } + break; + + case RT_STR_END : + --nestLevel; + break; + + case RT_ARR_START : + if (_mvlu_save_rt_uca_name (nestLevel, rt, &ucaNames[i])) + retCode = SD_FAILURE; /*continue but eventually return this*/ + + /* We let the array element inherit our name so we will generate */ + /* rd/wr ind handler functions and references for the contained */ + /* primitive elements */ + /* This causes duplicate names (name of array same as name of */ + /* object IN array). That's OK because names of anything inside */ + /* array are dropped when sorted (see _mvlu_sort_uca_names). */ + /* The "sorted" array of names is used in GetNameList response. */ + + if (ms_is_rt_prim (rt+1) || (rt+1)->el_tag==RT_STR_START) + { + +#if defined(USE_RT_TYPE_2) + (rt+1)->comp_name_ptr = rt->comp_name_ptr; +#elif defined(USE_RT_TYPE_3) + (rt+1)->name_index = rt->name_index; +#else + strcpy ((rt+1)->name, rt->name); +#endif + } + else + { + SLOGALWAYS1 ("Warning: Arrays of arrays not supported for UCA (%s)", + ucaNames[i].ucaName); + retCode = SD_FAILURE; /*continue but eventually return this*/ + } + break; + + case RT_ARR_END : + break; + + default : + if (_mvlu_save_rt_uca_name (nestLevel, rt, &ucaNames[i])) + retCode = SD_FAILURE; /*continue but eventually return this*/ + break; + } + } + return (retCode); + } + +/************************************************************************/ +/* _mvlu_save_rt_uca_name */ +/* Start with retCode=SD_SUCCESS. If anything fails, set retCode=SD_FAILURE.*/ +/************************************************************************/ +static ST_RET _mvlu_save_rt_uca_name (ST_INT nestLevel, + RUNTIME_TYPE *rt, + MVLU_UCA_NAME_CTRL *nameDest) + { +ST_CHAR nameBuf[256]; +ST_RET retCode = SD_SUCCESS; + + nameDest->ucaName [0] = '\0'; /* start with empty string */ + nameDest->rt = rt; + if (ms_comp_name_pres(rt)) + { + sprintf (nameBuf, "%s$%s", namePrefix[nestLevel], ms_comp_name_find(rt)); + /* Make sure there is room left for longest allowed Logical Node Name*/ + /* (11 characters according to IEC 61850-7-2 but we allow 15). */ + /* NOTE: this allows 5 or 6 more char than 61850-7-2 specifies, so */ + /* it is more forgiving, but it prevents illegal MMS names. */ + if (strlen (nameBuf) > (MAX_IDENT_LEN-15)) + { + SLOGALWAYS2 ("Error: Flattened IEC 61850 variable name '%s' > %d characters. Illegal.", + nameBuf, (MAX_IDENT_LEN-15)); + SLOGCALWAYS0 ("Must allow space for LNName up to 15 characters"); + retCode = SD_FAILURE; + } + else + strcpy (nameDest->ucaName, nameBuf); + } + return (retCode); + } + +/************************************************************************/ +/************************************************************************/ +/* SORTING UCA NAMES WITHIN A TYPE */ +/************************************************************************/ +/* elementCompare */ +/************************************************************************/ +/* This function is sorting the namelist table */ + +static ST_INT elementCompare (const MVLU_UCA_NAME_CTRL *a, + const MVLU_UCA_NAME_CTRL *b) + { + return (strcmp (a->ucaName, b->ucaName)); + } + +/************************************************************************/ +/* _mvlu_sort_uca_names */ +/************************************************************************/ + +static ST_VOID _mvlu_sort_uca_names (MVLU_UCA_NAME_CTRL *ucaNames, + RUNTIME_TYPE *rt, ST_INT numRt) + { +ST_INT i; +ST_INT numNames; +MVLU_UCA_NAME_CTRL *sortedNames; /* compressed/sorted array of names*/ + + sortedNames = (MVLU_UCA_NAME_CTRL *) M_MALLOC (MSMEM_GEN, numRt*sizeof(MVLU_UCA_NAME_CTRL)); + +/* Compress the name table */ + numNames = 0; + for (i = 0; i < numRt; ++i, ++rt) + { + if (ucaNames[i].ucaName[0] != '\0') + { + sortedNames[numNames] = ucaNames[i]; + ++numNames; +/* CRITICAL: + * The "ucaNames" array contains names for objects inside arrays. + * They must be kept in the original array, because they are needed + * for generating leaf function names. + * However, they are NOT legal variable names, so they are NOT + * copied to the SORTED array (used for GetNameList response). + * This is done by skipping over the runtime type for the array. + */ + if (rt->el_tag==RT_ARR_START) + { + rt += (rt->u.arr.num_rt_blks + 1); + i += (rt->u.arr.num_rt_blks + 1); + } + } + } + +/* OK, we now have a raw table of names, go ahead and sort them */ + qsort (sortedNames, numNames, sizeof (MVLU_UCA_NAME_CTRL), + (int (*)(const void *,const void *)) elementCompare); + +#if 0 /* DEBUG: enable this code to debug sorting algorithm */ + if (numNames) + { + ST_INT j; + SLOGALWAYS0 ("Array of UCA variable names (Uncompressed/Unsorted)"); + for (j = 0; jmvluTypeInfo.sortedNum = i+1; + } + M_FREE (MSMEM_GEN, sortedNames); + } + diff --git a/mmslib/mvlu/mvlu_sbo.c b/mmslib/mvlu/mvlu_sbo.c new file mode 100644 index 0000000..009b672 --- /dev/null +++ b/mmslib/mvlu/mvlu_sbo.c @@ -0,0 +1,352 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998-2004, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mvlu_sbo.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/06/08 JRB 15 Chg sbo_pool from static to global. */ +/* 02/26/07 JRB 14 initSboCtrl: add use_ms_timer arg. */ +/* 01/27/05 JRB 13 Log if createSboName fails. */ +/* 12/03/04 JRB 12 Move 61850 code to new module mvl61850_ctl.c.*/ +/* Make initSboCtrl funct global so 61850 */ +/* module can use it too. */ +/* Use strrchr to find last '$'. */ +/* 09/20/04 JRB 11 Replace chk_sbo_select w/ mvlu_sbo_chk_state.*/ +/* Chg chk_sbo_timeouts to mvlu_sbo_chk_timers. */ +/* Do timeouts ONLY in mvlu_sbo_chk_timers. */ +/* Do "Select" only if SBO is ONLY attribute */ +/* being read (not part of higher level var). */ +/* Add funct mvlu_sbo_ctrl_free. */ +/* Del currTime global variable. */ +/* Pass sboTimeout arg to initSboCtrl. */ +/* 12/11/02 JRB 10 Use new mvl_uca.h */ +/* 12/09/02 MDE 09 Changed SBO reference handling */ +/* 10/25/00 JRB 08 Add #ifdef MVL_UCA. */ +/* 07/13/00 JRB 07 Add #ifdef USE_RT_TYPE_2. */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 09/07/99 MDE 05 Changed MVL_VA_SCOPE to MVL_SCOPE */ +/* 12/11/98 MDE 04 Removed scope references from VA */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 02 Minor lint cleanup */ +/* 09/11/98 MDE 01 New */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "mmsdefs.h" +#include "mvl_uca.h" +#include "mvl_log.h" + +#if defined(MVL_UCA) /* This entire module is only valid for UCA. */ + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* Global variables */ +/************************************************************************/ + +MVL_SBO_CTRL sbo_pool[MAX_NUM_SBO_PEND]; + +/************************************************************************/ +/* Static functions */ + +static ST_VOID createSboName (MVL_VAR_ASSOC *va, MVL_SCOPE *va_scope, + ST_CHAR *dest, + ST_BOOLEAN select, ST_RTREF primRef); + +/************************************************************************/ +/************************************************************************/ +/* mvlu_sbo_select_rd_ind */ +/* Leaf function for reading UCA "SBO" attribute (i.e. performing */ +/* Control Model 'Select' Service). */ +/* NOTE: do NOT use this leaf function for IEC 61850 SBO. */ +/************************************************************************/ + +ST_VOID mvlu_sbo_select_rd_ind (MVLU_RD_VA_CTRL *mvluRdVaCtrl) + { +ST_CHAR *dest; +MVL_VAR_ASSOC *va; +MVL_SCOPE *va_scope; +ST_CHAR sboName[MAX_SBO_NAME_SIZE+1]; +MVL_SBO_CTRL *sboCtrl; +ST_CHAR *lastdollar; /* ptr to last '$' in var name */ + +/* First take care of timeout housekeeping */ + mvlu_sbo_chk_timers (); + +/* find the name of the attribute being selected */ + va = mvluRdVaCtrl->rdVaCtrl->va; + +/* Only perform "Select" if SBO is ONLY attribute being read. */ +/* Check this by seeing if variable name ends with "$SBO". */ +/* Point to where "$SBO" should be, then see if it's there. */ + lastdollar = strrchr (va->name, '$'); /* find last '$' */ + if (lastdollar != NULL && strcmp (lastdollar+1, "SBO") == 0) + { + va_scope = &mvluRdVaCtrl->rdVaCtrl->va_scope; + createSboName (va, va_scope, sboName, SD_TRUE, mvluRdVaCtrl->primRef); + +/* Get a SBO control element */ + sboCtrl = initSboCtrl (mvluRdVaCtrl->indCtrl->event->net_info,sboName, + SBO_SELECT_TIMEOUT, SD_FALSE); /* timeout in seconds*/ + if (sboCtrl == NULL) + { + mvlu_rd_prim_done (mvluRdVaCtrl, SD_FAILURE); + return; + } + } + else + /* Higher level variable read. Allow read, but just return NULL (empty) string.*/ + sboName[0]='\0'; + + dest = (ST_CHAR *) mvluRdVaCtrl->primData; + strcpy (dest, sboName); + mvlu_rd_prim_done (mvluRdVaCtrl, SD_SUCCESS); + } + +/************************************************************************/ +/* mvlu_sbo_operate_wr_ind */ +/* NOTE: this leaf function should be used only for UCA (not for 61850).*/ +/************************************************************************/ + +ST_VOID mvlu_sbo_operate_wr_ind (MVLU_WR_VA_CTRL *mvluWrVaCtrl) + { +MVL_SBO_CTRL *sboSelect; +MVL_SCOPE *va_scope; +ST_CHAR sboName[MAX_SBO_NAME_SIZE+1]; + +/* First take care of timeout housekeeping */ + mvlu_sbo_chk_timers (); + + va_scope = &mvluWrVaCtrl->wrVaCtrl->va_scope; + createSboName (mvluWrVaCtrl->wrVaCtrl->va, &mvluWrVaCtrl->wrVaCtrl->va_scope, sboName, SD_FALSE, (ST_RTREF) 0); + sboSelect = mvlu_sbo_chk_state (sboName, + mvluWrVaCtrl->indCtrl->event->net_info); + if (sboSelect != NULL) + { + u_mvl_sbo_operate (sboSelect, mvluWrVaCtrl); + sboSelect->in_use = SD_FALSE; + } + else /* The select was not in place, cannot operate ... */ + { + mvlu_wr_prim_done (mvluWrVaCtrl, SD_FAILURE); + } + } + +/************************************************************************/ +/* mvlu_clr_pend_sbo */ +/************************************************************************/ + +ST_VOID mvlu_clr_pend_sbo (MVL_NET_INFO *net_info) + { +ST_INT i; + + for (i = 0; i < MAX_NUM_SBO_PEND; ++i) + { + if (sbo_pool[i].net_info == net_info) + sbo_pool[i].in_use = SD_FALSE; + } + } + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* mvlu_sbo_chk_timers */ +/************************************************************************/ + +ST_VOID mvlu_sbo_chk_timers () + { +ST_INT i; +MVL_SBO_CTRL *sboCtrl; +time_t currTime; +ST_DOUBLE currTimeMs; /* current time in milliseconds */ + + currTime = time (NULL); /* PORT ISSUE: time() */ + currTimeMs = sGetMsTime (); + sboCtrl = sbo_pool; + for (i = 0; i < MAX_NUM_SBO_PEND; ++i, ++sboCtrl) + { + if (sboCtrl->in_use == SD_TRUE) + { + if (sboCtrl->use_ms_timer) + { + if (sboCtrl->expire_time_ms < currTimeMs) + sboCtrl->in_use = SD_FALSE; /* SBO timer expired */ + } + else /* use timer in seconds */ + { + if (sboCtrl->expire_time < currTime) + sboCtrl->in_use = SD_FALSE; /* SBO timer expired */ + } + /* renxiaobao ¿ØÖÆ */ + if (sboCtrl->in_use != SD_TRUE) + printf("sboCtrl TimeOut : %s currTime: %5.0f \n",sboCtrl->sbo_var,sGetMsTime()); + } + } + } + +/************************************************************************/ +/* initSboCtrl */ +/************************************************************************/ + +MVL_SBO_CTRL *initSboCtrl (MVL_NET_INFO *net_info, + ST_CHAR *sbo_name, + ST_UINT32 sboTimeout, + ST_BOOLEAN use_ms_timer) + { +ST_INT i; +MVL_SBO_CTRL *sboCtrl; +time_t currTime = time (NULL); + +/* OK, now see if the element is already selected */ + sboCtrl = sbo_pool; + for (i = 0; i < MAX_NUM_SBO_PEND; ++i, ++sboCtrl) + { + if (sboCtrl->in_use == SD_TRUE && !strcmp (sboCtrl->sbo_var, sbo_name)) + { + /* OK, already selected, make sure it is us then reset the timeout */ + if (sboCtrl->net_info != net_info) + return (NULL); + + if (sboCtrl->use_ms_timer) + sboCtrl->expire_time_ms = sGetMsTime () + sboTimeout; + else + sboCtrl->expire_time = currTime + sboTimeout; + return (sboCtrl); + } + } + +/* The protected element is not selected, find a unused SBO control */ + sboCtrl = sbo_pool; + for (i = 0; i < MAX_NUM_SBO_PEND; ++i, ++sboCtrl) + { + if (sboCtrl->in_use == SD_FALSE) + break; + } + if (i >= MAX_NUM_SBO_PEND) + return (NULL); + +/* OK, we have a newly selected SBO control, set the parameters */ + sboCtrl->in_use = SD_TRUE; + sboCtrl->use_ms_timer = use_ms_timer; + if (sboCtrl->use_ms_timer) + sboCtrl->expire_time_ms = sGetMsTime () + sboTimeout; + else + sboCtrl->expire_time = currTime + sboTimeout; + sboCtrl->net_info = net_info; + strcpy (sboCtrl->sbo_var, sbo_name); + return (sboCtrl); + } + +/************************************************************************/ +/* mvlu_sbo_chk_state */ +/* Find the MVL_SBO_CTRL struct for this "sboName". */ +/* Call createSboName (for UCA), mvl61850_sbo_create_sboname (for 61850)*/ +/* to generate the "sboName" string to pass to this function. */ +/************************************************************************/ + +MVL_SBO_CTRL *mvlu_sbo_chk_state (ST_CHAR *sboName, + MVL_NET_INFO *net_info) + { +ST_INT i; +MVL_SBO_CTRL *sboCtrl; + +/* See if we have selected the element */ + sboCtrl = sbo_pool; + for (i = 0; i < MAX_NUM_SBO_PEND; ++i, ++sboCtrl) + { + if (sboCtrl->in_use == SD_TRUE && + !strcmp (sboCtrl->sbo_var, sboName) && + sboCtrl->net_info == net_info) + { + return (sboCtrl); + } + } + return (NULL); + } + +/************************************************************************/ +/************************************************************************/ +/* createSboName */ +/* Creates a name to return when an UCA SBO attribute is read. */ +/* NOTE: this name may also be passed to "mvlu_sbo_chk_state" */ +/* to find the correct MVL_SBO_CTRL struct. */ +/************************************************************************/ +static ST_VOID createSboName (MVL_VAR_ASSOC *va, MVL_SCOPE *va_scope, + ST_CHAR *dest, ST_BOOLEAN select, ST_RTREF primRef) + { +ST_INT len; + +/* if primRef is NULL, then don't perform the string table lookup */ + switch (va_scope->scope) + { + case VMD_SPEC: + strcpy (dest, "/"); + break; + + case DOM_SPEC: + strcpy (dest, va_scope->dom->name); + strcat (dest, "/"); + break; + + case AA_SPEC: + strcpy (dest,"@/"); + break; + } + +/* Scope in place, now append the name of variable */ + strcat (dest, va->name); + +/* Now, "SBO" is the end of the name, and the reference is the index */ +/* to the string for the component that is being selected. So, if we */ +/* want the name of the protected element we just replace the "SBO" */ +/* with the element name. */ + if (select == SD_TRUE) + { + len = strlen (dest) - 3; + + if (primRef != 0) + /* primRef must be a pointer to a string; name of protected element */ + strcpy (&dest[len], (ST_CHAR *) primRef); + else + MVL_LOG_ERR1 ("SBO name generated '%s' is invalid", dest); + /* DEBUG: should this function return SD_FAILURE in this case? */ + } + } +/************************************************************************/ +/* mvlu_sbo_ctrl_free */ +/* Frees the MVL_SBO_CTRL struct by setting in_use=SD_FALSE. */ +/* Client must "Select" (i.e. read SBO) again before next "Operate". */ +/************************************************************************/ +void logprint(char * fmt,...); +ST_VOID mvlu_sbo_ctrl_free (MVL_SBO_CTRL *sboCtrl) + { + /* When writing non-SBO variables, sboCtrl == NULL. */ + if (sboCtrl) + { + sboCtrl->in_use = SD_FALSE; + /*renxiaobao ¿ØÖÆ*/ + //logprint("ctrl sboCtrl free : %s currTime: %5.0f \n",sboCtrl->sbo_var,sGetMsTime()); + } + return; + } +#endif /* defined(MVL_UCA) */ diff --git a/mmslib/mvlu/mvluleaf.c b/mmslib/mvlu/mvluleaf.c new file mode 100644 index 0000000..605d452 --- /dev/null +++ b/mmslib/mvlu/mvluleaf.c @@ -0,0 +1,477 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998-2001, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : mvluleaf.c */ +/* PRODUCT(S) : MMSEASE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/11/06 JRB 06 Add mvlu_set_leaf_param_name2. */ +/* mvlu_load_xml_leaf_file: fix error return. */ +/* 09/13/05 JRB 05 Add ERR log if mvlu_find_..._fun_index fails.*/ +/* 07/08/04 JRB 04 Fix "Reference" log msg. */ +/* 12/20/02 JRB 03 mvlu_set_leaf_param moved here. */ +/* MVL_LEAF_FUN_LOOKUP_ENABLE MUST be defined */ +/* for all except mvlu_set_leaf_param. */ +/* 12/11/02 JRB 02 Use new mvl_uca.h */ +/* 11/12/02 MDE 01 New */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mvl_uca.h" +#include "mvl_log.h" + +#if defined(MVL_UCA) /* This entire module is only valid for UCA. */ + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/* Most of the code in this module requires this to be defined. */ +#if defined(MVLU_LEAF_FUN_LOOKUP_ENABLE) + +/************************************************************************/ + +#define MAX_LEAF_NAME 200 +#define MAX_FUN_NAME 200 +#define MAX_REF_NAME 200 + +static ST_VOID _getAttribVal (ST_CHAR *xmlBuf, ST_CHAR *attribName, + ST_CHAR *dest, ST_INT destSize); + +/************************************************************************/ +/************************************************************************/ +/* mvlu_load_xml_leaf_file */ +/* NOTE: continue after errors, but save the last error detected and */ +/* return it. */ +/************************************************************************/ + +ST_RET mvlu_load_xml_leaf_file (ST_CHAR *fileName) + { +FILE *fp; +ST_CHAR leafName[MAX_LEAF_NAME+1]; +ST_CHAR rdIndFunName[MAX_FUN_NAME+1]; +ST_CHAR wrIndFunName[MAX_FUN_NAME+1]; +ST_CHAR refString[MAX_REF_NAME+1]; +ST_CHAR buf[1000]; +ST_CHAR *p; +ST_INT setFlags; +ST_RET ret; +ST_RET last_error = SD_SUCCESS; /* save last error detected */ + + fp = fopen (fileName, "rt"); + if (fp == NULL) + { + MVL_LOG_NERR1 ("Could not open leaf map XML file '%s'", fileName); + return (SD_FAILURE); + } + +/* Now read in the file and set the leaf parameters */ + MVLU_LOG_FLOW1 ("Setting Leaf Parameters using file '%s'", fileName); + ret = SD_SUCCESS; + while (SD_TRUE) + { + leafName[0] = 0; + rdIndFunName[0] = 0; + wrIndFunName[0] = 0; + refString[0] = 0; + + if (fgets (buf, sizeof(buf) - 1, fp) == NULL) + break; + if (strstr (buf, "") != NULL) + continue; + if (strstr (buf, "") != NULL) + break; + p = strstr (buf, " 0) + { + *(dest++) = *(p++); + --destSize; + } + *dest = 0; + } + + +/************************************************************************/ +/* mvlu_set_leaf_param_name */ +/************************************************************************/ + +ST_RET mvlu_set_leaf_param_name (ST_INT setFlags, ST_CHAR *leafName, + ST_CHAR *rdIndFunName, ST_CHAR *wrIndFunName, + ST_CHAR *refString) + { +ST_RTINT rdIndex; +ST_RTINT wrIndex; +ST_RTREF ref; +ST_RET ret; + + if (setFlags & MVLU_SET_RD_FUN) + { + rdIndex = mvlu_find_rd_ind_fun_index (rdIndFunName); + if (rdIndex < 0) + { + /* Error already logged in "mvlu_find_rd.." function. */ + return (SD_FAILURE); + } + } + + if (setFlags & MVLU_SET_WR_FUN) + { + wrIndex = mvlu_find_wr_ind_fun_index (wrIndFunName); + if (wrIndex < 0) + { + /* Error already logged in "mvlu_find_wr.." function. */ + return (SD_FAILURE); + } + } + + ret = u_mvlu_resolve_leaf_ref (leafName, &setFlags, refString, &ref); + if (ret != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Could not resolve reference '%s'", refString); + return (SD_FAILURE); + } + + MVLU_LOG_FLOW1 ("Setting Leaf Parameters for leaf '%s'", leafName); + if (setFlags & MVLU_SET_RD_FUN) + { + MVLU_LOG_CFLOW2 (" Read Indication: %s\t(%d)", rdIndFunName, (int) rdIndex); + } + if (setFlags & MVLU_SET_WR_FUN) + { + MVLU_LOG_CFLOW2 (" Write Indication: %s\t(%d)", wrIndFunName, (int) wrIndex); + } + if (setFlags & MVLU_SET_REF) + { + MVLU_LOG_CFLOW1 (" Reference: 0x%X", (long) ref); + } + + ret = mvlu_set_leaf_param (setFlags, leafName, rdIndex, wrIndex, (ST_RTREF) ref); + if (ret != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Could not set leaf %s parameters", leafName); + } + return (ret); + } + +/************************************************************************/ +/* mvlu_find_rd_ind_fun_index */ +/************************************************************************/ + +ST_RTINT mvlu_find_rd_ind_fun_index (ST_CHAR *funName) + { +ST_RTINT rdIndex; + + for (rdIndex = 0; rdIndex < mvluNumRdFunEntries; ++rdIndex) + { + if (!strcmp (funName, mvluRdFunInfoTbl[rdIndex].fun_name)) + break; + } + if (rdIndex >= mvluNumRdFunEntries) + { + MVL_LOG_ERR1 ("Could not find 'leaf read' function '%s'", funName); + return (-1); + } + + return (rdIndex); + } + +/************************************************************************/ +/* mvlu_find_wr_ind_fun_index */ +/************************************************************************/ + +ST_RTINT mvlu_find_wr_ind_fun_index (ST_CHAR *funName) + { +ST_RTINT wrIndex; + + for (wrIndex = 0; wrIndex < mvluNumWrFunEntries; ++wrIndex) + { + if (!strcmp (funName, mvluWrFunInfoTbl[wrIndex].fun_name)) + break; + } + if (wrIndex >= mvluNumWrFunEntries) + { + MVL_LOG_ERR1 ("Could not find 'leaf write' function '%s'", funName); + return (-1); + } + + return (wrIndex); + } +/************************************************************************/ +#endif /* defined(MVLU_LEAF_FUN_LOOKUP_ENABLE) */ +/************************************************************************/ + +/************************************************************************/ +/* mvlu_set_leaf_param */ +/* DEBUG: could change this to call mvlu_set_leaf_param2 after type found.*/ +/************************************************************************/ + +ST_RET mvlu_set_leaf_param (ST_INT setFlags, ST_CHAR *leafName, + ST_RTINT rdIndFunIndex, ST_RTINT wrIndFunIndex, + ST_RTREF ref) + { +RUNTIME_TYPE *rt; +ST_INT type_id; +ST_CHAR *leafNameBuf; +ST_CHAR *p; + +/* Make a working copy */ + leafNameBuf = chk_strdup (leafName); + rt = NULL; /* Flag that we failed */ + +/* The type name must be the first part of this string */ + p = strstr (leafNameBuf, "$"); + if (p) + { + *p = 0; + type_id = mvl_typename_to_typeid (leafNameBuf); + if (type_id >= 0) + { + ++p; + rt = mvlu_find_rt_leaf (type_id, p); + } + else + { + MVL_LOG_NERR1 ("Could not find type '%s'", leafNameBuf); + } + } + else + { + MVL_LOG_NERR1 ("Could not find type '%s'", leafNameBuf); + } + + chk_free (leafNameBuf); + if (!rt) + return (SD_FAILURE); + + if (setFlags & MVLU_SET_RD_FUN) + { + if (u_mvlu_leaf_rd_ind_fun == NULL && rdIndFunIndex >= mvluNumRdFunEntries) + { + MVL_LOG_NERR0 ("Read ind function index out of range for use with default leaf read handler"); + return (SD_FAILURE); + } + rt->mvluTypeInfo.rdIndFunIndex = rdIndFunIndex; + } + + if (setFlags & MVLU_SET_WR_FUN) + { + if (u_mvlu_leaf_wr_ind_fun == NULL && wrIndFunIndex >= mvluNumWrFunEntries) + { + MVL_LOG_NERR0 ("Write ind function index out of range for use with default leaf write handler"); + return (SD_FAILURE); + } + rt->mvluTypeInfo.wrIndFunIndex = wrIndFunIndex; + } + +#if defined(MVLU_USE_REF) + if (setFlags & MVLU_SET_REF) + rt->mvluTypeInfo.ref = ref; +#endif /* MVLU_USE_REF */ + return (SD_SUCCESS); + } + +/************************************************************************/ +/* mvlu_set_leaf_param2 */ +/* Similar to mvlu_set_leaf_param but uses additional base_var_type_id arg.*/ +/************************************************************************/ +static ST_RET mvlu_set_leaf_param2 (ST_INT base_var_type_id, + ST_INT setFlags, + ST_CHAR *leafName, + ST_RTINT rdIndFunIndex, + ST_RTINT wrIndFunIndex, + ST_RTREF ref) + { +RUNTIME_TYPE *rt; +ST_CHAR *p; + + /* The name to find starts after the first '$'. */ + p = strstr (leafName, "$"); + if (p) + { + ++p; /* point after '$' */ + rt = mvlu_find_rt_leaf (base_var_type_id, p); + if (!rt) + MVL_LOG_NERR1 ("Cannot find leaf '%s'", leafName); + } + else + { + MVL_LOG_NERR1 ("Cannot find leaf. No '$' in leaf name '%s'", leafName); + rt = NULL; + } + + if (!rt) + return (SD_FAILURE); + + if (setFlags & MVLU_SET_RD_FUN) + { + if (u_mvlu_leaf_rd_ind_fun == NULL && rdIndFunIndex >= mvluNumRdFunEntries) + { + MVL_LOG_NERR0 ("Read ind function index out of range for use with default leaf read handler"); + return (SD_FAILURE); + } + rt->mvluTypeInfo.rdIndFunIndex = rdIndFunIndex; + } + + if (setFlags & MVLU_SET_WR_FUN) + { + if (u_mvlu_leaf_wr_ind_fun == NULL && wrIndFunIndex >= mvluNumWrFunEntries) + { + MVL_LOG_NERR0 ("Write ind function index out of range for use with default leaf write handler"); + return (SD_FAILURE); + } + rt->mvluTypeInfo.wrIndFunIndex = wrIndFunIndex; + } + +#if defined(MVLU_USE_REF) + if (setFlags & MVLU_SET_REF) + rt->mvluTypeInfo.ref = ref; +#endif /* MVLU_USE_REF */ + return (SD_SUCCESS); + } + +/************************************************************************/ +/* mvlu_set_leaf_param_name2 */ +/* Similar to mvlu_set_leaf_param_name but uses additional base_var_type_id arg.*/ +/************************************************************************/ +ST_RET mvlu_set_leaf_param_name2 (ST_INT base_var_type_id, + ST_INT setFlags, + ST_CHAR *leafName, + ST_CHAR *rdIndFunName, + ST_CHAR *wrIndFunName, + ST_CHAR *refString) + { +ST_RTINT rdIndex; +ST_RTINT wrIndex; +ST_RTREF ref; +ST_RET ret; + + if (setFlags & MVLU_SET_RD_FUN) + { + rdIndex = mvlu_find_rd_ind_fun_index (rdIndFunName); + if (rdIndex < 0) + { + /* Error already logged in "mvlu_find_rd.." function. */ + return (SD_FAILURE); + } + } + + if (setFlags & MVLU_SET_WR_FUN) + { + wrIndex = mvlu_find_wr_ind_fun_index (wrIndFunName); + if (wrIndex < 0) + { + /* Error already logged in "mvlu_find_wr.." function. */ + return (SD_FAILURE); + } + } + + ret = u_mvlu_resolve_leaf_ref (leafName, &setFlags, refString, &ref); + if (ret != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Could not resolve reference '%s'", refString); + return (SD_FAILURE); + } + + MVLU_LOG_FLOW1 ("Setting Leaf Parameters for leaf '%s'", leafName); + if (setFlags & MVLU_SET_RD_FUN) + { + MVLU_LOG_CFLOW2 (" Read Indication: %s\t(%d)", rdIndFunName, (int) rdIndex); + } + if (setFlags & MVLU_SET_WR_FUN) + { + MVLU_LOG_CFLOW2 (" Write Indication: %s\t(%d)", wrIndFunName, (int) wrIndex); + } + if (setFlags & MVLU_SET_REF) + { + MVLU_LOG_CFLOW1 (" Reference: 0x%X", (long) ref); + } + + ret = mvlu_set_leaf_param2 (base_var_type_id, setFlags, leafName, rdIndex, wrIndex, (ST_RTREF) ref); + if (ret != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Could not set leaf %s parameters", leafName); + } + return (ret); + } + +/************************************************************************/ +#endif /* defined(MVL_UCA) */ +/************************************************************************/ diff --git a/mmslib/mvlu/s_cancel.c b/mmslib/mvlu/s_cancel.c new file mode 100644 index 0000000..e5e88a3 --- /dev/null +++ b/mmslib/mvlu/s_cancel.c @@ -0,0 +1,53 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : s_cancel.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/11/04 GLB 09 Remove "thisFileName" */ +/* 09/21/01 JRB 08 Alloc global bufs only once at startup. */ +/* 01/21/00 MDE 07 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 04/01/99 MDE 05 Changes to decode buffer allocation scheme */ +/* 11/16/98 MDE 04 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 03 Minor lint cleanup */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pvmd.h" + +#include "mvl_defs.h" +#include "mvl_log.h" + + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_cancel_ind */ +/* A MMS MMSOP_CANCEL request has been received. For now, just send error */ +/************************************************************************/ + +ST_VOID _mvl_process_cancel_ind (MVL_COMM_EVENT *event) + { +ST_RET rc; + +/* Build cancel error response message, */ +/* class = Cancel, code = 'Cancel Not Possible' */ + rc = mpl_cancel_err (event->u.mms.dec_rslt.id, 10, 2); + _mvl_send_resp (event, rc); + } + diff --git a/mmslib/mvlu/s_concl.c b/mmslib/mvlu/s_concl.c new file mode 100644 index 0000000..c59f669 --- /dev/null +++ b/mmslib/mvlu/s_concl.c @@ -0,0 +1,99 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : s_concl.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/14/08 JRB 07 Add mplas_concl_err. */ +/* 05/01/02 MDE 06 Added MLOG logging */ +/* 10/25/00 JRB 05 Pass ind up to user. User must call resp fct */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mvl_defs.h" +#include "mvl_log.h" +#include "mloguser.h" + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_concl_ind */ +/* A Conclude indication has been received. Pass it up to user. */ +/************************************************************************/ + +ST_VOID _mvl_process_concl_ind (MVL_COMM_EVENT *event) + { + /* Pass up to user for processing. User must call mplas_concl_resp */ + /* to send Conclude response. */ + u_mvl_concl_ind (event); + } + + +/************************************************************************/ +/* _mvl_process_concl_ind */ +/* Send Conclude response. */ +/************************************************************************/ +ST_VOID mplas_concl_resp (MVL_COMM_EVENT *event) + { +ST_RET rc; + +/* We can log here if so desired */ + if ((mms_debug_sel & MMS_LOG_RESP) && ml_log_resp_info_fun != NULL) + (*ml_log_resp_info_fun) (0, MMSOP_CONCLUDE, NULL); + +/* Send a Conclude response */ + rc = _mvl_send_msg ((ST_UCHAR *) "\x8C\x00",2,event->net_info); + + if (rc != SD_SUCCESS) + MVL_LOG_NERR1 ("Conclude Indication : _mvl_send_msg failed, ret = %x", rc); + _mvl_free_comm_event (event); /* All done with this event */ + } + +/************************************************************************/ +/* mplas_concl_err */ +/* Send Conclude error response. */ +/* NOTE: err_class should always be 9, and err_code should be 0 or 1. */ +/************************************************************************/ +ST_RET mplas_concl_err (MVL_COMM_EVENT *event, ST_INT16 err_class, ST_INT16 err_code) + { +ST_RET rc; + rc = mpl_conclude_err (err_class,err_code); /* encode Conclude-ErrorPDU*/ + if (rc) + { /* Should never happen. No good recovery. */ + MVL_LOG_ERR1 ("Error encoding Conclude-ErrorPDU, rc = %x", rc); + } + else + { /* send it */ + rc = _mvl_send_msg (mmsl_msg_start,mmsl_msg_len,event->net_info); + if (rc != SD_SUCCESS) + MVL_LOG_ERR1 ("Error sending Conclude-ErrorPDU, rc = %x", rc); + } + return (rc); + } diff --git a/mmslib/mvlu/s_defvl.c b/mmslib/mvlu/s_defvl.c new file mode 100644 index 0000000..45e4d1d --- /dev/null +++ b/mmslib/mvlu/s_defvl.c @@ -0,0 +1,137 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : s_defvl.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_defvlist_ind */ +/* mvlas_defvlist_resp */ +/* mplas_defvlist_resp */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/06/08 JRB 17 Send error resp if any variable not Named. */ +/* 04/09/07 MDE 16 Enhanced filtered logging */ +/* 02/21/07 JRB 15 Fix comment. */ +/* 10/30/06 JRB 14 Use new mvl_vmd_* object handling functions. */ +/* 01/30/06 GLB 13 Integrated porting changes for VMS */ +/* 09/21/01 JRB 12 Alloc global bufs only once at startup. */ +/* 01/21/00 MDE 11 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 10 Added SD_CONST modifiers */ +/* 01/20/99 JRB 09 Use new mvl_nvl_add (simpler, more efficient)*/ +/* 01/14/99 JRB 08 BUG FIX: Increment variable_list in loop. */ +/* 12/11/98 MDE 07 Removed scope references from VA */ +/* 11/16/98 MDE 06 Allow use of manufactured variables */ +/* 11/16/98 MDE 05 Renamed internal functions (prefix '_') */ +/* 07/09/98 JRB 04 Set altAcc=NULL (no alternate access). */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 06/05/98 MDE 02 Moved 'mvl_insert_nvlist' elsewhere */ +/* 04/14/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* _mvl_process_defvlist_ind */ +/* A "defvlist" indication has been received, process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_defvlist_ind (MVL_IND_PEND *indCtrl) + { + indCtrl->u.defvlist.req_info = + (DEFVLIST_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + u_mvl_defvlist_ind (indCtrl); + } + +/************************************************************************/ +/* mvlas_defvlist_resp */ +/* Most of this code doesn't care whether the Named Variable List is */ +/* VMD-specific, Dom-specific, etc. */ +/************************************************************************/ +ST_VOID mvlas_defvlist_resp (MVL_IND_PEND *indCtrl) + { +MVL_NVLIST_CTRL *nvlist_ctrl; /* alloc, fill in, & then copy to list */ +ST_INT j; +VARIABLE_LIST *variable_list; +DEFVLIST_REQ_INFO *req_info = indCtrl->u.defvlist.req_info; +OBJECT_NAME *tmp_obj_array; + + if (req_info->num_of_variables <= 0) + { + _mplas_err_resp (indCtrl,4,0); /* Service error , other */ + return; + } + + variable_list = (VARIABLE_LIST *) (req_info + 1); + + /* Create temporary obj array from var list. */ + tmp_obj_array = (OBJECT_NAME *) M_MALLOC (MSMEM_GEN, req_info->num_of_variables * sizeof (OBJECT_NAME)); + for (j = 0; j < req_info->num_of_variables; j++, variable_list++) + { + if (variable_list->var_spec.var_spec_tag != VA_SPEC_NAMED) + { /* Only "Named" variables supported */ + _mplas_err_resp (indCtrl, MMS_ERRCLASS_DEFINITION, MMS_ERRCODE_TYPE_UNSUPPORTED); + M_FREE (MSMEM_GEN, tmp_obj_array); /* cleanup */ + return; /* stop now */ + } + memcpy (&tmp_obj_array [j], &variable_list->var_spec.vs.name, sizeof (OBJECT_NAME)); + } + + /* NOTE: Use "obj_name.vmd_spec" for an object of any scope, */ + /* because "obj_name" is a union of identical type objects. */ + nvlist_ctrl = mvl_vmd_nvl_add (&mvl_vmd, &req_info->vl_name, indCtrl->event->net_info, + req_info->num_of_variables, tmp_obj_array, + SD_TRUE); /* copy name because it is volatile */ + + M_FREE (MSMEM_GEN, tmp_obj_array); /* free temporary object array. */ + + if (nvlist_ctrl == NULL) + { /* Failed. */ + _mplas_err_resp (indCtrl,4,0); /* Service error, other */ + return; + } + + nvlist_ctrl->mms_deletable = SD_TRUE; /* MMS spec requires this*/ + nvlist_ctrl->altAcc = NULL; /* Don't support alternate access*/ + + mplas_defvlist_resp (indCtrl); + } + + +/************************************************************************/ +/* mplas_defvlist_resp */ +/************************************************************************/ +ST_VOID mplas_defvlist_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + + /* Build a "defvlist" response (no response info). */ + rc = mpl_defvlist_resp (indCtrl->event->u.mms.dec_rslt.id); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, NULL); + + _mvl_send_resp_i (indCtrl, rc); + } + diff --git a/mmslib/mvlu/s_delvl.c b/mmslib/mvlu/s_delvl.c new file mode 100644 index 0000000..ffc3ac4 --- /dev/null +++ b/mmslib/mvlu/s_delvl.c @@ -0,0 +1,190 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : s_delvl.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_delvlist_ind */ +/* mvlas_delvlist_resp */ +/* mplas_delvlist_resp */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 16 Enhanced filtered logging */ +/* 10/30/06 JRB 15 Use new mvl_vmd_* object handling functions. */ +/* 08/21/06 JRB 14 Check mms_deletable flag in DELVL_SPEC case. */ +/* 09/21/01 JRB 13 Alloc global bufs only once at startup. */ +/* 07/13/00 JRB 12 Init num_matched, num_deleted for DELVL_SPEC.*/ +/* 01/21/00 MDE 11 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 10 Added SD_CONST modifiers */ +/* 04/07/99 JRB 09 Add support for SPECIFIC scope. */ +/* 04/07/99 MDE 08 Logging improvements */ +/* 01/21/99 JRB 07 Add support for AA-specific scope. */ +/* 01/14/99 JRB 06 Use new "bsearch" object model. */ +/* 11/16/98 MDE 05 Now use '_mvl_destroy_nvl_entries' */ +/* 11/16/98 MDE 04 Renamed internal functions (prefix '_') */ +/* 06/22/98 MDE 03 More changes to allow compile under C++ */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 04/14/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +static ST_RET delete_nvlist (DELVLIST_RESP_INFO *resp_info, + ST_INT *num_nvlist, + MVL_NVLIST_CTRL **nvlist_tbl); +/************************************************************************/ +/* _mvl_process_delvlist_ind */ +/* A "delvlist" indication has been received, process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_delvlist_ind (MVL_IND_PEND *indCtrl) + { + indCtrl->u.delvlist.req_info = + (DELVLIST_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + u_mvl_delvlist_ind (indCtrl); + } + +/************************************************************************/ +/* mvlas_delvlist_resp */ +/************************************************************************/ +ST_VOID mvlas_delvlist_resp (MVL_IND_PEND *indCtrl) + { +DELVLIST_RESP_INFO resp_info; +DELVLIST_REQ_INFO *req_info = indCtrl->u.delvlist.req_info; +MVL_DOM_CTRL *mvl_dom; +MVL_AA_OBJ_CTRL *aa_objs; +ST_INT j; +OBJECT_NAME *obj_name; +MVL_NVLIST_CTRL *nvl; + + if (req_info->scope == DELVL_VMD) + { + /* "delete_nvlist" deletes all deletable ("mvl_obj_delete" can't).*/ + if (delete_nvlist (&resp_info, &mvl_vmd.num_nvlist, mvl_vmd.nvlist_tbl)) + { + _mplas_err_resp (indCtrl,4,0); /* Service error , other */ + return; + } + } + else if (req_info->scope == DELVL_DOM) + { + mvl_dom = mvl_vmd_find_dom (&mvl_vmd, req_info->dname); + if (mvl_dom == NULL) + { + MVL_LOG_NERR1 ("Delete NVL ind: Domain '%s' not found", req_info->dname); + _mplas_err_resp (indCtrl,2,1); /* Object undefined */ + return; + } + /* "delete_nvlist" deletes all deletable ("mvl_obj_delete" can't).*/ + if (delete_nvlist (&resp_info, &mvl_dom->num_nvlist, mvl_dom->nvlist_tbl)) + { + _mplas_err_resp (indCtrl,4,0); /* Service error , other */ + return; + } + } + else if (req_info->scope == DELVL_AA) + { + aa_objs = indCtrl->event->net_info->aa_objs; + /* "delete_nvlist" deletes all deletable ("mvl_obj_delete" can't).*/ + if (delete_nvlist (&resp_info, &aa_objs->num_nvlist, aa_objs->nvlist_tbl)) + { + _mplas_err_resp (indCtrl,4,0); /* Service error , other */ + return; + } + } + else + { /* Must be DELVL_SPEC (i.e. delete listed NVLs). */ + /* Init "obj_name" to point to array of OBJECT_NAME structs which */ + /* MMS decoder puts right after the "req_info" struct. */ + resp_info.num_matched = 0; + resp_info.num_deleted = 0; + + obj_name = (OBJECT_NAME *) (req_info + 1); + for (j = 0; j < req_info->num_of_vnames; j++, obj_name++) + { + if ((nvl = mvl_vmd_find_nvl (&mvl_vmd, obj_name, indCtrl->event->net_info)) != NULL) + { + resp_info.num_matched++; + if (nvl->mms_deletable && + mvl_vmd_nvl_remove (&mvl_vmd, obj_name, indCtrl->event->net_info) == SD_SUCCESS) + resp_info.num_deleted++; + } + } + } + indCtrl->u.delvlist.resp_info = &resp_info; + mplas_delvlist_resp (indCtrl); + } + +/************************************************************************/ +/* mplas_delvlist_resp */ +/************************************************************************/ +ST_VOID mplas_delvlist_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + + /* Build a "delvlist" response */ + rc = mpl_delvlist_resp (indCtrl->event->u.mms.dec_rslt.id, + indCtrl->u.delvlist.resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, indCtrl->u.delvlist.resp_info); + + _mvl_send_resp_i (indCtrl, rc); + } + +/************************************************************************/ +/* delete_nvlist */ +/* This function deletes all nvlists with "mms_deletable == TRUE". */ +/* It is more efficient than multiple calls to "mvl_obj_delete" */ +/* because it deletes multiple entries with one call. */ +/* This function fills in "resp_info" and modifies "*num_mvlist" and */ +/* the array pointed to by "nvlist_tbl". */ +/************************************************************************/ +static ST_RET delete_nvlist (DELVLIST_RESP_INFO *resp_info, + ST_INT *num_nvlist, + MVL_NVLIST_CTRL **nvlist_tbl) + { +ST_INT j, k; + + resp_info->num_matched = (*num_nvlist); + resp_info->num_deleted = 0; /* Init count. */ + for (j = 0, k = 0; j < (*num_nvlist); j++) + { + if (nvlist_tbl[j]->mms_deletable) + { + /* free up allocated resources for this nvlist */ + mvl_nvl_destroy (nvlist_tbl[j]); + resp_info->num_deleted++; /* Increment count. */ + } + else + { /* move this entry up in array. */ + nvlist_tbl[k] = nvlist_tbl[j]; + k++; /* Increment count of entries left. */ + } + } + + (*num_nvlist) -= (ST_INT) resp_info->num_deleted; + return (SD_SUCCESS); + } diff --git a/mmslib/mvlu/s_fclose.c b/mmslib/mvlu/s_fclose.c new file mode 100644 index 0000000..c1a4f12 --- /dev/null +++ b/mmslib/mvlu/s_fclose.c @@ -0,0 +1,68 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : s_fclose.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_fclose_ind */ +/* mplas_fclose_resp */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 11 Enhanced filtered logging */ +/* 03/11/04 GLB 10 Remove "thisFileName" */ +/* 09/21/01 JRB 09 Alloc global bufs only once at startup. */ +/* 01/21/00 MDE 08 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 04/01/99 MDE 06 Changes to decode buffer allocation scheme */ +/* 11/16/98 MDE 05 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 04 Minor lint cleanup */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 05/14/98 JRB 02 Use MVL_IND_PEND. Add mvlas resp function. */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "mvl_defs.h" +#include "mvl_log.h" + + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_fclose_ind */ +/* A file close indication has been received, process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_fclose_ind (MVL_IND_PEND *indCtrl) + { + indCtrl->u.fclose.req_info = + (FCLOSE_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + u_mvl_fclose_ind (indCtrl); + } + +/************************************************************************/ +/* mplas_fclose_resp */ +/************************************************************************/ +ST_VOID mplas_fclose_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + + /* Build a File Close response */ + rc = mpl_fclose_resp (indCtrl->event->u.mms.dec_rslt.id); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, NULL); + + _mvl_send_resp_i (indCtrl, rc); + } + diff --git a/mmslib/mvlu/s_fdel.c b/mmslib/mvlu/s_fdel.c new file mode 100644 index 0000000..8a64dad --- /dev/null +++ b/mmslib/mvlu/s_fdel.c @@ -0,0 +1,77 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : s_fdel.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_fdelete_ind */ +/* mplas_fdelete_resp */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 10 Enhanced filtered logging */ +/* 03/11/04 GLB 09 Remove "thisFileName" */ +/* 09/21/01 JRB 08 Alloc global bufs only once at startup. */ +/* 01/21/00 MDE 07 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 04/01/99 MDE 05 Changes to decode buffer allocation scheme */ +/* 11/16/98 MDE 04 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 03 Minor lint cleanup */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 04/14/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* _mvl_process_fdelete_ind */ +/* A "fdelete" indication has been received, process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_fdelete_ind (MVL_IND_PEND *indCtrl) + { +FDELETE_REQ_INFO *req_info; +MVLAS_FDELETE_CTRL *fdelete; + + fdelete = &indCtrl->u.fdelete; + + req_info = (FDELETE_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + if (_mvl_concat_filename (fdelete->filename, req_info->num_of_fname, + (FILE_NAME *)(req_info + 1), sizeof (fdelete->filename))) + { + _mplas_err_resp (indCtrl,11,3); /* File name syntax error */ + return; + } + + u_mvl_fdelete_ind (indCtrl); + } + +/************************************************************************/ +/* mplas_fdelete_resp */ +/************************************************************************/ +ST_VOID mplas_fdelete_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + + /* Build a "fdelete" response */ + rc = mpl_fdelete_resp (indCtrl->event->u.mms.dec_rslt.id); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, NULL); + + _mvl_send_resp_i (indCtrl, rc); + } + + diff --git a/mmslib/mvlu/s_fdir.c b/mmslib/mvlu/s_fdir.c new file mode 100644 index 0000000..9baefee --- /dev/null +++ b/mmslib/mvlu/s_fdir.c @@ -0,0 +1,769 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : s_fdir.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_fdir_ind */ +/* mplas_fdir_resp */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 13 Enhanced filtered logging */ +/* 03/09/05 CRM 12 Added mvlas_fdir_resp, convertFileTime, and */ +/* fileFdirEnt functions for WIN32 defined */ +/* 09/21/01 JRB 11 Alloc global bufs only once at startup. */ +/* 03/30/01 MDE 10 Changed MSMEM_ENC_INFO to MSMEM_ENC_OS_INFO */ +/* 09/13/00 JRB 09 Compute resp_info size (don't use const). */ +/* 01/21/00 MDE 08 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 04/01/99 MDE 06 Changes to decode buffer allocation scheme */ +/* 11/16/98 MDE 05 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 04 Minor lint cleanup */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 05/14/98 JRB 02 Use MVL_IND_PEND. Add mvlas resp function. */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/*-----------------------------------------*/ +/* Global definitions used by all systems */ +/*-----------------------------------------*/ +/* +#define SERVICE_OVRHD 20 +#define DIR_ENTRY_OVRHD 32 +*/ +#define SERVICE_OVRHD 256 +#define DIR_ENTRY_OVRHD 64 + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_fdir_ind */ +/* A fdir indication has been received, process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_fdir_ind (MVL_IND_PEND *indCtrl) + { +FDIR_REQ_INFO *req_info; +FILE_NAME *fs_fname; /* ptr to array of FILE_NAME for "fs" */ +FILE_NAME *ca_fname; /* ptr to array of FILE_NAME for "ca" */ +MVLAS_FDIR_CTRL *fdir; + + fdir = &indCtrl->u.fdir; + + req_info = (FDIR_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + /* fs_fname array is right after req_info */ + fs_fname = (FILE_NAME *)(req_info + 1); + /* ca_fname array is right after fs_fname array */ + ca_fname = fs_fname + req_info->num_of_fs_fname; + + if (req_info->filespec_pres) + { + if (_mvl_concat_filename (fdir->fs_filename, req_info->num_of_fs_fname, + fs_fname, sizeof (fdir->fs_filename))) + { + _mplas_err_resp (indCtrl,11,3); /* File name syntax error */ + return; + } + } + else + fdir->fs_filename[0] = 0; + + if (req_info->cont_after_pres) + { + if (_mvl_concat_filename (fdir->ca_filename, req_info->num_of_ca_fname, + ca_fname, sizeof (fdir->ca_filename))) + { + _mplas_err_resp (indCtrl,11,3); /* File name syntax error */ + return; + } + } + else + fdir->ca_filename[0] = 0; + + u_mvl_fdir_ind (indCtrl); + } + +/************************************************************************/ +/* mplas_fdir_resp */ +/************************************************************************/ +ST_VOID mplas_fdir_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; +FDIR_RESP_INFO *resp_info; +ST_UINT resp_size; /* size of "resp_info" */ +FDIR_DIR_ENT *fdir_entry; +FILE_NAME *fname; +ST_INT j; +MVL_FDIR_RESP_INFO *mvl_resp_info; + + + mvl_resp_info = indCtrl->u.fdir.resp_info; + +/* Compute size needed for "resp_info". */ +/* NOTE: num_of_fname is always 1, so total_num_of_fname = num_dir_ent. */ + resp_size = sizeof (FDIR_RESP_INFO) + + (mvl_resp_info->num_dir_ent * sizeof (FDIR_DIR_ENT)) + + (mvl_resp_info->num_dir_ent * sizeof (FILE_NAME)); + resp_info = (FDIR_RESP_INFO *) M_CALLOC (MSMEM_ENC_OS_INFO, 1, resp_size); + + resp_info->num_dir_ent = mvl_resp_info->num_dir_ent; + resp_info->more_follows = mvl_resp_info->more_follows; + for (j = 0, fdir_entry = (FDIR_DIR_ENT *) (resp_info + 1); + j < resp_info->num_dir_ent; j++) + { + fdir_entry->fsize = mvl_resp_info->dir_ent[j].fsize; + fdir_entry->mtimpres = mvl_resp_info->dir_ent[j].mtimpres; + fdir_entry->mtime = mvl_resp_info->dir_ent[j].mtime; + fdir_entry->num_of_fname = 1; /* we always use 1 */ + + fname = (FILE_NAME *) (fdir_entry + 1); + fname->fn_len = strlen (mvl_resp_info->dir_ent[j].filename); + fname->fname = mvl_resp_info->dir_ent[j].filename; + + /* always 1 fname, so point after it to get to next fdir_entry. */ + fdir_entry = (FDIR_DIR_ENT *) (fname + 1); + } + + /* Build a File Directory response */ + rc = mpl_fdir_resp (indCtrl->event->u.mms.dec_rslt.id, resp_info); + _mvl_send_resp_i (indCtrl, rc); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, indCtrl->u.getvar.resp_info); + + + M_FREE (MSMEM_ENC_OS_INFO, resp_info); + } + + +/*renxiaobao Îļþ²Ù×÷*/ +#if defined(linux) || defined(__ECOS) || defined(VXWORKS) +#include +int MMS_DIR_READ_MAX = 200; +ST_VOID fillFdirEnt (struct stat *pstFindData, FDIR_DIR_ENT *pstFdirEnt, + FILE_NAME *pstFileName, ST_CHAR *nameBuffer,ST_CHAR *FileName) +{ + time_t theTime; + /* Fill in the FDIR_DIR_ENT struct. */ + /*printf("%s st_size %d st_mtime %lu ...\n",FileName,pstFindData->st_size,pstFindData->st_mtime);*/ + theTime = pstFindData->st_mtime; + pstFdirEnt->fsize = pstFindData->st_size ; + /* theTime = 1022036250; + if (theTime == -1) */ + if (theTime < 0) + { + printf("fillFdirEnt theTime = %lx\n",theTime); + pstFdirEnt->mtimpres = SD_FALSE; + } + else + { + pstFdirEnt->mtimpres = SD_TRUE; + pstFdirEnt->mtime = (ST_INT32) theTime; + } + pstFdirEnt->num_of_fname = 1; + /* Fill in nameBuffer. */ + strcpy (nameBuffer, FileName); + if(S_ISDIR (pstFindData->st_mode)) + { + /*strcat (nameBuffer, "\\");*/ + strcat (nameBuffer, "/"); + pstFdirEnt->fsize = pstFindData->st_size ; + } + /* Fill in the FILE_NAME struct. */ + pstFileName->fname = nameBuffer; + pstFileName->fn_len = strlen (nameBuffer); +} + + +short fdir_fullname_flag=1; +extern int mms_filename_conv(char *mms_name,char *sys_name); +extern int mms_open_root_dir(); +extern char mms_root_dir_buf[16][32]; +extern char sys_root_dir_buf[16][32]; +int root_dir_num=0; +#if defined(__ECOS) +void UTF_8ToGB2312(char *pOut, char *pText, int pLen); +char *GB_UTF(unsigned char *p_desStr,unsigned char *p_srcStr); +#define file_utf_to_gb2312 UTF_8ToGB2312 +#define file_gb2312_to_utf GB_UTF +#endif +#if defined(VXWORKS) +void gb2312_convert_uft8(char *p_desStr,char *p_srcStr); +void utf8_convert_gb2312(char *pOut, char *pText, int pLen); +#define file_utf_to_gb2312 utf8_convert_gb2312 +#define file_gb2312_to_utf gb2312_convert_uft8 +#endif +ST_VOID mvlas_fdir_resp (MVL_IND_PEND *indCtrl) +{ + ST_INT status,ret; + ST_CHAR tmp_name [128]; + ST_CHAR sys_name [128]; + ST_CHAR fs_name [128]; + ST_CHAR ca_name [128]; + ST_CHAR filename [128]; + FDIR_RESP_INFO *rsp_ptr; + FDIR_DIR_ENT *dir_ptr; + ST_INT rsp_size; + ST_CHAR *name_ptr; + ST_INT total_len, doMore; + FILE_NAME *fname_ptr; + ST_UCHAR found_ca = SD_FALSE; + ST_CHAR *data_buf; + MVLAS_FDIR_CTRL *fdir_ctrl; + ST_INT negotiatedPduSize; + ST_INT max_dir_ents; + ST_RET rc; + DIR *dir=0; + struct dirent *dirptr; + struct stat file_stat; + MVL_FDIR_RESP_INFO resp_info; + ST_CHAR *tmp_dir_ent_array; + short i; + char *str; + /* calculate the maximum message size and number of directory entries */ + negotiatedPduSize = (ST_INT) indCtrl->event->net_info->max_pdu_size; + max_dir_ents = (negotiatedPduSize - SERVICE_OVRHD) / DIR_ENTRY_OVRHD; + /* set the number of directory entries and allocate memory for response info */ + fdir_ctrl = &indCtrl->u.fdir; + /****************************/ + /* ¹ã¶«µçÍøÐÞ¸ÄÖÐÎÄÃû³Æ×ª»» */ + /****************************/ + file_utf_to_gb2312(tmp_name,fdir_ctrl->fs_filename,strlen(fdir_ctrl->fs_filename)); + strcpy(fdir_ctrl->fs_filename,tmp_name); + file_utf_to_gb2312(tmp_name,fdir_ctrl->ca_filename,strlen(fdir_ctrl->ca_filename)); + strcpy(fdir_ctrl->ca_filename,tmp_name); + /****************************/ + /* Ŀ¼Ãû¼ì²é */ + /****************************/ + if((strlen(fdir_ctrl->fs_filename)==0)||(strstr(fdir_ctrl->fs_filename,"*"))) + strcpy (fs_name, "/"); + else + strcpy (fs_name, fdir_ctrl->fs_filename); + /****************************/ + /* Ä¿Â¼Ðø¶Á */ + /****************************/ + strcpy (ca_name, fdir_ctrl->ca_filename); + /*Ðø¶ÁÎļþÃû²ð·Ö*/ + if((strlen (ca_name))&&(strrchr(ca_name,'/'))) + { + strcpy (fs_name,ca_name); + str = strrchr(fs_name,'/'); + strcpy (ca_name,str+1); + *(str+1) = 0; + printf("Ä¿Â¼Ðø¶Á²ð·Ö:%s fs_name:%s ca_name:%s...\n\r",fdir_ctrl->ca_filename,fs_name,ca_name); + } + if(strlen (ca_name)) found_ca = SD_FALSE; + else found_ca = SD_TRUE; + /****************************/ + /* ¸ùĿ¼¶ÁÈ¡ */ + /****************************/ + if(strcmp(fs_name, "/")==0) + { + root_dir_num = mms_open_root_dir(); + if(root_dir_num==0) printf("¸ùĿ¼¶Áȡʧ°Ü...\n\r"); + /*¸ùĿ¼icdÎļþ*/ + ret = stat ("/etc/device.icd", &file_stat); + if(ret==0) strcpy(mms_root_dir_buf[root_dir_num++],"/device.icd"); + else printf("%s stat ʧ°Ü...\n\r","/etc/device.icd"); + + resp_info.num_dir_ent = root_dir_num; + resp_info.more_follows = SD_FALSE; + tmp_dir_ent_array = (ST_CHAR *) chk_calloc (resp_info.num_dir_ent, sizeof(MVL_DIR_ENT)); + resp_info.dir_ent = (MVL_DIR_ENT *) tmp_dir_ent_array; + for(i=0;iresp_info = &resp_info; + mplas_fdir_resp (indCtrl); + chk_free (tmp_dir_ent_array); + return; + } + /*---------------------------------------------------------*/ + /* Find maximum response buffer size, calloc space for it, */ + /* and initialize the response structure variables. */ + /*---------------------------------------------------------*/ + rsp_size = sizeof (FDIR_RESP_INFO)+( max_dir_ents * sizeof (FDIR_DIR_ENT) )+( max_dir_ents * sizeof (FILE_NAME) ); + rsp_ptr = (FDIR_RESP_INFO *) chk_calloc (1,rsp_size); + data_buf = chk_malloc (negotiatedPduSize); + rsp_ptr->num_dir_ent = 0; + rsp_ptr->more_follows = SD_FALSE; + /*---------------------------------*/ + /* Initialize some other variables */ + /*---------------------------------*/ + name_ptr = data_buf; + total_len = 0; + status = SD_SUCCESS; + fname_ptr = ( FILE_NAME * )( fdir_ctrl + 1 ); + /****************************/ + /* Ŀ¼ÐÅÏ¢¶ÁÈ¡ */ + /****************************/ + if(fs_name[strlen (fs_name)-1]!='/') strcat(fs_name,"/"); + ret = mms_filename_conv(fs_name,sys_name); + if(sys_name[strlen (sys_name)-1]!='/') strcat(sys_name,"/"); + dir = opendir(sys_name); + if((!ret)||(!dir)) + { + printf("Ŀ¼ %s - %s¶Áȡʧ°Ü...\n\r",fs_name,sys_name); + status = SD_FAILURE; + } + if(status == SD_SUCCESS ) + { + if ((dirptr = readdir(dir))) + { + dir_ptr = (FDIR_DIR_ENT *)(rsp_ptr + 1); + fname_ptr = (FILE_NAME *)(dir_ptr + 1); + doMore = SD_TRUE; + while(doMore ) + { + /* Ä¿Â¼Ðø¶Á */ + if(! found_ca &&(!strcmp (dirptr->d_name, ca_name))) found_ca = SD_TRUE; + if(!(found_ca && (strcmp (dirptr->d_name, ca_name)))) + { + if(!(dirptr = readdir(dir))) doMore = SD_FALSE; + continue; + } + /* Discard the . and .. entries */ + if (!strcmp (dirptr->d_name, ".")|| !strcmp (dirptr->d_name, "..")) + { + if(!(dirptr = readdir(dir))) doMore = SD_FALSE; + continue; + } + /*Ó³Éä±íÖÐĿ¼ÌÞ³ý*/ + strcpy(filename,sys_name); + strcat(filename,dirptr->d_name); + strcat(filename,"/"); + for(i=0;id_name) + DIR_ENTRY_OVRHD); + total_len += strlen(sys_name); + /* ³¤¶È¡¢¸öÊý³¬ÏÞ */ + if((total_len >= (negotiatedPduSize - SERVICE_OVRHD)) || + (rsp_ptr->num_dir_ent>=MMS_DIR_READ_MAX)) + { + printf("total_len(%d) > %d num=%d ...\n", + total_len,negotiatedPduSize,rsp_ptr->num_dir_ent); + rsp_ptr->more_follows = SD_TRUE; + doMore = SD_FALSE; + continue; + } + /* Ŀ¼ÎļþÐÅÏ¢ */ + sprintf(filename,"%s%s",sys_name,dirptr->d_name); + ret = stat (filename, &file_stat); + if(ret!=0) printf("%s stat ʧ°Ü...\n\r",filename); + rsp_ptr->num_dir_ent++; + fillFdirEnt(&file_stat, dir_ptr, fname_ptr, name_ptr,dirptr->d_name); + /*ȫ·¾¶*/ + if(fdir_fullname_flag) + { + strcpy(filename,fs_name); + strcat(filename,fname_ptr->fname); + strcpy(fname_ptr->fname,filename); + } + /*UTF8±àÂëת»»*/ + /*UTF_8ToGB2312(tmp_name,fname_ptr->fname,strlen(fname_ptr->fname));*/ + file_gb2312_to_utf(tmp_name,fname_ptr->fname); + strcpy(fname_ptr->fname,tmp_name); + fname_ptr->fn_len = strlen (fname_ptr->fname); + name_ptr += fname_ptr->fn_len + 1; /* check for end of buffer */ + dir_ptr = (FDIR_DIR_ENT *) ((FILE_NAME *) (dir_ptr + 1) + 1); + fname_ptr = (FILE_NAME *)(dir_ptr + 1); + if(!(dirptr = readdir(dir))) doMore = SD_FALSE; + } + } + } + if (dir) closedir(dir); + /* if (status == SD_SUCCESS) directory was successful */ + if(1) + { + /* Build a File Directory response */ + rc = mpl_fdir_resp (indCtrl->event->u.mms.dec_rslt.id, rsp_ptr); + _mvl_send_resp_i (indCtrl, rc); + strcpy (fs_name, fdir_ctrl->fs_filename); + strcpy (ca_name, fdir_ctrl->ca_filename); + printf("filenum=%3d total_len=%5d fdir_name=%s %s %s\n\r",rsp_ptr->num_dir_ent,total_len, + fdir_ctrl->fs_filename,fdir_ctrl->ca_filename,sys_name); + } + /*------------------------*/ + /* Free allocated storage */ + /*------------------------*/ + chk_free (rsp_ptr); + chk_free (data_buf); +} +ST_VOID mvlas_fattr_resp (MVL_IND_PEND *indCtrl) +{ + ST_INT status; + ST_CHAR fs_name [MAX_FILE_NAME+1]; + ST_CHAR ca_name [MAX_FILE_NAME+1]; + ST_CHAR filename[MAX_FILE_NAME+1]; + FDIR_RESP_INFO *rsp_ptr; + FDIR_DIR_ENT *dir_ptr; + ST_INT rsp_size; + ST_CHAR *name_ptr; + ST_INT total_len, doMore; + FILE_NAME *fname_ptr; + ST_CHAR *data_buf; + MVLAS_FDIR_CTRL *fdir_ctrl; + ST_INT negotiatedPduSize; + ST_INT max_dir_ents; + ST_RET rc; + struct stat file_stat; + + /* calculate the maximum message size and number of directory entries */ + negotiatedPduSize = (ST_INT) indCtrl->event->net_info->max_pdu_size; + max_dir_ents = (negotiatedPduSize - SERVICE_OVRHD) / DIR_ENTRY_OVRHD; + + /* set the number of directory entries and allocate memory for response info */ + fdir_ctrl = &indCtrl->u.fdir; + + fs_name[0] = 0; + if(fdir_ctrl->fs_filename[0]!='/') strcpy (fs_name, "/"); + strcat (fs_name, fdir_ctrl->fs_filename); + /*strcpy (fs_name, fdir_ctrl->fs_filename);*/ + strcpy (ca_name, fdir_ctrl->ca_filename); + /*---------------------------------------------------------*/ + /* Find maximum response buffer size, calloc space for it, */ + /* and initialize the response structure variables. */ + /*---------------------------------------------------------*/ + rsp_size = sizeof (FDIR_RESP_INFO) + + ( max_dir_ents * sizeof (FDIR_DIR_ENT) ) + + ( max_dir_ents * sizeof (FILE_NAME) ); + rsp_ptr = (FDIR_RESP_INFO *) chk_calloc (1,rsp_size); + + /* Allocate buffer to hold just names. Will NEVER use whole buffer */ + /* because names plus overhead must be less than mms_max_msgsze. */ + data_buf = chk_malloc (negotiatedPduSize); + rsp_ptr->num_dir_ent = 0; + rsp_ptr->more_follows = SD_FALSE; /* set default value */ + /*---------------------------------*/ + /* Initialize some other variables */ + /*---------------------------------*/ + name_ptr = data_buf; + total_len = 0; + status = SD_SUCCESS; + fname_ptr = ( FILE_NAME * )( fdir_ctrl + 1 ); + dir_ptr = (FDIR_DIR_ENT *)(rsp_ptr + 1); + fname_ptr = (FILE_NAME *)(dir_ptr + 1); + total_len += ( strlen(fs_name) + DIR_ENTRY_OVRHD ); + memset(filename,0,MAX_FILE_NAME); + strcpy(filename,fs_name); + /*if(lstat(filename, &file_stat) != 0 )*/ + if(stat (filename, &file_stat) != 0 ) + { + printf("fdir(%s %s %s) read error ...\n", fdir_ctrl->fs_filename,fs_name,ca_name); + /*_mplas_err_resp (indCtrl,11,3);*/ /* File name syntax error */ + _mplas_err_resp (indCtrl,11,0); /* File name syntax error */ + chk_free (rsp_ptr); + chk_free (data_buf); + return; + } + rsp_ptr->num_dir_ent++; + fillFdirEnt (&file_stat, dir_ptr, fname_ptr, name_ptr,fs_name); + name_ptr += fname_ptr->fn_len + 1; /* check for end of buffer */ + dir_ptr = (FDIR_DIR_ENT *) ((FILE_NAME *) (dir_ptr + 1) + 1); + fname_ptr = (FILE_NAME *)(dir_ptr + 1); + doMore = SD_FALSE; + if (status == SD_SUCCESS) /* directory was successful */ + { + /* Build a File Directory response */ + rc = mpl_fdir_resp (indCtrl->event->u.mms.dec_rslt.id, rsp_ptr); + _mvl_send_resp_i (indCtrl, rc); + } + /*------------------------*/ + /* Free allocated storage */ + /*------------------------*/ + chk_free (rsp_ptr); + chk_free (data_buf); +} +#endif + + + + + + + + + + + +#if defined(_WIN32) +short fdir_fullname_flag=1; +/************************************************************************/ +/* convertFileTime */ +/* convert FILETIME to time_t */ +/************************************************************************/ + +static time_t convertFileTime (FILETIME *pstFileTime) + { +WORD wFatDate, wFatTime; +struct tm stTm; +time_t retTime; +FILETIME stLocalTime; + + FileTimeToLocalFileTime (pstFileTime, &stLocalTime); + + if (FileTimeToDosDateTime (&stLocalTime, &wFatDate, &wFatTime)) + { + stTm.tm_sec = (wFatTime & 0x001F) * 2; // bits 0-4 + stTm.tm_min = (wFatTime & 0x07E0) >> 5; // bits 5-10 + stTm.tm_hour = (wFatTime & 0xF800) >> 11; // bits 11-15 + + stTm.tm_mday = wFatDate & 0x001F; // bits 0-4 + stTm.tm_mon = ((wFatDate & 0x01E0)>>5) - 1; // bits 5-8 + stTm.tm_year = ((wFatDate & 0xFE00)>>9) + 80; // bits 9-15 + + stTm.tm_isdst = -1; // let someone else figure out DST + retTime = mktime (&stTm); + } + else + retTime = -1; + + return retTime; + } + +/************************************************************************/ +/* fileFdirEnt */ +/* fill up the FDIR_DIR_ENT struct, FILE_NAME struct, and nameBuffer */ +/* from the WIN32_FIND_DATA struct. */ +/************************************************************************/ +static ST_VOID fillFdirEnt (WIN32_FIND_DATA *pstFindData, FDIR_DIR_ENT *pstFdirEnt, + FILE_NAME *pstFileName, ST_CHAR *nameBuffer) + { +time_t theTime; + + /* Fill in the FDIR_DIR_ENT struct. */ + pstFdirEnt->fsize = (pstFindData->nFileSizeHigh * MAXDWORD) + pstFindData->nFileSizeLow; + + theTime = convertFileTime (&pstFindData->ftLastWriteTime); + + if (theTime == -1) + pstFdirEnt->mtimpres = SD_FALSE; + else + { + pstFdirEnt->mtimpres = SD_TRUE; + pstFdirEnt->mtime = (ST_INT32) theTime; + } + + pstFdirEnt->num_of_fname = 1; + + /* Fill in nameBuffer. */ + strcpy (nameBuffer, pstFindData->cFileName); + + if (pstFindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + strcat (nameBuffer, "\\"); + + /* Fill in the FILE_NAME struct. */ + pstFileName->fname = nameBuffer; + pstFileName->fn_len = strlen (nameBuffer); + } + +/************************************************************************/ +/* mvlas_fdir_resp */ +/************************************************************************/ +#include "stdio.h" +ST_VOID mvlas_fdir_resp (MVL_IND_PEND *indCtrl) + { +ST_INT status; +ST_CHAR tmp_name [MAX_FILE_NAME+1],*pfind; +ST_CHAR fs_name [MAX_FILE_NAME+1]; +ST_CHAR ca_name [MAX_FILE_NAME+1]; +ST_INT ca_len; +FDIR_RESP_INFO *rsp_ptr; +FDIR_DIR_ENT *dir_ptr; +ST_INT rsp_size; +ST_CHAR *name_ptr; +ST_INT total_len, doMore; +FILE_NAME *fname_ptr; +ST_UCHAR found_ca = SD_FALSE; +ST_CHAR *data_buf; +WIN32_FIND_DATA stFindData; +HANDLE hFind; +MVLAS_FDIR_CTRL *fdir_ctrl; +ST_INT negotiatedPduSize; +ST_INT max_dir_ents; +ST_RET rc; + + char path[MAX_PATH]; + /* calculate the maximum message size and number of directory entries */ + negotiatedPduSize = (ST_INT) indCtrl->event->net_info->max_pdu_size; + max_dir_ents = (negotiatedPduSize - SERVICE_OVRHD) / DIR_ENTRY_OVRHD; + + /* set the number of directory entries and allocate memory for response info */ + fdir_ctrl = &indCtrl->u.fdir; + strcpy (fs_name, fdir_ctrl->fs_filename); + strcpy (ca_name, fdir_ctrl->ca_filename); + path[0]=0; + if(!strstr(fs_name,":")) + { + GetCurrentDirectory (MAX_PATH,path); + GetCurrentDirectoryA(MAX_PATH,path); + } + //printf("GetCurrentDirectory1=%s fs_filename=%s\n",path,fs_name); + + //renxiaobao Îļþ·þÎñ + if(strlen(fs_name)==0) strcpy (fs_name, "\\"); + /* check if ca_filename is present */ + if ((ca_len = strlen (ca_name)) > 0) + { + /* strip off any '\' character at the end of file name */ + if (ca_len && ca_name[ca_len-1] == '\\') + { + ca_len--; + ca_name[ca_len] = '\0'; + } + } + else + found_ca = SD_TRUE; + + /*---------------------------------------------------------*/ + /* Find maximum response buffer size, calloc space for it, */ + /* and initialize the response structure variables. */ + /*---------------------------------------------------------*/ + rsp_size = sizeof (FDIR_RESP_INFO) + + ( max_dir_ents * sizeof (FDIR_DIR_ENT) ) + + ( max_dir_ents * sizeof (FILE_NAME) ); + rsp_ptr = (FDIR_RESP_INFO *) chk_calloc (1,rsp_size); + + /* Allocate buffer to hold just names. Will NEVER use whole buffer */ + /* because names plus overhead must be less than mms_max_msgsze. */ + data_buf = chk_malloc (negotiatedPduSize); + + rsp_ptr->num_dir_ent = 0; + rsp_ptr->more_follows = SD_FALSE; /* set default value */ + + /*---------------------------------*/ + /* Initialize some other variables */ + /*---------------------------------*/ + + name_ptr = data_buf; + total_len = 0; + status = SD_SUCCESS; + fname_ptr = ( FILE_NAME * )( fdir_ctrl + 1 ); + + /* traverse the directory and stash output in the resp struct */ + if ( status == SD_SUCCESS ) + { + sprintf(tmp_name,"%s%s",path,fs_name); + strcpy(fs_name,tmp_name); + while(pfind=strstr(fs_name,"/")) *pfind = 92; // '/'Ìæ»»³É'\\' + strcat (fs_name, "*"); + // printf("fs_name=%s\r\n",fs_name); + // hFind = FindFirstFile (fs_name, &stFindData); + hFind = FindFirstFileA (fs_name, &stFindData); + //printf("FindFirstFile fs_name=%s\r\n",fs_name); + + if (hFind != INVALID_HANDLE_VALUE) + { + dir_ptr = (FDIR_DIR_ENT *)(rsp_ptr + 1); + fname_ptr = (FILE_NAME *)(dir_ptr + 1); + doMore = SD_TRUE; + + while ( doMore ) + { + if (!found_ca && (!stricmp (stFindData.cFileName, ca_name)) ) + found_ca = SD_TRUE; + + if (found_ca && (stricmp (stFindData.cFileName, ca_name)) ) + { + /* Discard the . and .. entries */ + if (!strcmp (stFindData.cFileName, ".") || + !strcmp (stFindData.cFileName, "..")) + { + //doMore = FindNextFile (hFind, &stFindData); + doMore = FindNextFileA (hFind, &stFindData); + continue; + } + + /* see how big it would be and if it fits - keep it */ + total_len += ( strlen(stFindData.cFileName) + DIR_ENTRY_OVRHD ); + + + + + if (total_len < (negotiatedPduSize - SERVICE_OVRHD) ) + { + rsp_ptr->num_dir_ent++; + fillFdirEnt (&stFindData, dir_ptr, fname_ptr, name_ptr); + name_ptr += fname_ptr->fn_len + 1; /* check for end of buffer */ + dir_ptr = (FDIR_DIR_ENT *) ((FILE_NAME *) (dir_ptr + 1) + 1); + fname_ptr = (FILE_NAME *)(dir_ptr + 1); + //doMore = FindNextFile (hFind, &stFindData); + doMore = FindNextFileA (hFind, &stFindData); + + } + else /* message size limit */ + { + rsp_ptr->more_follows = SD_TRUE; + doMore = SD_FALSE; + } + + //printf("total_len=%d %d\n",total_len,negotiatedPduSize); + + } + else + //doMore = FindNextFile (hFind, &stFindData); + doMore = FindNextFileA (hFind, &stFindData); + } + FindClose (hFind); + } + } + + if (status == SD_SUCCESS) /* directory was successful */ + { + /* Build a File Directory response */ + rc = mpl_fdir_resp (indCtrl->event->u.mms.dec_rslt.id, rsp_ptr); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, rsp_ptr); + + _mvl_send_resp_i (indCtrl, rc); + } + /*------------------------*/ + /* Free allocated storage */ + /*------------------------*/ + + chk_free (rsp_ptr); + chk_free (data_buf); + } + +#endif /* if defined(_WIN32) */ diff --git a/mmslib/mvlu/s_fopen.c b/mmslib/mvlu/s_fopen.c new file mode 100644 index 0000000..7aa77f2 --- /dev/null +++ b/mmslib/mvlu/s_fopen.c @@ -0,0 +1,81 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : s_fopen.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_fopen_ind */ +/* mplas_fopen_resp */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 11 Enhanced filtered logging */ +/* 03/11/04 GLB 10 Remove "thisFileName" */ +/* 09/21/01 JRB 09 Alloc global bufs only once at startup. */ +/* 01/21/00 MDE 08 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 04/01/99 MDE 06 Changes to decode buffer allocation scheme */ +/* 11/16/98 MDE 05 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 04 Minor lint cleanup */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 05/14/98 JRB 02 Use MVL_IND_PEND. Add mvlas resp function. */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "mvl_defs.h" +#include "mvl_log.h" + + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_fopen_ind */ +/* A file open indication has been received, process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_fopen_ind (MVL_IND_PEND *indCtrl) + { +FOPEN_REQ_INFO *req_info; +MVLAS_FOPEN_CTRL *fopenCtrl; + + fopenCtrl = &indCtrl->u.fopen; + + req_info = (FOPEN_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + if (_mvl_concat_filename (fopenCtrl->filename, req_info->num_of_fname, + (FILE_NAME *)(req_info + 1), sizeof (fopenCtrl->filename))) + { + _mplas_err_resp (indCtrl,11,3); /* File name syntax error */ + return; + } + + fopenCtrl->init_pos = req_info->init_pos; + + u_mvl_fopen_ind (indCtrl); + } + +/************************************************************************/ +/* mplas_fopen_resp */ +/************************************************************************/ +ST_VOID mplas_fopen_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + +/* Build a "fopen" response. */ + rc = mpl_fopen_resp (indCtrl->event->u.mms.dec_rslt.id, + indCtrl->u.fopen.resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, indCtrl->u.fopen.resp_info); + + _mvl_send_resp_i (indCtrl, rc); + } diff --git a/mmslib/mvlu/s_fread.c b/mmslib/mvlu/s_fread.c new file mode 100644 index 0000000..306ebc2 --- /dev/null +++ b/mmslib/mvlu/s_fread.c @@ -0,0 +1,75 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : s_fread.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_fread_ind */ +/* mplas_fread_resp */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 11 Enhanced filtered logging */ +/* 03/11/04 GLB 10 Remove "thisFileName" */ +/* 09/21/01 JRB 09 Alloc global bufs only once at startup. */ +/* 01/21/00 MDE 08 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 04/01/99 MDE 06 Changes to decode buffer allocation scheme */ +/* 11/16/98 MDE 05 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 04 Minor lint cleanup */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 05/14/98 JRB 02 Use MVL_IND_PEND. Add mvlas resp function. */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "mvl_defs.h" +#include "mvl_log.h" + + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_fread_ind */ +/* A file open indication has been received, process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_fread_ind (MVL_IND_PEND *indCtrl) + { +MVLAS_FREAD_CTRL *freadCtrl; + + freadCtrl = &indCtrl->u.fread; + + freadCtrl->req_info = (FREAD_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + /* (Max file block size) = (Max PDU size) - 100 to allow for MMS headers.*/ + freadCtrl->max_size = indCtrl->event->net_info->max_pdu_size - 100; + + u_mvl_fread_ind (indCtrl); + } + +/************************************************************************/ +/* mplas_fread_resp */ +/************************************************************************/ +ST_VOID mplas_fread_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + + /* Build a File Read response */ + rc = mpl_fread_resp (indCtrl->event->u.mms.dec_rslt.id, + indCtrl->u.fread.resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, indCtrl->u.fread.resp_info); + + _mvl_send_resp_i (indCtrl, rc); + } + diff --git a/mmslib/mvlu/s_fren.c b/mmslib/mvlu/s_fren.c new file mode 100644 index 0000000..290547d --- /dev/null +++ b/mmslib/mvlu/s_fren.c @@ -0,0 +1,82 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : s_fren.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_frename_ind */ +/* mplas_frename_resp */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 05 Enhanced filtered logging */ +/* 03/11/04 GLB 04 Remove "thisFileName" */ +/* 09/21/01 JRB 03 Alloc global bufs only once at startup. */ +/* 01/21/00 MDE 02 Now use MEM_SMEM for dynamic memory */ +/* 10/15/99 GLB 01 Created to acommodate file Rename */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* _mvl_process_frename_ind */ +/* A "frename" indication has been received, process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_frename_ind (MVL_IND_PEND *indCtrl) + { +FRENAME_REQ_INFO *req_info; +MVLAS_FRENAME_CTRL *frename; +FILE_NAME *fname_idx; + + frename = &indCtrl->u.frename; + + req_info = (FRENAME_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + fname_idx = (FILE_NAME *)(req_info + 1); + + if (_mvl_concat_filename (frename->curfilename, req_info->num_of_cur_fname, + fname_idx, sizeof (frename->curfilename))) + { + _mplas_err_resp (indCtrl,11,3); /* File name syntax error */ + return; + } + + if (_mvl_concat_filename (frename->newfilename, req_info->num_of_new_fname, + (FILE_NAME *)(fname_idx + req_info->num_of_cur_fname), + sizeof (frename->newfilename))) + { + _mplas_err_resp (indCtrl,11,3); /* File name syntax error */ + return; + } + + u_mvl_frename_ind (indCtrl); + } + +/************************************************************************/ +/* mplas_frename_resp */ +/************************************************************************/ +ST_VOID mplas_frename_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + + /* Build a "frename" response */ + rc = mpl_frename_resp (indCtrl->event->u.mms.dec_rslt.id); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, NULL); + + _mvl_send_resp_i (indCtrl, rc); + } + + diff --git a/mmslib/mvlu/s_getcl.c b/mmslib/mvlu/s_getcl.c new file mode 100644 index 0000000..d509256 --- /dev/null +++ b/mmslib/mvlu/s_getcl.c @@ -0,0 +1,65 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2000 - 2000, All Rights Reserved */ +/* */ +/* MODULE NAME : s_getcl.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_getcl_ind */ +/* mplas_getcl_resp */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 04 Enhanced filtered logging */ +/* 03/11/04 GLB 03 Remove "thisFileName" */ +/* 09/21/01 JRB 02 Alloc global bufs only once at startup. */ +/* 10/25/00 JRB 01 Created. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/*----------------------------------------------------------------------*/ +/* Functions to process GetProgramInvocationAttributes Indication */ +/* and send GetProgramInvocationAttributes Response. */ +/*----------------------------------------------------------------------*/ + +/************************************************************************/ +/* _mvl_process_getcl_ind */ +/* GetProgramInvocationAttributes Indication received. */ +/* Process it and pass it up to user. */ +/************************************************************************/ +ST_VOID _mvl_process_getcl_ind (MVL_IND_PEND *indCtrl) + { + indCtrl->u.getcl.req_info = + (GETCL_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + u_mvl_getcl_ind (indCtrl); + } + +/************************************************************************/ +/* mplas_getcl_resp */ +/* Send GetProgramInvocationAttributes Response. */ +/************************************************************************/ +ST_VOID mplas_getcl_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + + rc = mpl_getcl_resp (indCtrl->event->u.mms.dec_rslt.id, + indCtrl->u.getcl.resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, indCtrl->u.getcl.resp_info); + + _mvl_send_resp_i (indCtrl, rc); + } + diff --git a/mmslib/mvlu/s_getdom.c b/mmslib/mvlu/s_getdom.c new file mode 100644 index 0000000..948eca4 --- /dev/null +++ b/mmslib/mvlu/s_getdom.c @@ -0,0 +1,108 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : s_getdom.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 09 Enhanced filtered logging */ +/* 10/30/06 JRB 08 Use new mvl_vmd_* object handling functions. */ +/* 09/21/01 JRB 07 Alloc global bufs only once at startup. */ +/* 01/21/00 MDE 06 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 11/16/98 MDE 04 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 05/14/98 JRB 02 Use MVL_IND_PEND. Add mplas resp function. */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pdom.h" +#include "mvl_defs.h" +#include "mvl_log.h" + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_getdom_ind */ +/* A 'Get Domain Attributes' indication has been received, */ +/* process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_getdom_ind (MVL_IND_PEND *indCtrl) + { + indCtrl->u.getdom.req_info = + (GETDOM_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + u_mvl_getdom_ind (indCtrl); + } + +/************************************************************************/ +/* mvlas_getdom_resp */ +/************************************************************************/ +ST_VOID mvlas_getdom_resp (MVL_IND_PEND *indCtrl) + { +GETDOM_REQ_INFO *req_info; +GETDOM_RESP_INFO *resp_info; +GETDOM_RESP_INFO default_resp_info; +MVL_DOM_CTRL *dom; + + req_info = indCtrl->u.getdom.req_info; + dom = mvl_vmd_find_dom (&mvl_vmd, req_info->dname); + if (dom == NULL) + { + MVL_LOG_NERR1 ("GetDomAttrib Ind : %s not found", req_info->dname); + _mplas_err_resp (indCtrl,2,1); /* definition, object undefined */ + return; + } + + resp_info = dom->get_dom_resp_info; + if (resp_info == NULL) + { + resp_info = &default_resp_info; + resp_info->num_of_capab = 0; + resp_info->mms_deletable = 0; + resp_info->sharable = 0; + resp_info->num_of_pinames = 0; + resp_info->state = 2; /* 2 : ready */ + } + indCtrl->u.getdom.resp_info = resp_info; + mplas_getdom_resp (indCtrl); + } + +/************************************************************************/ +/* mplas_getdom_resp */ +/************************************************************************/ +ST_VOID mplas_getdom_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + rc = mpl_getdom_resp (indCtrl->event->u.mms.dec_rslt.id, + indCtrl->u.getdom.resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, indCtrl->u.getdom.resp_info); + + _mvl_send_resp_i (indCtrl, rc); + } + diff --git a/mmslib/mvlu/s_getnam.c b/mmslib/mvlu/s_getnam.c new file mode 100644 index 0000000..54af9d8 --- /dev/null +++ b/mmslib/mvlu/s_getnam.c @@ -0,0 +1,439 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2005, All Rights Reserved */ +/* */ +/* MODULE NAME : s_getnam.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 21 Enhanced filtered logging */ +/* 10/30/06 JRB 20 Use new mvl_vmd_* object handling functions. */ +/* u_gnl_ind_*: add net_info arg to */ +/* elim use of global var "_mvl_curr_net_info". */ +/* 01/19/05 JRB 19 u_gnl_ind_* return (-1) on error. */ +/* mvlas_namelist_resp: send err resp on error */ +/* (instead of empty name list). */ +/* 08/20/04 JRB 18 Del uninformative "#pragma message". */ +/* 03/04/02 JRB 17 Avoid uninitialized locals in u_gnl_ind_jous */ +/* 01/23/02 EJV 16 Added journals to domain: */ +/* u_gnl_ind_jous - added DOM_SPEC case. */ +/* 09/21/01 JRB 15 Alloc global bufs only once at startup. */ +/* 03/30/01 MDE 14 Changed MSMEM_ENC_INFO to MSMEM_ENC_OS_INFO */ +/* 10/25/00 JRB 13 Del GNL funct ptrs. Call functs directly. */ +/* Control with #ifdefs. */ +/* Del NO_GLB_VAR_INIT code (no longer needed). */ +/* 01/21/00 MDE 12 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 11 Added SD_CONST modifiers */ +/* 04/07/99 MDE 10 Logging improvements */ +/* 01/08/99 JRB 09 Use new "bsearch" object model. */ +/* 11/16/98 MDE 08 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 07 Minor lint cleanup */ +/* 07/02/98 MDE 06 Added Journal support */ +/* 06/15/98 MDE 05 Changes to allow compile under C++ */ +/* 05/14/98 JRB 04 Use MVL_IND_PEND. Add mplas resp function. */ +/* 02/10/98 MDE 03 Added 'u_gnl_done' function pointer */ +/* 09/18/97 MDE 02 Fixed 'continue after' handling */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* Approximate worst case PDU overhead */ + +#define MVL_GNL_RESP_OH 25 + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ + +static ST_INT getLocalObjectNames (MVL_OBJ ** obj_tbl, ST_INT num_obj, + NAMELIST_REQ_INFO *req_info, ST_CHAR **ptr, + ST_BOOLEAN *moreFollowsOut, ST_INT maxNames); + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_getnam_ind */ +/* A get name indication has been received, process it and respond */ +/************************************************************************/ + +#define GETNAM_RESP_BUF_SIZE (sizeof(NAMELIST_RESP_INFO)+ \ + (MVL_MAX_GNL_NAMES * sizeof(ST_CHAR *))) + +ST_VOID _mvl_process_getnam_ind (MVL_IND_PEND *indCtrl) + { + indCtrl->u.namelist.req_info = + (NAMELIST_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + u_mvl_namelist_ind (indCtrl); + } + +/************************************************************************/ +/* mvlas_namelist_resp */ +/* NOTE: u_gnl_ind_* functions return negative value on errors. */ +/************************************************************************/ + +ST_VOID mvlas_namelist_resp (MVL_IND_PEND *indCtrl) + { +NAMELIST_REQ_INFO *req_info; +NAMELIST_RESP_INFO *resp_info; +ST_CHAR **ptr; +ST_INT num_obj; +ST_INT i; +ST_INT max_size; +ST_INT16 mms_class; + + req_info = indCtrl->u.namelist.req_info; + mms_class = req_info->obj.mms_class; + +/* Now create the response data structure */ + resp_info = (NAMELIST_RESP_INFO *) + M_CALLOC (MSMEM_ENC_OS_INFO, 1, GETNAM_RESP_BUF_SIZE); + ptr = (ST_CHAR **)(resp_info + 1); + + num_obj = 0; + switch (req_info->obj.mms_class) + { + case MMS_CLASS_VAR: /* NamedVariables */ + num_obj = u_gnl_ind_vars(indCtrl->event->net_info, req_info, ptr, &resp_info->more_follows, + MVL_MAX_GNL_NAMES); + break; + + case MMS_CLASS_VARLIST: /* NamedVariableLists */ + num_obj = u_gnl_ind_nvls(indCtrl->event->net_info, req_info, ptr, &resp_info->more_follows, + MVL_MAX_GNL_NAMES); + break; + + case MMS_CLASS_DOM: /* Domains */ + num_obj = u_gnl_ind_doms(req_info, ptr, &resp_info->more_follows, + MVL_MAX_GNL_NAMES); + break; + + case MMS_CLASS_JOU: /* Journals */ + num_obj = u_gnl_ind_jous(indCtrl->event->net_info, req_info, ptr, &resp_info->more_follows, + MVL_MAX_GNL_NAMES); + break; + + case MMS_CLASS_SCAT_ACC: /* Scattered Access */ + case MMS_CLASS_TYPE: /* NamedTypes */ + case MMS_CLASS_SEM: /* Semaphores */ + case MMS_CLASS_EV_COND: /* Event Conditions */ + case MMS_CLASS_EV_ACT: /* EventActions */ + case MMS_CLASS_EV_ENROLL: /* EventEnrollments */ + case MMS_CLASS_PI: /* Program Invocations */ + case MMS_CLASS_OPER_STA: /* OperatorStations */ + break; + + default: + break; + } + + if (num_obj < 0) + { /* error. Send error response. */ + _mplas_err_resp (indCtrl,7,2); /* access, non-existent */ + } + else + { + /* Let's make sure they will all fit into the PDU */ + max_size = indCtrl->event->net_info->max_pdu_size - MVL_GNL_RESP_OH; + resp_info->num_names = 0; + for (i = 0; i < num_obj; ++i, ++ptr) + { + max_size -= (2 + strlen (*ptr)); + if (resp_info->num_names > MVL_MAX_GNL_NAMES || max_size <= 0) + { + resp_info->more_follows = SD_TRUE; + break; + } + ++resp_info->num_names; + } + + /* Build a Get Name List response */ + indCtrl->u.namelist.resp_info = resp_info; + mplas_namelist_resp (indCtrl); + } + +#if defined(MVL_UCA) /* extra cleanup for UCA */ + u_gnl_done (mms_class, resp_info); +#endif /* defined(MVL_UCA) */ + + M_FREE (MSMEM_ENC_OS_INFO, resp_info); + } + +/************************************************************************/ +/* mplas_namelist_resp */ +/************************************************************************/ +ST_VOID mplas_namelist_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + + rc = mpl_namelist_resp (indCtrl->event->u.mms.dec_rslt.id, + indCtrl->u.namelist.resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, indCtrl->u.namelist.resp_info); + + _mvl_send_resp_i (indCtrl, rc); + } + +/************************************************************************/ +/************************************************************************/ + +#if defined(MVL_UCA) + /* This function not used. See customized 'u_gnl_ind_vars' in 'mvl_uca.c'.*/ +#elif defined(USE_MANUFACTURED_OBJS) +#pragma message("USE_MANUFACTURED_OBJS defined. Must provide customized 'u_gnl_ind_vars'.") +#else /* default */ + +ST_INT u_gnl_ind_vars (MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames) + { +ST_INT num_obj; +MVL_VAR_ASSOC **va; +MVL_AA_OBJ_CTRL *aa; +MVL_DOM_CTRL *domCtrl; + +/* First get the number of objects and pointer to the object table */ + num_obj = 0; + if (req_info->objscope == VMD_SPEC) + { + num_obj = mvl_vmd.num_var_assoc; + va = mvl_vmd.var_assoc_tbl; + } + else if (req_info->objscope == DOM_SPEC) + { + domCtrl = mvl_vmd_find_dom (&mvl_vmd, req_info->dname); + if (domCtrl) + { + num_obj = domCtrl->num_var_assoc; + va = domCtrl->var_assoc_tbl; + } + else + { + MVL_LOG_NERR1 ("GetNameList variables: Domain '%s' not found", req_info->dname); + *moreFollowsOut = SD_FALSE; + return (-1); /* error. This triggers error response */ + } + } + else /* AA_SPEC */ + { + aa = (MVL_AA_OBJ_CTRL *) net_info->aa_objs; + if (aa) + { + num_obj = aa->num_var_assoc; + va = aa->var_assoc_tbl; + } + else + { + *moreFollowsOut = SD_FALSE; + return (-1); /* error. This triggers error response */ + } + } + +/* Get all the names. */ + return (getLocalObjectNames ((MVL_OBJ **) va, num_obj, + req_info, ptr, moreFollowsOut, maxNames)); + } +#endif /* default */ + +/************************************************************************/ +/************************************************************************/ + +#if defined(MVL_UCA) + /* This function not used. See customized 'u_gnl_ind_nvls' in 'mvl_uca.c'.*/ +#elif defined(USE_MANUFACTURED_OBJS) +#pragma message("USE_MANUFACTURED_OBJS defined. Must provide customized 'u_gnl_ind_nvls'.") +#else /* default */ + +ST_INT u_gnl_ind_nvls (MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames) + { +ST_INT num_obj; +MVL_AA_OBJ_CTRL *aa; +MVL_NVLIST_CTRL **vl; +MVL_DOM_CTRL *domCtrl; + +/* First get the number of objects and pointer to the object table */ + num_obj = 0; + if (req_info->objscope == VMD_SPEC) + { + num_obj = mvl_vmd.num_nvlist; + vl = mvl_vmd.nvlist_tbl; + } + else if (req_info->objscope == DOM_SPEC) + { + domCtrl = mvl_vmd_find_dom (&mvl_vmd, req_info->dname); + if (domCtrl) + { + num_obj = domCtrl->num_nvlist; + vl = domCtrl->nvlist_tbl; + } + else + { + MVL_LOG_NERR1 ("GetNameList NVL: Domain '%s' not found", req_info->dname); + *moreFollowsOut = SD_FALSE; + return (-1); /* error. This triggers error response */ + } + } + else /* AA_SPEC */ + { + aa = (MVL_AA_OBJ_CTRL *) net_info->aa_objs; + if (aa) + { + num_obj = aa->num_nvlist; + vl = aa->nvlist_tbl; + } + else + { + *moreFollowsOut = SD_FALSE; + return (-1); /* error. This triggers error response */ + } + } + +/* Get all the names. */ + return (getLocalObjectNames ((MVL_OBJ **) vl, num_obj, + req_info, ptr, moreFollowsOut, maxNames)); + } +#endif /* default */ + +/************************************************************************/ +/************************************************************************/ + +#if defined(USE_MANUFACTURED_OBJS) +#pragma message("USE_MANUFACTURED_OBJS defined. Must provide customized 'u_gnl_ind_doms'.") +#else /* default */ + +ST_INT u_gnl_ind_doms (NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames) + { +/* Get all the names. */ + return (getLocalObjectNames ((MVL_OBJ **) mvl_vmd.dom_tbl, mvl_vmd.num_dom, + req_info, ptr, moreFollowsOut, maxNames)); + } +#endif /* default */ + + + + +/************************************************************************/ +/************************************************************************/ + +ST_INT u_gnl_ind_jous (MVL_NET_INFO *net_info, NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames) + { +ST_INT num_obj; +MVL_AA_OBJ_CTRL *aa; +MVL_DOM_CTRL *dom; +MVL_JOURNAL_CTRL **jou; + +/* First get the number of objects and pointer to the object table */ + num_obj = 0; + jou = NULL; + switch (req_info->objscope) + { + case VMD_SPEC: + num_obj = mvl_vmd.num_jou; + jou = mvl_vmd.jou_tbl; + break; + + case AA_SPEC: + aa = (MVL_AA_OBJ_CTRL *) net_info->aa_objs; + if (aa) + { + num_obj = aa->num_jou; + jou = aa->jou_tbl; + } + break; + + case DOM_SPEC: + dom = mvl_vmd_find_dom (&mvl_vmd, req_info->dname); + if (dom) + { + num_obj = dom->num_jou; + jou = dom->jou_tbl; + } + else + { + MVL_LOG_NERR1 ("GetNameList NVL Journal: Domain '%s' not found", req_info->dname); + *moreFollowsOut = SD_FALSE; + return (-1); /* error. This triggers error response */ + } + break; + + default: + *moreFollowsOut = SD_FALSE; + return (-1); /* error. This triggers error response */ + } + +/* Get all the names. */ + if (num_obj) + return (getLocalObjectNames ((MVL_OBJ **) jou, num_obj, + req_info, ptr, moreFollowsOut, maxNames)); + return (0); + } + +/************************************************************************/ +/* getLocalObjectNames */ +/* Find index into array of pointers for name AFTER continue_after name.*/ +/************************************************************************/ +static ST_INT getLocalObjectNames (MVL_OBJ ** obj_tbl, + ST_INT num_obj, + NAMELIST_REQ_INFO *req_info, + ST_CHAR **ptr, /* array of ptrs to names*/ + ST_BOOLEAN *moreFollowsOut, + ST_INT maxNames) /* max # of names */ + { +ST_INT obj_index; /* index to array of objects */ +ST_INT name_index; /* index to array of names */ +MVL_OBJ **key; + + if (req_info->cont_after_pres) + { + key = mvl_obj_find_key (obj_tbl, num_obj, req_info->continue_after); + if (key) + obj_index = key - obj_tbl + 1; /* index to next one (i.e. + 1).*/ + else + { + MVL_LOG_ERR1 ("GetNameList Error: continue after name '%s' not found", + req_info->continue_after); + obj_index = num_obj; /* Treat as if there are no more objects.*/ + } + } + else + obj_index = 0; /* No continue_after. Start with first entry. */ + +/* Now make the list for the response */ + for (name_index = 0; name_index < maxNames && obj_index < num_obj; + ++obj_index, ++name_index) + ptr[name_index] = obj_tbl[obj_index]->name; + + if (obj_index < num_obj) + *moreFollowsOut = SD_TRUE; + + return (name_index); + } diff --git a/mmslib/mvlu/s_getvaa.c b/mmslib/mvlu/s_getvaa.c new file mode 100644 index 0000000..3426bcd --- /dev/null +++ b/mmslib/mvlu/s_getvaa.c @@ -0,0 +1,265 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2002, All Rights Reserved */ +/* */ +/* MODULE NAME : s_getvaa.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 22 Enhanced filtered logging */ +/* 11/03/06 RKR 21 Added code to generate a misencoded typespec */ +/* 11/02/06 JRB 20 mplas_err_resp: fix class/code for IEC 61850.*/ +/* 10/30/06 JRB 19 Add args on call to _mvl_objname_to_va. */ +/* Del MVL_DYN_ASN1_TYPES option (was enabled */ +/* by default). Always do default behavior. */ +/* Elim use of global var "_mvl_curr_net_info". */ +/* 01/30/06 GLB 18 Integrated porting changes for VMS */ +/* 06/29/04 JRB 17 Improve NERR log msg. */ +/* 03/13/03 JRB 16 Use mvl_type_ctrl_find. */ +/* 02/25/02 MDE 15 Now get max PDU size from mvl_cfg_info */ +/* 01/02/02 JRB 14 Converted to use ASN1R (re-entrant ASN1) */ +/* 09/21/01 JRB 13 Alloc global bufs only once at startup. */ +/* 10/25/00 JRB 12 Del u_mvl funct ptrs. Call functs directly. */ +/* Control with #ifdefs. */ +/* 01/21/00 MDE 11 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 10 Added SD_CONST modifiers */ +/* 04/07/99 MDE 09 Logging improvements */ +/* 12/11/98 MDE 08 Removed scope references from VA */ +/* 12/11/98 MDE 07 Now use 'va_to_free' as manufactured flag */ +/* 11/16/98 MDE 06 Renamed internal functions (prefix '_') */ +/* 08/06/98 JRB 05 Use mmsl_max_msg_size to encode type_spec. */ +/* 06/15/98 MDE 04 Changes to allow compile under C++ */ +/* 05/14/98 JRB 03 Use MVL_IND_PEND. Add mplas resp function. */ +/* 02/10/98 MDE 02 Removed NEST_RT_TYPES, use _mvl_call_get_va */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_acse.h" +#include "mvl_log.h" + +#if defined(_S_TEST_PROBES) +#include "stestprb.h" +ST_CHAR *misencodedPDU = "\xA2\x82\x05\x20\xA1\x82\x05\x1C\x30\x82\x01\x93\x80\x02\x53\x54\ +\xA1\x82\x01\x8B\xA2\x82\x01\x87\xA1\x82\x01\x83\x30\x2C\x80\x03\ +\x4D\x6F\x64\xA1\x25\xA2\x23\xA1\x21\x30\x0C\x80\x05\x73\x74\x56\ +\x61\x6C\xA1\x03\x85\x01\x08\x30\x08\x80\x01\x71\xA1\x03\x84\x01\ +\xF3\x30\x07\x80\x01\x74\xA1\x02\x91\x00\x30\x2C\x80\x03\x42\x65\ +\x68\xA1\x25\xA2\x23\xA1\x21\x30\x0C\x80\x05\x73\x74\x56\x61\x6C\ +\xA1\x03\x85\x01\x08\x30\x08\x80\x01\x71\xA1\x03\x84\x01\xF3\x30\ +\x07\x80\x01\x74\xA1\x02\x91\x00\x30\x2F\x80\x06\x48\x65\x61\x6C\ +\x74\x68\xA1\x25\xA2\x23\xA1\x21\x30\x0C\x80\x05\x73\x74\x56\x61\ +\x6C\xA1\x03\x85\x01\x08\x30\x08\x80\x01\x71\xA1\x03\x84\x01\xF3\ +\x30\x07\x80\x01\x74\xA1\x02\x91\x00\x30\x30\x80\x07\x4F\x70\x43\ +\x6E\x74\x52\x73\xA1\x25\xA2\x23\xA1\x21\x30\x0C\x80\x05\x73\x74\ +\x56\x61\x6C\xA1\x03\x85\x01\x20\x30\x08\x80\x01\x71\xA1\x03\x84\ +\x01\xF3\x30\x07\x80\x01\x74\xA1\x02\x91\x00\x30\x31\x80\x08\x4E\ +\x75\x6D\x43\x6E\x74\x52\x73\xA1\x25\xA2\x23\xA1\x21\x30\x0C\x80\ +\x05\x73\x74\x56\x61\x6C\xA1\x03\x85\x01\x20\x30\x08\x80\x01\x71\ +\xA1\x03\x84\x01\xF3\x30\x07\x80\x01\x74\xA1\x02\x91\x00\x30\x2F\ +\x80\x06\x43\x68\x6B\x48\x64\x75\xA1\x25\xA2\x23\xA1\x21\x30\x0C\ +\x80\x05\x73\x74\x56\x61\x6C\xA1\x03\x84\x01\xF8\x30\x08\x80\x01\ +\x71\xA1\x03\x84\x01\xF3\x30\x07\x80\x01\x74\xA1\x02\x91\x00\x30\ +\x2D\x80\x05\x4D\x65\x6D\x4F\x76\xA1\x24\xA2\x22\xA1\x20\x30\x0B\ +\x80\x05\x73\x74\x56\x61\x6C\xA1\x02\x83\x00\x30\x08\x80\x01\x71\ +\xA1\x03\x84\x01\xF3\x30\x07\x80\x01\x74\xA1\x02\x91\x00\x30\x2F\ +\x80\x06\x4E\x75\x6D\x52\x63\x64\xA1\x25\xA2\x23\xA1\x21\x30\x0C\ +\x80\x05\x73\x74\x56\x61\x6C\xA1\x03\x85\x01\x20\x30\x08\x80\x01\ +\x71\xA1\x03\x84\x01\xF3\x30\x07\x80\x01\x74\xA1\x02\x91\x00\x30\ +\x82\x01\xC0\x80\x02\x43\x4F\xA1\x82\x01\xB8\xA2\x82\x01\xB4\xA1\ +\x82\x01\xB0\x30\x81\x8D\x80\x07\x4F\x70\x43\x6E\x74\x52\x73\xA1\ +\x81\x81\xA2\x7F\xA1\x7D\x30\x7B\x80\x04\x4F\x70\x65\x72\xA1\x73\ +\xA2\x71\xA1\x6F\x30\x0D\x80\x06\x63\x74\x6C\x56\x61\x6C\xA1\x03\ +\x85\x01\x20\x30\x2C\x80\x06\x6F\x72\x69\x67\x69\x6E\xA1\x22\xA2\ +\x20\xA1\x1E\x30\x0C\x80\x05\x6F\x72\x43\x61\x74\xA1\x03\x85\x01\ +\x08\x30\x0E\x80\x07\x6F\x72\x49\x64\x65\x6E\x74\xA1\x03\x89\x01\ +\xC0\x30\x0D\x80\x06\x63\x74\x6C\x4E\x75\x6D\xA1\x03\x86\x01\x08\ +\x30\x07\x80\x01\x54\xA1\x02\x91\x00\x30\x0A\x80\x04\x54\x65\x73\ +\x74\xA1\x02\x83\x00\x30\x0C\x80\x05\x43\x68\x65\x63\x6B\xA1\x03\ +\x84\x01\xFE\x30\x81\x8E\x80\x08\x4E\x75\x6D\x43\x6E\x74\x52\x73\ +\xA1\x81\x81\xA2\x7F\xA1\x7D\x30\x7B\x80\x04\x4F\x70\x65\x72\xA1\ +\x73\xA2\x71\xA1\x6F\x30\x0D\x80\x06\x63\x74\x6C\x56\x61\x6C\xA1\ +\x03\x85\x01\x20\x30\x2C\x80\x06\x6F\x72\x69\x67\x69\x6E\xA1\x22\ +\xA2\x20\xA1\x1E\x30\x0C\x80\x05\x6F\x72\x43\x61\x74\xA1\x03\x85\ +\x01\x08\x30\x0E\x80\x07\x6F\x72\x49\x64\x65\x6E\x74\xA1\x03\x89\ +\x01\xC0\x30\x0D\x80\x06\x63\x74\x6C\x4E\x75\x6D\xA1\x03\x86\x01\ +\x08\x30\x07\x80\x01\x54\xA1\x02\x91\x00\x30\x0A\x80\x04\x54\x65\ +\x73\x74\xA1\x02\x83\x00\x30\x0C\x80\x05\x43\x68\x65\x63\x6B\xA1\ +\x03\x84\x01\xFE\x30\x81\x8C\x80\x06\x43\x68\x6B\x48\x64\x75\xA1\ +\x81\x81\xA2\x7F\xA1\x7D\x30\x7B\x80\x04\x4F\x70\x65\x72\xA1\x73\ +\xA2\x71\xA1\x6F\x30\x0D\x80\x06\x63\x74\x6C\x56\x61\x6C\xA1\x03\ +\x85\x01\xC0\x30\x2C\x80\x06\x6F\x72\x69\x67\x69\x6E\xA1\x22\xA2\ +\x20\xA1\x1E\x30\x0C\x80\x05\x6F\x72\x43\x61\x74\xA1\x03\x85\x01\ +\x08\x30\x0E\x80\x07\x6F\x72\x49\x64\x65\x6E\x74\xA1\x03\x89\x01\ +\xC0\x30\x0D\x80\x06\x63\x74\x6C\x4E\x75\x6D\xA1\x03\x86\x01\x08\ +\x30\x07\x80\x01\x54\xA1\x02\x91\x00\x30\x0A\x80\x04\x54\x65\x73\ +\x74\xA1\x02\x83\x00\x30\x0C\x80\x05\x43\x68\x65\x63\x6B\xA1\x03\ +\x84\x01\xFE\x30\x81\x91\x80\x02\x43\x46\xA1\x81\x8A\xA2\x81\x87\ +\xA1\x81\x84\x30\x1C\x80\x03\x4D\x6F\x64\xA1\x15\xA2\x13\xA1\x11\ +\x30\x0F\x80\x08\x63\x74\x6C\x4D\x6F\x64\x65\x6C\xA1\x03\x85\x01\ +\x08\x30\x20\x80\x07\x4F\x70\x43\x6E\x74\x52\x73\xA1\x15\xA2\x13\ +\xA1\x11\x30\x0F\x80\x08\x63\x74\x6C\x4D\x6F\x64\x65\x6C\xA1\x03\ +\x85\x01\x08\x30\x21\x80\x08\x4E\x75\x6D\x43\x6E\x74\x52\x73\xA1\ +\x15\xA2\x13\xA1\x11\x30\x0F\x80\x08\x63\x74\x6C\x4D\x6F\x64\x65\ +\x6C\xA1\x03\x85\x01\x08\x30\x1F\x80\x06\x43\x68\x6B\x48\x64\x75\ +\xA1\x15\xA2\x13\xA1\x11\x30\x0F\x80\x08\x63\x74\x6C\x4D\x6F\x64\ +\x65\x6C\xA1\x03\x85\x01\x08\x30\x81\xFE\x80\x02\x44\x43\xA1\x81\ +\xF7\xA2\x81\xF4\xA1\x81\xF1\x30\x19\x80\x06\x48\x65\x61\x6C\x74\ +\x68\xA1\x0F\xA2\x0D\xA1\x0B\x30\x09\x80\x01\x64\xA1\x04\x8A\x02\ +\xFF\x01\x30\x4B\x80\x06\x4E\x61\x6D\x50\x6C\x74\xA1\x41\xA2\x3F\ +\xA1\x3D\x30\x0E\x80\x06\x76\x65\x6E\x64\x6F\x72\xA1\x04\x8A\x02\ +\xFF\x01\x30\x0D\x80\x05\x73\x77\x52\x65\x76\xA1\x04\x8A\x02\xFF\ +\x01\x30\x09\x80\x01\x64\xA1\x04\x8A\x02\xFF\x01\x30\x11\x80\x09\ +\x63\x6F\x6E\x66\x69\x67\x52\x65\x76\xA1\x04\x8A\x02\xFF\x01\x30\ +\x1A\x80\x07\x4F\x70\x43\x6E\x74\x52\x73\xA1\x0F\xA2\x0D\xA1\x0B\ +\x30\x09\x80\x01\x64\xA1\x04\x8A\x02\xFF\x01\x30\x1B\x80\x08\x4E\ +\x75\x6D\x43\x6E\x74\x52\x73\xA1\x0F\xA2\x0D\xA1\x0B\x30\x09\x80\ +\x01\x64\xA1\x04\x8A\x02\xFF\x01\x30\x19\x80\x06\x43\x68\x6B\x48\ +\x64\x75\xA1\x0F\xA2\x0D\xA1\x0B\x30\x09\x80\x01\x64\xA1\x04\x8A\ +\x02\xFF\x01\x30\x18\x80\x05\x4D\x65\x6D\x4F\x76\xA1\x0F\xA2\x0D\ +\xA1\x0B\x30\x09\x80\x01\x64\xA1\x04\x8A\x02\xFF\x01\x30\x19\x80\ +\x06\x4E\x75\x6D\x52\x63\x64\xA1\x0F\xA2\x0D\xA1\x0B\x30\x09\x80\ +\x01\x64\xA1\x04\x8A\x02\xFF\x01\x30\x2A\x80\x02\x45\x58\xA1\x24\ +\xA2\x22\xA1\x20\x30\x1E\x80\x06\x43\x68\x6B\x48\x64\x75\xA1\x14\ +\xA2\x12\xA1\x10\x30\x0E\x80\x06\x64\x61\x74\x61\x4E\x73\xA1\x04\ +\x8A\x02\xFF\x01"; +#endif + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_getvaa_ind */ +/* A 'Get Variable Access Attributes' indication has been received, */ +/* process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_getvaa_ind (MVL_IND_PEND *indCtrl) + { + indCtrl->u.getvar.req_info = + (GETVAR_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + u_mvl_getvar_ind (indCtrl); + } + +/************************************************************************/ +/* mvlas_getvar_resp */ +/************************************************************************/ +ST_VOID mvlas_getvar_resp (MVL_IND_PEND *indCtrl) + { +GETVAR_REQ_INFO *req_info; +GETVAR_RESP_INFO resp_info; +MVL_VAR_ASSOC *va; +ST_RET rc; +ST_UCHAR *asn1_buf; +ST_INT asn1_len; +ST_UCHAR *asn1_start; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; +MVL_TYPE_CTRL *type_ctrl; + + req_info = indCtrl->u.getvar.req_info; + + asn1_buf = (ST_UCHAR *) M_MALLOC (MSMEM_ASN1_DATA_ENC, mvl_cfg_info->max_msg_size); + + rc = SD_FAILURE; + if (req_info->req_tag == 0) /* Object Name */ + { + va = _mvl_objname_to_va (&mvl_vmd, indCtrl->event->net_info, MMSOP_GET_VAR, &req_info->name, + NULL, + SD_FALSE, + NULL, + NULL); + + if (va) + { + resp_info.mms_deletable = SD_FALSE; + resp_info.address_pres = SD_FALSE; + + /* We will derive the ASN.1 directly from the runtime type. */ + /* This takes a bit more code, but if we have Lot's of types we can */ + /* save space. */ + + type_ctrl = mvl_type_ctrl_find (va->type_id); /* find type */ + + asn1r_strt_asn1_bld (aCtx, asn1_buf, mvl_cfg_info->max_msg_size); + rc = ms_runtime_to_asn1 (aCtx, type_ctrl->rt, type_ctrl->num_rt); + if (rc == SD_SUCCESS) + { + asn1_start = aCtx->asn1r_field_ptr+1; + asn1_len = (asn1_buf + mvl_cfg_info->max_msg_size) - asn1_start; + + resp_info.type_spec.len = asn1_len; + resp_info.type_spec.data = asn1_start; + } + else + { + MVL_LOG_NERR1 ("GetVarAccAttrib : VarName='%s'. Could not create ASN.1 from RUNTIME. Probably MMS msgsize to small.", + req_info->name.obj_name.vmd_spec); + } + +#if defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS) + if (va->va_to_free) + u_mvl_free_va (MMSOP_GET_VAR, va, indCtrl->event->net_info); +#endif /* defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS) */ + } + else + { + MVL_LOG_NERR1 ("GetVarAccAttrib : Variable Association '%s' not found", + req_info->name.obj_name.vmd_spec); + } + } /* End 'if object (variable name) */ + + if (rc != SD_SUCCESS) + _mplas_err_resp (indCtrl,MMS_ERRCLASS_ACCESS,MMS_ERRCODE_OBJ_NON_EXISTENT); + else + { +#if defined(_S_TEST_PROBES) + if (_sTestProbeEnabled(_MVL_TEST_RETURN_BAD_TYPE)) + { + SLOGALWAYS0 ("TEST: Sending bad type for getVaa"); + resp_info.type_spec.data = misencodedPDU; + resp_info.type_spec.len = 1316; /* 0x524 in Hex */ + } +#endif + indCtrl->u.getvar.resp_info = &resp_info; + mplas_getvar_resp (indCtrl); + } + + M_FREE (MSMEM_ASN1_DATA_ENC, asn1_buf); + } + +/************************************************************************/ +/* mplas_getvar_resp */ +/************************************************************************/ +ST_VOID mplas_getvar_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + + rc = mpl_getvar_resp (indCtrl->event->u.mms.dec_rslt.id, + indCtrl->u.getvar.resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, indCtrl->u.getvar.resp_info); + + _mvl_send_resp_i (indCtrl, rc); + } diff --git a/mmslib/mvlu/s_getvla.c b/mmslib/mvlu/s_getvla.c new file mode 100644 index 0000000..69d19a7 --- /dev/null +++ b/mmslib/mvlu/s_getvla.c @@ -0,0 +1,167 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : s_getvla.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_getvla_ind */ +/* mvlas_getvlist_resp */ +/* mplas_getvlist_resp */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 17 Enhanced filtered logging */ +/* 11/02/06 JRB 16 mplas_err_resp: fix class/code for IEC 61850.*/ +/* 10/30/06 JRB 15 Use new mvl_vmd_* object handling functions. */ +/* Elim use of global var "_mvl_curr_net_info". */ +/* 08/09/06 JRB 14 For MVL_UCA, call mvl_find_nvl */ +/* (DO NOT call u_mvl_get_nvl, u_mvl_free_nvl). */ +/* 09/21/01 JRB 13 Alloc global bufs only once at startup. */ +/* 03/30/01 MDE 12 Changed MSMEM_ENC_INFO to MSMEM_ENC_OS_INFO */ +/* 10/25/00 JRB 11 Del u_mvl funct ptrs. Call functs directly. */ +/* Control with #ifdefs. */ +/* 01/21/00 MDE 10 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 09 Added SD_CONST modifiers */ +/* 09/07/99 MDE 08 Changed MVL_VA_SCOPE to MVL_SCOPE */ +/* 01/15/99 JRB 07 IF (u_mvl_get_nvl_fun != NULL) call it, */ +/* ELSE call "mvl_find_nvl". */ +/* 12/11/98 MDE 06 Removed scope references from VA */ +/* 11/16/98 MDE 05 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 04 Minor lint cleanup */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 05/14/98 JRB 02 Use MVL_IND_PEND. Add mvlas resp function. */ +/* Use new mms_deletable in MVL_NVLIST_CTRL. */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_getvla_ind */ +/* A 'Get Variable List Attributes' indication has been received, */ +/* process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_getvla_ind (MVL_IND_PEND *indCtrl) + { + indCtrl->u.getvlist.req_info = + (GETVLIST_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + u_mvl_getvlist_ind (indCtrl); + } + +/************************************************************************/ +/* mvlas_getvlist_resp */ +/************************************************************************/ +ST_VOID mvlas_getvlist_resp (MVL_IND_PEND *indCtrl) + { +GETVLIST_REQ_INFO *req_info; +GETVLIST_RESP_INFO *resp_info; +MVL_NVLIST_CTRL *nvlist; +ST_INT num_var; +ST_INT i; +VARIABLE_LIST *vl; +MVL_VAR_ASSOC *va; +MVL_SCOPE *va_scope; +MVL_SCOPE vmdVaScope; + + req_info = indCtrl->u.getvlist.req_info; + +/* Now find the named variable list */ +#if defined(USE_MANUFACTURED_OBJS) + nvlist = u_mvl_get_nvl (MMSOP_GET_VLIST, &req_info->vl_name, + indCtrl->event->net_info); +#else /* default */ + nvlist = mvl_vmd_find_nvl (&mvl_vmd, &req_info->vl_name, indCtrl->event->net_info); +#endif /* default */ + + if (nvlist) + { + num_var = nvlist->num_of_entries; + resp_info = (GETVLIST_RESP_INFO *) + M_CALLOC (MSMEM_ENC_OS_INFO, 1, sizeof(GETVLIST_RESP_INFO) + + (num_var * sizeof(VARIABLE_LIST))); + resp_info->mms_deletable = nvlist->mms_deletable; + resp_info->num_of_variables = num_var; + vl = (VARIABLE_LIST *) (resp_info + 1); + for (i = 0; i < num_var; ++i, ++vl) + { + va = nvlist->entries[i]; + + /* For backwards compatibility only ... */ + if (nvlist->va_scope != NULL) + va_scope = &nvlist->va_scope[i]; + else + { + MVL_LOG_NERR0 ("Warning: Info Rpt nvl->va_scope is NULL, using VMD scope"); + va_scope = &vmdVaScope; + va_scope->scope = VMD_SPEC; + } + + vl->alt_access_pres = SD_FALSE; + vl->var_spec.var_spec_tag = VA_SPEC_NAMED; + + /* We know this is a union so the following line is OK ... */ + vl->var_spec.vs.name.obj_name.vmd_spec = va->name; + vl->var_spec.vs.name.object_tag = va_scope->scope; + if (va_scope->scope == DOM_SPEC) + vl->var_spec.vs.name.domain_id = va_scope->dom->name; + } + + indCtrl->u.getvlist.resp_info = resp_info; + + mplas_getvlist_resp (indCtrl); + +#if defined(USE_MANUFACTURED_OBJS) + u_mvl_free_nvl (MMSOP_GET_VLIST, nvlist, indCtrl->event->net_info); +#endif + + M_FREE (MSMEM_ENC_OS_INFO, resp_info); + } + else + { + MVL_LOG_NERR0 ("Get Var List Attributes Indication : could not find the list"); + _mplas_err_resp (indCtrl,MMS_ERRCLASS_DEFINITION,MMS_ERRCODE_OBJ_UNDEFINED); + } + } + +/************************************************************************/ +/* mplas_getvlist_resp */ +/************************************************************************/ + +ST_VOID mplas_getvlist_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + + rc = mpl_getvlist_resp (indCtrl->event->u.mms.dec_rslt.id, + indCtrl->u.getvlist.resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, indCtrl->u.getvlist.resp_info); + + _mvl_send_resp_i (indCtrl, rc); + } + diff --git a/mmslib/mvlu/s_ident.c b/mmslib/mvlu/s_ident.c new file mode 100644 index 0000000..c682429 --- /dev/null +++ b/mmslib/mvlu/s_ident.c @@ -0,0 +1,65 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : s_ident.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 11 Enhanced filtered logging */ +/* 03/11/04 GLB 10 Remove "thisFileName" */ +/* 09/21/01 JRB 09 Alloc global bufs only once at startup. */ +/* 01/21/00 MDE 08 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 04/01/99 MDE 06 Changes to decode buffer allocation scheme */ +/* 11/16/98 MDE 05 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 04 Minor lint cleanup */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 05/14/98 JRB 02 Use MVL_IND_PEND. Add mplas resp function. */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_ident_ind */ +/* A identify indication has been received, process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_ident_ind (MVL_IND_PEND *indCtrl) + { + /* There is no Request Info for this service. Just call user function.*/ + u_mvl_ident_ind (indCtrl); + } + +/************************************************************************/ +/* mplas_ident_resp */ +/************************************************************************/ +ST_VOID mplas_ident_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + +/* Build an identify response */ + rc = mpl_ident_resp (indCtrl->event->u.mms.dec_rslt.id, + indCtrl->u.ident.resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, indCtrl->u.ident.resp_info); + + _mvl_send_resp_i (indCtrl, rc); + } + diff --git a/mmslib/mvlu/s_info.c b/mmslib/mvlu/s_info.c new file mode 100644 index 0000000..04138a7 --- /dev/null +++ b/mmslib/mvlu/s_info.c @@ -0,0 +1,219 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : s_info.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 20 Enhanced filtered logging */ +/* 01/30/06 GLB 19 Integrated porting changes for VMS */ +/* 12/12/02 JRB 18 Add & use mvl_encode_info_rpt funct. */ +/* Use new thread-safe mpl_info,_mvl_send_msg */ +/* and skip S_LOCK.. */ +/* Pass net_info to mvl_get_va_asn1_data so */ +/* don't need mvl_curr_net_info global var. */ +/* 07/10/02 JRB 17 Call mvl_ureq_bufs_avail. */ +/* 02/25/02 MDE 16 Now get max PDU size from mvl_cfg_info */ +/* 09/21/01 JRB 15 Alloc global bufs only once at startup. */ +/* 03/30/01 MDE 14 Changed MSMEM_ENC_INFO to MSMEM_ENC_OS_INFO */ +/* 10/06/00 MDE 13 Added LOCK/UNLOCK */ +/* 08/07/00 JRB 12 Set scope & domain name correctly for NVL. */ +/* 05/15/00 MDE 11 Added MMS statistics */ +/* 04/14/00 JRB 10 Lint cleanup. */ +/* 01/21/00 MDE 09 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 08 Added SD_CONST modifiers */ +/* 09/07/99 MDE 07 Changed MVL_VA_SCOPE to MVL_SCOPE */ +/* 12/11/98 MDE 06 Removed scope references from VA */ +/* 11/16/98 MDE 05 Renamed internal functions (prefix '_') */ +/* 06/15/98 MDE 04 Changes to allow compile under C++ */ +/* 02/10/98 MDE 03 Removed NEST_RT_TYPES, always support AA */ +/* 09/18/97 MDE 02 Fixed problem when no nvl->altAcc */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mvl_acse.h" +#include "mvl_log.h" +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ + +ST_RET mvl_info_variables (MVL_NET_INFO *net_info, MVL_NVLIST_CTRL *nvl, + ST_BOOLEAN listOfVariables) + { +ST_RET rc; +ASN1_ENC_CTXT aCtx; +ST_UCHAR *my_enc_buf; + + if (mvl_ureq_bufs_avail (net_info) <= 0) + { + MVL_LOG_ERR0 ("Not enough ACSE buffers available to send InformationReport"); + return (MVL_ERR_REQ_PEND_COUNT); + } + + my_enc_buf = (ST_UCHAR *) mvl_enc_buf_alloc (mmsl_enc_buf_size); + asn1r_strt_asn1_bld (&aCtx, my_enc_buf, mmsl_enc_buf_size);/*CRITICAL*/ + rc = mvl_encode_info_rpt (net_info, nvl, listOfVariables, &aCtx); + if (rc == SD_SUCCESS) + { /* Encode was successful, go ahead and send. */ + rc = _mvl_send_msg (ASN1_ENC_PTR(&aCtx),ASN1_ENC_LEN(&aCtx),net_info); + if (rc == SD_SUCCESS) /* _mvl_send_msg logs on any error. */ + ++mvl_mms_statistics.serverInfoRpt; + } + mvl_enc_buf_free (my_enc_buf); + return(rc); + } + +/************************************************************************/ +/* mvl_encode_info_rpt */ +/************************************************************************/ +ST_RET mvl_encode_info_rpt (MVL_NET_INFO *net_info, + MVL_NVLIST_CTRL *nvl, + ST_BOOLEAN listOfVariables, + ASN1_ENC_CTXT *aCtx) + { +ST_RET rc; +INFO_REQ_INFO *info_info; +ACCESS_RESULT *ar; +ST_INT req_info_size; +MVL_VAR_ASSOC *va; +MVL_SCOPE *va_scope; +MVL_SCOPE vmdVaScope; +ST_UCHAR *asn1_buf; +ST_UCHAR *asn1_start; +ST_INT asn1_len; +ST_INT asn1_buf_left; +VARIABLE_LIST *vl; +ST_INT num_var; +ST_INT i; +ST_BOOLEAN alt_access_pres; +ALT_ACCESS *alt_acc; + + va = *nvl->entries; + num_var = nvl->num_of_entries; + +/* Calculate the required size for the info report information */ + req_info_size = sizeof(INFO_REQ_INFO) + + (num_var * sizeof(ACCESS_RESULT)); + +/* May need to add some more to handle the variable specification */ + if (listOfVariables == SD_TRUE) + req_info_size += (num_var * sizeof(VARIABLE_LIST)); + + info_info = (INFO_REQ_INFO *) M_CALLOC (MSMEM_ENC_OS_INFO, 1, req_info_size); + info_info->num_of_acc_result = num_var; + +/* We need to create the variable specification - either a list of */ +/* variables or a named variable list */ + if (listOfVariables == SD_TRUE) + { + info_info->va_spec.var_acc_tag = VAR_ACC_VARLIST; + info_info->va_spec.num_of_variables = num_var; + + vl = (VARIABLE_LIST *) (info_info + 1); + for (i = 0; i < nvl->num_of_entries; ++i, ++vl) + { + va = nvl->entries[i]; + + /* For backwards compatibility only ... */ + if (nvl->va_scope != NULL) + va_scope = &nvl->va_scope[i]; + else + { + MVL_LOG_NERR0 ("Warning: Info Rpt nvl->va_scope is NULL, using VMD scope"); + va_scope = &vmdVaScope; + va_scope->scope = VMD_SPEC; + } + + /* We know this is a union so the following line is OK ... */ + vl->var_spec.vs.name.obj_name.vmd_spec = va->name; + vl->var_spec.vs.name.object_tag = va_scope->scope; + if (va_scope->scope == DOM_SPEC) + vl->var_spec.vs.name.domain_id = va_scope->dom->name; + + } + info_info->acc_rslt_list = (ACCESS_RESULT *) (vl); + } + else /* Named Variable List */ + { + info_info->va_spec.var_acc_tag = VAR_ACC_NAMEDLIST; + info_info->va_spec.vl_name.object_tag = nvl->nvl_scope.scope; + if (nvl->nvl_scope.scope == DOM_SPEC) + info_info->va_spec.vl_name.domain_id = nvl->nvl_scope.dom->name; + info_info->va_spec.vl_name.obj_name.vmd_spec = nvl->name; + info_info->acc_rslt_list = (ACCESS_RESULT *) (info_info + 1); + } + ar = info_info->acc_rslt_list; + + asn1_buf = (ST_UCHAR *) M_MALLOC (MSMEM_ASN1_DATA_ENC, mvl_cfg_info->max_msg_size); + asn1_buf_left = mvl_cfg_info->max_msg_size; + +/* Now encode the data, create the access result */ + asn1_start = asn1_buf; + + for (i = 0; i < nvl->num_of_entries; ++i, ++ar) + { + va = nvl->entries[i]; + alt_access_pres = SD_FALSE; + if (nvl->altAcc) + { + alt_acc = nvl->altAcc[i]; + if (alt_acc != NULL) + alt_access_pres = SD_TRUE; + } + else + alt_acc = NULL; /* Just so it's initialized. Eliminates warning.*/ + rc = mvl_get_va_asn1_data (net_info, va, alt_access_pres, alt_acc, asn1_start, + asn1_buf_left, &asn1_len); + + if (rc == SD_SUCCESS) + { + ar->acc_rslt_tag = ACC_RSLT_SUCCESS; + ar->va_data.len = asn1_len; + ar->va_data.data = asn1_start; + asn1_buf_left -= asn1_len; /* adjust buffer control variables */ + asn1_start += asn1_len; + } + else + { + ar->acc_rslt_tag = ACC_RSLT_FAILURE; + ar->failure = ARE_TYPE_INCONSISTENT; + } + } + + /* Build a info request */ + rc = mpl_info (aCtx, info_info); + + /* Log the PDU, if enabled */ + mpl_unsol_req_log (net_info, MMSOP_INFO_RPT, info_info); + + M_FREE (MSMEM_ENC_OS_INFO, info_info); + M_FREE (MSMEM_ASN1_DATA_ENC, asn1_buf); + if (rc != SD_SUCCESS) + MVL_LOG_NERR1 ("mvl_encode_info_rpt error = %x", rc); + + return (rc); + } diff --git a/mmslib/mvlu/s_jinit.c b/mmslib/mvlu/s_jinit.c new file mode 100644 index 0000000..ecbb3d1 --- /dev/null +++ b/mmslib/mvlu/s_jinit.c @@ -0,0 +1,69 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : s_jinit.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_jinit_ind */ +/* mplas_jinit_resp */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 11 Enhanced filtered logging */ +/* 03/11/04 GLB 10 Remove "thisFileName" */ +/* 09/21/01 JRB 09 Alloc global bufs only once at startup. */ +/* 01/21/00 MDE 08 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 04/01/99 MDE 06 Changes to decode buffer allocation scheme */ +/* 11/16/98 MDE 05 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 04 Minor lint cleanup */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 05/14/98 JRB 02 Use MVL_IND_PEND. Add mvlas resp function. */ +/* 11/04/97 MDE 01 Created */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_jinit_ind */ +/* A Initialize Journal indication has been rcved, process and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_jinit_ind (MVL_IND_PEND *indCtrl) + { + indCtrl->u.jinit.req_info = + (JINIT_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + u_mvl_jinit_ind (indCtrl); + } + +/************************************************************************/ +/* mplas_jinit_resp */ +/************************************************************************/ +ST_VOID mplas_jinit_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + + /* Build a jinit response */ + rc = mpl_jinit_resp (indCtrl->event->u.mms.dec_rslt.id, + indCtrl->u.jinit.resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, indCtrl->u.jinit.resp_info); + + _mvl_send_resp_i (indCtrl, rc); + } + diff --git a/mmslib/mvlu/s_jread.c b/mmslib/mvlu/s_jread.c new file mode 100644 index 0000000..065d6e0 --- /dev/null +++ b/mmslib/mvlu/s_jread.c @@ -0,0 +1,337 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : s_jread.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_jread_ind */ +/* mvlas_jread_resp */ +/* mplas_jread_resp */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 21 Enhanced filtered logging */ +/* 10/30/06 JRB 20 Use new mvl_vmd_* object handling functions. */ +/* 01/30/06 GLB 19 Integrated porting changes for VMS */ +/* 03/28/05 JRB 18 Del suicacse header. */ +/* 02/25/02 MDE 17 Now get max PDU size from mvl_cfg_info */ +/* 09/21/01 JRB 16 Alloc global bufs only once at startup. */ +/* 03/30/01 MDE 15 Changed MSMEM_ENC_INFO to MSMEM_ENC_OS_INFO */ +/* 01/21/00 MDE 14 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 13 Added SD_CONST modifiers */ +/* 08/30/99 JRB 12 DON'T log after mplas_err_resp (causes GPF). */ +/* 01/15/99 JRB 11 Call mvl_find_jou to find journal. */ +/* 11/16/98 MDE 10 Renamed internal functions (prefix '_') */ +/* 10/09/98 JRB 09 Use modified MVL_JOURNAL_ENTRY. */ +/* 09/21/98 MDE 08 Minor lint cleanup */ +/* 09/10/98 JRB 07 Make sure moreFollows set correctly. */ +/* 07/16/98 MDE 06 More journal work */ +/* 07/15/98 MDE 05 Changed Journal Read user functions */ +/* 06/15/98 MDE 04 Changes to allow compile under C++ */ +/* 05/14/98 JRB 03 Use MVL_IND_PEND. Add mvlas resp function. */ +/* 05/14/98 JRB 02 Fixed uninitialized pointers, etc. */ +/* 11/04/97 MDE 01 Created */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_acse.h" +#include "mvl_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/* Local variables and functions */ + +static MVL_JREAD_BUF_CTRL _bufCtrl; +static ST_UCHAR *_asn1BufStart; +static ST_INT _asn1BufLeft; + +static ST_RET mvlJe_to_je (JOURNAL_ENTRY *je, MVL_JOURNAL_ENTRY *mvlJe); + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_jread_ind */ +/* A Read Journal indication has been rcved, process and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_jread_ind (MVL_IND_PEND *indCtrl) + { + indCtrl->u.jread.req_info = + (JREAD_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + u_mvl_jread_ind (indCtrl); + } + +/************************************************************************/ +/* mvlas_jread_resp */ +/* This is the Virtual Machine response function for ReadJournal. */ +/* It calls the following user functions to manage the Journal data: */ +/* u_mvl_start_jread */ +/* u_mvl_get_next_jread_entry */ +/* u_mvl_free_jread_entry */ +/* u_mvl_end_jread */ +/************************************************************************/ +ST_RET app_start_jread(MVL_JOURNAL_CTRL *jCtrl,JREAD_REQ_INFO *reqInfo,MVL_JREAD_BUF_CTRL *bufCtrl, + void **usrHandleOut); +ST_VOID mvlas_jread_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; +JREAD_REQ_INFO *reqInfo; +JREAD_RESP_INFO *respInfo; +JOURNAL_ENTRY *je; +ST_BOOLEAN moreFollows = SD_FALSE; /* Would never get set if 0 entries*/ +MVL_JOURNAL_CTRL *jCtrl; +MVL_JOURNAL_ENTRY mvlJe; +MVL_JOURNAL_ENTRY *mvlJep; +ST_VOID *usrHandle; +ST_UCHAR *asn1_buf; +ST_INT i; + + reqInfo = indCtrl->u.jread.req_info; +/* First find our Journal Control element */ + jCtrl = mvl_vmd_find_jou (&mvl_vmd, &reqInfo->jou_name, indCtrl->event->net_info); + if (jCtrl == NULL) + { + MVL_LOG_NERR1 ("ReadJournal - could not find journal '%s'", + reqInfo->jou_name.obj_name.vmd_spec); + printf("ReadJournal - could not find journal '%s'\n", + reqInfo->jou_name.obj_name.vmd_spec); + _mplas_err_resp (indCtrl, 2, 1); /* object undefined */ + return; + } + +/* Give the user the JREAD request information */ + memset (&_bufCtrl, 0, sizeof (MVL_JREAD_BUF_CTRL)); + /* renxiaobao ÈÕÖ¾*/ +/*rc = u_mvl_start_jread (jCtrl, reqInfo, &_bufCtrl, &usrHandle);*/ + rc = app_start_jread(jCtrl, reqInfo, &_bufCtrl, &usrHandle); + if (rc != SD_SUCCESS) + { + _mplas_err_resp (indCtrl, 2, 1); /* object undefined */ + return; + } + +/* Limit the number we will return */ + if (_bufCtrl.numUsrEntries > MAX_JREAD_RESP_ENTRIES) + _bufCtrl.numUsrEntries = MAX_JREAD_RESP_ENTRIES; + + if (_bufCtrl.numVarInfo > MAX_JREAD_RESP_VARS) + _bufCtrl.numVarInfo = MAX_JREAD_RESP_VARS; + +/* Allocate the response information data buffer */ + respInfo = + (JREAD_RESP_INFO *) M_CALLOC (MSMEM_ENC_OS_INFO, 1, sizeof (JREAD_RESP_INFO) + + (_bufCtrl.numUsrEntries * sizeof (JOURNAL_ENTRY)) + + (_bufCtrl.numVarInfo * sizeof (VAR_INFO)) ); + +/* + //printf("respInfo size=%d \n ",sizeof (JREAD_RESP_INFO) + +// (_bufCtrl.numUsrEntries * sizeof (JOURNAL_ENTRY)) + +// (_bufCtrl.numVarInfo * sizeof (VAR_INFO))); +*/ +/* Set the storage buffer start locations */ +#if defined (MVL_JREAD_ENTRYID_DYNAMIC) + _bufCtrl.nextEntryId = _bufCtrl.entryIdBuf; +#endif +#if defined (MVL_JREAD_VARTAG_DYNAMIC) + _bufCtrl.nextVarTag = _bufCtrl.varTagBuf; +#endif +#if defined (MVL_JREAD_ANNOTATION_DYNAMIC) + _bufCtrl.nextAnnotation = _bufCtrl.annotationBuf; +#endif + +/* Allocate the ASN.1 data encode buffer */ + asn1_buf = (ST_UCHAR *) M_MALLOC (MSMEM_ASN1_DATA_ENC, mvl_cfg_info->max_msg_size); + _asn1BufStart = asn1_buf; + _asn1BufLeft = mvl_cfg_info->max_msg_size; + +/* Now get the journals from the user, one at a time */ + respInfo->num_of_jou_entry = 0; + je = (JOURNAL_ENTRY *) (respInfo + 1); + for (i = 0; i < _bufCtrl.numUsrEntries; ++i) + { + /* get the next from the user */ + mvlJep = &mvlJe; + rc = u_mvl_get_next_jread_entry (jCtrl, usrHandle, &moreFollows, &mvlJep); + if (rc != SD_SUCCESS) + { + moreFollows = SD_FALSE; /* Didn't get entry, so can't be more. */ + break; + } + + /* Map it onto the MMS-EASE JOURNAL_ENTRY */ + + rc = mvlJe_to_je (je, mvlJep); + /* Let the user free resources */ + u_mvl_free_jread_entry (jCtrl, usrHandle, mvlJep); + + /* Verify that the mapping was OK */ + if (rc != SD_SUCCESS) + { + M_FREE (MSMEM_ASN1_DATA_ENC, asn1_buf); + M_FREE (MSMEM_ENC_OS_INFO, respInfo); + _mplas_err_resp (indCtrl, 1, 3); /* application reference invalid */ + return; + } + + ++respInfo->num_of_jou_entry; + if (moreFollows == SD_FALSE) + break; + + /* We need to adjust the MMS-EASE JE pointer to the next position */ + /* Each JE is possibly followed by a array of VAR_INFO */ + if (je->ent_content.entry_form_tag == 2 && + je->ent_content.ef.data.list_of_var_pres) + { + je = (JOURNAL_ENTRY *) ((ST_CHAR *)je + sizeof (JOURNAL_ENTRY) + + je->ent_content.ef.data.num_of_var * sizeof (VAR_INFO)); + } + else + ++je; /* CRITICAL: don't try to access je after this */ + } + respInfo->more_follows = moreFollows; + +/* OK, the MMS-EASE data structure is ready to roll */ + + indCtrl->u.jread.resp_info = respInfo; + + mplas_jread_resp (indCtrl); + + M_FREE (MSMEM_ASN1_DATA_ENC, asn1_buf); + M_FREE (MSMEM_ENC_OS_INFO, respInfo); +/* Tell the user we are done */ + u_mvl_end_jread (jCtrl, usrHandle, &_bufCtrl, reqInfo); + } + +/************************************************************************/ +/* mplas_jread_resp */ +/************************************************************************/ +ST_VOID mplas_jread_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + + /* Build a jread response */ + rc = mpl_jread_resp (indCtrl->event->u.mms.dec_rslt.id, + indCtrl->u.jread.resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, indCtrl->u.jread.resp_info); + + _mvl_send_resp_i (indCtrl, rc); + } + + +/************************************************************************/ +/* mvlJe_to_je */ +/************************************************************************/ + +static ST_RET mvlJe_to_je (JOURNAL_ENTRY *je, MVL_JOURNAL_ENTRY *mvlJe) + { +ST_UCHAR *appRefAsn1Start; +ST_INT appRefAsn1Len; +ST_INT i; +ST_INT numVar; +ST_RET rc; +VAR_INFO *varInfo; + +/* First take care of the entry ID */ +#if defined (MVL_JREAD_ENTRYID_DYNAMIC) + je->entry_id_len = mvlJe->entry_id_len; + je->entry_id = _bufCtrl.nextEntryId; + memcpy (_bufCtrl.nextEntryId, mvlJe->entry_id, mvlJe->entry_id_len); + _bufCtrl.nextEntryId += mvlJe->entry_id_len; +#else + je->entry_id_len = mvlJe->entry_id_len; + je->entry_id = mvlJe->entry_id; +#endif + +/* Now take care of the application reference ... */ + rc = ms_appref_to_asn1 (&(mvlJe->orig_app), _asn1BufStart, _asn1BufLeft, + &appRefAsn1Start, &appRefAsn1Len); + if (rc == SD_SUCCESS) + { + je->orig_ae_len = appRefAsn1Len; + je->orig_ae = appRefAsn1Start; + + /* Adjust ASN.1 buffer control - this was built from the back, so */ + /* don't need to change the buffer start pointer. */ + _asn1BufLeft -= appRefAsn1Len; + } + else + { + MVL_LOG_ERR0 ("Error: ReadJournal.Resp: orig_app encode failed"); + return (rc); + } + +/* Now set up the entry content */ + +/* Occurance Time */ + memcpy (&(je->ent_content.occur_time), &(mvlJe->occur_time), + sizeof (MMS_BTOD)); + +/* No additional detail */ + je->ent_content.addl_detail_pres = SD_FALSE; + + je->ent_content.entry_form_tag = mvlJe->entry_form_tag; + if (mvlJe->entry_form_tag == 2) /* event/data */ + { + je->ent_content.ef.data.event_pres = mvlJe->ef.data.event_pres; + + memcpy (&(je->ent_content.ef.data.evcon_name), + &(mvlJe->ef.data.evcon_name), sizeof (OBJECT_NAME)); + je->ent_content.ef.data.cur_state = mvlJe->ef.data.cur_state; + + je->ent_content.ef.data.list_of_var_pres = mvlJe->ef.data.list_of_var_pres; + if (je->ent_content.ef.data.list_of_var_pres) + { + numVar = mvlJe->ef.data.num_of_var; + je->ent_content.ef.data.num_of_var = numVar; + + varInfo = (VAR_INFO *) (je + 1); + for (i = 0; i < numVar; ++i, ++varInfo) + { + /* OK, now tell MMS-EASE where the ASN.1 data is */ + varInfo->value_spec.data = mvlJe->ef.data.list_of_var[i].value_spec.data; + varInfo->value_spec.len = mvlJe->ef.data.list_of_var[i].value_spec.len; + + /* Now store the var_tag in our buffer and set the MMS pointer */ +#if defined (MVL_JREAD_VARTAG_DYNAMIC) + varInfo->var_tag = _bufCtrl.nextVarTag; + strcpy (_bufCtrl.nextVarTag, mvlJe->ef.data.list_of_var[i].var_tag); + _bufCtrl.nextVarTag += (strlen (_bufCtrl.nextVarTag) + 1); +#else + varInfo->var_tag = mvlJe->ef.data.list_of_var[i].var_tag; +#endif + } /* end "loop" */ + } /* end "if list_of_var_pres" */ + } + else /* entry form is annotation */ + { +#if defined (MVL_JREAD_ANNOTATION_DYNAMIC) + je->ent_content.ef.annotation = _bufCtrl.nextAnnotation; + strcpy (_bufCtrl.nextAnnotation, mvlJe->ef.annotation); + _bufCtrl.nextAnnotation += (strlen (_bufCtrl.nextAnnotation) + 1); +#else + je->ent_content.ef.annotation = mvlJe->ef.annotation; +#endif + } + return (SD_SUCCESS); + } + diff --git a/mmslib/mvlu/s_jstat.c b/mmslib/mvlu/s_jstat.c new file mode 100644 index 0000000..4ab8d6a --- /dev/null +++ b/mmslib/mvlu/s_jstat.c @@ -0,0 +1,67 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1998, All Rights Reserved */ +/* */ +/* MODULE NAME : s_jstat.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_jstat_ind */ +/* mplas_jstat_resp */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 10 Enhanced filtered logging */ +/* 03/11/04 GLB 09 Remove "thisFileName" */ +/* 09/21/01 JRB 08 Alloc global bufs only once at startup. */ +/* 01/21/00 MDE 07 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 04/01/99 MDE 05 Changes to decode buffer allocation scheme */ +/* 11/16/98 MDE 04 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 03 Minor lint cleanup */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 04/14/98 JRB 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pfil.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/* _mvl_process_jstat_ind */ +/* A "jstat" indication has been received, process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_jstat_ind (MVL_IND_PEND *indCtrl) + { + indCtrl->u.jstat.req_info = + (JSTAT_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + u_mvl_jstat_ind (indCtrl); + } + +/************************************************************************/ +/* mplas_jstat_resp */ +/************************************************************************/ +ST_VOID mplas_jstat_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + + /* Build a jstat response */ + rc = mpl_jstat_resp (indCtrl->event->u.mms.dec_rslt.id, + indCtrl->u.jstat.resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, indCtrl->u.jstat.resp_info); + + _mvl_send_resp_i (indCtrl, rc); + } + + diff --git a/mmslib/mvlu/s_obtfi.c b/mmslib/mvlu/s_obtfi.c new file mode 100644 index 0000000..7dd6c5a --- /dev/null +++ b/mmslib/mvlu/s_obtfi.c @@ -0,0 +1,466 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1998 - 1999, All Rights Reserved */ +/* */ +/* MODULE NAME : s_obtfi.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* _mvl_process_obtfile_ind */ +/* mplas_obtfile_resp */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/12/07 MDE 10 Use _mvl_getpath for temp file path */ +/* 04/09/07 MDE 09 Enhanced filtered logging */ +/* 10/17/06 MDE 08 Added mvlas_obtfile_resp_ex */ +/* 01/30/06 GLB 07 Integrated porting changes for VMS */ +/* 02/04/03 MDE 06 Now use _mvl_tmpnam */ +/* 09/21/01 JRB 05 Alloc global bufs only once at startup. */ +/* 04/14/00 EJV 04 Added check for more error conditions in */ +/* u_fopen_done and u_fread_done */ +/* 03/21/00 JRB 03 Send err resp if tmpnam or fopen fails. */ +/* 01/21/00 MDE 02 Now use MEM_SMEM for dynamic memory */ +/* 10/15/99 GLB 01 Created to add Obtain File function */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +#include +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +typedef struct filecopyinfo + { + ST_CHAR tempfilename[MVL_MAX_TMPNAM_LEN+1]; + ST_CHAR destfilename[MAX_FILE_NAME+1]; + MVL_IND_PEND *indCtrl; + FILE *fp; + ST_INT32 frsmid; + ST_UINT32 fsize; + ST_UINT32 fileSizeLimit; + } MVL_OBTFILE_STATE; + +MVL_REQ_PEND *send_file_open (MVL_NET_INFO *NetInfo, ST_CHAR *src); +MVL_REQ_PEND *send_file_read (MVL_NET_INFO *NetInfo, + MVL_OBTFILE_STATE *u_file_info); +MVL_REQ_PEND *send_file_close (MVL_NET_INFO *NetInfo, + MVL_OBTFILE_STATE *u_file_info); +ST_VOID u_fopen_done (MVL_REQ_PEND *req); +ST_VOID u_fread_done( MVL_REQ_PEND *req); +ST_VOID u_fclose_done( MVL_REQ_PEND *req); + + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_obtfile_ind */ +/* An Obtain File request has been sent and */ +/* An Obtain File indication was received, so process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_obtfile_ind (MVL_IND_PEND *indCtrl) + { + OBTFILE_REQ_INFO *req_info; + MVLAS_OBTFILE_CTRL *obtfile; + FILE_NAME *fname_idx; + + + req_info = (OBTFILE_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + fname_idx = (FILE_NAME *)(req_info + 1); + + obtfile = &indCtrl->u.obtfile; + + if (_mvl_concat_filename (obtfile->srcfilename, req_info->num_of_src_fname, + fname_idx, sizeof (obtfile->srcfilename))) + { + MVL_LOG_ERR0 ("ObtFile error: _mvl_process_obtfile_ind failed (_mvl_concat_filename(srcfilename) failed)"); + _mplas_err_resp (indCtrl,11,3); /* 3 = File name syntax error */ + return; + } + + if (_mvl_concat_filename (obtfile->destfilename, req_info->num_of_dest_fname, + (FILE_NAME *)(fname_idx + req_info->num_of_src_fname), + sizeof (obtfile->destfilename))) + { + MVL_LOG_ERR0 ("ObtFile error: _mvl_process_obtfile_ind failed (_mvl_concat_filename(destfilename) failed)"); + _mplas_err_resp (indCtrl,11,3); /* 3 = File name syntax error */ + return; + } + + u_mvl_obtfile_ind (indCtrl); + } + +/************************************************************************/ +/* mvlas_obtfile_resp */ +/* Open a temp file to copy into and save the destination file name */ +/************************************************************************/ + +ST_VOID mvlas_obtfile_resp (MVL_IND_PEND *indCtrl) + { + mvlas_obtfile_resp_ex (indCtrl, 0); + } + +extern int mms_filename_conv(char *mms_name,char *sys_name); +ST_VOID mvlas_obtfile_resp_ex (MVL_IND_PEND *indCtrl, ST_UINT32 fileSizeLimit) + { + MVL_OBTFILE_STATE *obtfile_state; + MVL_REQ_PEND *req; + MVLAS_OBTFILE_CTRL *obtfile; + int ret; + ST_CHAR tmpfile_path[MVL_MAX_TMPFILE_PATH]; + ST_CHAR destfilename[MVL_MAX_TMPFILE_PATH]; + + obtfile = &indCtrl->u.obtfile; + + obtfile_state = (MVL_OBTFILE_STATE *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_OBTFILE_STATE)); + /* save destination name for rename */ + + /*ÎļþÃûÓ³Éä*/ + ret = mms_filename_conv(obtfile->destfilename,destfilename); + if(!ret) printf("Îļþ%sÓ³Éäʧ°Ü...\n\r",obtfile->destfilename); + strcpy(obtfile->destfilename,destfilename); + + /*renxiaobao Îļþ²Ù×÷ + tmpfile_path[0] = 0; + if(obtfile->destfilename[0]!='/') strcpy (tmpfile_path, "/"); + strcat (tmpfile_path, obtfile->destfilename); + strcpy(obtfile->destfilename,tmpfile_path);*/ + + strncpy (obtfile_state->destfilename, obtfile->destfilename, MAX_FILE_NAME+1); + + obtfile_state->indCtrl = indCtrl; + /* Create a temporary file name to copy into. This prevents partially */ + /* transferred files from hanging around and being accidently used */ + /* Open the created temporary file. Send the file open request. */ + + _mvl_getpath (destfilename, tmpfile_path); + + if (_mvl_tmpnam (obtfile_state->tempfilename, tmpfile_path) != SD_SUCCESS || + (obtfile_state->fp = fopen(obtfile_state->tempfilename, "wb")) == NULL || + (req = send_file_open (indCtrl->event->net_info,obtfile->srcfilename)) == NULL) + { + if ( obtfile_state->fp ) + { + MVL_LOG_ERR0 ("ObtFile error: mvlas_obtfile_resp failed (fopen failed)"); + fclose (obtfile_state->fp); /* close temporary file */ + remove (obtfile_state->tempfilename); /* get rid of temporary file */ + } + else + { + MVL_LOG_ERR1 ("ObtFile: mvlas_obtfile_resp failed (invalid tmpnam (%s) or send_file_open failed)", + obtfile_state->tempfilename); + } + _mplas_err_resp (indCtrl,11,0); /* 0 = other */ + } + else + { + req->v = obtfile_state; + obtfile_state->fileSizeLimit = fileSizeLimit; + } + } + +/************************************************************************/ +/* send_file_open */ +/* Send a file open request to open file on the other side */ +/************************************************************************/ + +MVL_REQ_PEND *send_file_open (MVL_NET_INFO *NetInfo, ST_CHAR *src) + { +MVL_REQ_PEND *req= NULL; + + if ((mvla_fopen(NetInfo, src, 0, &req)) == SD_SUCCESS) + { + req->u_req_done = u_fopen_done; + } + return (req); + } + +/************************************************************************/ +/* u_fopen_done */ +/* It was indicated that a file open request was made */ +/* Confirm file open response that was received as a result of a request*/ +/************************************************************************/ + +ST_VOID u_fopen_done( MVL_REQ_PEND *req) + { + ST_RET ret; + MVL_REQ_PEND *freadreq= NULL; + MVL_OBTFILE_STATE *obtfile_state; + FOPEN_RESP_INFO *resp_info; +#if 0 + ERR_INFO *err_ptr; + REJECT_RESP_INFO *rej_ptr; +#endif + + obtfile_state = (MVL_OBTFILE_STATE *) req->v; + ret = req->result; + if (ret == SD_SUCCESS) + { + resp_info = req->u.fopen.resp_info; + if (obtfile_state->fileSizeLimit > 0 && + (resp_info->ent.fsize > obtfile_state->fileSizeLimit)) + { + MVL_LOG_NERR2 ("ObtFile error: file size %ld exceeds limit %ld", + resp_info->ent.fsize, obtfile_state->fileSizeLimit); + ret = SD_FAILURE; + } + else + { + + obtfile_state ->frsmid = resp_info->frsmid; + obtfile_state ->fsize = resp_info->ent.fsize; + if ((freadreq = send_file_read (req->net_info, obtfile_state)) != NULL) + { + freadreq->v = obtfile_state; + } + else + { + MVL_LOG_ERR0 ("ObtFile error: u_fopen_done failed (send_file_read failed)"); + ret = SD_FAILURE; + } + } + } + else + { + MVL_LOG_ERR0 ("ObtFile error: u_fopen_done failed (mvla_fopen failed)"); + } + if ( ret != SD_SUCCESS ) + { /* file open failed */ +#if 0 + if (req->result==MVL_ERR_CNF_REJ_ERR) + { + rej_ptr = (REJECT_RESP_INFO *) req->event->u.mms.dec_rslt.data_ptr; + printf ("\n MMS REJECT"); + printf ("\n detected_here = %d",req->u.reject.resp_info->detected_here); + printf ("\n invoke_known = %d",req->u.reject.resp_info->invoke_known); + printf ("\n invoke = %d",req->u.reject.resp_info->invoke); + printf ("\n pdu_type = %d",req->u.reject.resp_info->pdu_type); + printf ("\n rej_class = %d",req->u.reject.resp_info->rej_class); + printf ("\n rej_code = %d",req->u.reject.resp_info->rej_code); + } + if (req->result==MVL_ERR_CNF_ERR_OK) + { + err_ptr = (ERR_INFO *) req->event->u.mms.dec_rslt.data_ptr; + printf ("\n MMS ERROR RESPONSE"); + printf ("\n class = %d, code = %d", req->u.error.resp_info->eclass, + req->u.error.resp_info->code); + + } +#endif + fclose (obtfile_state->fp); /* close temporary file */ + remove (obtfile_state->tempfilename); /* get rid of temporary file */ + if (req->net_info->conn_active == SD_TRUE) + _mplas_err_resp (obtfile_state->indCtrl,11,0); /* 0 = other */ + M_FREE (MSMEM_GEN, obtfile_state); + } + mvl_free_req_ctrl (req); + } + +/************************************************************************/ +/* send_file_read */ +/* Send a file read request to obtain a block of the file data */ +/************************************************************************/ + +MVL_REQ_PEND *send_file_read (MVL_NET_INFO *NetInfo, + MVL_OBTFILE_STATE *obtfile_state) + { + MVL_REQ_PEND *req= NULL; + + FREAD_REQ_INFO fread_req; + + fread_req.frsmid = obtfile_state->frsmid; + if ((mvla_fread (NetInfo, &fread_req, &req)) == SD_SUCCESS) + { + req->u_req_done = u_fread_done; + } + + return (req); + } + + +/************************************************************************/ +/* u_fread_done */ +/* Confirm the file read response sent to indicate a read request */ +/************************************************************************/ + +ST_VOID u_fread_done( MVL_REQ_PEND *req) + { + ST_RET ret; + MVL_REQ_PEND *freadreq= NULL; + MVL_REQ_PEND *fclosereq= NULL; + MVL_OBTFILE_STATE *obtfile_state; + FREAD_RESP_INFO *resp_info; + + obtfile_state = (MVL_OBTFILE_STATE *) req->v; + + ret = req->result; + if (ret == SD_SUCCESS) + { + resp_info = req->u.fread.resp_info; + + if ( fwrite (resp_info->filedata, sizeof(ST_CHAR), resp_info->fd_len, obtfile_state->fp) + == (unsigned) resp_info->fd_len ) + { + if ( resp_info->more_follows == SD_TRUE) + { + if ((freadreq = send_file_read (req->net_info, obtfile_state)) != NULL) + { + freadreq->v = obtfile_state; /* if more file data request to read another block */ + } + else + { + MVL_LOG_ERR0 ("ObtFile error: u_fread_done failed (send_file_read failed)"); + ret = SD_FAILURE; + } + } + else + { + if ((fclosereq = send_file_close (req->net_info, obtfile_state)) != NULL) + { + fclosereq->v = obtfile_state; /* no more file data so send a file close request */ + } + else + { + MVL_LOG_ERR0 ("ObtFile error: u_fread_done failed (send_file_close failed)"); + ret = SD_FAILURE; + } + } + } + else + { + /* write failed */ + MVL_LOG_ERR0 ("ObtFile error: u_fread_done failed (fwrite failed)"); + ret = SD_FAILURE; + } + } + else + { + MVL_LOG_ERR0 ("ObtFile error: u_fread_done failed (mvla_fread failed)"); + } + + if (ret != SD_SUCCESS ) + { /* read failed so close and remove temp file */ + fclose (obtfile_state->fp); + remove (obtfile_state->tempfilename); /* may fail if file nonexistent */ + if (req->net_info->conn_active == SD_TRUE) + _mplas_err_resp (obtfile_state->indCtrl,11,0); /* 0 = Other */ + M_FREE (MSMEM_GEN, obtfile_state); + } + + mvl_free_req_ctrl (req); + } + +/************************************************************************/ +/* send_file_close */ +/* No more data to read from file so send a request to close the file */ +/************************************************************************/ + +MVL_REQ_PEND *send_file_close (MVL_NET_INFO *NetInfo, + MVL_OBTFILE_STATE *obtfile_state) + { + MVL_REQ_PEND *req= NULL; + FCLOSE_REQ_INFO fclose_req; + + fclose_req.frsmid = obtfile_state->frsmid; + if ((mvla_fclose (NetInfo, &fclose_req, &req)) == SD_SUCCESS) + { + req->u_req_done = u_fclose_done; + } + + return (req); + } + +/************************************************************************/ +/* u_fclose_done */ +/* Confirm file closed response */ +/************************************************************************/ +int obtfile_call_back(MVL_IND_PEND *indCtrl); +ST_VOID u_fclose_done( MVL_REQ_PEND *req) + { + int ret; + MVL_OBTFILE_STATE *obtfile_state; + + obtfile_state = (MVL_OBTFILE_STATE *) req->v; + + if (req->result == SD_SUCCESS) /* close succeeded */ + { + + /* always close transferred file, rename and remove temp file */ + fclose (obtfile_state->fp); /* close temp file */ + remove (obtfile_state->destfilename); /* may fail if file nonexistent */ + + /* rename the temporary file to become the requested destination file */ + /* use the ANSI rename function if available on your OS */ + /* otherwise use other function appropriate for your system */ + if (rename (obtfile_state->tempfilename, obtfile_state->destfilename)) + { + MVL_LOG_ERR0 ("ObtFile error: u_fclose_done failed (rename failed)"); + printf("ObtFile error: %s-%s)",obtfile_state->tempfilename, obtfile_state->destfilename); + remove (obtfile_state->tempfilename); /* cleanup useless file */ + _mplas_err_resp (obtfile_state->indCtrl, 11, 0); /* 0 = other file error */ + } + else /* send an obtainfile response */ + { + ret = obtfile_call_back (obtfile_state->indCtrl); + if(ret==0) mplas_obtfile_resp (obtfile_state->indCtrl); + else _mplas_err_resp (obtfile_state->indCtrl, 11, 0); + /* mplas_obtfile_resp (obtfile_state->indCtrl); */ + } + + } + else /* close failed */ + { + MVL_LOG_ERR0 ("ObtFile error: u_fclose_done failed (mvla_fclose failed)"); + + /* always close transferred file, rename and remove temp file */ + fclose (obtfile_state->fp); /* close temp file */ + + remove (obtfile_state->tempfilename); /* cleanup useless file */ + /* but don't send an obtainfile response */ + + if (req->net_info->conn_active == SD_TRUE) + _mplas_err_resp (obtfile_state->indCtrl,11,0); /* 0 = other */ + } + + M_FREE (MSMEM_GEN, obtfile_state); + mvl_free_req_ctrl (req); + } + + +/************************************************************************/ +/* mplas_obtfile_resp */ +/* Send a response to confirm the obtain file request that prompted the */ +/* reading of file data */ +/************************************************************************/ +ST_VOID mplas_obtfile_resp (MVL_IND_PEND *indCtrl) + { + ST_RET rc; + + /* Build an Obtain File Response with Null to confirm */ + rc = mpl_obtfile_resp (indCtrl->event->u.mms.dec_rslt.id); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, NULL); + + _mvl_send_resp_i (indCtrl, rc); + + + } + diff --git a/mmslib/mvlu/s_read.c b/mmslib/mvlu/s_read.c new file mode 100644 index 0000000..833b64d --- /dev/null +++ b/mmslib/mvlu/s_read.c @@ -0,0 +1,449 @@ +/*******************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2005, All Rights Reserved */ +/* */ +/* MODULE NAME : s_read.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/23/09 JRB 30 Deal with non-named variables better */ +/* 04/09/07 MDE 29 Enhanced filtered logging */ +/* 10/30/06 JRB 28 Use new mvl_vmd_* object handling functions. */ +/* Add args on call to _mvl_objname_to_va. */ +/* Elim use of global "_mvl_curr_usr_ind_ctrl". */ +/* 08/09/06 JRB 27 For MVL_UCA, call mvl_find_nvl */ +/* (DO NOT call u_mvl_get_nvl, u_mvl_free_nvl). */ +/* 01/30/06 GLB 26 Integrated porting changes for VMS */ +/* 10/19/05 JRB 25 Fix spec_in_result handling (was ignored). */ +/* 05/16/05 JRB 24 Send appropriate failure codes in read resp. */ +/* 12/12/02 JRB 23 Add net_info arg to mvl_get_va_asn1_data & */ +/* prep_.. functions to elim use of */ +/* mvl_curr_net_info global var. */ +/* 07/24/02 JRB 22 Use mvl_send_resp_i like ALL responses. */ +/* 07/09/02 MDE 21 Add maxpend_ind support */ +/* 02/25/02 MDE 20 Now get max PDU size from mvl_cfg_info */ +/* 09/21/01 JRB 19 Alloc global bufs only once at startup. */ +/* 03/30/01 MDE 18 Changed MSMEM_ENC_INFO to MSMEM_ENC_OS_INFO */ +/* 10/25/00 JRB 17 Del u_mvl funct ptrs. Call functs directly. */ +/* Control with #ifdefs. */ +/* 06/19/00 JRB 16 Free rdCtrl->vaCtrlTbl on error. */ +/* 05/15/00 MDE 15 Added MMS statistics */ +/* 03/10/00 JRB 14 Copy va_scope to appropriate structures. */ +/* 01/21/00 MDE 13 Now use MEM_SMEM for dynamic memory */ +/* 11/22/99 JRB 12 mvlas_read_resp: del indCtrl from link list */ +/* 09/13/99 MDE 11 Added SD_CONST modifiers */ +/* 04/07/99 MDE 10 Logging improvements */ +/* 01/15/99 JRB 09 IF (u_mvl_get_nvl_fun != NULL) call it, */ +/* ELSE call "mvl_find_nvl". */ +/* 12/11/98 MDE 08 Removed scope references from VA */ +/* 11/16/98 MDE 07 Renamed internal functions (prefix '_') */ +/* 11/10/98 MDE 06 Moved 'mvl_get_va_asn1_data' to mvl_var.c */ +/* 06/15/98 MDE 05 Changes to allow compile under C++ */ +/* 05/15/98 JRB 04 Chg mvl_process.. arg to (MVL_IND_PEND *). */ +/* 05/15/98 JRB 03 Call u_mvl_read_ind direct (no funct ptr). */ +/* 02/10/98 MDE 02 Removed NEST_RT_TYPES, always support AA, */ +/* added 'u_mvl_rd_ind_start' and */ +/* 'u_mvl_rd_resp_sent', other */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mvl_acse.h" +#include "mvl_log.h" + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + + +/************************************************************************/ +/************************************************************************/ + +ST_RET (*u_mvl_rd_ind_start) (MVL_IND_PEND *indCtrl); +ST_VOID (*u_mvl_rd_resp_sent) (MVL_IND_PEND *indCtrl); + +/************************************************************************/ +/************************************************************************/ +/* Internal functions */ + +static ST_RET prep_lov_rd_ctrl (MVL_IND_PEND *indCtrl, READ_REQ_INFO *read_info, + MVLAS_READ_CTRL *rdCtrlOut); +static ST_RET prep_nvl_rd_ctrl (MVL_IND_PEND *indCtrl, MVL_NET_INFO *net_info, READ_REQ_INFO *read_info, + MVLAS_READ_CTRL *rdCtrlOut); +static ST_RET prep_read_resp (MVL_NET_INFO *net_info, MVLAS_READ_CTRL *rdCtrl, + READ_REQ_INFO *req_info, + READ_RESP_INFO **resp_info_out, + ST_UCHAR *asn1_buf, ST_INT asn1_buf_size); + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_read_ind */ +/************************************************************************/ + +ST_VOID _mvl_process_read_ind (MVL_IND_PEND *indCtrl) + { +READ_REQ_INFO *read_info; +MVLAS_READ_CTRL *rdCtrl; +ST_RET rc; + + rdCtrl = &indCtrl->u.rd; + read_info = (READ_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + rdCtrl->var_acc_tag = read_info->va_spec.var_acc_tag; + + rc = SD_SUCCESS; + if (u_mvl_rd_ind_start) + { + /* This might set optional user pointer "indCtrl->usr_ind_ctrl". */ + rc = (*u_mvl_rd_ind_start) (indCtrl); + } + + if (rc == SD_SUCCESS) + { + if (rdCtrl->var_acc_tag == VAR_ACC_NAMEDLIST) + rc = prep_nvl_rd_ctrl (indCtrl, indCtrl->event->net_info, read_info, rdCtrl); + else + rc = prep_lov_rd_ctrl (indCtrl, read_info, rdCtrl); + } + + if (rc == SD_SUCCESS) + { + u_mvl_read_ind (indCtrl); + } + else + { + _mplas_err_resp (indCtrl,7,2); + } + } + +/************************************************************************/ +/* prep_lov_rd_ctrl */ +/************************************************************************/ + +static ST_RET prep_lov_rd_ctrl (MVL_IND_PEND *indCtrl, READ_REQ_INFO *read_info, + MVLAS_READ_CTRL *rdCtrl) + { +MVLAS_RD_VA_CTRL *vaCtrl; +VARIABLE_LIST *vl; +ST_INT num_var; +ST_INT i; +ST_BOOLEAN alt_access_pres; + + /* This is a list of variables */ + + /* Allocate the read control data structures */ + num_var = read_info->va_spec.num_of_variables; + rdCtrl->vaCtrlTbl = (MVLAS_RD_VA_CTRL *) M_CALLOC (MSMEM_GEN, num_var, + sizeof(MVLAS_RD_VA_CTRL)); + vaCtrl = rdCtrl->vaCtrlTbl; + rdCtrl->numVar = num_var; + + /* Prepare to process each variable in the list */ + vl = (VARIABLE_LIST *) (read_info + 1); + for (i = 0; i < num_var; ++i, ++vl, ++vaCtrl) + { + ST_BOOLEAN alt_access_done = SD_FALSE; /* chg if AA processed */ + + /* These are done by the 'chk_calloc' call */ + /* vaCtrl->va = NULL; */ + /* vaCtrl->alt_access_pres = SD_FALSE; */ + vaCtrl->acc_rslt_tag = ACC_RSLT_SUCCESS; + + + alt_access_pres = vl->alt_access_pres; + if (alt_access_pres) /* no alternate access support now */ + { +#if !defined(MVL_AA_SUPP) + MVL_LOG_NERR0 ("Read Indication : Alternate Access not supported"); + continue; +#else + /* now create the AA, given the ASN.1 spec */ + if (ms_asn1_to_aa (vl->alt_access.data, vl->alt_access.len, + &vaCtrl->alt_acc)) + { + MVL_LOG_NERR0 ("Read Indication : ASN.1 -> AA failure"); + continue; + } + vaCtrl->alt_access_pres = SD_TRUE; +#endif + } + + switch (vl->var_spec.var_spec_tag) + { + case VA_SPEC_NAMED : + vaCtrl->va = _mvl_objname_to_va (&mvl_vmd, indCtrl->event->net_info, MMSOP_READ, &vl->var_spec.vs.name, + &vaCtrl->va_scope, + alt_access_pres, + &vaCtrl->alt_acc, + &alt_access_done); + if (!vaCtrl->va) + { + MVL_LOG_NERR1 ("Read ind : Variable Association '%s' not found", + vl->var_spec.vs.name.obj_name.vmd_spec); + } + break; + + case VA_SPEC_ADDRESSED: + case VA_SPEC_DESCRIBED: + case VA_SPEC_SCATTERED: + case VA_SPEC_INVALIDATED: + default : + MVL_LOG_NERR1 ("Read: Unsupported MMS VariableSpecification Tag %d", vl->var_spec.var_spec_tag); + /* NOTE: "vaCtrl->va = NULL" already. That's GOOD. */ + break; + } + + if (vaCtrl->va) + vaCtrl->va->usr_ind_ctrl = indCtrl->usr_ind_ctrl; /* save optional user pointer in va*/ + + /* If alt_acc allocated, free it now if done with it, or if va not found.*/ + if (alt_access_pres && (alt_access_done || vaCtrl->va==NULL)) + { + M_FREE (MSMEM_GEN, vaCtrl->alt_acc.aa); + vaCtrl->alt_access_pres = SD_FALSE; + } + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/* prep_nvl_rd_ctrl */ +/************************************************************************/ + +static ST_RET prep_nvl_rd_ctrl (MVL_IND_PEND *indCtrl, MVL_NET_INFO *net_info, READ_REQ_INFO *read_info, + MVLAS_READ_CTRL *rdCtrl) + { +MVL_NVLIST_CTRL *nvList; +MVLAS_RD_VA_CTRL *vaCtrl; +ST_INT i; +ST_INT num_var; + +/* search for the NVL */ +#if defined(USE_MANUFACTURED_OBJS) + nvList = u_mvl_get_nvl (MMSOP_READ, &read_info->va_spec.vl_name, + net_info); +#else /* default */ + nvList = mvl_vmd_find_nvl (&mvl_vmd, &read_info->va_spec.vl_name, indCtrl->event->net_info); +#endif /* default */ + + if (!nvList) + { + MVL_LOG_NERR0 ("Read NVL : NamedVariableList not found"); + return (MVL_ERR_NVL_NOT_FOUND); + } + rdCtrl->nvList = nvList; + +/* Found the named variable list, create the response */ + num_var = nvList->num_of_entries; + rdCtrl->vaCtrlTbl = (MVLAS_RD_VA_CTRL *) M_CALLOC (MSMEM_GEN, num_var, + sizeof(MVLAS_RD_VA_CTRL)); + vaCtrl = rdCtrl->vaCtrlTbl; + rdCtrl->numVar = num_var; + + for (i = 0; i < num_var; ++i, ++vaCtrl) + { + /* These are done by the 'chk_calloc' call */ + /* vaCtrl->va = NULL; */ + /* vaCtrl->alt_access_pres = NULL; */ + vaCtrl->va = nvList->entries[i]; + memcpy (&vaCtrl->va_scope, &nvList->va_scope[i], sizeof(MVL_SCOPE)); + vaCtrl->acc_rslt_tag = ACC_RSLT_SUCCESS; + vaCtrl->va->usr_ind_ctrl = indCtrl->usr_ind_ctrl; /* save optional user pointer in va*/ + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* mvlas_read_resp */ +/************************************************************************/ + +ST_RET mvlas_read_resp (MVL_IND_PEND *indCtrl) + { +MVLAS_READ_CTRL *rdCtrl; +MVL_COMM_EVENT *event; +MVL_NET_INFO *net_info; +READ_RESP_INFO *resp_info; +ST_UCHAR *asn1_buf; +ST_RET rc; +READ_REQ_INFO *req_info = (READ_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + event = indCtrl->event; + net_info = indCtrl->event->net_info; + rdCtrl = &indCtrl->u.rd; + + asn1_buf = (ST_UCHAR *) M_MALLOC (MSMEM_ASN1_DATA_ENC, mvl_cfg_info->max_msg_size); + rc = prep_read_resp (net_info, rdCtrl, req_info, &resp_info, asn1_buf, mvl_cfg_info->max_msg_size); + + if (rc == SD_SUCCESS) + { + /* Build the read response */ + rc = mpl_read_resp (event->u.mms.dec_rslt.id, resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, resp_info); + + /* The process functions allocate the response buffer */ + M_FREE (MSMEM_ENC_OS_INFO, resp_info); + } + +#if defined(USE_MANUFACTURED_OBJS) + if (rdCtrl->nvList) /* For NVL, this was allocated by prep_nvl_... */ + u_mvl_free_nvl (MMSOP_READ, rdCtrl->nvList, event->net_info); +#endif + + if (u_mvl_rd_resp_sent) + (*u_mvl_rd_resp_sent) (indCtrl); + + M_FREE (MSMEM_ASN1_DATA_ENC, asn1_buf); + M_FREE (MSMEM_GEN, rdCtrl->vaCtrlTbl); + + /* NOTE: This funct frees indCtrl. DO NOT use after this. */ + /* NOTE: if rc != SD_SUCCESS, this funct sends error resp. */ + _mvl_send_resp_i (indCtrl, rc); + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* prep_read_resp */ +/************************************************************************/ + +static ST_RET prep_read_resp (MVL_NET_INFO *net_info, MVLAS_READ_CTRL *rdCtrl, + READ_REQ_INFO *req_info, + READ_RESP_INFO **resp_info_out, + ST_UCHAR *asn1_buf, ST_INT asn1_buf_size) + { +MVLAS_RD_VA_CTRL *vaCtrl; +MVL_VAR_ASSOC *va; +READ_RESP_INFO *resp_info; +ACCESS_RESULT *ar_ptr; +ST_UCHAR *asn1_start; +ST_INT asn1_len; +ST_INT asn1_buf_left; +ST_INT num_var; +ST_INT i; + + num_var = rdCtrl->numVar; + + /* Allocate READ_RESP_INFO struct plus space for variableAccessSpec */ + /* (only used if spec_in_result=TRUE) and accessResults. */ + resp_info = + (READ_RESP_INFO *) M_CALLOC (MSMEM_ENC_OS_INFO, 1, sizeof (READ_RESP_INFO) + + (num_var * sizeof (VARIABLE_LIST)) + /* for variableAccessSpec*/ + (num_var * sizeof (ACCESS_RESULT))); + *resp_info_out = resp_info; + + if (req_info->spec_in_result) + { /* Send variableAccessSpec in response */ + resp_info->va_spec_pres = SD_TRUE; + resp_info->va_spec.var_acc_tag = req_info->va_spec.var_acc_tag; + if (resp_info->va_spec.var_acc_tag == VAR_ACC_VARLIST) + { /* list of variables */ + /* Copy variableAccessSpec (array of VARIABLE_LIST) from req to resp.*/ + resp_info->va_spec.num_of_variables = num_var; + memcpy ((resp_info + 1), (req_info + 1), num_var * sizeof (VARIABLE_LIST)); + } + else + { /* variable list name : copy name from req to resp. */ + memcpy (&resp_info->va_spec.vl_name, &req_info->va_spec.vl_name, sizeof (OBJECT_NAME)); + } + } + else + { /* Do NOT send variableAccessSpec in response. */ + resp_info->va_spec_pres = SD_FALSE; + } + + resp_info->num_of_acc_result = num_var; + /* Calculate pointer to start of accessResults (after variableAccessSpec)*/ + resp_info->acc_rslt_list = (ACCESS_RESULT *) + ((((VARIABLE_LIST *)(resp_info+1)) + num_var)); + + ar_ptr = resp_info->acc_rslt_list; + asn1_start = asn1_buf; + asn1_buf_left = asn1_buf_size; + vaCtrl = rdCtrl->vaCtrlTbl; + for (i = 0; i < num_var; ++i, ++ar_ptr, ++vaCtrl) + { + va = vaCtrl->va; + if (va == NULL) + { + ar_ptr->acc_rslt_tag = ACC_RSLT_FAILURE; + ar_ptr->failure = ARE_OBJ_NONEXISTENT; + } + else + { +/* Copy values from vaCtrl, but may change due to other errors. */ + ar_ptr->acc_rslt_tag = vaCtrl->acc_rslt_tag; + ar_ptr->failure = vaCtrl->failure; + if (ar_ptr->acc_rslt_tag == ACC_RSLT_SUCCESS) + { /* may still fail other checks */ +/* Sanity check, because foundry can generate configured variables w/o */ +/* the data pointer initialized. */ + if (va->data == NULL) + { /* Error. Override values set before */ + MVL_LOG_NERR1 ("Read Indication : va '%s' data is NULL", va->name); + ar_ptr->acc_rslt_tag = ACC_RSLT_FAILURE; + ar_ptr->failure = ARE_OBJ_INVALIDATED; + } + else if (mvl_get_va_asn1_data (net_info, + va, vaCtrl->alt_access_pres, &vaCtrl->alt_acc, + asn1_start, asn1_buf_left, &asn1_len) != SD_SUCCESS) + { /* Error. Override values set before */ + ar_ptr->acc_rslt_tag = ACC_RSLT_FAILURE; + ar_ptr->failure = ARE_OBJ_ACC_UNSUPPORTED; + } + else + { /* this is the only path to success */ + ar_ptr->va_data.len = asn1_len; + ar_ptr->va_data.data = asn1_start; + + asn1_buf_left -= asn1_len; /* adjust buffer control variables */ + asn1_start += asn1_len; + } + } + } + + /* IMPORTANT: Use ar_ptr->acc_rslt_tag here (not vaCtrl->acc_rslt_tag).*/ + if (ar_ptr->acc_rslt_tag == ACC_RSLT_SUCCESS) + ++mvl_mms_statistics.serverVarRdOk; + else + ++mvl_mms_statistics.serverVarRdErr; + + /* The user needs to free a manufactured NVL and the associated VA's */ + /* in the 'u_mvl_free_va_fun'; here just free manufactured variables */ + /* associated with a list of variables. */ +#if defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS) + if (rdCtrl->var_acc_tag == VAR_ACC_VARLIST) + { + if (va && va->va_to_free != NULL) + u_mvl_free_va (MMSOP_READ, va, net_info); + } +#endif /* defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS) */ + +#if defined(MVL_AA_SUPP) + if (vaCtrl->alt_access_pres) /* if we calloc'd this AA, free it */ + M_FREE (MSMEM_GEN, vaCtrl->alt_acc.aa); +#endif + } /* end loop */ + + return (SD_SUCCESS); + } diff --git a/mmslib/mvlu/s_status.c b/mmslib/mvlu/s_status.c new file mode 100644 index 0000000..8ad759c --- /dev/null +++ b/mmslib/mvlu/s_status.c @@ -0,0 +1,67 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : s_status.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/09/07 MDE 11 Enhanced filtered logging */ +/* 03/11/04 GLB 10 Remove "thisFileName" */ +/* 09/21/01 JRB 09 Alloc global bufs only once at startup. */ +/* 01/21/00 MDE 08 Now use MEM_SMEM for dynamic memory */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 04/01/99 MDE 06 Changes to decode buffer allocation scheme */ +/* 11/16/98 MDE 05 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 04 Minor lint cleanup */ +/* 06/15/98 MDE 03 Changes to allow compile under C++ */ +/* 05/14/98 JRB 02 Use MVL_IND_PEND. Add mplas resp function. */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pvmd.h" +#include "mvl_defs.h" +#include "mvl_log.h" + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_status_ind */ +/* A "status" indication has been received, process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_status_ind (MVL_IND_PEND *indCtrl) + { + indCtrl->u.status.req_info = + (STATUS_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + + u_mvl_status_ind (indCtrl); + } + +/************************************************************************/ +/* mplas_status_resp */ +/************************************************************************/ +ST_VOID mplas_status_resp (MVL_IND_PEND *indCtrl) + { +ST_RET rc; + +/* Build an status response */ + rc = mpl_status_resp (indCtrl->event->u.mms.dec_rslt.id, + indCtrl->u.status.resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, indCtrl->u.status.resp_info); + + _mvl_send_resp_i (indCtrl, rc); + } + diff --git a/mmslib/mvlu/s_write.c b/mmslib/mvlu/s_write.c new file mode 100644 index 0000000..032876f --- /dev/null +++ b/mmslib/mvlu/s_write.c @@ -0,0 +1,438 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 1996, All Rights Reserved */ +/* */ +/* MODULE NAME : s_write.c */ +/* PRODUCT(S) : MMSEASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* NONE */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/02/09 JRB 32 Chk va_to_free before ...free_va. */ +/* 01/23/09 MDE 31 Use 0x%X for hex values in log msgs. */ +/* 01/13/09 MDE 30 Free VA (and temp type) in case of errors */ +/* 05/01/08 JRB 29 Chk ms_asn1_to_local return & set */ +/* WRITE_RESULT "failure" appropriately. */ +/* 04/09/07 MDE 28 Enhanced filtered logging */ +/* 10/30/06 JRB 27 Use new mvl_vmd_* object handling functions. */ +/* Add args on call to _mvl_objname_to_va. */ +/* Elim use of global "_mvl_curr_net_info". */ +/* Elim use of global "_mvl_curr_usr_ind_ctrl". */ +/* 08/09/06 JRB 26 ALWAYS set resp_tag & failure in wr_rslt */ +/* same as in vaCtrl. In put_asn1_data, set */ +/* vaCtrl->failure to appropriate value. */ +/* 01/30/06 GLB 25 Integrated porting changes for VMS */ +/* 05/16/05 JRB 24 Send appropriate failure codes in write resp.*/ +/* Move statistics code so it is always executed*/ +/* 03/13/03 JRB 23 Use mvl_type_ctrl_find. */ +/* 07/24/02 JRB 22 Use mvl_send_resp_i like ALL responses. */ +/* 07/09/02 MDE 21 Add maxpend_ind support */ +/* 09/21/01 JRB 20 Alloc global bufs only once at startup. */ +/* 05/25/01 MDE 19 Moved where the old data is saved */ +/* 03/30/01 MDE 18 Changed MSMEM_ENC_INFO to MSMEM_ENC_OS_INFO */ +/* 10/25/00 JRB 17 Del u_mvl funct ptrs. Call functs directly. */ +/* Control with #ifdefs. */ +/* 10/06/00 MDE 16 Now restore old data for write failure */ +/* 05/15/00 MDE 15 Added MMS statistics */ +/* 01/21/00 MDE 14 Now use MEM_SMEM for dynamic memory */ +/* 11/22/99 JRB 13 mvlas_write_resp: del indCtrl from link list */ +/* 09/13/99 MDE 12 Added SD_CONST modifiers */ +/* 04/07/99 MDE 11 Logging improvements */ +/* 12/11/98 MDE 10 Removed scope references from VA */ +/* 12/08/98 MDE 09 Fixed write handling for alternate access */ +/* 11/16/98 MDE 08 Renamed internal functions (prefix '_') */ +/* 09/21/98 MDE 07 Minor lint cleanup */ +/* 06/15/98 MDE 06 Changes to allow compile under C++ */ +/* 05/15/98 JRB 05 Chg mvl_process.. arg to (MVL_IND_PEND *). */ +/* 05/15/98 JRB 04 Call u_mvl_write_ind direct (no funct ptr). */ +/* 02/20/98 MDE 03 Fixed usrVa set problem */ +/* 02/10/98 MDE 02 Removed NEST_RT_TYPES, always support AA, */ +/* added 'u_mvl_wr_ind_start' and */ +/* 'u_mvl_wr_resp_sent', other */ +/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mmsdefs.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "mvl_defs.h" +#include "mvl_log.h" + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ + +ST_RET (*u_mvl_wr_ind_start) (MVL_IND_PEND *indCtrl); +ST_VOID (*u_mvl_wr_resp_sent) (MVL_IND_PEND *indCtrl); + +/************************************************************************/ +/* Internal functions */ + +static ST_VOID put_asn1_data (MVL_IND_PEND *indCtrl, VARIABLE_LIST *vl, + ST_UCHAR *asn1_buffer, ST_INT asn1_len, + MVLAS_WR_VA_CTRL *vaCtrl); + +/************************************************************************/ +/************************************************************************/ +/* _mvl_process_write_ind */ +/* A write indication has been received, process it and respond */ +/************************************************************************/ + +ST_VOID _mvl_process_write_ind (MVL_IND_PEND *indCtrl) + { +MVLAS_WRITE_CTRL *wrCtrl; +MVLAS_WR_VA_CTRL *vaCtrl; +WRITE_REQ_INFO *write_info; +ST_INT num_var; +VARIABLE_LIST *vl_ptr; +VAR_ACC_DATA *va_ptr; +ST_INT i; +ST_RET rc; + + write_info = (WRITE_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr; + num_var = write_info->va_spec.num_of_variables; + + /* verify that this is a list of variables */ + if (write_info->va_spec.var_acc_tag != VAR_ACC_VARLIST) + { + _mplas_err_resp (indCtrl,7,2); /* access, non-existent */ + return; + } + + if (u_mvl_wr_ind_start) + { + /* This might set optional user pointer "indCtrl->usr_ind_ctrl". */ + rc = (*u_mvl_wr_ind_start) (indCtrl); + if (rc != SD_SUCCESS) + { + _mplas_err_resp (indCtrl,7,2); /* access, non-existent */ + return; + } + } + + wrCtrl = &indCtrl->u.wr; + wrCtrl->vaCtrlTbl = (MVLAS_WR_VA_CTRL *) M_CALLOC (MSMEM_GEN, num_var, + sizeof(MVLAS_WR_VA_CTRL)); + vaCtrl = wrCtrl->vaCtrlTbl; + wrCtrl->numVar = num_var; + +/* Looks OK, prepare to process each variable in the list */ + vl_ptr = (VARIABLE_LIST *) (write_info+1); + va_ptr = write_info->va_data; + + for (i = 0; i < num_var; ++i, ++vl_ptr, ++va_ptr, ++vaCtrl) + put_asn1_data (indCtrl, vl_ptr, va_ptr->data, va_ptr->len, vaCtrl); + + u_mvl_write_ind (indCtrl); + } + + +/************************************************************************/ +/* mvlas_write_resp */ +/************************************************************************/ + +ST_VOID mvlas_write_resp (MVL_IND_PEND *indCtrl) + { +MVLAS_WRITE_CTRL *wrCtrl; +MVLAS_WR_VA_CTRL *vaCtrl; +MVL_COMM_EVENT *event; +MVL_NET_INFO *net_info; +ST_RET rc; +ST_CHAR *resp_buf; +ST_INT num_var; +ST_INT va_data_size; +WRITE_RESP_INFO *resp_info; +WRITE_RESULT *wr_rslt; +ST_INT i; +MVL_TYPE_CTRL *type_ctrl; + + net_info = indCtrl->event->net_info; + event = indCtrl->event; + wrCtrl = &indCtrl->u.wr; + vaCtrl = wrCtrl->vaCtrlTbl; + num_var = wrCtrl->numVar; + + resp_buf = (ST_CHAR *) M_CALLOC (MSMEM_ENC_OS_INFO, 1, sizeof(WRITE_RESP_INFO) + + (num_var * sizeof (WRITE_RESULT))); + + /* Create a write response info struct */ + resp_info = (WRITE_RESP_INFO *) resp_buf; + resp_info->num_of_result = num_var; + wr_rslt = (WRITE_RESULT *) (resp_info +1); + + for (i = 0; i < num_var; ++i, ++wr_rslt, ++vaCtrl) + { + wr_rslt->resp_tag = vaCtrl->resp_tag; + wr_rslt->failure = vaCtrl->failure; + if (vaCtrl->va != NULL) + { + if (wr_rslt->resp_tag == WR_RSLT_FAILURE) + { /* On a failure, restore the previous data */ + type_ctrl = mvl_type_ctrl_find (vaCtrl->va->type_id); + va_data_size = type_ctrl->data_size; + memcpy (vaCtrl->va->data, vaCtrl->oldData, va_data_size); + } + M_FREE (MSMEM_GEN, vaCtrl->oldData); +#if defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS) + if (vaCtrl->va->va_to_free != NULL) + u_mvl_free_va (MMSOP_WRITE, vaCtrl->va, event->net_info); +#endif /* defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS) */ + } + + if (wr_rslt->resp_tag == WR_RSLT_SUCCESS) + ++mvl_mms_statistics.serverVarWrOk; + else + ++mvl_mms_statistics.serverVarWrErr; + } /* end loop */ + +/* Build a write response */ + rc = mpl_write_resp (event->u.mms.dec_rslt.id, resp_info); + if (rc == SD_SUCCESS) + mpl_resp_log (indCtrl, resp_info); + + if (u_mvl_wr_resp_sent) + (*u_mvl_wr_resp_sent) (indCtrl); + + M_FREE (MSMEM_ENC_OS_INFO, resp_buf); + M_FREE (MSMEM_GEN, wrCtrl->vaCtrlTbl); + + /* NOTE: This funct frees indCtrl. DO NOT use after this. */ + /* NOTE: if rc != SD_SUCCESS, this funct sends error resp. */ + _mvl_send_resp_i (indCtrl, rc); + } + + +/************************************************************************/ +/* put_asn1_data */ +/* This function is to provide ASN.1 encoded data, given the variable */ +/* list element. */ +/************************************************************************/ + +static ST_VOID put_asn1_data (MVL_IND_PEND *indCtrl, VARIABLE_LIST *vl, + ST_UCHAR *asn1_buffer, ST_INT asn1_len, + MVLAS_WR_VA_CTRL *vaCtrl) + { +MVL_VAR_ASSOC *va; +RUNTIME_TYPE *rt; +ST_INT num_rt; +ST_RET rc; +ST_CHAR *temp_data_buf; +ST_CHAR *va_data; +ST_INT va_data_size; +ST_INT aa_mode; +ALT_ACCESS alt_acc; /* Alternate Access specification */ +ST_BOOLEAN alt_access_pres; +ST_BOOLEAN alt_access_done; +MVL_TYPE_CTRL *type_ctrl; + +/* There are more ways to fail than to succeed! */ +/* Assume failure=ARE_TYPE_INCONSISTENT, but may be changed in some cases.*/ + vaCtrl->resp_tag = WR_RSLT_FAILURE; + vaCtrl->failure = ARE_TYPE_INCONSISTENT; + + alt_access_pres = vl->alt_access_pres; + if (alt_access_pres) /* no alternate access support now */ + { +#if !defined(MVL_AA_SUPP) + MVL_LOG_NERR0 ("Put ASN1 Data : Alternate Access not supported"); + return; +#else + /* now create the AA, given the ASN.1 spec */ + if (ms_asn1_to_aa (vl->alt_access.data, vl->alt_access.len, + &alt_acc)) + { + MVL_LOG_NERR0 ("Write Indication : ASN.1 -> AA failure"); + return; + } +#endif + } + + switch (vl->var_spec.var_spec_tag) + { + case VA_SPEC_NAMED : + va = _mvl_objname_to_va (&mvl_vmd, indCtrl->event->net_info, MMSOP_WRITE, &vl->var_spec.vs.name, + &vaCtrl->va_scope, + alt_access_pres, + &alt_acc, + &alt_access_done); + + if (alt_access_pres && alt_access_done) + { + M_FREE (MSMEM_GEN, alt_acc.aa); + alt_access_pres = SD_FALSE; + } + + if (!va) /* could not find variable association */ + { + MVL_LOG_NERR1 ("Write ind : Variable Association '%s' not found", + vl->var_spec.vs.name.obj_name.vmd_spec); + vaCtrl->failure = ARE_OBJ_NONEXISTENT; + return; + } + + vaCtrl->va = va; + va->usr_ind_ctrl = indCtrl->usr_ind_ctrl; /* save optional user pointer in va*/ + + /* Save the current data in case the user rejects the write */ + + type_ctrl = mvl_type_ctrl_find (va->type_id); /* find type */ + va_data_size = type_ctrl->data_size; + vaCtrl->oldData = (ST_UCHAR *) M_MALLOC (MSMEM_GEN, va_data_size); + memcpy (vaCtrl->oldData, va->data, va_data_size); + + /* We have obtained a variable association */ + /* Now do the alternate access preprocess function if appropriate */ + +#if defined(MVL_AA_SUPP) + aa_mode = MVL_USE_UNPACKED_AA; + if (alt_access_pres && va->proc && va->proc->proc_write_aa) + { + rc = (*va->proc->proc_write_aa)(&va, &alt_acc, + indCtrl->event->net_info, &aa_mode); + + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Write : proc_write_aa returned %d", rc); + return; + } + } +#endif + + + /* Now take care of the data conversion (asn1 to local) */ + rc = mvl_get_runtime (va->type_id, &rt, &num_rt); + if (rc != SD_SUCCESS) + { + M_FREE (MSMEM_GEN, vaCtrl->oldData); + MVL_LOG_NERR1 ("Could not get type_id %d", va->type_id); + vaCtrl->va = NULL; + return; + } + + /* Sanity check, because foundry can generate configured vars w/o */ + /* the data pointer initialized. */ + if (va->data == NULL) + { + M_FREE (MSMEM_GEN, vaCtrl->oldData); + MVL_LOG_NERR1 ("Write Indication : va '%s' data is NULL", va->name); + vaCtrl->va = NULL; + return; + } + + va_data = (ST_CHAR *) va->data; + /* "va_data_size" already set above */ + break; + + case VA_SPEC_DESCRIBED : + default : + MVL_LOG_NERR0 ("Put ASN1 Data : Invalid Variable Specification Tag"); + vaCtrl->failure = ARE_OBJ_ACC_UNSUPPORTED; + return; + break; + } + +/* If we got here, we have a valid runtime and have resolved local */ +/* data pointer and size. Go ahead and convert the ASN.1 data element to*/ +/* local data format */ + + temp_data_buf = (ST_CHAR *) M_MALLOC (MSMEM_WR_DATA_DEC_BUF, va_data_size); + + +#if defined(MVL_AA_SUPP) + if (alt_access_pres == SD_FALSE || aa_mode == MVL_USE_NO_AA) + rc = ms_asn1_to_local (rt, num_rt, asn1_buffer, asn1_len, temp_data_buf); + else + { + /* This is an alternate access write, we must first copy the data */ + /* contents to to the temp buffer, then only the selected elements */ + /* will be written by the data conversion. */ + memcpy (temp_data_buf, va_data, va_data_size); + + if (aa_mode == MVL_USE_PACKED_AA) + m_alt_acc_packed = SD_TRUE; + else + m_alt_acc_packed = SD_FALSE; + + rc = ms_asn1_to_local_aa (rt, num_rt, &alt_acc, + asn1_buffer, asn1_len, temp_data_buf); + } +#else + rc = ms_asn1_to_local (rt, num_rt, asn1_buffer, asn1_len, temp_data_buf); +#endif + + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Put ASN1 Data : ms_asn1_to_local failed, rc = 0x%X", rc); + M_FREE (MSMEM_GEN, vaCtrl->oldData); + M_FREE (MSMEM_WR_DATA_DEC_BUF, temp_data_buf); + +#if defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS) + /* Need to free VA (caller will not if vaCtrl->va == NULL) */ + if (vaCtrl->va->va_to_free != NULL) + u_mvl_free_va (MMSOP_WRITE, vaCtrl->va, NULL); +#endif + vaCtrl->va = NULL; + if (rc == ASN1E_UNEXPECTED_TAG) + /* Tag mismatch in this context indicates MMS type mismatch. */ + vaCtrl->failure = ARE_TYPE_INCONSISTENT; + else + vaCtrl->failure = ARE_OBJ_VALUE_INVALID; + return; + } + + /* Call the preprocessing function for this variable, if it exists */ + if (va->proc && va->proc->pre_write_aa) + { + rc = (*va->proc->pre_write_aa)(va, alt_access_pres, &alt_acc, + indCtrl->event->net_info, + temp_data_buf, va_data_size); + + if (rc != SD_SUCCESS) + { + MVL_LOG_NERR1 ("Put ASN1 Data : call to Write pre-processor failed, rc = 0x%X", rc); + M_FREE (MSMEM_GEN, vaCtrl->oldData); +#if defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS) + /* Need to free VA (caller will not if vaCtrl->va == NULL) */ + if (vaCtrl->va->va_to_free != NULL) + u_mvl_free_va (MMSOP_WRITE, vaCtrl->va, NULL); +#endif + vaCtrl->va = NULL; + } + } + +/* OK, almost done. The data has been converted OK and the user has had */ +/* a chance to look at it. If rc == SD_SUCCESS, we are OK. */ + + if (rc == SD_SUCCESS) + { + vaCtrl->resp_tag = WR_RSLT_SUCCESS; + memcpy (va_data, temp_data_buf, va_data_size); + + /* Call the postprocessing function for this variable, if it exists */ + if (va->proc && va->proc->post_write_aa) + (*va->proc->post_write_aa)(va, alt_access_pres, &alt_acc, indCtrl->event->net_info); + } + +#if defined(MVL_AA_SUPP) + if (alt_access_pres) /* if we calloc'd this AA, free it */ + M_FREE (MSMEM_GEN, alt_acc.aa); +#endif + M_FREE (MSMEM_WR_DATA_DEC_BUF, temp_data_buf); + } diff --git a/mmslib/mvlu/sclproc.c b/mmslib/mvlu/sclproc.c new file mode 100644 index 0000000..69f04e4 --- /dev/null +++ b/mmslib/mvlu/sclproc.c @@ -0,0 +1,3286 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2004-2006 All Rights Reserved */ +/* */ +/* MODULE NAME : sclproc.c */ +/* PRODUCT(S) : MMS-EASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Functions to "post-proccess" information parsed from SCL file. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* scl2_datatype_create_all */ +/* scl2_ld_create_all */ +/* */ +/* NOTE: FC must be "ST" "MX" "CO" "SP" "SG" "SE" "SV" "CF" "DC" or "EX"*/ +/* */ +/* NOTE: scl2_datatype_create_all allocates an array of RESERVED_INFO */ +/* structures to save extra SCL data for each datatype created. */ +/* The array pointer is saved in the reserved_1 member of */ +/* RUNTIME_CTRL, to be used later by scl2_ld_create_all, */ +/* which then frees it (see reserved_free_all). */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/30/08 JRB 47 Init DstAddress in GSSE control block. */ +/* 05/14/08 JRB 46 rtadd_da_or_bda: save init Val for Enum too. */ +/* Move FLOW log inside "if" for BasicType. */ +/* 04/23/08 JRB 45 If SGCB configured, add it to "SP". */ +/* Eliminate warnings. */ +/* 04/20/08 JRB 44 Add DstAddress to GSSE control block. */ +/* 03/03/08 JRB 43 Use new mvl_var_add_alloc (avoids extra alloc)*/ +/* 02/25/08 JRB 42 Add ObjRef type and map to VisString129. */ +/* Add INT64, INT64U types. */ +/* 02/25/08 JRB 41 For bType=Enum, convert Val text as a number */ +/* ONLY if text does not match any EnumVal. */ +/* 12/20/07 JRB 40 Add rcb_name_no_index flag. */ +/* 12/13/07 JRB 39 Allow nested SDO (needed for Wind Power). */ +/* scl_gse_find: match "cbName" also. */ +/* 10/29/07 JRB 38 strncat_safe obsolete, use strncat_maxstrlen.*/ +/* 09/05/07 JRB 37 Chg "Check" (PACKED LIST) to bvstring. */ +/* 08/13/07 MDE 36 Added more scl_debug_mode */ +/* 08/10/07 JRB 35 scl2_dai_set_value: if no "Val", do nothing. */ +/* 08/02/07 JRB 34 scl2_datatype_create: use new ms_rt_bld* */ +/* features to avoid realloc. */ +/* 07/03/07 JRB 33 Init DstAddress struct in MVL61850_GCB_DATA. */ +/* Add scl_gse_find. */ +/* 05/10/07 JRB 32 Reallocate reserved_1 smaller to save mem. */ +/* 03/06/07 JRB 31 Fix LogRef initial value (ObjectReference). */ +/* 02/13/07 JRB 30 Use RptEnabled max attribute for BRCB too. */ +/* Save rpt scan rate in rpt_ctrl->scan_rate. */ +/* 10/30/06 JRB 29 scl2_datatype_create_all: all args changed. */ +/* scl2_ld_create_all: add vmd_ctrl, is_client args.*/ +/* Use element of or to init */ +/* all variables containing the attribute. */ +/* Instead of creating TDL, create RUNTIME_TYPE */ +/* array directly (allows saving extra type info).*/ +/* Don't need type names anymore. Only use names*/ +/* if caller requests it. */ +/* Allow bType="Check", "VisString???". */ +/* 08/21/06 MDE 28 Added more scl_debug_mode */ +/* 08/09/06 JRB 27 Create multiple RCBs for each URCB configured.*/ +/* Add 01, 02, etc suffixes to all RCB names. */ +/* Allow scl_rcb->datSet="" (i.e. datSet not */ +/* present in ReportControl element of SCL file).*/ +/* Allow datSet write with mvl61850_datset_wr_ind.*/ +/* Chg DatSet in BRCB, URCB, GCB, LCB, MSVCB, */ +/* and USVCB to Vstring129. */ +/* Chg LogRef in LCB to Vstring129. */ +/* Del mvlu_rpt_create_scan_ctrl2 call */ +/* (new mvl61850_rpt_service automatically scans).*/ +/* 08/04/06 MDE 26 Tweaked logging */ +/* 08/04/06 MDE 25 Added scl_debug_mode, scl2_add_btype, etc. */ +/* 06/22/06 RKR 24 Added Vstring129 */ +/* 03/20/06 JRB 23 Add code for Sampled Value config (see svcb).*/ +/* Del unused scl_rcb_counters. */ +/* 12/14/05 JRB 22 Fix init val of DatSet in LCB or GCB */ +/* (must be ObjectReference). */ +/* 11/22/05 JRB 21 Fix spelling of "BufTm" in brcb, urcb. */ +/* (Only UCA uses the spelling "BufTim"). */ +/* 09/15/05 JRB 20 Fix spelling. */ +/* 07/27/05 JRB 19 Don't set OptFlds len=9 (default=10 is good).*/ +/* Don't set OptFlds bits bufovfl, entryID for URCB.*/ +/* 07/25/05 JRB 18 scl2_ld_create_all: Add brcb_bufsize arg. */ +/* 07/21/05 JRB 17 Set initial vals for LCB, GCB, SCB. */ +/* 07/11/05 JRB 16 scl2_ld_create_all: Call */ +/* mvl61850_ctl_lastapplerror_create. */ +/* 06/27/05 JRB 15 Use mvl_nvl_add (mvlu_rpt_nvl_add is obsolete).*/ +/* 05/27/05 JRB 14 Construct NVL name from LN & DataSet name */ +/* as 61850-8-1 requires. */ +/* 05/25/05 JRB 13 Del all code to generate RCB name & just use */ +/* name configured in SCL file (scl_rcb->name). */ +/* Add errflag so if one call to tdladd_string */ +/* fails, subsequent calls fail too. */ +/* 05/09/05 JRB 12 Chg leaf write functions for SqNum (in BRCB */ +/* & URCB) to u_no_write_allowed. */ +/* 04/05/05 MDE 11 Supress invalid log messages */ +/* 03/18/05 JRB 10 Use mvl_max_dyn when creating domains. */ +/* 02/15/05 JRB 09 Use new generated scl_ld->domName, not */ +/* scl_ld->inst as domain name. */ +/* Use new generated scl_fcda->domName, not */ +/* scl_fcda->ldInst as domain name. */ +/* Use new scl_ln->varName, generated once, */ +/* instead of generating ln_name repeatedly. */ +/* Compute max_num_var for mvl_dom_add call. */ +/* 01/19/05 JRB 08 Add scl2_dai_set_value_all & use it to init */ +/* data from DOI/SDI/DAI entries in SCL file. */ +/* Fix len on all strncat calls. */ +/* scl2_rcb_create_all: init ln_name just once. */ +/* Improve some logging. */ +/* 09/01/04 JRB 07 Map Octet64 to OVstring64 (to match 61850-8-1)*/ +/* 08/29/04 JRB 06 Chg Quality type back to BVstring13 because */ +/* final IEC-61850-8-1 changed back. */ +/* 08/19/04 JRB 05 Init return value in scl2_ld_create_all. */ +/* 07/19/04 JRB 04 Add tdladd_lg, tdladd_go_or_gs. */ +/* 07/14/04 JRB 03 Chg Quality type to BVstring14. */ +/* 07/09/04 JRB 02 scl2_ld_create_all: add reportScanRate arg */ +/* to this and lower level functions. */ +/* 07/02/04 JRB 01 Initial Revision. */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "scl.h" +#include "sx_log.h" +#include "mvl_defs.h" +#include "mvl_uca.h" +#include "mvl_log.h" +#include "str_util.h" /* for strn..._safe protos */ +#include "sx_arb.h" /* for sxaText.... proto */ + + +/*renxiaobao Êý¾ÝÓ³Éä*/ +DATA_MAP_LINK *DATA_MAP_saddr=0; +int BRCB_NUM = 0,URCB_NUM = 0; +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/* RESERVED_INFO: structure for extra type related info that is not */ +/* contained in RUNTIME_TYPE or RUNTIME_CTRL. Allocate array of these. */ +typedef struct + { + SCL_ENUMTYPE *scl_enumtype; /* SCL enumtype def for this type */ + ST_CHAR *Val; /* SCL initial value for this type */ + } RESERVED_INFO; + +/* CRITICAL: this struct must be compatible with RUNTIME_TYPE. */ +/* If either one changes, the other must change to match. */ +typedef struct + { + ST_UINT8 LogEna; /* Bool */ + ST_CHAR LogRef[MVL61850_MAX_OBJREF_LEN+1]; /* Vstring129 (ObjectReference) */ + ST_CHAR DatSet[MVL61850_MAX_OBJREF_LEN+1]; /* Vstring129 (ObjectReference) */ + MMS_BTIME6 OldEntrTim; /* Btime6 */ + MMS_BTIME6 NewEntrTim; /* Btime6 */ + ST_UINT8 OldEntr[8]; /* Ostring8 */ + ST_UINT8 NewEntr[8]; /* Ostring8 */ + MMS_BVSTRING TrgOps; /* BVstring6 - struct includes 1 byte data. Enough.*/ + ST_UINT32 IntgPd; /* Ulong */ + } MVL61850_LCB_DATA; /* struct to store data for LCB (IEC Log Control Block) */ + +/* CRITICAL: this struct must be compatible with RUNTIME_TYPE. */ +/* If either one changes, the other must change to match. */ +typedef struct + { + ST_BOOLEAN GoEna; + ST_CHAR GoID[66]; + ST_CHAR DatSet[MVL61850_MAX_OBJREF_LEN+1]; /* Vstring129 (ObjectReference)*/ + ST_UINT32 ConfRev; + ST_BOOLEAN NdsCom; + struct + { + ST_UCHAR Addr[6]; + ST_UINT8 PRIORITY; + ST_UINT16 VID; + ST_UINT16 APPID; + } DstAddress; + } MVL61850_GCB_DATA; /* struct to store data for GCB (GOOSE Control Block) */ + +/* CRITICAL: this struct must be compatible with RUNTIME_TYPE. */ +/* If either one changes, the other must change to match. */ +typedef struct + { + ST_BOOLEAN GsEna; + ST_CHAR GsID[66]; + ST_CHAR DNALabels[32][66]; + ST_CHAR UserSTLabels[128][66]; + struct + { + ST_CHAR GsID[66]; + MMS_BTIME6 t; + ST_UINT32 SqNum; + ST_UINT32 StNum; + ST_UINT32 TAL; + ST_UINT32 usec; + ST_UINT16 PhsID; + ST_UCHAR DNA[8]; + ST_UCHAR UserST[32]; + } LSentData; + struct + { + ST_UCHAR Addr[6]; + ST_UINT8 PRIORITY; + ST_UINT16 VID; + ST_UINT16 APPID; + } DstAddress; + } MVL61850_SCB_DATA; /* struct to store data for SCB (GSSE Control Block) */ + +typedef struct + { + ST_UINT8 SvEna; /* Bool */ + ST_CHAR MsvID[MVL61850_MAX_RPTID_LEN+1]; /* Vstring65 */ + ST_CHAR DatSet[MVL61850_MAX_OBJREF_LEN+1]; /* Vstring129 (ObjectReference) */ + ST_UINT32 ConfRev; /* Ulong */ + ST_UINT32 SmpRate; /* Ulong */ + MMS_BVSTRING OptFlds; /* BVstring3 - struct includes 1 byte data. Enough.*/ + } MVL61850_MSVCB_DATA; /* struct to store data for MSVCB */ + +typedef struct + { + ST_UINT8 SvEna; /* Bool */ + ST_UINT8 Resv; /* Bool */ + ST_CHAR UsvID[MVL61850_MAX_RPTID_LEN+1]; /* Vstring65 */ + ST_CHAR DatSet[MVL61850_MAX_OBJREF_LEN+1]; /* Vstring129 (ObjectReference) */ + ST_UINT32 ConfRev; /* Ulong */ + ST_UINT32 SmpRate; /* Ulong */ + MMS_BVSTRING OptFlds; /* BVstring3 - struct includes 1 byte data. Enough.*/ + } MVL61850_USVCB_DATA; /* struct to store data for USVCB */ + +/* CRITICAL: this struct must be compatible with RUNTIME_TYPE. */ +/* If either one changes, the other must change to match. */ +typedef struct + { + ST_UINT8 NumOfSG; + ST_UINT8 ActSG; + ST_UINT8 EditSG; + ST_BOOLEAN CnfEdit; + MMS_UTC_TIME LActTm; /* TimeStamp */ + } MVL61850_SGCB_DATA; /* struct to store data for SGCB (Setting Group Control Block) */ + +/************************************************************************/ +/* STATIC FUNCTION PROTOTYPES */ +/* Need prototypes for these static functions because rtadd_da_struct */ +/* calls rtadd_da_or_bda and vice versa. */ +/* Other static functions are just defined in the order they are needed */ +/* so prototypes are not needed. */ +/************************************************************************/ +static ST_RET rtadd_da_struct ( + RUNTIME_BUILD_CTXT *ctxt, + SCL_INFO *scl_info, + ST_CHAR *type_id, + ST_CHAR *comp_name); +static ST_RET rtadd_da_or_bda ( + RUNTIME_BUILD_CTXT *ctxt, + SCL_INFO *scl_info, + ST_CHAR *name, /* DA or BDA name */ + ST_CHAR *bType, /* DA or BDA bType */ + ST_CHAR *type, /* DA or BDA type */ + ST_UINT count, /* DA or BDA count */ + ST_CHAR *Val); /* DA or BDA Val */ + +/************************************************************************/ +/************************************************************************/ +ST_BOOLEAN scl_debug_mode; +ST_INT scl_debug_mode_error_count; +SCL2_BTYPE *scl2_btype_list; +/* NOTE: setting this flag changes the way RCB names generated. */ +ST_BOOLEAN rcb_name_no_index; /* change to SD_TRUE to skip RCB index */ + /* suffix when maxClient==1 */ + +/************************************************************************/ +/* Add a "custom" basic type to the RUNTIME_TYPE array. */ +/************************************************************************/ +static ST_RET ms_rt_bld_61850_add_custom_btype (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *btype, ST_CHAR *comp_name) + { +SCL2_BTYPE *sclBtype; + sclBtype = scl2_btype_list; + while (sclBtype != NULL) + { + if (!strcmp (sclBtype->btype, btype)) + { /* already checked that this is simple type, so just use ...rt_first*/ + return (ms_rt_bld_add_special (ctxt, comp_name, sclBtype->rt_ctrl->rt_first)); + } + sclBtype = list_get_next (scl2_btype_list, sclBtype); + } + SXLOG_ERR1 ("bType='%s' is not recognized", btype); + return (SD_FAILURE); + } +/************************************************************************/ +/* Add a basic type to the RUNTIME_TYPE array. */ +/************************************************************************/ +static ST_RET ms_rt_bld_61850_add_btype (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *btype, ST_CHAR *comp_name) + { + /* First check for any of the PredefinedBasicTypes. */ + if (strcmp (btype, "BOOLEAN") == 0) + return (ms_rt_bld_add_bool (ctxt, comp_name)); + if (strcmp (btype, "INT8") == 0) + return (ms_rt_bld_add_int (ctxt, comp_name, 1)); + if (strcmp (btype, "INT16") == 0) + return (ms_rt_bld_add_int (ctxt, comp_name, 2)); + if (strcmp (btype, "INT32") == 0) + return (ms_rt_bld_add_int (ctxt, comp_name, 4)); + if (strcmp (btype, "INT64") == 0) + { +#if defined(INT64_SUPPORT) + return (ms_rt_bld_add_int (ctxt, comp_name, 8)); +#else + SXLOG_ERR0 ("INT64 not supported on this platform"); + return (SD_FAILURE); +#endif + } + if (strcmp (btype, "INT8U") == 0) + return (ms_rt_bld_add_uint (ctxt, comp_name, 1)); + if (strcmp (btype, "INT16U") == 0) + return (ms_rt_bld_add_uint (ctxt, comp_name, 2)); + if (strcmp (btype, "INT32U") == 0) + return (ms_rt_bld_add_uint (ctxt, comp_name, 4)); + if (strcmp (btype, "INT64U") == 0) + { +#if defined(INT64_SUPPORT) + return (ms_rt_bld_add_uint (ctxt, comp_name, 8)); +#else + SXLOG_ERR0 ("INT64U not supported on this platform"); + return (SD_FAILURE); +#endif + } + if (strcmp (btype, "FLOAT32") == 0) + return (ms_rt_bld_add_float (ctxt, comp_name, 4)); + if (strcmp (btype, "FLOAT64") == 0) + return (ms_rt_bld_add_float (ctxt, comp_name, 8)); + if (strcmp (btype, "Dbpos") == 0 + || strcmp (btype, "Tcmd") == 0) + return (ms_rt_bld_add_bstring (ctxt, comp_name, 2)); /* 2 bits*/ + /* "Check" is PACKED LIST. Maps to BVstring. */ + if (strcmp (btype, "Check") == 0) + return (ms_rt_bld_add_bvstring (ctxt, comp_name, 2)); /* max 2 bits*/ + if (strcmp (btype, "Quality") == 0) + return (ms_rt_bld_add_bvstring (ctxt, comp_name, 13)); /* max 13 bits*/ + if (strcmp (btype, "Timestamp") == 0) + return (ms_rt_bld_add_utctime (ctxt, comp_name)); + if (strcmp (btype, "VisString32") == 0) + return (ms_rt_bld_add_vstring (ctxt, comp_name, 32)); /* max 32 char*/ + if (strcmp (btype, "VisString64") == 0) + return (ms_rt_bld_add_vstring (ctxt, comp_name, 64)); /* max 64 char*/ + if (strcmp (btype, "VisString65") == 0) + return (ms_rt_bld_add_vstring (ctxt, comp_name, 65)); /* max 65 char*/ + if (strcmp (btype, "VisString128") == 0) + return (ms_rt_bld_add_vstring (ctxt, comp_name, 128)); /* max 128 char*/ + if (strcmp (btype, "VisString129") == 0) + return (ms_rt_bld_add_vstring (ctxt, comp_name, 129)); /* max 129 char*/ + if (strcmp (btype, "ObjRef") == 0) + return (ms_rt_bld_add_vstring (ctxt, comp_name, 129)); /* max 129 char*/ + if (strcmp (btype, "VisString255") == 0) + return (ms_rt_bld_add_vstring (ctxt, comp_name, 255)); /* max 255 char*/ + if (strcmp (btype, "Octet64") == 0) + /* 61850-8-1 says all octet strings are variable length*/ + return (ms_rt_bld_add_ovstring (ctxt, comp_name, 64)); /* max 64 bytes*/ + if (strcmp (btype, "EntryTime") == 0) + return (ms_rt_bld_add_btime6 (ctxt, comp_name)); + if (strcmp (btype, "Unicode255") == 0) + return (ms_rt_bld_add_utf8vstring (ctxt, comp_name, 255)); /* max 255 char*/ + /* If the "btype" does not match any PredefinedBasicTypes, */ + /* see if it matches a "custom" type (i.e. a type created earlier by */ + /* calling scl2_add_btype). */ + return (ms_rt_bld_61850_add_custom_btype (ctxt, btype, comp_name)); + } + +/************************************************************************/ +/* ms_rt_bld_61850_add_brcb */ +/* NOTE: check only last return code. If one "ms_rt_bld_add_*" call fails, */ +/* subsequent calls will fail too. */ +/************************************************************************/ +static ST_RET ms_rt_bld_61850_add_brcb (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name) + { +ST_RET retcode; + ms_rt_bld_add_str_start (ctxt, comp_name); + ms_rt_bld_add_vstring (ctxt, "RptID", MVL61850_MAX_RPTID_LEN); + ms_rt_bld_add_bool (ctxt, "RptEna"); + ms_rt_bld_add_vstring (ctxt, "DatSet", MVL61850_MAX_OBJREF_LEN); + ms_rt_bld_add_uint (ctxt, "ConfRev", 4); + ms_rt_bld_add_bvstring (ctxt, "OptFlds", 10); + ms_rt_bld_add_uint (ctxt, "BufTm", 4); + ms_rt_bld_add_uint (ctxt, "SqNum", 2); + ms_rt_bld_add_bvstring (ctxt, "TrgOps", 6); + ms_rt_bld_add_uint (ctxt, "IntgPd", 4); + ms_rt_bld_add_bool (ctxt, "GI"); + ms_rt_bld_add_bool (ctxt, "PurgeBuf"); + ms_rt_bld_add_ostring (ctxt, "EntryID", 8); + ms_rt_bld_add_btime6 (ctxt, "TimeofEntry"); + retcode = ms_rt_bld_add_str_end (ctxt); + return (retcode); + } +/************************************************************************/ +/* ms_rt_bld_61850_add_urcb */ +/* NOTE: check only last return code. If one "ms_rt_bld_add_*" call fails, */ +/* subsequent calls will fail too. */ +/************************************************************************/ +static ST_RET ms_rt_bld_61850_add_urcb (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name) + { +ST_RET retcode; + ms_rt_bld_add_str_start (ctxt, comp_name); + ms_rt_bld_add_vstring (ctxt, "RptID", MVL61850_MAX_RPTID_LEN); + ms_rt_bld_add_bool (ctxt, "RptEna"); + ms_rt_bld_add_bool (ctxt, "Resv"); + ms_rt_bld_add_vstring (ctxt, "DatSet", MVL61850_MAX_OBJREF_LEN); + ms_rt_bld_add_uint (ctxt, "ConfRev", 4); + ms_rt_bld_add_bvstring (ctxt, "OptFlds", 10); + ms_rt_bld_add_uint (ctxt, "BufTm", 4); + ms_rt_bld_add_uint (ctxt, "SqNum", 1); + ms_rt_bld_add_bvstring (ctxt, "TrgOps", 6); + ms_rt_bld_add_uint (ctxt, "IntgPd", 4); + ms_rt_bld_add_bool (ctxt, "GI"); + retcode = ms_rt_bld_add_str_end (ctxt); + return (retcode); + } +/************************************************************************/ +/* ms_rt_bld_61850_add_lcb */ +/* NOTE: check only last return code. If one "ms_rt_bld_add_*" call fails, */ +/* subsequent calls will fail too. */ +/************************************************************************/ +static ST_RET ms_rt_bld_61850_add_lcb (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name) + { +ST_RET retcode; + ms_rt_bld_add_str_start (ctxt, comp_name); + ms_rt_bld_add_bool (ctxt, "LogEna"); + ms_rt_bld_add_vstring (ctxt, "LogRef", MVL61850_MAX_OBJREF_LEN); + ms_rt_bld_add_vstring (ctxt, "DatSet", MVL61850_MAX_OBJREF_LEN); +#if 0 /*renxiaobao 20170106 mod*/ + ms_rt_bld_add_btime6 (ctxt, "OldEntrTim"); + ms_rt_bld_add_btime6 (ctxt, "NewEntrTim"); +#else + ms_rt_bld_add_btime6 (ctxt, "OldEntrTm"); + ms_rt_bld_add_btime6 (ctxt, "NewEntrTm"); +#endif + ms_rt_bld_add_ostring (ctxt, "OldEntr", 8); + ms_rt_bld_add_ostring (ctxt, "NewEntr", 8); + ms_rt_bld_add_bvstring (ctxt, "TrgOps", 6); + ms_rt_bld_add_uint (ctxt, "IntgPd", 4); + retcode = ms_rt_bld_add_str_end (ctxt); + return (retcode); + } +/************************************************************************/ +/* ms_rt_bld_61850_add_gcb */ +/* NOTE: check only last return code. If one "ms_rt_bld_add_*" call fails, */ +/* subsequent calls will fail too. */ +/************************************************************************/ +static ST_RET ms_rt_bld_61850_add_gcb (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name) + { +ST_RET retcode; + ms_rt_bld_add_str_start (ctxt, comp_name); + ms_rt_bld_add_bool (ctxt, "GoEna"); + ms_rt_bld_add_vstring (ctxt, "GoID", MVL61850_MAX_RPTID_LEN); + ms_rt_bld_add_vstring (ctxt, "DatSet", MVL61850_MAX_OBJREF_LEN); + ms_rt_bld_add_uint (ctxt, "ConfRev", 4); + ms_rt_bld_add_bool (ctxt, "NdsCom"); + ms_rt_bld_add_str_start (ctxt, "DstAddress"); + ms_rt_bld_add_ostring (ctxt, "Addr", 6); + ms_rt_bld_add_uint (ctxt, "PRIORITY", 1); + ms_rt_bld_add_uint (ctxt, "VID", 2); + ms_rt_bld_add_uint (ctxt, "APPID", 2); + ms_rt_bld_add_str_end (ctxt); + retcode = ms_rt_bld_add_str_end (ctxt); + return (retcode); + } +/************************************************************************/ +/* ms_rt_bld_61850_add_scb */ +/* NOTE: check only last return code. If one "ms_rt_bld_add_*" call fails, */ +/* subsequent calls will fail too. */ +/************************************************************************/ +static ST_RET ms_rt_bld_61850_add_scb (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name) + { +ST_RET retcode; + ms_rt_bld_add_str_start (ctxt, comp_name); + ms_rt_bld_add_bool (ctxt, "GsEna"); + ms_rt_bld_add_vstring (ctxt, "GsID", MVL61850_MAX_RPTID_LEN); + ms_rt_bld_add_arr_start (ctxt, "DNALabels", 32); + ms_rt_bld_add_vstring (ctxt, "DNALabels", 65); + ms_rt_bld_add_arr_end (ctxt); + ms_rt_bld_add_arr_start (ctxt, "UserSTLabels", 128); + ms_rt_bld_add_vstring (ctxt, "DNALabels", 65); + ms_rt_bld_add_arr_end (ctxt); + ms_rt_bld_add_str_start (ctxt, "LSentData"); + ms_rt_bld_add_vstring (ctxt, "GsID", MVL61850_MAX_RPTID_LEN); + ms_rt_bld_add_btime6 (ctxt, "t"); + ms_rt_bld_add_uint (ctxt, "SqNum", 4); + ms_rt_bld_add_uint (ctxt, "StNum", 4); + ms_rt_bld_add_uint (ctxt, "TAL", 4); + ms_rt_bld_add_uint (ctxt, "usec", 4); + ms_rt_bld_add_uint (ctxt, "PhsID", 2); + ms_rt_bld_add_bstring (ctxt, "DNA", 64); + ms_rt_bld_add_bstring (ctxt, "UserST", 256); + ms_rt_bld_add_str_end (ctxt); + ms_rt_bld_add_str_start (ctxt, "DstAddress"); + ms_rt_bld_add_ostring (ctxt, "Addr", 6); + ms_rt_bld_add_uint (ctxt, "PRIORITY", 1); + ms_rt_bld_add_uint (ctxt, "VID", 2); + ms_rt_bld_add_uint (ctxt, "APPID", 2); + ms_rt_bld_add_str_end (ctxt); + retcode = ms_rt_bld_add_str_end (ctxt); + return (retcode); + } +/************************************************************************/ +/* ms_rt_bld_61850_add_msvcb */ +/* NOTE: check only last return code. If one "ms_rt_bld_add_*" call fails, */ +/* subsequent calls will fail too. */ +/************************************************************************/ +static ST_RET ms_rt_bld_61850_add_msvcb (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name) + { +ST_RET retcode; + ms_rt_bld_add_str_start (ctxt, comp_name); + ms_rt_bld_add_bool (ctxt, "SvEna"); + ms_rt_bld_add_vstring (ctxt, "MsvID", MVL61850_MAX_RPTID_LEN); + ms_rt_bld_add_vstring (ctxt, "DatSet", MVL61850_MAX_OBJREF_LEN); + ms_rt_bld_add_uint (ctxt, "ConfRev", 4); + ms_rt_bld_add_uint (ctxt, "SmpRate", 4); + ms_rt_bld_add_bvstring (ctxt, "OptFlds", 3); + retcode = ms_rt_bld_add_str_end (ctxt); + return (retcode); + } +/************************************************************************/ +/* ms_rt_bld_61850_add_usvcb */ +/* NOTE: check only last return code. If one "ms_rt_bld_add_*" call fails, */ +/* subsequent calls will fail too. */ +/************************************************************************/ +static ST_RET ms_rt_bld_61850_add_usvcb (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name) + { +ST_RET retcode; + ms_rt_bld_add_str_start (ctxt, comp_name); + ms_rt_bld_add_bool (ctxt, "SvEna"); + ms_rt_bld_add_bool (ctxt, "Resv"); + ms_rt_bld_add_vstring (ctxt, "UsvID", MVL61850_MAX_RPTID_LEN); + ms_rt_bld_add_vstring (ctxt, "DatSet", MVL61850_MAX_OBJREF_LEN); + ms_rt_bld_add_uint (ctxt, "ConfRev", 4); + ms_rt_bld_add_uint (ctxt, "SmpRate", 4); + ms_rt_bld_add_bvstring (ctxt, "OptFlds", 3); + retcode = ms_rt_bld_add_str_end (ctxt); + return (retcode); + } +/************************************************************************/ +/* ms_rt_bld_61850_add_sgcb */ +/* NOTE: check only last return code. If one "ms_rt_bld_add_*" call fails,*/ +/* subsequent calls will fail too. */ +/************************************************************************/ +static ST_RET ms_rt_bld_61850_add_sgcb (RUNTIME_BUILD_CTXT *ctxt) + { +ST_RET retcode; + ms_rt_bld_add_str_start (ctxt, "SGCB"); /* fixed struct name */ + ms_rt_bld_add_uint (ctxt, "NumOfSG", 1); + ms_rt_bld_add_uint (ctxt, "ActSG", 1); + ms_rt_bld_add_uint (ctxt, "EditSG", 1); + ms_rt_bld_add_bool (ctxt, "CnfEdit"); + ms_rt_bld_add_utctime (ctxt, "LActTm"); + retcode = ms_rt_bld_add_str_end (ctxt); + return (retcode); + } +/************************************************************************/ +/* reserved_free_all */ +/* Find all types used by this VMD. If rt_ctrl->reserved_1 is not NULL, */ +/* we must have allocated it in "scl2_datatype_create", so free it and */ +/* set it to NULL. */ +/************************************************************************/ +static ST_VOID reserved_free_all (MVL_VMD_CTRL *vmd_ctrl) + + { +ST_INT type_id; +MVL_TYPE_CTRL *type_ctrl; +RUNTIME_CTRL *rt_ctrl; + /* This only works for "dynamic" types so start with first dynamic type.*/ + for (type_id = mvl_num_types - mvl_max_dyn.types; type_id < mvl_num_types; type_id++) + { + type_ctrl = mvl_vmd_type_ctrl_find (vmd_ctrl, type_id); + if (type_ctrl) /* type found in this VMD */ + { + rt_ctrl = type_ctrl->rt_ctrl; /* always valid */ + if (rt_ctrl->reserved_1 != NULL) + { + chk_free (rt_ctrl->reserved_1); + rt_ctrl->reserved_1 = NULL; + } + } + } + } +/************************************************************************/ +/* scl_make_objref */ +/* Construct ObjectReference from SCL info. */ +/************************************************************************/ +static ST_RET scl_make_objref ( + SCL_LD *scl_ld, + SCL_LN *scl_ln, + ST_CHAR *objName, /* Object (DataSet, Data) name */ + ST_CHAR *objRef, /* ptr to resulting ObjRef string */ + ST_UINT max_len) /* max len of resulting ObjRef string */ + { +ST_RET retcode; + + if (strlen (scl_ld->domName) + + strlen (scl_ln->prefix) + strlen (scl_ln->lnClass) + strlen (scl_ln->inst) + + strlen (objName) + 2 > max_len) /* 2 added for '/' and '$' */ + { + SXLOG_ERR1 ("Constructed ObjectReference would be too long for '%s'.", objName); + retcode = SD_FAILURE; + } + else + { + sprintf (objRef, "%s/%s%s%s$%s", scl_ld->domName, scl_ln->prefix, + scl_ln->lnClass, scl_ln->inst, objName); + retcode = SD_SUCCESS; + } + return (retcode); + } + +/************************************************************************/ +/* scl_make_objref2 */ +/* Construct ObjectReference from SCL info (LN Name not included). */ +/* Similar to scl_make_objref, but does not include LN name. */ +/************************************************************************/ +static ST_RET scl_make_objref2 ( + SCL_LD *scl_ld, + ST_CHAR *objName, /* Object name */ + ST_CHAR *objRef, /* ptr to resulting ObjRef string */ + ST_UINT max_len) /* max len of resulting ObjRef string */ + { +ST_RET retcode; + if (strlen (scl_ld->domName) + + strlen (objName) + 2 > max_len) /* 2 added for '/' and '$' */ + { + SXLOG_ERR1 ("Constructed ObjectReference would be too long for '%s'.", objName); + retcode = SD_FAILURE; + } + else + { + sprintf (objRef, "%s/%s", scl_ld->domName, objName); + retcode = SD_SUCCESS; + } + return (retcode); + } + +/************************************************************************/ +/* special_type_name */ +/* Create type name for a special LN (one that includes RCB, LCB, etc.).*/ +/* NOTE: do not use '$'. This will confuse "mvlu_set_leaf_param". */ +/************************************************************************/ +ST_RET special_type_name (ST_CHAR *prefix, SCL_LD *scl_ld, SCL_LN *scl_ln, + ST_CHAR *type_name, size_t type_name_size) + { /* Create unique type name for this LN. */ +size_t len = 0; +ST_RET retcode; + if (prefix) /* NOTE: if prefix is not NULL, add prefix. */ + len += strlen (prefix); + len += strlen (scl_ld->inst); + len += strlen (scl_ln->prefix); + len += strlen (scl_ln->lnClass); + len += strlen (scl_ln->inst); + + type_name [0] = '\0'; /* start with empty string */ + if (len < type_name_size) + { /* name will fit, so write it */ + if (prefix) + strcat (type_name, prefix); + strcat (type_name, scl_ld->inst); + strcat (type_name, scl_ln->prefix); + strcat (type_name, scl_ln->lnClass); + strcat (type_name, scl_ln->inst); + retcode = SD_SUCCESS; + } + else + retcode = SD_FAILURE; /* name would be too long */ + return (retcode); + } + +/************************************************************************/ +/* simple_type_name */ +/* Create type name for a simple type. */ +/* NOTE: do not use '$'. This will confuse "mvlu_set_leaf_param". */ +/************************************************************************/ +ST_RET simple_type_name (ST_CHAR *prefix, SCL_LNTYPE *scl_lntype, + ST_CHAR *type_name, size_t type_name_size) + { /* Create unique type name for this LN. */ +size_t len = 0; +ST_RET retcode; + + if (prefix) /* NOTE: if prefix is not NULL, add prefix. */ + len += strlen (prefix); + len += strlen (scl_lntype->id); + + type_name [0] = '\0'; /* start with empty string */ + if (len < type_name_size) + { /* name will fit, so write it */ + if (prefix) + strcat (type_name, prefix); + strcat (type_name, scl_lntype->id); + retcode = SD_SUCCESS; + } + else + retcode = SD_FAILURE; /* name would be too long */ + return (retcode); + } + +/************************************************************************/ +/* scl_find_dotype */ +/************************************************************************/ +static SCL_DOTYPE *scl_find_dotype ( + SCL_INFO *scl_info, /* main struct where all SCL info stored*/ + ST_CHAR *type_id) + { +SCL_DOTYPE *scl_dotype; + + for (scl_dotype = (SCL_DOTYPE *) list_find_last ((DBL_LNK *) scl_info->doTypeHead); + scl_dotype != NULL; + scl_dotype = (SCL_DOTYPE *) list_find_prev ((DBL_LNK *) scl_info->doTypeHead, (DBL_LNK *) scl_dotype)) + { + if (strcmp (scl_dotype->id, type_id) ==0) + return (scl_dotype); + } + return (NULL); /* match not found */ + } +/************************************************************************/ +/* scl_find_datype */ +/************************************************************************/ +static SCL_DATYPE *scl_find_datype ( + SCL_INFO *scl_info, /* main struct where all SCL info stored*/ + ST_CHAR *type_id) + { +SCL_DATYPE *scl_datype; + + for (scl_datype = (SCL_DATYPE *) list_find_last ((DBL_LNK *) scl_info->daTypeHead); + scl_datype != NULL; + scl_datype = (SCL_DATYPE *) list_find_prev ((DBL_LNK *) scl_info->daTypeHead, (DBL_LNK *) scl_datype)) + { + if (strcmp (scl_datype->id, type_id) ==0) + return (scl_datype); + } + return (NULL); /* match not found */ + } +/************************************************************************/ +/************************************************************************/ +static SCL_DATASET *scl_find_dataset ( + SCL_LN *scl_ln, + ST_CHAR *dataset_name) + { +SCL_DATASET *scl_dataset; + + for (scl_dataset = (SCL_DATASET *) list_find_last ((DBL_LNK *) scl_ln->datasetHead); + scl_dataset != NULL; + scl_dataset = (SCL_DATASET *) list_find_prev ((DBL_LNK *) scl_ln->datasetHead, (DBL_LNK *) scl_dataset)) + { + if (strcmp (scl_dataset->name, dataset_name) ==0) + return (scl_dataset); + } + return (NULL); /* match not found */ + } + +/************************************************************************/ +/* scl2_find_enumtype */ +/************************************************************************/ +SCL_ENUMTYPE *scl2_find_enumtype (SCL_INFO *scl_info, ST_CHAR *name) + { +SCL_ENUMTYPE *scl_enumtype; + for (scl_enumtype = (SCL_ENUMTYPE *) list_find_last ((DBL_LNK *) scl_info->enumTypeHead); + scl_enumtype != NULL; + scl_enumtype = (SCL_ENUMTYPE *) list_find_prev ((DBL_LNK *) scl_info->enumTypeHead, (DBL_LNK *) scl_enumtype)) + { + if (strcmp (scl_enumtype->id, name) == 0) + break; /* found a match */ + } + return (scl_enumtype); + } + +/************************************************************************/ +/* scl2_add_btype */ +/************************************************************************/ +SCL2_BTYPE *scl2_add_btype (ST_CHAR *btype, ST_CHAR *tdl) + { +SCL2_BTYPE *sclBtype; +RUNTIME_CTRL *rt_ctrl; +ST_UCHAR asn1_buf [200]; /* simple types only, so this should be big enough*/ + + sclBtype = NULL; /* assume failure for now */ + rt_ctrl = ms_tdl_to_runtime (tdl, asn1_buf, sizeof(asn1_buf)); + if (rt_ctrl) + { + if (rt_ctrl->rt_num == 1) /* must be simple type */ + { + sclBtype = chk_calloc (1, sizeof (SCL2_BTYPE) + strlen (btype) + 1); + sclBtype->btype = (ST_CHAR *) (sclBtype + 1); /* point after struct*/ + strcpy (sclBtype->btype, btype); + sclBtype->rt_ctrl = rt_ctrl; /* rt_ctrl allocated, just save ptr*/ + list_add_last (&scl2_btype_list, sclBtype); + } + else + { /* Complex type not allowed, so destroy it now. Err return already set*/ + ms_runtime_destroy (rt_ctrl); + } + } + return (sclBtype); + } + +/************************************************************************/ +/* rtadd_sdo */ +/* NOTE: if (error) returned, caller should break out of loop. */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +static ST_RET rtadd_sdo ( + RUNTIME_BUILD_CTXT *rt_ctxt, + SCL_INFO *scl_info, + ST_CHAR *FC, /* FC to match */ + ST_CHAR *name, /* SDO name */ + ST_CHAR *type) /* SDO type */ + { +SCL_DOTYPE *scl_dotype; +SCL_DA *scl_da; +ST_RET retcode; +ST_INT rt_num_after_str_start; /* index after str_start added */ + + /* First add SDO name (passed to this funct). May need rollback later */ + if (ms_rt_bld_add_str_start (rt_ctxt, name)!=SD_SUCCESS) + return (SD_FAILURE); /* error (already logged) */ + + /* Save current index. Use later to check if any types added. */ + rt_num_after_str_start = ms_rt_bld_get_count (rt_ctxt); + + /* Find DOType whose "id" matches the SDO "type". */ + scl_dotype = scl_find_dotype (scl_info, type); + if (scl_dotype) + { + /* Find all DA or SDO in this DO that match the FC */ + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_da = (SCL_DA *) list_find_last ((DBL_LNK *) scl_dotype->daHead); + scl_da != NULL; + scl_da = (SCL_DA *) list_find_prev ((DBL_LNK *) scl_dotype->daHead, (DBL_LNK *) scl_da)) + { + if (scl_da->objtype == SCL_OBJTYPE_SDO) + { + /* This is a "nested" SDO. Just call rtadd_sdo again recursively. */ + retcode = rtadd_sdo (rt_ctxt, scl_info, FC, scl_da->name, scl_da->type); + if (retcode != SD_SUCCESS) /* error (already logged) */ + return (retcode); /* error */ + } + else + { /* objtype must be SCL_OBJTYPE_DA */ + if (strcmp (scl_da->fc, FC) == 0) /* FC of this DA matches FC */ + { + retcode = rtadd_da_or_bda (rt_ctxt, scl_info, scl_da->name, scl_da->bType, + scl_da->type, scl_da->count, scl_da->Val); + if (retcode != SD_SUCCESS) /* error (already logged) */ + return (retcode); /* error */ + } + } + } /* end "for (scl_da...)" loop */ + + } + else + { + SXLOG_ERR1 ("SDO type '%s' cannot be found", type); + return (SD_FAILURE); /* error */ + } + + /* Check if any types were added after start of struct */ + if (ms_rt_bld_get_count (rt_ctxt) > rt_num_after_str_start) + { /* types were added, so finish struct now */ + if (ms_rt_bld_add_str_end (rt_ctxt) != SD_SUCCESS) + return (SD_FAILURE); /* error (already logged) */ + } + else + { /* types NOT added so remove start of struct */ + ms_rt_bld_remove_last (rt_ctxt); + } + return (SD_SUCCESS); /* only successful return */ + } +/************************************************************************/ +/* rtadd_da_or_bda */ +/* NOTE: if (error) returned, caller should break out of loop. */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +static ST_RET rtadd_da_or_bda ( + RUNTIME_BUILD_CTXT *rt_ctxt, + SCL_INFO *scl_info, + ST_CHAR *name, /* DA or BDA name */ + ST_CHAR *bType, /* DA or BDA bType */ + ST_CHAR *type, /* DA or BDA type */ + ST_UINT count, /* DA or BDA count */ + ST_CHAR *Val) /* DA or BDA Val (may be NULL) */ + { +ST_RET retcode; +RESERVED_INFO *reserved_info; /* ptr to array of extra type info. */ + + /* Cast "reserved_1" pointer to the type we allocated. */ + if (rt_ctxt->do_count) + reserved_info = NULL; /* rt_ctrl & reserved_1 not allocated yet*/ + else + reserved_info = (RESERVED_INFO *) rt_ctxt->rt_ctrl->reserved_1; + + /* If count!=0, this is array. */ + if (count) + { + /* NOTE: comp_name stored on arr_start AND on first element of array.*/ + if (ms_rt_bld_add_arr_start (rt_ctxt, name, count)) + return (SD_FAILURE); /* error (already logged) */ + } + + /* Add different text depending on "bType" (Struct, Enum, or BasicType). */ + if (strcmp (bType, "Struct") == 0) + { + /* NOTE: this may cause recursion */ + /* (i.e. rtadd_da_struct may call rtadd_da_or_bda).*/ + retcode = rtadd_da_struct (rt_ctxt, scl_info, type, name); + if (retcode != SD_SUCCESS) + { + SXLOG_ERR1 ("SCL ERROR: Can't add type definition for BDA Struct type=%s", type); + return (retcode); + } + } + else if (strcmp (bType, "Enum") == 0) + { + SCL_ENUMTYPE *scl_enumtype; + if ((scl_enumtype = scl2_find_enumtype (scl_info, type))==NULL) + { + SXLOG_ERR1 ("EnumType '%s' could not be found", type); + return (SD_FAILURE); + } + else + { + /* DEBUG: for now assume all enums are 8-bit */ + /* Someday may need to chk for maximum "EnumVal ord" to determine # of bits */ + /* Save the scl_enumtype pointer in reserved_info array. */ + /* Also save "Val", if present. */ + /* CRITICAL: Do this BEFORE calling "ms_rt_bld_add_*" so that */ + /* scl_enumtype is saved in the current array entry. */ + if (!rt_ctxt->do_count) /* if (do_count), reserved_info not set.*/ + { + reserved_info[rt_ctxt->rt_ctrl->rt_num].scl_enumtype = scl_enumtype; + if (Val != NULL) + { + SXLOG_FLOW2 ("Saving Val='%s' for DA or BDA='%s'", Val, name); + reserved_info[rt_ctxt->rt_ctrl->rt_num].Val = Val; + } + } + + if (ms_rt_bld_add_int (rt_ctxt, name, 1) != SD_SUCCESS) + return (SD_FAILURE); /* error (already logged) */ + } + } + else + { /* must be BasicType */ + /* Save initial value of this component, if present. */ + /* CRITICAL: Do this BEFORE calling "ms_rt_bld_add_*" so that */ + /* "Val" is saved in the current array entry. */ + if (Val != NULL) + { + if (!rt_ctxt->do_count) /* if (do_count), reserved_info not set.*/ + { + SXLOG_FLOW2 ("Saving Val='%s' for DA or BDA='%s'", Val, name); + reserved_info[rt_ctxt->rt_ctrl->rt_num].Val = Val; + } + } + if (ms_rt_bld_61850_add_btype (rt_ctxt, bType, name)) + return (SD_FAILURE); /* error (already logged) */ + } + + /* If count!=0, this is array. */ + if (count) + { /* this BDA is array */ + if (ms_rt_bld_add_arr_end (rt_ctxt)) + return (SD_FAILURE); /* error (already logged) */ + } + + return (SD_SUCCESS); /* only successful return */ + } +/************************************************************************/ +/* rtadd_da_struct */ +/* Add the RUNTIME_TYPE definitions for a DA that is "Struct". */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +static ST_RET rtadd_da_struct ( + RUNTIME_BUILD_CTXT *rt_ctxt, + SCL_INFO *scl_info, + ST_CHAR *type_id, + ST_CHAR *comp_name) + { +SCL_DATYPE *scl_datype; +SCL_BDA *scl_bda; +ST_RET retcode; + + scl_datype = scl_find_datype (scl_info, type_id); + if (scl_datype) + { + if (ms_rt_bld_add_str_start (rt_ctxt, comp_name)!=SD_SUCCESS) + return (SD_FAILURE); /* error (already logged) */ + + /* Add info for all BDA in this DAType. */ + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_bda = (SCL_BDA *) list_find_last ((DBL_LNK *) scl_datype->bdaHead); + scl_bda != NULL; + scl_bda = (SCL_BDA *) list_find_prev ((DBL_LNK *) scl_datype->bdaHead, (DBL_LNK *) scl_bda)) + { + retcode = rtadd_da_or_bda (rt_ctxt, scl_info, scl_bda->name, scl_bda->bType, + scl_bda->type, scl_bda->count, scl_bda->Val); + if (retcode != SD_SUCCESS) /* error (already logged) */ + return (retcode); /* error */ + } /* end "for (scl_bda...)" loop */ + + if (ms_rt_bld_add_str_end (rt_ctxt)!=SD_SUCCESS) + return (SD_FAILURE); /* error (already logged) */ + } + else + { + SXLOG_ERR1 ("SCL ERROR: DAType id=%s not found", type_id); + return (SD_FAILURE); /* error */ + } + + return (SD_SUCCESS); /* only successful return */ + } +/************************************************************************/ +/* rtadd_do */ +/* Add the RUNTIME_TYPE definitions for one DO. */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +static ST_RET rtadd_do ( + RUNTIME_BUILD_CTXT *rt_ctxt, + char *FC, + SCL_INFO *scl_info, + ST_CHAR *do_name, + SCL_DOTYPE *scl_dotype) + { +SCL_DA *scl_da; +ST_RET retcode; +ST_INT rt_num_after_str_start; /* index after str_start added */ + + if (ms_rt_bld_add_str_start (rt_ctxt, do_name)!=SD_SUCCESS) + return (SD_FAILURE); /* error (already logged) */ + + /* Save current index. Use later to check if any types added. */ + rt_num_after_str_start = ms_rt_bld_get_count (rt_ctxt); + + /* Find all DA or SDO in this DO that match the FC */ + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_da = (SCL_DA *) list_find_last ((DBL_LNK *) scl_dotype->daHead); + scl_da != NULL; + scl_da = (SCL_DA *) list_find_prev ((DBL_LNK *) scl_dotype->daHead, (DBL_LNK *) scl_da)) + { + if (scl_da->objtype == SCL_OBJTYPE_SDO) + { + /* Only "name" and "type" used for SDO. */ + retcode = rtadd_sdo (rt_ctxt, scl_info, FC, scl_da->name, scl_da->type); + if (retcode != SD_SUCCESS) /* error (already logged) */ + return (retcode); /* error */ + } + else + { + /*renxiaobao ¶¨Öµ */ + if (strcmp ("SE", FC) == 0) + { + if (strcmp (scl_da->fc, "SG") == 0) /* FC of this DA matches FC */ + { + retcode = rtadd_da_or_bda (rt_ctxt, scl_info, scl_da->name, scl_da->bType, + scl_da->type, scl_da->count, scl_da->Val); + if (retcode != SD_SUCCESS) /* error (already logged) */ + return (retcode); /* error */ + } + } + /* objtype must be SCL_OBJTYPE_DA */ + if (strcmp (scl_da->fc, FC) == 0) /* FC of this DA matches FC */ + { + retcode = rtadd_da_or_bda (rt_ctxt, scl_info, scl_da->name, scl_da->bType, + scl_da->type, scl_da->count, scl_da->Val); + if (retcode != SD_SUCCESS) /* error (already logged) */ + return (retcode); /* error */ + } + } + } /* end "for (scl_da...)" loop */ + + /* Check if any types were added after start of struct */ + if (ms_rt_bld_get_count (rt_ctxt) > rt_num_after_str_start) + { /* types were added, so finish struct now */ + if (ms_rt_bld_add_str_end (rt_ctxt) != SD_SUCCESS) + return (SD_FAILURE); /* error (already logged) */ + } + else + { /* types NOT added so remove start of struct */ + ms_rt_bld_remove_last (rt_ctxt); + } + return (SD_SUCCESS); /* only successful return */ + } +/************************************************************************/ +/* rtadd_fc */ +/* RETURNS: SD_SUCCESS or error code */ +/* Add the types for one FC to the RUNTIME_BUILD_CTXT. */ +/************************************************************************/ +static ST_RET rtadd_fc ( + RUNTIME_BUILD_CTXT *rt_ctxt, + ST_CHAR *FC, + SCL_INFO *scl_info, + SCL_LNTYPE *scl_lntype, + SCL_LN *scl_ln_special) /* needed for SGCB */ + { +SCL_DO *scl_do; +SCL_DOTYPE *scl_dotype; +ST_RET retcode; +ST_INT rt_num_after_str_start; /* index after str_start added */ + + /* Add start of struct for this FC. Remove later if no DA's found.*/ + if (ms_rt_bld_add_str_start (rt_ctxt, FC)!=SD_SUCCESS) + return (SD_FAILURE); + + /* Save current index. Use later to check if any types added. */ + rt_num_after_str_start = ms_rt_bld_get_count (rt_ctxt); + + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_do = (SCL_DO *) list_find_last ((DBL_LNK *) scl_lntype->doHead); + scl_do != NULL; + scl_do = (SCL_DO *) list_find_prev ((DBL_LNK *) scl_lntype->doHead, (DBL_LNK *) scl_do)) + { + /* Find DOType for this DO. */ + scl_dotype = scl_find_dotype (scl_info, scl_do->type); + if (scl_dotype) /* found DOType */ + { + retcode = rtadd_do (rt_ctxt, FC, scl_info, scl_do->name, scl_dotype); + if (retcode != SD_SUCCESS) + { + SXLOG_ERR1 ("ERROR adding type definitions for DO='%s'", scl_do->name); + return (retcode); + } + } + else + { /* can't find DOType for this DO. Cannot continue. */ + SXLOG_ERR2 ("Cannot find DOType='%s' for DO='%s'.", + scl_do->type, scl_do->name); + return (SD_FAILURE); + } + } /* end "for (scl_do...)" loop */ + + /* If SGCB configured and FC="SP", add SGCB here after other attributes.*/ + if (scl_ln_special && scl_ln_special->sgcb && strcmp (FC, "SP") == 0) + { + retcode = ms_rt_bld_61850_add_sgcb (rt_ctxt); /* Add SGCB struct.*/ + if (retcode != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR adding SGCB"); + return (retcode); + } + } + + /* Check if any types were added after start of struct */ + if (ms_rt_bld_get_count (rt_ctxt) > rt_num_after_str_start) + { /* types were added, so finish struct now */ + if (ms_rt_bld_add_str_end (rt_ctxt) != SD_SUCCESS) + return (SD_FAILURE); /* error (already logged) */ + } + else + { /* types NOT added so remove start of struct */ + ms_rt_bld_remove_last (rt_ctxt); + } + return (SD_SUCCESS); /* this is only "good" return */ + } +/************************************************************************/ +/* rtadd_rp_or_br */ +/* RETURNS: SD_SUCCESS or error code */ +/* Add runtime type definition for special FC=RP or FC=BR. */ +/* CRITICAL: Last arg "buffered" must be SD_TRUE or SD_FALSE (other */ +/* non-zero values NOT treated the same as SD_TRUE). */ +/************************************************************************/ +static ST_RET rtadd_rp_or_br ( + RUNTIME_BUILD_CTXT *rt_ctxt, + SCL_INFO *scl_info, + SCL_LNTYPE *scl_lntype, + SCL_LN *scl_ln, + ST_BOOLEAN buffered) /* SD_TRUE to add "buffered" reports */ + /* SD_FALSE to add "unbuffered" reports */ + /* CRITICAL: no other values allowed */ + { +SCL_RCB *scl_rcb; +ST_INT count = 0; +ST_RET retcode = SD_SUCCESS; +ST_INT index, maxClient; + + for (scl_rcb = (SCL_RCB *) list_find_last ((DBL_LNK *) scl_ln->rcbHead); + scl_rcb != NULL; + scl_rcb = (SCL_RCB *) list_find_prev ((DBL_LNK *) scl_ln->rcbHead, (DBL_LNK *) scl_rcb)) + { + /* If RCB doesn't match the kind we're looking for, ignore it. */ + if (scl_rcb->buffered != buffered) + continue; + + /* NOTE: if NOT the type we're looking for, never get here (see 'continue' above)*/ + /* NOTE: don't chk every rtadd.. return. If one call fails, subsequent calls fail too.*/ + if (buffered) /* looking for buffered & this is buffered */ + { + if (count==0) + ms_rt_bld_add_str_start (rt_ctxt, "BR"); + } + else /* looking for unbuffered & this is unbuffered */ + { + if (count==0) + ms_rt_bld_add_str_start (rt_ctxt, "RP"); + } + + maxClient = scl_rcb->maxClient; /* use value of "RptEnabled max" in SCL*/ + + /* Add type definitions for each RCB in a loop. */ + for (index = 1; index<=maxClient; index++) + { + ST_CHAR rcb_name [MAX_IDENT_LEN + 1]; + if (strlen (scl_rcb->name) <= MAX_IDENT_LEN - 2) /* make sure there's room*/ + { + if (rcb_name_no_index && maxClient == 1) + sprintf (rcb_name, "%s", scl_rcb->name); /* do NOT add suffix*/ + else + sprintf (rcb_name, "%s%02d", scl_rcb->name, index); /* construct RCB name*/ + if (buffered) /* looking for buffered & this is buffered */ + retcode = ms_rt_bld_61850_add_brcb (rt_ctxt, rcb_name); + else /* looking for unbuffered & this is unbuffered */ + retcode = ms_rt_bld_61850_add_urcb (rt_ctxt, rcb_name); + } + else + retcode = SD_FAILURE; /* name too long. Should NEVER get this error*/ + } + + if (retcode) /* if error, stop */ + return (retcode); + + count++; /* increment count of rcb */ + } /* end loop */ + + /* If any found, add ending text. */ + if (count>0) + retcode = ms_rt_bld_add_str_end (rt_ctxt); + + return (retcode); /* NOTE: may have returned sooner on some errors*/ + } /* end rtadd_rp_or_br */ + +/************************************************************************/ +/* rtadd_lg */ +/* RETURNS: SD_SUCCESS or error code */ +/* Add runtime type definition for special FC=LG. */ +/* NOTE: OptFlds in 61850-7-2 not mapped to MMS. */ +/************************************************************************/ +static ST_RET rtadd_lg ( + RUNTIME_BUILD_CTXT *rt_ctxt, + SCL_INFO *scl_info, + SCL_LNTYPE *scl_lntype, + SCL_LN *scl_ln) + { +SCL_LCB *scl_lcb; +ST_INT count = 0; +SCL_DATASET *scl_dataset; +ST_RET retcode = SD_SUCCESS; + + for (scl_lcb = (SCL_LCB *) list_find_last ((DBL_LNK *) scl_ln->lcbHead); + scl_lcb != NULL; + scl_lcb = (SCL_LCB *) list_find_prev ((DBL_LNK *) scl_ln->lcbHead, (DBL_LNK *) scl_lcb)) + { + scl_dataset = scl_find_dataset (scl_ln, scl_lcb->datSet); + if (scl_dataset == NULL) + { + SXLOG_ERR1 ("rtadd_lg: datSet='%s' not found", scl_lcb->datSet); + return (SD_FAILURE); + } + + if (count==0) + retcode = ms_rt_bld_add_str_start (rt_ctxt, "LG"); /* first one needs (LG) */ + + if (retcode) /* if error, stop */ + return (retcode); + + /* Add lcb name as component name.*/ + retcode = ms_rt_bld_61850_add_lcb (rt_ctxt, scl_lcb->name); + + if (retcode) /* if error, stop */ + return (retcode); + + count++; /* increment count of lcb */ + } /* end loop */ + + /* If any found, add ending text. */ + if (count>0) + retcode = ms_rt_bld_add_str_end (rt_ctxt); + + return (retcode); /* NOTE: may have returned sooner on some errors*/ + } /* end rtadd_lg */ + +/************************************************************************/ +/* rtadd_go_or_gs */ +/* RETURNS: SD_SUCCESS or error code */ +/* Add runtime type definition for special FC=GO or FC=GS. */ +/************************************************************************/ +static ST_RET rtadd_go_or_gs ( + RUNTIME_BUILD_CTXT *rt_ctxt, + SCL_INFO *scl_info, + SCL_LNTYPE *scl_lntype, + SCL_LN *scl_ln, + ST_BOOLEAN isGoose) /* SD_TRUE to add GOOSE (FC=GO) */ + /* SD_FALSE to add GSSE (FC=GS) */ + /* CRITICAL: no other values allowed */ + { +SCL_GCB *scl_gcb; +ST_INT count = 0; +SCL_DATASET *scl_dataset; +ST_RET retcode = SD_SUCCESS; + + for (scl_gcb = (SCL_GCB *) list_find_last ((DBL_LNK *) scl_ln->gcbHead); + scl_gcb != NULL; + scl_gcb = (SCL_GCB *) list_find_prev ((DBL_LNK *) scl_ln->gcbHead, (DBL_LNK *) scl_gcb)) + { + /* If GCB doesn't match the kind we're looking for, ignore it. */ + if (scl_gcb->isGoose != isGoose) + continue; + + /* NOTE: if NOT the type we're looking for, never get here (see 'continue' above)*/ + if (scl_gcb->isGoose) + { + /* GOOSE needs dataset. Find it now. */ + scl_dataset = scl_find_dataset (scl_ln, scl_gcb->datSet); + if (scl_dataset == NULL) + { + SXLOG_ERR1 ("rtadd_go_or_gs: datSet='%s' not found", scl_gcb->datSet); + return (SD_FAILURE); + } + + if (count==0) + ms_rt_bld_add_str_start (rt_ctxt, "GO"); /* first one needs "GO" */ + } + else + { + if (count==0) + ms_rt_bld_add_str_start (rt_ctxt, "GS"); /* first one needs "GS" */ + } + + if (retcode) /* if error, stop */ + return (retcode); + + if (scl_gcb->isGoose) /* looking for GOOSE & this is GOOSE */ + retcode = ms_rt_bld_61850_add_gcb (rt_ctxt, scl_gcb->name); + else /* looking for GSSE & this is GSSE */ + retcode = ms_rt_bld_61850_add_scb (rt_ctxt, scl_gcb->name); + + if (retcode) /* if error, stop */ + return (retcode); + + count++; /* increment count of gcb */ + } /* end loop */ + + /* If any found, add ending text. */ + if (count>0) + retcode = ms_rt_bld_add_str_end (rt_ctxt); + + return (retcode); /* NOTE: may have returned sooner on some errors*/ + } /* end rtadd_go_or_gs */ + +/************************************************************************/ +/* rtadd_ms_or_us */ +/* RETURNS: SD_SUCCESS or error code */ +/* Add runtime type definition for FC=MS or FC=US. */ +/* CRITICAL: Last arg "multicast" must be SD_TRUE or SD_FALSE (other */ +/* non-zero values NOT treated the same as SD_TRUE). */ +/************************************************************************/ +static ST_RET rtadd_ms_or_us ( + RUNTIME_BUILD_CTXT *rt_ctxt, + SCL_INFO *scl_info, + SCL_LNTYPE *scl_lntype, + SCL_LN *scl_ln, + ST_BOOLEAN multicast) /* SD_TRUE to add all MSVCB (FC=MS) */ + /* SD_FALSE to add all USVCB (FC=US) */ + /* CRITICAL: no other values allowed */ + { +SCL_SVCB *scl_svcb; +ST_INT count = 0; +SCL_DATASET *scl_dataset; +ST_RET retcode = SD_SUCCESS; + + for (scl_svcb = (SCL_SVCB *) list_find_last ((DBL_LNK *) scl_ln->svcbHead); + scl_svcb != NULL; + scl_svcb = (SCL_SVCB *) list_find_prev ((DBL_LNK *) scl_ln->svcbHead, (DBL_LNK *) scl_svcb)) + { + /* If svcb doesn't match the kind we're looking for, ignore it. */ + if (scl_svcb->multicast != multicast) + continue; + + scl_dataset = scl_find_dataset (scl_ln, scl_svcb->datSet); + if (scl_dataset == NULL) + { + SXLOG_ERR1 ("rtadd_ms_or_us: datSet='%s' not found", scl_svcb->datSet); + return (SD_FAILURE); + } + + /* NOTE: if NOT the type we're looking for, never get here (see 'continue' above)*/ + /* NOTE: don't chk every rtadd.. return. If one call fails, subsequent calls fail too.*/ + if (multicast) /* looking for multicast & this is multicast */ + { + if (count==0) + ms_rt_bld_add_str_start (rt_ctxt, "MS"); /* first one needs (MS) */ + } + else /* looking for unicast & this is unicast */ + { + if (count==0) + ms_rt_bld_add_str_start (rt_ctxt, "US"); /* first one needs (US) */ + } + + + /* NOTE: if NOT the type we're looking for, never get here (see 'continue' above)*/ + if (multicast) /* looking for multicast & this is multicast */ + retcode = ms_rt_bld_61850_add_msvcb (rt_ctxt, scl_svcb->name); + else /* looking for unicast & this is unicast */ + retcode = ms_rt_bld_61850_add_usvcb (rt_ctxt, scl_svcb->name); + + if (retcode) /* if error, stop */ + return (retcode); + + count++; /* increment count of svcb */ + } /* end loop */ + + /* If any found, add ending text. */ + if (count>0) + retcode = ms_rt_bld_add_str_end (rt_ctxt); + + return (retcode); /* NOTE: may have returned sooner on some errors*/ + } /* end rtadd_ms_or_us */ + +/************************************************************************/ +/* scl2_datatype_create */ +/* Create MMS Data type for one Logical Node Type (LNodeType) */ +/* defined in SCL. */ +/* RETURNS: type_id (-1 on error) */ +/************************************************************************/ +static ST_INT scl2_datatype_create ( + MVL_VMD_CTRL *vmd_ctrl, /* VMD in which to add this type */ + SCL_INFO *scl_info, /* main struct where all SCL info stored*/ + SCL_LNTYPE *scl_lntype, /* info for this LNType */ + ST_INT max_rt_num, /* max num of RUNTIME_TYPE for this LNodeType*/ + /* If you don't care, set this = 0. */ + ST_BOOLEAN use_names, /* If set, use type names. */ + ST_CHAR *name_prefix, /* unique prefix to add to each type name*/ + /* only used if "use_names==SD_TRUE". */ + SCL_LD *scl_ld_special, /* LD containing LN with "special stuff"*/ + /* (i.e. ReportControl, LogControl, etc)*/ + /* NULL if nothing special in LN. */ + SCL_LN *scl_ln_special) /* LN with "special stuff" */ + /* NULL if nothing special in LN. */ + { +ST_RET retcode; +ST_INT type_id = -1; /* assumes failure. */ +RUNTIME_BUILD_CTXT rt_ctxt; +MVL_TYPE_CTRL *type_ctrl; +ST_CHAR type_name[MAX_IDENT_LEN+1]; +ST_INT loop; /* loop counter */ +ST_INT save_rt_num=0; /* RUNTIME_TYPE count computed on first loop */ + + if (use_names) + { + /* Generate type_name. */ + if (scl_ln_special) + { /* Create unique type name for this LN. */ + retcode = special_type_name (name_prefix, scl_ld_special, scl_ln_special, type_name, sizeof(type_name)); + } + else + retcode = simple_type_name (name_prefix, scl_lntype, type_name, sizeof(type_name)); + if (retcode) + { + SXLOG_ERR1 ("Error generating type name for LNodeType id='%s'", scl_lntype->id); + return (-1); /* return type_id of (-1) to indicate error */ + } + } + + /* Begin constructing the data type in rt_ctxt. */ + /* Loop exactly 2 times. First iteration, just compute "rt_num". */ + /* Call "ms_rt_bld_get_count" at end of loop to get the count. */ + /* Second iteration, build type (pass rt_num to ms_rt_bld_start). */ + /* CRITICAL: do not access rt_ctxt->rt_ctrl on first loop iteration. */ + /* It is not set yet. */ + for (loop = 0; loop < 2; loop++) + { + if (loop == 0) + ms_rt_bld_start (&rt_ctxt, 0); /* 2nd arg = 0 so bld functions */ + /* just compute rt_num */ + else + { + ms_rt_bld_start (&rt_ctxt, save_rt_num); /* first loop computed save_rt_num*/ + /* Allocate extra array of structs. Free this when all SCL processing*/ + /* done (see end of scl2_ld_create_all). */ + rt_ctxt.rt_ctrl->reserved_1 = (ST_VOID *) chk_calloc (save_rt_num, sizeof (RESERVED_INFO)); /* array of ptrs*/ + } + + /* Go through all linked lists and create COMPLETE type definition. */ + /* NOTE: order of FC specified in 61850-8-1 (section 6.1.3). */ + + /* NOTE: SCL only allows "ST" "MX" "CO" "SP" "SG" "SE" "SV" "CF" "DC" "EX".*/ + /* "RP", "LG", and "BR" are special cases. */ + do + { /* "do-while" loop: only needed so we can break on first error. */ + /* if any rtadd_* call fails, break and return error. */ + if ((retcode = ms_rt_bld_add_str_start (&rt_ctxt, NULL)) != SD_SUCCESS) /* no comp name*/ + break; + if ((retcode = rtadd_fc (&rt_ctxt, "MX", scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS) + break; + if ((retcode = rtadd_fc (&rt_ctxt, "ST", scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS) + break; + if ((retcode = rtadd_fc (&rt_ctxt, "CO", scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS) + break; + if ((retcode = rtadd_fc (&rt_ctxt, "CF", scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS) + break; + if ((retcode = rtadd_fc (&rt_ctxt, "DC", scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS) + break; + if ((retcode = rtadd_fc (&rt_ctxt, "SP", scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS) + break; + if ((retcode = rtadd_fc (&rt_ctxt, "SG", scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS) + break; + + /* FC=RP is special case. Call special function. */ + if (scl_ln_special) + { /* special type for LN containing RCBs */ + if ((retcode = rtadd_rp_or_br (&rt_ctxt, scl_info, scl_lntype, scl_ln_special, SD_FALSE)) != SD_SUCCESS) + break; + } + + /* FC=LG is special case. Call special function. */ + if (scl_ln_special) + { + if ((retcode = rtadd_lg (&rt_ctxt, scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS) + break; + } + + /* FC=BR is special case. Call special function. */ + if (scl_ln_special) + { /* special type for LN containing RCBs */ + if ((retcode = rtadd_rp_or_br (&rt_ctxt, scl_info, scl_lntype, scl_ln_special, SD_TRUE)) != SD_SUCCESS) + break; + } + + if (scl_ln_special) + { + /* FC=GO is special case. Call special function (last arg SD_TRUE). */ + if ((retcode = rtadd_go_or_gs (&rt_ctxt, scl_info, scl_lntype, scl_ln_special, SD_TRUE)) != SD_SUCCESS) + break; + /* FC=GS is special case. Call special function (last arg SD_FALSE). */ + if ((retcode = rtadd_go_or_gs (&rt_ctxt, scl_info, scl_lntype, scl_ln_special, SD_FALSE)) != SD_SUCCESS) + break; + } + + if ((retcode = rtadd_fc (&rt_ctxt, "SV", scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS) + break; + if ((retcode = rtadd_fc (&rt_ctxt, "SE", scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS) + break; + + /* Add types for "MS" and "US" (sampled value control blocks). */ + if (scl_ln_special) + { + /* FC=MS: This funct with arg = SD_TRUE adds types for FC=MS. */ + if ((retcode = rtadd_ms_or_us (&rt_ctxt, scl_info, scl_lntype, scl_ln_special, SD_TRUE)) != SD_SUCCESS) + break; + /* FC=US: This funct with arg = SD_FALSE adds types for FC=US. */ + if ((retcode = rtadd_ms_or_us (&rt_ctxt, scl_info, scl_lntype, scl_ln_special, SD_FALSE)) != SD_SUCCESS) + break; + } + + if ((retcode = rtadd_fc (&rt_ctxt, "EX", scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS) + break; + if ((retcode = ms_rt_bld_add_str_end (&rt_ctxt)) != SD_SUCCESS) + break; + } while (0); /* end of "do-while" loop: only needed so we can break on first error. */ + + if (loop==0) + { + /* First loop: computing rt_num. Save rt_num to use on second loop.*/ + /* CRITICAL: use ..get_max_count here to get "maximum" count. */ + /* May be slightly larger than "current" count. */ + save_rt_num = ms_rt_bld_get_max_count (&rt_ctxt); + /* NOTE: no need to call ms_rt_bld_finish (nothing to clean up). */ + + /* If max_rt_num != 0, and save_rt_num exceeds it, log and return error.*/ + if (max_rt_num != 0 && save_rt_num > max_rt_num) + { + SXLOG_ERR3 ("Number of RUNTIME_TYPE elements (%d) exceeds maximum (%d). Cannot create type for LNodeType id=%s", + save_rt_num, max_rt_num, scl_lntype->id); + return (-1); /* error. Cannot continue */ + } + else if (save_rt_num == 0) + { + SXLOG_ERR1 ("Number of RUNTIME_TYPE elements = 0. Cannot create type for LNodeType id=%s", + scl_lntype->id); + return (-1); /* error. Cannot continue */ + } + } + /* On Second loop, nothing else to do. */ + } /* end outer loop */ + + /* If retcode==SD_SUCCESS, ALL "rtadd_fc" calls were successful, so create type here */ + if (retcode == SD_SUCCESS) + { + ms_rt_bld_finish (&rt_ctxt); + + /* "rt_num" must NEVER exceed size allocated, but may be slightly less.*/ + assert (rt_ctxt.rt_ctrl->rt_num <= save_rt_num); + SXLOG_FLOW2 ("RUNTIME_TYPE count for LNodeType id='%s' = %d", + scl_lntype->id, rt_ctxt.rt_ctrl->rt_num); + + /* Create the type now. */ + if (use_names) + type_id = mvl_vmd_type_id_create (vmd_ctrl, type_name, rt_ctxt.rt_ctrl); + else + type_id = mvl_vmd_type_id_create (vmd_ctrl, NULL, rt_ctxt.rt_ctrl); + } + else + { /* build failed, so cleanup now */ + chk_free (rt_ctxt.rt_ctrl->reserved_1); + ms_rt_bld_cancel (&rt_ctxt); + } + + if (type_id >= 0) + { /* type successfully created */ + type_ctrl = mvl_type_ctrl_find (type_id); + if (mms_debug_sel & MMS_LOG_RT) + { + MLOG_ALWAYS1 ("RUNTIME_TYPE definition for LNodeType id='%s':", scl_lntype->id); + ms_log_runtime (type_ctrl->rt_ctrl->rt_first, type_ctrl->rt_ctrl->rt_num); + } + + /* CRITICAL: we want the same leaf function for every leaf, so */ + /* set leaf functions now in every RUNTIME_TYPE element. */ + /* NOTE: leaf functions never used for RT_STR_START, RT_ARR_START,*/ + /* etc. but they're set anyway because it's easier to set all.*/ + /* NOTE: this function may be customized for each application. */ + /* It should be placed in a "user" module. */ + + if (u_set_all_leaf_functions (type_ctrl->rt_ctrl) != SD_SUCCESS) + { + SXLOG_ERR1 ("Error setting leaf functions for LNodeType id=%s", scl_lntype->id); + mvl_type_id_destroy (type_id); /* destroy type just created */ + type_id = -1; /* set invalid type_id to indicate error */ + } + } + + if (type_id < 0) + SXLOG_ERR1 ("scl2_datatype_create FAILED for LNodeType id=%s", scl_lntype->id); + else + SXLOG_FLOW1 ("scl2_datatype_create SUCCESSFUL for LNodeType id=%s", scl_lntype->id); + + return (type_id); + } +/************************************************************************/ +/* find_scl_lntype */ +/* Search for lntype by name. */ +/************************************************************************/ +SCL_LNTYPE *find_scl_lntype (SCL_INFO *scl_info, ST_CHAR *name) + { +SCL_LNTYPE *scl_lntype; + for (scl_lntype = (SCL_LNTYPE *) list_find_last ((DBL_LNK *) scl_info->lnTypeHead); + scl_lntype != NULL; + scl_lntype = (SCL_LNTYPE *) list_find_prev ((DBL_LNK *) scl_info->lnTypeHead, (DBL_LNK *) scl_lntype)) + { + if (strcmp (name, scl_lntype->id) == 0) /* type name matches*/ + return (scl_lntype); + } + return (NULL); /* lntype not found*/ + } +/************************************************************************/ +/* scl2_datatype_create_all */ +/* Create MMS Data types for all Logical Node Types (LNodeType) */ +/* defined in SCL. */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +ST_RET scl2_datatype_create_all ( + MVL_VMD_CTRL *vmd_ctrl, /* VMD in which to add types. */ + SCL_INFO *scl_info, /* main struct where all SCL info stored*/ + ST_INT max_rt_num, /* max num of RUNTIME_TYPE for each LNodeType*/ + ST_BOOLEAN use_names, /* if SD_TRUE, generate a name for each type*/ + ST_CHAR *name_prefix) /* unique prefix to add to each type name*/ + /* only used if "use_names==SD_TRUE". */ + { +ST_RET retcode; +SCL_LNTYPE *scl_lntype; +SCL_LD *scl_ld; +SCL_LN *scl_ln; + + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + retcode = SD_SUCCESS; + + /* CRITICAL: Don't allow this to be called again for the same SCL_INFO struct.*/ + /* That would cause types to be created twice, and the "type_id" saved*/ + /* in each SCL_LN and SCL_LNTYPE would be overwritten. */ + if (scl_info->datatype_create_done) + { + SXLOG_ERR0 ("Data types already created for this SCL file. Cannot create again."); + return (SD_FAILURE); + } + else + scl_info->datatype_create_done = SD_TRUE; /* Set flag now */ + + /* Loop through all scl_lntype structs. For each one, create type & save type_id in scl_lntype->type_id.*/ + for (scl_lntype = (SCL_LNTYPE *) list_find_last ((DBL_LNK *) scl_info->lnTypeHead); + scl_lntype != NULL; + scl_lntype = (SCL_LNTYPE *) list_find_prev ((DBL_LNK *) scl_info->lnTypeHead, (DBL_LNK *) scl_lntype)) + { + scl_lntype->type_id = scl2_datatype_create (vmd_ctrl, scl_info, scl_lntype, + max_rt_num, use_names, name_prefix, NULL, NULL); + /* NOTE: could fail (type_id < 0). OK for now. Might not be used by any LN.*/ + } + + /* Loop through all Logical Nodes. If a Locical Node + * contains "special stuff" (i.e. ReportControl, LogControl, GSEControl), + * create a special type that includes the "special stuff". + * If not, use the appropriate type created by the above loop (scl_lntype->type_id). + * Must check all Logical Nodes (scl_ln) in all Logical Devices (scl_ld). + */ + for (scl_ld = (SCL_LD *) list_find_last ((DBL_LNK *) scl_info->ldHead); + scl_ld != NULL; + scl_ld = (SCL_LD *) list_find_prev ((DBL_LNK *) scl_info->ldHead, (DBL_LNK *) scl_ld)) + { + for (scl_ln = (SCL_LN *) list_find_last ((DBL_LNK *) scl_ld->lnHead); + scl_ln != NULL; + scl_ln = (SCL_LN *) list_find_prev ((DBL_LNK *) scl_ld->lnHead, (DBL_LNK *) scl_ln)) + { + scl_lntype = find_scl_lntype (scl_info, scl_ln->lnType); /* search for lntype by name*/ + if (scl_lntype) + { + assert (scl_ln->type_id == 0); /* already set. Something's wrong*/ + /* If rcbHead!=NULL, this LN contains ReportControl. */ + /* If lcbHead!=NULL, this LN contains LogControl. */ + /* If gcbHead!=NULL, this LN contains GSEControl. */ + /* If svcbHead!=NULL, this LN contains SampledValueControl */ + /* NOTE: do nothing if it fails. Detected later when rcb created.*/ + if (scl_ln->rcbHead || scl_ln->lcbHead || scl_ln->gcbHead || scl_ln->svcbHead) + { /* "Special" LN. Create special type just for this LN. */ + /* Last 2 args point to LD & LN containing special info (rcb, gcb, etc.).*/ + scl_ln->type_id = scl2_datatype_create (vmd_ctrl, scl_info, scl_lntype, + max_rt_num, use_names, name_prefix, scl_ld, scl_ln); + } + else + { /* "Normal" LN. Save type_id created by first loop. */ + scl_ln->type_id = scl_lntype->type_id; + } + } + else + { /* type not found. Set invalid type_id. Error logged below.*/ + scl_ln->type_id = -1; + } + if (scl_ln->type_id < 0) + { + SXLOG_ERR2 ("Could not find or create lnType '%s' for LN '%s'", + scl_ln->lnType, scl_ln->varName); + retcode = SD_FAILURE; /* create failed for this LN, return error.*/ + /* NOTE: function fails, but continue looping to log other errors too.*/ + } + } + } + if (retcode) + { + /* If anything failed, reserved_1 member of every */ + /* RUNTIME_CTRL should no longer be needed. */ + reserved_free_all (vmd_ctrl); + } + return (retcode); + } + +/************************************************************************/ +/* scl2_ln_init_lcb_vals */ +/* Use mvlu_find_comp_type to find the data offset of each LCB in the LN.*/ +/* Then write the SCL data there. */ +/************************************************************************/ +static ST_VOID scl2_ln_init_lcb_vals ( + SCL_INFO *scl_info, /* main struct where all SCL info stored*/ + SCL_LD *scl_ld, + SCL_LN *scl_ln) + { +ST_CHAR flatname [MAX_IDENT_LEN +1]; +SCL_LCB *scl_lcb; +MVL61850_LCB_DATA *lcb_data; +RUNTIME_TYPE *comp_rt_type; /* first rt_type of component */ +ST_INT comp_rt_num; /* num of rt_types in component */ +ST_RET retcode = SD_SUCCESS; + + for (scl_lcb = (SCL_LCB *) list_find_last ((DBL_LNK *) scl_ln->lcbHead); + scl_lcb != NULL; + scl_lcb = (SCL_LCB *) list_find_prev ((DBL_LNK *) scl_ln->lcbHead, (DBL_LNK *) scl_lcb)) + { + /* NOTE: mvlu_find_comp_type uses flattened name without LN prefix. */ + sprintf (flatname, "LG$%s", scl_lcb->name); + retcode = mvlu_find_comp_type (scl_ln->mvl_var_assoc->type_id, + flatname, &comp_rt_type, &comp_rt_num); + if (retcode!=SD_SUCCESS) + { + SXLOG_ERR2 ("Cannot find component '%s' in var '%s'. Initial values not set.", + flatname, scl_ln->mvl_var_assoc->name); + } + else + { + lcb_data = (MVL61850_LCB_DATA *)((ST_CHAR *) scl_ln->mvl_var_assoc->data + comp_rt_type->mvluTypeInfo.offSet); + /* Use SCL info to initialize LCB data. */ + /* Construct ObjectReference for lcb_data->DatSet. */ + scl_make_objref (scl_ld, scl_ln, scl_lcb->datSet, + lcb_data->DatSet, sizeof (lcb_data->DatSet) - 1); + lcb_data->IntgPd = (ST_UINT32) scl_lcb->intgPd; + /* Construct ObjectReference for lcb_data->LogRef. */ + scl_make_objref2 (scl_ld, scl_lcb->logName, + lcb_data->LogRef, sizeof (lcb_data->LogRef) - 1); + lcb_data->LogEna = scl_lcb->logEna; + /* NOTE: "scl_lcb->reasonCode" may be read from SCL file, but it */ + /* is not in LCB (according to 61850-8-1) so just ignore it. */ + lcb_data->TrgOps.len = 6; /* Var len 6-bit bitstring */ + lcb_data->TrgOps.data[0] = scl_lcb->TrgOps[0]; /* 1 byte of data */ + } + } /* end loop */ + } +/************************************************************************/ +/* scl2_ln_init_gcb_vals */ +/* Use mvlu_find_comp_type to find the data offset of each GCB in the LN.*/ +/* Then write the SCL data there. */ +/************************************************************************/ +static ST_VOID scl2_ln_init_gcb_vals ( + SCL_INFO *scl_info, /* main struct where all SCL info stored*/ + SCL_LD *scl_ld, + SCL_LN *scl_ln) + { +ST_CHAR flatname [MAX_IDENT_LEN +1]; +SCL_GCB *scl_gcb; +MVL61850_GCB_DATA *gcb_data; /* GOOSE Control Block data */ +MVL61850_SCB_DATA *scb_data; /* GSSE Control Block data */ +RUNTIME_TYPE *comp_rt_type; /* first rt_type of component */ +ST_INT comp_rt_num; /* num of rt_types in component */ +ST_RET retcode = SD_SUCCESS; +ST_CHAR *dataptr; +SCL_GSE *scl_gse; /* GOOSE addressing info */ + + for (scl_gcb = (SCL_GCB *) list_find_last ((DBL_LNK *) scl_ln->gcbHead); + scl_gcb != NULL; + scl_gcb = (SCL_GCB *) list_find_prev ((DBL_LNK *) scl_ln->gcbHead, (DBL_LNK *) scl_gcb)) + { + /* NOTE: mvlu_find_comp_type uses flattened name without LN prefix. */ + if (scl_gcb->isGoose) /* GOOSE */ + sprintf (flatname, "GO$%s", scl_gcb->name); + else /* GSSE */ + sprintf (flatname, "GS$%s", scl_gcb->name); + retcode = mvlu_find_comp_type (scl_ln->mvl_var_assoc->type_id, + flatname, &comp_rt_type, &comp_rt_num); + if (retcode!=SD_SUCCESS) + { + SXLOG_ERR2 ("Cannot find component '%s' in var '%s'. Initial values not set.", + flatname, scl_ln->mvl_var_assoc->name); + } + else + { + dataptr = (ST_CHAR *) scl_ln->mvl_var_assoc->data + + comp_rt_type->mvluTypeInfo.offSet; + /* Use SCL info to initialize GCB data. */ + if (scl_gcb->isGoose) + { /* GOOSE */ + gcb_data = (MVL61850_GCB_DATA *) dataptr; + /* Construct ObjectReference for gcb_data->DatSet. */ + scl_make_objref (scl_ld, scl_ln, scl_gcb->datSet, + gcb_data->DatSet, sizeof (gcb_data->DatSet) - 1); + gcb_data->ConfRev = (ST_UINT32) scl_gcb->confRev; + /* 61850-8-1 maps appID to GoID */ + strcpy (gcb_data->GoID, scl_gcb->appID); + /* NOTE: NdsCom is not configured in SCL so initial value of */ + /* "gcb_data->NdsCom" is always 0. */ + if ((scl_gse = scl_gse_find (scl_info, scl_ld, scl_gcb)) != NULL) + { + /* Initialize DstAddress structure. */ + memcpy (gcb_data->DstAddress.Addr, scl_gse->MAC, CLNP_MAX_LEN_MAC); + gcb_data->DstAddress.PRIORITY = (ST_UINT8) scl_gse->VLANPRI; + gcb_data->DstAddress.VID = (ST_UINT16) scl_gse->VLANID; + gcb_data->DstAddress.APPID = (ST_UINT16) scl_gse->APPID; + } + else + MVL_LOG_ERR1 ("Cannot find GSE element to set address for GOOSE Control '%s'. DstAddress NOT INITIALIZED.", + scl_gcb->name); + } + else + { /* GSSE */ + scb_data = (MVL61850_SCB_DATA *) dataptr; + /* datSet, confRev ignored for GSSE. */ + /* 61850-8-1 maps appID to GsID */ + strcpy (scb_data->GsID, scl_gcb->appID); + if ((scl_gse = scl_gse_find (scl_info, scl_ld, scl_gcb)) != NULL) + { + /* Initialize DstAddress structure. */ + memcpy (scb_data->DstAddress.Addr, scl_gse->MAC, CLNP_MAX_LEN_MAC); + scb_data->DstAddress.PRIORITY = (ST_UINT8) scl_gse->VLANPRI; + scb_data->DstAddress.VID = (ST_UINT16) scl_gse->VLANID; + scb_data->DstAddress.APPID = (ST_UINT16) scl_gse->APPID; + } + else + MVL_LOG_ERR1 ("Cannot find GSE element to set address for GSSE Control '%s'. DstAddress NOT INITIALIZED.", + scl_gcb->name); + } + } + } /* end loop */ + } +/************************************************************************/ +/* scl2_ln_init_svcb_vals */ +/* Use mvlu_find_comp_type to find the data offset of each SVCB in the LN.*/ +/* Then write the SCL data there. */ +/************************************************************************/ +static ST_VOID scl2_ln_init_svcb_vals ( + SCL_INFO *scl_info, /* main struct where all SCL info stored*/ + SCL_LD *scl_ld, + SCL_LN *scl_ln) + { +ST_CHAR flatname [MAX_IDENT_LEN +1]; +SCL_SVCB *scl_svcb; +RUNTIME_TYPE *comp_rt_type; /* first rt_type of component */ +ST_INT comp_rt_num; /* num of rt_types in component */ +ST_RET retcode = SD_SUCCESS; +ST_CHAR *dataptr; + + for (scl_svcb = (SCL_SVCB *) list_find_last ((DBL_LNK *) scl_ln->svcbHead); + scl_svcb != NULL; + scl_svcb = (SCL_SVCB *) list_find_prev ((DBL_LNK *) scl_ln->svcbHead, (DBL_LNK *) scl_svcb)) + { + /* NOTE: mvlu_find_comp_type uses flattened name without LN prefix. */ + if (scl_svcb->multicast) + sprintf (flatname, "MS$%s", scl_svcb->name); + else + sprintf (flatname, "US$%s", scl_svcb->name); + retcode = mvlu_find_comp_type (scl_ln->mvl_var_assoc->type_id, + flatname, &comp_rt_type, &comp_rt_num); + if (retcode!=SD_SUCCESS) + { + SXLOG_ERR2 ("Cannot find component '%s' in var '%s'. Initial values not set.", + flatname, scl_ln->mvl_var_assoc->name); + } + else + { + dataptr = (ST_CHAR *) scl_ln->mvl_var_assoc->data + + comp_rt_type->mvluTypeInfo.offSet; + /* Use SCL info to initialize SVCB data. */ + if (scl_svcb->multicast) + { /* MSVCB */ + MVL61850_MSVCB_DATA *msvcb_data = (MVL61850_MSVCB_DATA *) dataptr; + msvcb_data->SvEna = SD_FALSE; /* can't be configured. Init to FALSE*/ + strcpy (msvcb_data->MsvID, scl_svcb->smvID); + /* Construct ObjectReference to initialize msvcb_data->DatSet. */ + scl_make_objref (scl_ld, scl_ln, scl_svcb->datSet, + msvcb_data->DatSet, sizeof (msvcb_data->DatSet) - 1); + msvcb_data->ConfRev = scl_svcb->confRev; + msvcb_data->SmpRate = scl_svcb->smpRate; + msvcb_data->OptFlds.len = 3; /* Var len 3-bit bitstring */ + msvcb_data->OptFlds.data[0] = scl_svcb->OptFlds[0]; /* 1 byte of data*/ + } + else + { /* USVCB */ + MVL61850_USVCB_DATA *usvcb_data = (MVL61850_USVCB_DATA *) dataptr; + usvcb_data->SvEna = SD_FALSE; /* can't be configured. Init to FALSE*/ + usvcb_data->Resv = SD_FALSE; /* can't be configured. Init to FALSE*/ + strcpy (usvcb_data->UsvID, scl_svcb->smvID); + /* Construct ObjectReference to initialize usvcb_data->DatSet. */ + scl_make_objref (scl_ld, scl_ln, scl_svcb->datSet, + usvcb_data->DatSet, sizeof (usvcb_data->DatSet) - 1); + usvcb_data->ConfRev = scl_svcb->confRev; + usvcb_data->SmpRate = scl_svcb->smpRate; + usvcb_data->OptFlds.len = 3; /* Var len 3-bit bitstring */ + usvcb_data->OptFlds.data[0] = scl_svcb->OptFlds[0]; /* 1 byte of data*/ + } + } + } /* end loop */ + } +/************************************************************************/ +/* scl2_ln_init_sgcb_vals */ +/* Use mvlu_find_comp_type to find the data offset of the SGCB in the LN.*/ +/* Then write the SCL data there. */ +/************************************************************************/ +static ST_VOID scl2_ln_init_sgcb_vals ( + SCL_INFO *scl_info, /* main struct where all SCL info stored*/ + SCL_LD *scl_ld, + SCL_LN *scl_ln) + { +ST_CHAR flatname [MAX_IDENT_LEN +1]; +RUNTIME_TYPE *comp_rt_type; /* first rt_type of component */ +ST_INT comp_rt_num; /* num of rt_types in component */ +ST_RET retcode = SD_SUCCESS; +ST_CHAR *dataptr; +MVL61850_SGCB_DATA *sgcb_data; + + /* Only 1 SGCB allowed. Don't need loop. */ + if (scl_ln->sgcb) + { + /* NOTE: mvlu_find_comp_type uses flattened name without LN prefix. */ + strcpy (flatname, "SP$SGCB"); + retcode = mvlu_find_comp_type (scl_ln->mvl_var_assoc->type_id, + flatname, &comp_rt_type, &comp_rt_num); + if (retcode!=SD_SUCCESS) + { + SXLOG_ERR2 ("Cannot find component '%s' in var '%s'. Initial values not set.", + flatname, scl_ln->mvl_var_assoc->name); + } + else + { + dataptr = (ST_CHAR *) scl_ln->mvl_var_assoc->data + + comp_rt_type->mvluTypeInfo.offSet; + /* Use SCL info to initialize SGCB data. */ + sgcb_data = (MVL61850_SGCB_DATA *) dataptr; + sgcb_data->NumOfSG = scl_ln->sgcb->numOfSGs; + sgcb_data->ActSG = scl_ln->sgcb->actSG; + } + } + } +/************************************************************************/ +/* scl2_ln_create */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +static ST_RET scl2_ln_create ( + MVL_VMD_CTRL *vmd_ctrl, + SCL_INFO *scl_info, /* main struct where all SCL info stored*/ + SCL_LD *scl_ld, + SCL_LN *scl_ln) + { +ST_INT type_id; +MVL_VAR_ASSOC *var_assoc; +OBJECT_NAME object_name; +ST_RET retcode; + + retcode = SD_FAILURE; /* assume failure */ + + type_id = scl_ln->type_id; + if (type_id < 0) + SXLOG_ERR2 ("Cannot find type='%s' for logical node='%s'", scl_ln->lnType, scl_ln->varName); + else + { + /* Construct object name from LD & LN info. */ + object_name.object_tag = DOM_SPEC; /* ALWAYS Domain specific */ + object_name.domain_id = scl_ld->domName; + object_name.obj_name.vmd_spec = scl_ln->varName; + + /* Create the MMS variable (Logical Node). */ + /* This function also allocates "var_alloc->data" where this */ + /* variable's data is stored. */ + var_assoc = mvl_var_add_alloc (vmd_ctrl, &object_name, + NULL, /* MVL_NET_INFO * */ + type_id, + NULL); /* MVL_VAR_PROC * */ + if (var_assoc == NULL) + SXLOG_ERR2 ("Cannot create LN='%s' in LD='%s'", scl_ln->varName, scl_ld->domName); + else + { + var_assoc->flags = MVL_VAR_FLAG_UCA; /* CRITICAL: must make it a UCA variable*/ + + /* NOTE: var_assoc->use_static_data flag is automatically set */ + /* by mvl_vmd_var_add because data is never NULL. */ + scl_ln->mvl_var_assoc = var_assoc; /* save var_assoc for later*/ + retcode = SD_SUCCESS; + } + } + if (retcode == SD_SUCCESS) + { + /* Set initial vals for LCB, GCB, & SCB (i.e. GSSE control block). */ + scl2_ln_init_lcb_vals (scl_info, scl_ld, scl_ln); + scl2_ln_init_gcb_vals (scl_info, scl_ld, scl_ln); + scl2_ln_init_svcb_vals (scl_info, scl_ld, scl_ln); + scl2_ln_init_sgcb_vals (scl_info, scl_ld, scl_ln); + } + return (retcode); + } +/************************************************************************/ +/* scl2_dataset_create */ +/* Create one DataSet (SCL_DATASET) for this Logical Node (SCL_LN). */ +/* A DataSet maps to a MMS NamedVariableList (NVL). */ +/* The MMS NVL name follows the form "LogicalNodeName$DataSetName". */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +static ST_RET scl2_dataset_create ( + MVL_VMD_CTRL *vmd_ctrl, + SCL_LD *scl_ld, + SCL_LN *scl_ln, + SCL_DATASET *scl_dataset) + { +OBJECT_NAME nvl_obj; +MVL_NVLIST_CTRL *nvlist_ctrl; +ST_INT num_var = 0; +OBJECT_NAME *var_obj; /* array of var names */ +SCL_FCDA *scl_fcda; +ST_RET ret; +/* allow extra char in var_name so strncat can go beyond limit. If it does, return error.*/ +ST_CHAR *var_name_buf; /* one buf allocated to hold all var names */ +ST_CHAR *var_name; /* ptr to current name being constructed */ +ST_CHAR *dot_ptr; /* ptr to '.' within var_name */ +ST_CHAR nvl_name [MAX_IDENT_LEN+1]; /* one extra byte for NULL */ + + ret = SD_SUCCESS; /* assume success */ + + /* Construct NVL object name from LD, LN, and DataSet info. */ + if (strlen (scl_ln->prefix) + strlen (scl_ln->lnClass) + strlen (scl_ln->inst) + + strlen (scl_dataset->name) + 1 > MAX_IDENT_LEN) + { + SXLOG_ERR1 ("Constructed NVL name would be too long for dataset '%s'.", scl_dataset->name); + return (SD_FAILURE); + } + sprintf (nvl_name, "%s%s%s$%s", scl_ln->prefix, scl_ln->lnClass, scl_ln->inst, scl_dataset->name); + nvl_obj.object_tag = DOM_SPEC; /* ALWAYS Domain specific */ + nvl_obj.domain_id = scl_ld->domName; + nvl_obj.obj_name.vmd_spec = nvl_name; /* use constructed NVL name */ + + /* Go through list once just to count number of variables. */ + for (scl_fcda = (SCL_FCDA *) list_find_last ((DBL_LNK *) scl_dataset->fcdaHead); + scl_fcda != NULL; + scl_fcda = (SCL_FCDA *) list_find_prev ((DBL_LNK *) scl_dataset->fcdaHead, (DBL_LNK *) scl_fcda)) + { + num_var++; + } + /* Allocate var_obj array. */ + var_obj = chk_calloc (num_var, sizeof (OBJECT_NAME)); + + /* NOTE: this is a bit tricky. OBJECT_NAME struct contains only a ptr + * to name, no storage. Need to allocate storage for names. Here we + * allocate one big buffer for all names. In the loop below, + * we use part of this buffer for each name. + */ + var_name_buf = chk_calloc (num_var, MAX_IDENT_LEN+2); /* Note +2 for NULL plus extra char*/ + + /* Go through list again to fill in var_obj array. */ + num_var = 0; + for (scl_fcda = (SCL_FCDA *) list_find_last ((DBL_LNK *) scl_dataset->fcdaHead); + scl_fcda != NULL; + scl_fcda = (SCL_FCDA *) list_find_prev ((DBL_LNK *) scl_dataset->fcdaHead, (DBL_LNK *) scl_fcda)) + { + /* Set "var_name" pointing to proper section of big buffer. */ + var_name = var_name_buf + num_var*(MAX_IDENT_LEN+2); + /* Fill in "var_name". */ + /* NOTE: allow 1 extra char. If it is used, name is too long, so return error.*/ + strncpy (var_name, scl_fcda->prefix, MAX_IDENT_LEN+1); + strncat_maxstrlen (var_name, scl_fcda->lnClass, MAX_IDENT_LEN+1); + strncat_maxstrlen (var_name, scl_fcda->lnInst, MAX_IDENT_LEN+1); + strncat_maxstrlen (var_name, "$", MAX_IDENT_LEN+1); + strncat_maxstrlen (var_name, scl_fcda->fc, MAX_IDENT_LEN+1); + if (strlen (scl_fcda->doName)) + { + strncat_maxstrlen (var_name, "$", MAX_IDENT_LEN+1); + strncat_maxstrlen (var_name, scl_fcda->doName, MAX_IDENT_LEN+1); + } + if (strlen (scl_fcda->daName)) + { + strncat_maxstrlen (var_name, "$", MAX_IDENT_LEN+1); + strncat_maxstrlen (var_name, scl_fcda->daName, MAX_IDENT_LEN+1); + } + /* doName or daName may contain '.'. Each '.' must be replaced with '$'.*/ + dot_ptr = var_name; + while ((dot_ptr = strchr (dot_ptr, '.')) != NULL) + *dot_ptr++ = '$'; + if (strlen (var_name) > MAX_IDENT_LEN) + { + SXLOG_ERR1 ("Variable name generated from FCDA info too long '%s'", var_name); + ret = SD_FAILURE; + break; /* stop looping */ + } + + /* var_name generated, now fill in this "var_obj". */ + var_obj[num_var].object_tag = DOM_SPEC; /* ALWAYS Domain specific */ + var_obj[num_var].domain_id = scl_fcda->domName; + var_obj[num_var].obj_name.vmd_spec = var_name; + num_var++; + } + + if (ret == SD_SUCCESS) + { + nvlist_ctrl = mvl_vmd_nvl_add (vmd_ctrl, &nvl_obj, NULL, num_var, var_obj, SD_TRUE); + if (nvlist_ctrl) + ret = SD_SUCCESS; + else + ret = SD_FAILURE; + } + /* NOTE: can free these now because mvl_vmd_nvl_add copied this info.*/ + chk_free (var_obj); + chk_free (var_name_buf); + return (ret); + } +/************************************************************************/ +/* scl2_dataset_create_all */ +/* Create all DataSets (SCL_DATASET) for this Logical Node (SCL_LN). */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +static ST_RET scl2_dataset_create_all ( + MVL_VMD_CTRL *vmd_ctrl, + SCL_LD *scl_ld, + SCL_LN *scl_ln) + { +SCL_DATASET *scl_dataset; +ST_RET ret; + + ret = SD_SUCCESS; /* assume success */ + + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_dataset = (SCL_DATASET *) list_find_last ((DBL_LNK *) scl_ln->datasetHead); + scl_dataset != NULL; + scl_dataset = (SCL_DATASET *) list_find_prev ((DBL_LNK *) scl_ln->datasetHead, (DBL_LNK *) scl_dataset)) + { +ST_UINT32 mvl_debug_sel_save; + + mvl_debug_sel_save = mvl_debug_sel; + mvl_debug_sel &= ~MVLLOG_NERR; + ret = scl2_dataset_create (vmd_ctrl, scl_ld, scl_ln, scl_dataset); + mvl_debug_sel = mvl_debug_sel_save; + if (ret) + { + if (!scl_debug_mode) + break; /* if one fails, stop processing */ + + ++scl_debug_mode_error_count; + } + else + { + SXLOG_FLOW3 ("scl2_dataset_create DONE for '%s' (LD=%s LN=%s)", + scl_dataset->name, scl_ld->domName, scl_ln->varName); + } + } + return (ret); + } +/************************************************************************/ +/* init_basrcb_data */ +/* Use other info in scl_rcb to initialize data in basrcb. */ +/************************************************************************/ +static ST_VOID init_basrcb_data ( + MVLU_RPT_CTRL *rpt_ctrl, + SCL_RCB *scl_rcb) + { + MVLU_BASRCB *basrcb; + + basrcb = &rpt_ctrl->only_client.basrcb; + + /* If RptID configured in SCL, overwrite default RptID generated by mvlu_create_rpt_ctrl */ + if (strlen (scl_rcb->rptID)) + strncpy_safe (basrcb->RptID, scl_rcb->rptID, sizeof (basrcb->RptID)-1); + /* Use other info in scl_rcb to initialize data in basrcb */ + /* NOTE: scl_rcb->name, scl_rcb->desc not used. */ + basrcb->IntgPd = scl_rcb->intgPd; + basrcb->BufTim = scl_rcb->bufTime; + + basrcb->TrgOps.len = 6; /* BVstring. Assume max len*/ + basrcb->TrgOps.data [0] = scl_rcb->TrgOps [0]; + /*renxiaobao Ôö¼Ó*/ + basrcb->TrgOps.data [0]|= TRGOPS_BITNUM_GENERAL_INTERROGATION; + + basrcb->OptFlds.data_1 [0] = scl_rcb->OptFlds [0]; + basrcb->OptFlds.data_1 [1] = scl_rcb->OptFlds [1]; + if (!scl_rcb->buffered) + { /* For URCB, 61850-8-1 says to ignore buffer-overflow, entryID bits, so clear them*/ + BSTR_BIT_SET_OFF (basrcb->OptFlds.data_1, OPTFLD_BITNUM_BUFOVFL); + BSTR_BIT_SET_OFF (basrcb->OptFlds.data_1, OPTFLD_BITNUM_ENTRYID); + } + } +/************************************************************************/ +/* init_rpt_ctrl */ +/* Used only by loop in "scl2_rcb_create". */ +/************************************************************************/ +ST_RET init_rpt_ctrl ( + SCL_INFO *scl_info, /* main struct where all SCL info stored*/ + SCL_RCB *scl_rcb, + MVL_NVLIST_CTRL *nvl, + MVL_VAR_ASSOC *base_va, + ST_CHAR *basrcb_var_namexx, + ST_CHAR *basrcb_type_namexx, + ST_UINT reportScanRate) /* report scan rate (millisec) */ + { +ST_INT buftim_action; +ST_INT set_flags; /* flags for mvlu_set_leaf_param_name */ +ST_RET ret; +ST_CHAR leaf_name [MAX_IDENT_LEN + 1]; +MVLU_RPT_CTRL *rpt_ctrl; + + /* DEBUG: nothing in SCL to set buftim_action. Is there another way to get this info? */ + buftim_action = MVLU_RPT_BUFTIM_SEND_NOW; + + /* Set all leaf functions required to implement RCB. + * NOTE: these leaf functions replace the default leaf functions + * set by "u_set_all_leaf_functions" when the datatype was created. + */ + + /* Use same flags for all leafs */ + set_flags = MVLU_SET_RD_FUN | MVLU_SET_WR_FUN | MVLU_SET_REF; + + /* Start with good return value & OR all returns together. If ANY call + * to mvlu_set_leaf_param_name fails, this function will fail. + */ + ret = SD_SUCCESS; + /* CRITICAL: len of basrcb_type_name chked above, so none of these "sprintf"s + * will cause leaf_name to be exceeded. + */ + sprintf (leaf_name, "%s$RptID", basrcb_type_namexx); + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_rptid_rd_ind_fun", + "mvlu_rptid_wr_ind_fun", + ""); + sprintf (leaf_name, "%s$RptEna", basrcb_type_namexx); + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_rptena_rd_ind_fun", + "mvlu_rptena_wr_ind_fun", + ""); + if (!scl_rcb->buffered) /* "Resv" only for Unbuffered */ + { + sprintf (leaf_name, "%s$Resv", basrcb_type_namexx); + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_resv_rd_ind_fun", + "mvlu_resv_wr_ind_fun", + ""); + } + sprintf (leaf_name, "%s$DatSet", basrcb_type_namexx); + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_datsetna_rd_ind_fun", + "mvl61850_datset_wr_ind", + ""); + sprintf (leaf_name, "%s$ConfRev", basrcb_type_namexx); + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_confrev_rd_ind", + "u_no_write_allowed", /* NOT writable */ + ""); + sprintf (leaf_name, "%s$OptFlds", basrcb_type_namexx); + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_optflds_rd_ind_fun", + "mvlu_optflds_wr_ind_fun", + ""); + sprintf (leaf_name, "%s$BufTm", basrcb_type_namexx); + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_buftim_rd_ind_fun", + "mvlu_buftim_wr_ind_fun", + ""); + sprintf (leaf_name, "%s$SqNum", basrcb_type_namexx); + if (scl_rcb->buffered) + { /* Buffered uses INT16U for SqNum */ + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_sqnum_int16u_rd_ind_fun", + "u_no_write_allowed", + ""); + } + else + { /* Unbuffered uses INT8U for SqNum */ + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_sqnum_rd_ind_fun", + "u_no_write_allowed", + ""); + } + sprintf (leaf_name, "%s$TrgOps", basrcb_type_namexx); + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_trgops_rd_ind_fun", + "mvlu_trgops_wr_ind_fun", + ""); + sprintf (leaf_name, "%s$IntgPd", basrcb_type_namexx); + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_intgpd_rd_ind_fun", + "mvlu_intgpd_wr_ind_fun", + ""); + sprintf (leaf_name, "%s$GI", basrcb_type_namexx); + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_gi_rd_ind", + "mvlu_gi_wr_ind", + ""); + if (scl_rcb->buffered) /* only for Buffered */ + { + sprintf (leaf_name, "%s$PurgeBuf", basrcb_type_namexx); + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_purgebuf_rd_ind", + "mvlu_purgebuf_wr_ind", + ""); + sprintf (leaf_name, "%s$EntryID", basrcb_type_namexx); + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_entryid_rd_ind", + "mvlu_entryid_wr_ind", + ""); + sprintf (leaf_name, "%s$TimeofEntry", basrcb_type_namexx); + ret |= mvlu_set_leaf_param_name2 (base_va->type_id, set_flags, + leaf_name, + "mvlu_timeofentry_rd_ind", + "u_no_write_allowed", /* NOT writable */ + ""); + } /* only for Buffered */ + + if (ret) + { + SXLOG_ERR1 ("At least one leaf function could not be found for RCB '%s'", basrcb_var_namexx); + if (scl_debug_mode) + { + ++scl_debug_mode_error_count; + return (SD_SUCCESS); /* Don't let this stop us for now ... */ + } + return (ret); + } + + /* NOTE: nvl may be NULL. If so, it must be set later when client writes DatSet.*/ + rpt_ctrl = mvl61850_create_rpt_ctrl (basrcb_var_namexx, nvl, + base_va, + (scl_rcb->buffered ? RCB_TYPE_IEC_BRCB : RCB_TYPE_IEC_URCB), + buftim_action, + scl_info->brcb_bufsize, /* BRCB bufsize */ + scl_rcb->confRev); /* ConfRev */ + if (rpt_ctrl) + { + init_basrcb_data (rpt_ctrl, scl_rcb); /* use scl_rcb to init data*/ + rpt_ctrl->scan_rate = (ST_DOUBLE) reportScanRate; /* init scan rate*/ + ret = SD_SUCCESS; + /* renxiaobao ±¨¸æ*/ + if(scl_rcb->buffered==RCB_TYPE_IEC_BRCB) BRCB_NUM++; + else URCB_NUM++; + } + else + ret = SD_FAILURE; + return (ret); + } +/************************************************************************/ +/* scl2_rcb_create */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +static ST_RET scl2_rcb_create ( + MVL_VMD_CTRL *vmd_ctrl, + SCL_INFO *scl_info, + SCL_LD *scl_ld, + SCL_LN *scl_ln, + SCL_RCB *scl_rcb, + ST_UINT reportScanRate) /* report scan rate (millisec) */ + { +ST_RET ret = SD_FAILURE; +ST_CHAR basrcb_var_name [MAX_IDENT_LEN + 1]; +ST_CHAR basrcb_type_name [MAX_IDENT_LEN + 1]; /* for setting leaf functions*/ +ST_CHAR basrcb_var_namexx [MAX_IDENT_LEN + 1]; /* name plus 2 char index*/ +ST_CHAR basrcb_type_namexx [MAX_IDENT_LEN + 1]; /* name plus 2 char index*/ +MVL_VAR_ASSOC *base_va; +OBJECT_NAME base_var_oname; +OBJECT_NAME nvl_oname; +MVL_NVLIST_CTRL *nvl; +SCL_DATASET *scl_dataset; +ST_CHAR nvl_name [MAX_IDENT_LEN+1]; +ST_INT index, maxClient; + + /* Initialize basrcb_type_name. Add $BR.. or $RP.. later. */ + /* First part of name shouldn't matter now that init_rpt_ctrl uses */ + /* mvlu_set_leaf_param_name2 to set leaf params. Use simple name. */ + strcpy (basrcb_type_name, "b"); + + /* Generate basrcb_var_name from SCL info. The code below should generate a unique + * basrcb_var_name for every RCB in this LN. + */ + strcpy (basrcb_var_name, scl_ln->varName); /* never too long */ + if (scl_rcb->buffered) + { + strncat_maxstrlen (basrcb_var_name, "$BR$", MAX_IDENT_LEN); + strncat_maxstrlen (basrcb_type_name, "$BR$", MAX_IDENT_LEN); + } + else + { + strncat_maxstrlen (basrcb_var_name, "$RP$", MAX_IDENT_LEN); + strncat_maxstrlen (basrcb_type_name, "$RP$", MAX_IDENT_LEN); + } + /* Add RCB name (read from SCL file). */ + strncat_maxstrlen (basrcb_var_name, scl_rcb->name, MAX_IDENT_LEN); + strncat_maxstrlen (basrcb_type_name, scl_rcb->name, MAX_IDENT_LEN); + + /* Make sure there's room for 2 char "index" plus longest suffix */ + if (strlen (basrcb_var_name) + 2 + sizeof("$TimeOfEntry") > MAX_IDENT_LEN) + { + SXLOG_ERR1 ("BasRCB variable name '%s' too long", basrcb_var_name); + return (SD_FAILURE); + } + if (strlen (basrcb_type_name) + 2 + sizeof("$TimeOfEntry") > MAX_IDENT_LEN) + { + SXLOG_ERR1 ("BasRCB type name '%s' too long", basrcb_type_name); + return (SD_FAILURE); + } + + /* If "datSet" is not NULL, try to find it. */ + if (scl_rcb->datSet[0] != '\0') + { + scl_dataset = scl_find_dataset (scl_ln, scl_rcb->datSet); + if (scl_dataset == NULL) + { + SXLOG_ERR1 ("scl2_rcb_create: datSet='%s' not found", scl_rcb->datSet); + return (SD_FAILURE); + } + /* Construct NVL object name from LD, LN, and DataSet info. */ + if (strlen (scl_ln->prefix) + strlen (scl_ln->lnClass) + strlen (scl_ln->inst) + + strlen (scl_rcb->datSet) + 1 > MAX_IDENT_LEN) + { + SXLOG_ERR1 ("Constructed NVL name would be too long for dataset '%s'.", scl_rcb->datSet); + return (SD_FAILURE); + } + sprintf (nvl_name, "%s%s%s$%s", scl_ln->prefix, scl_ln->lnClass, scl_ln->inst, scl_rcb->datSet); + nvl_oname.object_tag = DOM_SPEC; + nvl_oname.domain_id = scl_ld->domName; /* domain name */ + nvl_oname.obj_name.item_id = nvl_name; /* use constructed NVL name */ + nvl = mvl_vmd_find_nvl (vmd_ctrl, &nvl_oname, + NULL); /* DOM_SPEC so net_info doesn't matter*/ + if (nvl == NULL) + { + SXLOG_ERR3 ("Cannot find NVL '%s' in domain '%s' to create RCB '%s'", + nvl_oname.obj_name.item_id, + nvl_oname.domain_id, + basrcb_var_name); + return (SD_FAILURE); + } + } + else + nvl = NULL; /* datSet="" so can't find NVL */ + + /* Find the "base_va". Needed as arg to mvlu_create_rpt_ctrl. */ + base_var_oname.object_tag = DOM_SPEC; + base_var_oname.domain_id = scl_ld->domName; + + base_var_oname.obj_name.item_id = scl_ln->varName; + base_va = mvl_vmd_find_var (vmd_ctrl, &base_var_oname, + NULL); /* DOM_SPEC so net_info doesn't matter*/ + if (base_va == NULL) + { + SXLOG_ERR1 ("Cannot find base variable='%s' for RCB", scl_ln->varName); + return (SD_FAILURE); + } + + assert (scl_rcb->maxClient > 0 && scl_rcb->maxClient <= 99); /* was checked during parsing */ + + maxClient = scl_rcb->maxClient; /* use value of "RptEnabled max" in SCL*/ + + /* Create "maxClient" RCBs, each with "index" as a suffix. */ + for (index = 1; index <= maxClient; index++) + { + if (rcb_name_no_index && maxClient == 1) + { /* do NOT add suffix */ + sprintf (basrcb_var_namexx, "%s", basrcb_var_name); + sprintf (basrcb_type_namexx, "%s", basrcb_type_name); + } + else + { + /* Add "index" suffix to var and type name. */ + sprintf (basrcb_var_namexx, "%s%02d", basrcb_var_name, index); + sprintf (basrcb_type_namexx, "%s%02d", basrcb_type_name, index); + } + + ret = init_rpt_ctrl (scl_info, scl_rcb, nvl, base_va, + basrcb_var_namexx, basrcb_type_namexx, reportScanRate); + if (ret) + break; /* stop looping on any error. */ + } /* end of loop */ + return (ret); + } +/************************************************************************/ +/* scl2_rcb_create_all */ +/* Create all Report Control Blocks (SCL_RCB) for this Logical Node (SCL_LN).*/ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +static ST_RET scl2_rcb_create_all ( + MVL_VMD_CTRL *vmd_ctrl, + SCL_INFO *scl_info, + SCL_LD *scl_ld, + SCL_LN *scl_ln, + ST_UINT reportScanRate) /* report scan rate (millisec) */ + { +SCL_RCB *scl_rcb; +ST_RET ret; + + ret = SD_SUCCESS; /* assume success */ + + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_rcb = (SCL_RCB *) list_find_last ((DBL_LNK *) scl_ln->rcbHead); + scl_rcb != NULL; + scl_rcb = (SCL_RCB *) list_find_prev ((DBL_LNK *) scl_ln->rcbHead, (DBL_LNK *) scl_rcb)) + { + ret = scl2_rcb_create (vmd_ctrl, scl_info, scl_ld, scl_ln, scl_rcb, + reportScanRate); + if (ret) + break; /* if one fails, stop processing */ + else + SXLOG_FLOW3 ("scl2_rcb_create DONE for '%s' (LD=%s LN=%s)", + scl_rcb->name, scl_ld->domName, scl_ln->varName); + } + return (ret); + } +/************************************************************************/ +/* convert_initial_value */ +/* NOTE: This function does special conversion for "Enum" and "Boolean" */ +/* values. For all other types, it just calls sxaTextToLocal. */ +/************************************************************************/ +ST_RET convert_initial_value (SCL_INFO *scl_info, + SCL_LD *scl_ld, + SCL_LN *scl_ln, + ST_CHAR *flattened_name, /* flattened variable name */ + RUNTIME_CTRL *rt_ctrl, + ST_INT comp_rt_index, /* index to this comp in array */ + ST_VOID *data, /* Pointer to converted data */ + ST_CHAR *valstring) /* string to be converted. */ + { +ST_RET ret = SD_SUCCESS; +RUNTIME_TYPE *comp_rt_type; +SCL_ENUMTYPE *scl_enumtype; +RESERVED_INFO *reserved_info; /* ptr to array of extra type info. */ +short i; +char *ptr0,*ptr1; + + /* Cast "reserved_1" pointer to the type we allocated. */ + reserved_info = (RESERVED_INFO *) rt_ctrl->reserved_1; + + comp_rt_type = rt_ctrl->rt_first + comp_rt_index; + scl_enumtype = reserved_info[comp_rt_index].scl_enumtype; /* may be NULL*/ + + /* Component must be primitive. */ + assert (ms_is_rt_prim (comp_rt_type)); + if (comp_rt_type->el_tag == RT_INTEGER && scl_enumtype) /* must be Enum */ + { + /* Try to match text with EnumType definition.*/ + SCL_ENUMVAL *scl_enumval; + ST_BOOLEAN found = SD_FALSE; + for (scl_enumval = (SCL_ENUMVAL *) list_find_last ((DBL_LNK *) scl_enumtype->enumvalHead); + scl_enumval != NULL; + scl_enumval = (SCL_ENUMVAL *) list_find_prev ((DBL_LNK *) scl_enumtype->enumvalHead, (DBL_LNK *) scl_enumval)) + { + if (strcmp (scl_enumval->EnumVal, valstring) == 0) + { + *(ST_INT8*)data = (ST_INT8) scl_enumval->ord; + found = SD_TRUE; + break; + } + } + if (!found) + { + SXLOG_ERR3("%s$%s does not match any EnumVal. Trying numeric conversion. %s",scl_ln->varName,flattened_name,valstring); + /* SXLOG_ERR1 ("Val='$s' does not match any EnumVal. Trying numeric conversion.",valstring);*/ + /* This is not required by IEC 61850, but if valstring does not match */ + /* any EnumVal and it starts with a digit, do numeric conversion. */ + if (isdigit (valstring[0])) + ret = sxaTextToLocal (valstring, data, 1, /* rt_num always 1 (primitive) */ + comp_rt_type); + else + ret = SD_FAILURE; + + + + + } + } + else if (comp_rt_type->el_tag == RT_BOOL) + { /* convert boolean (may be "0", "1", "true", or "false") */ + if (strcmp (valstring, "true") == 0 || strcmp (valstring, "1") == 0) + *(ST_INT8 *)data = 1; + else if (strcmp (valstring, "false") == 0 || strcmp (valstring, "0") == 0) + *(ST_INT8 *)data = 0; + else + ret = SD_FAILURE; + } + /* Do special checking for visible strings. */ + else if (comp_rt_type->el_tag == RT_VISIBLE_STRING) + { + ST_CHAR *ptr; + /* Visible string must not contain any control chars. */ + for (ptr = valstring; *ptr!=0; ptr++) + { + if (*ptr < ' ') /* Check that character is not a control char. */ + { + SXLOG_ERR1 ("Illegal character (0x%02x) in visible string", + (ST_UINT)(ST_UCHAR) *ptr); /* 2 casts to avoid sign extension*/ + ret = SD_FAILURE; + break; /* stop on first error */ + return SD_SUCCESS; /*renxiaobao da³õʼ»¯*/ + } + } + if (ret == SD_SUCCESS) + { + if (comp_rt_type->u.p.el_len < 0 /* variable len */ + && strlen (valstring) > (size_t) abs (comp_rt_type->u.p.el_len)) + { + SXLOG_ERR2 ("String '%s' exceeds max len '%d'", + valstring, abs (comp_rt_type->u.p.el_len)); + ret = SD_FAILURE; + return SD_SUCCESS; /*renxiaobao da³õʼ»¯*/ + } + else if (comp_rt_type->u.p.el_len >= 0 /* fixed len */ + && strlen (valstring) != (size_t) comp_rt_type->u.p.el_len) + { + /* Shouldn't get here because no fixed len in SCL, but just in case..*/ + SXLOG_ERR2 ("String '%s' does not match fixed len '%d'", + valstring, comp_rt_type->u.p.el_len); + ret = SD_FAILURE; + return SD_SUCCESS; /*renxiaobao da³õʼ»¯*/ + } + else + strcpy (data, valstring); /* all is ok, so copy string*/ + } + } /* end RT_VISIBLE_STRING */ + /*renxiaobao UTF8±àÂë*/ + else if (comp_rt_type->el_tag == RT_UTF8_STRING) + { + ptr0 = data; + ptr1 = valstring; + for(i=0;((iel_size)&&ptr1[i]);i++) + { + ptr0[i] = ptr1[i]; + } + } + else + { /* handle all other element types */ + ret = sxaTextToLocal (valstring, data, 1, /* rt_num always 1 (primitive) */ + comp_rt_type); + } + if (ret) + { /* Our conversion code failed. Let the user try. */ + SCL2_IV_TRANSLATE_CTRL translate_ctrl; + memset (&translate_ctrl, 0, sizeof (SCL2_IV_TRANSLATE_CTRL)); + + translate_ctrl.scl_info = scl_info; + translate_ctrl.scl_ld = scl_ld; + translate_ctrl.scl_ln = scl_ln; + translate_ctrl.valText = valstring; + translate_ctrl.attrib = flattened_name; + translate_ctrl.dest = data; + translate_ctrl.numRt = 1; /* always 1 (primitive) */ + translate_ctrl.rtHead = comp_rt_type; + + ret = u_mvl_scl_set_initial_value (&translate_ctrl);/* call user funct*/ + } + return (ret); + } + +/************************************************************************/ +/* scl2_dai_set_value */ +/* Set initial data value from DAI input from SCL file. */ +/* Use sxaTextToLocal to convert the text to data. */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +int sAddr_num=0,sAddr_num_bak; +static ST_RET scl2_dai_set_value (SCL_INFO *scl_info, + SCL_LD *scl_ld, + SCL_LN *scl_ln, + SCL_DAI *scl_dai) + { +ST_CHAR fixed_name [MAX_IDENT_LEN +1]; +ST_CHAR fixed_name1 [MAX_IDENT_LEN +1]; +ST_CHAR leaf_name [MAX_IDENT_LEN +1]; +ST_RET ret = SD_FAILURE; +MVL_VAR_ASSOC *var; /* MVL Variable Association created from LN info*/ +RUNTIME_TYPE *comp_rt_type; /* first rt_type of component */ +RUNTIME_TYPE *comp_rt_type1=0; +ST_INT comp_rt_num; /* num of rt_types in component */ +ST_UINT32 mvl_debug_sel_save; +MVL_TYPE_CTRL *type_ctrl; +DATA_MAP_LINK *data_map; +ST_CHAR *LeafToFind; +ST_CHAR leafname [MAX_IDENT_LEN +1]; +unsigned char *pdat; + + /* It seems strange but "Val" is optional for DAI (i.e. Instantiated */ + /* Data Attribute with no value). If "Val" not present, do nothing. */ + /* //if (scl_dai->Val == NULL) + //{ + // SXLOG_FLOW2 ("scl2_dai_set_value: 'Val' not present for attribute '%s' in '%s'. Do nothing.", + // scl_dai->flattened, scl_ln->varName); + // return (SD_SUCCESS); // nothing to do, so stop now + //}*/ + + var = scl_ln->mvl_var_assoc; + if (strlen (scl_dai->flattened) <= (MAX_IDENT_LEN-3)) + { + /* Turn off false NERR log messages */ + mvl_debug_sel_save = mvl_debug_sel; + mvl_debug_sel &= ~MVLLOG_NERR; + + /* Find the attribute type. Don't know the FC, so try all possible */ + /* FC (i.e."ST" "MX" "CO" "SP" "SG" "SE" "SV" "CF" "DC" or "EX"). */ + do /* use "do-while" loop only so we can break out on success*/ + { + strcpy (fixed_name, "ST$"); /* Try "ST" first. */ + strcat (fixed_name, scl_dai->flattened); + if ((ret = mvlu_find_comp_type (var->type_id, fixed_name, &comp_rt_type, &comp_rt_num)) == SD_SUCCESS) + break; /* found it. done */ + + strncpy (fixed_name, "MX", 2); /* replace FC prefix*/ + if ((ret = mvlu_find_comp_type (var->type_id, fixed_name, &comp_rt_type, &comp_rt_num)) == SD_SUCCESS) + break; /* found it. done */ + + strncpy (fixed_name, "CO", 2); /* replace prefix*/ + if ((ret = mvlu_find_comp_type (var->type_id, fixed_name, &comp_rt_type, &comp_rt_num)) == SD_SUCCESS) + break; /* found it. done */ + + strncpy (fixed_name, "SP", 2); /* replace prefix*/ + if ((ret = mvlu_find_comp_type (var->type_id, fixed_name, &comp_rt_type, &comp_rt_num)) == SD_SUCCESS) + break; /* found it. done */ + + strncpy (fixed_name, "SG", 2); /* replace prefix*/ + if ((ret = mvlu_find_comp_type (var->type_id, fixed_name, &comp_rt_type, &comp_rt_num)) == SD_SUCCESS) + { + /*renxiaobao Êý¾ÝÓ³Éä*/ + strcpy (fixed_name1, "SE$"); /* Try "ST" first. */ + strcat (fixed_name1, scl_dai->flattened); + if ((ret = mvlu_find_comp_type (var->type_id, fixed_name1, &comp_rt_type1, &comp_rt_num)) != SD_SUCCESS) + { + printf("%s mvlu_find_comp_type error...\n",fixed_name1); + } + break; /* found it. done */ + } + /* + //strncpy (fixed_name, "SE", 2); // replace prefix + //if ((ret = mvlu_find_comp_type (var->type_id, fixed_name, &comp_rt_type, &comp_rt_num)) == SD_SUCCESS) + //break; found it. done + */ + strncpy (fixed_name, "SV", 2); /* replace prefix*/ + if ((ret = mvlu_find_comp_type (var->type_id, fixed_name, &comp_rt_type, &comp_rt_num)) == SD_SUCCESS) + break; /* found it. done */ + + strncpy (fixed_name, "CF", 2); /* replace prefix*/ + if ((ret = mvlu_find_comp_type (var->type_id, fixed_name, &comp_rt_type, &comp_rt_num)) == SD_SUCCESS) + break; /* found it. done */ + + strncpy (fixed_name, "DC", 2); /* replace prefix*/ + if ((ret = mvlu_find_comp_type (var->type_id, fixed_name, &comp_rt_type, &comp_rt_num)) == SD_SUCCESS) + break; /* found it. done */ + + strncpy (fixed_name, "EX", 2); /* replace prefix*/ + if ((ret = mvlu_find_comp_type (var->type_id, fixed_name, &comp_rt_type, &comp_rt_num)) == SD_SUCCESS) + break; /* found it. done */ + } while (0); /* end of do-while loop */ + + /* Restore MVL log mask settings */ + mvl_debug_sel = mvl_debug_sel_save; + } + /*renxiaobao Êý¾ÝÓ³Éä*/ + if(strlen(scl_dai->sAddr)) + { + sAddr_num++; + sAddr_num_bak = sAddr_num; + sprintf(leaf_name,"%s$%s",scl_ln->varName,fixed_name); + data_map = chk_calloc (1, sizeof (DATA_MAP_LINK)); + +// logprint("%s",leaf_name); + + strcpy(data_map->leaf,leaf_name); + strcpy(data_map->ldevice,scl_ld->domName); + strcpy(data_map->usr_data_info,scl_dai->sAddr); + list_add_last (&DATA_MAP_saddr, data_map); + strcpy(leafname,leaf_name); + LeafToFind = strstr(leafname,"$SG$"); + if(LeafToFind) + { + strncpy(LeafToFind,"$SE$",4); + sAddr_num++; + data_map = chk_calloc (1, sizeof (DATA_MAP_LINK)); + strcpy(data_map->leaf,leafname); + strcpy(data_map->ldevice,scl_ld->domName); + strcpy(data_map->usr_data_info,scl_dai->sAddr); + list_add_last (&DATA_MAP_saddr, data_map); + } + } + /* Tried all possible FC. Did we find a match. */ + if (ret != SD_SUCCESS) + { + SXLOG_ERR2 ("scl2_dai_set_value: Attribute '%s' in '%s' not found.", + scl_dai->flattened, scl_ln->varName); + if (strchr (scl_dai->flattened, '[') != NULL) + SXLOG_CERR0 ("Initialization of array elements not yet supported."); + } + else if (comp_rt_num !=1) + { + SXLOG_ERR2 ("scl2_dai_set_value: Attribute '%s' in '%s' not a primitive type.", + scl_dai->flattened, scl_ln->varName); + ret = SD_FAILURE; + } + if(ret == SD_SUCCESS) + { + /*renxiaobao Êý¾ÝÓ³Éä*/ + if(strlen(scl_dai->sAddr)) + { + pdat = (unsigned char*)(var->data)+comp_rt_type->mvluTypeInfo.offSet; + *pdat = ((sAddr_num_bak-1)/1000)+0x80; + if(scl_dai->Val != NULL) + { + printf("warning:scl_dai sAddr and Val both exist(%s %s)...",scl_dai->sAddr,scl_dai->Val); + } + if(comp_rt_type1) + { + pdat = (unsigned char*)(var->data)+comp_rt_type1->mvluTypeInfo.offSet; + *pdat = ((sAddr_num-1)/1000)+0x80; + } + } + else if(scl_dai->Val != NULL) + { + type_ctrl = mvl_type_ctrl_find (var->type_id); + ret = convert_initial_value (scl_info, scl_ld, scl_ln, fixed_name, + type_ctrl->rt_ctrl, + comp_rt_type - type_ctrl->rt_ctrl->rt_first, /* index to this comp*/ + (ST_INT8*)(var->data)+comp_rt_type->mvluTypeInfo.offSet, + scl_dai->Val); + } + } + if (ret == SD_SUCCESS) + { + SXLOG_FLOW3 ("scl2_dai_set_value: Val '%s' conversion for '%s$%s' SUCCESSFUL", + scl_dai->Val, scl_ln->varName, fixed_name); + } + else + { + SXLOG_ERR3 ("scl2_dai_set_value: Val '%s' conversion for '%s$%s' FAILED", + scl_dai->Val, scl_ln->varName, fixed_name); + printf ("scl2_dai_set_value: Val '%s' conversion for '%s$%s' FAILED",scl_dai->Val, scl_ln->varName, fixed_name); + } + + if (scl_debug_mode) + { + if (ret != SD_SUCCESS) + ++scl_debug_mode_error_count; + + return (SD_SUCCESS); /* Don't let this stop us for now ... */ + } + return (ret); + } + +/************************************************************************/ +/* scl2_da_or_bda_set_value_all */ +/* NOTE: the same Val text might get converted many times by this */ +/* function, but not enough info available to do conversion before now. */ +/************************************************************************/ +static ST_RET scl2_da_or_bda_set_value_all (SCL_INFO *scl_info, + SCL_LD *scl_ld, + SCL_LN *scl_ln) + { +ST_RET ret; +MVL_TYPE_CTRL *type_ctrl; +RUNTIME_TYPE *rt_type; +ST_INT rt_idx; /* index into RUNTIME_TYPE array. */ +RESERVED_INFO *reserved_info; /* ptr to array of extra type info. */ + + ret = SD_SUCCESS; /* assume success */ + +/* If this var could not be created, don't crash */ + if (scl_ln->mvl_var_assoc == NULL) + { + if (scl_debug_mode) + { + if (ret != SD_SUCCESS) + ++scl_debug_mode_error_count; + + return (SD_SUCCESS); /* Don't let this stop us for now ... */ + } + } + + type_ctrl = mvl_type_ctrl_find (scl_ln->mvl_var_assoc->type_id); + assert (type_ctrl); + /* Cast "reserved_1" pointer to the type we allocated. */ + reserved_info = (RESERVED_INFO *) type_ctrl->rt_ctrl->reserved_1; + + /* Loop through all elements of RUNTIME_TYPE array */ + for (rt_idx = 0, rt_type = type_ctrl->rt_ctrl->rt_first; + rt_idx < type_ctrl->rt_ctrl->rt_num; + rt_idx++, rt_type++) + { + ST_CHAR *Val = reserved_info[rt_idx].Val; + + if (Val) /* string to convert*/ + { + /* Convert text to value & store in Variable. */ + ret = convert_initial_value (scl_info, scl_ld, scl_ln, + NULL, /* don't know flattened_name in this case. */ + type_ctrl->rt_ctrl, + rt_idx, + (ST_INT8*)(scl_ln->mvl_var_assoc->data) + rt_type->mvluTypeInfo.offSet, + Val); /* string to convert*/ + if (ret != SD_SUCCESS) + { + SXLOG_ERR2 ("Cannot convert DA or BDA Val='%s' to data for '%s' attribute.", + Val, ms_comp_name_find(rt_type)); + break; /* stop now */ + } + } + } + return (ret); + } +/************************************************************************/ +/* scl2_dai_set_value_all */ +/* Initialize data for all DAI in this logical node. */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +static ST_RET scl2_dai_set_value_all (SCL_INFO *scl_info, + SCL_LD *scl_ld, + SCL_LN *scl_ln) + { +SCL_DAI *scl_dai; +ST_RET ret; + + ret = SD_SUCCESS; /* assume success */ + + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_dai = (SCL_DAI *) list_find_last ((DBL_LNK *) scl_ln->daiHead); + scl_dai != NULL; + scl_dai = (SCL_DAI *) list_find_prev ((DBL_LNK *) scl_ln->daiHead, (DBL_LNK *) scl_dai)) + { + ret = scl2_dai_set_value (scl_info, scl_ld, scl_ln, scl_dai); + if (ret) + { + SXLOG_ERR3 ("scl2_dai_set_value FAILED for '%s' (LD=%s LN=%s)", + scl_dai->flattened, scl_ld->domName, scl_ln->varName); + break; /* if one fails, stop processing */ + } + else + SXLOG_FLOW3 ("scl2_dai_set_value DONE for '%s' (LD=%s LN=%s)", + scl_dai->flattened, scl_ld->domName, scl_ln->varName); + } + + ret = SD_SUCCESS; /*renxiaobao20221014 */ + return (ret); + } +/************************************************************************/ +/* scl2_ld_create_part1 */ +/* Create Domain and all variables in it. */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +static ST_RET scl2_ld_create_part1 ( + MVL_VMD_CTRL *vmd_ctrl, + SCL_INFO *scl_info, /* main struct where all SCL info stored*/ + SCL_LD *scl_ld) + { +ST_RET ret = SD_SUCCESS; /* Assume success */ +MVL_DOM_CTRL *dom_ctrl; +ST_INT max_num_var; /* compute from scl_ld info */ +ST_INT max_num_nvl; +ST_INT max_num_jou; +SCL_LN *scl_ln; + + /* Make sure there's room for all Logical Nodes (variables) defined in SCL.*/ + /* plus room for the configured maximum number of dynamic variables. */ + max_num_var = list_get_sizeof (scl_ld->lnHead) + mvl_max_dyn.dom_vars; + max_num_nvl = mvl_max_dyn.dom_nvls; + max_num_jou = mvl_max_dyn.journals; + + /* First create MMS domain */ + dom_ctrl = mvl_vmd_dom_add (vmd_ctrl, + scl_ld->domName, /* domain name */ + max_num_var, + max_num_nvl, + max_num_jou, + SD_TRUE); /* always copy name to dom_ctrl */ + if (!dom_ctrl) + ret = SD_FAILURE; + + /* If MMS domain created successfully, create all MMS variables (logical nodes). */ + if (ret == SD_SUCCESS) + { + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_ln = (SCL_LN *) list_find_last ((DBL_LNK *) scl_ld->lnHead); + scl_ln != NULL; + scl_ln = (SCL_LN *) list_find_prev ((DBL_LNK *) scl_ld->lnHead, (DBL_LNK *) scl_ln)) + { + ret = scl2_ln_create (vmd_ctrl, scl_info, scl_ld, scl_ln); + if (ret) + { + SXLOG_ERR1 ("scl2_ln_create FAILED for %s", scl_ln->varName); + break; /* if one fails, stop processing */ + } + else + SXLOG_FLOW1 ("scl2_ln_create for %s SUCCESSFUL", scl_ln->varName); + } + } + + return (ret); + } + +/************************************************************************/ +/* scl2_ld_create_part2 */ +/* Create all NVLs and RCBs in this domain. */ +/* NOTE: this cannot be done in "scl2_ld_create_part1" because NVL */ +/* may include VAR from another Domain that was not defined yet. */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +static ST_RET scl2_ld_create_part2 ( + MVL_VMD_CTRL *vmd_ctrl, + SCL_INFO *scl_info, /* main struct where all SCL info stored*/ + SCL_LD *scl_ld, + ST_UINT reportScanRate, /* report scan rate (millisec) */ + ST_BOOLEAN is_client) /* see description in scl2_ld_create_all*/ + { +ST_RET ret = SD_SUCCESS; /* Assume success */ +SCL_LN *scl_ln; + + /* Create all MMS NVLs (DataSets). + * IEC 61850 defines a DataSet "inside" a Logical Node. + * This should seem a little strange, because + * a Logical Node maps to a MMS Variable, and a DataSet maps to a + * MMS Named Variable List, and of course, a Named Variable List CANNOT + * be "inside" of a Variable. + * This is resolved by simply creating a normal Named Variable List, and just + * adding it to the same Domain as the Variable. + * CRITICAL: THIS IS DONE AFTER ALL VARIABLES (LOGICAL NODES) CREATED BECAUSE + * DATASET MAY REFERENCE OTHER LOGICAL NODES. + */ + if (ret == SD_SUCCESS) + { + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_ln = (SCL_LN *) list_find_last ((DBL_LNK *) scl_ld->lnHead); + scl_ln != NULL; + scl_ln = (SCL_LN *) list_find_prev ((DBL_LNK *) scl_ld->lnHead, (DBL_LNK *) scl_ln)) + { + ret = scl2_dataset_create_all (vmd_ctrl, scl_ld, scl_ln); + if (ret) + { + break; /* if one fails, stop processing (error already logged) */ + } + } + } + + if (is_client) + { + SXLOG_FLOW0 ("Client configuration. Control blocks not created."); + return (ret); /* Stop now. Do NOT create RCB, LCB, etc. */ + } + + /* If all successful up to here, create all RCBs. */ + if (ret == SD_SUCCESS) + { + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_ln = (SCL_LN *) list_find_last ((DBL_LNK *) scl_ld->lnHead); + scl_ln != NULL; + scl_ln = (SCL_LN *) list_find_prev ((DBL_LNK *) scl_ld->lnHead, (DBL_LNK *) scl_ln)) + { + ret = scl2_rcb_create_all (vmd_ctrl, scl_info, scl_ld, scl_ln, reportScanRate); + if (ret) + { + break; /* if one fails, stop processing (error already logged) */ + } + } + } + /* If all successful up to here, set initial values from DA & BDA. */ + if (ret == SD_SUCCESS) + { + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_ln = (SCL_LN *) list_find_last ((DBL_LNK *) scl_ld->lnHead); + scl_ln != NULL; + scl_ln = (SCL_LN *) list_find_prev ((DBL_LNK *) scl_ld->lnHead, (DBL_LNK *) scl_ln)) + { + ret = scl2_da_or_bda_set_value_all (scl_info, scl_ld, scl_ln); + if (ret) + { + break; /* if one fails, stop processing (error already logged) */ + } + } + } + + /* If all successful up to here, set initial data values from */ + /* DOI/SDI/DAI entries found in the SCL file. */ + if (ret == SD_SUCCESS) + { + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_ln = (SCL_LN *) list_find_last ((DBL_LNK *) scl_ld->lnHead); + scl_ln != NULL; + scl_ln = (SCL_LN *) list_find_prev ((DBL_LNK *) scl_ld->lnHead, (DBL_LNK *) scl_ln)) + { + ret = scl2_dai_set_value_all (scl_info, scl_ld, scl_ln); + if (ret) + { + break; /* if one fails, stop processing (error already logged) */ + } + } + } + + return (ret); + } +/************************************************************************/ +/* scl2_ld_create_all */ +/* Create all Logical Devices from SCL info saved in "scl_info". */ +/* NOTE: must be done in 2 parts, because NVLs created in part2, may */ +/* reference Vars from different domains created in part1. */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +ST_RET scl2_ld_create_all ( + MVL_VMD_CTRL *vmd_ctrl, /* VMD in which to add Logical Devices. */ + SCL_INFO *scl_info, /* main struct where all SCL info stored*/ + ST_UINT reportScanRate, /* report scan rate (millisec) */ + ST_INT brcb_bufsize, /* BRCB buffer size */ + ST_BOOLEAN is_client) /* If this flag is set, Client model is */ + /* created (i.e. Control Blocks NOT created).*/ + { +ST_RET ret; +SCL_LD *scl_ld; + + /* CRITICAL: Don't allow this to be called again for the same SCL_INFO struct.*/ + /* That would cause duplicate objects. */ + if (scl_info->ld_create_done) + { + SXLOG_ERR0 ("Logical Devices already created for this SCL file. Cannot create again."); + return (SD_FAILURE); + } + else + scl_info->ld_create_done = SD_TRUE; /* Set flag now */ + + /* Save BRCB buffer size in scl_info so lower functions can access it.*/ + scl_info->brcb_bufsize = brcb_bufsize; + + ret = SD_SUCCESS; /* default ret val: returned if LD linked list empty.*/ + + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_ld = (SCL_LD *) list_find_last ((DBL_LNK *) scl_info->ldHead); + scl_ld != NULL; + scl_ld = (SCL_LD *) list_find_prev ((DBL_LNK *) scl_info->ldHead, (DBL_LNK *) scl_ld)) + { + ret = scl2_ld_create_part1 (vmd_ctrl, scl_info, scl_ld); + if (ret) + { + SXLOG_ERR1 ("scl2_ld_create_part1 for '%s' FAILED", scl_ld->domName); + break; /* if one fails, stop processing */ + } + else + { + SXLOG_FLOW1 ("scl2_ld_create_part1 for '%s' SUCCESSFUL", scl_ld->domName); + } + } + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_ld = (SCL_LD *) list_find_last ((DBL_LNK *) scl_info->ldHead); + scl_ld != NULL; + scl_ld = (SCL_LD *) list_find_prev ((DBL_LNK *) scl_info->ldHead, (DBL_LNK *) scl_ld)) + { + ret = scl2_ld_create_part2 (vmd_ctrl, scl_info, scl_ld, reportScanRate, is_client); + if (ret) + { + SXLOG_ERR1 ("scl2_ld_create_part2 for '%s' FAILED", scl_ld->domName); + if (!scl_debug_mode) + break; /* if one fails, stop processing */ + + ++scl_debug_mode_error_count; + } + else + { + SXLOG_FLOW1 ("scl2_ld_create_part2 for '%s' SUCCESSFUL", scl_ld->domName); + } + } + /* Create "LastApplError" variable (required if "Control with */ + /* enhanced security" supported). */ + if (ret == SD_SUCCESS) + ret = mvl61850_ctl_lastapplerror_create (); + + /* The reserved_1 member of every RUNTIME_CTRL is must now be freed. */ + reserved_free_all (vmd_ctrl); + return (ret); + } + +/************************************************************************/ +/* scl_gse_find */ +/* Find addressing info for this GCB in this LD. */ +/************************************************************************/ +SCL_GSE *scl_gse_find (SCL_INFO *scl_info, SCL_LD *scl_ld, SCL_GCB *scl_gcb) + { +SCL_SUBNET *scl_subnet; +SCL_CAP *scl_cap; +SCL_GSE *scl_gse; + + for (scl_subnet = (SCL_SUBNET *) list_find_last ((DBL_LNK *) scl_info->subnetHead); + scl_subnet != NULL; + scl_subnet = (SCL_SUBNET *) list_find_prev ((DBL_LNK *) scl_info->subnetHead, (DBL_LNK *) scl_subnet)) + { + for (scl_cap = (SCL_CAP *) list_find_last ((DBL_LNK *) scl_subnet->capHead); + scl_cap != NULL; + scl_cap = (SCL_CAP *) list_find_prev ((DBL_LNK *) scl_subnet->capHead, (DBL_LNK *) scl_cap)) + { + if (strcmp (scl_info->iedName, scl_cap->iedName) == 0) + { /* found matching iedName */ + for (scl_gse = (SCL_GSE *) list_find_last ((DBL_LNK *) scl_cap->gseHead); + scl_gse != NULL; + scl_gse = (SCL_GSE *) list_find_prev ((DBL_LNK *) scl_cap->gseHead, (DBL_LNK *) scl_gse)) + { + if (strcmp (scl_ld->inst, scl_gse->ldInst) == 0 && + strcmp (scl_gcb->name, scl_gse->cbName) == 0) + { /* Found it. Too many loops to break out of, so just return.*/ + return (scl_gse); + } + } /* end scl_gse loop */ + } + } /* end scl_cap loop */ + } /* end scl_subnet loop */ + + return (NULL); /* Not found */ + } + diff --git a/mmslib/object_script.libmmslib.Debug b/mmslib/object_script.libmmslib.Debug new file mode 100644 index 0000000..42310f1 --- /dev/null +++ b/mmslib/object_script.libmmslib.Debug @@ -0,0 +1,349 @@ +CREATE debug\libmmslib.a +ADDMOD debug\mmslib.o +ADDMOD debug\asn1r.o +ADDMOD debug\are_vstr.o +ADDMOD debug\are_utc.o +ADDMOD debug\are_time.o +ADDMOD debug\are_ostr.o +ADDMOD debug\are_objd.o +ADDMOD debug\are_int.o +ADDMOD debug\are_flt.o +ADDMOD debug\are_delm.o +ADDMOD debug\are_btod.o +ADDMOD debug\are_bstr.o +ADDMOD debug\are_bool.o +ADDMOD debug\ard_vstr.o +ADDMOD debug\ard_utc.o +ADDMOD debug\ard_time.o +ADDMOD debug\ard_strn.o +ADDMOD debug\ard_ostr.o +ADDMOD debug\ard_objd.o +ADDMOD debug\ard_int.o +ADDMOD debug\ard_idnt.o +ADDMOD debug\ard_flt.o +ADDMOD debug\ard_delm.o +ADDMOD debug\ard_btod.o +ADDMOD debug\ard_bstr.o +ADDMOD debug\ard_bool.o +ADDMOD debug\mem_chks.o +ADDMOD debug\rs_write.o +ADDMOD debug\rs_ustat.o +ADDMOD debug\rs_trige.o +ADDMOD debug\rs_stat.o +ADDMOD debug\rs_repee.o +ADDMOD debug\rs_repec.o +ADDMOD debug\rs_repea.o +ADDMOD debug\rs_read.o +ADDMOD debug\rs_namel.o +ADDMOD debug\rs_init.o +ADDMOD debug\rs_info.o +ADDMOD debug\rs_ident.o +ADDMOD debug\rs_getvl.o +ADDMOD debug\rs_getva.o +ADDMOD debug\rs_getty.o +ADDMOD debug\rs_getpi.o +ADDMOD debug\rs_getee.o +ADDMOD debug\rs_getec.o +ADDMOD debug\rs_getea.o +ADDMOD debug\rs_getdo.o +ADDMOD debug\rs_getcl.o +ADDMOD debug\rs_evnot.o +ADDMOD debug\rs_defee.o +ADDMOD debug\rs_concl.o +ADDMOD debug\rs_cancl.o +ADDMOD debug\rs_ackev.o +ADDMOD debug\rq_write.o +ADDMOD debug\rq_ustat.o +ADDMOD debug\rq_trige.o +ADDMOD debug\rq_stat.o +ADDMOD debug\rq_repee.o +ADDMOD debug\rq_repec.o +ADDMOD debug\rq_repea.o +ADDMOD debug\rq_read.o +ADDMOD debug\rq_namel.o +ADDMOD debug\rq_init.o +ADDMOD debug\rq_info.o +ADDMOD debug\rq_ident.o +ADDMOD debug\rq_getvl.o +ADDMOD debug\rq_getva.o +ADDMOD debug\rq_getty.o +ADDMOD debug\rq_getpi.o +ADDMOD debug\rq_getee.o +ADDMOD debug\rq_getec.o +ADDMOD debug\rq_getea.o +ADDMOD debug\rq_getdo.o +ADDMOD debug\rq_getcl.o +ADDMOD debug\rq_evnot.o +ADDMOD debug\rq_defee.o +ADDMOD debug\rq_concl.o +ADDMOD debug\rq_cancl.o +ADDMOD debug\rq_ackev.o +ADDMOD debug\msdataas.o +ADDMOD debug\ms_tdef4.o +ADDMOD debug\ms_tdef2.o +ADDMOD debug\ms_tdef.o +ADDMOD debug\ms_size.o +ADDMOD debug\ms_ext.o +ADDMOD debug\mmsstat.o +ADDMOD debug\mmslvar.o +ADDMOD debug\mmsl_fin.o +ADDMOD debug\mmsinit.o +ADDMOD debug\mmsdtext.o +ADDMOD debug\mmsdec.o +ADDMOD debug\mmsdatat.o +ADDMOD debug\mmsdata.o +ADDMOD debug\mmsconcl.o +ADDMOD debug\mmscancl.o +ADDMOD debug\mms_tdef.o +ADDMOD debug\mms_rtaa.o +ADDMOD debug\mms_rej.o +ADDMOD debug\mms_err4.o +ADDMOD debug\mms_err3.o +ADDMOD debug\mms_err2.o +ADDMOD debug\mms_err.o +ADDMOD debug\mms_ced7.o +ADDMOD debug\mms_ced6.o +ADDMOD debug\mms_ced5.o +ADDMOD debug\mms_ced4.o +ADDMOD debug\mms_ced3.o +ADDMOD debug\mms_ced.o +ADDMOD debug\mms_aref.o +ADDMOD debug\mms_alta.o +ADDMOD debug\mms_adl.o +ADDMOD debug\rs_uploa.o +ADDMOD debug\rs_termu.o +ADDMOD debug\rs_termd.o +ADDMOD debug\rs_takec.o +ADDMOD debug\rs_store.o +ADDMOD debug\rs_stop.o +ADDMOD debug\rs_start.o +ADDMOD debug\rs_rssta.o +ADDMOD debug\rs_rspoo.o +ADDMOD debug\rs_rsent.o +ADDMOD debug\rs_resum.o +ADDMOD debug\rs_reset.o +ADDMOD debug\rs_renam.o +ADDMOD debug\rs_relct.o +ADDMOD debug\rs_rdupl.o +ADDMOD debug\rs_rddwn.o +ADDMOD debug\rs_outpu.o +ADDMOD debug\rs_obtfi.o +ADDMOD debug\rs_loadd.o +ADDMOD debug\rs_kill.o +ADDMOD debug\rs_jwrit.o +ADDMOD debug\rs_jstat.o +ADDMOD debug\rs_jread.o +ADDMOD debug\rs_jinit.o +ADDMOD debug\rs_jdele.o +ADDMOD debug\rs_jcrea.o +ADDMOD debug\rs_input.o +ADDMOD debug\rs_initu.o +ADDMOD debug\rs_initd.o +ADDMOD debug\rs_getsc.o +ADDMOD debug\rs_getas.o +ADDMOD debug\rs_getae.o +ADDMOD debug\rs_frena.o +ADDMOD debug\rs_fread.o +ADDMOD debug\rs_fopen.o +ADDMOD debug\rs_fdir.o +ADDMOD debug\rs_fdele.o +ADDMOD debug\rs_fclos.o +ADDMOD debug\rs_downl.o +ADDMOD debug\rs_delvl.o +ADDMOD debug\rs_delva.o +ADDMOD debug\rs_delty.o +ADDMOD debug\rs_delse.o +ADDMOD debug\rs_delpi.o +ADDMOD debug\rs_delee.o +ADDMOD debug\rs_delec.o +ADDMOD debug\rs_delea.o +ADDMOD debug\rs_deldo.o +ADDMOD debug\rs_defvl.o +ADDMOD debug\rs_defva.o +ADDMOD debug\rs_defty.o +ADDMOD debug\rs_defse.o +ADDMOD debug\rs_defsc.o +ADDMOD debug\rs_defec.o +ADDMOD debug\rs_defea.o +ADDMOD debug\rs_crepi.o +ADDMOD debug\rs_altee.o +ADDMOD debug\rs_altec.o +ADDMOD debug\rq_uploa.o +ADDMOD debug\rq_termu.o +ADDMOD debug\rq_termd.o +ADDMOD debug\rq_takec.o +ADDMOD debug\rq_store.o +ADDMOD debug\rq_stop.o +ADDMOD debug\rq_start.o +ADDMOD debug\rq_rssta.o +ADDMOD debug\rq_rspoo.o +ADDMOD debug\rq_rsent.o +ADDMOD debug\rq_resum.o +ADDMOD debug\rq_reset.o +ADDMOD debug\rq_renam.o +ADDMOD debug\rq_relct.o +ADDMOD debug\rq_rdupl.o +ADDMOD debug\rq_rddwn.o +ADDMOD debug\rq_outpu.o +ADDMOD debug\rq_obtfi.o +ADDMOD debug\rq_loadd.o +ADDMOD debug\rq_kill.o +ADDMOD debug\rq_jwrit.o +ADDMOD debug\rq_jstat.o +ADDMOD debug\rq_jread.o +ADDMOD debug\rq_jinit.o +ADDMOD debug\rq_jdele.o +ADDMOD debug\rq_jcrea.o +ADDMOD debug\rq_input.o +ADDMOD debug\rq_initu.o +ADDMOD debug\rq_initd.o +ADDMOD debug\rq_getsc.o +ADDMOD debug\rq_getas.o +ADDMOD debug\rq_getae.o +ADDMOD debug\rq_frena.o +ADDMOD debug\rq_fread.o +ADDMOD debug\rq_fopen.o +ADDMOD debug\rq_fdir.o +ADDMOD debug\rq_fdele.o +ADDMOD debug\rq_fclos.o +ADDMOD debug\rq_downl.o +ADDMOD debug\rq_delvl.o +ADDMOD debug\rq_delva.o +ADDMOD debug\rq_delty.o +ADDMOD debug\rq_delse.o +ADDMOD debug\rq_delpi.o +ADDMOD debug\rq_delee.o +ADDMOD debug\rq_delec.o +ADDMOD debug\rq_delea.o +ADDMOD debug\rq_deldo.o +ADDMOD debug\rq_defvl.o +ADDMOD debug\rq_defva.o +ADDMOD debug\rq_defty.o +ADDMOD debug\rq_defse.o +ADDMOD debug\rq_defsc.o +ADDMOD debug\rq_defec.o +ADDMOD debug\rq_defea.o +ADDMOD debug\rq_crepi.o +ADDMOD debug\rq_altee.o +ADDMOD debug\rq_altec.o +ADDMOD debug\mms_ced2.o +ADDMOD debug\mms_ced1.o +ADDMOD debug\sclproc.o +ADDMOD debug\s_write.o +ADDMOD debug\s_status.o +ADDMOD debug\s_read.o +ADDMOD debug\s_obtfi.o +ADDMOD debug\s_jstat.o +ADDMOD debug\s_jread.o +ADDMOD debug\s_jinit.o +ADDMOD debug\s_info.o +ADDMOD debug\s_ident.o +ADDMOD debug\s_getvla.o +ADDMOD debug\s_getvaa.o +ADDMOD debug\s_getnam.o +ADDMOD debug\s_getdom.o +ADDMOD debug\s_getcl.o +ADDMOD debug\s_fren.o +ADDMOD debug\s_fread.o +ADDMOD debug\s_fopen.o +ADDMOD debug\s_fdir.o +ADDMOD debug\s_fdel.o +ADDMOD debug\s_fclose.o +ADDMOD debug\s_delvl.o +ADDMOD debug\s_defvl.o +ADDMOD debug\s_concl.o +ADDMOD debug\s_cancel.o +ADDMOD debug\mvluleaf.o +ADDMOD debug\mvlu_sbo.o +ADDMOD debug\mvlu_rt.o +ADDMOD debug\mvlu_rpt.o +ADDMOD debug\mvl61850_rpt.o +ADDMOD debug\mvl61850_ctl.o +ADDMOD debug\mvl61850.o +ADDMOD debug\mvl_var.o +ADDMOD debug\mvl_uca.o +ADDMOD debug\mvl_type.o +ADDMOD debug\mvl_typ2.o +ADDMOD debug\mvl_serv.o +ADDMOD debug\mvl_send.o +ADDMOD debug\mvl_objb.o +ADDMOD debug\mvl_obj.o +ADDMOD debug\mvl_ijou.o +ADDMOD debug\mvl_dtyp.o +ADDMOD debug\mvl_buf.o +ADDMOD debug\c_write.o +ADDMOD debug\c_status.o +ADDMOD debug\c_read.o +ADDMOD debug\c_obtfi.o +ADDMOD debug\c_jstat.o +ADDMOD debug\c_jread.o +ADDMOD debug\c_jinit.o +ADDMOD debug\c_info.o +ADDMOD debug\c_ident.o +ADDMOD debug\c_getvla.o +ADDMOD debug\c_getvar.o +ADDMOD debug\c_getnam.o +ADDMOD debug\c_getdom.o +ADDMOD debug\c_fren.o +ADDMOD debug\c_fread.o +ADDMOD debug\c_fopen.o +ADDMOD debug\c_fget.o +ADDMOD debug\c_fdir.o +ADDMOD debug\c_fdel.o +ADDMOD debug\c_fclose.o +ADDMOD debug\c_delvl.o +ADDMOD debug\c_defvl.o +ADDMOD debug\c_concl.o +ADDMOD debug\tpx_dec.o +ADDMOD debug\tp4port.o +ADDMOD debug\tp4_enc.o +ADDMOD debug\tp0main.o +ADDMOD debug\tp0callg.o +ADDMOD debug\tp0calld.o +ADDMOD debug\tp0_socks.o +ADDMOD debug\tp0_dec.o +ADDMOD debug\osicfgx.o +ADDMOD debug\lean_var.o +ADDMOD debug\lean_cfg.o +ADDMOD debug\cospmain.o +ADDMOD debug\cosp_enc.o +ADDMOD debug\cosp_dec.o +ADDMOD debug\coppdcpr.o +ADDMOD debug\coppdcp.o +ADDMOD debug\coppdaru.o +ADDMOD debug\copp_enc.o +ADDMOD debug\copp_dec.o +ADDMOD debug\checksum.o +ADDMOD debug\acse2var.o +ADDMOD debug\acse2enc.o +ADDMOD debug\acse2dib.o +ADDMOD debug\acse2dec.o +ADDMOD debug\slogmem.o +ADDMOD debug\slogipcs.o +ADDMOD debug\sloghex.o +ADDMOD debug\slogfil.o +ADDMOD debug\slog.o +ADDMOD debug\qmem.o +ADDMOD debug\ssecusr0.o +ADDMOD debug\time_str.o +ADDMOD debug\sx_enc.o +ADDMOD debug\sx_dec.o +ADDMOD debug\sx_data.o +ADDMOD debug\sx_axs4d.o +ADDMOD debug\str_util.o +ADDMOD debug\stime.o +ADDMOD debug\stdtime_w32.o +ADDMOD debug\stdtime_quadlib.o +ADDMOD debug\stdtime_mms_utctime.o +ADDMOD debug\stdtime_mms_btime.o +ADDMOD debug\stdtime.o +ADDMOD debug\sclstore.o +ADDMOD debug\sclparse.o +ADDMOD debug\scl_log.o +ADDMOD debug\glbsem_w32.o +ADDMOD debug\glbsem_unix.o +ADDMOD debug\glbsem.o +ADDMOD debug\gensock2.o +ADDMOD debug\genlists.o +ADDMOD debug\cfg_util.o +SAVE diff --git a/mmslib/object_script.libmmslib.Release b/mmslib/object_script.libmmslib.Release new file mode 100644 index 0000000..f2b8c68 --- /dev/null +++ b/mmslib/object_script.libmmslib.Release @@ -0,0 +1,349 @@ +CREATE release\libmmslib.a +ADDMOD release\mmslib.o +ADDMOD release\asn1r.o +ADDMOD release\are_vstr.o +ADDMOD release\are_utc.o +ADDMOD release\are_time.o +ADDMOD release\are_ostr.o +ADDMOD release\are_objd.o +ADDMOD release\are_int.o +ADDMOD release\are_flt.o +ADDMOD release\are_delm.o +ADDMOD release\are_btod.o +ADDMOD release\are_bstr.o +ADDMOD release\are_bool.o +ADDMOD release\ard_vstr.o +ADDMOD release\ard_utc.o +ADDMOD release\ard_time.o +ADDMOD release\ard_strn.o +ADDMOD release\ard_ostr.o +ADDMOD release\ard_objd.o +ADDMOD release\ard_int.o +ADDMOD release\ard_idnt.o +ADDMOD release\ard_flt.o +ADDMOD release\ard_delm.o +ADDMOD release\ard_btod.o +ADDMOD release\ard_bstr.o +ADDMOD release\ard_bool.o +ADDMOD release\mem_chks.o +ADDMOD release\rs_write.o +ADDMOD release\rs_ustat.o +ADDMOD release\rs_trige.o +ADDMOD release\rs_stat.o +ADDMOD release\rs_repee.o +ADDMOD release\rs_repec.o +ADDMOD release\rs_repea.o +ADDMOD release\rs_read.o +ADDMOD release\rs_namel.o +ADDMOD release\rs_init.o +ADDMOD release\rs_info.o +ADDMOD release\rs_ident.o +ADDMOD release\rs_getvl.o +ADDMOD release\rs_getva.o +ADDMOD release\rs_getty.o +ADDMOD release\rs_getpi.o +ADDMOD release\rs_getee.o +ADDMOD release\rs_getec.o +ADDMOD release\rs_getea.o +ADDMOD release\rs_getdo.o +ADDMOD release\rs_getcl.o +ADDMOD release\rs_evnot.o +ADDMOD release\rs_defee.o +ADDMOD release\rs_concl.o +ADDMOD release\rs_cancl.o +ADDMOD release\rs_ackev.o +ADDMOD release\rq_write.o +ADDMOD release\rq_ustat.o +ADDMOD release\rq_trige.o +ADDMOD release\rq_stat.o +ADDMOD release\rq_repee.o +ADDMOD release\rq_repec.o +ADDMOD release\rq_repea.o +ADDMOD release\rq_read.o +ADDMOD release\rq_namel.o +ADDMOD release\rq_init.o +ADDMOD release\rq_info.o +ADDMOD release\rq_ident.o +ADDMOD release\rq_getvl.o +ADDMOD release\rq_getva.o +ADDMOD release\rq_getty.o +ADDMOD release\rq_getpi.o +ADDMOD release\rq_getee.o +ADDMOD release\rq_getec.o +ADDMOD release\rq_getea.o +ADDMOD release\rq_getdo.o +ADDMOD release\rq_getcl.o +ADDMOD release\rq_evnot.o +ADDMOD release\rq_defee.o +ADDMOD release\rq_concl.o +ADDMOD release\rq_cancl.o +ADDMOD release\rq_ackev.o +ADDMOD release\msdataas.o +ADDMOD release\ms_tdef4.o +ADDMOD release\ms_tdef2.o +ADDMOD release\ms_tdef.o +ADDMOD release\ms_size.o +ADDMOD release\ms_ext.o +ADDMOD release\mmsstat.o +ADDMOD release\mmslvar.o +ADDMOD release\mmsl_fin.o +ADDMOD release\mmsinit.o +ADDMOD release\mmsdtext.o +ADDMOD release\mmsdec.o +ADDMOD release\mmsdatat.o +ADDMOD release\mmsdata.o +ADDMOD release\mmsconcl.o +ADDMOD release\mmscancl.o +ADDMOD release\mms_tdef.o +ADDMOD release\mms_rtaa.o +ADDMOD release\mms_rej.o +ADDMOD release\mms_err4.o +ADDMOD release\mms_err3.o +ADDMOD release\mms_err2.o +ADDMOD release\mms_err.o +ADDMOD release\mms_ced7.o +ADDMOD release\mms_ced6.o +ADDMOD release\mms_ced5.o +ADDMOD release\mms_ced4.o +ADDMOD release\mms_ced3.o +ADDMOD release\mms_ced.o +ADDMOD release\mms_aref.o +ADDMOD release\mms_alta.o +ADDMOD release\mms_adl.o +ADDMOD release\rs_uploa.o +ADDMOD release\rs_termu.o +ADDMOD release\rs_termd.o +ADDMOD release\rs_takec.o +ADDMOD release\rs_store.o +ADDMOD release\rs_stop.o +ADDMOD release\rs_start.o +ADDMOD release\rs_rssta.o +ADDMOD release\rs_rspoo.o +ADDMOD release\rs_rsent.o +ADDMOD release\rs_resum.o +ADDMOD release\rs_reset.o +ADDMOD release\rs_renam.o +ADDMOD release\rs_relct.o +ADDMOD release\rs_rdupl.o +ADDMOD release\rs_rddwn.o +ADDMOD release\rs_outpu.o +ADDMOD release\rs_obtfi.o +ADDMOD release\rs_loadd.o +ADDMOD release\rs_kill.o +ADDMOD release\rs_jwrit.o +ADDMOD release\rs_jstat.o +ADDMOD release\rs_jread.o +ADDMOD release\rs_jinit.o +ADDMOD release\rs_jdele.o +ADDMOD release\rs_jcrea.o +ADDMOD release\rs_input.o +ADDMOD release\rs_initu.o +ADDMOD release\rs_initd.o +ADDMOD release\rs_getsc.o +ADDMOD release\rs_getas.o +ADDMOD release\rs_getae.o +ADDMOD release\rs_frena.o +ADDMOD release\rs_fread.o +ADDMOD release\rs_fopen.o +ADDMOD release\rs_fdir.o +ADDMOD release\rs_fdele.o +ADDMOD release\rs_fclos.o +ADDMOD release\rs_downl.o +ADDMOD release\rs_delvl.o +ADDMOD release\rs_delva.o +ADDMOD release\rs_delty.o +ADDMOD release\rs_delse.o +ADDMOD release\rs_delpi.o +ADDMOD release\rs_delee.o +ADDMOD release\rs_delec.o +ADDMOD release\rs_delea.o +ADDMOD release\rs_deldo.o +ADDMOD release\rs_defvl.o +ADDMOD release\rs_defva.o +ADDMOD release\rs_defty.o +ADDMOD release\rs_defse.o +ADDMOD release\rs_defsc.o +ADDMOD release\rs_defec.o +ADDMOD release\rs_defea.o +ADDMOD release\rs_crepi.o +ADDMOD release\rs_altee.o +ADDMOD release\rs_altec.o +ADDMOD release\rq_uploa.o +ADDMOD release\rq_termu.o +ADDMOD release\rq_termd.o +ADDMOD release\rq_takec.o +ADDMOD release\rq_store.o +ADDMOD release\rq_stop.o +ADDMOD release\rq_start.o +ADDMOD release\rq_rssta.o +ADDMOD release\rq_rspoo.o +ADDMOD release\rq_rsent.o +ADDMOD release\rq_resum.o +ADDMOD release\rq_reset.o +ADDMOD release\rq_renam.o +ADDMOD release\rq_relct.o +ADDMOD release\rq_rdupl.o +ADDMOD release\rq_rddwn.o +ADDMOD release\rq_outpu.o +ADDMOD release\rq_obtfi.o +ADDMOD release\rq_loadd.o +ADDMOD release\rq_kill.o +ADDMOD release\rq_jwrit.o +ADDMOD release\rq_jstat.o +ADDMOD release\rq_jread.o +ADDMOD release\rq_jinit.o +ADDMOD release\rq_jdele.o +ADDMOD release\rq_jcrea.o +ADDMOD release\rq_input.o +ADDMOD release\rq_initu.o +ADDMOD release\rq_initd.o +ADDMOD release\rq_getsc.o +ADDMOD release\rq_getas.o +ADDMOD release\rq_getae.o +ADDMOD release\rq_frena.o +ADDMOD release\rq_fread.o +ADDMOD release\rq_fopen.o +ADDMOD release\rq_fdir.o +ADDMOD release\rq_fdele.o +ADDMOD release\rq_fclos.o +ADDMOD release\rq_downl.o +ADDMOD release\rq_delvl.o +ADDMOD release\rq_delva.o +ADDMOD release\rq_delty.o +ADDMOD release\rq_delse.o +ADDMOD release\rq_delpi.o +ADDMOD release\rq_delee.o +ADDMOD release\rq_delec.o +ADDMOD release\rq_delea.o +ADDMOD release\rq_deldo.o +ADDMOD release\rq_defvl.o +ADDMOD release\rq_defva.o +ADDMOD release\rq_defty.o +ADDMOD release\rq_defse.o +ADDMOD release\rq_defsc.o +ADDMOD release\rq_defec.o +ADDMOD release\rq_defea.o +ADDMOD release\rq_crepi.o +ADDMOD release\rq_altee.o +ADDMOD release\rq_altec.o +ADDMOD release\mms_ced2.o +ADDMOD release\mms_ced1.o +ADDMOD release\sclproc.o +ADDMOD release\s_write.o +ADDMOD release\s_status.o +ADDMOD release\s_read.o +ADDMOD release\s_obtfi.o +ADDMOD release\s_jstat.o +ADDMOD release\s_jread.o +ADDMOD release\s_jinit.o +ADDMOD release\s_info.o +ADDMOD release\s_ident.o +ADDMOD release\s_getvla.o +ADDMOD release\s_getvaa.o +ADDMOD release\s_getnam.o +ADDMOD release\s_getdom.o +ADDMOD release\s_getcl.o +ADDMOD release\s_fren.o +ADDMOD release\s_fread.o +ADDMOD release\s_fopen.o +ADDMOD release\s_fdir.o +ADDMOD release\s_fdel.o +ADDMOD release\s_fclose.o +ADDMOD release\s_delvl.o +ADDMOD release\s_defvl.o +ADDMOD release\s_concl.o +ADDMOD release\s_cancel.o +ADDMOD release\mvluleaf.o +ADDMOD release\mvlu_sbo.o +ADDMOD release\mvlu_rt.o +ADDMOD release\mvlu_rpt.o +ADDMOD release\mvl61850_rpt.o +ADDMOD release\mvl61850_ctl.o +ADDMOD release\mvl61850.o +ADDMOD release\mvl_var.o +ADDMOD release\mvl_uca.o +ADDMOD release\mvl_type.o +ADDMOD release\mvl_typ2.o +ADDMOD release\mvl_serv.o +ADDMOD release\mvl_send.o +ADDMOD release\mvl_objb.o +ADDMOD release\mvl_obj.o +ADDMOD release\mvl_ijou.o +ADDMOD release\mvl_dtyp.o +ADDMOD release\mvl_buf.o +ADDMOD release\c_write.o +ADDMOD release\c_status.o +ADDMOD release\c_read.o +ADDMOD release\c_obtfi.o +ADDMOD release\c_jstat.o +ADDMOD release\c_jread.o +ADDMOD release\c_jinit.o +ADDMOD release\c_info.o +ADDMOD release\c_ident.o +ADDMOD release\c_getvla.o +ADDMOD release\c_getvar.o +ADDMOD release\c_getnam.o +ADDMOD release\c_getdom.o +ADDMOD release\c_fren.o +ADDMOD release\c_fread.o +ADDMOD release\c_fopen.o +ADDMOD release\c_fget.o +ADDMOD release\c_fdir.o +ADDMOD release\c_fdel.o +ADDMOD release\c_fclose.o +ADDMOD release\c_delvl.o +ADDMOD release\c_defvl.o +ADDMOD release\c_concl.o +ADDMOD release\tpx_dec.o +ADDMOD release\tp4port.o +ADDMOD release\tp4_enc.o +ADDMOD release\tp0main.o +ADDMOD release\tp0callg.o +ADDMOD release\tp0calld.o +ADDMOD release\tp0_socks.o +ADDMOD release\tp0_dec.o +ADDMOD release\osicfgx.o +ADDMOD release\lean_var.o +ADDMOD release\lean_cfg.o +ADDMOD release\cospmain.o +ADDMOD release\cosp_enc.o +ADDMOD release\cosp_dec.o +ADDMOD release\coppdcpr.o +ADDMOD release\coppdcp.o +ADDMOD release\coppdaru.o +ADDMOD release\copp_enc.o +ADDMOD release\copp_dec.o +ADDMOD release\checksum.o +ADDMOD release\acse2var.o +ADDMOD release\acse2enc.o +ADDMOD release\acse2dib.o +ADDMOD release\acse2dec.o +ADDMOD release\slogmem.o +ADDMOD release\slogipcs.o +ADDMOD release\sloghex.o +ADDMOD release\slogfil.o +ADDMOD release\slog.o +ADDMOD release\qmem.o +ADDMOD release\ssecusr0.o +ADDMOD release\time_str.o +ADDMOD release\sx_enc.o +ADDMOD release\sx_dec.o +ADDMOD release\sx_data.o +ADDMOD release\sx_axs4d.o +ADDMOD release\str_util.o +ADDMOD release\stime.o +ADDMOD release\stdtime_w32.o +ADDMOD release\stdtime_quadlib.o +ADDMOD release\stdtime_mms_utctime.o +ADDMOD release\stdtime_mms_btime.o +ADDMOD release\stdtime.o +ADDMOD release\sclstore.o +ADDMOD release\sclparse.o +ADDMOD release\scl_log.o +ADDMOD release\glbsem_w32.o +ADDMOD release\glbsem_unix.o +ADDMOD release\glbsem.o +ADDMOD release\gensock2.o +ADDMOD release\genlists.o +ADDMOD release\cfg_util.o +SAVE diff --git a/mmslib/ositcps/acse2dec.c b/mmslib/ositcps/acse2dec.c new file mode 100644 index 0000000..a4dc768 --- /dev/null +++ b/mmslib/ositcps/acse2dec.c @@ -0,0 +1,2268 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-2005, All Rights Reserved */ +/* */ +/* MODULE NAME : acse2dec.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* ACSE Decode Functions. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/26/09 JRB 12 Fix to handle PDV len=0 or user_info len=0. */ +/* 04/28/08 GLB 59 Removed CALLED_ONLY and CALLING_ONLY */ +/* 01/30/06 GLB 58 Integrated porting changes for VMS */ +/* 07/06/05 EJV 57 Log "IP ADDR:" on the same line as the ip. */ +/* 05/19/05 JRB 56 Chg "unrecognized tag" logs from ERR to DEC. */ +/* 03/31/05 EJV 55 a_get_rem_ip_addr: added defined(linux) */ +/* 09/20/04 JRB 54 u_copp_con_cnf: don't access acse_conn after */ +/* copp_u_abort_req (it may have been freed). */ +/* 08/06/04 EJV 53 _a_dec_authentication: chg param to ST_UCHAR.*/ +/* 03/15/04 GLB 51 Delete "iso_mms_is_ASO_context_name" */ +/* 03/04/04 JRB 51 Use ASN1 decode log macros (ALOG_DEC*) */ +/* Del logging of A-DATA.ind (use MVL or COPP) */ +/* 02/06/04 EJV 50 Use MACE_MECH_ID define. */ +/* 01/08/04 EJV 49 Ported funcs to sun. */ +/* 12/12/03 JRB 48 Fix asn1r_get_bitstr calls, init data=0 first*/ +/* 10/24/03 JRB 47 Chg #if ..TP0.. to avoid compile errors. */ +/* 07/08/03 EJV 46 Del old password auth (OBSOLETE_ACSE_AUTH); */ +/* ACSE_AUTH_ENABLED code wo/define. */ +/* Fix the ACSE Auth decode. */ +/* 03/31/03 JRB 45 asn1r_get_bitstr: add max_bits arg. */ +/* 11/08/02 JRB 44 asn1_skip_elmnt ret error if indef len. */ +/* 10/29/02 JRB 43 Fix a_auth_password_dec ret if pwd too long. */ +/* 10/22/02 ASK 42 Wrap ifdef TP0_ENABLED around inet_ntoa calls*/ +/* 10/14/02 ASK 41 Added decode of abort diagnostic. */ +/* 10/03/02 ASK 40 Now send abort when AARQ fails to decode */ +/* 09/27/02 ASK 39 Added ACSE auth decode to AARE, moved */ +/* bitstring defines into acse2.h */ +/* 06/26/02 JRB 38 con_ind: Log calling/called address. */ +/* 06/20/02 JRB 37 con_ind: Copy calling/called PADDR to AARQ. */ +/* 01/10/02 EJV 36 Converted to use ASN1R for TRIM7 */ +/* 01/02/02 JRB 35 Converted to use ASN1R (re-entrant ASN1) */ +/* 10/09/01 JRB 34 Log if unrecognized tag received. */ +/* 06/22/01 JRB 33 Fix u_copp_rel_cnf_pos & tp4_data_ind */ +/* handling of STATE_RESP_COLL */ +/* state per ISO 8650 (was kluged before). */ +/* 03/15/01 JRB 32 Use new SMEM allocation functions. */ +/* 01/02/01 EJV 31 Ported to _AIX */ +/* 04/12/00 JRB 30 Lint cleanup. */ +/* 09/13/99 MDE 29 Added SD_CONST modifiers */ +/* 07/14/99 JRB 28 Add ACSE Password Authentication. */ +/* 07/14/99 JRB 27 Add functions to get remote NSAP or IP Addr. */ +/* 08/13/98 JRB 26 Lint cleanup. */ +/* 08/11/98 JRB 25 BUG_FIX: MOSI: only save user_info if PCI=MMS*/ +/* 03/18/98 JRB 24 Use defines (not variables) for ASN1 errors. */ +/* 11/07/97 JRB 23 Can't use // for comments. */ +/* 07/13/97 EJV 22 Commented out call to exit() in tp4_except. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/19/97 JRB 21 Add MOSI "CALLING" support. */ +/* 03/19/97 JRB 20 tp4_connect_cnf send AARQ (already encoded). */ +/* Use acse_free_conn to free conn ctrl struct. */ +/* Improve logging. */ +/* Improve release collision handling. */ +/* 03/07/97 JRB 19 Only pass abort to user if not in IDLE state.*/ +/* 03/07/97 JRB 18 Don't call acse_decode unless class==APP. */ +/* 03/07/97 JRB 17 Use new asn1_skip_elmnt funct instead of */ +/* inline code and "parse_next" calls. */ +/* 03/07/97 JRB 16 Added MOSI support. */ +/* 08/12/96 JRB 15 Handle decode error gracefully in */ +/* tp4_data_ind_aarqind & tp4_data_ind_aarqcnf. */ +/* 07/15/96 JRB 14 Only free acse_conn->aarq_apdu.user_info.ptr */ +/* if len != 0 (wasn't alloc'd otherwise). */ +/* 07/08/96 JRB 13 Add tp4_except for LEAN_T. */ +/* 06/25/96 JRB 12 Fix return codes for tp4_data_ind_aarq* */ +/* 05/02/96 JRB 11 Add STATE_TP4CONN_WAIT. */ +/* 04/25/96 JRB 10 Set acse_conn->initiator = SD_TRUE in */ +/* tp4_data_ind_aarqcnf (for release collisions)*/ +/* 04/18/96 JRB 09 if (acse_conn->state == STATE_AARE_ABANDON) */ +/* in tp4_connect_cnf or tp4_data_ind, call */ +/* tp4_disconnect and free acse_conn. */ +/* 04/16/96 JRB 08 Copy rcv_data and rcv_data_len to local */ +/* variables in tp4_data_ind for safe freeing. */ +/* 03/26/96 MDE 07 Added REDUCED_STACK support */ +/* 03/11/96 JRB 06 Move acse_msgsize to acse2enc.c */ +/* 03/08/96 JRB 05 Define thisFileName even if !DEBUG_MMS. */ +/* 03/07/96 JRB 04 Set default for acse_msgsize in case */ +/* a_set_msgsize not called by user. */ +/* 02/16/96 JRB 03 Clean up asn1_set_dec_err codes. */ +/* 12/29/95 JRB 02 Broke up tp4_data_ind into subfunctions. */ +/* 10/30/95 JRB 01 Created */ +/************************************************************************/ +static char *thisFileName = __FILE__; + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "asn1defs.h" +#include "asn1log.h" /* for ASN.1 decode logging */ +#include "acseauth.h" +#include "acse2.h" +#if defined (MOSI) +#include "copp_usr.h" +#endif /* MOSI */ +#include "tp4api.h" +#include "tp4.h" /* need MIN_TP0_CONN_ID definition */ + +/************************************************************************/ +/************************************************************************/ + +static MMS_OBJ_ID *my_obj_id; +static ST_INT32 *my_i32; +static ST_INT16 *my_i16; + +static AARQ_APDU aarq_apdu; +static AARE_APDU aare_apdu; +static RLRQ_APDU rlrq_apdu; +static RLRE_APDU rlre_apdu; +static ABRT_APDU abrt_apdu; + +static ST_VOID decode_aarq (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_aarq_main (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code); +static ST_VOID decode_aarq_done (ASN1_DEC_CTXT *aCtx); + +static ST_VOID decode_aare (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_aare_main (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code); +static ST_VOID decode_aare_done (ASN1_DEC_CTXT *aCtx); + +static ST_VOID decode_rlrq (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_rlrq_main (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code); +static ST_VOID decode_rlrq_done (ASN1_DEC_CTXT *aCtx); + +static ST_VOID decode_rlre (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_rlre_main (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code); +static ST_VOID decode_rlre_done (ASN1_DEC_CTXT *aCtx); + +static ST_VOID decode_abrt (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_abrt_main (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code); +static ST_VOID decode_abrt_done (ASN1_DEC_CTXT *aCtx); + +static ST_VOID decode_obj_id (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_i32 (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_i16 (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_result_source1 (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_result_source2 (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_acse_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_constr_done (ASN1_DEC_CTXT *aCtx); +/* DEBUG: all calls to tp4_reldata could be eliminated if tp4 quits */ +/* allocating data buffers. This would save a malloc and a memcpy in tp4.*/ + +static ST_CHAR *a_auth_password_dec (ST_UCHAR *asn1_ptr); +static ST_RET _a_dec_authentication (ACSE_AUTH_INFO *authInfo, /* out */ + ST_UCHAR *auth_value, /* in */ + ST_INT auth_value_len); /* in */ + + +#if defined (MOSI) +ACSE_CONN *decode_acse_conn; /* connection we're doing decode for. */ + +static ST_VOID END_user_info (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/* u_copp_con_cnf */ +/* P-CONNECT.cnf (Connect Confirm). */ +/* Parameters: */ +/* acse_conn Pointer to connection info */ +/* result P_CON_RESULT_ACCEPT, P_CON_RESULT_USER_REJ or */ +/* P_CON_RESULT_PROVIDER_REJ */ +/* reason Provider-reason (if result=P_CON_RESULT_PROVIDER_REJ)*/ +/************************************************************************/ +ST_VOID u_copp_con_cnf (ACSE_CONN *acse_conn, ST_INT result, ST_INT reason) + { +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean */ + + if (acse_conn->state != STATE_AARE_WAIT) + { + ACSELOG_ERR0 ("ACSE-ERROR: Ignoring unexpected P-CONNECT.cnf"); + return; + } + if (result == P_CON_RESULT_PROVIDER_REJ) + { /* No AARE to decode. */ + ACSELOG_DEC2 ("A-ASSOCIATE.cnf-: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + ACSELOG_DEC1C ("Rejected by PS-provider. Provider-reason = %d. No P-user-data.", + reason); + + /* ACSE spec says to pass "A-ASSOCIATE.cnf-" primitive to */ + /* ACSE-user, but ACSE-user may not handle it with no AARE info, so */ + /* pass "A-P-ABORT.ind" primitive instead. The result is the same. */ + abrt_apdu.source = ACSE_SERVICE_PROVIDER; + abrt_apdu.user_info.len = 0; + u_a_abort_ind (acse_conn->user_conn_id, &abrt_apdu); + acse_conn->state = STATE_IDLE; + /* DON'T free acse_conn. COSP will free it when T-DISCONNECT done. */ + return; + } + + /* result != P_CON_RESULT_PROVIDER_REJ. Decode AARE. */ + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + decode_acse_conn = acse_conn; /* Save in global so asn1r_decode_asn1 (aCtx, */ + /* can fill it in. */ + + /* CRITICAL: Init global PDV ptr & len. Changed only if PDV found in msg.*/ + pdv_data_ptr = NULL; + pdv_data_len = 0; + + ASN1R_TAG_ADD (aCtx, APP|CONSTR,TAG_AARE,decode_aare); + asn1r_decode_asn1 (aCtx, acse_conn->apdu_ptr,acse_conn->apdu_len); /* decode APDU */ + + if (aCtx->asn1r_pdu_dec_err == NO_DECODE_ERR) + { /* Handle AARE. */ + if (aare_apdu.result == 0) + { + acse_conn->initiator = SD_TRUE; + acse_conn->state = STATE_ASSOCIATED; + ACSELOG_DEC2 ("A-ASSOCIATE.cnf+: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + } + else + { + acse_conn->state = STATE_IDLE; + ACSELOG_DEC2 ("A-ASSOCIATE.cnf-: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + } + + /* save partner's security info to the ACSE_CONN for user's anytime examination */ + acse_conn->part_auth_info = aare_apdu.auth_info; + if (aare_apdu.auth_info.mech_type == ACSE_AUTH_MECH_OTHER) + { + /* allocate buffer for the Authentication Value */ + acse_conn->part_auth_info.u.other_auth.auth_value.buf = acse_conn->part_auth_info.u.other_auth.auth_value.ptr = + (ST_UCHAR *) chk_calloc (aare_apdu.auth_info.u.other_auth.auth_value.len, sizeof(ST_CHAR)); + memcpy (acse_conn->part_auth_info.u.other_auth.auth_value.ptr, aare_apdu.auth_info.u.other_auth.auth_value.ptr, + aare_apdu.auth_info.u.other_auth.auth_value.len); + } + aare_apdu.encrypt_ctrl = acse_conn->encrypt_ctrl; + + u_a_associate_cnf ((ST_LONG) acse_conn, (ST_LONG) acse_conn->user_conn_id, + &aare_apdu); + } + else + { /* Handle ASN1 decode error. */ + ACSELOG_ERR0 ("ACSE-ERROR: AARE decode failed. Aborting."); + /* Pass up A-P-ABORT.ind */ + abrt_apdu.source = ACSE_SERVICE_PROVIDER; + abrt_apdu.user_info.len = 0; + u_a_abort_ind (acse_conn->user_conn_id, &abrt_apdu); + + acse_conn->state = STATE_IDLE; + + /* NOTE: Send copp_u_abort_req ONLY IF COPP accepted conn. */ + if (result == P_CON_RESULT_ACCEPT) + copp_u_abort_req (acse_conn); + /* CRITICAL: DO NOT access acse_conn after abort. It may have been */ + /* freed by cosp_u_abort_req (called from copp_u_abort_req). */ + } + return; + } + +/************************************************************************/ +/* u_copp_rel_cnf_pos */ +/* P-RELEASE.cnf+ (POSITIVE Release Confirm). */ +/* Must be RLRE APDU. Decode it and call u_a_release_cnf. */ +/************************************************************************/ +ST_VOID u_copp_rel_cnf_pos (ACSE_CONN *acse_conn) + { +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean */ + + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + decode_acse_conn = acse_conn; /* Save in global so asn1r_decode_asn1 (aCtx, */ + /* can fill it in. */ + + /* CRITICAL: Init global PDV ptr & len. Changed only if PDV found in msg.*/ + pdv_data_ptr = NULL; + pdv_data_len = 0; + + ASN1R_TAG_ADD (aCtx, APP|CONSTR,TAG_RLRE,decode_rlre); + asn1r_decode_asn1 (aCtx, acse_conn->apdu_ptr,acse_conn->apdu_len); /* decode APDU */ + + if (aCtx->asn1r_pdu_dec_err == NO_DECODE_ERR) + { + /* Handle RLRE. */ + switch (acse_conn->state) + { + case STATE_RLRE_WAIT: + acse_conn->state = STATE_IDLE; + ACSELOG_DEC2 ("A-RELEASE.cnf+: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + u_a_release_cnf (acse_conn->user_conn_id, &rlre_apdu); + break; + + case STATE_RESP_COLL: + acse_conn->state = STATE_ARLSRSP_WAIT; + ACSELOG_DEC2 ("A-RELEASE.cnf+: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + u_a_release_cnf (acse_conn->user_conn_id, &rlre_apdu); + break; + + default: + u_a_except (acse_conn->user_conn_id, EX_ACSE_INVALID_STATE, + thisFileName, __LINE__); + break; + } /* end "switch" */ + } + else + { + /* Handle ASN1 decode error. */ + ACSELOG_ERR0 ("ACSE-ERROR: RLRE decode failed. Aborting."); + /* Pass up A-P-ABORT.ind */ + abrt_apdu.source = ACSE_SERVICE_PROVIDER; + abrt_apdu.user_info.len = 0; + u_a_abort_ind (acse_conn->user_conn_id, &abrt_apdu); + + acse_conn->state = STATE_IDLE; + } + } + + +/************************************************************************/ +/* u_copp_con_ind */ +/* P-Connect Indication. */ +/* Must be AARQ APDU. Decode it and call u_a_associate_ind. */ +/************************************************************************/ +ST_VOID u_copp_con_ind (ST_LONG user_bind_id, ACSE_CONN *acse_conn) + { +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; +ST_INT j; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean */ + + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + decode_acse_conn = acse_conn; /* Save in global so asn1r_decode_asn1 (aCtx, */ + /* can fill it in. */ + + /* CRITICAL: Init global PDV ptr & len. Changed only if PDV found in msg.*/ + pdv_data_ptr = NULL; + pdv_data_len = 0; + + ASN1R_TAG_ADD (aCtx, APP|CONSTR,TAG_AARQ,decode_aarq); + asn1r_decode_asn1 (aCtx, acse_conn->apdu_ptr,acse_conn->apdu_len); /* decode APDU */ + + if (aCtx->asn1r_pdu_dec_err == NO_DECODE_ERR) + { + /* Handle AARQ. */ + acse_conn->state = STATE_AASCRSP_WAIT; + + /* Copy "calling" (remote) address to aarq_apdu. */ + if ((aarq_apdu.calling_paddr.psel_len = acse_conn->rem_psel[0])!=0) + memcpy (aarq_apdu.calling_paddr.psel, &acse_conn->rem_psel[1], + acse_conn->rem_psel[0]); + if ((aarq_apdu.calling_paddr.ssel_len = acse_conn->rem_ssel[0])!=0) + memcpy (aarq_apdu.calling_paddr.ssel, &acse_conn->rem_ssel[1], + acse_conn->rem_ssel[0]); + if ((aarq_apdu.calling_paddr.tsel_len = acse_conn->rem_tsel[0])!=0) + memcpy (aarq_apdu.calling_paddr.tsel, &acse_conn->rem_tsel[1], + acse_conn->rem_tsel[0]); + + if (acse_conn->tp4_conn_id >= MIN_TP0_CONN_ID) /* This is TP0 conn. Save IP addr*/ + { + aarq_apdu.calling_paddr.tp_type = TP_TYPE_TCP; + aarq_apdu.calling_paddr.netAddr.ip = acse_conn->remNetAddr.ip; + } + else /* This is TP4 conn. Save NSAP */ + { + aarq_apdu.calling_paddr.tp_type = TP_TYPE_TP4; + if ((aarq_apdu.calling_paddr.nsap_len = acse_conn->remNetAddr.nsap[0])!=0) + memcpy (aarq_apdu.calling_paddr.netAddr.nsap, &acse_conn->remNetAddr.nsap[1], + acse_conn->remNetAddr.nsap[0]); + } + + /* Copy "called" (local) address (except NSAP) to aarq_apdu. */ + /* NOTE: "called" tp_type must be same as "calling". */ + aarq_apdu.called_paddr.tp_type = aarq_apdu.calling_paddr.tp_type; + if ((aarq_apdu.called_paddr.psel_len = acse_conn->loc_psel[0])!=0) + memcpy (aarq_apdu.called_paddr.psel, &acse_conn->loc_psel[1], + acse_conn->loc_psel[0]); + if ((aarq_apdu.called_paddr.ssel_len = acse_conn->loc_ssel[0])!=0) + memcpy (aarq_apdu.called_paddr.ssel, &acse_conn->loc_ssel[1], + acse_conn->loc_ssel[0]); + if ((aarq_apdu.called_paddr.tsel_len = acse_conn->loc_tsel[0])!=0) + memcpy (aarq_apdu.called_paddr.tsel, &acse_conn->loc_tsel[1], + acse_conn->loc_tsel[0]); + + ACSELOG_DEC1 ("A-ASSOCIATE.ind: acse_conn_id =0x%08X", acse_conn); + ACSELOG_DEC0C ("DST (CALLED) ADDRESS:"); + if (aarq_apdu.called_ae_title.AP_title_pres) + { + for (j = 0; j < aarq_apdu.called_ae_title.AP_title.num_comps; ++j) + { /* Verbose but gets the job done. */ + ACSELOG_DEC2C (" AP_title.comps[%d] = %d", + j, aarq_apdu.called_ae_title.AP_title.comps[j]); + } + } + if (aarq_apdu.called_ae_title.AE_qual_pres) + { + ACSELOG_DEC1C (" AE_qual = %ld", aarq_apdu.called_ae_title.AE_qual); + } + ACSELOG_DEC0C (" PSEL:"); + ACSELOG_DECH (aarq_apdu.called_paddr.psel_len, aarq_apdu.called_paddr.psel); + ACSELOG_DEC0C (" SSEL:"); + ACSELOG_DECH (aarq_apdu.called_paddr.ssel_len, aarq_apdu.called_paddr.ssel); + ACSELOG_DEC0C (" TSEL:"); + ACSELOG_DECH (aarq_apdu.called_paddr.tsel_len, aarq_apdu.called_paddr.tsel); + + ACSELOG_DEC0C ("SRC (CALLING) ADDRESS:"); + if (aarq_apdu.calling_ae_title.AP_title_pres) + { + for (j = 0; j < aarq_apdu.calling_ae_title.AP_title.num_comps; ++j) + { /* Verbose but gets the job done. */ + ACSELOG_DEC2C (" AP_title.comps[%d] = %d", + j, aarq_apdu.calling_ae_title.AP_title.comps[j]); + } + } + if (aarq_apdu.calling_ae_title.AE_qual_pres) + { + ACSELOG_DEC1C (" AE_qual = %ld", aarq_apdu.calling_ae_title.AE_qual); + } + ACSELOG_DEC0C (" PSEL:"); + ACSELOG_DECH (aarq_apdu.calling_paddr.psel_len, aarq_apdu.calling_paddr.psel); + ACSELOG_DEC0C (" SSEL:"); + ACSELOG_DECH (aarq_apdu.calling_paddr.ssel_len, aarq_apdu.calling_paddr.ssel); + ACSELOG_DEC0C (" TSEL:"); + ACSELOG_DECH (aarq_apdu.calling_paddr.tsel_len, aarq_apdu.calling_paddr.tsel); + if (aarq_apdu.calling_paddr.tp_type == TP_TYPE_TCP) + { +#if defined(TP0_ENABLED) + struct in_addr sin_addr; /* inet_ntoa needs this addr format*/ + sin_addr.s_addr = aarq_apdu.calling_paddr.netAddr.ip; + ACSELOG_DEC1C (" IP ADDR: %s", inet_ntoa (sin_addr)); +#else + ACSELOG_ERR0 ("Received TCP conn ind. TCP not supported"); +#endif + } + else + { + ACSELOG_DEC0C (" NSAP:"); + ACSELOG_DECH (aarq_apdu.calling_paddr.nsap_len, aarq_apdu.calling_paddr.netAddr.nsap); + } + + /* save partner's security info to the ACSE_CONN for user's anytime examination */ + acse_conn->part_auth_info = aarq_apdu.auth_info; + if (aarq_apdu.auth_info.mech_type == ACSE_AUTH_MECH_OTHER) + { + /* allocate buffer for the Authentication Value */ + acse_conn->part_auth_info.u.other_auth.auth_value.buf = acse_conn->part_auth_info.u.other_auth.auth_value.ptr = + (ST_UCHAR *) chk_calloc (aarq_apdu.auth_info.u.other_auth.auth_value.len, sizeof(ST_CHAR)); + memcpy (acse_conn->part_auth_info.u.other_auth.auth_value.ptr, aarq_apdu.auth_info.u.other_auth.auth_value.ptr, + aarq_apdu.auth_info.u.other_auth.auth_value.len); + } + aarq_apdu.encrypt_ctrl = acse_conn->encrypt_ctrl; + + u_a_associate_ind (user_bind_id, (ST_LONG) acse_conn, &aarq_apdu); + } + else + { + /* Handle ASN1 decode error. */ + /* According to the ACSE spec section 7.3.3.4 (pg 20) we should */ + /* be sending an Abort PDU upon protocol error. */ + ACSELOG_ERR0 ("ACSE-ERROR: AARQ decode failed"); + copp_u_abort_req (acse_conn); + acse_conn->state = STATE_IDLE; + } + } + +/************************************************************************/ +/* u_copp_rel_ind */ +/* P-Release Indication. */ +/* Must be RLRQ APDU. Decode it and call u_a_release_ind. */ +/************************************************************************/ +ST_VOID u_copp_rel_ind (ACSE_CONN *acse_conn) + { +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean */ + + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + decode_acse_conn = acse_conn; /* Save in global so asn1r_decode_asn1 (aCtx, */ + /* can fill it in. */ + + /* CRITICAL: Init global PDV ptr & len. Changed only if PDV found in msg.*/ + pdv_data_ptr = NULL; + pdv_data_len = 0; + + ASN1R_TAG_ADD (aCtx, APP|CONSTR,TAG_RLRQ,decode_rlrq); + asn1r_decode_asn1 (aCtx, acse_conn->apdu_ptr,acse_conn->apdu_len); /* decode APDU */ + + if (aCtx->asn1r_pdu_dec_err == NO_DECODE_ERR) + { + /* Handle RLRQ. */ + switch (acse_conn->state) + { + case STATE_ASSOCIATED: + acse_conn->state = STATE_ARLSRSP_WAIT; + ACSELOG_DEC2 ("A-RELEASE.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + u_a_release_ind (acse_conn->user_conn_id, &rlrq_apdu); + break; + + case STATE_RLRE_WAIT: + if (acse_conn->initiator) + acse_conn->state = STATE_INIT_COLL; + else + acse_conn->state = STATE_RESP_COLL; + ACSELOG_DEC2 ("A-RELEASE.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + u_a_release_ind (acse_conn->user_conn_id, &rlrq_apdu); + break; + + default: + u_a_except (acse_conn->user_conn_id, EX_ACSE_INVALID_STATE, + thisFileName, __LINE__); + break; + } /* end "switch" */ + } + else + { + /* Handle ASN1 decode error. */ + ACSELOG_ERR0 ("ACSE-ERROR: RLRQ decode failed"); + } + } + +/************************************************************************/ +/* u_copp_p_abort_ind */ +/* P-P-Abort Indication. */ +/* ACSE doesn't need to decode anything. Just pass up A-P-ABORT.ind */ +/************************************************************************/ +ST_VOID u_copp_p_abort_ind (ACSE_CONN *acse_conn, ST_INT reason) + { + acse_conn->state = STATE_IDLE; + ACSELOG_DEC2 ("A-P-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + ACSELOG_DEC1C ("Provider-reason = %d", reason); + /* Pass up A-P-ABORT.ind */ + abrt_apdu.source = ACSE_SERVICE_PROVIDER; + abrt_apdu.user_info.len = 0; + u_a_abort_ind (acse_conn->user_conn_id, &abrt_apdu); + } + +/************************************************************************/ +/* u_copp_u_abort_ind */ +/* P-U-Abort Indication. */ +/* Must be ABRT APDU. Decode it and call u_a_abort_ind. */ +/************************************************************************/ +ST_VOID u_copp_u_abort_ind (ACSE_CONN *acse_conn) + { +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean */ + + /* This must be ABRT. Perform ASN1 Decode of ABRT. */ + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + decode_acse_conn = acse_conn; /* Save in global so asn1r_decode_asn1 (aCtx, */ + /* can fill it in. */ + + /* CRITICAL: Init global PDV ptr & len. Changed only if PDV found in msg.*/ + pdv_data_ptr = NULL; + pdv_data_len = 0; + + ASN1R_TAG_ADD (aCtx, APP|CONSTR,TAG_ABRT,decode_abrt); + asn1r_decode_asn1 (aCtx, acse_conn->apdu_ptr,acse_conn->apdu_len); /* decode APDU */ + + /* "asn1r_decode_asn1 (aCtx," has filled in Global "abrt_apdu" structure. */ + + if (aCtx->asn1r_pdu_dec_err != NO_DECODE_ERR) + { + ACSELOG_ERR1 ("ACSE-ERROR: ABRT decode failed (code = %d). Call u_a_abort_ind anyway.", + aCtx->asn1r_pdu_dec_err); + /* Fill "abrt_apdu" with defaults (possibly corrupted during decode).*/ + abrt_apdu.source = ACSE_SERVICE_USER; + abrt_apdu.user_info.len = 0; + } + + acse_conn->state = STATE_IDLE; + ACSELOG_DEC2 ("A-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + u_a_abort_ind (acse_conn->user_conn_id, &abrt_apdu); + } + +/************************************************************************/ +/* u_copp_data_ind */ +/* P-Data Indication. */ +/* ACSE doesn't need to decode anything. Just call u_a_data_ind. */ +/************************************************************************/ +ST_VOID u_copp_data_ind (ACSE_CONN *acse_conn) + { + u_a_data_ind (acse_conn->user_conn_id, acse_conn->apdu_len, acse_conn->apdu_ptr); + } + +#else /* !MOSI */ + +static ST_INT acse_tag; + +static ST_BOOLEAN tp4_data_ind_aarqind (ACSE_CONN *acse_conn, ST_UINT len); +static ST_BOOLEAN tp4_data_ind_aarqcnf (ACSE_CONN *acse_conn, ST_UINT len); +static ST_RET acse_decode (ASN1_DEC_CTXT *aCtx, ST_UCHAR *msg_ptr, ST_UINT len); + +/************************************************************************/ +/* tp4_session_timer_expired */ +/*----------------------------------------------------------------------*/ +/* This function is called by TP4 when the session_timer expires. */ +/* TRIM-7 does not use any Session timers, so this function will */ +/* never be called. It's only purpose is to resolve link with LEAN_T. */ +/* For MOSI, the "tp4_session_timer_expired" function is in COSP????.C */ +/************************************************************************/ +ST_VOID tp4_session_timer_expired (ST_LONG user_conn_id) + { + } + +/************************************************************************/ +/* tp4_bind_cnf */ +/************************************************************************/ +ST_VOID tp4_bind_cnf (ST_LONG user_bind_id, ST_LONG copp_bind_id, ST_RET result) + { + ACSELOG_DEC2 ("COPP-Bind Cnf. user_bind_id =%9ld copp_bind_id =%9ld", + user_bind_id, copp_bind_id); + u_copp_bind_cnf (user_bind_id, copp_bind_id, result); + } + +/************************************************************************/ +/* tp4_unbind_cnf */ +/************************************************************************/ +ST_VOID tp4_unbind_cnf (ST_LONG user_bind_id) + { + ACSELOG_DEC1 ("COPP-Unbind Cnf. user_bind_id =%9ld", user_bind_id); + u_copp_unbind_cnf (user_bind_id); + } + +/************************************************************************/ +/* tp4_connect_ind */ +/* This function is called by the Transport provider when an ACSE */ +/* Associate request is received. */ +/************************************************************************/ +ST_VOID tp4_connect_ind ( + ST_LONG user_bind_id, + ST_LONG tp4_conn_id, /* TP4's connection ID */ + TP4_ADDR *rem_tp4_addr, + ST_INT data_len, + char *data) + { + ACSE_CONN * acse_conn; + /* This function uses global "aarq_apdu" - Decoded Associate Req Data.*/ + + tp4_reldata (data); /* I never use this. */ + + acse_conn = (ACSE_CONN *) M_CALLOC (MSMEM_ACSE_CONN, 1, sizeof (ACSE_CONN)); + + /* Save TP4's connection ID. Use it in calls to TP4 functions. */ + acse_conn->tp4_conn_id = tp4_conn_id; + /* Save user_bind_id for later passing to u_a_associate_ind */ + acse_conn->user_bind_id = user_bind_id; + + tp4_accept (tp4_conn_id, (ST_LONG) acse_conn, 15, "SISCO Transport"); + return; + } + +/************************************************************************/ +/* tp4_connect_cnf */ +/* This function is called by the Transport provider when a POSITIVE */ +/* T-CONNECT confirm is received. */ +/* Now send the AARQ APDU (save_buf) that was built by a_associate_req. */ +/************************************************************************/ +ST_VOID tp4_connect_cnf ( + ST_LONG acse_conn_id, + ST_LONG tp4_conn_id, /* TP4's connection ID */ + ST_INT data_len, + char *data) + { + ACSE_CONN * acse_conn; + /* This function uses global "aare_apdu" - Decoded Associate Rsp Data. */ + + tp4_reldata (data); /* I never use this. */ + + acse_conn = (ACSE_CONN *) acse_conn_id; + + if (acse_conn->state == STATE_AARE_ABANDON) + { + /* User already aborted. Couldn't wait for cnf (impatient!!) */ + tp4_disconnect (tp4_conn_id, 0, NULL); + acse_free_con (acse_conn); + return; + } + + if (acse_conn->state != STATE_TP4CONN_WAIT) + { + u_a_except (acse_conn->user_conn_id, EX_ACSE_INVALID_STATE, + thisFileName, __LINE__); + acse_free_con (acse_conn); /* Dump conn tracking struct */ + return; + } + + /* Save TP4's connection ID. Use it in calls to TP4 functions. */ + acse_conn->tp4_conn_id = tp4_conn_id; + + /* Send saved AARQ APDU (save_buf) via Transport Data request. */ + if (tp4_data (acse_conn->tp4_conn_id, 1, (ST_UINT) acse_conn->save_buf.len, + (ST_CHAR *) acse_conn->save_buf.ptr) != SD_SUCCESS) + { /* This should never happen. */ + ACSELOG_ERR0 ("ACSE-ERROR: AARQ APDU could not be sent. Unrecoverable"); + } + /* Free encoded AARQ buffer now. Reset len so know not to free later. */ + M_FREE (MSMEM_ACSE_DATA, acse_conn->save_buf.ptr); + acse_conn->save_buf.len = 0; /* This indicates "ptr" has been freed. */ + + acse_conn->state = STATE_AARE_WAIT; /* Waiting for AARE-apdu */ + } + +/************************************************************************/ +/* tp4_disconnect_ind */ +/************************************************************************/ +ST_VOID tp4_disconnect_ind ( + ST_LONG acse_conn_id, + ST_INT reason, + ST_INT data_len, + char *data) + { + ACSE_CONN * acse_conn; + + tp4_reldata (data); /* I never use this. */ + + acse_conn = (ACSE_CONN *) acse_conn_id; + + /* Only pass up abort to user if not already in idle state. */ + if (acse_conn->state != STATE_IDLE) + { + if (reason == 0) + { + ACSELOG_DEC2 ("A-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + abrt_apdu.source = ACSE_SERVICE_USER; + } + else + { + ACSELOG_DEC2 ("A-P-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + abrt_apdu.source = ACSE_SERVICE_PROVIDER; + } + + abrt_apdu.user_info.len = 0; + u_a_abort_ind (acse_conn->user_conn_id, &abrt_apdu); + } + + /* In any case, we're done with this connection. */ + acse_free_con (acse_conn); /* Dump conn tracking struct */ + return; + } + +/************************************************************************/ +/* tp4_data_ind */ +/* This function is called by the Transport provider when a data packet */ +/* is received on a previously established connection. */ +/* It could be one of the following PDUs: */ +/* A-RELEASE.ind */ +/* A-RELEASE.cnf */ +/* DEBUG: MUST call tp4_reldata before returning from this function. */ +/************************************************************************/ +ST_VOID tp4_data_ind ( + ST_LONG acse_conn_id, + ST_INT eot, + ST_UINT data_len, + char *data) + { + /* This function uses globals "rlrq_apdu", "rlre_apdu", etc. */ + ACSE_CONN * acse_conn; + ST_BOOLEAN free_flag = SD_FALSE; /* Flag: does acse_conn need to be freed?*/ + ST_UCHAR *rcv_data; /* Local copy of data ptr. */ + ST_UINT rcv_data_len; /* Local copy of data len. */ + ASN1_DEC_CTXT aLocalCtx; + ASN1_DEC_CTXT *aCtx = &aLocalCtx; + + acse_conn = (ACSE_CONN *) acse_conn_id; + + if (acse_conn->state == STATE_AARE_ABANDON) + { + /* User already aborted. Couldn't wait for cnf (impatient!!) */ + tp4_disconnect (acse_conn->tp4_conn_id, 0, NULL); + acse_free_con (acse_conn); + return; + } + + if (eot == 0) + { /* NOT complete PDU, so just save data and return. */ + if (acse_conn->rcv_data_len == 0) + acse_conn->rcv_data = (ST_UCHAR *) M_CALLOC (MSMEM_ACSE_DATA, 1, acse_msgsize); + if (acse_conn->rcv_data_len + data_len > acse_msgsize) + { + u_a_except (acse_conn->user_conn_id, EX_ACSE_DECODE, + thisFileName, __LINE__); + acse_free_con (acse_conn); /* Dump conn tracking struct */ + tp4_reldata (data); + return; + } + memcpy (acse_conn->rcv_data + acse_conn->rcv_data_len, data, data_len); + acse_conn->rcv_data_len += data_len; + tp4_reldata (data); + return; + } + else + { /* eot != 0 */ + /* Complete PDU or Last piece of assembled PDU. */ + if (acse_conn->rcv_data_len == 0) + { /* This is complete PDU */ + /* DO NOT ALLOCATE a rcv buffer & DO NOT COPY DATA. */ + /* Just set "acse_conn->rcv_data" to point to data. */ + /* At end of function, if (acse_conn->rcv_data_len == data_len), */ + /* DO NOT FREE "acse_conn->rcv_data". */ + acse_conn->rcv_data = (ST_UCHAR *) data; + } + else + { /* This is last piece of assembled PDU */ + memcpy (acse_conn->rcv_data + acse_conn->rcv_data_len, data, data_len); + } + acse_conn->rcv_data_len += data_len; + } + + /* Save ptr in local variable so it can be freed later. */ + rcv_data = acse_conn->rcv_data; + + /* Save len in local variable and reset it so ready for next indication.*/ + rcv_data_len = acse_conn->rcv_data_len; + acse_conn->rcv_data_len = 0; + /* WARNING: acse_conn->rcv_data_len must not be used by any functions */ + /* called after this point because it's already been reset. */ + + /******* HAVE A COMPLETE PDU NOW. HANDLE ALL POSSIBLE PDUs. *********/ + + if (acse_conn->state == STATE_IDLE) + { /* Handle A-Associate indication. */ + free_flag = tp4_data_ind_aarqind (acse_conn, rcv_data_len); + } + else if (acse_conn->state == STATE_AARE_WAIT) + { /* Handle A-Associate confirm. */ + free_flag = tp4_data_ind_aarqcnf (acse_conn, rcv_data_len); + } + else if ((acse_conn->rcv_data[0] & 0xC0) != APP) /* chk ASN.1 class*/ + { /* Handle NON-ACSE PDU. */ + /* Pass up to user (i.e. MMS). */ + ACSELOG_DEC2 ("A-DATA.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + ACSELOG_DEC1C ("User data length: %d", rcv_data_len); + u_a_data_ind (acse_conn->user_conn_id, rcv_data_len, acse_conn->rcv_data); + } + else if (acse_decode (aCtx, acse_conn->rcv_data, rcv_data_len) == SD_SUCCESS) + { /* Handle all other ACSE PDUs. */ + switch (acse_tag) /* acse_tag set by acse_decode above. */ + { + case TAG_RLRQ: + switch (acse_conn->state) + { + case STATE_ASSOCIATED: + acse_conn->state = STATE_ARLSRSP_WAIT; + ACSELOG_DEC2 ("A-RELEASE.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + u_a_release_ind (acse_conn->user_conn_id, &rlrq_apdu); + break; + + case STATE_RLRE_WAIT: + if (acse_conn->initiator) + acse_conn->state = STATE_INIT_COLL; + else + acse_conn->state = STATE_RESP_COLL; + u_a_release_ind (acse_conn->user_conn_id, &rlrq_apdu); + break; + + default: + u_a_except (acse_conn->user_conn_id, EX_ACSE_INVALID_STATE, + thisFileName, __LINE__); + break; + } /* end inner "switch" */ + break; + + case TAG_RLRE: + switch (acse_conn->state) + { + case STATE_RLRE_WAIT: + acse_conn->state = STATE_IDLE; + ACSELOG_DEC2 ("A-RELEASE.cnf: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + u_a_release_cnf (acse_conn->user_conn_id, &rlre_apdu); + tp4_disconnect (acse_conn->tp4_conn_id, 0, NULL); + free_flag = SD_TRUE; /* conn tracking struct must be freed */ + break; + + case STATE_RESP_COLL: + acse_conn->state = STATE_ARLSRSP_WAIT; + ACSELOG_DEC2 ("A-RELEASE.cnf: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + u_a_release_cnf (acse_conn->user_conn_id, &rlre_apdu); + break; + + default: + u_a_except (acse_conn->user_conn_id, EX_ACSE_INVALID_STATE, + thisFileName, __LINE__); + break; + } /* end inner "switch" */ + break; + + default: + /* Illegal from this ACSE state. */ + u_a_except (acse_conn->user_conn_id, EX_ACSE_INVALID_STATE, + thisFileName, __LINE__); + break; + } /* end outer "switch" */ + } /* end big "else" */ + + if (rcv_data_len != data_len) + M_FREE (MSMEM_ACSE_DATA, rcv_data); + if (free_flag) /* Does acse_conn need to be freed ?? */ + acse_free_con (acse_conn); + tp4_reldata (data); + return; + } + +/************************************************************************/ +/* tp4_data_ind_aarqind */ +/* Subfunction for "tp4_data_ind" to handle AARQ.ind */ +/* RETURNS: SD_TRUE (means acse_conn needs to be freed) */ +/* SD_FALSE (means acse_conn does NOT need to be freed) */ +/************************************************************************/ +static ST_BOOLEAN tp4_data_ind_aarqind (ACSE_CONN *acse_conn, + ST_UINT rcv_data_len) + { +ST_UCHAR *msg_ptr; +ST_UINT len; +ASN1_DEC_CTXT aLocalCtx; +ASN1_DEC_CTXT *aCtx = &aLocalCtx; + + /* Strip off Fastbyte Session and Presentation bytes. */ +#if !defined(REDUCED_STACK) + if ((ST_UCHAR) acse_conn->rcv_data [0] == 0xE8 && + acse_conn->rcv_data [1] == 0x01) + { + msg_ptr = &acse_conn->rcv_data [2]; + len = rcv_data_len-2; +#else + { + msg_ptr = acse_conn->rcv_data; + len = rcv_data_len; +#endif + /* Decode the AARQ APDU and fill in the AARQ_APDU structure. */ + if (acse_decode (aCtx, msg_ptr, len) == SD_SUCCESS) + { + if (acse_tag == TAG_AARQ) + { + acse_conn->state = STATE_AASCRSP_WAIT; + ACSELOG_DEC1 ("A-ASSOCIATE.ind: acse_conn_id =0x%08X", acse_conn); + u_a_associate_ind (acse_conn->user_bind_id, (ST_LONG) acse_conn, &aarq_apdu); + return (SD_FALSE); + } + } + } + + ACSELOG_ERR0 ("ACSE-ERROR: AARQ decode failed"); + tp4_disconnect (acse_conn->tp4_conn_id, 0, NULL); + return (SD_TRUE); + } + +/************************************************************************/ +/* tp4_data_ind_aarqcnf */ +/* Subfunction for "tp4_data_ind" to handle AARQ.cnf */ +/* RETURNS: SD_TRUE (means acse_conn needs to be freed) */ +/* SD_FALSE (means acse_conn does NOT need to be freed) */ +/************************************************************************/ +static ST_BOOLEAN tp4_data_ind_aarqcnf (ACSE_CONN *acse_conn, + ST_UINT rcv_data_len) + { +ST_UCHAR *msg_ptr; +ST_UINT len; +ASN1_DEC_CTXT aLocalCtx; +ASN1_DEC_CTXT *aCtx = &aLocalCtx; + + /* Strip off Fastbyte Session byte. */ +#if !defined(REDUCED_STACK) + if ((ST_UCHAR) acse_conn->rcv_data [0] == 0xF0 || /* Short-SAC */ + (ST_UCHAR) acse_conn->rcv_data [0] == 0xE3 || /* Short-SRF, permanent */ + (ST_UCHAR) acse_conn->rcv_data [0] == 0xE2) /* Short-SRF, transient */ + { + /* Strip off Fastbyte Presentation byte. */ + if (acse_conn->rcv_data [1] == 0x01) /* Short-CP */ + { + msg_ptr = &acse_conn->rcv_data [2]; + len = rcv_data_len-2; +#else + { + { + msg_ptr = acse_conn->rcv_data; + len = rcv_data_len; +#endif + /* Decode the AARE APDU and fill in the AARE_APDU structure. */ + if (acse_decode (aCtx, msg_ptr, len) == SD_SUCCESS) + { + if (acse_tag == TAG_AARE) + { + ACSELOG_DEC2 ("A-ASSOCIATE.cnf: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + u_a_associate_cnf ((ST_LONG) acse_conn, (ST_LONG) acse_conn->user_conn_id, + &aare_apdu); + if (aare_apdu.result == 0) + { + acse_conn->initiator = SD_TRUE; + acse_conn->state = STATE_ASSOCIATED; + return (SD_FALSE); + } + else + { + tp4_disconnect (acse_conn->tp4_conn_id, 0, NULL); + return (SD_TRUE); /* Only so don't call u_a_except. */ + } + } + } + } + } + + ACSELOG_ERR0 ("ACSE-ERROR: AARE decode failed"); + tp4_disconnect (acse_conn->tp4_conn_id, 0, NULL); + /* Pass up a Provider Abort Ind. */ + abrt_apdu.source = ACSE_SERVICE_PROVIDER; + abrt_apdu.user_info.len = 0; + ACSELOG_DEC2 ("A-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + u_a_abort_ind (acse_conn->user_conn_id, &abrt_apdu); + return (SD_TRUE); + } + +/************************************************************************/ +/* tp4_expdata_ind */ +/************************************************************************/ +ST_VOID tp4_expdata_ind ( + ST_LONG acse_conn_id, + ST_UINT data_len, + char *data) + { + /* Treat like normal data. Assume "eot" = 1. */ + tp4_data_ind (acse_conn_id, 1, data_len, data); + } + +/************************************************************************/ +/* acse_decode */ +/* Function to setup and initiate MMS PDU decode */ +/* Only fourteen context specific codes are legal at start */ +/* Input parameters : pointer to message start, length of message, */ +/* pointer to result buffer. */ +/************************************************************************/ + +static ST_RET acse_decode (ASN1_DEC_CTXT *aCtx, ST_UCHAR *msg_ptr, ST_UINT len) + { + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + ASN1R_TAG_ADD (aCtx, APP|CONSTR,TAG_AARQ,decode_aarq); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,TAG_AARE,decode_aare); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,TAG_RLRQ,decode_rlrq); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,TAG_RLRE,decode_rlre); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,TAG_ABRT,decode_abrt); + + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + +/* Call 'asn1r_decode_asn1 (aCtx,' to parse the message. */ + + asn1r_decode_asn1 (aCtx, msg_ptr,len); /* do message decode */ + if (aCtx->asn1r_pdu_dec_err == NO_DECODE_ERR) + return (SD_SUCCESS); + ACSELOG_ERR0 ("ACSE-ERROR: decode of APDU failed"); + return (SD_FAILURE); + } + +#endif /* !MOSI */ + +/************************************************************************/ +/* decode_aarq */ +/************************************************************************/ +static ST_VOID decode_aarq (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_method = ASN1_CLASS_METHOD; /* Use ASN1_CLASS_METHOD method to decode. */ + aCtx->asn1r_c_id_fun = decode_aarq_main; + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_aarq_done; + aCtx->asn1r_u_id_fun = asn1r_class_err; /* no universals to start */ + aCtx->asn1r_a_id_fun = asn1r_class_err; /* no applications to start */ + aCtx->asn1r_p_id_fun = asn1r_class_err; /* no privates to start */ + + /* Clean out old stuff from structure. */ + memset (&aarq_apdu, 0, sizeof (aarq_apdu)); + } + +/************************************************************************/ +/* decode_aarq_main */ +/************************************************************************/ +static ST_VOID decode_aarq_main (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code) + { +ST_RET ret; +ST_UCHAR bit_str; +MMS_OBJ_ID mechanism_name; +MMS_OBJ_ID maceMechId = MACE_MECH_ID; + + switch (id_code) + { + case AARQ_protocol_version: + if (aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* constructor not allowed */ + return; + } + /* CRITICAL: asn1r_get_bitstr doesn't set unused bits, so init all bits=0*/ + bit_str = 0; + asn1r_get_bitstr (aCtx, &bit_str, 8); + if ((bit_str & BIT_VERSION1) == 0) /* NOT Version1 */ + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BITSTR); /* Illegal ACSE version */ + return; + } + break; + + case AARQ_ASO_context_name: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aarq_apdu.ASO_context_name_pres = SD_TRUE; + my_obj_id = &aarq_apdu.ASO_context_name; + ASN1R_TAG_ADD (aCtx, UNI,OBJ_ID_CODE,decode_obj_id); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARQ_CALLED_AP_title: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aarq_apdu.called_ae_title.AP_title_pres = SD_TRUE; + my_obj_id = &aarq_apdu.called_ae_title.AP_title; + ASN1R_TAG_ADD (aCtx, UNI,OBJ_ID_CODE,decode_obj_id); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARQ_CALLED_AE_qual: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aarq_apdu.called_ae_title.AE_qual_pres = SD_TRUE; + my_i32 = &aarq_apdu.called_ae_title.AE_qual; + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_i32); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARQ_CALLED_AP_inv_id: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aarq_apdu.called_ae_title.AP_inv_id_pres = SD_TRUE; + my_i32 = &aarq_apdu.called_ae_title.AP_inv_id; + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_i32); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARQ_CALLED_AE_inv_id: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aarq_apdu.called_ae_title.AE_inv_id_pres = SD_TRUE; + my_i32 = &aarq_apdu.called_ae_title.AE_inv_id; + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_i32); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARQ_CALLING_AP_title: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aarq_apdu.calling_ae_title.AP_title_pres = SD_TRUE; + my_obj_id = &aarq_apdu.calling_ae_title.AP_title; + ASN1R_TAG_ADD (aCtx, UNI,OBJ_ID_CODE,decode_obj_id); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARQ_CALLING_AE_qual: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aarq_apdu.calling_ae_title.AE_qual_pres = SD_TRUE; + my_i32 = &aarq_apdu.calling_ae_title.AE_qual; + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_i32); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARQ_CALLING_AP_inv_id: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aarq_apdu.calling_ae_title.AP_inv_id_pres = SD_TRUE; + my_i32 = &aarq_apdu.calling_ae_title.AP_inv_id; + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_i32); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARQ_CALLING_AE_inv_id: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aarq_apdu.calling_ae_title.AE_inv_id_pres = SD_TRUE; + my_i32 = &aarq_apdu.calling_ae_title.AE_inv_id; + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_i32); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARQ_acse_requirements: + if (aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must NOT be constr*/ + return; + } + /* CRITICAL: asn1r_get_bitstr doesn't set unused bits, so init all bits=0*/ + bit_str = 0; + asn1r_get_bitstr (aCtx, &bit_str, 8); + /* DEBUG: some stacks incorrectly set the low bit (0x01) in the */ + /* bitstring. To be nice, we will let them get away with it. */ + if ((bit_str & BIT_AUTHENTICATION) || (bit_str & 0x01)) + aarq_apdu.auth_info.auth_pres = SD_TRUE; + /* Don't support AP context negotiation, so ignore Bit 1. */ + /* We will never set Bit 1 in the response. */ + break; + + + case AARQ_mechanism_name: + if (aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must NOT be constr*/ + return; + } + if (asn1r_get_objid (aCtx, mechanism_name.comps, + &mechanism_name.num_comps)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + + /* Save the mechanism id for the user */ + if (asn1_objidcmp (&mechanism_name, &a_auth_password_obj_id) == 0) + aarq_apdu.auth_info.mech_type = ACSE_AUTH_MECH_PASSWORD; + else + { + if (asn1_objidcmp (&mechanism_name, &maceMechId) == 0) + aarq_apdu.auth_info.mech_type = ACSE_AUTH_MECH_MACE_CERT; + else + aarq_apdu.auth_info.mech_type = ACSE_AUTH_MECH_OTHER; + memcpy(&aarq_apdu.auth_info.u.other_auth.mech_id, &mechanism_name, sizeof(MMS_OBJ_ID)); + } + + break; + + case AARQ_CALLING_auth_value: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + + if (aarq_apdu.auth_info.mech_type == ACSE_AUTH_MECH_OTHER || + aarq_apdu.auth_info.mech_type == ACSE_AUTH_MECH_MACE_CERT) + { + ret = _a_dec_authentication (&aarq_apdu.auth_info, /* out */ + aCtx->asn1r_field_ptr, /* in */ + aCtx->asn1r_elmnt_len); /* in */ + if (ret != SD_SUCCESS) + return; + } + else + strncpy(aarq_apdu.auth_info.u.pw_auth.password, + a_auth_password_dec(aCtx->asn1r_field_ptr), ACSE_MAX_LEN_PASSWORD); + + asn1_skip_elmnt (aCtx); /* Skip over this ASN.1 element. */ + break; + + case AARQ_user_info: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } +#if defined (MOSI) + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + /* Set the PCI to be expected in PDV-list decode. */ + expected_pdv_pci = decode_acse_conn->pcimms; + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,EXTERN_CODE,START_pdv_list); /* see copp_dec.c*/ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_user_info; +#else /* !MOSI */ + /* This is MMS user data. Just pass up for MMS user to decode. */ + aarq_apdu.user_info.ptr = aCtx->asn1r_field_ptr; + aarq_apdu.user_info.len = aCtx->asn1r_elmnt_len; + asn1_skip_elmnt (aCtx); /* Skip over this ASN.1 element. */ +#endif /* !MOSI */ + break; + + default: /* Don't know how to decode. */ + ACSELOG_DEC1 ("AARQ unrecognized tag %d. Ignored.", id_code); + asn1_skip_elmnt (aCtx); /* Skip over this ASN.1 element. */ + break; + } /* End "switch (id_code)" */ + } + +/************************************************************************/ +/* decode_aarq_done */ +/************************************************************************/ +static ST_VOID decode_aarq_done (ASN1_DEC_CTXT *aCtx) + { +#if defined (MOSI) + if (expected_pdv_pci == decode_acse_conn->pcimms) + { /* only set these if this is MMS (not ACSE) data */ + aarq_apdu.user_info.ptr = pdv_data_ptr; + aarq_apdu.user_info.len = pdv_data_len; + } +#else /* !MOSI */ + acse_tag = TAG_AARQ; +#endif /* !MOSI */ + aCtx->asn1r_decode_done_fun = decode_acse_done; + } + +/************************************************************************/ +/* decode_aare */ +/************************************************************************/ +static ST_VOID decode_aare (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_method = ASN1_CLASS_METHOD; /* Use ASN1_CLASS_METHOD method to decode. */ + aCtx->asn1r_c_id_fun = decode_aare_main; + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_aare_done; + aCtx->asn1r_u_id_fun = asn1r_class_err; /* no universals to start */ + aCtx->asn1r_a_id_fun = asn1r_class_err; /* no applications to start */ + aCtx->asn1r_p_id_fun = asn1r_class_err; /* no privates to start */ + + /* Clean out old stuff from structure. */ + memset (&aare_apdu, 0, sizeof (aare_apdu)); + } + +/************************************************************************/ +/* decode_aare_main */ +/************************************************************************/ +static ST_VOID decode_aare_main (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code) + { +ST_RET ret; +ST_UCHAR bit_str; +MMS_OBJ_ID mechanism_name; +MMS_OBJ_ID maceMechId = MACE_MECH_ID; + + switch (id_code) + { + case AARE_protocol_version: + if (aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* constructor not allowed */ + return; + } + /* CRITICAL: asn1r_get_bitstr doesn't set unused bits, so init all bits=0*/ + bit_str = 0; + asn1r_get_bitstr (aCtx, &bit_str, 8); + if ((bit_str & BIT_VERSION1)==0) /* NOT Version1 */ + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BITSTR); /* Illegal ACSE version */ + return; + } + break; + + case AARE_ASO_context_name: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aare_apdu.ASO_context_name_pres = SD_TRUE; + my_obj_id = &aare_apdu.ASO_context_name; + ASN1R_TAG_ADD (aCtx, UNI,OBJ_ID_CODE,decode_obj_id); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARE_result: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + my_i16 = &aare_apdu.result; + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_i16); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARE_result_source_diagnostic: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aare_apdu.result_source_diag_pres = SD_TRUE; + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,decode_result_source1); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,decode_result_source2); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARE_RESPONDING_AP_title: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aare_apdu.responding_ae_title.AP_title_pres = SD_TRUE; + my_obj_id = &aare_apdu.responding_ae_title.AP_title; + ASN1R_TAG_ADD (aCtx, UNI,OBJ_ID_CODE,decode_obj_id); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARE_RESPONDING_AE_qual: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aare_apdu.responding_ae_title.AE_qual_pres = SD_TRUE; + my_i32 = &aare_apdu.responding_ae_title.AE_qual; + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_i32); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARE_RESPONDING_AP_inv_id: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aare_apdu.responding_ae_title.AP_inv_id_pres = SD_TRUE; + my_i32 = &aare_apdu.responding_ae_title.AP_inv_id; + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_i32); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + case AARE_RESPONDING_AE_inv_id: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aare_apdu.responding_ae_title.AE_inv_id_pres = SD_TRUE; + my_i32 = &aare_apdu.responding_ae_title.AE_inv_id; + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_i32); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + break; + + + case AARE_RESPONDER_acse_requirements: + if (aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must NOT be constr*/ + return; + } + /* CRITICAL: asn1r_get_bitstr doesn't set unused bits, so init all bits=0*/ + bit_str = 0; + asn1r_get_bitstr (aCtx, &bit_str, 8); + /* DEBUG: some stacks incorrectly set the low bit (0x01) in the */ + /* bitstring. To be nice, we will let them get away with it. */ + if ((bit_str & BIT_AUTHENTICATION) || (bit_str & 0x01)) + aare_apdu.auth_info.auth_pres = SD_TRUE; + /* Don't support AP context negotiation, so ignore Bit 1. */ + /* We will never set Bit 1 in the response. */ + break; + + case AARE_mechanism_name: + if (aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must NOT be constr*/ + return; + } + /* NOTE: this is IMPLICIT objid, so decoding simpler than normal. */ + if (asn1r_get_objid (aCtx, mechanism_name.comps, &mechanism_name.num_comps)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + + /* Save the mechanism id for the user */ + if (asn1_objidcmp (&mechanism_name, &a_auth_password_obj_id) == 0) + aare_apdu.auth_info.mech_type = ACSE_AUTH_MECH_PASSWORD; + else + { + if (asn1_objidcmp (&mechanism_name, &maceMechId) == 0) + aare_apdu.auth_info.mech_type = ACSE_AUTH_MECH_MACE_CERT; + else + aare_apdu.auth_info.mech_type = ACSE_AUTH_MECH_OTHER; + memcpy(&aare_apdu.auth_info.u.other_auth.mech_id, &mechanism_name, sizeof(MMS_OBJ_ID)); + } + + break; + + case AARE_RESPONDING_auth_value: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } + + if (aare_apdu.auth_info.mech_type == ACSE_AUTH_MECH_OTHER || + aare_apdu.auth_info.mech_type == ACSE_AUTH_MECH_MACE_CERT) + { + ret = _a_dec_authentication (&aare_apdu.auth_info, /* out */ + aCtx->asn1r_field_ptr, /* in */ + aCtx->asn1r_elmnt_len); /* in */ + if (ret != SD_SUCCESS) + return; + } + else + strncpy(aare_apdu.auth_info.u.pw_auth.password, + a_auth_password_dec(aCtx->asn1r_field_ptr), ACSE_MAX_LEN_PASSWORD); + + asn1_skip_elmnt (aCtx); /* Skip over this ASN.1 element. */ + break; + + case AARE_user_info: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } +#if defined (MOSI) + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + /* Set the PCI to be expected in PDV-list decode. */ + expected_pdv_pci = decode_acse_conn->pcimms; + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,EXTERN_CODE,START_pdv_list); /* see copp_dec.c*/ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_user_info; +#else /* !MOSI */ + /* This is MMS user data. Just pass up for MMS user to decode. */ + aare_apdu.user_info.ptr = aCtx->asn1r_field_ptr; + aare_apdu.user_info.len = aCtx->asn1r_elmnt_len; + asn1_skip_elmnt (aCtx); /* Skip over this ASN.1 element. */ +#endif /* !MOSI */ + break; + + default: /* Don't know how to decode. */ + ACSELOG_DEC1 ("AARE unrecognized tag %d. Ignored.", id_code); + asn1_skip_elmnt (aCtx); /* Skip over this ASN.1 element. */ + break; + } /* End "switch (id_code)" */ + } + +/************************************************************************/ +/* decode_aare_done */ +/************************************************************************/ +static ST_VOID decode_aare_done (ASN1_DEC_CTXT *aCtx) + { +#if defined (MOSI) + if (expected_pdv_pci == decode_acse_conn->pcimms) + { /* only set these if this is MMS (not ACSE) data */ + aare_apdu.user_info.ptr = pdv_data_ptr; + aare_apdu.user_info.len = pdv_data_len; + } +#else /* !MOSI */ + acse_tag = TAG_AARE; +#endif /* !MOSI */ + aCtx->asn1r_decode_done_fun = decode_acse_done; + } + +/************************************************************************/ +/* decode_rlrq */ +/************************************************************************/ +static ST_VOID decode_rlrq (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_method = ASN1_CLASS_METHOD; /* Use ASN1_CLASS_METHOD method to decode. */ + aCtx->asn1r_c_id_fun = decode_rlrq_main; + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_rlrq_done; + aCtx->asn1r_u_id_fun = asn1r_class_err; /* no universals to start */ + aCtx->asn1r_a_id_fun = asn1r_class_err; /* no applications to start */ + aCtx->asn1r_p_id_fun = asn1r_class_err; /* no privates to start */ + + /* Clean out old stuff from structure. */ + memset (&rlrq_apdu, 0, sizeof (rlrq_apdu)); + } + +/************************************************************************/ +/* decode_rlrq_main */ +/************************************************************************/ +static ST_VOID decode_rlrq_main (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code) + { + switch (id_code) + { + case RLRQ_reason: + if (aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be primitive */ + return; + } + rlrq_apdu.reason_pres = SD_TRUE; + if (asn1r_get_i16 (aCtx, &rlrq_apdu.reason)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + break; + + case RLRQ_user_info: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } +#if defined (MOSI) + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + /* Set the PCI to be expected in PDV-list decode. */ + expected_pdv_pci = decode_acse_conn->pcimms; + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,EXTERN_CODE,START_pdv_list); /* see copp_dec.c*/ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_user_info; +#else /* !MOSI */ + /* This is MMS user data. Just pass up for MMS user to decode. */ + rlrq_apdu.user_info.ptr = aCtx->asn1r_field_ptr; + rlrq_apdu.user_info.len = aCtx->asn1r_elmnt_len; + asn1_skip_elmnt (aCtx); /* Skip over this ASN.1 element. */ +#endif /* !MOSI */ + break; + + default: /* Don't know how to decode. */ + ACSELOG_DEC1 ("RLRQ unrecognized tag %d. Ignored.", id_code); + asn1_skip_elmnt (aCtx); /* Skip over this ASN.1 element. */ + break; + } /* End "switch (id_code)" */ + } + +/************************************************************************/ +/* decode_rlrq_done */ +/************************************************************************/ +static ST_VOID decode_rlrq_done (ASN1_DEC_CTXT *aCtx) + { +#if defined (MOSI) + if (expected_pdv_pci == decode_acse_conn->pcimms) + { /* only set these if this is MMS (not ACSE) data */ + rlrq_apdu.user_info.ptr = pdv_data_ptr; + rlrq_apdu.user_info.len = pdv_data_len; + } +#else /* !MOSI */ + acse_tag = TAG_RLRQ; +#endif /* !MOSI */ + aCtx->asn1r_decode_done_fun = decode_acse_done; + } + +/************************************************************************/ +/* decode_rlre */ +/************************************************************************/ +static ST_VOID decode_rlre (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_method = ASN1_CLASS_METHOD; /* Use ASN1_CLASS_METHOD method to decode. */ + aCtx->asn1r_c_id_fun = decode_rlre_main; + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_rlre_done; + aCtx->asn1r_u_id_fun = asn1r_class_err; /* no universals to start */ + aCtx->asn1r_a_id_fun = asn1r_class_err; /* no applications to start */ + aCtx->asn1r_p_id_fun = asn1r_class_err; /* no privates to start */ + + /* Clean out old stuff from structure. */ + memset (&rlre_apdu, 0, sizeof (rlre_apdu)); + } + +/************************************************************************/ +/* decode_rlre_main */ +/************************************************************************/ +static ST_VOID decode_rlre_main (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code) + { + switch (id_code) + { + case RLRE_reason: + if (aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be primitive */ + return; + } + rlre_apdu.reason_pres = SD_TRUE; + if (asn1r_get_i16 (aCtx, &rlre_apdu.reason)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + break; + + case RLRE_user_info: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } +#if defined (MOSI) + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + /* Set the PCI to be expected in PDV-list decode. */ + expected_pdv_pci = decode_acse_conn->pcimms; + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,EXTERN_CODE,START_pdv_list); /* see copp_dec.c*/ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_user_info; +#else /* !MOSI */ + /* This is MMS user data. Just pass up for MMS user to decode. */ + rlre_apdu.user_info.ptr = aCtx->asn1r_field_ptr; + rlre_apdu.user_info.len = aCtx->asn1r_elmnt_len; + asn1_skip_elmnt (aCtx); /* Skip over this ASN.1 element. */ +#endif /* !MOSI */ + break; + + default: /* Don't know how to decode. */ + ACSELOG_DEC1 ("RLRE unrecognized tag %d. Ignored.", id_code); + asn1_skip_elmnt (aCtx); /* Skip over this ASN.1 element. */ + break; + } /* End "switch (id_code)" */ + } + +/************************************************************************/ +/* decode_rlre_done */ +/************************************************************************/ +static ST_VOID decode_rlre_done (ASN1_DEC_CTXT *aCtx) + { +#if defined (MOSI) + if (expected_pdv_pci == decode_acse_conn->pcimms) + { /* only set these if this is MMS (not ACSE) data */ + rlre_apdu.user_info.ptr = pdv_data_ptr; + rlre_apdu.user_info.len = pdv_data_len; + } +#else /* !MOSI */ + acse_tag = TAG_RLRE; +#endif /* !MOSI */ + aCtx->asn1r_decode_done_fun = decode_acse_done; + } + +/************************************************************************/ +/* decode_abrt */ +/************************************************************************/ +static ST_VOID decode_abrt (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_method = ASN1_CLASS_METHOD; /* Use ASN1_CLASS_METHOD method to decode. */ + aCtx->asn1r_c_id_fun = decode_abrt_main; + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_abrt_done; + aCtx->asn1r_u_id_fun = asn1r_class_err; /* no universals to start */ + aCtx->asn1r_a_id_fun = asn1r_class_err; /* no applications to start */ + aCtx->asn1r_p_id_fun = asn1r_class_err; /* no privates to start */ + + /* Clean out old stuff from structure. */ + memset (&abrt_apdu, 0, sizeof (abrt_apdu)); + abrt_apdu.source = -1; /* So can verify that gets set by decode*/ + } + +/************************************************************************/ +/* decode_abrt_main */ +/************************************************************************/ +static ST_VOID decode_abrt_main (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code) + { + switch (id_code) + { + case ABRT_source: + if (aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be primitive */ + return; + } + if (asn1r_get_i16 (aCtx, &abrt_apdu.source)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + break; + + case ABRT_diagnostic: + if (aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be primitive */ + return; + } + if (asn1r_get_i16 (aCtx, &abrt_apdu.diagnostic)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + else + abrt_apdu.diagnostic_pres = SD_TRUE; + break; + + case ABRT_user_info: + if (!aCtx->asn1r_constr_elmnt) + { + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); /* Must be constructor */ + return; + } +#if defined (MOSI) + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + /* Set the PCI to be expected in PDV-list decode. */ + expected_pdv_pci = decode_acse_conn->pcimms; + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,EXTERN_CODE,START_pdv_list); /* see copp_dec.c*/ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_user_info; +#else /* !MOSI */ + /* This is MMS user data. Just pass up for MMS user to decode. */ + abrt_apdu.user_info.ptr = aCtx->asn1r_field_ptr; + abrt_apdu.user_info.len = aCtx->asn1r_elmnt_len; + asn1_skip_elmnt (aCtx); /* Skip over this ASN.1 element. */ +#endif /* !MOSI */ + break; + + default: /* Don't know how to decode. */ + ACSELOG_DEC1 ("ABRT unrecognized tag %d. Ignored.", id_code); + asn1_skip_elmnt (aCtx); /* Skip over this ASN.1 element. */ + break; + } /* End "switch (id_code)" */ + } + +/************************************************************************/ +/* decode_abrt_done */ +/************************************************************************/ +static ST_VOID decode_abrt_done (ASN1_DEC_CTXT *aCtx) + { + if (abrt_apdu.source == -1) + { + asn1r_set_dec_err (aCtx, ASN1E_END_OF_MESSAGE); /* Did not contain MANDATORY "source". */ + return; + } +#if defined (MOSI) + if (expected_pdv_pci == decode_acse_conn->pcimms) + { /* only set these if this is MMS (not ACSE) data */ + abrt_apdu.user_info.ptr = pdv_data_ptr; + abrt_apdu.user_info.len = pdv_data_len; + } +#else /* !MOSI */ + acse_tag = TAG_ABRT; +#endif /* !MOSI */ + aCtx->asn1r_decode_done_fun = decode_acse_done; + } + +/************************************************************************/ +/* decode_obj_id */ +/************************************************************************/ +static ST_VOID decode_obj_id (ASN1_DEC_CTXT *aCtx) + { + if (asn1r_get_objid (aCtx, my_obj_id->comps,&my_obj_id->num_comps)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + /* Go back to ASN1_CLASS_METHOD mode. "aCtx->asn1r_c_id_fun" should still = "decode_????_main"*/ + aCtx->asn1r_decode_method = ASN1_CLASS_METHOD; + return; + } + +/************************************************************************/ +/* decode_i32 */ +/************************************************************************/ +static ST_VOID decode_i32 (ASN1_DEC_CTXT *aCtx) + { + if (asn1r_get_i32 (aCtx, my_i32)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + /* Go back to ASN1_CLASS_METHOD mode. "aCtx->asn1r_c_id_fun" should still = "decode_????_main"*/ + aCtx->asn1r_decode_method = ASN1_CLASS_METHOD; + return; + } + +/************************************************************************/ +/* decode_i16 */ +/************************************************************************/ +static ST_VOID decode_i16 (ASN1_DEC_CTXT *aCtx) + { + if (asn1r_get_i16 (aCtx, my_i16)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + /* Go back to ASN1_CLASS_METHOD mode. "aCtx->asn1r_c_id_fun" should still = "decode_????_main"*/ + aCtx->asn1r_decode_method = ASN1_CLASS_METHOD; + return; + } + +/************************************************************************/ +/* decode_result_source1 */ +/************************************************************************/ +static ST_VOID decode_result_source1 (ASN1_DEC_CTXT *aCtx) + { + aare_apdu.result_source = 1; + + my_i16 = &aare_apdu.result_diag; + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_i16); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + + return; + } + +/************************************************************************/ +/* decode_result_source2 */ +/************************************************************************/ +static ST_VOID decode_result_source2 (ASN1_DEC_CTXT *aCtx) + { + aare_apdu.result_source = 2; + + my_i16 = &aare_apdu.result_diag; + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_i16); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = decode_constr_done; + + return; + } + +/************************************************************************/ +/* decode_acse_done */ +/************************************************************************/ +static ST_VOID decode_acse_done (ASN1_DEC_CTXT *aCtx) + { + return; + } + +/************************************************************************/ +/* decode_constr_done */ +/************************************************************************/ +static ST_VOID decode_constr_done (ASN1_DEC_CTXT *aCtx) + { + return; + } + +/************************************************************************/ +/* asn1_skip_elmnt */ +/* Skip over current ASN.1 element without decoding. */ +/************************************************************************/ +ST_VOID asn1_skip_elmnt (ASN1_DEC_CTXT *aCtx) + { + /* This function can't handle indefinite length encoding. */ + /* Only possible for constr, but let's chk here to be extra paranoid. */ + if (aCtx->asn1r_indef_flag) + { + /* NOTE: if this ever happens, chg code to use asn1r_parse_next. */ + ACSELOG_ERR0 ("asn1_skip_elmnt: indefinite length encoding not supported"); + asn1r_set_dec_err (aCtx, ASN1E_UNEXPECTED_FORM); + return; + } + if (aCtx->asn1r_constr_elmnt) + { + aCtx->asn1r_constr_elmnt = 0; /* Make ASN.1 treat it like primitive. */ + --aCtx->asn1r_msg_level; /* Already incremented for constructor */ + } /* so decrement to act like primitive. */ + aCtx->asn1r_field_ptr += aCtx->asn1r_elmnt_len; + } + +#if defined (MOSI) +/************************************************************************/ +/* END_user_info */ +/************************************************************************/ +static ST_VOID END_user_info (ASN1_DEC_CTXT *aCtx) + { + } +#endif /* MOSI */ + +#ifdef LEAN_T +/************************************************************************/ +/* tp4_except */ +/************************************************************************/ +ST_VOID tp4_except ( + ST_CHAR *filename, /* Source code file name */ + ST_INT line) /* source code line number */ + { + /* DEBUG: need better way to deal with all exceptions. */ + /* How about one exception function, pass component name and errcode */ + ACSELOG_ERR2 ("ERROR: TP4 exception: File = %s, Line = %d", filename, line); + /* DEBUG: create new errcode, or SKIP IT and use only filename/line?? */ + u_a_except (-1L, EX_ACSE_DECODE, filename, line); + } +#endif /* LEAN_T */ + + +/************************************************************************/ +/* a_auth_password_dec */ +/* Authentication password decode function. */ +/* RETURN: pointer to static NULL terminated string containing password.*/ +/* NULL if decode fails. */ +/************************************************************************/ +static ST_CHAR *a_auth_password_dec (ST_UCHAR *asn1_ptr) + { +static ST_CHAR password [ACSE_MAX_LEN_PASSWORD + 1]; +ST_UINT password_len; +ST_CHAR *ret_ptr = NULL; /* assume error */ + + if (asn1_ptr [0] == (CTX|0)) /* Tag 0 - GraphicString */ + { + password_len = asn1_ptr[1]; + if (password_len <= ACSE_MAX_LEN_PASSWORD) + { + memcpy (password, &asn1_ptr [2], password_len); + password [password_len] = 0; /* NULL terminate */ + ret_ptr = password; /* only valid return value */ + } + } + return (ret_ptr); + } + +#if defined (TP4_ENABLED) +/************************************************************************/ +/* a_get_rem_nsap */ +/* RETURN: pointer to NSAP. First byte is length. */ +/************************************************************************/ +#include "tp4.h" /* Need internal TP4 defines */ +ST_UCHAR *a_get_rem_nsap (ST_LONG acse_conn_id) + { +ACSE_CONN *acse_conn; +ST_LONG tp_conn_id; +TP_CONN *tp_conn; + + acse_conn = (ACSE_CONN *) acse_conn_id; + tp_conn_id = acse_conn->tp4_conn_id; + if (tp_conn_id < 0 || tp_conn_id >= tp_cfg.max_num_conns) + return (NULL); /* Invalid conn_id (could be TP0 conn id */ + /* which starts at MIN_TP0_CONN_ID). */ + tp_conn = &tp_conn_arr [tp_conn_id]; + return (tp_conn->rem_nsap); + } +#endif /* defined (TP4_ENABLED) */ + +#if defined (TP0_ENABLED) +/************************************************************************/ +/* a_get_rem_ip_addr */ +/* This function returns the remote IP Address as an unsigned long in */ +/* "network byte order", just like the "standard sockets" function */ +/* "inet_addr" does. If there is an error, it returns */ +/* "htonl (INADDR_NONE)", just like "inet_addr" does. */ +/* The return value can be stored in the appropriate union member */ +/* in the structure "in_addr", which can be passed to "inet_ntoa". */ +/************************************************************************/ +#include "tp4.h" /* Need internal TP4 defines */ +#include "tp0_sock.h" /* Need "sockets" defines */ +ST_ULONG a_get_rem_ip_addr (ST_LONG acse_conn_id) + { +ACSE_CONN *acse_conn; +ST_LONG tp_conn_id; +TP0_CONN *tp0_conn; +ST_INT ret; +SOCKADDR_IN sockaddr_in; +SOCK_ADDRLEN addr_len; + + acse_conn = (ACSE_CONN *) acse_conn_id; + tp_conn_id = acse_conn->tp4_conn_id; + if (tp_conn_id >= MIN_TP0_CONN_ID && + tp_conn_id < tp0_cfg.max_num_conns + MIN_TP0_CONN_ID) + { /* Conn id is a legal TP0 conn id */ + tp0_conn = &tp0_conn_arr [tp_conn_id - MIN_TP0_CONN_ID]; + + addr_len = sizeof (SOCKADDR_IN); /* CRITICAL: set to expected len.*/ + ret = getpeername (tp0_conn->sock_info->hSock, (SOCKADDR *) &sockaddr_in, &addr_len); + if (ret == 0) + return (sockaddr_in.sin_addr.s_addr); + } + + return (htonl (INADDR_NONE)); /* something failed */ + } +#endif /* defined (TP0_ENABLED) */ + + + /************************************************************************/ + /* NOTE: Copied from marb_rx.c, if any changes are required */ + /* consider making them also in marb_rx.c file! */ + /************************************************************************/ + +static ST_VOID _a_dec_auth_value_external (ASN1_DEC_CTXT *aCtx); +static ST_VOID _a_dec_external_singleAsn1Type (ASN1_DEC_CTXT *aCtx); +static ST_VOID _a_dec_external_singleAsn1Type_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _a_dec_auth_value_external_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID _a_dec_auth_value_graphicString (ASN1_DEC_CTXT *aCtx); +static ST_VOID _a_dec_auth_done (ASN1_DEC_CTXT *aCtx); + +/********************************************************************************/ +/* _a_dec_authentication */ +/*------------------------------------------------------------------------------*/ +/* Decodes Authentication info. The buffer needed to hold authentication info */ +/* is allocated in this function and should be released after connection */ +/* terminates. */ +/* Parameters: */ +/* ACSE_AUTH_INFO *authInfo pointer to the decoded authInfo */ +/* ST_CHAR *auth_value ptr to encoded authentication value */ +/* ST_INT auth_value_len length of the authentication encoding */ +/* Return: */ +/* ST_RET SD_SUCCESS or SD_FAILURE */ +/********************************************************************************/ + +static ST_RET _a_dec_authentication (ACSE_AUTH_INFO *authInfo, /* out */ + ST_UCHAR *auth_value, /* in */ + ST_INT auth_value_len) /* in */ + +{ +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + ALOG_DEC0 ("Decoding Authentication"); + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean*/ + + /* Get ptr to association indication information. */ + authInfo->auth_pres = SD_FALSE; /* set in case we fail */ + + if (auth_value_len <= 0) + { + ACSELOG_ERR1 ("_a_dec_authentication: invalid authentication len=%d", auth_value_len); + return (SD_FAILURE); + } + + if (authInfo->mech_type == ACSE_AUTH_MECH_PASSWORD) + ASN1R_TAG_ADD (aCtx, CTX, 0, _a_dec_auth_value_graphicString); + else + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 2, _a_dec_auth_value_external); + + /* decode the authentication value */ + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + + aCtx->usr_info[0] = authInfo; /* need to be set by dec funcs */ + + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + + /* Call function to parse the message */ + asn1r_decode_asn1 (aCtx, auth_value, auth_value_len); + + if (aCtx->asn1r_pdu_dec_err == NO_DECODE_ERR) + { + /* decoding of authentication successful */ + authInfo->auth_pres = SD_TRUE; + return (SD_SUCCESS); + } + + return (SD_FAILURE); + } + +/************************************************************************/ +/* _a_dec_auth_value_external */ +/************************************************************************/ + +static ST_VOID _a_dec_auth_value_external (ASN1_DEC_CTXT *aCtx) + { + ALOG_CDEC0 ("_a_dec_auth_value_external"); + +/* We need to see the Single Asn1 Type constructor */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 0, _a_dec_external_singleAsn1Type); + } + + +/************************************************************************/ +/* _a_dec_external_singleAsn1Type */ +/************************************************************************/ + +static ST_VOID _a_dec_external_singleAsn1Type (ASN1_DEC_CTXT *aCtx) + { + ALOG_CDEC0 ("_a_dec_external_singleAsn1Type"); + +/* OK, we are at the start of the data ... just record the position */ + aCtx->usr_info[1] = ASN1_DEC_PTR(aCtx); + + asn1r_parse_next (aCtx, _a_dec_external_singleAsn1Type_done); /* parse entire element */ + } + + +/************************************************************************/ +/* _a_dec_external_singleAsn1Type_done */ +/************************************************************************/ + +static ST_VOID _a_dec_external_singleAsn1Type_done (ASN1_DEC_CTXT *aCtx) + { +ACSE_AUTH_INFO *authInfo = (ACSE_AUTH_INFO *) aCtx->usr_info[0]; +ST_UCHAR *data_start; +ST_INT data_len; + + ALOG_CDEC0 ("_a_dec_external_singleAsn1Type_done"); + + data_start = (ST_UCHAR *) aCtx->usr_info[1]; + data_len = aCtx->asn1r_octetcount; + + authInfo->u.other_auth.auth_value.len = data_len; + authInfo->u.other_auth.auth_value.buf = authInfo->u.other_auth.auth_value.ptr = + (ST_UCHAR *) chk_calloc (data_len, sizeof(ST_CHAR)); + memcpy (authInfo->u.other_auth.auth_value.ptr, data_start, data_len); + + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = _a_dec_auth_value_external_done; + } + +/************************************************************************/ +/* _a_dec_auth_value_external_done */ +/************************************************************************/ + +static ST_VOID _a_dec_auth_value_external_done (ASN1_DEC_CTXT *aCtx) + { + ALOG_CDEC0 ("_a_dec_auth_value_external_done"); + aCtx->asn1r_decode_done_fun = _a_dec_auth_done; + aCtx->asn1r_decode_done = SD_TRUE; + } + + +/************************************************************************/ +/* _a_dec_auth_value_graphicString */ +/************************************************************************/ + +static ST_VOID _a_dec_auth_value_graphicString (ASN1_DEC_CTXT *aCtx) + { +ACSE_AUTH_INFO *authInfo = (ACSE_AUTH_INFO *) aCtx->usr_info[0]; +ST_INT password_len; + + ALOG_CDEC0 ("_a_dec_auth_value_graphicString"); + +/* OK, here we have the data we need */ + password_len = ASN1_DEC_LEN(aCtx); + if (password_len <= ACSE_MAX_LEN_PASSWORD) + { + memcpy (authInfo->u.pw_auth.password, ASN1_DEC_PTR(aCtx), password_len); + authInfo->u.pw_auth.password[password_len] = 0; /* NULL terminate */ + aCtx->asn1r_decode_done_fun = _a_dec_auth_done; + } + else + { + ACSELOG_ERR1 ("_a_dec_auth_value: password too long (%d bytes)", password_len); + authInfo->u.pw_auth.password[0] = 0; /* NULL password */ + asn1r_set_dec_err (aCtx, ASN1E_INVALID_LENGTH); + } + aCtx->asn1r_decode_done = SD_TRUE; + } + +/************************************************************************/ +/* _a_dec_auth_done */ +/************************************************************************/ + +static ST_VOID _a_dec_auth_done (ASN1_DEC_CTXT *aCtx) + { + ALOG_CDEC0 ("_a_dec_auth_done"); + } + diff --git a/mmslib/ositcps/acse2dib.c b/mmslib/ositcps/acse2dib.c new file mode 100644 index 0000000..e162851 --- /dev/null +++ b/mmslib/ositcps/acse2dib.c @@ -0,0 +1,522 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003 - 2003, All Rights Reserved */ +/* */ +/* MODULE NAME : acse2dib.c */ +/* PRODUCT(S) : MMS-LITE */ +/* */ +/* MODULE DESCRIPTION : Address matching functions. */ +/* */ +/* NOTE: !!! If changes are made to this file the same changes */ +/* have to be made in the marb_dib.c (MMS-EASE). */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/28/05 JRB 03 Del suicacse header. */ +/* 06/16/03 EJV 02 Renamed m_match.c to acse2dib.c */ +/* 06/02/03 MDE 01 Created */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "acse2.h" + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +static ST_CHAR *thisFileName = __FILE__; +#endif + + +/************************************************************************/ +/* Internal Functions */ + +static ST_VOID _dib_match_ap_title (DIB_MATCH_CTRL *matchCtrl, + ST_INT *matchLevel, + ST_BOOLEAN ind_pres, MMS_OBJ_ID *ind_apTitle, + ST_BOOLEAN dib_pres, MMS_OBJ_ID *dib_apTitle); +static ST_VOID _dib_match_ae_int (DIB_MATCH_CTRL *matchCtrl, + ST_INT *matchLevel, + ST_BOOLEAN ind_pres, ST_INT32 ind_val, + ST_BOOLEAN dib_pres, ST_INT32 dib_val, + ST_CHAR *itemText); +static ST_VOID _dib_match_mem (ST_INT *matchLevel, + ST_INT ind_sel_len, ST_UCHAR *ind_sel, + ST_INT dib_sel_len, ST_UCHAR *dib_sel, + ST_CHAR *sel_text); +static ST_VOID _dib_match_ae_present_flag (DIB_MATCH_CTRL *matchCtrl, + ST_INT *matchLevelIo, + ST_CHAR *aeElText, + ST_BOOLEAN dibPres, + ST_BOOLEAN remotePres, + ST_BOOLEAN *doCompareOut); + +/************************************************************************/ +/* ml_match_remote_ar */ +/************************************************************************/ + +ST_RET dib_match_remote_ar (DIB_MATCH_CTRL *matchCtrl, + AARQ_APDU *aarq, DIB_ENTRY **dib_entry_out) + { +ST_INT i; +DIB_ENTRY *de; +DIB_ENTRY *closeDe; +ST_INT remMatch; + + ACSELOG_DIB0 ("Matching Remote AR"); + closeDe = NULL; + for (i = 0; i < num_rem_dib_entries; ++i) + { + de = &rem_dib_table[i]; + ACSELOG_DIB1C (" Remote AR '%s'", de->name); + remMatch = dib_cmp_remote_addr (matchCtrl, aarq, de); + if (remMatch == DIB_MATCH_EXACT) + { + *dib_entry_out = de; + ACSELOG_DIB1C ("Exact Match: '%s'", de->name); + return (SD_SUCCESS); + } + if (remMatch == DIB_MATCH_CLOSE && closeDe == NULL) + closeDe = de; + } + + if (closeDe != NULL) + { + *dib_entry_out = closeDe; + ACSELOG_DIB1C ("Close Match: '%s'", closeDe->name); + return (SD_SUCCESS); + } + + return (SD_FAILURE); + } + +/************************************************************************/ +/* dib_match_local_ar */ +/************************************************************************/ + +ST_RET dib_match_local_ar (DIB_MATCH_CTRL *matchCtrl, + AARQ_APDU *aarq, DIB_ENTRY **dib_entry_out) + { +ST_INT i; +DIB_ENTRY *de; +DIB_ENTRY *closeDe; +ST_INT locMatch; + + ACSELOG_DIB0 ("Matching Local AR"); + closeDe = NULL; + for (i = 0; i < num_loc_dib_entries; ++i) + { + de = &loc_dib_table[i]; + ACSELOG_DIB1C (" Local AR '%s'", de->name); + locMatch = dib_cmp_local_addr (matchCtrl,aarq, de); + if (locMatch == DIB_MATCH_EXACT) + { + ACSELOG_DIB1C ("Exact Match: '%s'", de->name); + *dib_entry_out = de; + return (SD_SUCCESS); + } + + if (locMatch == DIB_MATCH_CLOSE && closeDe == NULL) + closeDe = de; + } + + if (closeDe != NULL) + { + ACSELOG_DIB1C ("Close Match: '%s'", de->name); + *dib_entry_out = closeDe; + return (SD_SUCCESS); + } + + return (SD_FAILURE); + } + + +/************************************************************************/ +/************************************************************************/ +/* dib_cmp_local_addr */ +/************************************************************************/ + +ST_INT dib_cmp_local_addr (DIB_MATCH_CTRL *matchCtrl, + AARQ_APDU *aarq, DIB_ENTRY *dib_entry) + { +ST_INT matchLevel; + +/* The best we can do ... */ + matchLevel = DIB_MATCH_EXACT; + +/* Compare local network address with dib entry */ +#if 0 + if (matchCtrl->match_net_addr) + { + if (aarq->transport == TCP) + { + _dib_match_mem (&matchLevel, + strlen (aarq->ip_addr), aarq->ip_addr, + strlen (dib_entry->ip_addr), dib_entry->ip_addr, + "Local IP Address"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + else if (aarq->transport == TP4) + { + _dib_match_mem (&matchLevel, + aarq->net_addr_len,aarq->net_addr, + dib_entry->net_addr_len, dib_entry->net_addr, + "Local Network Address"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + else + { + ACSELOG_ERR1 ("Transport type problem: %d", aarq->transport); + return (DIB_MATCH_NOT); + } + } +#endif + + +/* Compare selectors with dib entry */ + /* PSEL */ + if (matchCtrl->match_psel) + { + _dib_match_mem (&matchLevel, aarq->called_paddr.psel_len, aarq->called_paddr.psel, + dib_entry->pres_addr.psel_len, dib_entry->pres_addr.psel, + "PSEL"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + + /* SSEL */ + if (matchCtrl->match_ssel) + { + _dib_match_mem (&matchLevel, aarq->called_paddr.ssel_len, aarq->called_paddr.ssel, + dib_entry->pres_addr.ssel_len, dib_entry->pres_addr.ssel, + "SSEL"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + + /* TSEL */ + if (matchCtrl->match_tsel) + { + _dib_match_mem (&matchLevel, aarq->called_paddr.tsel_len, aarq->called_paddr.tsel, + dib_entry->pres_addr.tsel_len, dib_entry->pres_addr.tsel, + "TSEL"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + +/* Now compare AE Titles */ + /* AP Title */ + if (matchCtrl->match_ap_title) + { + _dib_match_ap_title (matchCtrl,&matchLevel, + aarq->called_ae_title.AP_title_pres, &aarq->called_ae_title.AP_title, + dib_entry->AP_title_pres, &dib_entry->AP_title); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + + /* AE Qualifier */ + if (matchCtrl->match_ae_qualifier) + { + _dib_match_ae_int (matchCtrl, &matchLevel, + aarq->called_ae_title.AE_qual_pres, aarq->called_ae_title.AE_qual, + dib_entry->AE_qual_pres, dib_entry->AE_qual, + "AE Qualifier"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + + /* AP Invoke ID */ + if (matchCtrl->match_ap_invoke) + { + _dib_match_ae_int (matchCtrl, &matchLevel, + aarq->called_ae_title.AP_inv_id_pres, aarq->called_ae_title.AP_inv_id, + dib_entry->AP_inv_id_pres, dib_entry->AP_invoke_id, + "AP invoke ID"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + + /* AE Invoke ID */ + if (matchCtrl->match_ae_invoke) + { + _dib_match_ae_int (matchCtrl, &matchLevel, + aarq->called_ae_title.AE_inv_id_pres, aarq->called_ae_title.AE_inv_id, + dib_entry->AE_inv_id_pres, dib_entry->AE_invoke_id, + "AE invoke ID"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + return (matchLevel); /* exact */ + } + + +/************************************************************************/ +/* dib_cmp_remote_addr */ +/************************************************************************/ + +ST_INT dib_cmp_remote_addr (DIB_MATCH_CTRL *matchCtrl, + AARQ_APDU *aarq, DIB_ENTRY *dib_entry) + { +ST_INT matchLevel; + +/* The best we can do ... */ + matchLevel = DIB_MATCH_EXACT; + +/* Compare partner network address with dib entry */ +#if 0 + if (matchCtrl->match_net_addr) + { + if (aarq->transport == TCP) + { + _dib_match_mem (&matchLevel, + strlen (aarq->part_ip_addr), aarq->part_ip_addr, + strlen (dib_entry->ip_addr), dib_entry->ip_addr, + "Remote IP Address"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + else if (aarq->transport == TP4) + { + _dib_match_mem (&matchLevel, + aarq->part_net_addr_len,aarq->part_net_addr, + dib_entry->net_addr_len, dib_entry->net_addr, + "Remote Network Address"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + else + { + ACSELOG_ERR1 ("Transport type problem: %d", aarq->transport); + return (DIB_MATCH_NOT); + } + } +#endif + +/* Compare selectors with dib entry */ + /* PSEL */ + if (matchCtrl->match_psel) + { + _dib_match_mem (&matchLevel, aarq->calling_paddr.psel_len, aarq->calling_paddr.psel, + dib_entry->pres_addr.psel_len, dib_entry->pres_addr.psel, + "PSEL"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + + /* SSEL */ + if (matchCtrl->match_ssel) + { + _dib_match_mem (&matchLevel, aarq->calling_paddr.ssel_len, aarq->calling_paddr.ssel, + dib_entry->pres_addr.ssel_len, dib_entry->pres_addr.ssel, + "SSEL"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + + /* TSEL */ + if (matchCtrl->match_tsel) + { + _dib_match_mem (&matchLevel, aarq->calling_paddr.tsel_len, aarq->calling_paddr.tsel, + dib_entry->pres_addr.tsel_len, dib_entry->pres_addr.tsel, + "TSEL"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + +/* Now compare AE Titles */ +/* AP Title */ + if (matchCtrl->match_ap_title) + { + _dib_match_ap_title (matchCtrl, &matchLevel, + aarq->calling_ae_title.AP_title_pres, &aarq->calling_ae_title.AP_title, + dib_entry->AP_title_pres, &dib_entry->AP_title); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + + /* AE Qualifier */ + if (matchCtrl->match_ae_qualifier) + { + _dib_match_ae_int (matchCtrl, &matchLevel, + aarq->calling_ae_title.AE_qual_pres, aarq->calling_ae_title.AE_qual, + dib_entry->AE_qual_pres, dib_entry->AE_qual, + "AE Qualifier"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + + /* AP Invoke ID */ + if (matchCtrl->match_ap_invoke) + { + _dib_match_ae_int (matchCtrl, &matchLevel, + aarq->calling_ae_title.AP_inv_id_pres, aarq->calling_ae_title.AP_inv_id, + dib_entry->AP_inv_id_pres, dib_entry->AP_invoke_id, + "AP invoke ID"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + + /* AE Invoke ID */ + if (matchCtrl->match_ae_invoke) + { + _dib_match_ae_int (matchCtrl, &matchLevel, + aarq->calling_ae_title.AE_inv_id_pres, aarq->calling_ae_title.AE_inv_id, + dib_entry->AE_inv_id_pres, dib_entry->AE_invoke_id, + "AE invoke ID"); + if (matchLevel == DIB_MATCH_NOT) + return (DIB_MATCH_NOT); + } + + return (matchLevel); + } + +/************************************************************************/ +/* _dib_match_ap_title */ +/************************************************************************/ + +/* Set match level to DIB_MATCH_NOT, or leave alone */ + +static ST_VOID _dib_match_ap_title (DIB_MATCH_CTRL *matchCtrl, + ST_INT *matchLevel, + ST_BOOLEAN ind_pres, MMS_OBJ_ID *ind_apTitle, + ST_BOOLEAN dib_pres, MMS_OBJ_ID *dib_apTitle) + { +ST_CHAR *itemText = "AP Title"; +ST_BOOLEAN doCompare; + + _dib_match_ae_present_flag (matchCtrl, matchLevel, itemText, dib_pres, + ind_pres, &doCompare); +/* See if we need to compare */ + if (doCompare) + { + if (asn1_objidcmp (ind_apTitle, dib_apTitle)) + { + ACSELOG_DIB1C (" %s mismatch", itemText); + *matchLevel = DIB_MATCH_NOT; + return; + } + } + } + +/************************************************************************/ +/* _dib_match_ae_int */ +/************************************************************************/ + +/* Set match level to DIB_MATCH_NOT, or leave alone */ + +static ST_VOID _dib_match_ae_int (DIB_MATCH_CTRL *matchCtrl, ST_INT *matchLevel, + ST_BOOLEAN ind_pres, ST_INT32 ind_val, + ST_BOOLEAN dib_pres, ST_INT32 dib_val, + ST_CHAR *itemText) + { +ST_BOOLEAN doCompare; + + _dib_match_ae_present_flag (matchCtrl, matchLevel, itemText, dib_pres, + ind_pres, &doCompare); + +/* OK, we matched, see if we need to compare */ + if (doCompare) + { + if (ind_val != dib_val) + { + ACSELOG_DIB1C (" %s mismatch", itemText); + *matchLevel = DIB_MATCH_NOT; + return; + } + } + } + +/************************************************************************/ +/* _dib_match_mem */ +/************************************************************************/ + +/* Set match level to DIB_MATCH_NOT, or leave alone */ + +static ST_VOID _dib_match_mem (ST_INT *matchLevel, + ST_INT ind_sel_len, ST_UCHAR *ind_sel, + ST_INT dib_sel_len, ST_UCHAR *dib_sel, + ST_CHAR *sel_text) + { +/* See if the selectors match */ + if (ind_sel_len == dib_sel_len && + !memcmp (ind_sel, dib_sel, ind_sel_len)) + { + return; + } + + ACSELOG_DIB1C (" %s mismatch", sel_text); + *matchLevel = DIB_MATCH_NOT; + return; + } + +/************************************************************************/ +/* _dib_match_ae_present_flag */ +/************************************************************************/ + +/* Set match level to DIB_MATCH_CLOSE or DIB_MATCH_NOT, or leave alone */ + +static ST_VOID _dib_match_ae_present_flag (DIB_MATCH_CTRL *matchCtrl, + ST_INT *matchLevelIo, + ST_CHAR *aeElText, + ST_BOOLEAN dibPres, + ST_BOOLEAN remotePres, + ST_BOOLEAN *doCompareOut) + { + +/* If the remote sent the parameter and it is in the DIB, SUCCESS */ + if (dibPres == remotePres) + { + *doCompareOut = dibPres; /* If it is present, then compare it */ + return; + } + *doCompareOut = SD_FALSE; /* Can't compare */ + +/* OK, this is more complicated. We need to find out what the mismatch */ +/* is and what the user wants to do about it. */ + + if (!remotePres) + { + if (matchCtrl->match_allow_missing_ae_elements) + { + ACSELOG_DIB1C (" Remote did not send: %s, ignoring", aeElText); + if (*matchLevelIo == DIB_MATCH_EXACT) + *matchLevelIo = DIB_MATCH_CLOSE; + } + else + { + ACSELOG_DIB1C (" Remote did not send required: %s", aeElText); + *matchLevelIo = DIB_MATCH_NOT; + } + } + + if (remotePres) + { + if (matchCtrl->match_allow_extra_ae_elements) + { + ACSELOG_DIB1C (" Remote sent unexpected: %s, ignoring", aeElText); + if (*matchLevelIo == DIB_MATCH_EXACT) + *matchLevelIo = DIB_MATCH_CLOSE; + } + else + { + ACSELOG_DIB1C (" Remote sent unexpected: %s", aeElText); + *matchLevelIo = DIB_MATCH_NOT; + } + } + } + + + diff --git a/mmslib/ositcps/acse2enc.c b/mmslib/ositcps/acse2enc.c new file mode 100644 index 0000000..6a90400 --- /dev/null +++ b/mmslib/ositcps/acse2enc.c @@ -0,0 +1,1334 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995-2008, All Rights Reserved */ +/* */ +/* MODULE NAME : acse2enc.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* ACSE Encode Functions. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/27/08 EJV 35 a_associate_rsp: do not free acse_conn. */ +/* 11/07/06 EJV 34 MMSEASE_MOSI:elim HPUX warn when logging PSEL*/ +/* 07/06/05 EJV 33 a_associate_req: log "IP ADDR: ip" same line,*/ +/* MMSEASE_MOSI: log local PSEL,SSEL,TSEL. */ +/* 05/06/05 EJV 32 Log PORT if configured. */ +/* 01/24/05 JRB 31 Move acse_debug_sel & "*_logstr" to lean_var.c*/ +/* 09/17/04 JRB 30 a_abort_req: don't access acse_conn after */ +/* copp_u_abort_req (it may have been freed). */ +/* 08/06/04 EJV 29 Added typecast (ST_UCHAR *) ...password. */ +/* 03/04/04 JRB 28 Mov thisFil.. after incs, they may define DEBUG_..*/ +/* Del logging of A-DATA.req (use MVL or COPP) */ +/* 12/18/03 JRB 27 If MOSI, use cosp_buf, DON't use acse_buf. */ +/* Use ASN1_ENC_PTR, ASN1_ENC_LEN macros. */ +/* 10/21/03 JRB 26 Add a_get_event_handles_unix. */ +/* 08/20/03 EJV 25 Chg cosp_msgsize to fit larger User Data */ +/* ACSE_AUTH_ENABLED code wo/define. */ +/* Added security functions. */ +/* Added param to tp4_connect . */ +/* Fix the ACSE Auth encode. */ +/* 06/17/03 EJV 24 Added _acse_dib_logstr. */ +/* 10/22/02 ASK 23 Wrap ifdef TP0_ENABLED around inet_ntoa calls*/ +/* 10/14/02 ASK 22 Added encoding for abort diagnostic. */ +/* 08/26/02 ASK 21 Added password mechanism encoding in */ +/* a_associate_req and a_associate rsp. */ +/* 07/16/02 JRB 20 Add tp0_sock.h for sockets/IP defs. */ +/* 06/26/02 JRB 19 associate_req: Log calling/called address. */ +/* 01/22/02 JRB 18 Add args to copp_initialize (same as MAP30..)*/ +/* Del a_set_msgsize (no longer needed). */ +/* 01/02/02 JRB 17 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/22/01 JRB 16 Fix a_release_rsp handling of STATE_RESP_COLL*/ +/* state per ISO 8650 (was kluged before). */ +/* 03/15/01 JRB 15 Use new SMEM allocation functions. */ +/* 01/04/01 EJV 14 a_get_event_handles used only on _WIN32 */ +/* 09/24/99 JRB 13 a_get_event_handles not used on */ +/* DOS, QNX or VXWORKS */ +/* 09/13/99 MDE 12 Added SD_CONST modifiers */ +/* 08/05/99 JRB 11 Add "a_get_event_handles" function for MOSI. */ +/* 10/08/98 MDE 10 Migrated to updated SLOG interface */ +/* 08/13/98 JRB 09 Lint cleanup. */ +/* 07/10/98 JRB 08 Del *_obj_id, use acse2var.c */ +/* 03/23/98 NAV 07 Free buffers on termination */ +/* 02/16/98 JRB 06 Del or "#if out" unused locals. */ +/* 11/10/97 JRB 05 Chg cosp_buf to (ST_UCHAR *). */ +/* 09/22/97 JRB 04 acse_msgsize MUST be set before copp_init. */ +/* a_data_req (MOSI): check for buffer overflow */ +/* 09/04/97 JRB 03 Pass SPDU msgsize arg to tp4_initialize. */ +/* 07/31/97 JRB 02 copp_bind & a_associate_req set "tp_type" */ +/* in tp4_addr. New TP4 needs it. */ +/* 06/09/97 JRB 01 If !MOSI, on A-ASSOCIATE.rsp-, just set */ +/* state=STATE_IDLE. Don't free as did on 3/7/97*/ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 05/02/97 JRB 24 wr_* functs now ret void, so don't check. */ +/* 04/09/97 JRB 23 a_associate_req return (0L) for any error. */ +/* 03/19/97 JRB 22 Add MOSI "CALLING" support. */ +/* 03/19/97 JRB 21 Encode AARQ in a_associate_req: need for MOSI*/ +/* In a_release_req, chg handling if send fails.*/ +/* Use acse_free_conn to free conn ctrl struct. */ +/* Improve logging. */ +/* Improve release collision handling. */ +/* 03/07/97 JRB 20 Always send result-source-diag on AARE. */ +/* Rechecked spec, and this is MANDATORY. */ +/* 03/07/97 JRB 19 If !MOSI, free acse_conn on negative */ +/* A-Associate.rsp (MOSI frees in COSP). */ +/* 03/07/97 JRB 18 Use new "acse_free_con" to free acse_conn. */ +/* 03/07/97 JRB 17 Added MOSI support. */ +/* 02/11/97 JRB 16 In a_release_rsp, if send fails, don't free */ +/* acse_conn and don't change state. */ +/* 01/23/97 JRB 15 Init acse_debug_sel in copp_initialize. */ +/* 11/18/96 JRB 14 Del acse_dummyfun call. Funct is gone now. */ +/* 11/15/96 JRB 13 Don't initialize globals. */ +/* Move acse_debug_sel global here. */ +/* 08/19/96 MDE 12 Add dummy a_buffers_avail for Reduced Stack */ +/* 08/14/96 JRB 11 Add a_buffers_avail function. */ +/* 07/19/96 JRB 10 Change DEBUG_MMS to DEBUG_SISCO. */ +/* 07/15/96 JRB 09 Only free acse_conn->aarq_apdu.user_info.ptr */ +/* if len != 0 (wasn't alloc'd otherwise). */ +/* 05/02/96 JRB 08 Add STATE_TP4CONN_WAIT. */ +/* 04/23/96 MDE 07 Fixed minor warning */ +/* 04/18/96 JRB 06 a_associate_req return acse_conn_id or NULL */ +/* on error, instead of just SD_SUCCESS or error. */ +/* if (acse_conn->state == STATE_AARE_WAIT) */ +/* in a_abort_req, set to STATE_AARE_ABANDON. */ +/* 03/26/96 MDE 05 Added REDUCED_STACK support */ +/* 03/11/96 JRB 04 Move acse_msgsize here & use for acse_buf. */ +/* 03/07/96 JRB 03 Handle aarq_apdu->user_info.len = 0. */ +/* 01/19/96 JRB 02 Cast constant chars to ST_UCHAR. */ +/* 10/30/95 JRB 01 Created */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "asn1defs.h" +#include "acse2.h" +#if defined (MOSI) +#include "cosp_usr.h" +#include "copp_usr.h" +#endif /* MOSI */ +#if defined (MMSEASE_MOSI) +#include "cosp.h" /* for cosp_only_sel */ +#include "copp.h" /* for only_loc_psel */ +#include "tp4.h" /* for tp0_check_bind_id */ +#endif +#include "tp4api.h" +#include "tp0_sock.h" + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +ST_UINT acse_msgsize; + + +/* Buffer for building init, release, and abort reqests. */ +#if defined (MOSI) +ST_UINT cosp_msgsize; +ST_UCHAR *cosp_buf; /* Buffer containing "acse_buf" + COSP&COPP headers.*/ +static ST_VOID acse_encode_user_info (ASN1_ENC_CTXT *aCtx, ACSE_CONN *acse_conn, BUFFER *user_info); +#else /* !MOSI */ +static ST_UCHAR *acse_buf; +#endif /* !MOSI */ + +#define TP4_EOT 1 /* for tp4_data calls. */ + +/************************************************************************/ +/* copp_initialize */ +/* Save "msg_size". Pass "max_conns" to tp4_initialize. */ +/************************************************************************/ +ST_RET copp_initialize (ST_INT max_conns, ST_UINT msg_size) + { +ST_RET ret; + + + + + acse_msgsize = msg_size; /* Save msg size in global. */ + + /* Always enable error logging. */ +#if defined(DEBUG_SISCO) + acse_debug_sel |= (ACSE_LOG_ERR | COPP_LOG_ERR | COSP_LOG_ERR); +#endif + + if (acse_msgsize == 0) + { /* ACSE user must call a_set_msgsize first. */ + ACSELOG_ERR0 ("ACSE-ERROR: msg size not set"); + return (E_ACSE_INVALID_PARAM); /* Invalid Parameter */ + } +#if defined(MOSI) + cosp_msgsize = max(acse_msgsize, COSP_MAX_UDATA_CON) + MAX_COSP_COPP_HEADER; + cosp_buf = (ST_UCHAR *) M_MALLOC (MSMEM_STARTUP, cosp_msgsize); + + ret = tp4_initialize (max_conns, cosp_msgsize); +#else /* !MOSI */ + acse_buf = (ST_UCHAR *) M_MALLOC (MSMEM_STARTUP, acse_msgsize); + ret = tp4_initialize (max_conns, acse_msgsize); +#endif /* !MOSI */ + return (ret); + } + +/************************************************************************/ +/* copp_terminate */ +/************************************************************************/ +ST_RET copp_terminate (ST_VOID) + { + +#ifdef MOSI + if (cosp_buf) + M_FREE (MSMEM_STARTUP, cosp_buf); +#else + if(acse_buf) + M_FREE (MSMEM_STARTUP, acse_buf); +#endif + + return (tp4_terminate ()); + } + +/************************************************************************/ +/* copp_event */ +/************************************************************************/ +ST_BOOLEAN copp_event (ST_VOID) + { + return (tp4_event ()); + } + +#if !defined (MOSI) /* see copp_enc.c for MOSI bind functs. */ +/************************************************************************/ +/* copp_bind */ +/************************************************************************/ +ST_RET copp_bind (ST_LONG user_bind_id, PRES_ADDR *pres_addr, + ST_INT sharable, ST_INT max_conns) + { +TP4_ADDR tp4_addr; + + ACSELOG_ENC1 ("COPP-Bind Req. user_bind_id =%9ld", user_bind_id); + +#if !defined(REDUCED_STACK) + /* Copy tsel and nsap from pres_addr to tp4_addr struct */ + tp4_addr.tp_type = pres_addr->tp_type; + tp4_addr.tp4_sel_len = pres_addr->tsel_len; + memcpy (tp4_addr.tp4_sel, pres_addr->tsel, pres_addr->tsel_len); + tp4_addr.net_addr_len = pres_addr->nsap_len; + memcpy (tp4_addr.net_addr, pres_addr->nsap, pres_addr->nsap_len); +#else + tp4_addr.adlcAddr = pres_addr->adlcAddr; +#endif + + /* Call tp4_bind. */ + return (tp4_bind (user_bind_id, &tp4_addr, sharable, max_conns)); + } + +/************************************************************************/ +/* copp_unbind */ +/************************************************************************/ +ST_RET copp_unbind (ST_LONG copp_bind_id) + { + ACSELOG_ENC1 ("COPP-Unbind Req. copp_bind_id =%9ld", copp_bind_id); + return (tp4_unbind (copp_bind_id)); + } +#endif /* !MOSI */ + +/************************************************************************/ +/* a_associate_req */ +/************************************************************************/ +ST_LONG a_associate_req ( + ST_LONG copp_bind_id, /* ACSE's bind ID received in u_copp_bind_cnf*/ + ST_LONG user_conn_id, /* USER's connection ID */ + AARQ_APDU *aarq_apdu) /* AARQ_APDU info */ + { +#if !defined (MOSI) +TP4_ADDR tp4_addr; +#endif /* !MOSI */ +ACSE_CONN *acse_conn; +AE_TITLE *ae_title; +ST_UCHAR version1_bit_str = BIT_VERSION1; /* Bit 0 of bitstr (high bit) set */ +ST_UCHAR auth_bit_str = BIT_AUTHENTICATION; + +ST_UCHAR *msg_ptr; +ST_UINT msg_len; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; +ST_INT j; + + /* Allocate connection tracking structure "acse_conn". */ + acse_conn = (ACSE_CONN *) M_CALLOC (MSMEM_ACSE_CONN, 1, sizeof (ACSE_CONN)); + + /* Save USER's connection ID. Use it in calls to user functions. */ + acse_conn->user_conn_id = user_conn_id; + + /* save the encryption info */ + acse_conn->encrypt_ctrl = aarq_apdu->encrypt_ctrl; + + ACSELOG_ENC2 ("A-ASSOCIATE.req: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + ACSELOG_ENC0C ("DST (CALLED) ADDRESS:"); + if (aarq_apdu->called_ae_title.AP_title_pres) + { + for (j = 0; j < aarq_apdu->called_ae_title.AP_title.num_comps; ++j) + { /* Verbose but gets the job done. */ + ACSELOG_ENC2C (" AP_title.comps[%d] = %d", + j, aarq_apdu->called_ae_title.AP_title.comps[j]); + } + } + if (aarq_apdu->called_ae_title.AE_qual_pres) + { + ACSELOG_ENC1C (" AE_qual = %ld", aarq_apdu->called_ae_title.AE_qual); + } + ACSELOG_ENC0C (" PSEL:"); + ACSELOG_ENCH (aarq_apdu->called_paddr.psel_len, aarq_apdu->called_paddr.psel); + ACSELOG_ENC0C (" SSEL:"); + ACSELOG_ENCH (aarq_apdu->called_paddr.ssel_len, aarq_apdu->called_paddr.ssel); + ACSELOG_ENC0C (" TSEL:"); + ACSELOG_ENCH (aarq_apdu->called_paddr.tsel_len, aarq_apdu->called_paddr.tsel); + if (aarq_apdu->called_paddr.tp_type == TP_TYPE_TCP) + { + struct in_addr sin_addr; /* inet_ntoa needs this addr format*/ + sin_addr.s_addr = aarq_apdu->called_paddr.netAddr.ip; +#if defined(TP0_ENABLED) + ACSELOG_ENC1C (" IP ADDR: %s", inet_ntoa (sin_addr)); + if (!aarq_apdu->encrypt_ctrl.encryptMode == S_SEC_ENCRYPT_SSL && + aarq_apdu->called_paddr.port) + ACSELOG_ENC1C (" PORT: %u", (ST_UINT) aarq_apdu->called_paddr.port); +#endif + if (aarq_apdu->encrypt_ctrl.encryptMode == S_SEC_ENCRYPT_SSL) + ACSELOG_ENC1C (" Encryption: SSL, port=%d", aarq_apdu->encrypt_ctrl.u.ssl.port); + else + ACSELOG_ENC0C (" Encryption: None"); + if (aarq_apdu->auth_info.auth_pres) + { + if (aarq_apdu->auth_info.mech_type == ACSE_AUTH_MECH_MACE_CERT) + ACSELOG_ENC0C (" Authentication: MACE"); + else if (aarq_apdu->auth_info.mech_type == ACSE_AUTH_MECH_PASSWORD) + ACSELOG_ENC0C (" Authentication: password"); + else + ACSELOG_ENC0C (" Authentication: other"); + } + else + ACSELOG_ENC0C (" Authentication: None"); + } + else + { + ACSELOG_ENC0C (" NSAP:"); + ACSELOG_ENCH (aarq_apdu->called_paddr.nsap_len, aarq_apdu->called_paddr.netAddr.nsap); + } + + ACSELOG_ENC0C ("SRC (CALLING) ADDRESS:"); + if (aarq_apdu->calling_ae_title.AP_title_pres) + { + for (j = 0; j < aarq_apdu->calling_ae_title.AP_title.num_comps; ++j) + { /* Verbose but gets the job done. */ + ACSELOG_ENC2C (" AP_title.comps[%d] = %d", + j, aarq_apdu->calling_ae_title.AP_title.comps[j]); + } + } + if (aarq_apdu->calling_ae_title.AE_qual_pres) + { + ACSELOG_ENC1C (" AE_qual = %ld", aarq_apdu->calling_ae_title.AE_qual); + } +#if defined (MMSEASE_MOSI) + { + ST_UCHAR *tp0_loc_tsap; + ACSELOG_ENC0C (" PSEL:"); + if (only_loc_psel[0]) + ACSELOG_ENCH ((ST_UINT) only_loc_psel[0], &only_loc_psel[1]); + ACSELOG_ENC0C (" SSEL:"); + if (cosp_only_ssel[0]) + ACSELOG_ENCH ((ST_UINT) cosp_only_ssel[0], &cosp_only_ssel[1]); + ACSELOG_ENC0C (" TSEL:"); + if (tp0_check_bind_id (copp_bind_id, &tp0_loc_tsap) == SD_SUCCESS) + ACSELOG_ENCH ((ST_UINT) tp0_loc_tsap[0], &tp0_loc_tsap[1]); + } +#else + /* NOTE: aarq_apdu->calling_paddr is NOT logged because caller may */ + /* not set it, and even if they do, it is not used. The address */ + /* passed to "copp_bind" is used as the calling_paddr. */ +#endif + + /* Begin encoding request. */ +#if defined (MOSI) + asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize); +#else + asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize); +#endif + + asn1r_strt_constr (aCtx); /* Start AARQ APDU constructor */ + /* Write user_info. */ + if (aarq_apdu->user_info.len) + { + asn1r_strt_constr (aCtx); +#if defined (MOSI) + /* PCI's must be set before any encoding. */ + acse_conn->pciacse = 1; + acse_conn->pcimms = 3; + acse_encode_user_info (aCtx, acse_conn, &aarq_apdu->user_info); +#else /* !MOSI */ + asn1r_wr_octstr (aCtx, aarq_apdu->user_info.ptr, aarq_apdu->user_info.len); + /* No P-Contexts in this implementation, so skip transfer-syntax */ + /* and p-context-id. */ +#endif /* !MOSI */ + asn1r_fin_constr (aCtx, AARQ_user_info,CTX,DEF); + } + + if(aarq_apdu->auth_info.auth_pres == SD_TRUE) + { + if(aarq_apdu->auth_info.mech_type == ACSE_AUTH_MECH_PASSWORD) + { + ACSELOG_ENC0C (" Authentication: password"); + /* Write the password value */ + asn1r_strt_constr (aCtx); + asn1r_wr_octstr (aCtx, (ST_UCHAR *) aarq_apdu->auth_info.u.pw_auth.password, + strlen(aarq_apdu->auth_info.u.pw_auth.password)); /* Strip off the NULL */ + asn1r_fin_prim (aCtx, 0,CTX); + asn1r_fin_constr (aCtx, AARQ_CALLING_auth_value,CTX,DEF); + + /* Write the mechanism name (password in this case) */ + asn1r_wr_objid (aCtx, a_auth_password_obj_id.comps, a_auth_password_obj_id.num_comps); + asn1r_fin_prim (aCtx, AARQ_mechanism_name, CTX); + } + else + { + if (aarq_apdu->auth_info.mech_type == ACSE_AUTH_MECH_MACE_CERT) + ACSELOG_ENC0C ("Authentication: MACE"); + else + ACSELOG_ENC0C ("Authentication: other"); + asn1r_strt_constr (aCtx); + asn1r_strt_constr (aCtx); /* Authentication-value */ + asn1r_strt_constr (aCtx); /* Single ASN.1 Type */ + asn1r_wr_octstr (aCtx, aarq_apdu->auth_info.u.other_auth.auth_value.ptr, + aarq_apdu->auth_info.u.other_auth.auth_value.len); + asn1r_fin_constr (aCtx, 0, CTX, SD_FALSE); /* Single ASN.1 Type */ + asn1r_fin_constr (aCtx, 2, CTX, SD_FALSE); /* Authentication-value */ + asn1r_fin_constr (aCtx, AARQ_CALLING_auth_value,CTX,DEF); + + /* Write the mechanism name */ + asn1r_wr_objid (aCtx, aarq_apdu->auth_info.u.other_auth.mech_id.comps, aarq_apdu->auth_info.u.other_auth.mech_id.num_comps); + asn1r_fin_prim (aCtx, AARQ_mechanism_name, CTX); + } + + /* Let's encode the authentication present bit to enable security */ + asn1r_wr_bitstr (aCtx, &auth_bit_str, 1); + asn1r_fin_prim (aCtx, AARQ_acse_requirements, CTX); + } + + /* Write CALLING AE Title (i.e. AP_title, AE_qual, AP_inv_id, AE_inv_id).*/ + ae_title = &aarq_apdu->calling_ae_title; + + if (ae_title->AE_inv_id_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_i32 (aCtx, ae_title->AE_inv_id); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, AARQ_CALLING_AE_inv_id,CTX,DEF); + } + + if (ae_title->AP_inv_id_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_i32 (aCtx, ae_title->AP_inv_id); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, AARQ_CALLING_AP_inv_id,CTX,DEF); + } + + if (ae_title->AE_qual_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_i32 (aCtx, ae_title->AE_qual); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, AARQ_CALLING_AE_qual,CTX,DEF); + } + + if (ae_title->AP_title_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_objid (aCtx, ae_title->AP_title.comps, ae_title->AP_title.num_comps); + asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI); + asn1r_fin_constr (aCtx, AARQ_CALLING_AP_title,CTX,DEF); + } + + + /* Write CALLED AE Title (i.e. AP_title, AE_qual, AP_inv_id, AE_inv_id).*/ + ae_title = &aarq_apdu->called_ae_title; + + if (ae_title->AE_inv_id_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_i32 (aCtx, ae_title->AE_inv_id); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, AARQ_CALLED_AE_inv_id,CTX,DEF); + } + + if (ae_title->AP_inv_id_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_i32 (aCtx, ae_title->AP_inv_id); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, AARQ_CALLED_AP_inv_id,CTX,DEF); + } + + if (ae_title->AE_qual_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_i32 (aCtx, ae_title->AE_qual); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, AARQ_CALLED_AE_qual,CTX,DEF); + } + + if (ae_title->AP_title_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_objid (aCtx, ae_title->AP_title.comps, ae_title->AP_title.num_comps); + asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI); + asn1r_fin_constr (aCtx, AARQ_CALLED_AP_title,CTX,DEF); + } + + /* Write ASO Context Name. */ + if (aarq_apdu->ASO_context_name_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_objid (aCtx, aarq_apdu->ASO_context_name.comps, aarq_apdu->ASO_context_name.num_comps); + asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI); + asn1r_fin_constr (aCtx, AARQ_ASO_context_name,CTX,DEF); + } + + /* Write protocol_version. */ + asn1r_wr_bitstr (aCtx, &version1_bit_str, 1); + asn1r_fin_prim (aCtx, AARQ_protocol_version, CTX); + + asn1r_fin_constr (aCtx, TAG_AARQ,APP,DEF); /* Finish AARQ APDU */ + + msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */ + msg_len = ASN1_ENC_LEN (aCtx); + +#if ! (defined(REDUCED_STACK) || defined(MOSI) ) + /* Fastbyte Presentation and Session (2 bytes). */ + *(--msg_ptr) = 0x01; /* Short-CP mode = BER */ + *(--msg_ptr) = (ST_UCHAR) 0xE8; /* Short-SCN, SI = 11101, 0 params */ + msg_len+=2; /* adjust len */ +#endif /* ! (defined(REDUCED_STACK) || defined(MOSI) ) */ + if (msg_len > acse_msgsize) + return (0L); + +#if defined (MOSI) + acse_conn->apdu_ptr = msg_ptr; + acse_conn->apdu_len = msg_len; + /* Send AARQ APDU via P-CONNECT.req */ + if (copp_con_req (copp_bind_id, acse_conn, &aarq_apdu->called_paddr) != SD_SUCCESS) + { + acse_free_con (acse_conn); /* Dump conn tracking struct */ + return (0L); + } + acse_conn->state = STATE_AARE_WAIT; /* Waiting for AARE-apdu */ +#else /* !MOSI */ + /* Save AARQ APDU (in save_buf) to send when tp4 connection */ + /* established (see tp4_connect_cnf). */ + acse_conn->save_buf.len = msg_len; + acse_conn->save_buf.ptr = (ST_UCHAR *) M_MALLOC (MSMEM_ACSE_DATA, msg_len); + memcpy (acse_conn->save_buf.ptr, msg_ptr, msg_len); + + /* Send Transport connect request. */ + /* The connection ID is just a pointer to "acse_conn" cast to a ST_LONG. */ + /* Copy tsel and nsap from aarq_apdu->called_paddr to tp4_addr */ +#if !defined(REDUCED_STACK) + tp4_addr.tp_type = aarq_apdu->called_paddr.tp_type; + tp4_addr.tp4_sel_len = aarq_apdu->called_paddr.tsel_len; + memcpy (tp4_addr.tp4_sel, aarq_apdu->called_paddr.tsel, + aarq_apdu->called_paddr.tsel_len); + tp4_addr.net_addr_len = aarq_apdu->called_paddr.nsap_len; + memcpy (tp4_addr.net_addr, aarq_apdu->called_paddr.nsap, + aarq_apdu->called_paddr.nsap_len); +#else + tp4_addr.adlcAddr = aarq_apdu->called_paddr.adlcAddr; +#endif + + if (tp4_connect (copp_bind_id, (ST_LONG) acse_conn, + &tp4_addr, 0, NULL, NULL) != SD_SUCCESS) + { + acse_free_con (acse_conn); /* Dump conn tracking struct */ + return (0L); + } + acse_conn->state = STATE_TP4CONN_WAIT; /* Waiting for TP4 connection*/ +#endif /* !MOSI */ + return ((ST_LONG)acse_conn); + } + +/************************************************************************/ +/* a_associate_rsp */ +/************************************************************************/ +ST_RET a_associate_rsp ( + ST_LONG acse_conn_id, /* ACSE's connection ID */ + ST_LONG user_conn_id, /* USER's connection ID */ + AARE_APDU *info) /* AARE_APDU info */ + { +AE_TITLE *ae_title; +ST_UCHAR version1_bit_str = BIT_VERSION1; /* Bit 0 of bitstr (high bit) set */ +ST_UCHAR auth_bit_str = BIT_AUTHENTICATION; + +ST_UCHAR *msg_ptr; +ST_UINT msg_len; +ACSE_CONN *acse_conn; +ST_RET retcode; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + ACSELOG_ENC2 ("A-ASSOCIATE.rsp: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn_id, user_conn_id); + + acse_conn = (ACSE_CONN *) acse_conn_id; + + if (acse_conn == NULL) + return (E_ACSE_INVALID_CONN_ID); /* Invalid acse_conn_id */ + + if (acse_conn->state != STATE_AASCRSP_WAIT) + return (E_ACSE_INVALID_STATE); /* Invalid state for this operation*/ + + /* Save USER's connection ID. Use it in calls to user functions. */ + acse_conn->user_conn_id = user_conn_id; + + /* Everything looks OK. Go ahead and encode response and send it. */ +#if defined (MOSI) + asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize); +#else + asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize); +#endif + + asn1r_strt_constr (aCtx); /* Start AARE APDU constructor */ + /* Write user_info. */ + if (info->user_info.len) + { + asn1r_strt_constr (aCtx); +#if defined (MOSI) + acse_encode_user_info (aCtx, acse_conn, &info->user_info); +#else /* !MOSI */ + asn1r_wr_octstr (aCtx, info->user_info.ptr, info->user_info.len); + /* No P-Contexts in this implementation, so skip transfer-syntax */ + /* and p-context-id. */ +#endif /* !MOSI */ + asn1r_fin_constr (aCtx, AARE_user_info,CTX,DEF); + } + + if(info->auth_info.auth_pres == SD_TRUE) + { + if(info->auth_info.mech_type == ACSE_AUTH_MECH_PASSWORD) + { + /* Write the password value */ + asn1r_strt_constr (aCtx); + asn1r_wr_octstr (aCtx, (ST_UCHAR *) info->auth_info.u.pw_auth.password, + strlen(info->auth_info.u.pw_auth.password)); /* Strip off the NULL */ + asn1r_fin_prim (aCtx, 0,CTX); + asn1r_fin_constr (aCtx, AARE_RESPONDING_auth_value,CTX,DEF); + + /* Write the mechanism name (password in this case) */ + asn1r_wr_objid (aCtx, a_auth_password_obj_id.comps, a_auth_password_obj_id.num_comps); + asn1r_fin_prim (aCtx, AARE_mechanism_name, CTX); + } + else + { + if (info->auth_info.mech_type == ACSE_AUTH_MECH_MACE_CERT) + ACSELOG_ENC0C ("Authentication: MACE"); + else + ACSELOG_ENC0C ("Authentication: other"); + asn1r_strt_constr (aCtx); + asn1r_strt_constr (aCtx); /* Authentication-value */ + asn1r_strt_constr (aCtx); /* Single ASN.1 Type */ + asn1r_wr_octstr (aCtx, info->auth_info.u.other_auth.auth_value.ptr, + info->auth_info.u.other_auth.auth_value.len); + asn1r_fin_constr (aCtx, 0, CTX, SD_FALSE); /* Single ASN.1 Type */ + asn1r_fin_constr (aCtx, 2, CTX, SD_FALSE); /* Authentication-value */ + asn1r_fin_constr (aCtx, AARE_RESPONDING_auth_value,CTX,DEF); + + /* Write the mechanism name */ + asn1r_wr_objid (aCtx, info->auth_info.u.other_auth.mech_id.comps, + info->auth_info.u.other_auth.mech_id.num_comps); + asn1r_fin_prim (aCtx, AARE_mechanism_name, CTX); + } + + /* Let's encode the authentication present bit to enable security */ + asn1r_wr_bitstr (aCtx, &auth_bit_str, 1); + asn1r_fin_prim (aCtx, AARE_RESPONDER_acse_requirements, CTX); + } + + /* Write RESP AE Title (i.e. AP_title, AE_qual, AP_inv_id, AE_inv_id) */ + /* fields of AARE APDU. */ + ae_title = &info->responding_ae_title; + + if (ae_title->AE_inv_id_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_i32 (aCtx, ae_title->AE_inv_id); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, AARE_RESPONDING_AE_inv_id,CTX,DEF); + } + + if (ae_title->AP_inv_id_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_i32 (aCtx, ae_title->AP_inv_id); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, AARE_RESPONDING_AP_inv_id,CTX,DEF); + } + + if (ae_title->AE_qual_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_i32 (aCtx, ae_title->AE_qual); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, AARE_RESPONDING_AE_qual,CTX,DEF); + } + + if (ae_title->AP_title_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_objid (aCtx, ae_title->AP_title.comps, ae_title->AP_title.num_comps); + asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI); + asn1r_fin_constr (aCtx, AARE_RESPONDING_AP_title,CTX,DEF); + } + + /* Write result-source-diagnostic. */ + /* DEBUG: If user required to set "result_source" and "result_diag", */ + /* "result_source_diag_pres" would no longer be needed. */ + if (info->result_source_diag_pres == 0) + { /* User probably didn't set values, so set to default. */ + info->result_source = 1; /* Source = acse-service-user. */ + info->result_diag = 0; /* Diag = null. */ + } + asn1r_strt_constr (aCtx); + asn1r_strt_constr (aCtx); + asn1r_wr_i16 (aCtx, info->result_diag); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + if (info->result_source != 1 && info->result_source != 2) + return (E_ACSE_ENC_ERR); /* Make sure source legal. */ + asn1r_fin_constr (aCtx, info->result_source,CTX,DEF); + asn1r_fin_constr (aCtx, AARE_result_source_diagnostic,CTX,DEF); + + /* Write result */ + asn1r_strt_constr (aCtx); + asn1r_wr_i16 (aCtx, info->result); + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, AARE_result,CTX,DEF); + + /* Write ASO Context Name. */ + if (info->ASO_context_name_pres) + { + asn1r_strt_constr (aCtx); + asn1r_wr_objid (aCtx, info->ASO_context_name.comps, info->ASO_context_name.num_comps); + asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI); + asn1r_fin_constr (aCtx, AARE_ASO_context_name,CTX,DEF); + } + + /* Write protocol_version. */ + asn1r_wr_bitstr (aCtx, &version1_bit_str, 1); + asn1r_fin_prim (aCtx, AARE_protocol_version, CTX); + + asn1r_fin_constr (aCtx, TAG_AARE,APP,DEF); /* Finish AARE APDU */ + + msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */ + msg_len = ASN1_ENC_LEN (aCtx); + +#if !(defined(REDUCED_STACK) || defined(MOSI)) + /* Fastbyte Presentation and Session (2 bytes). */ + *(--msg_ptr) = 0x01; /* Short-CP mode = BER */ + switch (info->result) + { + case 0: + *(--msg_ptr)=(ST_UCHAR)0xF0; /* Short-SAC (SI=11110) 0 params */ + break; + case 1: + *(--msg_ptr)=(ST_UCHAR)0xE3; /* Short-SRF (SI=11100) 0 params, */ + /* transport conn released, permanent */ + break; + case 2: + *(--msg_ptr)=(ST_UCHAR)0xE2; /* Short-SRF (SI=11100) 0 params, */ + /* transport conn released, transient */ + break; + default: + return (E_ACSE_INVALID_PARAM); /* Invalid Parameter */ + } + msg_len+=2; /* adjust len */ +#endif /* !(defined(REDUCED_STACK) || defined(MOSI)) */ + + if (msg_len > acse_msgsize) + return (E_ACSE_BUFFER_OVERFLOW); + +#if defined(MOSI) + acse_conn->apdu_ptr = msg_ptr; + acse_conn->apdu_len = msg_len; + if (info->result) + /* NOTE: COSP will free "acse_conn" after T-disconnect. */ + retcode = copp_con_rsp_neg (acse_conn, -1); /* -1 means "from user" */ + else + { + retcode = copp_con_rsp_pos (acse_conn); + if (retcode == SD_SUCCESS) + acse_conn->state = STATE_ASSOCIATED; + } + if (retcode != SD_SUCCESS) + { + #if 0 + /* EJV 2/27/2008: if copp_con_rsp_* fails then the most probable cause is */ + /* that the socket was disconencted. In this case the */ + /* the tp0_disconnect_ind will free the acse_conn. */ + /* If it was other error the application will issue an abort */ + /* to cleanup the connection. */ + acse_free_con (acse_conn); /* Dump conn tracking struct */ + #endif /* 0 */ + ACSELOG_ENC0 ("ACSE-ERROR: failed to send A-ASSOCIATE.rsp (disconnected socket or other error)."); + return (E_ACSE_SEND_ERR); + } +#else /* !MOSI */ + /* Send via tp4_data. */ + /* The "user_conn_id" is just a pointer to "acse_conn" cast to a ST_LONG.*/ + retcode = tp4_data (acse_conn->tp4_conn_id, TP4_EOT, msg_len, (ST_CHAR *) msg_ptr); + if (retcode != SD_SUCCESS) + { + acse_free_con (acse_conn); /* Dump conn tracking struct */ + return (E_ACSE_SEND_ERR); + } + + if (info->result == 0) + acse_conn->state = STATE_ASSOCIATED; + else + acse_conn->state = STATE_IDLE; +#endif /* !MOSI */ + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* a_release_req */ +/************************************************************************/ +ST_RET a_release_req ( + ST_LONG acse_conn_id, /* ACSE's connection ID */ + RLRQ_APDU *info) /* RLRQ_APDU info */ + { +ST_UCHAR *msg_ptr; +ST_UINT msg_len; +ACSE_CONN *acse_conn; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + acse_conn = (ACSE_CONN *)acse_conn_id; + + ACSELOG_ENC2 ("A-RELEASE.req: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + + if (acse_conn == NULL) + return (E_ACSE_INVALID_CONN_ID); /* Invalid acse_conn_id */ + + if (acse_conn->state != STATE_ASSOCIATED) + return (E_ACSE_INVALID_STATE); /* Invalid state for this operation*/ + + /* Everything looks OK. Go ahead and encode request and send it. */ +#if defined (MOSI) + asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize); +#else + asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize); +#endif + + asn1r_strt_constr (aCtx); /* Start RLRQ APDU constructor */ + /* Write user_info. */ + if (info->user_info.len) + { + asn1r_strt_constr (aCtx); +#if defined (MOSI) + acse_encode_user_info (aCtx, acse_conn, &info->user_info); +#else /* !MOSI */ + asn1r_wr_octstr (aCtx, info->user_info.ptr, info->user_info.len); + /* No P-Contexts in this implementation, so skip transfer-syntax */ + /* and p-context-id. */ +#endif /* !MOSI */ + asn1r_fin_constr (aCtx, RLRQ_user_info,CTX,DEF); + } + + /* Write Release Reason. */ + if (info->reason_pres) + { + asn1r_wr_i16 (aCtx, info->reason); + asn1r_fin_prim (aCtx, RLRQ_reason,CTX); + } + + asn1r_fin_constr (aCtx, TAG_RLRQ,APP,DEF); /* Finish RLRQ APDU */ + msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */ + msg_len = ASN1_ENC_LEN (aCtx); + if (msg_len > acse_msgsize) + return (E_ACSE_BUFFER_OVERFLOW); + +#if defined(MOSI) + acse_conn->apdu_ptr = msg_ptr; + acse_conn->apdu_len = msg_len; + /* Send RLRQ APDU via P-RELEASE.req */ + if (copp_rel_req (acse_conn) != SD_SUCCESS) + return (E_ACSE_SEND_ERR); +#else /* !MOSI */ + /* Send RLRQ APDU via T-DATA.req */ + if (tp4_data (acse_conn->tp4_conn_id, TP4_EOT, msg_len, (ST_CHAR *) msg_ptr) != SD_SUCCESS) + return (E_ACSE_SEND_ERR); +#endif /* !MOSI */ + acse_conn->state = STATE_RLRE_WAIT; + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* a_release_rsp */ +/************************************************************************/ +ST_RET a_release_rsp ( + ST_LONG acse_conn_id, /* ACSE's connection ID */ + RLRE_APDU *info) /* RLRE_APDU info */ + { +ST_UCHAR *msg_ptr; +ST_UINT msg_len; +ACSE_CONN *acse_conn; +ST_RET retcode; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + acse_conn = (ACSE_CONN *)acse_conn_id; + + ACSELOG_ENC2 ("A-RELEASE.rsp: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + + if (acse_conn == 0) + return (E_ACSE_INVALID_CONN_ID); /* Invalid acse_conn_id */ + + /* This state may happen, but ACSE state machine says do nothing. */ + if (acse_conn->state == STATE_RESP_COLL) + { + ACSELOG_ENC0C ("A-RELEASE.rsp not sent because this is Responder side of RELEASE collision"); + return (SD_SUCCESS); + } + + if (acse_conn->state != STATE_ARLSRSP_WAIT && + acse_conn->state != STATE_INIT_COLL) + return (E_ACSE_INVALID_STATE); /* Invalid state for this operation*/ + + /* Everything looks OK. Go ahead and encode response and send it. */ +#if defined (MOSI) + asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize); +#else + asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize); +#endif + + asn1r_strt_constr (aCtx); /* Start RLRE APDU constructor */ + /* Write user_info. */ + if (info->user_info.len) + { + asn1r_strt_constr (aCtx); +#if defined (MOSI) + acse_encode_user_info (aCtx, acse_conn, &info->user_info); +#else /* !MOSI */ + asn1r_wr_octstr (aCtx, info->user_info.ptr, info->user_info.len); + /* No P-Contexts in this implementation, so skip transfer-syntax */ + /* and p-context-id. */ +#endif /* !MOSI */ + asn1r_fin_constr (aCtx, RLRE_user_info,CTX,DEF); + } + + /* Write Release Reason. */ + if (info->reason_pres) + { + asn1r_wr_i16 (aCtx, info->reason); + asn1r_fin_prim (aCtx, RLRE_reason,CTX); + } + + asn1r_fin_constr (aCtx, TAG_RLRE,APP,DEF); /* Finish RLRE APDU */ + msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */ + msg_len = ASN1_ENC_LEN (aCtx); + if (msg_len > acse_msgsize) + return (E_ACSE_BUFFER_OVERFLOW); + +#if defined(MOSI) + acse_conn->apdu_ptr = msg_ptr; + acse_conn->apdu_len = msg_len; + /* NOTE: Only "affirmative" allowed because "Negotiated Release" not */ + /* supported by Session. */ + retcode = copp_rel_rsp_pos (acse_conn); +#else /* !MOSI */ + /* Send Transport Data request. */ + retcode = tp4_data (acse_conn->tp4_conn_id, TP4_EOT, msg_len, (ST_CHAR *) msg_ptr); +#endif /* !MOSI */ + if (retcode != SD_SUCCESS) + return (E_ACSE_SEND_ERR); + + if (acse_conn->state == STATE_ARLSRSP_WAIT) + acse_conn->state = STATE_IDLE; + else /* must be STATE_INIT_COLL */ + acse_conn->state = STATE_RLRE_WAIT; + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* a_abort_req */ +/************************************************************************/ +ST_RET a_abort_req ( + ST_LONG acse_conn_id, /* ACSE's connection ID */ + ABRT_APDU *info) /* ABRT_APDU info */ + { +ST_UCHAR *msg_ptr; +ST_UINT msg_len; +ACSE_CONN *acse_conn; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + + + + acse_conn = (ACSE_CONN *)acse_conn_id; + + ACSELOG_ENC2 ("A-ABORT.req: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + + if (acse_conn == NULL) + return (E_ACSE_INVALID_CONN_ID); /* Invalid acse_conn_id */ + + if (acse_conn->state == STATE_IDLE) /* Waiting for T-DISCONNECT */ + return (E_ACSE_INVALID_STATE); /* Invalid state for this operation*/ + +#ifndef MOSI + if (acse_conn->state == STATE_TP4CONN_WAIT) + { + /* Don't free struct now. When get response, don't pass up to user */ + /* and free acse_conn then. */ + acse_conn->state = STATE_AARE_ABANDON; + return (SD_SUCCESS); + } + + if (acse_conn->state == STATE_AARE_WAIT) + { + /* Don't free struct now. When get response, don't pass up to user */ + /* and free acse_conn then. */ + acse_conn->state = STATE_AARE_ABANDON; + return (SD_SUCCESS); + } +#endif /* !MOSI */ + + /* Everything looks OK. Go ahead and encode request and send it. */ +#if defined (MOSI) + asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize); +#else + asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize); +#endif + + asn1r_strt_constr (aCtx); /* Start ABRT APDU constructor */ + /* Write user_info. */ + if (info->user_info.len) + { + asn1r_strt_constr (aCtx); +#if defined (MOSI) + acse_encode_user_info (aCtx, acse_conn, &info->user_info); +#else /* !MOSI */ + asn1r_wr_octstr (aCtx, info->user_info.ptr, info->user_info.len); + /* No P-Contexts in this implementation, so skip transfer-syntax */ + /* and p-context-id. */ +#endif /* !MOSI */ + asn1r_fin_constr (aCtx, ABRT_user_info,CTX,DEF); + } + + /* Write Abort Diagnostic. */ + if(info->diagnostic_pres == SD_TRUE) + { + asn1r_wr_i16 (aCtx, info->diagnostic); + asn1r_fin_prim (aCtx, ABRT_diagnostic,CTX); + } + + /* Write Abort Source. */ + asn1r_wr_i16 (aCtx, info->source); + asn1r_fin_prim (aCtx, ABRT_source,CTX); + + asn1r_fin_constr (aCtx, TAG_ABRT,APP,DEF); /* Finish ABRT APDU */ + msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */ + msg_len = ASN1_ENC_LEN (aCtx); + if (msg_len > acse_msgsize) + return (E_ACSE_BUFFER_OVERFLOW); + + + + +#if defined(MOSI) + /* Send P-U-Abort Request. */ + acse_conn->apdu_ptr = msg_ptr; + acse_conn->apdu_len = msg_len; + acse_conn->state = STATE_IDLE; /* COSP will free acse_conn. */ + if (copp_u_abort_req (acse_conn) != SD_SUCCESS) + return (E_ACSE_SEND_ERR); + /* CRITICAL: DO NOT access acse_conn after abort. It may have been */ + /* freed by cosp_u_abort_req (called from copp_u_abort_req). */ +#else /* !MOSI */ + /* Send Transport Disconnect request. */ + tp4_disconnect (acse_conn->tp4_conn_id, msg_len, (ST_CHAR *) msg_ptr); + acse_free_con (acse_conn); /* Dump conn tracking struct */ +#endif /* !MOSI */ + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* a_data_req - Send A-Data req. */ +/************************************************************************/ +ST_RET a_data_req ( + ST_LONG acse_conn_id, /* ACSE's ID for this connection */ + ST_UINT data_len, + ST_UCHAR *data) + { +ACSE_CONN *acse_conn; + + acse_conn = (ACSE_CONN *)acse_conn_id; + +#if defined(MOSI) + if (data_len > acse_msgsize) + { /* Should never happen if ACSE user code is correct. */ + ACSELOG_ERR2 ("ACSE-ERROR: A-DATA.req: data len (%d) > max (%d)", + data_len, acse_msgsize); + return (E_ACSE_BUFFER_OVERFLOW); + } + /* Just copy data to end of "cosp_buf" & set apdu_ptr, apdu_len. */ + /* copp_data_req will add COPP encoding in front of this data. */ + acse_conn->apdu_ptr = cosp_buf + cosp_msgsize - data_len; + acse_conn->apdu_len = data_len; + memcpy (acse_conn->apdu_ptr, data, data_len); + + return (copp_data_req (acse_conn)); +#else /* !MOSI */ + return (tp4_data (acse_conn->tp4_conn_id, TP4_EOT, data_len,(ST_CHAR *)data)); +#endif /* !MOSI */ + } + +#if defined (MOSI) +/************************************************************************/ +/* acse_encode_user_info */ +/************************************************************************/ +static ST_VOID acse_encode_user_info (ASN1_ENC_CTXT *aCtx, ACSE_CONN *acse_conn, BUFFER *user_info) + { + asn1r_strt_constr (aCtx); /* start EXTERNAL */ + asn1r_strt_constr (aCtx); /* start single-ASN1-type */ + asn1r_wr_octstr (aCtx, user_info->ptr, user_info->len); + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish single-ASN1-type */ + asn1r_wr_i8 (aCtx, acse_conn->pcimms); /* PCI for MMS */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + + /* NOTE: Transfer-syntax-name (OPTIONAL) not sent. Saves few bytes. */ + + asn1r_fin_constr (aCtx, EXTERN_CODE,UNI,DEF); /* finish EXTERNAL */ + return; + } + +#endif /* MOSI */ + +#if !defined (MOSI) +/************************************************************************/ +/* acse_free_con */ +/*----------------------------------------------------------------------*/ +/* This function will free the pointer to connection info. */ +/* For MOSI, a slightly different "acse_free_con" function is */ +/* defined in COSP????.c */ +/************************************************************************/ +ST_VOID acse_free_con (ACSE_CONN *acse_conn) + { + if (acse_conn->save_buf.len) + M_FREE (MSMEM_ACSE_DATA, acse_conn->save_buf.ptr); + M_FREE (MSMEM_ACSE_CONN, acse_conn); + } +#endif /* !MOSI */ + +/************************************************************************/ +/* a_buffers_avail - Buffers available for sending A-Data req. */ +/* This function returns the number of buffers available for sending */ +/* A-Data. This may be used, for example, when sending Information */ +/* Reports, to make sure there are always enough buffers for sending */ +/* responses to incoming requests. */ +/* */ +/* Parameters: */ +/* ST_LONG acse_conn_id ACSE Connection ID */ +/* */ +/* Return: */ +/* ST_INT # of ACSE transmit buffers available */ +/************************************************************************/ + +#if defined(LEAN_T) || defined(REDUCED_STACK) + +ST_INT a_buffers_avail ( + ST_LONG acse_conn_id) /* ACSE's ID for this connection */ + { +#if defined(LEAN_T) +ACSE_CONN *acse_conn; + + acse_conn = (ACSE_CONN *)acse_conn_id; + + return (tp4_buffers_avail (acse_conn->tp4_conn_id)); +#endif + +#if defined(REDUCED_STACK) + return (2); +#endif + } + +#endif + +#if defined (MOSI) /* Only MOSI uses events. */ +#if defined(_WIN32) +/* Not used for DOS, QNX, or VXWORKS */ +/************************************************************************/ +/* a_get_event_handles */ +/* Returns a pointer to an array of (ST_EVENT_SEM) and sets */ +/* (*pNumEntries) equal to the number of entries. */ +/************************************************************************/ +ST_EVENT_SEM a_get_event_handles (ST_INT *pNumEntries) + { +static ST_EVENT_SEM EventArray [2]; +ST_INT NumEntries = 0; + +#if defined (TP4_ENABLED) + /* If "hMainEvent" initialized, use it instead of default "hMMSEvent"*/ + if (hMainEvent) + EventArray [NumEntries++] = hMainEvent; /* CLNP thread event. */ + else + EventArray [NumEntries++] = hMMSEvent; /* driver event */ +#endif +#if defined (TP0_ENABLED) + EventArray [NumEntries++] = hTcpEvent; /* TCP/IP sockets event */ +#endif + + *pNumEntries = NumEntries; + return (EventArray); + } +#else /* !defined(_WIN32) */ +/************************************************************************/ +/* a_get_event_handles_unix */ +/* Returns a pointer to an array of handles and sets */ +/* (*pNumEntries) equal to the number of entries. */ +/* NOTE: The TP4_ENABLED option currently only works on "linux". */ +/************************************************************************/ +#if defined(TP4_ENABLED) +#if defined(linux) +extern int hPktSock; +#else +#error TP4 not supported on this platform +#endif +#endif +#if defined(TP0_ENABLED) +extern int pipe_to_main; /* DEBUG: move to include */ +#endif +int *a_get_event_handles_unix (ST_INT *pNumEntries) + { +static int fd_array [2]; +ST_INT NumEntries = 0; + +#if defined(TP4_ENABLED) + fd_array[NumEntries++] = hPktSock; +#endif +#if defined(TP0_ENABLED) + fd_array[NumEntries++] = pipe_to_main; +#endif + *pNumEntries = NumEntries; + return (fd_array); + } +#endif /* !defined(_WIN32) */ +#endif /* MOSI */ + + + /*------------------------------------------------------*/ + /* Security functions */ + /*------------------------------------------------------*/ + +/********************************************************************************/ +/* a_get_security_info */ +/*------------------------------------------------------------------------------*/ +/* Returns pointers to encryption control and partner's authentication info */ +/* from the specified channel info. This functions should be called after */ +/* connection indication was received to retrieve the security informations. */ +/* After the connection terminates call the s_free_part_security_info() to free */ +/* the allocated auth_value buf and cleanup the channel info. */ +/* Parameters: */ +/* ST_LONG acse_conn_id indirect ptr to access security info */ +/* S_SEC_PARAMS *secParams pointer where to ret security info. */ +/* Return: */ +/* ST_RET SD_SUCCESS if get operation succeeded, otherwise */ +/* SD_FAILURE or other error. */ +/********************************************************************************/ +ST_RET a_get_security_info (ST_LONG acse_conn_id, S_SEC_SPARAMS *secParams) +{ +ST_RET ret = SD_SUCCESS; +ACSE_CONN *acse_conn; + + secParams->authInfo = NULL; /* local auth info not stored */ + secParams->partAuthInfo = NULL; /* partner auth info */ + secParams->encryptCtrl = NULL; /* connection encryption info */ + + if (acse_conn_id) + { + acse_conn= (ACSE_CONN *) acse_conn_id; + if (acse_conn) + { + secParams->partAuthInfo = &acse_conn->part_auth_info; + secParams->encryptCtrl = &acse_conn->encrypt_ctrl; + } + } + else + ret = SD_FAILURE; /* cc should be valid in this call */ + + return (ret); +} + +/********************************************************************************/ +/* a_free_security_info */ +/*------------------------------------------------------------------------------*/ +/* Releases authentication info resources. */ +/* Parameters: */ +/* ACSE_AUTH_INFO *authInfo ptr to free the security resources */ +/* Return: */ +/* ST_RET SD_SUCCESS if free operation succeeded */ +/* SD_FAILURE otherwise */ +/********************************************************************************/ +ST_RET a_free_security_info (ACSE_AUTH_INFO *authInfo) +{ +ST_RET ret = SD_SUCCESS; + + if (authInfo) + { + /* clear authentication info */ + /* if there is an existing auth_value buf pointer then we have to free it */ + if (authInfo->auth_pres && authInfo->mech_type != ACSE_AUTH_MECH_PASSWORD) + if (authInfo->u.other_auth.auth_value.buf) + { + chk_free (authInfo->u.other_auth.auth_value.buf); + authInfo->u.other_auth.auth_value.buf = NULL; + authInfo->u.other_auth.auth_value.ptr = NULL; + authInfo->u.other_auth.auth_value.len = 0; + } + authInfo->auth_pres = SD_FALSE; + } + + return (ret); +} + + +/********************************************************************************/ +/* a_free_part_security_info */ +/*------------------------------------------------------------------------------*/ +/* Releases partner authentication resources and resets the field in ACSE_CONN. */ +/* Parameters: */ +/* ST_LONG acse_conn_id indirect ptr to access security info */ +/* Return: */ +/* ST_RET SD_SUCCESS if free operation succeeded */ +/* SD_FAILURE otherwise */ +/********************************************************************************/ +ST_RET a_free_part_security_info (ST_LONG acse_conn_id) +{ +ST_RET ret = SD_SUCCESS; +ACSE_CONN *acse_conn; + + if (acse_conn_id) + { + acse_conn= (ACSE_CONN *) acse_conn_id; + if (acse_conn) + ret = a_free_security_info (&acse_conn->part_auth_info); + } + return (ret); +} + diff --git a/mmslib/ositcps/acse2var.c b/mmslib/ositcps/acse2var.c new file mode 100644 index 0000000..3cda39c --- /dev/null +++ b/mmslib/ositcps/acse2var.c @@ -0,0 +1,39 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1995 All Rights Reserved */ +/* */ +/* MODULE NAME : acse2var.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* Global variables for ACSE component. Used by both connection- */ +/* oriented ACSE and connectionless ACSE. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 09/13/99 MDE 08 Added SD_CONST modifiers */ +/* 07/14/99 JRB 07 Add ACSE Password Authentication obj id. */ +/* 07/10/98 JRB 06 Add *_obj_id so CO and CL ACSE can share. */ +/* 11/15/96 JRB 05 Move acse_debug_sel to acse2enc.c */ +/* 05/02/96 KCR 04 Initialized acse_debug_sel to make sure it */ +/* is pulled into OS/2 library */ +/* 04/17/96 JRB 03 Del acse_sLogCtrl, use sLogCtrl (slog.c) now */ +/* 03/26/96 MDE 02 Chg define to PLAIN_DOS. */ +/* 10/30/95 JRB 01 Created */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "asn1defs.h" + +/* NOTE: we only support ISO MMS Abstract Syntax. No more MAP MMS. */ +SD_CONST MMS_OBJ_ID mms_obj_id = {5,{1,0,9506,2,1}}; /* ISO MMS Abstract Syntax*/ +SD_CONST MMS_OBJ_ID acse_obj_id = {5,{2,2,1,0,1}}; /* ACSE Abstract Syntax*/ +SD_CONST MMS_OBJ_ID asn1_obj_id = {3,{2,1,1}}; /* ASN.1 Transfer Syntax*/ + +SD_CONST MMS_OBJ_ID a_auth_password_obj_id = {4,{2,2,3,1}}; /* ACSE Authent. - Password*/ diff --git a/mmslib/ositcps/checksum.c b/mmslib/ositcps/checksum.c new file mode 100644 index 0000000..2d14127 --- /dev/null +++ b/mmslib/ositcps/checksum.c @@ -0,0 +1,246 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : checksum.c */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module implements the computation of checksum */ +/* using the algorithm defined in Annex B of the ISO 8073 */ +/* or in the ISO 8473. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* checksum_insert */ +/* checksum_verified */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 05/12/97 JRB 03 ch*_verified chk c0. Was checking c1 twice. */ +/* Clean up data types. */ +/* Clarify casting computing x,y in ch*_insert. */ +/* 05/07/97 JRB 02 Changed non-ANSI "%hu" to "%u". */ +/* 06/17/96 EJV 01 Created */ +/************************************************************************/ +#if 0 +/* this file is not neccessary when printf will be replaced with slog */ +#include +#endif + +#include "glbtypes.h" +#include "checksum.h" + + +static ST_VOID get_checksum_c0_c1 (ST_UCHAR *buf, ST_UINT16 buf_len, + ST_UCHAR *pC0, ST_UCHAR *pC1); + + +/************************************************************************/ +/* checksum_insert */ +/*----------------------------------------------------------------------*/ +/* This function computes and inserts the 2 byte checksum into a PDU */ +/* buffer at specified position (and position+1). */ +/* The checksum algorithm is described in ISO 8473 (CLNP) and */ +/* ISO 8073 (Transport protocol). */ +/* Note that the maximum len of TPDU in ISO 8073 is 8192 bytes. */ +/* */ +/* Parameters: */ +/* ST_UCHAR *buf Ptr to encoding buffer on which checksum*/ +/* will be computed. */ +/* ST_UINT16 buf_len Length of the buffer (PDU). */ +/* ST_UINT16 position Position of checksum's first byte in buf*/ +/* (position=0 if checksum is the first */ +/* byte in buffer). */ +/* */ +/* Return: */ +/* ST_VOID none */ +/************************************************************************/ +ST_VOID checksum_insert (ST_UCHAR *buf, ST_UINT16 buf_len, ST_UINT16 position) +{ +ST_UCHAR c0, c1; +ST_LONG x, y; /* the checksum's first and second byte */ +ST_UINT16 sum_pos; /* this is the position of checksum first byte */ + /* in the PDU as specified by algorithm, first */ + /* byte position is 1 not 0. */ + + sum_pos = position+1; + + /* make sure the checksum bytes are cleared */ + buf [position] = buf [position+1] = 0; + + get_checksum_c0_c1 (buf, buf_len, &c0, &c1); + +#if 0 + /* LIZ substitute the printf with slogging */ + printf ("\n Checksum computation: c0=0x%2.2X=%u, c1=0x%2.2X=%u", + (ST_UINT) c0, (ST_UINT) c0, (ST_UINT) c1, (ST_UINT) c1); +#endif + + + x = ((ST_LONG) (buf_len-sum_pos) * (ST_LONG) c0 - (ST_LONG) c1) % 255L; + y = ((ST_LONG) c1 - (ST_LONG) (buf_len-sum_pos+1) * (ST_LONG) c0) % 255L; + + buf [position] = (ST_UCHAR) (x <= 0L ? x+255L : x); + buf [position+1] = (ST_UCHAR) (y <= 0L ? y+255L : y); + +#if 0 + /* LIZ substitute the printf with slogging */ + printf ("\n Checksum computation: buf[%u]=%u, buf[%u]=%u", + position, (ST_UINT) buf[position], + position+1,(ST_UINT) buf[position+1]); +#endif +} + + +/************************************************************************/ +/* checksum_verified */ +/*----------------------------------------------------------------------*/ +/* This function verifies the checksum of a PDU. */ +/* The checksum algorithm is described in ISO 8473 (CLNP) and */ +/* ISO 8073 (Transport protocol). */ +/* Note that the maximum len of TPDU in ISO 8073 is 8192 bytes. */ +/* */ +/* Parameters: */ +/* ST_UCHAR *buf Ptr to encoding buffer on which checksum*/ +/* will be computed. */ +/* ST_UINT16 buf_len Length of the buffer (PDU). */ +/* ST_UINT16 position Position of checksum's first byte in buf*/ +/* (position=0 if checksum is the first */ +/* byte in buffer), used only for CLNP. */ +/* ST_BOOLEAN clnp_csum If SD_TRUE the CLNP checksum will be */ +/* verified, if SD_FALSE the Transport Prot. */ +/* checksum will be verified. */ +/* */ +/* Return: */ +/* ST_BOOLEAN SD_TRUE if verification of checksum is */ +/* successful; */ +/* SD_FALSE if verification failed. */ +/************************************************************************/ +ST_BOOLEAN checksum_verified (ST_UCHAR *buf, ST_UINT16 buf_len, ST_UINT16 position, + ST_BOOLEAN clnp_csum) +{ +ST_BOOLEAN checksum_correct; +ST_UCHAR c0, c1; + + checksum_correct = SD_FALSE; + + if (clnp_csum) + { + if (buf [position] != 0 && buf [position+1] != 0) + { + /* if both bytes in checksum are not 0 then we have to compute the */ + /* checksum */ + + get_checksum_c0_c1 (buf, buf_len, &c0, &c1); + +#if 0 + /* LIZ substitute the printf with slogging */ + printf ("\n Checksum verification: c0=0x%2.2X=%u, c1=0x%2.2X=%u", + (ST_UINT) c0, (ST_UINT) c0, (ST_UINT) c1, (ST_UINT) c1); +#endif + + if (c0 == 0 && c1 == 0) + checksum_correct = SD_TRUE; + } + else if (buf [position] == 0 && buf [position+1] == 0) + { + /* if both bytes in checksum are 0 then the checksum should be */ + /* ignored, and is considered as correct. */ + + checksum_correct = SD_TRUE; + } + + /* if one byte (but not both bytes) in checksum is 0 then the */ + /* checksum is invalid. */ + } + else + { + /* transport protocol checksum */ + + get_checksum_c0_c1 (buf, buf_len, &c0, &c1); + + if (c0 == 0 && c1 == 0) + checksum_correct = SD_TRUE; + } + + return (checksum_correct); +} + + +/************************************************************************/ +/* get_checksum_c0_c1 */ +/*----------------------------------------------------------------------*/ +/* This function computes the checksum values C0 and C1 described in */ +/* ISO 8473 (CLNP) and ISO 8073 (Transport protocol). */ +/* Note that the maximum len of TPDU in ISO 8073 is 8192 bytes. */ +/* To avoid overflow of long values c0 or c1 when the buffer len is */ +/* greater then 4096 the values c0 and c1 are computed in two stages. */ +/* */ +/* Parameters: */ +/* ST_UCHAR *buf Ptr to encoding buffer on which checksum*/ +/* will be computed. */ +/* ST_UINT16 buf_len Length of the buffer (TPDU). */ +/* ST_UCHAR *pC0 Pointer where to return the computed C0.*/ +/* ST_UCHAR *pC1 Pointer where to return the computed C1.*/ +/* */ +/* Return: */ +/* ST_VOID none */ +/************************************************************************/ +static ST_VOID get_checksum_c0_c1 (ST_UCHAR *buf, ST_UINT16 buf_len, + ST_UCHAR *pC0, ST_UCHAR *pC1) +{ +ST_ULONG c0, c1; + + c0 = c1 = 0L; + + while (buf_len-- > 0) + { + c0 = c0 + (ST_ULONG) *(buf++); + c1 = c1 + c0; + + /* if the buf_len > 4096 there is risk of overflowing, so we take */ + /* modulus at 4096 bytes to bring the c0 and c1 numbers down */ + + if (buf_len == 4096) + { + c0 = c0 % 255L; + c1 = c1 % 255L; + } + } + *pC0 = (ST_UCHAR) (c0 % 255L); + *pC1 = (ST_UCHAR) (c1 % 255L); + + /* the code below can substitute the code above if long 32-bit values */ + /* are not available with given compiler. */ + #if 0 + ST_UINT16 c0,c1; + c0 = c1 = 0; + while (buf_len-- > 0) + { + c0 += (ST_UINT16) *(buf++); + if (c0 >= 255) + { + ++c0; /* this two lines are equvalen to mod 255 */ + c0 &= 0x00ff; + } + c1 += c0; + if (c1 >= 255) + { + ++c1; + c1 &= 0x00ff; + } + } + *pC0 = (ST_UCHAR) c0; + *pC1 = (ST_UCHAR) c1; + #endif +} + + diff --git a/mmslib/ositcps/copp_dec.c b/mmslib/ositcps/copp_dec.c new file mode 100644 index 0000000..5bd83bc --- /dev/null +++ b/mmslib/ositcps/copp_dec.c @@ -0,0 +1,488 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2002, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : copp_dec.c */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file implements decoding of most confirm/indication*/ +/* functions. */ +/* */ +/* For information see the: */ +/* ISO 8822 "Information processing systems - Open Systems */ +/* Interconnection - Connection oriented presentation service */ +/* definition. */ +/* ISO 8823 "Information processing systems - Open Systems */ +/* Interconnection - Connection oriented presentation protocol */ +/* specification. */ +/* */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* u_cosp_bind_cnf */ +/* u_cosp_unbind_cnf */ +/* */ +/* u_cosp_rel_cnf_pos */ +/* u_cosp_rel_ind */ +/* u_cosp_p_abort_ind */ +/* u_cosp_data_ind */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/26/09 JRB 12 Fix to handle PDV len=0 or User-data len=0. */ +/* 04/28/08 GLB 11 Removed CALLED_ONLY and CALLING_ONLY */ +/* 01/02/02 JRB 10 Converted to use ASN1R (re-entrant ASN1) */ +/* 04/24/01 JRB 09 Allow octet-aligned PDV. Don't think it's */ +/* legal but some stacks (ONE?) may use it. */ +/* 02/21/01 JRB 08 Fix previous change. Was checking wrong byte */ +/* in PDU for Indef Len. Use global flag instead*/ +/* 12/20/00 JRB 07 asn1_skip_elmnt doesn't work for indef len */ +/* encoding. Use "parse_next" instead. */ +/* 08/13/98 JRB 06 Lint cleanup. */ +/* 03/18/98 JRB 05 Use defines (not variables) for ASN1 errors. */ +/* 02/20/98 JRB 04 Chg abort_reason & event_id to ST_INT8. */ +/* 12/22/97 JRB 03 Use ST_INT8. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/19/97 JRB 02 Add "CALLING" support. General cleanup. */ +/* 02/27/97 JRB 01 Created */ +/************************************************************************/ +#ifdef DEBUG_SISCO +static char *thisFileName = __FILE__; +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "asn1defs.h" +#include "acse2.h" + +#include "copp.h" +#include "cosp_usr.h" + +/* START_p_user_data used by everyone, so proto in include */ +/* START_pdv_list used by everyone, so proto in include */ +static ST_VOID decode_pdv_tsn (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_pdv_pci (ASN1_DEC_CTXT *aCtx); +static ST_VOID START_pdv (ASN1_DEC_CTXT *aCtx); +static ST_VOID parse_next_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_pdv (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_pdv_list (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_p_user_data (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/* Global Variables */ +/************************************************************************/ +ST_CHAR expected_pdv_pci; +ST_UCHAR *pdv_data_ptr; +ST_INT pdv_data_len; + +ST_BOOLEAN p_user_data_is_outer; /* Is P-User-data outermost constr?*/ + /* SD_TRUE or SD_FALSE */ + +/************************************************************************/ +/* u_cosp_bind_cnf */ +/************************************************************************/ +ST_VOID u_cosp_bind_cnf (ST_LONG user_bind_id, ST_LONG cosp_bind_id, ST_RET result) + { + COPP_LOG_DEC3 ("P-BIND.cnf: copp_user_bind_id =0x%08X copp_bind_id =%9ld result =%d", + user_bind_id, cosp_bind_id, result); + + u_copp_bind_cnf (user_bind_id, cosp_bind_id, result); + } + +/************************************************************************/ +/* u_cosp_unbind_cnf */ +/************************************************************************/ +ST_VOID u_cosp_unbind_cnf (ST_LONG user_bind_id) + { + COPP_LOG_DEC1 ("P-UNBIND.cnf: copp_user_bind_id =0x%08X", user_bind_id); + + u_copp_unbind_cnf (user_bind_id); + } + +/* See "coppdcp.c" for "u_cosp_con_cnf_pos" function. */ +/* See "coppdcpr.c" for "u_cosp_con_cnf_neg" function. */ + +/************************************************************************/ +/* u_cosp_rel_cnf_pos */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate positive */ +/* result of the release operation. */ +/* */ +/* Parameters: */ +/* acse_conn Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_rel_cnf_pos (ACSE_CONN *acse_conn) + { +ST_INT8 abort_reason; +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean */ + + if (acse_conn->copp_state != COPP_STATE_CONNECTED) + { + COPP_LOG_ERR1 ("COPP-ERROR: Cannot process S-RELEASE.cnf+ (Illegal state=%d)", + acse_conn->copp_state); + return; + } + + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + + /* Clean out old stuff from structure. */ + decode_acse_conn = acse_conn; /* Save in global so asn1r_decode_asn1 (aCtx, */ + /* can fill it in. */ + + /* Set the PCI to be used during P-User-Data decode. */ + expected_pdv_pci = decode_acse_conn->pciacse; + + p_user_data_is_outer = SD_TRUE; /* P-User-data IS outermost constr. */ + + /* CRITICAL: Init APDU ptr & len. Changed only if APDU found in msg. */ + acse_conn->apdu_ptr = NULL; + acse_conn->apdu_len = 0; + /* CRITICAL: Init global PDV ptr & len. Changed only if PDV found in msg.*/ + pdv_data_ptr = NULL; + pdv_data_len = 0; + +/* Call 'asn1r_decode_asn1 (aCtx,' to parse the message. */ + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + asn1r_decode_asn1 (aCtx, acse_conn->ppdu_ptr,acse_conn->ppdu_len); + if (aCtx->asn1r_pdu_dec_err != NO_DECODE_ERR) + { + COPP_LOG_ERR1 ("COPP-ERROR: ASN.1 decode of S-Release.cnf failed, err=%d", aCtx->asn1r_pdu_dec_err); + abort_reason = 1; /* unrecognized-ppdu */ + /* Don't send ARP PPDU. COSP already thinks we're released. */ + /* Pass P-P-Abort.ind to COPP-user. */ + u_copp_p_abort_ind (acse_conn, abort_reason); + } + else + { + COPP_LOG_DEC2 ("P-RELEASE.cnf+: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + COPP_LOG_DECC1 ("User data length: %d", acse_conn->apdu_len); + COPP_LOG_DECH (acse_conn->apdu_len, acse_conn->apdu_ptr); + + if (acse_conn->cr) + { + acse_conn->cr = SD_FALSE; + acse_conn->rl = SD_FALSE; /* and stay in COPP_STATE_CONNECTED */ + } + else + acse_conn->copp_state = COPP_STATE_IDLE; + + u_copp_rel_cnf_pos (acse_conn); + } + } + +/* See "coppdcp.c" for "u_cosp_con_ind" function. */ + +/************************************************************************/ +/* u_cosp_rel_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* remote node wishes to release a connection. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *acse_conn Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_rel_ind (ACSE_CONN *acse_conn) + { +ST_INT8 abort_reason; +ST_INT8 event_id; +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean */ + + if (acse_conn->copp_state != COPP_STATE_CONNECTED) + { + COPP_LOG_ERR1 ("COPP-ERROR: Cannot process S-RELEASE.ind (Illegal state=%d)", + acse_conn->copp_state); + return; + } + /* Set release collision flags. */ + if (acse_conn->rl) + acse_conn->cr = SD_TRUE; + acse_conn->rl = SD_TRUE; + + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + + /* Clean out old stuff from structure. */ + decode_acse_conn = acse_conn; /* Save in global so asn1r_decode_asn1 (aCtx, */ + /* can fill it in. */ + + /* Set the PCI to be used during P-User-Data decode. */ + expected_pdv_pci = decode_acse_conn->pciacse; + + p_user_data_is_outer = SD_TRUE; /* P-User-data IS outermost constr. */ + + /* CRITICAL: Init APDU ptr & len. Changed only if APDU found in msg. */ + acse_conn->apdu_ptr = NULL; + acse_conn->apdu_len = 0; + /* CRITICAL: Init global PDV ptr & len. Changed only if PDV found in msg.*/ + pdv_data_ptr = NULL; + pdv_data_len = 0; + +/* Call 'asn1r_decode_asn1 (aCtx,' to parse the message. */ + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + asn1r_decode_asn1 (aCtx, acse_conn->ppdu_ptr,acse_conn->ppdu_len); + if (aCtx->asn1r_pdu_dec_err != NO_DECODE_ERR) + { + COPP_LOG_ERR1 ("COPP-ERROR: ASN.1 decode of S-Release.ind failed, err=%d", aCtx->asn1r_pdu_dec_err); + acse_conn->copp_state = COPP_STATE_IDLE; + abort_reason = 1; /* unrecognized-ppdu */ + event_id = 14; /* s-release-indication */ + /* Encode and send ARP PPDU. */ + copp_p_abort_req (acse_conn, abort_reason, event_id); + /* Pass P-P-Abort.ind to COPP-user. */ + u_copp_p_abort_ind (acse_conn, abort_reason); + } + else + { + COPP_LOG_DEC2 ("P-RELEASE.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + COPP_LOG_DECC1 ("User data length: %d", acse_conn->apdu_len); + COPP_LOG_DECH (acse_conn->apdu_len, acse_conn->apdu_ptr); + + u_copp_rel_ind (acse_conn); + } + } + +/************************************************************************/ +/* u_cosp_p_abort_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* connection has been aborted by SS-provider (local or remote). */ +/* */ +/* Parameters: */ +/* ACSE_CONN *acse_con Pointer to connection info */ +/* ST_INT reason see def reasons COSP_P_AB_IND_... above */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_p_abort_ind (ACSE_CONN *acse_conn, ST_INT reason) + { + if (acse_conn->copp_state == COPP_STATE_IDLE) + { + COPP_LOG_ERR1 ("COPP-ERROR: Cannot process S-P-ABORT.ind (Illegal state=%d)", + acse_conn->copp_state); + return; + } + + COPP_LOG_DEC3 ("P-P-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d", + acse_conn, acse_conn->user_conn_id, reason + 0x100); + + acse_conn->copp_state = COPP_STATE_IDLE; + u_copp_p_abort_ind (acse_conn, reason + 0x100); + } + +/************************************************************************/ +/* u_cosp_data_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* data SPDU has been received. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *acse_conn Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_data_ind (ACSE_CONN *acse_conn) + { +ST_INT8 abort_reason; +ST_INT8 event_id; +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean */ + + if (acse_conn->copp_state != COPP_STATE_CONNECTED) + { + COPP_LOG_ERR1 ("COPP-ERROR: Cannot process S-DATA.ind (Illegal state=%d)", + acse_conn->copp_state); + return; + } + + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + + /* Clean out old stuff from structure. */ + decode_acse_conn = acse_conn; /* Save in global so asn1r_decode_asn1 (aCtx, */ + /* can fill it in. */ + + /* Set the PCI to be used during P-User-Data decode. */ + expected_pdv_pci = decode_acse_conn->pcimms; + + p_user_data_is_outer = SD_TRUE; /* P-User-data IS outermost constr. */ + + /* CRITICAL: Init APDU ptr & len. Changed only if APDU found in msg. */ + acse_conn->apdu_ptr = NULL; + acse_conn->apdu_len = 0; + /* CRITICAL: Init global PDV ptr & len. Changed only if PDV found in msg.*/ + pdv_data_ptr = NULL; + pdv_data_len = 0; + +/* Call 'asn1r_decode_asn1 (aCtx,' to parse the message. */ + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + asn1r_decode_asn1 (aCtx, acse_conn->ppdu_ptr,acse_conn->ppdu_len); + if (aCtx->asn1r_pdu_dec_err != NO_DECODE_ERR) + { + COPP_LOG_ERR1 ("COPP-ERROR: ASN.1 decode of S-Data.ind failed, err=%d", aCtx->asn1r_pdu_dec_err); + abort_reason = 1; /* unrecognized-ppdu */ + event_id = -1; /* Unlisted */ + /* Encode and send ARP PPDU. */ + copp_p_abort_req (acse_conn, abort_reason, event_id); + /* Pass P-P-Abort.ind to COPP-user. */ + u_copp_p_abort_ind (acse_conn, abort_reason); + } + else + { + COPP_LOG_DEC2 ("P-DATA.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + COPP_LOG_DECC1 ("User data length: %d", acse_conn->apdu_len); + COPP_LOG_DECH (acse_conn->apdu_len, acse_conn->apdu_ptr); + + u_copp_data_ind (acse_conn); + } + } + + /*======================================================*/ + /* ASN.1 DECODE FUNCTIONS FOR P-USER-DATA */ + /* */ + /* Used for CP, CPA, CPR, ARU, DT, or REL decode. */ + /*======================================================*/ + +/************************************************************************/ +/* START_p_user_data */ +/************************************************************************/ +ST_VOID START_p_user_data (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,START_pdv_list); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_p_user_data; + } +/************************************************************************/ +/* START_pdv_list */ +/* ACSE also uses this function to decode "EXTERNAL". Although defined */ +/* independently, it's encoding is same as "PDV-list". */ +/************************************************************************/ +ST_VOID START_pdv_list (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, UNI,OBJ_ID_CODE,decode_pdv_tsn); + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_pdv_pci); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_pdv_list; + } +/************************************************************************/ +/* decode_pdv_tsn */ +/************************************************************************/ +static ST_VOID decode_pdv_tsn (ASN1_DEC_CTXT *aCtx) + { +MMS_OBJ_ID tsn; + + if (asn1r_get_objid (aCtx, tsn.comps,&tsn.num_comps)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + if (asn1_objidcmp (&tsn, &asn1_obj_id) != 0) + { /* TSN better be ASN1 */ + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BITSTR); + return; + } + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_pdv_pci); + } +/************************************************************************/ +/* decode_pdv_pci */ +/************************************************************************/ +static ST_VOID decode_pdv_pci (ASN1_DEC_CTXT *aCtx) + { +ST_INT8 pci; + + if (asn1r_get_i8 (aCtx, &pci)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + if (pci != expected_pdv_pci) + { /* Not the pci we're expecting. */ + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BITSTR); + return; + } + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,START_pdv); /* Must be single-ASN1-type */ + /* Octet-aligned doesn't appear to be legal, but some stacks (ONE?) */ + /* may use it. To be friendly, let's accept it. */ + ASN1R_TAG_ADD (aCtx, CTX,1,START_pdv); /* Allow octet-aligned */ + } +/************************************************************************/ +/* START_pdv */ +/************************************************************************/ +static ST_VOID START_pdv (ASN1_DEC_CTXT *aCtx) + { + /* Should now point to PDV data. Save until decode done. */ + pdv_data_ptr = aCtx->asn1r_field_ptr; + + /* If this is indefinite length encoding, use "asn1r_parse_next (aCtx,". */ + /* If "normal" encoding, use "asn1_skip_elmnt" (faster). */ + if (aCtx->asn1r_indef_flag) + { /* indefinite length encoding */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_pdv; + asn1r_parse_next (aCtx, parse_next_done); + } + else + { /* "normal" encoding */ + pdv_data_len = aCtx->asn1r_elmnt_len; + asn1_skip_elmnt (aCtx); /* Done decoding PPDU. Let ACSE decode rest. */ + } + } +/************************************************************************/ +/* parse_next_done */ +/* Only used for indefinite length encoding. */ +/************************************************************************/ +static ST_VOID parse_next_done (ASN1_DEC_CTXT *aCtx) + { /* called when "asn1r_parse_next (aCtx," is done */ + } +/************************************************************************/ +/* END_pdv */ +/* Only used for indefinite length encoding. */ +/************************************************************************/ +static ST_VOID END_pdv (ASN1_DEC_CTXT *aCtx) + { + pdv_data_len = aCtx->asn1r_field_ptr - pdv_data_ptr - 2; /* -2 strips 00 00*/ + } +/************************************************************************/ +/* END_pdv_list */ +/************************************************************************/ +static ST_VOID END_pdv_list (ASN1_DEC_CTXT *aCtx) + { + } +/************************************************************************/ +/* END_p_user_data */ +/************************************************************************/ +static ST_VOID END_p_user_data (ASN1_DEC_CTXT *aCtx) + { + decode_acse_conn->apdu_ptr = pdv_data_ptr; + decode_acse_conn->apdu_len = pdv_data_len; + if (p_user_data_is_outer) /* Is P-User-data outermost constr? */ + aCtx->asn1r_decode_done_fun = NULL; /* done decoding */ + } + diff --git a/mmslib/ositcps/copp_enc.c b/mmslib/ositcps/copp_enc.c new file mode 100644 index 0000000..597943e --- /dev/null +++ b/mmslib/ositcps/copp_enc.c @@ -0,0 +1,660 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2002, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : copp_enc.c */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file implements binding and encoding functions */ +/* of the COPP protocol. */ +/* */ +/* For information see the: */ +/* ISO 8822 "Information processing systems - Open Systems */ +/* Interconnection - Connection oriented presentation service */ +/* definition. */ +/* ISO 8823 "Information processing systems - Open Systems */ +/* Interconnection - Connection oriented presentation protocol */ +/* specification. */ +/* */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* copp_bind */ +/* copp_unbind */ +/* */ +/* copp_con_req */ +/* copp_con_rsp_pos */ +/* copp_con_rsp_neg */ +/* */ +/* copp_rel_req */ +/* copp_rel_rsp_pos */ +/* */ +/* copp_u_abort_req */ +/* */ +/* copp_data_req */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/28/08 GLB 07 Removed CALLED_ONLY and CALLING_ONLY */ +/* 01/02/02 JRB 06 Converted to use ASN1R (re-entrant ASN1) */ +/* 06/17/98 JRB 05 Allow second call to copp_bind if PSEL same. */ +/* Use new error codes. */ +/* 02/20/98 JRB 04 Cast wr_i8 arg. Chg abort_reason to ST_INT8. */ +/* 12/22/97 JRB 03 Use ST_INT8. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/19/97 JRB 02 Add "CALLING" support. General cleanup. */ +/* 02/27/97 JRB 01 Created */ +/************************************************************************/ +#ifdef DEBUG_SISCO +static char *thisFileName = __FILE__; +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "asn1defs.h" +#include "acse2.h" + +#include "copp.h" +#include "cosp_usr.h" + +ST_BOOLEAN copp_bind_called; /* flag to tell if copp_bind was called */ +ST_UCHAR only_loc_psel [1+MAX_PSEL_LEN]; /* Local len & PSEL */ + +/************************************************************************/ +/* copp_bind */ +/************************************************************************/ +ST_RET copp_bind (ST_LONG user_bind_id, PRES_ADDR *pres_addr, + ST_INT sharable, ST_INT max_conns) + { +ST_INT ret = SD_SUCCESS; + + + + COPP_LOG_ENC1 ("P-BIND.req: copp_user_bind_id =0x%08X", user_bind_id); + + + + if (!copp_bind_called) + { + /* Make sure Local PSEL len is legal before copying. */ + if (pres_addr->psel_len <= sizeof (only_loc_psel)-1) + { + /* Save Local PSEL (only do memcpy if len != 0). */ + if ((only_loc_psel [0] = (ST_UCHAR) pres_addr->psel_len) != 0) + memcpy (&only_loc_psel [1], pres_addr->psel, pres_addr->psel_len); + } + else + { + COPP_LOG_ERR1 ("COPP-ERROR: P-BIND.req: Invalid length=%d of PSEL.", + pres_addr->psel_len); + ret = COPP_ERR_INV_PSEL; /* invalid local PSEL */ + } + } + else + { /* Second Bind. Only allow it if the PSEL is the same. */ + if (only_loc_psel [0] != (ST_UCHAR) pres_addr->psel_len || + (pres_addr->psel_len != 0 && + memcmp (&only_loc_psel [1], pres_addr->psel, pres_addr->psel_len))) + { + COPP_LOG_ERR0 ("COPP-ERROR: Cannot BIND to different PSEL"); + ret = COPP_ERR_INV_PSEL; /* invalid local PSEL */ + } + } + + /* Call cosp_bind. */ + + + + if (ret == SD_SUCCESS) + ret = cosp_bind (user_bind_id, pres_addr, sharable, max_conns); + + + + + /* If successful, set called flag. Otherwise, treat next bind like first.*/ + if (ret == SD_SUCCESS) + copp_bind_called = SD_TRUE; + + return (ret); + } + +/************************************************************************/ +/* copp_unbind */ +/************************************************************************/ +ST_RET copp_unbind (ST_LONG copp_bind_id) + { + COPP_LOG_ENC1 ("P-UNBIND.req: copp_bind_id =%9ld", copp_bind_id); + return (cosp_unbind (copp_bind_id)); + } + +/************************************************************************/ +/* copp_con_req */ +/************************************************************************/ +ST_RET copp_con_req (ST_LONG copp_bind_id, ACSE_CONN *acse_conn, PRES_ADDR *rem_addr) + { + /* WARNING: this hardcoding assumes that ACSE pci always equals 1 */ + /* and MMS pci always equals 3 when we send P-CONNECT.req. */ + /* These must be set in a_associate_req before any encoding. */ +static ST_UCHAR hc_definition_list [] = + { + 0x30, 0x0f, 0x02, 0x01, 0x01, 0x06, 0x04, 0x52, 0x01, 0x00, 0x01, + 0x30, 0x04, 0x06, 0x02, 0x51, 0x01, + 0x30, 0x10, 0x02, 0x01, 0x03, 0x06, 0x05, 0x28, 0xca, 0x22, 0x02, 0x01, + 0x30, 0x04, 0x06, 0x02, 0x51, 0x01 + }; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + /* DEBUG: should we check the copp_bind_id????? */ + + COPP_LOG_ENC2 ("P-CONNECT.req: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + COPP_LOG_ENCC1 ("User data length: %d", acse_conn->apdu_len); + COPP_LOG_ENCH (acse_conn->apdu_len, acse_conn->apdu_ptr); + + if (acse_conn->copp_state != COPP_STATE_IDLE) + { + COPP_LOG_ERR1 ("COPP-ERROR: Cannot send P-CONNECT.req (Illegal state=%d)", + acse_conn->copp_state); + return (COPP_ERR_INV_STATE); + } + acse_conn->cr = SD_FALSE; + acse_conn->rl = SD_FALSE; + + /* Begin encoding request. */ + asn1r_strt_asn1_bld (aCtx, cosp_buf, cosp_msgsize); + + asn1r_strt_constr (aCtx); /* start CP SET */ + asn1r_strt_constr (aCtx); /* start enclosed SEQUENCE */ + asn1r_strt_constr (aCtx); /* start P-User-data (fully-encoded) */ + asn1r_strt_constr (aCtx); /* start SEQUENCE */ + asn1r_strt_constr (aCtx); /* start single-ASN1-type */ + + /* Fake out ACSE encoding. Already encoded into cosp_buf. */ + aCtx->asn1r_field_ptr -= acse_conn->apdu_len; + + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish single-ASN1-type */ + asn1r_wr_i8 (aCtx, acse_conn->pciacse); /* PCI for ACSE */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + /* Do not encode Transfer syntax name. We know it is ASN1. */ + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish SEQUENCE */ + asn1r_fin_constr (aCtx, 1,APP,DEF); /* finish P-User-data (fully-encoded) */ + + /* Hardcode Presentation-requirements (kernel only). */ + *aCtx->asn1r_field_ptr-- = 0x00; + *aCtx->asn1r_field_ptr-- = 0x06; + *aCtx->asn1r_field_ptr-- = 0x02; + *aCtx->asn1r_field_ptr-- = 0x88; + + /* 2 P-contexts: ACSE and MMS, and they both have a TSN of ASN1, */ + /* so we can hardcode this. */ + /* WARNING: this hardcoding assumes that ACSE pci always equals 1 */ + /* and MMS pci always equals 3 when we send P-CONNECT.req. */ + /* These must be set in a_associate_req before any encoding. */ + asn1r_strt_constr (aCtx); /* start P-context-def-list. */ + aCtx->asn1r_field_ptr -= sizeof (hc_definition_list); + memcpy (aCtx->asn1r_field_ptr + 1, hc_definition_list, sizeof (hc_definition_list)); + asn1r_fin_constr (aCtx, 4,CTX,DEF); /* finish P-context-def-list. */ + + /* Encode Called-p-selector. */ + aCtx->asn1r_field_ptr -= rem_addr->psel_len; + memcpy (aCtx->asn1r_field_ptr + 1, rem_addr->psel, rem_addr->psel_len); + *aCtx->asn1r_field_ptr-- = rem_addr->psel_len; + *aCtx->asn1r_field_ptr-- = 0x82; /* Tag for Called-p-selector */ + + /* Encode Calling-p-selector. */ + aCtx->asn1r_field_ptr -= (only_loc_psel[0]+1); + memcpy (aCtx->asn1r_field_ptr + 1, only_loc_psel, only_loc_psel[0]+1); + *aCtx->asn1r_field_ptr-- = 0x81; /* Tag for Calling-p-selector */ + + /* Protocol-version defaults to version-1, so don't encode. */ + + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* finish enclosed SEQUENCE */ + /* Hard-code Mode. Always "normal-mode". */ + *aCtx->asn1r_field_ptr-- = 0x01; + *aCtx->asn1r_field_ptr-- = 0x01; + *aCtx->asn1r_field_ptr-- = 0x80; + *aCtx->asn1r_field_ptr-- = 0x03; + *aCtx->asn1r_field_ptr-- = 0xA0; + asn1r_fin_constr (aCtx, SET_CODE,UNI,DEF); /* finish CPA SET */ + acse_conn->ppdu_ptr = aCtx->asn1r_field_ptr + 1; + acse_conn->ppdu_len = cosp_buf + cosp_msgsize - acse_conn->ppdu_ptr; + /* Pointing to beginning of Session User Information Field now. */ + + acse_conn->copp_state = COPP_STATE_AWAIT_CPA; + /* Pass to COSP. */ + return (cosp_con_req (copp_bind_id, rem_addr, acse_conn)); + } +/************************************************************************/ +/* copp_rel_req */ +/************************************************************************/ +ST_RET copp_rel_req (ACSE_CONN *acse_conn) + { +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + COPP_LOG_ENC2 ("P-RELEASE.req: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + COPP_LOG_ENCC1 ("User data length: %d", acse_conn->apdu_len); + COPP_LOG_ENCH (acse_conn->apdu_len, acse_conn->apdu_ptr); + + if (acse_conn->copp_state != COPP_STATE_CONNECTED) + { + COPP_LOG_ERR1 ("COPP-ERROR: Cannot send P-RELEASE.req (Illegal state=%d)", + acse_conn->copp_state); + return (COPP_ERR_INV_STATE); + } + /* Set release collision flags. */ + if (acse_conn->rl) + acse_conn->cr = SD_TRUE; + acse_conn->rl = SD_TRUE; + + /* Begin encoding request. */ + asn1r_strt_asn1_bld (aCtx, cosp_buf, cosp_msgsize); + + asn1r_strt_constr (aCtx); /* start P-User-data (fully-encoded) */ + asn1r_strt_constr (aCtx); /* start SEQUENCE */ + asn1r_strt_constr (aCtx); /* start single-ASN1-type */ + + /* Fake out ACSE encoding. Already encoded into cosp_buf. */ + aCtx->asn1r_field_ptr -= acse_conn->apdu_len; + + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish single-ASN1-type */ + asn1r_wr_i8 (aCtx, acse_conn->pciacse); /* PCI for ACSE */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + /* Do not encode Transfer syntax name. We know it is ASN1. */ + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish SEQUENCE */ + asn1r_fin_constr (aCtx, 1,APP,DEF); /* finish P-User-data (fully-encoded) */ + + acse_conn->ppdu_ptr = aCtx->asn1r_field_ptr + 1; + acse_conn->ppdu_len = cosp_buf + cosp_msgsize - acse_conn->ppdu_ptr; + /* Pointing to beginning of Session User Information Field now. */ + + return (cosp_rel_req (acse_conn)); + } + +/************************************************************************/ +/* copp_con_rsp_pos */ +/* Encode and send CPA PPDU. */ +/************************************************************************/ +ST_RET copp_con_rsp_pos (ACSE_CONN *acse_conn) + { +static ST_UCHAR hc_result_list [] = +{ +0x30, 0x07, 0x80, 0x01, 0x00, 0x81, 0x02, 0x51, 0x01, +0x30, 0x07, 0x80, 0x01, 0x00, 0x81, 0x02, 0x51, 0x01 +}; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + COPP_LOG_ENC2 ("P-CONNECT.rsp+: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + COPP_LOG_ENCC1 ("User data length: %d", acse_conn->apdu_len); + COPP_LOG_ENCH (acse_conn->apdu_len, acse_conn->apdu_ptr); + + if (acse_conn->copp_state != COPP_STATE_AWAIT_CON_RSP) + { + COPP_LOG_ERR1 ("COPP-ERROR: Cannot send P-CONNECT.rsp+ (Illegal state=%d)", + acse_conn->copp_state); + return (COPP_ERR_INV_STATE); + } + + /* Begin encoding request. */ + asn1r_strt_asn1_bld (aCtx, cosp_buf, cosp_msgsize); + + asn1r_strt_constr (aCtx); /* start CPA SET */ + asn1r_strt_constr (aCtx); /* start enclosed SEQUENCE */ + asn1r_strt_constr (aCtx); /* start P-User-data (fully-encoded) */ + asn1r_strt_constr (aCtx); /* start SEQUENCE */ + asn1r_strt_constr (aCtx); /* start single-ASN1-type */ + + /* Fake out ACSE encoding. Already encoded into cosp_buf. */ + aCtx->asn1r_field_ptr -= acse_conn->apdu_len; + + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish single-ASN1-type */ + asn1r_wr_i8 (aCtx, acse_conn->pciacse); /* PCI for ACSE */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + /* Do not encode Transfer syntax name. We know it is ASN1. */ + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish SEQUENCE */ + asn1r_fin_constr (aCtx, 1,APP,DEF); /* finish P-User-data (fully-encoded) */ + + /* Hardcode Presentation-requirements (kernel only). */ + *aCtx->asn1r_field_ptr-- = 0x00; + *aCtx->asn1r_field_ptr-- = 0x06; + *aCtx->asn1r_field_ptr-- = 0x02; + *aCtx->asn1r_field_ptr-- = 0x88; + + /* Hey, I like this. We only accept connections if there are */ + /* 2 P-contexts: ACSE and MMS, and they both have a TSN of ASN1, */ + /* so we can hardcode this. */ + asn1r_strt_constr (aCtx); /* start P-context-def-result-list. */ + aCtx->asn1r_field_ptr -= sizeof (hc_result_list); + memcpy (aCtx->asn1r_field_ptr + 1, hc_result_list, sizeof (hc_result_list)); + asn1r_fin_constr (aCtx, 5,CTX,DEF); /* finish P-context-def-result-list. */ + + /* Encode Responding-p-selector. */ + aCtx->asn1r_field_ptr -= (only_loc_psel[0]+1); + memcpy (aCtx->asn1r_field_ptr + 1, only_loc_psel, only_loc_psel[0]+1); + *aCtx->asn1r_field_ptr-- = 0x83; /* Tag for Responding-p-selector */ + + /* Protocol-version defaults to version-1, so don't encode. */ + + asn1r_fin_constr (aCtx, 2,CTX,DEF); /* finish enclosed SEQUENCE */ + /* Hard-code Mode. Always "normal-mode". */ + *aCtx->asn1r_field_ptr-- = 0x01; + *aCtx->asn1r_field_ptr-- = 0x01; + *aCtx->asn1r_field_ptr-- = 0x80; + *aCtx->asn1r_field_ptr-- = 0x03; + *aCtx->asn1r_field_ptr-- = 0xA0; + asn1r_fin_constr (aCtx, SET_CODE,UNI,DEF); /* finish CPA SET */ + acse_conn->ppdu_ptr = aCtx->asn1r_field_ptr + 1; + acse_conn->ppdu_len = cosp_buf + cosp_msgsize - acse_conn->ppdu_ptr; + /* Pointing to beginning of Session User Information Field now. */ + + acse_conn->copp_state = COPP_STATE_CONNECTED; + /* Pass to COSP. */ + return (cosp_con_rsp_pos (acse_conn)); + } + +/************************************************************************/ +/* copp_con_rsp_neg */ +/* Encode and send CPR PPDU. */ +/* If "provider_reason" < 0, this is "user-reject", else this is */ +/* "provider-reject" and the value of "provider_reason" will be */ +/* encoded in the "Provider-reason" parameter of the PPDU. */ +/************************************************************************/ +ST_RET copp_con_rsp_neg (ACSE_CONN *acse_conn, ST_INT provider_reason) + { +ST_INT j; +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + COPP_LOG_ENC3 ("P-CONNECT.rsp-: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d", + acse_conn, acse_conn->user_conn_id, provider_reason); + if (provider_reason < 0) + { /* user-reject: must have User-data */ + COPP_LOG_ENCC1 ("User data length: %d", acse_conn->apdu_len); + COPP_LOG_ENCH (acse_conn->apdu_len, acse_conn->apdu_ptr); + } + + if (provider_reason < 0 && acse_conn->copp_state != COPP_STATE_AWAIT_CON_RSP) + { /* If from user, must be in "await P-CONrsp" state. */ + COPP_LOG_ERR1 ("COPP-ERROR: Cannot send P-CONNECT.rsp- (Illegal state=%d)", + acse_conn->copp_state); + return (COPP_ERR_INV_STATE); + } + + /* Begin encoding request. */ + asn1r_strt_asn1_bld (aCtx, cosp_buf, cosp_msgsize); + + asn1r_strt_constr (aCtx); /* start CPR SEQUENCE */ + if (provider_reason < 0) + { /* user-reject: encode P-User-data */ + asn1r_strt_constr (aCtx); /* start P-User-data (fully-encoded) */ + asn1r_strt_constr (aCtx); /* start SEQUENCE */ + asn1r_strt_constr (aCtx); /* start single-ASN1-type */ + + /* Fake out ACSE encoding. Already encoded into cosp_buf. */ + aCtx->asn1r_field_ptr -= acse_conn->apdu_len; + + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish single-ASN1-type */ + asn1r_wr_i8 (aCtx, acse_conn->pciacse); /* PCI for ACSE */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + /* Do not encode Transfer syntax name. We know it is ASN1. */ + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish SEQUENCE */ + asn1r_fin_constr (aCtx, 1,APP,DEF); /* finish P-User-data (fully-encoded) */ + } /* end "if (provider_reason < 0)" */ + + if (provider_reason >= 0) + { /* provider-reject: encode Provider-reason */ + asn1r_wr_i8 (aCtx, (ST_INT8) provider_reason); /* Provider-reason */ + asn1r_fin_prim (aCtx, 10,CTX); + } + + if (provider_reason == PROV_REASON_DEFAULT_CONTEXT) + { /* Hardcode "Default-context-result = 2" (provider rejection) */ + *aCtx->asn1r_field_ptr-- = 0x02; + *aCtx->asn1r_field_ptr-- = 0x01; + *aCtx->asn1r_field_ptr-- = 0x87; + } + + /* If P-contexts proposed, just accept all of them. */ + /* We're rejecting the connect anyway, so it doesn't matter. */ + if (acse_conn->num_ctxt) + { + asn1r_strt_constr (aCtx); /* start P-context-def-result-list. */ + for (j = 0; j < acse_conn->num_ctxt; j++) + { + asn1r_strt_constr (aCtx); /* start SEQUENCE */ + /* DEBUG: would be better to encode same TSN they sent. */ + *aCtx->asn1r_field_ptr-- = 0x01; /* Hardcode Transfer-syntax-name = ASN.1*/ + *aCtx->asn1r_field_ptr-- = 0x51; + *aCtx->asn1r_field_ptr-- = 0x02; + *aCtx->asn1r_field_ptr-- = 0x81; + *aCtx->asn1r_field_ptr-- = 0x00; /* Hardcode "Result=0" (acceptance) */ + *aCtx->asn1r_field_ptr-- = 0x01; + *aCtx->asn1r_field_ptr-- = 0x80; + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish SEQUENCE */ + } + asn1r_fin_constr (aCtx, 5,CTX,DEF); /* finish P-context-def-result-list. */ + } + + /* Encode Responding-p-selector. */ + aCtx->asn1r_field_ptr -= (only_loc_psel[0]+1); + memcpy (aCtx->asn1r_field_ptr + 1, only_loc_psel, only_loc_psel[0]+1); + *aCtx->asn1r_field_ptr-- = 0x83; /* Tag for Responding-p-selector */ + + /* Protocol-version defaults to version-1, so don't encode. */ + + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish CPR SEQUENCE */ + acse_conn->ppdu_ptr = aCtx->asn1r_field_ptr + 1; + acse_conn->ppdu_len = cosp_buf + cosp_msgsize - acse_conn->ppdu_ptr; + /* Pointing to beginning of Session User Information Field now. */ + + acse_conn->copp_state = COPP_STATE_IDLE; + /* Pass to COSP. */ + return (cosp_con_rsp_neg (acse_conn, COSP_CON_RSP_U_IN_UDATA)); + } + +/************************************************************************/ +/* copp_rel_rsp_pos */ +/************************************************************************/ +ST_RET copp_rel_rsp_pos (ACSE_CONN *acse_conn) + { +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + COPP_LOG_ENC2 ("P-RELEASE.rsp+: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + COPP_LOG_ENCC1 ("User data length: %d", acse_conn->apdu_len); + COPP_LOG_ENCH (acse_conn->apdu_len, acse_conn->apdu_ptr); + + if (acse_conn->copp_state != COPP_STATE_CONNECTED) + { + COPP_LOG_ERR1 ("COPP-ERROR: Cannot send P-RELEASE.rsp+ (Illegal state=%d)", + acse_conn->copp_state); + return (COPP_ERR_INV_STATE); + } + + /* Begin encoding request. */ + asn1r_strt_asn1_bld (aCtx, cosp_buf, cosp_msgsize); + + asn1r_strt_constr (aCtx); /* start P-User-data (fully-encoded) */ + asn1r_strt_constr (aCtx); /* start SEQUENCE */ + asn1r_strt_constr (aCtx); /* start single-ASN1-type */ + + /* Fake out ACSE encoding. Already encoded into cosp_buf. */ + aCtx->asn1r_field_ptr -= acse_conn->apdu_len; + + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish single-ASN1-type */ + asn1r_wr_i8 (aCtx, acse_conn->pciacse); /* PCI for ACSE */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + /* Do not encode Transfer syntax name. We know it is ASN1. */ + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish SEQUENCE */ + asn1r_fin_constr (aCtx, 1,APP,DEF); /* finish P-User-data (fully-encoded) */ + + acse_conn->ppdu_ptr = aCtx->asn1r_field_ptr + 1; + acse_conn->ppdu_len = cosp_buf + cosp_msgsize - acse_conn->ppdu_ptr; + /* Pointing to beginning of Session User Information Field now. */ + + if (acse_conn->cr) + { + acse_conn->cr = SD_FALSE; + acse_conn->rl = SD_FALSE; /* and stay in COPP_STATE_CONNECTED */ + } + else + acse_conn->copp_state = COPP_STATE_IDLE; + + return (cosp_rel_rsp_pos (acse_conn)); + } + +/************************************************************************/ +/* copp_u_abort_req */ +/************************************************************************/ +ST_RET copp_u_abort_req (ACSE_CONN *acse_conn) + { +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + COPP_LOG_ENC2 ("P-U-ABORT.req: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + COPP_LOG_ENCC1 ("User data length: %d", acse_conn->apdu_len); + COPP_LOG_ENCH (acse_conn->apdu_len, acse_conn->apdu_ptr); + + if (acse_conn->copp_state == COPP_STATE_IDLE) + { + COPP_LOG_ERR1 ("COPP-ERROR: Cannot send P-U-ABORT.req (Illegal state=%d)", + acse_conn->copp_state); + return (COPP_ERR_INV_STATE); + } + + /* Begin encoding request. */ + asn1r_strt_asn1_bld (aCtx, cosp_buf, cosp_msgsize); + + asn1r_strt_constr (aCtx); /* start ARU */ + asn1r_strt_constr (aCtx); /* start P-User-data (fully-encoded) */ + asn1r_strt_constr (aCtx); /* start SEQUENCE */ + asn1r_strt_constr (aCtx); /* start single-ASN1-type */ + + /* Fake out ACSE encoding. Already encoded into cosp_buf. */ + aCtx->asn1r_field_ptr -= acse_conn->apdu_len; + + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish single-ASN1-type */ + asn1r_wr_i8 (aCtx, acse_conn->pciacse); /* PCI for ACSE */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + /* Do not encode Transfer syntax name. We know it is ASN1. */ + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish SEQUENCE */ + asn1r_fin_constr (aCtx, 1,APP,DEF); /* finish P-User-data (fully-encoded) */ + + asn1r_strt_constr (aCtx); /* start P-context-identifier-list */ + asn1r_strt_constr (aCtx); /* start SEQUENCE */ + asn1r_wr_objid (aCtx, asn1_obj_id.comps, + asn1_obj_id.num_comps); /* Transfer syntax name (i.e. ASN1)*/ + asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI); + asn1r_wr_i8 (aCtx, acse_conn->pciacse); /* PCI for ACSE */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish SEQUENCE */ + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish P-context-identifier-list */ + + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish ARU */ + + acse_conn->ppdu_ptr = aCtx->asn1r_field_ptr + 1; + acse_conn->ppdu_len = cosp_buf + cosp_msgsize - acse_conn->ppdu_ptr; + /* Pointing to beginning of Session User Information Field now. */ + + acse_conn->copp_state = COPP_STATE_IDLE; + return (cosp_u_abort_req (acse_conn)); + } + +/************************************************************************/ +/* copp_data_req */ +/************************************************************************/ +ST_RET copp_data_req (ACSE_CONN *acse_conn) + { +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + COPP_LOG_ENC2 ("P-DATA.req: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + COPP_LOG_ENCC1 ("User data length: %d", acse_conn->apdu_len); + COPP_LOG_ENCH (acse_conn->apdu_len, acse_conn->apdu_ptr); + + if (acse_conn->copp_state != COPP_STATE_CONNECTED) + { + COPP_LOG_ERR1 ("COPP-ERROR: Cannot send P-DATA.req (Illegal state=%d)", + acse_conn->copp_state); + return (COPP_ERR_INV_STATE); + } + + /* Begin encoding request. */ + asn1r_strt_asn1_bld (aCtx, cosp_buf, cosp_msgsize); + + asn1r_strt_constr (aCtx); /* start P-User-data (fully-encoded) */ + asn1r_strt_constr (aCtx); /* start SEQUENCE */ + asn1r_strt_constr (aCtx); /* start single-ASN1-type */ + + /* Fake out ACSE encoding. Already encoded into cosp_buf. */ + aCtx->asn1r_field_ptr -= acse_conn->apdu_len; + + asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish single-ASN1-type */ + asn1r_wr_i8 (aCtx, acse_conn->pcimms); /* PCI for MMS */ + asn1r_fin_prim (aCtx, INT_CODE,UNI); + /* Do not encode Transfer syntax name. We know it is ASN1. */ + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish SEQUENCE */ + asn1r_fin_constr (aCtx, 1,APP,DEF); /* finish P-User-data (fully-encoded) */ + + acse_conn->ppdu_ptr = aCtx->asn1r_field_ptr + 1; + acse_conn->ppdu_len = cosp_buf + cosp_msgsize - acse_conn->ppdu_ptr; + /* Pointing to beginning of Session User Information Field now. */ + + return (cosp_data_req (acse_conn)); + } + +/************************************************************************/ +/* copp_p_abort_req */ +/* Encode and send ARP PPDU (i.e. P-P-Abort.req). */ +/* This function only called by the COPP-provider (not by COPP-user). */ +/* Parameters: */ +/* ACSE_CONN *acse_conn Pointer to connection info */ +/* ST_INT8 abort_reason Abort-reason to send in ARP */ +/* ST_INT8 event_id Event-identifier to send in ARP */ +/* If -1, don't send it. */ +/************************************************************************/ +ST_VOID copp_p_abort_req (ACSE_CONN *acse_conn, ST_INT8 abort_reason, ST_INT8 event_id) + { +ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_ENC_CTXT *aCtx = &localEncCtx; + + COPP_LOG_ENC4 ("P-P-ABORT.req: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d event_id =%d", + acse_conn, acse_conn->user_conn_id, (ST_INT) abort_reason, (ST_INT) event_id); + + /* Begin encoding request. */ + asn1r_strt_asn1_bld (aCtx, cosp_buf, cosp_msgsize); + + asn1r_strt_constr (aCtx); /* start ARP SEQUENCE */ + + if (event_id != -1) + { + asn1r_wr_i8 (aCtx, event_id); /* Event-identifier */ + asn1r_fin_prim (aCtx, 1,CTX); + } + + asn1r_wr_i8 (aCtx, abort_reason); /* Abort-reason */ + asn1r_fin_prim (aCtx, 0,CTX); + + asn1r_fin_constr (aCtx, SEQ_CODE,UNI,DEF); /* finish ARP SEQUENCE */ + acse_conn->ppdu_ptr = aCtx->asn1r_field_ptr + 1; + acse_conn->ppdu_len = cosp_buf + cosp_msgsize - acse_conn->ppdu_ptr; + /* Pointing to beginning of Session User Information Field now. */ + + /* Pass ARP to COSP. */ + cosp_u_abort_req (acse_conn); + } diff --git a/mmslib/ositcps/coppdaru.c b/mmslib/ositcps/coppdaru.c new file mode 100644 index 0000000..5be833a --- /dev/null +++ b/mmslib/ositcps/coppdaru.c @@ -0,0 +1,280 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2002, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : coppdaru.c */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file implements decoding of U-ABORT indication. */ +/* */ +/* For information see the: */ +/* ISO 8822 "Information processing systems - Open Systems */ +/* Interconnection - Connection oriented presentation service */ +/* definition. */ +/* ISO 8823 "Information processing systems - Open Systems */ +/* Interconnection - Connection oriented presentation protocol */ +/* specification. */ +/* */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* u_cosp_u_abort_ind */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/26/09 JRB 07 Fix to handle PDV len=0 or User-data len=0. */ +/* 01/30/06 GLB 06 Integrated porting changes for VMS */ +/* 01/02/02 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ +/* 03/18/98 JRB 04 Use defines (not variables) for ASN1 errors. */ +/* 12/22/97 JRB 03 Use ST_INT8. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/19/97 JRB 02 General cleanup. */ +/* 02/27/97 JRB 01 Created */ +/************************************************************************/ +#ifdef DEBUG_SISCO +static char *thisFileName = __FILE__; +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "asn1defs.h" +#include "acse2.h" + +#include "copp.h" +#include "cosp_usr.h" + +/************************************************************************/ +/* Global Variables */ +/************************************************************************/ +/* Structure for tracking ARP/ARU decode. */ +typedef struct + { +#define COPP_U_ABORT 0 /* Use to set "abort_type" */ +#define COPP_P_ABORT 1 /* Use to set "abort_type" */ + ST_INT8 abort_type; + ST_INT8 abort_reason; + ST_INT8 event_id; + } DECODE_ARX; +static DECODE_ARX decode_arx; + +static ST_VOID START_aru (ASN1_DEC_CTXT *aCtx); +static ST_VOID START_pc_identifier_list (ASN1_DEC_CTXT *aCtx); +static ST_VOID START_sequence (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_pci (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_tsn (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_sequence (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_pc_identifier_list (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_aru (ASN1_DEC_CTXT *aCtx); + +static ST_VOID START_arp (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_abort_reason (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_event_id (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_arp (ASN1_DEC_CTXT *aCtx); + +/************************************************************************/ +/* u_cosp_u_abort_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* connection has been aborted by remote SS-user. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *acse_conn Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_u_abort_ind (ACSE_CONN *acse_conn) + { +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean */ + + if (acse_conn->copp_state == COPP_STATE_IDLE) + { + COPP_LOG_ERR1 ("COPP-ERROR: Cannot process S-U-ABORT.ind (Illegal state=%d)", + acse_conn->copp_state); + return; + } + + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + + decode_acse_conn = acse_conn; /* Save in global so asn1r_decode_asn1 (aCtx, */ + /* can fill it in. */ + + /* Set the PCI to be used during P-User-Data decode. */ + expected_pdv_pci = decode_acse_conn->pciacse; + + p_user_data_is_outer = SD_FALSE; /* P-User-data IS NOT outermost constr. */ + + /* CRITICAL: Init APDU ptr & len. Changed only if APDU found in msg. */ + acse_conn->apdu_ptr = NULL; + acse_conn->apdu_len = 0; + /* CRITICAL: Init global PDV ptr & len. Changed only if PDV found in msg.*/ + pdv_data_ptr = NULL; + pdv_data_len = 0; + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,START_aru); + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,START_arp); + asn1r_decode_asn1 (aCtx, acse_conn->ppdu_ptr,acse_conn->ppdu_len); + if (aCtx->asn1r_pdu_dec_err != NO_DECODE_ERR) + { /* DECODE FAILED */ + /* Couldn't decode ARP or ARU, so pass up as P-P-Abort.ind with */ + /* reason = unrecognized-ppdu */ + decode_arx.abort_reason = 1; /* unrecognized-ppdu. */ + COPP_LOG_ERR1 ("COPP-ERROR: ASN.1 decode of S-U-Abort.ind failed, err=%d", aCtx->asn1r_pdu_dec_err); + COPP_LOG_DEC3 ("P-P-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d", + acse_conn, acse_conn->user_conn_id, decode_arx.abort_reason); + u_copp_p_abort_ind (acse_conn, decode_arx.abort_reason); + } + else + { /* DECODE SUCCESSFUL */ + if (decode_arx.abort_type == COPP_U_ABORT) + { /* This is P-U-Abort */ + COPP_LOG_DEC2 ("P-U-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + COPP_LOG_DECC1 ("User data length: %d", acse_conn->apdu_len); + COPP_LOG_DECH (acse_conn->apdu_len, acse_conn->apdu_ptr); + u_copp_u_abort_ind (acse_conn); + } + else + { /* This is P-P-Abort */ + COPP_LOG_DEC4 ("P-P-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d, event_id =%d", + acse_conn, acse_conn->user_conn_id, decode_arx.abort_reason, decode_arx.event_id); + u_copp_p_abort_ind (acse_conn, decode_arx.abort_reason); + } + } + acse_conn->copp_state = COPP_STATE_IDLE; /* No matter what. */ + } + +/************************************************************************/ +/* START_aru */ +/************************************************************************/ +static ST_VOID START_aru (ASN1_DEC_CTXT *aCtx) + { + decode_arx.abort_type = COPP_U_ABORT; /* Set type to U-Abort */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,START_pc_identifier_list); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_aru; + } +/************************************************************************/ +/* START_pc_identifier_list */ +/************************************************************************/ +static ST_VOID START_pc_identifier_list (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,START_sequence); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_pc_identifier_list; + } +/************************************************************************/ +/* START_sequence */ +/************************************************************************/ +static ST_VOID START_sequence (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_pci); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_sequence; + } +/************************************************************************/ +/* decode_pci */ +/************************************************************************/ +static ST_VOID decode_pci (ASN1_DEC_CTXT *aCtx) + { +ST_INT8 pci; + if (asn1r_get_i8 (aCtx, &pci)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + ASN1R_TAG_ADD (aCtx, UNI,OBJ_ID_CODE,decode_tsn); + } +/************************************************************************/ +/* decode_tsn */ +/************************************************************************/ +static ST_VOID decode_tsn (ASN1_DEC_CTXT *aCtx) + { +MMS_OBJ_ID tsn; + + if (asn1r_get_objid (aCtx, tsn.comps,&tsn.num_comps)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + if (asn1_objidcmp (&tsn, (MMS_OBJ_ID *) &asn1_obj_id) != 0) + { /* TSN better be ASN1 */ + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BITSTR); + return; + } + } +/************************************************************************/ +/* END_sequence */ +/************************************************************************/ +static ST_VOID END_sequence (ASN1_DEC_CTXT *aCtx) + { + /* May be another context. */ + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,START_sequence); + } +/************************************************************************/ +/* END_pc_identifier_list */ +/************************************************************************/ +static ST_VOID END_pc_identifier_list (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + } +/************************************************************************/ +/* END_aru */ +/************************************************************************/ +static ST_VOID END_aru (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_done_fun = NULL; /* done decoding */ + } + + +/************************************************************************/ +/* START_arp */ +/************************************************************************/ +static ST_VOID START_arp (ASN1_DEC_CTXT *aCtx) + { + decode_arx.abort_type = COPP_P_ABORT; /* Set type to P-Abort */ + ASN1R_TAG_ADD (aCtx, CTX,0,decode_abort_reason); + ASN1R_TAG_ADD (aCtx, CTX,1,decode_event_id); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_arp; + } +/************************************************************************/ +/* decode_abort_reason */ +/************************************************************************/ +static ST_VOID decode_abort_reason (ASN1_DEC_CTXT *aCtx) + { + if (asn1r_get_i8 (aCtx, &decode_arx.abort_reason)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + ASN1R_TAG_ADD (aCtx, CTX,1,decode_event_id); + } +/************************************************************************/ +/* decode_event_id */ +/************************************************************************/ +static ST_VOID decode_event_id (ASN1_DEC_CTXT *aCtx) + { + if (asn1r_get_i8 (aCtx, &decode_arx.event_id)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + } +/************************************************************************/ +/* END_arp */ +/************************************************************************/ +static ST_VOID END_arp (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_done_fun = NULL; /* done decoding */ + } diff --git a/mmslib/ositcps/coppdcp.c b/mmslib/ositcps/coppdcp.c new file mode 100644 index 0000000..324ad44 --- /dev/null +++ b/mmslib/ositcps/coppdcp.c @@ -0,0 +1,767 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2002, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : coppdcp.c */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file implements decoding of CP and CPA PPDUs. */ +/* */ +/* For information see the: */ +/* ISO 8822 "Information processing systems - Open Systems */ +/* Interconnection - Connection oriented presentation service */ +/* definition. */ +/* ISO 8823 "Information processing systems - Open Systems */ +/* Interconnection - Connection oriented presentation protocol */ +/* specification. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* u_cosp_con_ind */ +/* u_cosp_con_cnf_pos */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/26/09 JRB 17 Fix to handle PDV len=0 or User-data len=0. */ +/* 10/23/08 JRB 16 Del unused variable. */ +/* 10/08/08 JRB 15 Fix PSEL decode (didn't work if len > 127). */ +/* 04/28/08 GLB 14 Removed CALLED_ONLY and CALLING_ONLY */ +/* 01/30/06 GLB 13 Integrated porting changes for VMS */ +/* 08/01/03 JRB 12 Elim compiler warning. */ +/* 06/24/03 JRB 11 Init psels before decode to avoid crash */ +/* when sender does not send psels. */ +/* 03/31/03 JRB 10 asn1r_get_bitstr: add max_bits arg. */ +/* 01/02/02 JRB 09 Converted to use ASN1R (re-entrant ASN1) */ +/* 10/10/01 JRB 08 asn1_skip_elmnt doesn't work for indef len */ +/* encoding. Use "parse_next" instead. */ +/* 05/09/01 JRB 07 On P-CONNECT.ind, save PSELs in ACSE_CONN. */ +/* 02/02/99 JRB 06 BUG FIX: Decode "prov_reas" in "Result-list" */ +/* even if no TSN (see decode_result). */ +/* 03/18/98 JRB 05 Use defines (not variables) for ASN1 errors. */ +/* 02/20/98 JRB 04 Chg abort_reason & event_id to ST_INT8. */ +/* 12/22/97 JRB 03 Use ST_INT8. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/19/97 JRB 02 Add "CALLING" support. General cleanup. */ +/* 02/27/97 JRB 01 Created */ +/************************************************************************/ +#ifdef DEBUG_SISCO +static char *thisFileName = __FILE__; +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "asn1defs.h" +#include "acse2.h" + +#include "copp.h" +#include "cosp_usr.h" + +/************************************************************************/ +/* Global Variables */ +/************************************************************************/ +/* Structure for tracking this decode. */ +typedef struct + { +#define PPDU_TYPE_CP 0 /* This is a CP PPDU. */ +#define PPDU_TYPE_CPA 1 /* This is a CPA PPDU. */ + ST_INT ppdu_type; /* PPDU_TYPE_CP or PPDU_TYPE_CPA */ + ST_UCHAR version_bit_str; + ST_UCHAR calling_psel [MAX_PSEL_LEN+1]; + ST_UCHAR called_psel [MAX_PSEL_LEN+1]; + ST_UCHAR responding_psel[MAX_PSEL_LEN+1]; + ST_INT num_ctxt; + ST_BOOLEAN bad_pc_deflist; /* SD_TRUE if anything we don't like in pc_deflist*/ + ST_BOOLEAN def_ctxt_proposed; + ST_INT8 mode; + ST_BOOLEAN pres_req_present; + ST_UCHAR pres_req [1]; + ST_BOOLEAN user_ses_req_present; + ST_UCHAR user_sess_req [2]; + ST_BOOLEAN send_negative_resp; /* if set, send negative response */ + ST_INT negative_resp_reason; /* reason to send in negative response */ + } DECODE_CP; +static DECODE_CP decode_cp; +static ST_INT8 pci; /* PCI rcvd in P-context-def-list */ + +static ST_VOID START_p_cp (ASN1_DEC_CTXT *aCtx); +static ST_VOID START_mode (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_mode2 (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_mode (ASN1_DEC_CTXT *aCtx); +static ST_VOID START_p_cp_sequence (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_version (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_calling_psel (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_called_psel (ASN1_DEC_CTXT *aCtx); +static ST_VOID START_pc_deflist (ASN1_DEC_CTXT *aCtx); +static ST_VOID START_context (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_pci (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_asn (ASN1_DEC_CTXT *aCtx); +static ST_VOID START_tsn_list (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_tsn (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_tsn_list (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_context (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_pc_deflist (ASN1_DEC_CTXT *aCtx); +static ST_VOID START_def_ctxt_name (ASN1_DEC_CTXT *aCtx); +static ST_VOID parse_next_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_def_ctxt_name (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_pres_req (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_user_sess_req (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_p_cp_sequence (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_p_cp (ASN1_DEC_CTXT *aCtx); + +/* Functions used only for CPA decode */ +static ST_VOID decode_responding_psel (ASN1_DEC_CTXT *aCtx); +static ST_VOID START_pc_def_result_list (ASN1_DEC_CTXT *aCtx); +static ST_VOID START_result_seq (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_result (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_tsn2 (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_result_list_prov_reas (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_result_seq (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_pc_def_result_list (ASN1_DEC_CTXT *aCtx); + +/* All code dealing with "*_psel" (here and in other modules) assumes */ +/* length fits in first byte of PSEL. */ +/* NOTE: Longer PSELs should never be needed, and if another app sends */ +/* one, this code gracefully refuses the connection. */ +#if MAX_PSEL_LEN > 127 +#error This code will not work because (MAX_PSEL_LEN > 127). Length must fit in first byte of psel. +#endif +/************************************************************************/ +/* u_cosp_con_ind */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that a */ +/* remote node wishes to establish a connection. */ +/* */ +/* Parameters: */ +/* ST_LONG user_bind_id SS-User's id for this binding. */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_con_ind (ST_LONG user_bind_id, ACSE_CONN *acse_conn) + { +ST_INT8 abort_reason; +ST_INT8 event_id; +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean */ + + if (acse_conn->copp_state != COPP_STATE_IDLE) + { + COPP_LOG_ERR1 ("COPP-ERROR: Cannot process S-CONNECT.ind (Illegal state=%d)", + acse_conn->copp_state); + return; + } + + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + + /* Clean out old stuff from structure. */ + memset (&decode_cp, 0, sizeof (decode_cp)); + decode_cp.ppdu_type = PPDU_TYPE_CP; + decode_cp.version_bit_str = 0x80; /* Default to "version1". */ + + /* CRITICAL: memset above initializes "decode_cp.*_psel[0]=0" */ + /* (i.e. length=0) in case they are NOT received in CP. */ + + decode_acse_conn = acse_conn; /* Save in global so asn1r_decode_asn1 (aCtx, */ + /* can fill it in. */ + + /* WARNING: expected_pdv_pci MUST BE SET before START_p_user_data */ + /* is called (by asn1r_decode_asn1 (aCtx,). Don't know it yet, so don't set here. */ + + p_user_data_is_outer = SD_FALSE; /* P-User-data IS NOT outermost constr. */ + + /* CRITICAL: Init APDU ptr & len. Changed only if APDU found in msg. */ + acse_conn->apdu_ptr = NULL; + acse_conn->apdu_len = 0; + /* CRITICAL: Init global PDV ptr & len. Changed only if PDV found in msg.*/ + pdv_data_ptr = NULL; + pdv_data_len = 0; + +/* Call 'asn1r_decode_asn1 (aCtx,' to parse the message. */ + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SET_CODE,START_p_cp); + asn1r_decode_asn1 (aCtx, acse_conn->ppdu_ptr,acse_conn->ppdu_len); + if (aCtx->asn1r_pdu_dec_err != NO_DECODE_ERR) + { + COPP_LOG_ERR1 ("COPP-ERROR: ASN.1 decode of S-Connect.ind failed, err=%d", aCtx->asn1r_pdu_dec_err); + abort_reason = 1; /* unrecognized-ppdu */ + event_id = -1; /* Unlisted */ + /* Encode and send ARP PPDU. */ + copp_p_abort_req (acse_conn, abort_reason, event_id); + /* DON'T pass P-P-Abort.ind to COPP-user. User doesn't know about conn.*/ + } + else if (decode_cp.send_negative_resp) + { + /* Flag was set during decode to trigger negative response, so send it.*/ + copp_con_rsp_neg (acse_conn, decode_cp.negative_resp_reason); + } + else if (decode_cp.version_bit_str != 0x80) + { /* Must be version1: Bit 0 of bitstr (high bit) set */ + COPP_LOG_ERR0 ("COPP-ERROR: P-CONNECT.ind contains illegal P-version."); + copp_con_rsp_neg (acse_conn, PROV_REASON_VERSION); + } + else if (decode_cp.def_ctxt_proposed) + { + COPP_LOG_ERR0 ("COPP-ERROR: P-CONNECT.ind contains unsupported P-default-context."); + copp_con_rsp_neg (acse_conn, PROV_REASON_DEFAULT_CONTEXT); + } + else if (memcmp (decode_cp.called_psel, only_loc_psel, only_loc_psel [0]+1)) + { /* Called PSEL must be one that is bound. */ + COPP_LOG_ERR0 ("COPP-ERROR: P-CONNECT.ind contains invalid Called-P-address."); + copp_con_rsp_neg (acse_conn, PROV_REASON_CALLED_PRES_ADDR); + } + else if (decode_cp.bad_pc_deflist) + { /* Something we can't handle in pc_deflist. */ + COPP_LOG_ERR0 ("COPP-ERROR: P-CONNECT.ind contains illegal PC-deflist."); + copp_con_rsp_neg (acse_conn, PROV_REASON_LOCAL_LIMIT); + } + else + { + COPP_LOG_DEC1 ("P-CONNECT.ind: acse_conn_id =0x%08X", acse_conn); + COPP_LOG_DECC1 ("User data length: %d", acse_conn->apdu_len); + COPP_LOG_DECH (acse_conn->apdu_len, acse_conn->apdu_ptr); + + acse_conn->copp_state = COPP_STATE_AWAIT_CON_RSP; + + /* Save called_psel, calling_psel in acse_conn. */ + /* Will NEVER be too long, because len checked above. */ + memcpy (acse_conn->loc_psel, decode_cp.called_psel, decode_cp.called_psel [0]+1); + memcpy (acse_conn->rem_psel, decode_cp.calling_psel, decode_cp.calling_psel [0]+1); + + u_copp_con_ind (user_bind_id, acse_conn); + } + } + +/************************************************************************/ +/* u_cosp_con_cnf_pos */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate that */ +/* the connection has been established. */ +/* */ +/* Parameters: */ +/* acse_conn Pointer to connection info */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_con_cnf_pos (ACSE_CONN *acse_conn) + { +ST_INT8 abort_reason; +ST_INT8 event_id; +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean */ + + if (acse_conn->copp_state != COPP_STATE_AWAIT_CPA) + { + COPP_LOG_ERR1 ("COPP-ERROR: Cannot process S-CONNECT.cnf+ (Illegal state=%d)", + acse_conn->copp_state); + return; + } + + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + + /* Clean out old stuff from structure. */ + memset (&decode_cp, 0, sizeof (decode_cp)); + decode_cp.ppdu_type = PPDU_TYPE_CPA; + decode_cp.version_bit_str = 0x80; /* Default to "version1". */ + + /* CRITICAL: memset above initializes "decode_cp.*_psel[0]=0" */ + /* (i.e. length=0) in case they are NOT received in CPA. */ + + decode_acse_conn = acse_conn; /* Save in global so asn1r_decode_asn1 (aCtx, */ + /* can fill it in. */ + + /* WARNING: expected_pdv_pci MUST BE SET before START_p_user_data */ + /* is called (by asn1r_decode_asn1 (aCtx,). SET IT NOW. */ + expected_pdv_pci = acse_conn->pciacse; + + p_user_data_is_outer = SD_FALSE; /* P-User-data IS NOT outermost constr. */ + + /* CRITICAL: Init APDU ptr & len. Changed only if APDU found in msg. */ + acse_conn->apdu_ptr = NULL; + acse_conn->apdu_len = 0; + /* CRITICAL: Init global PDV ptr & len. Changed only if PDV found in msg.*/ + pdv_data_ptr = NULL; + pdv_data_len = 0; + +/* Call 'asn1r_decode_asn1 (aCtx,' to parse the message. */ + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SET_CODE,START_p_cp); + asn1r_decode_asn1 (aCtx, acse_conn->ppdu_ptr,acse_conn->ppdu_len); + if (aCtx->asn1r_pdu_dec_err != NO_DECODE_ERR) + { + COPP_LOG_ERR1 ("COPP-ERROR: ASN.1 decode of S-Connect.cnf+ failed, err=%d", aCtx->asn1r_pdu_dec_err); + acse_conn->copp_state = COPP_STATE_IDLE; + abort_reason = 1; /* unrecognized-ppdu */ + event_id = -1; /* Unlisted */ + /* Encode and send ARP PPDU. */ + copp_p_abort_req (acse_conn, abort_reason, event_id); + /* Pass P-P-Abort.ind to COPP-user. */ + u_copp_p_abort_ind (acse_conn, abort_reason); + } + else if (decode_cp.version_bit_str != 0x80 || decode_cp.bad_pc_deflist) + { /* Must be version1: Bit 0 of bitstr (high bit) set */ + COPP_LOG_ERR1 ("COPP-ERROR: Unsupported version in CPA received for conn %d", + acse_conn->user_conn_id); + acse_conn->copp_state = COPP_STATE_IDLE; + abort_reason = 6; /* invalid-ppdu-parameter-value */ + event_id = 1; /* cpa-PPDU */ + /* Encode and send ARP PPDU. */ + copp_p_abort_req (acse_conn, abort_reason, event_id); + /* Pass P-P-Abort.ind to COPP-user. */ + u_copp_p_abort_ind (acse_conn, abort_reason); + } + else + { + COPP_LOG_DEC2 ("P-CONNECT.cnf+: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + COPP_LOG_DECC1 ("User data length: %d", acse_conn->apdu_len); + COPP_LOG_DECH (acse_conn->apdu_len, acse_conn->apdu_ptr); + + acse_conn->copp_state = COPP_STATE_CONNECTED; + u_copp_con_cnf (acse_conn, P_CON_RESULT_ACCEPT, 0); + } + } + + /*======================================================*/ + /* FUNCTIONS BELOW USED FOR BOTH */ + /* "CP" AND "CPA" DECODE */ + /*======================================================*/ + +/************************************************************************/ +/* START_p_cp */ +/************************************************************************/ +static ST_VOID START_p_cp (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,START_mode); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,START_p_cp_sequence); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_p_cp; + } +/************************************************************************/ +/* START_mode */ +/************************************************************************/ +static ST_VOID START_mode (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX,0,decode_mode2); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_mode; + } +/************************************************************************/ +/* decode_mode2 */ +/************************************************************************/ +static ST_VOID decode_mode2 (ASN1_DEC_CTXT *aCtx) + { + if (asn1r_get_i8 (aCtx, &decode_cp.mode) || decode_cp.mode != 1) /* Not "normal" mode. Give up. */ + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + } +/************************************************************************/ +/* END_mode */ +/************************************************************************/ +static ST_VOID END_mode (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,START_p_cp_sequence); + } +/************************************************************************/ +/* START_p_cp_sequence */ +/************************************************************************/ +static ST_VOID START_p_cp_sequence (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX,0,decode_version); + if (decode_cp.ppdu_type == PPDU_TYPE_CP) + { /* This is CP PPDU */ + ASN1R_TAG_ADD (aCtx, CTX,1,decode_calling_psel); + ASN1R_TAG_ADD (aCtx, CTX,2,decode_called_psel); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,4,START_pc_deflist); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,6,START_def_ctxt_name); + } + else + { /* This is CPA PPDU */ + ASN1R_TAG_ADD (aCtx, CTX,3,decode_responding_psel); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,5,START_pc_def_result_list); + } + ASN1R_TAG_ADD (aCtx, CTX,8,decode_pres_req); + ASN1R_TAG_ADD (aCtx, CTX,9,decode_user_sess_req); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_p_cp_sequence; + } +/************************************************************************/ +/* decode_version */ +/************************************************************************/ +static ST_VOID decode_version (ASN1_DEC_CTXT *aCtx) + { + asn1r_get_bitstr (aCtx, &decode_cp.version_bit_str, 8); + if (decode_cp.ppdu_type == PPDU_TYPE_CP) + { /* This is CP PPDU */ + ASN1R_TAG_ADD (aCtx, CTX,1,decode_calling_psel); + ASN1R_TAG_ADD (aCtx, CTX,2,decode_called_psel); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,4,START_pc_deflist); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,6,START_def_ctxt_name); + } + else + { /* This is CPA PPDU */ + ASN1R_TAG_ADD (aCtx, CTX,3,decode_responding_psel); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,5,START_pc_def_result_list); + } + ASN1R_TAG_ADD (aCtx, CTX,8,decode_pres_req); + ASN1R_TAG_ADD (aCtx, CTX,9,decode_user_sess_req); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + } +/************************************************************************/ +/* decode_calling_psel */ +/************************************************************************/ +static ST_VOID decode_calling_psel (ASN1_DEC_CTXT *aCtx) + { + /* If len within limit, copy psel to decode structure. */ + /* If not, set flag to send negative response. */ + if (aCtx->asn1r_elmnt_len <= MAX_PSEL_LEN) + { + decode_cp.calling_psel [0] = aCtx->asn1r_elmnt_len; + memcpy (&decode_cp.calling_psel [1], aCtx->asn1r_field_ptr, aCtx->asn1r_elmnt_len); + } + else + { + COPP_LOG_ERR2 ("P-CONNECT.ind: Calling PSEL len=%d exceeds max=%d", + aCtx->asn1r_elmnt_len, MAX_PSEL_LEN); + decode_cp.send_negative_resp = SD_TRUE; /* send negative response*/ + decode_cp.negative_resp_reason = PROV_REASON_LOCAL_LIMIT; + } + + /* Primitive CAN'T be indef len, so asn1_skip_elmnt is safe here. */ + asn1_skip_elmnt (aCtx); /* Don't bother decoding it. */ + ASN1R_TAG_ADD (aCtx, CTX,2,decode_called_psel); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,4,START_pc_deflist); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,6,START_def_ctxt_name); + ASN1R_TAG_ADD (aCtx, CTX,8,decode_pres_req); + ASN1R_TAG_ADD (aCtx, CTX,9,decode_user_sess_req); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + } +/************************************************************************/ +/* decode_called_psel */ +/************************************************************************/ +static ST_VOID decode_called_psel (ASN1_DEC_CTXT *aCtx) + { + /* If len within limit, copy psel to decode structure. */ + /* If not, set flag to send negative response. */ + if (aCtx->asn1r_elmnt_len <= MAX_PSEL_LEN) + { + decode_cp.called_psel [0] = aCtx->asn1r_elmnt_len; /* first byte is len*/ + memcpy (&decode_cp.called_psel [1], aCtx->asn1r_field_ptr, aCtx->asn1r_elmnt_len); + } + else + { + COPP_LOG_ERR2 ("P-CONNECT.ind: Called PSEL len=%d exceeds max=%d", + aCtx->asn1r_elmnt_len, MAX_PSEL_LEN); + decode_cp.send_negative_resp = SD_TRUE; /* send negative response*/ + decode_cp.negative_resp_reason = PROV_REASON_LOCAL_LIMIT; + } + + /* Primitive CAN'T be indef len, so asn1_skip_elmnt is safe here. */ + asn1_skip_elmnt (aCtx); /* Don't bother decoding it. */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,4,START_pc_deflist); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,6,START_def_ctxt_name); + ASN1R_TAG_ADD (aCtx, CTX,8,decode_pres_req); + ASN1R_TAG_ADD (aCtx, CTX,9,decode_user_sess_req); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + } +/************************************************************************/ +/* START_pc_deflist */ +/************************************************************************/ +static ST_VOID START_pc_deflist (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,START_context); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_pc_deflist; + } +/************************************************************************/ +/* START_context */ +/************************************************************************/ +static ST_VOID START_context (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,decode_pci); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_context; + } +/************************************************************************/ +/* decode_pci */ +/************************************************************************/ +static ST_VOID decode_pci (ASN1_DEC_CTXT *aCtx) + { + if (asn1r_get_i8 (aCtx, &pci)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + ASN1R_TAG_ADD (aCtx, UNI,OBJ_ID_CODE,decode_asn); + } +/************************************************************************/ +/* decode_asn */ +/************************************************************************/ +static ST_VOID decode_asn (ASN1_DEC_CTXT *aCtx) + { +MMS_OBJ_ID asn; + if (asn1r_get_objid (aCtx, asn.comps,&asn.num_comps)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + if (asn1_objidcmp (&asn, (MMS_OBJ_ID *) &mms_obj_id) == 0) + decode_acse_conn->pcimms = pci; + else if (asn1_objidcmp (&asn, (MMS_OBJ_ID *) &acse_obj_id) == 0) + decode_acse_conn->pciacse = pci; + else + { /* Unrecognized Abstract Syntax. Must be "ACSE" or "ISO MMS". */ + decode_cp.bad_pc_deflist = SD_TRUE; + } + + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,START_tsn_list); + } +/************************************************************************/ +/* START_tsn_list */ +/************************************************************************/ +static ST_VOID START_tsn_list (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, UNI,OBJ_ID_CODE,decode_tsn); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_tsn_list; + } +/************************************************************************/ +/* decode_tsn */ +/************************************************************************/ +static ST_VOID decode_tsn (ASN1_DEC_CTXT *aCtx) + { +MMS_OBJ_ID tsn; + + if (asn1r_get_objid (aCtx, tsn.comps,&tsn.num_comps)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + if (asn1_objidcmp (&tsn, (MMS_OBJ_ID *) &asn1_obj_id) != 0) + { /* TSN better be ASN1 */ + decode_cp.bad_pc_deflist = SD_TRUE; + } + /* DEBUG: we don't support multiple TSN so no ASN1R_TAG_ADD (aCtx, here. */ + /* Should end up in END_tsn_list after this. */ + } +/************************************************************************/ +/* END_tsn_list */ +/************************************************************************/ +static ST_VOID END_tsn_list (ASN1_DEC_CTXT *aCtx) + { + return; + } +/************************************************************************/ +/* END_context */ +/************************************************************************/ +static ST_VOID END_context (ASN1_DEC_CTXT *aCtx) + { + decode_acse_conn->num_ctxt++; + /* May be another context. */ + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,START_context); + } +/************************************************************************/ +/* END_pc_deflist */ +/************************************************************************/ +static ST_VOID END_pc_deflist (ASN1_DEC_CTXT *aCtx) + { + /* Set the PCI to be used during P-User-Data decode. */ + /* WARNING: this must be done here because we don't know what it is */ + /* beforehand. */ + expected_pdv_pci = decode_acse_conn->pciacse; + + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,6,START_def_ctxt_name); + ASN1R_TAG_ADD (aCtx, CTX,8,decode_pres_req); + ASN1R_TAG_ADD (aCtx, CTX,9,decode_user_sess_req); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + } +/************************************************************************/ +/* START_def_ctxt_name */ +/* Default-context-name. If this is present, we will refuse this */ +/* connection so don't bother decoding it. */ +/************************************************************************/ +static ST_VOID START_def_ctxt_name (ASN1_DEC_CTXT *aCtx) + { + decode_cp.def_ctxt_proposed = SD_TRUE; + /* Don't bother decoding it. Use asn1r_parse_next (aCtx, to skip over it. */ + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_def_ctxt_name; + asn1r_parse_next (aCtx, parse_next_done); + } +/************************************************************************/ +/* parse_next_done */ +/************************************************************************/ +static ST_VOID parse_next_done (ASN1_DEC_CTXT *aCtx) + { /* called when "asn1r_parse_next (aCtx," is done */ + } +/************************************************************************/ +/* END_def_ctxt_name */ +/************************************************************************/ +static ST_VOID END_def_ctxt_name (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX,8,decode_pres_req); + ASN1R_TAG_ADD (aCtx, CTX,9,decode_user_sess_req); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + } +/************************************************************************/ +/* decode_pres_req */ +/************************************************************************/ +static ST_VOID decode_pres_req (ASN1_DEC_CTXT *aCtx) + { + decode_cp.pres_req_present = SD_TRUE; + asn1r_get_bitstr (aCtx, decode_cp.pres_req, 8); + ASN1R_TAG_ADD (aCtx, CTX,9,decode_user_sess_req); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + } +/************************************************************************/ +/* decode_user_sess_req */ +/************************************************************************/ +static ST_VOID decode_user_sess_req (ASN1_DEC_CTXT *aCtx) + { + decode_cp.user_ses_req_present = SD_TRUE; + asn1r_get_bitstr (aCtx, decode_cp.user_sess_req, 16); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + } +/************************************************************************/ +/* END_p_cp_sequence */ +/************************************************************************/ +static ST_VOID END_p_cp_sequence (ASN1_DEC_CTXT *aCtx) + { /* Somebody might encode "mode" after "p_cp_sequence". */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,START_mode); + } +/************************************************************************/ +/* END_p_cp */ +/************************************************************************/ +static ST_VOID END_p_cp (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_done_fun = NULL; /* done decoding */ + } + + /*======================================================*/ + /* FUNCTIONS BELOW USED ONLY FOR "CPA" DECODE */ + /* */ + /*======================================================*/ + +/************************************************************************/ +/* decode_responding_psel */ +/* NOTE: Responding PSEL not used, so if can't decode, just ignore it. */ +/************************************************************************/ +static ST_VOID decode_responding_psel (ASN1_DEC_CTXT *aCtx) + { + /* If len within limit, copy psel to decode structure. */ + /* If not, just log & ignore (responding PSEL not usually needed). */ + if (aCtx->asn1r_elmnt_len <= MAX_PSEL_LEN) + { + decode_cp.responding_psel [0] = aCtx->asn1r_elmnt_len; + memcpy (&decode_cp.responding_psel [1], aCtx->asn1r_field_ptr, aCtx->asn1r_elmnt_len); + } + else + COPP_LOG_DEC2 ("P-CONNECT.cnf+: Responding PSEL len=%d exceeds max=%d. Ignored.", + aCtx->asn1r_elmnt_len, MAX_PSEL_LEN); + + /* Primitive CAN'T be indef len, so asn1_skip_elmnt is safe here. */ + asn1_skip_elmnt (aCtx); /* Don't bother decoding it. */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,5,START_pc_def_result_list); + ASN1R_TAG_ADD (aCtx, CTX,8,decode_pres_req); + ASN1R_TAG_ADD (aCtx, CTX,9,decode_user_sess_req); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + } +/************************************************************************/ +/* START_pc_def_result_list */ +/************************************************************************/ +static ST_VOID START_pc_def_result_list (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,START_result_seq); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_pc_def_result_list; + } +/************************************************************************/ +/* START_result_seq */ +/************************************************************************/ +static ST_VOID START_result_seq (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX,0,decode_result); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_result_seq; + } +/************************************************************************/ +/* decode_result */ +/************************************************************************/ +static ST_VOID decode_result (ASN1_DEC_CTXT *aCtx) + { +ST_INT8 result; + if (asn1r_get_i8 (aCtx, &result)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + if (result != 0) + { /* P-Context rejected. We can't handle any rejection so set flag.*/ + decode_cp.bad_pc_deflist = SD_TRUE; + } + ASN1R_TAG_ADD (aCtx, CTX,1,decode_tsn2); + ASN1R_TAG_ADD (aCtx, CTX,2,decode_result_list_prov_reas); + } +/************************************************************************/ +/* decode_tsn2 */ +/* NOTE: This is essentially same as decode_tsn used in the CP decode */ +/* except for the different ASN1R_TAG_ADD (aCtx, at the end. In either case */ +/* if we receive any TSN that is not ASN.1 (this is the only */ +/* TSN we will ever accept or propose) we set the flag */ +/* decode_cp.bad_pc_deflist = SD_TRUE */ +/************************************************************************/ +static ST_VOID decode_tsn2 (ASN1_DEC_CTXT *aCtx) + { +MMS_OBJ_ID tsn; + + if (asn1r_get_objid (aCtx, tsn.comps,&tsn.num_comps)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + if (asn1_objidcmp (&tsn, (MMS_OBJ_ID *) &asn1_obj_id) != 0) + { /* TSN better be ASN1 */ + decode_cp.bad_pc_deflist = SD_TRUE; + } + ASN1R_TAG_ADD (aCtx, CTX,2,decode_result_list_prov_reas); + } +/************************************************************************/ +/* decode_result_list_prov_reas */ +/* NOTE: Decode but don't save value, because no real use for it. */ +/************************************************************************/ +static ST_VOID decode_result_list_prov_reas (ASN1_DEC_CTXT *aCtx) + { +ST_INT8 result_list_prov_reas; + if (asn1r_get_i8 (aCtx, &result_list_prov_reas)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + } +/************************************************************************/ +/* END_result_seq */ +/************************************************************************/ +static ST_VOID END_result_seq (ASN1_DEC_CTXT *aCtx) + { + decode_acse_conn->num_ctxt++; + /* May be another "result sequence". */ + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,START_result_seq); + } +/************************************************************************/ +/* END_pc_def_result_list */ +/************************************************************************/ +static ST_VOID END_pc_def_result_list (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX,8,decode_pres_req); + ASN1R_TAG_ADD (aCtx, CTX,9,decode_user_sess_req); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + } + diff --git a/mmslib/ositcps/coppdcpr.c b/mmslib/ositcps/coppdcpr.c new file mode 100644 index 0000000..1e1ddbd --- /dev/null +++ b/mmslib/ositcps/coppdcpr.c @@ -0,0 +1,401 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2002, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : coppdcpr.c */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file implements decoding of CPR PPDU. */ +/* */ +/* For information see the: */ +/* ISO 8822 "Information processing systems - Open Systems */ +/* Interconnection - Connection oriented presentation service */ +/* definition. */ +/* ISO 8823 "Information processing systems - Open Systems */ +/* Interconnection - Connection oriented presentation protocol */ +/* specification. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* u_cosp_con_cnf_neg */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/26/09 JRB 11 Fix to handle PDV len=0 or User-data len=0. */ +/* 10/08/08 JRB 10 Fix PSEL decode (didn't work if len > 127). */ +/* 04/28/08 GLB 09 Removed CALLED_ONLY. */ +/* 03/31/03 JRB 08 asn1r_get_bitstr: add max_bits arg. */ +/* 01/02/02 JRB 07 Converted to use ASN1R (re-entrant ASN1) */ +/* 10/09/01 JRB 06 asn1_skip_elmnt doesn't work for indef len */ +/* encoding. Use "parse_next" instead. */ +/* 02/02/99 JRB 05 BUG FIX: Decode "prov_reas" in "Result-list" */ +/* even if no TSN (see decode_result). */ +/* 02/02/99 JRB 04 Allow User-data with Prov-reason but ignore. */ +/* 03/18/98 JRB 03 Use defines (not variables) for ASN1 errors. */ +/* 12/22/97 JRB 02 Use ST_INT8. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/19/97 JRB 01 Created */ +/************************************************************************/ +#ifdef DEBUG_SISCO +static char *thisFileName = __FILE__; +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "asn1defs.h" +#include "acse2.h" + +#include "copp.h" +#include "cosp_usr.h" + +/* Define illegal value for "provider_reason". Init to this before */ +/* decode. If still equals this after decode, it was not encoded in PDU.*/ +#define CPR_PROVIDER_REASON_NOT_ENCODED -1 + +/************************************************************************/ +/* Global Variables */ +/************************************************************************/ +/* Structure for tracking this decode. */ +typedef struct + { + ST_UCHAR version_bit_str; + ST_UCHAR responding_psel [MAX_PSEL_LEN+1]; + ST_INT num_ctxt; + ST_BOOLEAN bad_pc_deflist; /* SD_TRUE if anything we don't like in pc_deflist*/ + ST_INT8 default_context_result; + ST_INT8 provider_reason; + } CPR_INFO; +static CPR_INFO cpr_info; + +static ST_VOID START_p_cpr (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_version (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_responding_psel (ASN1_DEC_CTXT *aCtx); +static ST_VOID START_pc_def_result_list (ASN1_DEC_CTXT *aCtx); +static ST_VOID START_result_seq (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_result (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_tsn2 (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_result_list_prov_reas (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_result_seq (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_pc_def_result_list (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_default_context_result (ASN1_DEC_CTXT *aCtx); +static ST_VOID decode_provider_reason (ASN1_DEC_CTXT *aCtx); +static ST_VOID SKIP_p_user_data (ASN1_DEC_CTXT *aCtx); +static ST_VOID parse_next_done (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_skip_p_user_data (ASN1_DEC_CTXT *aCtx); +static ST_VOID END_p_cpr (ASN1_DEC_CTXT *aCtx); + + +/************************************************************************/ +/* u_cosp_con_cnf_neg */ +/*----------------------------------------------------------------------*/ +/* This USER function is called by the SS-Provider to indicate the */ +/* connection has been rejected by remote. */ +/* */ +/* Parameters: */ +/* acse_conn Pointer to connection info */ +/* result see def results COSP_CON_CNF_... above */ +/* reason see def reasons COSP_CON_CNF_... above */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID u_cosp_con_cnf_neg (ACSE_CONN *acse_conn, ST_INT result, ST_INT reason) + { +ST_INT8 abort_reason; +ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/ +ASN1_DEC_CTXT *aCtx = &localDecCtx; + + memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean */ + + if (acse_conn->copp_state != COPP_STATE_AWAIT_CPA) + { + COPP_LOG_ERR1 ("COPP-ERROR: Cannot process S-CONNECT.cnf- (Illegal state=%d)", + acse_conn->copp_state); + return; + } + + aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* Use asn1_tag method for decoding. */ + aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */ + aCtx->asn1r_err_fun = NULL; /* set up error detected fun */ + + /* Clean out old stuff from structure. */ + memset (&cpr_info, 0, sizeof (cpr_info)); + cpr_info.version_bit_str = 0x80; /* Default to "version1". */ + cpr_info.provider_reason = CPR_PROVIDER_REASON_NOT_ENCODED; + + /* CRITICAL: memset above initializes "cpr_info.responding_psel[0]=0" */ + /* (i.e. length=0) in case it is NOT received in CPR. */ + + decode_acse_conn = acse_conn; /* Save in global so asn1r_decode_asn1 (aCtx, */ + /* can fill it in. */ + + /* WARNING: expected_pdv_pci MUST BE SET before START_p_user_data */ + /* is called (by asn1r_decode_asn1 (aCtx,). SET IT NOW. */ + expected_pdv_pci = acse_conn->pciacse; + + p_user_data_is_outer = SD_FALSE; /* P-User-data IS NOT outermost constr. */ + + /* CRITICAL: Init APDU ptr & len. Changed only if APDU found in msg. */ + acse_conn->apdu_ptr = NULL; + acse_conn->apdu_len = 0; + /* CRITICAL: Init global PDV ptr & len. Changed only if PDV found in msg.*/ + pdv_data_ptr = NULL; + pdv_data_len = 0; + +/* Call 'asn1r_decode_asn1 (aCtx,' to parse the message. */ + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,START_p_cpr); + asn1r_decode_asn1 (aCtx, acse_conn->ppdu_ptr,acse_conn->ppdu_len); + if (aCtx->asn1r_pdu_dec_err != NO_DECODE_ERR) + { + COPP_LOG_ERR1 ("COPP-ERROR: ASN.1 decode of S-Connect.cnf- failed, err=%d", aCtx->asn1r_pdu_dec_err); + abort_reason = 1; /* unrecognized-ppdu */ + /* Don't send ARP PPDU. Remote node is already rejecting connect. */ + /* Pass P-P-Abort.ind to COPP-user. */ + u_copp_p_abort_ind (acse_conn, abort_reason); + } + else if (cpr_info.version_bit_str != 0x80) + { /* Must be version1: Bit 0 of bitstr (high bit) set */ + COPP_LOG_ERR1 ("COPP-ERROR: Unsupported version in CPR received for conn %d", + acse_conn->user_conn_id); + abort_reason = 6; /* invalid-ppdu-parameter-value */ + /* Don't send ARP PPDU. Remote node is already rejecting connect. */ + /* Pass P-P-Abort.ind to COPP-user. */ + u_copp_p_abort_ind (acse_conn, abort_reason); + } + else if (cpr_info.provider_reason != CPR_PROVIDER_REASON_NOT_ENCODED) + { /* Provider reject */ + COPP_LOG_DEC2 ("P-CONNECT.cnf-: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + COPP_LOG_DECC1 ("Provider-reason = %d. No P-user-data.", + cpr_info.provider_reason); + /* NOTE: there is no User-data with this one. */ + u_copp_con_cnf (acse_conn, P_CON_RESULT_PROVIDER_REJ, + cpr_info.provider_reason); + } + else if (cpr_info.bad_pc_deflist) + { + COPP_LOG_ERR1 ("COPP-ERROR: Unsupported P-context in CPR received for conn %d", + acse_conn->user_conn_id); + abort_reason = 6; /* invalid-ppdu-parameter-value */ + /* Don't send ARP PPDU. Remote node is already rejecting connect. */ + /* Pass P-P-Abort.ind to COPP-user. */ + u_copp_p_abort_ind (acse_conn, abort_reason); + } + else + { /* User reject */ + COPP_LOG_DEC2 ("P-CONNECT.cnf-: acse_conn_id =0x%08X user_conn_id =%4ld", + acse_conn, acse_conn->user_conn_id); + COPP_LOG_DECC1 ("User data length: %d", acse_conn->apdu_len); + COPP_LOG_DECH (acse_conn->apdu_len, acse_conn->apdu_ptr); + + u_copp_con_cnf (acse_conn, P_CON_RESULT_USER_REJ, 0); + } + acse_conn->copp_state = COPP_STATE_IDLE; /* No matter what */ + } + + /*======================================================*/ + /* FUNCTIONS BELOW USED FOR "CPR" DECODE */ + /* */ + /*======================================================*/ + +/************************************************************************/ +/* START_p_cpr */ +/************************************************************************/ +static ST_VOID START_p_cpr (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX,0,decode_version); + ASN1R_TAG_ADD (aCtx, CTX,3,decode_responding_psel); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,5,START_pc_def_result_list); + ASN1R_TAG_ADD (aCtx, CTX,7,decode_default_context_result); + ASN1R_TAG_ADD (aCtx, CTX,10,decode_provider_reason); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_p_cpr; + } +/************************************************************************/ +/* decode_version */ +/************************************************************************/ +static ST_VOID decode_version (ASN1_DEC_CTXT *aCtx) + { + asn1r_get_bitstr (aCtx, &cpr_info.version_bit_str, 8); + ASN1R_TAG_ADD (aCtx, CTX,3,decode_responding_psel); + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,5,START_pc_def_result_list); + ASN1R_TAG_ADD (aCtx, CTX,7,decode_default_context_result); + ASN1R_TAG_ADD (aCtx, CTX,10,decode_provider_reason); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + } +/************************************************************************/ +/* decode_responding_psel */ +/* NOTE: Responding PSEL not used, so if can't decode, just ignore it. */ +/************************************************************************/ +static ST_VOID decode_responding_psel (ASN1_DEC_CTXT *aCtx) + { + /* If len within limit, copy psel to decode structure. */ + /* If not, just log & ignore (responding PSEL not usually needed). */ + if (aCtx->asn1r_elmnt_len <= MAX_PSEL_LEN) + { + cpr_info.responding_psel [0] = aCtx->asn1r_elmnt_len; /* first byte is len*/ + memcpy (&cpr_info.responding_psel [1], aCtx->asn1r_field_ptr, aCtx->asn1r_elmnt_len); + } + else + COPP_LOG_DEC2 ("P-CONNECT.cnf-: Responding PSEL len=%d exceeds max=%d. Ignored.", + aCtx->asn1r_elmnt_len, MAX_PSEL_LEN); + + /* Primitive CAN'T be indef len, so asn1_skip_elmnt is safe here. */ + asn1_skip_elmnt (aCtx); /* Don't bother decoding it. */ + ASN1R_TAG_ADD (aCtx, CTX|CONSTR,5,START_pc_def_result_list); + ASN1R_TAG_ADD (aCtx, CTX,7,decode_default_context_result); + ASN1R_TAG_ADD (aCtx, CTX,10,decode_provider_reason); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + } +/************************************************************************/ +/* START_pc_def_result_list */ +/************************************************************************/ +static ST_VOID START_pc_def_result_list (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,START_result_seq); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_pc_def_result_list; + } +/************************************************************************/ +/* START_result_seq */ +/************************************************************************/ +static ST_VOID START_result_seq (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX,0,decode_result); + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_result_seq; + } +/************************************************************************/ +/* decode_result */ +/************************************************************************/ +static ST_VOID decode_result (ASN1_DEC_CTXT *aCtx) + { +ST_INT8 result; + if (asn1r_get_i8 (aCtx, &result)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + if (result != 0) + { /* P-Context rejected. We can't handle any rejection so set flag.*/ + cpr_info.bad_pc_deflist = SD_TRUE; + } + ASN1R_TAG_ADD (aCtx, CTX,1,decode_tsn2); + ASN1R_TAG_ADD (aCtx, CTX,2,decode_result_list_prov_reas); + } +/************************************************************************/ +/* decode_tsn2 */ +/* NOTE: This is essentially same as decode_tsn used in the CP decode */ +/* except for the different ASN1R_TAG_ADD (aCtx, at the end. In either case */ +/* if we receive any TSN that is not ASN.1 (this is the only */ +/* TSN we will ever accept or propose) we set the flag */ +/* cpr_info.bad_pc_deflist = SD_TRUE */ +/************************************************************************/ +static ST_VOID decode_tsn2 (ASN1_DEC_CTXT *aCtx) + { +MMS_OBJ_ID tsn; + + if (asn1r_get_objid (aCtx, tsn.comps,&tsn.num_comps)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + if (asn1_objidcmp (&tsn, &asn1_obj_id) != 0) + { /* TSN better be ASN1 */ + cpr_info.bad_pc_deflist = SD_TRUE; + } + ASN1R_TAG_ADD (aCtx, CTX,2,decode_result_list_prov_reas); + } +/************************************************************************/ +/* decode_result_list_prov_reas */ +/* NOTE: Decode but don't save value, because no real use for it. */ +/************************************************************************/ +static ST_VOID decode_result_list_prov_reas (ASN1_DEC_CTXT *aCtx) + { +ST_INT8 result_list_prov_reas; + if (asn1r_get_i8 (aCtx, &result_list_prov_reas)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + } +/************************************************************************/ +/* END_result_seq */ +/************************************************************************/ +static ST_VOID END_result_seq (ASN1_DEC_CTXT *aCtx) + { + decode_acse_conn->num_ctxt++; + /* May be another "result sequence". */ + ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,START_result_seq); + } +/************************************************************************/ +/* END_pc_def_result_list */ +/************************************************************************/ +static ST_VOID END_pc_def_result_list (ASN1_DEC_CTXT *aCtx) + { + ASN1R_TAG_ADD (aCtx, CTX,7,decode_default_context_result); + ASN1R_TAG_ADD (aCtx, CTX,10,decode_provider_reason); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + } +/************************************************************************/ +/* decode_default_context_result */ +/************************************************************************/ +static ST_VOID decode_default_context_result (ASN1_DEC_CTXT *aCtx) + { /* Ignore value, because we never proposed Default-context-name.*/ + if (asn1r_get_i8 (aCtx, &cpr_info.default_context_result)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + ASN1R_TAG_ADD (aCtx, CTX,10,decode_provider_reason); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,START_p_user_data); + } +/************************************************************************/ +/* decode_provider_reason */ +/************************************************************************/ +static ST_VOID decode_provider_reason (ASN1_DEC_CTXT *aCtx) + { + if (asn1r_get_i8 (aCtx, &cpr_info.provider_reason)) + { + asn1r_set_dec_err (aCtx, ASN1E_INVALID_BOOLEAN); + return; + } + /* Marben sends bad p_user_data in this case. Skip over it. */ + COPP_LOG_DEC0 ("WARNING: Ignoring P-user-data received on CPR."); + ASN1R_TAG_ADD (aCtx, APP|CONSTR,1,SKIP_p_user_data); + } + +/************************************************************************/ +/* SKIP_p_user_data */ +/************************************************************************/ +ST_VOID SKIP_p_user_data (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = END_skip_p_user_data; + asn1r_parse_next (aCtx, parse_next_done); + } +/************************************************************************/ +/* parse_next_done */ +/************************************************************************/ +static ST_VOID parse_next_done (ASN1_DEC_CTXT *aCtx) + { /* called when "asn1r_parse_next (aCtx," is done */ + } +/************************************************************************/ +/* END_skip_p_user_data */ +/************************************************************************/ +static ST_VOID END_skip_p_user_data (ASN1_DEC_CTXT *aCtx) + { + } +/************************************************************************/ +/* END_p_cpr */ +/************************************************************************/ +static ST_VOID END_p_cpr (ASN1_DEC_CTXT *aCtx) + { + aCtx->asn1r_decode_done_fun = NULL; /* done decoding */ + } + + diff --git a/mmslib/ositcps/cosp_dec.c b/mmslib/ositcps/cosp_dec.c new file mode 100644 index 0000000..f279270 --- /dev/null +++ b/mmslib/ositcps/cosp_dec.c @@ -0,0 +1,1090 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997 - 2003, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : cosp_dec.c */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file implements the decoding of COSP SPDUs. */ +/* */ +/* For information see the: */ +/* ISO 8326 "Information processing systems - Open Systems */ +/* Interconnection - Basic connection oriented session service */ +/* definition. */ +/* ISO 8327 "Information processing systems - Open Systems */ +/* Interconnection - Basic connection oriented session protocol */ +/* specification. */ +/* ISO 8327/ADD.2 (Draft for Version2). */ +/* */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* cosp_dec_cn_ac */ +/* cosp_dec_rf */ +/* cosp_dec_fn_dn */ +/* cosp_dec_ab */ +/* cosp_dec_dt */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/19/03 EJV 08 Allow for ACCEPT User Data <= COSP_MAX_UDATA*/ +/* 06/05/02 JRB 07 Allow Called SSEL=NULL on connect if */ +/* configured SSEL=NULL. */ +/* 04/26/01 EJV 06 Correction to version check in CN/AC. */ +/* Corrected spelling. */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 01/08/99 EJV 04 Added decoding of param 17 in FINISH SPDU. */ +/* Make sure param 17 is extracted properly. */ +/* 08/13/98 JRB 03 Lint cleanup. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/20/97 EJV 02 Enhanced logging. */ +/* 01/17/97 EJV 01 Created */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; /* Define for SLOG mechanism */ +#endif + +#include "acse2.h" + +#include "cosp_log.h" +#include "cosp.h" +#include "cosp_usr.h" + + + /*--------------------------------------*/ + /* Local function prototypes */ + /*--------------------------------------*/ + +static ST_UINT16 cosp_dec_len (ST_UCHAR *buf, ST_UINT *bytes); +static ST_RET cosp_validate_cn_ac (COSP_CN_AC *dec_par, ST_UCHAR spdu_type); + + +/************************************************************************/ +/* cosp_dec_cn_ac */ +/*----------------------------------------------------------------------*/ +/* Function to decode a CONNECT or ACCEPT SPDU. */ +/* Note if User Data are present in received SPDU then the length in the*/ +/* dec_par->udata_len will be > 0. The dec_par->udata_ptr points into */ +/* the spdu_buf (it is not an allocated pointer). */ +/* */ +/* Parameters: */ +/* COSP_CN_AC *dec_par ptr to decoded parameters struct*/ +/* char *spdu_buf Pointer to received SPDU buf */ +/* ST_UINT spdu_len Length of received SPDU */ +/* ST_UCHAR spdu_type SPDU type to decode (CN, AC) */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_dec_cn_ac (COSP_CN_AC *dec_par, char *spdu_buf, ST_UINT spdu_len, + ST_UCHAR spdu_type) +{ +ST_RET ret; +ST_UCHAR *dec_buf; +ST_UINT dec_len; +ST_UCHAR param_code; +ST_UINT param_len; +ST_UINT group_len; +ST_UINT len_bytes; /* number of bytes for encoded len (1 or 3) */ +ST_UINT idx; + + ret = SD_SUCCESS; + + dec_buf = (ST_UCHAR *) spdu_buf; + dec_len = 0; + idx = 0; + + /*-----------------------------------------------------*/ + /* set defaults in case params are not present in SPDU */ + /*-----------------------------------------------------*/ + + memset (dec_par, 0, sizeof (COSP_CN_AC)); + dec_par->ver_num = COSP_VER1; /*!default ver is Version1 */ + dec_par->ses_urequir [0]= 0x03; /* bits 9-16: 9 and 10 set */ + dec_par->ses_urequir [1]= 0x49; /* bits 1-8: 1,4 and 7 set */ + + /* in addition memset is equivalent to following con params settings */ + /* dec_par->prot_option = 0; rcv extended concatination not supported */ + /* dec_par->initiator_tsdu_size = 0; SSDU segmenting from initiator not supported */ + /* dec_par->responder_tsdu_size = 0; SSDU segmenting from responder not supported */ + /* dec_par->loc_ssel [0] = 0; called SSEL is NULL */ + /* dec_par->rem_ssel [0] = 0; calling SSEL is NULL */ + /* dec_par->udata_len = 0; User Data length */ + /* dec_par->udata_ptr = 0; User Data pointer (points into spdu_buf!) */ + + /* we will use the first while loop to avoid excesive nesting of if...else... */ + + while (SD_TRUE) + { + /* NOTE: we should never return back from bottom of the loop here!!! */ + + /* the decoded len should be comparable with spdu_len passed to this func */ + dec_len = (ST_UINT) cosp_dec_len (&dec_buf [idx+1], &len_bytes); + if (dec_len + 1+len_bytes != spdu_len) + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR2 ("COSP-ERROR: Decoding CN/AC: invalid SPDU len=%u or decoded len=%u.", + spdu_len, dec_len + 1+len_bytes); + break; + } + idx += 1+len_bytes; /* 1 for SPDU code */ + + /* decode all connect parameters */ + while (dec_len > 0) + { + param_code = dec_buf [idx]; + param_len = (ST_UINT) cosp_dec_len (&dec_buf [idx+1], &len_bytes); + + /* signal error if param_len is greater then decoding length left */ + if (param_len + 1+len_bytes > dec_len) + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR2 ("COSP-ERROR: Decoding CN/AC: invalid parameter len=%u (length left to decode len=%u).", + param_len + 1+len_bytes, dec_len); + break; + } + dec_len -= 1+len_bytes; + idx += 1+len_bytes; + + /* do not try to decode if param_len is 0 (param is empty) */ + if (param_len == 0) + continue; + + switch (param_code) + { + case 1: /* PGI - Connection Identifier group */ + /* we will ignore this group (skip all decoding) */ + break; + + case 5: /* PGI - Connect/Accept Item group */ + group_len = param_len; + while (group_len > 0) + { + param_code = dec_buf [idx]; + param_len = (ST_UINT) cosp_dec_len (&dec_buf [idx+1], &len_bytes); + + /* signal error if param_len is greater then decoding length left */ + if (param_len + 1+len_bytes > group_len) + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR2 ("COSP-ERROR: Decoding CN/AC: invalid parameter len=%u (PGI-5 group length left to decode len=%u).", + param_len + 1+len_bytes, group_len); + break; + } + dec_len -= 1+len_bytes; + group_len -= 1+len_bytes; + idx += 1+len_bytes; + + /* do not try to decode if param_len is 0 (param is empty) */ + if (param_len == 0) + continue; + + switch (param_code) + { + case 19: /* PI - Protocol Options */ + if (param_len == 1) + dec_par->prot_option = dec_buf [idx]; + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding CN/AC: invalid PI-19 parameter len=%u (should be len=1).", + param_len); + } + break; + + case 21: /* PI - TSDU Max Size */ + if (param_len == 4) + { + dec_par->initiator_tsdu_size = + ((ST_UINT16) dec_buf [idx] << 8) | (ST_UINT16) dec_buf [idx+1]; + dec_par->responder_tsdu_size = + ((ST_UINT16) dec_buf [idx+2] << 8) | (ST_UINT16) dec_buf [idx+3]; + } + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding CN/AC: invalid PI-21 parameter len=%u (should be len=4).", + param_len); + } + break; + + case 22: /* PI - Version Number */ + if (param_len == 1) + dec_par->ver_num = dec_buf [idx]; + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding CN/AC: invalid PI-22 parameter len=%u (should be len=1)", + param_len); + } + break; + + case 23: /* PI - Initial Serial Number */ + /* we will ignore this param (skip all decoding) */ + break; + + case 26: /* PI - Token Setting Item */ + /* we will ignore this param (skip all decoding) */ + break; + + default: + ret = COSP_ERR_DEC_INV_PI_CODE; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding CN/AC: invalid PI code=%d in PGI-5", + param_code); + } /* end of switch */ + + if (ret == SD_SUCCESS) + { + /* adjust processing vars by the length of param processed */ + dec_len -= param_len; + group_len -= param_len; + idx += param_len; + } + else + break; /* error, exit this loop */ + } /* end of while (group_len > 0) */ + + param_len = 0; /* dec_len & idx already adjusted */ + break; + + case 16: /* PI - Token Item */ + if (spdu_type == COSP_SI_ACCEPT) + /* we will ignore this param (skip all decoding) */ + ; + else + { + ret = COSP_ERR_DEC_INV_PI_CODE; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding CN/AC: invalid PI code=%d", param_code); + } + break; + + case 20: /* PI - Session User Requirements param */ + if (param_len == 2) + { + dec_par->ses_urequir [0]= dec_buf [idx]; /* bits 9-16 */ + dec_par->ses_urequir [1]= dec_buf [idx+1]; /* bits 1-8 */ + } + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding CN/AC: invalid PI-20 parameter len=%u (should be len=2).", + param_len); + } + break; + + case 51: /* PI - Calling Session Selector param */ + if (param_len <= MAX_SSEL_LEN) /* 16 */ + { + if (spdu_type == COSP_SI_CONNECT) + { + dec_par->rem_ssel [0] = (ST_UCHAR) param_len; + memcpy (&dec_par->rem_ssel [1], &dec_buf [idx], param_len); + } + else + { + /* if COSP_SI_ACCEPT then same as Calling in S-CONNECT */ + dec_par->loc_ssel [0] = (ST_UCHAR) param_len; + memcpy (&dec_par->loc_ssel [1], &dec_buf [idx], param_len); + } + } + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR2 ("COSP-ERROR: Decoding CN/AC: invalid PI-51 parameter len=%u (should be len<=%u).", + param_len, MAX_SSEL_LEN); + } + break; + + case 52: /* PI - Called(CN)/Responding(AC) Session Selector param */ + if (param_len <= MAX_SSEL_LEN) /* 16 */ + { + if (spdu_type == COSP_SI_CONNECT) + { + dec_par->loc_ssel [0] = (ST_UCHAR) param_len; + memcpy (&dec_par->loc_ssel [1], &dec_buf [idx], param_len); + } + else + { + /* if COSP_SI_ACCEPT then Responder SSEL */ + dec_par->rem_ssel [0] = (ST_UCHAR) param_len; + memcpy (&dec_par->rem_ssel [1], &dec_buf [idx], param_len); + } + } + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR2 ("COSP-ERROR: Decoding CN/AC: invalid PI-52 parameter len=%u (should be len<=%u).", + param_len, MAX_SSEL_LEN); + } + break; + + case 193: /* PGI - User Data - used only if len <=512 in CONNECT and */ + /* len up to 65539 total SPDU size in ACCEPT (ISO 8327/DAD2) */ + if ((spdu_type == COSP_SI_CONNECT && param_len <= 512) || + (spdu_type == COSP_SI_ACCEPT && param_len <= COSP_MAX_UDATA)) + { + dec_par->udata_len = param_len; + dec_par->udata_ptr = &dec_buf [idx]; + } + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR2 ("COSP-ERROR: Decoding CN/AC: invalid PI-193 (User Data) parameter len=%u (max should be len<=%u).", + param_len, (spdu_type == COSP_SI_CONNECT) ? 512 : COSP_MAX_UDATA); + } + break; + + case 194: /* PGI - Extended User Data - used if len>512 */ + if (param_len <= COSP_MAX_UDATA_CON) /* and len<=10240 */ + { + dec_par->udata_len = param_len; + dec_par->udata_ptr = &dec_buf [idx]; + } + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR2 ("COSP-ERROR: Decoding CN/AC: invalid PI-194 (User Data) parameter len=%u (should be len<=%u).", + param_len, COSP_MAX_UDATA_CON); + } + break; + + default: + ret = COSP_ERR_DEC_INV_PI_CODE; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding CN/AC: invalid PI code=%d", param_code); + } /* end of switch */ + + /* adjust processing vars by the length of param processed */ + if (ret == SD_SUCCESS) + { + dec_len -= param_len; + idx += param_len; + } + else + break; + } /* end while len to decode */ + + break; /* this is end of decoding, exit loop unconditionally */ + } /* end of while (SD_TRUE) loop */ + + if (ret == SD_SUCCESS) + /* validate the received SPDU */ + ret = cosp_validate_cn_ac (dec_par, spdu_type); + + return (ret); +} + + +/************************************************************************/ +/* cosp_dec_rf */ +/*----------------------------------------------------------------------*/ +/* Function to decode a REFUSE SPDU. */ +/* Note if User Data are present in received SPDU then the length in the*/ +/* dec_par->udata_len will be > 0. The dec_par->udata_ptr points into */ +/* the spdu_buf (it is not an allocated pointer). */ +/* */ +/* Parameters: */ +/* COSP_RF *dec_par ptr to decoded parameters struct*/ +/* char *spdu_buf Pointer to received SPDU buf */ +/* ST_UINT spdu_len Length of received SPDU */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_dec_rf (COSP_RF *dec_par, char *spdu_buf, ST_UINT spdu_len) +{ +ST_RET ret; +ST_UCHAR *dec_buf; +ST_UINT dec_len; +ST_UCHAR param_code; +ST_UINT param_len; +ST_UINT len_bytes; /* number of bytes for encoded len (1 or 3) */ +ST_UINT idx; + + ret = SD_SUCCESS; + + dec_buf = (ST_UCHAR *) spdu_buf; + dec_len = 0; + idx = 0; + + /*-----------------------------------------------------*/ + /* set defaults in case params are not present in SPDU */ + /*-----------------------------------------------------*/ + + memset (dec_par, 0, sizeof (COSP_RF)); + dec_par->disconnect = 1; /* default disconnect transport */ + dec_par->ver_num = COSP_VER1; /* default is Version1 */ + dec_par->ses_urequir [0] = 0x03; /* bits 9-16: 9 and 10 set */ + dec_par->ses_urequir [1] = 0x49; /* bits 1-8: 1,4 and 7 set */ + + /* in addition memset is equivalent to following con params settings */ + /* dec_par->reason = 0; rejected by called SS (SS-user?)*/ + /* dec_par->udata_len = 0; Length of User Data */ + /* dec_par->udata_ptr = 0; Pointer to User Data (points into spdu_buf!) */ + + /* we will use the first while loop to avoid excesive nesting of if...else... */ + + while (SD_TRUE) + { + /* NOTE: we should never return back from bottom of the loop here!!! */ + + /* the decoded len should be comparable with spdu_len passed to this func */ + dec_len = (ST_UINT) cosp_dec_len (&dec_buf [idx+1], &len_bytes); + if (dec_len + 1+len_bytes != spdu_len) + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR2 ("COSP-ERROR: Decoding RF: invalid SPDU len=%u or decoded len=%u.", + spdu_len, dec_len + 1+len_bytes); + break; + } + idx += 1+len_bytes; /* 1 for RF SPDU code */ + + /* decode all REFUSE parameters */ + while (dec_len > 0) + { + param_code = dec_buf [idx]; + param_len = (ST_UINT) cosp_dec_len (&dec_buf [idx+1], &len_bytes); + + /* signal error if param_len is greater then decoding length left */ + if (param_len + 1+len_bytes > dec_len) + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR2 ("COSP-ERROR: Decoding RF: invalid parameter len=%u (length left to decode len=%u).", + param_len + 1+len_bytes, dec_len); + break; + } + dec_len -= 1+len_bytes; + idx += 1+len_bytes; + + /* do not try to decode if param_len is 0 (param is empty) */ + if (param_len == 0) + continue; + + switch (param_code) + { + case 1: /* PGI - Connection Identifier group */ + /* we will ignore this group (skip all decoding) */ + break; + + case 17: /* PI - Transport Disconnect */ + if (param_len == 1) + dec_par->disconnect = (ST_BOOLEAN)(dec_buf [idx] & 0x01); + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding RF: invalid PI-17 parameter len=%u (should be len=1).", + param_len); + } + break; + + case 20: /* PI - Session User Requirements param */ + if (param_len == 2) + { + dec_par->ses_urequir [0]= dec_buf [idx]; /* bits 9-16 */ + dec_par->ses_urequir [1]= dec_buf [idx+1]; /* bits 1-8 */ + } + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding RF: invalid PI-20 parameter len=%u (should be len=2).", + param_len); + } + break; + + case 22: /* PI - Version Number */ + if (param_len == 1) + dec_par->ver_num = dec_buf [idx]; + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding RF: invalid PI-22 parameter len=%u (should be len=1).", + param_len); + } + break; + + case 50: /* PI - Reason Code param */ + dec_par->reason = dec_buf [idx]; /* refuse reason code */ + + if (param_len > 1) + { + dec_par->udata_len = param_len-1; + dec_par->udata_ptr = &dec_buf [idx+1]; + } + break; + + default: + ret = COSP_ERR_DEC_INV_PI_CODE; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding RF: invalid PI code=%d", param_code); + } /* end of switch */ + + /* adjust processing vars by the length of param processed */ + if (ret == SD_SUCCESS) + { + dec_len -= param_len; + idx += param_len; + } + else + break; + } /* end while len to decode */ + + break; /* this is end of decoding, exit loop unconditionally */ + } /* end of while (SD_TRUE) loop */ + + /* validate the received SPDU */ + if (ret == SD_SUCCESS) + { + /* User Data may be present only if refuse reason=2 */ + if (dec_par->reason != COSP_RF_REASON_U_REJECT) + if (dec_par->udata_len > 0) + { + ret = COSP_ERR_DEC_INV_RF_UDATA; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding RF: User Data present (len=%u) when Refuse Reason!=2", + dec_par->udata_len); + } + } + + return (ret); +} + + +/************************************************************************/ +/* cosp_dec_fn_dn */ +/*----------------------------------------------------------------------*/ +/* Function to decode a FINISH or DISCONNECT SPDU. */ +/* Note if User Data are present in received SPDU then the length in the*/ +/* dec_par->udata_len will be > 0. The dec_par->udata_ptr points into */ +/* the spdu_buf (it is not an allocated pointer). */ +/* */ +/* Parameters: */ +/* COSP_FN_DN *dec_par Ptr to decoded parameters struct*/ +/* char *spdu_buf Pointer to received SPDU buf */ +/* ST_UINT spdu_len Length of received SPDU */ +/* ST_UCHAR spdu_type SPDU type to decode (FN, DN) */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_dec_fn_dn (COSP_FN_DN *dec_par, char *spdu_buf, ST_UINT spdu_len, + ST_UCHAR spdu_type) +{ +ST_RET ret; +ST_UCHAR *dec_buf; +ST_UINT dec_len; +ST_UCHAR param_code; +ST_UINT param_len; +ST_UINT len_bytes; /* number of bytes for encoded len (1 or 3) */ +ST_UINT idx; + + ret = SD_SUCCESS; + + dec_buf = (ST_UCHAR *) spdu_buf; + dec_len = 0; + idx = 0; + + /*-----------------------------------------------------*/ + /* set defaults in case params are not present in SPDU */ + /*-----------------------------------------------------*/ + + memset (dec_par, 0, sizeof (COSP_FN_DN)); + if (spdu_type == COSP_SI_FINISH) + dec_par->disconnect = 1; /* default disconnect transport */ + + /* in addition memset is equivalent to following con params settings */ + /* dec_par->udata_len = 0; Length of User Data */ + /* dec_par->udata_ptr = 0; Pointer to User Data (points into spdu_buf!) */ + + /* we will use the first while loop to avoid excesive nesting of if...else... */ + + while (SD_TRUE) + { + /* NOTE: we should never return back from bottom of the loop here!!! */ + + /* the decoded len should be comparable with spdu_len passed to this func */ + dec_len = (ST_UINT) cosp_dec_len (&dec_buf [idx+1], &len_bytes); + if (dec_len + 1+len_bytes != spdu_len) + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR2 ("COSP-ERROR: Decoding FN/DN: invalid SPDU len=%u or decoded len=%u.", + spdu_len, dec_len + 1+len_bytes); + break; + } + idx += 1+len_bytes; /* 1 for FN/DN SPDU code */ + + /* decode all FINISH / DISCONNECT parameters */ + while (dec_len > 0) + { + param_code = dec_buf [idx]; + param_len = (ST_UINT) cosp_dec_len (&dec_buf [idx+1], &len_bytes); + + /* signal error if param_len is greater then decoding length left */ + if (param_len + 1+len_bytes > dec_len) + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR2 ("COSP-ERROR: Decoding FN/DN: invalid parameter len=%u (length left to decode len=%u).", + param_len + 1+len_bytes, dec_len); + break; + } + dec_len -= 1+len_bytes; + idx += 1+len_bytes; + + /* do not try to decode if param_len is 0 (param is empty) */ + if (param_len == 0) + continue; + + switch (param_code) + { + case 17: /* PI - Transport Disconnect */ + /* this param is valid only in FINISH SPDU */ + if (spdu_type == COSP_SI_FINISH) + { + dec_par->disconnect = (ST_BOOLEAN)(dec_buf [idx] & 0x01); + if (dec_par->disconnect != 1) + { + /* we do NOT support reusing transport connection */ + ret = COSP_ERR_DEC_INV_PI_CODE; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding FN: PI code=%d (keep transport connection not supported)", param_code); + } + } + else + { + ret = COSP_ERR_DEC_INV_PI_CODE; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding DN: invalid PI code=%d", param_code); + } + break; + + case 193: /* PGI - User Data group */ + dec_par->udata_len = param_len; + dec_par->udata_ptr = &dec_buf [idx]; + break; + + default: + ret = COSP_ERR_DEC_INV_PI_CODE; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding FN/DN: invalid PI code=%d", param_code); + } /* end of switch */ + + /* adjust processing vars by the length of param processed */ + if (ret == SD_SUCCESS) + { + dec_len -= param_len; + idx += param_len; + } + else + break; + } /* end while len to decode */ + + break; /* this is end of decoding, exit loop unconditionally */ + } /* end of while (SD_TRUE) loop */ + + /* validate the received SPDU */ + if (ret == SD_SUCCESS) + { + if (dec_par->udata_len == 0) + { + ret = COSP_ERR_INV_UDATA_LEN; + COSP_LOG_ERR0 ("COSP-ERROR: Decoding FN/DN: invalid User Data len=0"); + } + } + + return (ret); +} + + +/************************************************************************/ +/* cosp_dec_ab */ +/*----------------------------------------------------------------------*/ +/* Function to decode an ABORT SPDU. */ +/* Note if User Data are present in received SPDU then the length in the*/ +/* dec_par->udata_len will be > 0. The dec_par->udata_ptr points into */ +/* the spdu_buf (it is not an allocated pointer). */ +/* */ +/* Parameters: */ +/* COSP_AB *dec_par Ptr to decoded parameters struct*/ +/* char *spdu_buf Pointer to received SPDU buf */ +/* ST_UINT spdu_len Length of received SPDU */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_dec_ab (COSP_AB *dec_par, char *spdu_buf, ST_UINT spdu_len) +{ +ST_RET ret; +ST_UCHAR *dec_buf; +ST_UINT dec_len; +ST_UCHAR param_code; +ST_UINT param_len; +ST_UINT len_bytes; /* number of bytes for encoded len (1 or 3) */ +ST_UINT idx; + + ret = SD_SUCCESS; + + dec_buf = (ST_UCHAR *) spdu_buf; + dec_len = 0; + idx = 0; + + /*-----------------------------------------------------*/ + /* set defaults in case params are not present in SPDU */ + /*-----------------------------------------------------*/ + + memset (dec_par, 0, sizeof (COSP_AB)); + dec_par->disconnect = 1; /* default disconnect transport */ + + /* in addition memset is equivalent to following con params settings */ + /* dec_par->reason = 0; undefined reason */ + /* dec_par->reflect_par_len= 0; Len of implementation defined protocol err code*/ + /* dec_par->reflect_par [9]= 0; Buf for implementation defined protocol err code*/ + /* dec_par->udata_len = 0; Length of User Data */ + /* dec_par->udata_ptr = 0; Pointer to User Data (points into spdu_buf!) */ + + /* we will use the first while loop to avoid excesive nesting of if...else... */ + + while (SD_TRUE) + { + /* NOTE: we should never return back from bottom of the loop here!!! */ + + /* the decoded len should be comparable with spdu_len passed to this func */ + dec_len = (ST_UINT) cosp_dec_len (&dec_buf [idx+1], &len_bytes); + if (dec_len + 1+len_bytes != spdu_len) + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR2 ("COSP-ERROR: Decoding AB: invalid SPDU len=%u or decoded len=%u.", + spdu_len, dec_len + 1+len_bytes); + break; + } + idx += 1+len_bytes; /* 1 for AB SPDU code */ + + /* decode all ABORT parameters */ + while (dec_len > 0) + { + param_code = dec_buf [idx]; + param_len = (ST_UINT) cosp_dec_len (&dec_buf [idx+1], &len_bytes); + + /* signal error if param_len is greater then decoding length left */ + if (param_len + 1+len_bytes > dec_len) + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR2 ("COSP-ERROR: Decoding AB: invalid parameter len=%u (length left to decode len=%u).", + param_len + 1+len_bytes, dec_len); + break; + } + dec_len -= 1+len_bytes; + idx += 1+len_bytes; + + /* do not try to decode if param_len is 0 (param is empty) */ + if (param_len == 0) + continue; + + switch (param_code) + { + case 17: /* PI - Transport Disconnect */ + if (param_len == 1) + { + dec_par->disconnect = (ST_BOOLEAN) (dec_buf [idx] & 0x01); + dec_par->reason = (ST_UCHAR) (dec_buf [idx] & 0x1E); + } + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding AB: invalid PI-17 parameter len=%u (should be len=1).", + param_len); + } + break; + + case 49: /* PI - Reflect param */ + if (param_len <= 9) + { + dec_par->reflect_par_len = param_len; + memcpy (dec_par->reflect_par, &dec_buf [idx], param_len); + } + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding AB: invalid PI-49 parameter len=%u (should be len<=9).", + param_len); + } + break; + + case 193: /* PGI - User Data group */ + dec_par->udata_len = param_len; + dec_par->udata_ptr = &dec_buf [idx]; + break; + + default: + ret = COSP_ERR_DEC_INV_PI_CODE; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding AB: invalid PI code=%d", param_code); + } /* end of switch */ + + /* adjust processing vars by the length of param processed */ + if (ret == SD_SUCCESS) + { + dec_len -= param_len; + idx += param_len; + } + else + break; + } /* end while len to decode */ + + break; /* this is end of decoding, exit loop unconditionally */ + } /* end of while (SD_TRUE) loop */ + + /* validate the received SPDU */ + if (ret == SD_SUCCESS) + { + if (dec_par->reason == COSP_AB_REASON_PROT_ERROR) + if (dec_par->reflect_par_len == 0) + { + ret = COSP_ERR_DEC_INV_AB_RP; + COSP_LOG_ERR0 ("COSP-ERROR: Decoding AB: invalid Reflect Parameter len=0"); + } + + if (dec_par->reason == COSP_AB_REASON_USER_ABORT) + if (dec_par->udata_len == 0) + { + ret = COSP_ERR_INV_UDATA_LEN; + COSP_LOG_ERR0 ("COSP-ERROR: Decoding AB: invalid User Data len=0"); + } + } + + return (ret); +} + + +/************************************************************************/ +/* cosp_dec_dt */ +/*----------------------------------------------------------------------*/ +/* Function to decode an DATA SPDU. */ +/* Note if User Data are present in received SPDU then the length in the*/ +/* dec_par->udata_len will be > 0. The dec_par->udata_ptr points into */ +/* the spdu_buf (it is not an allocated pointer). */ +/* */ +/* Parameters: */ +/* COSP_DT *dec_par Ptr to decoded parameters struct*/ +/* char *spdu_buf Pointer to received SPDU buf */ +/* ST_UINT spdu_len Length of received SPDU */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_dec_dt (COSP_DT *dec_par, char *spdu_buf, ST_UINT spdu_len) +{ +ST_RET ret; +ST_UCHAR *dec_buf; +ST_UINT dec_len; +ST_UINT len_bytes; /* number of bytes for encoded len (1 or 3) */ +ST_UINT idx; + + ret = SD_SUCCESS; + + dec_buf = (ST_UCHAR *) spdu_buf; + dec_len = 0; + idx = 0; + + /*-----------------------------------------------------*/ + /* set defaults in case params are not present in SPDU */ + /*-----------------------------------------------------*/ + + memset (dec_par, 0, sizeof (COSP_DT)); + + /* memset is equivalent to following con params settings */ + /* dec_par->udata_len = 0; Length of User Data */ + /* dec_par->udata_ptr = 0; Pointer to User Data (points into spdu_buf!) */ + + /*--------------------------------------------------------------------*/ + /* the protocol calls for GIVE-TOKEN and DT SPDU to be concatinated */ + /* even if we do not use the token mechanism. */ + /*--------------------------------------------------------------------*/ + + dec_len = (ST_UINT) cosp_dec_len (&dec_buf [idx+1], &len_bytes); + if (dec_len == 0) + { + idx += 1+len_bytes; + /* token mechanism not used, decode DT */ + if (dec_buf [idx] == COSP_SI_DATA) + { + /*------------------------------------------------------------*/ + /* note that Enclosure Item PI should not be present because */ + /* we do not support segmenting (see CONNECT) */ + /*------------------------------------------------------------*/ + + /* get the params length, should be 0, we do not send/rcv any params in DT */ + dec_len = (ST_UINT) cosp_dec_len (&dec_buf [idx+1], &len_bytes); + if (dec_len == 0) + { + idx += 1+len_bytes; /* 1 for DT SPDU code and 1 byte for params len LI */ + + dec_par->udata_len = spdu_len - (2 + 1+len_bytes); + dec_par->udata_ptr = &dec_buf [idx]; + } + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR0 ("COSP-ERROR: Decoding DT: Decoding of parameters in DATA SPDU not supported."); + } + } + else + { + ret = COSP_ERR_DEC_INV_SPDU; + COSP_LOG_ERR1 ("COSP-ERROR: Decoding DT: Invalid SPDU code=%u detected after Token SPDU.", + (ST_UINT) dec_buf [idx]); + } + } + else + { + ret = COSP_ERR_DEC_INV_LEN; + COSP_LOG_ERR0 ("COSP-ERROR: Decoding DT: Parameters in Token SPDU not supported."); + } + + return (ret); +} + + +/************************************************************************/ +/* cosp_dec_len */ +/*----------------------------------------------------------------------*/ +/* Function to decode a parameter's length (8-bit or 16-bit value). */ +/* */ +/* Parameters: */ +/* ST_UCHAR *buf Pointer to len in received SPDU buf */ +/* ST_UINT *bytes Pointer where to return number of */ +/* bytes for decoded field */ +/* */ +/* Return: */ +/* ST_UINT16 the length of a parameter */ +/************************************************************************/ +static ST_UINT16 cosp_dec_len (ST_UCHAR *buf, ST_UINT *bytes) +{ +ST_UINT16 len; + + if (buf [0] == 0xFF) + { + /* len >254 high order byte low order byte */ + len = ((ST_UINT16) buf [1] << 8) | (ST_UINT16) buf [2]; + *bytes = 3; + } + else + { + /* len <=254 */ + len = (ST_UINT16) buf [0]; + *bytes = 1; + } + + return (len); +} + + +/************************************************************************/ +/* cosp_validate_cn_ac */ +/*----------------------------------------------------------------------*/ +/* Function to validate parameters in a CONNECT or ACCEPT SPDU. */ +/* */ +/* Parameters: */ +/* COSP_CN_AC *dec_par ptr to decoded parameters struct*/ +/* ST_UCHAR spdu_type SPDU type to validate (CN, AC) */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if validation successful */ +/* error code otherwise */ +/************************************************************************/ +static ST_RET cosp_validate_cn_ac (COSP_CN_AC *dec_par, ST_UCHAR spdu_type) +{ + if (spdu_type == COSP_SI_CONNECT) + { + /* check if CONNECT SPDU is addressed to us */ + if (memcmp (dec_par->loc_ssel, cosp_only_ssel, cosp_only_ssel [0]+1)!=0) + { + COSP_LOG_ERR1 ("COSP-ERROR: Decoding CN/AC: Invalid Called SSEL (len=%d).", + (ST_INT) dec_par->loc_ssel [0]); + COSP_LOG_ERRH((ST_INT) dec_par->loc_ssel [0], &dec_par->loc_ssel [1]); + return (COSP_ERR_DEC_INV_LOC_SSEL); + } + } + else + { + /* ACCEPT SPDU, check the local SSEL if present */ + if (dec_par->loc_ssel [0] > 0) + { + if (dec_par->loc_ssel [0] != cosp_only_ssel [0] || + memcmp (&dec_par->loc_ssel [1], &cosp_only_ssel [1], cosp_only_ssel [0]) + != 0) + { + COSP_LOG_ERR1 ("COSP-ERROR: Decoding CN/AC: Invalid Calling SSEL (len=%d).", + (ST_INT) dec_par->loc_ssel [0]); + COSP_LOG_ERRH((ST_INT) dec_par->loc_ssel [0], &dec_par->loc_ssel [1]); + return (COSP_ERR_DEC_INV_LOC_SSEL); + } + } + } + + /* currently we support Version 2 of the Session Protocol */ + if (spdu_type == COSP_SI_CONNECT) + { + /* CONNECT, check if one of choices is COSP_VER2 */ + if ((dec_par->ver_num & COSP_VER2) == 0) + { + COSP_LOG_ERR2 ("COSP-ERROR: Decoding CN/AC: Session Protocol Version '%d' not supported (supported ver=%d).", + dec_par->ver_num, COSP_VER2); + return (COSP_ERR_DEC_INV_PROT_VER); + } + } + else + { + /* ACCEPT, make sure COSP_VER2 was accepted */ + if (dec_par->ver_num != COSP_VER2) + { + COSP_LOG_ERR2 ("COSP-ERROR: Decoding CN/AC: Session Protocol Version '%d' not supported (supported ver=%d).", + dec_par->ver_num, COSP_VER2); + return (COSP_ERR_DEC_INV_PROT_VER); + } + } + + /* make sure extended concatination is not set (we do not support it)*/ + if (dec_par->prot_option != 0) + { + COSP_LOG_ERR0 ("COSP-ERROR: Decoding CN/AC: Extended Concatination not supported."); + return (COSP_ERR_DEC_INV_PROT_OPT); + } + + /* make sure that segmenting of SSDUs was not specified */ + if (dec_par->initiator_tsdu_size != 0 || + dec_par->responder_tsdu_size != 0) + { + COSP_LOG_ERR0 ("COSP-ERROR: Decoding CN/AC: SSDUs segmenting not supported."); + return (COSP_ERR_DEC_INV_SEG); + } + + if (spdu_type == COSP_SI_CONNECT) + { + /* we support only Duplex Functional Units, make sure it is available*/ + if (!(dec_par->ses_urequir [1] & 0x02)) /* is bit2 set? */ + { + COSP_LOG_ERR0 ("COSP-ERROR: Decoding CN/AC: Duplex Functional Unit not proposed (Session User Requirements)."); + return (COSP_ERR_DEC_INV_FUN_UNITS); + } + } + else + { + /* ACCEPT, make sure only Duplex Functional Units (FU) has been selected */ + if (dec_par->ses_urequir [0] != 0 || /* bits 9-16: must be 0 */ + dec_par->ses_urequir [1] != 0x02) /* bits 1-8: bit2 set */ + { + COSP_LOG_ERR0 ("COSP-ERROR: Decoding CN/AC: Only Duplex Functional Unit supported (Session User Requirements)."); + return (COSP_ERR_DEC_INV_FUN_UNITS); + } + } + + return (SD_SUCCESS); +} + + diff --git a/mmslib/ositcps/cosp_enc.c b/mmslib/ositcps/cosp_enc.c new file mode 100644 index 0000000..cac4506 --- /dev/null +++ b/mmslib/ositcps/cosp_enc.c @@ -0,0 +1,812 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : cosp_enc.c */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file implements the encoding of COSP SPDUs. */ +/* */ +/* NOTE: Implementation restrictions: */ +/* Non-segmenting COSP, */ +/* Transport connections are not reused. */ +/* */ +/* For information see the: */ +/* ISO 8326 "Information processing systems - Open Systems */ +/* Interconnection - Basic connection oriented session service */ +/* definition. */ +/* ISO 8327 "Information processing systems - Open Systems */ +/* Interconnection - Basic connection oriented session protocol */ +/* specification. */ +/* ISO 8327/ADD.2 (Draft for Version2). */ +/* */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* cosp_envelope_len */ +/* cosp_enc_cn_ac */ +/* cosp_enc_rf */ +/* cosp_enc_fn_dn */ +/* cosp_enc_ab */ +/* cosp_enc_dt */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/02/04 JRB 10 cosp_enc_dt: do NOT restrict user data len. */ +/* 07/16/02 JRB 09 Clean up & fix comments in cosp_enc_cn_ac. */ +/* 06/05/02 JRB 08 Send Calling SSEL on connect request. */ +/* 09/12/01 JRB 07 Reverse last change (not needed). */ +/* 08/01/01 JRB 06 Del rem_addr arg from cosp_enc_cn_ac. */ +/* 04/12/00 JRB 05 Lint cleanup. */ +/* 09/13/99 MDE 04 Added SD_CONST modifiers */ +/* 08/13/98 JRB 03 Lint cleanup. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/20/97 EJV 02 Enhanced logging. */ +/* 01/17/97 EJV 01 Created */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; /* Define for SLOG mechanism */ +#endif + +#include "acse2.h" + +#include "cosp_log.h" +#include "cosp.h" +#include "cosp_usr.h" + + + /*----------------------------------------------*/ + /* Fixed encoding for CONNECT / ACCEPT SPDU: */ + /* Connect/Accept PGI: */ + /* - extended concatination not supported, */ + /* - COSP Version2 supported */ + /* Session User Requirements PI: */ + /* - duplex functional unit (FU) supported */ + /*----------------------------------------------*/ + +static ST_UCHAR cosp_cn_ac_fixed [12] = { + 5, /* CN-AC PGI code */ + 6, /* CN-AC PGI len */ + /* Protocol Option PI: */ + 19, /* PI code */ + 1, /* PI len */ + 0, /* 0 if rcv extended concatinat. not supported*/ + /* Version Number PI: */ + 22, /* PI code */ + 1, /* PI len */ + COSP_VER2, /* we supporting Version2 */ + /* Session User Requirements PI: */ + 20, /* PI code */ + 2, /* PI len */ + 0, /* bits 9-16 are 0 */ + 2}; /* bits 1-8 (only bit2=1 duplex FU supported) */ + + + + /*----------------------------------------------*/ + /* Fixed encoding for REFUSE SPDU: */ + /* Session User Requirements PI: */ + /* - duplex functional unit (FU) supported */ + /* COSP Version PI: */ + /* - Version2 supported */ + /*----------------------------------------------*/ + +static ST_UCHAR cosp_rf_fixed [7] = { + /* Session User Requirements PI: */ + 20, /* PI code */ + 2, /* PI len */ + 0, /* bits 9-16 are 0 */ + 2, /* bits 1-8 (only bit2=1 duplex FU supported) */ + /* Version Number PI: */ + 22, /* PI code */ + 1, /* PI len */ + COSP_VER2}; /* we supporting Version2 */ + + +static ST_UINT cosp_enc_len (ST_UINT16 len, ST_UCHAR *buf); + + +/************************************************************************/ +/* cosp_envelope_len */ +/*----------------------------------------------------------------------*/ +/* Function to compute the number of envelope bytes needed to encode */ +/* a SPDU. The returned length does not include the SS-user data length.*/ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Connection info parameters */ +/* ST_UINT rem_ssel_len Remote SSEL length */ +/* ST_UCHAR spdu_type One of COSP_SI_... from cosp.h */ +/* */ +/* Return: */ +/* ST_UINT Length of SPDU envelope encoding */ +/************************************************************************/ +ST_UINT cosp_envelope_len (ACSE_CONN *con, ST_UINT rem_ssel_len, ST_UCHAR spdu_type) +{ +ST_UINT enc_len; +ST_UINT udata_len; + + udata_len = con->ppdu_len; + enc_len = 0; + + switch (spdu_type) + { + case COSP_SI_CONNECT: + enc_len = + 2+6 /* Connect/Accept PGI */ + + 2+2 /* Ses User Requirem. PI*/ + + (cosp_only_ssel[0] != 0 ? 2+cosp_only_ssel[0] : 0)/* Calling SSEL*/ + + (rem_ssel_len != 0 ? 2+rem_ssel_len : 0)/* Called SSEL */ + + (udata_len > 0 ? 2 : 0) /* 1 PI code, 1 len */ + + (udata_len > 254 ? 2 : 0); /* add 2 bytes for len */ + break; + + case COSP_SI_ACCEPT: + enc_len = + 2+6 /* Connect/Accept PGI */ + + 2+2 /* Ses User Requirem. PI*/ + + (udata_len > 0 ? 2 : 0) /* 1 PI code, 1 len */ + + (udata_len > 254 ? 2 : 0); /* add 2 bytes for len */ + break; + + case COSP_SI_REFUSE: + enc_len = + 2+2 /* Ses User Requirem. PI*/ + + 2+1 /* Supported Version PI */ + + 2+1 /* 1 PI code, 1 len, 1 Reason Code*/ + + (udata_len > 254 ? 2 : 0); /* add 2 bytes for len */ + break; + + case COSP_SI_FINISH: + case COSP_SI_DISCON: + enc_len = + (udata_len > 0 ? 2 : 0) /* 1 PI code, 1 len */ + + (udata_len > 254 ? 2 : 0); /* addl 2 bytes for len */ + break; + + case COSP_SI_ABORT: + enc_len = + 2+1 /* TP Disconnect PI */ + + (udata_len > 0 ? 2 : 0) /* 1 PI code, 1 len */ + + (udata_len > 254 ? 2 : 0); /* add 2 bytes for len */ + break; + + case COSP_SI_DATA: + /* We send Give Token SPDU concatinated with the DT (basic concatination) */ + enc_len = 2; /* (SI=01,LI=0) token functionality not used */ + break; + + default: + COSP_LOG_ERR1 ("COSP-ERROR: Encoding: Invalid PDU type = %d", spdu_type); + break; + } + + /* add bytes for params len (none in DT) */ + if (spdu_type == COSP_SI_DATA) + /* in DT we do not send any parameters but we have to send the LI=0 */ + enc_len += 1; /* 1 byte for len */ + else + { + /* all udata is encoded in a parameter */ + if (enc_len + udata_len > 254) + enc_len += 3; /* 3 bytes for len */ + else + enc_len += 1; /* 1 byte for len */ + } + + /* add byte for SPDU code */ + enc_len += 1; + + return (enc_len); +} + + +/************************************************************************/ +/* cosp_enc_cn_ac */ +/*----------------------------------------------------------------------*/ +/* Function to encode a CONNECT or ACCEPT SPDU. */ +/* This function assumed that there is enough place in the enc_buf for */ +/* the CN or AC SPDU encoding. The function cosp_envelope_len can be */ +/* used to compute exact envelope encoding length. */ +/* Note that this function assumes that the SS-user data (CP / CPA PPDU)*/ +/* has been already copied into the enc_buf in proper position. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Connection info parameters */ +/* PRES_ADDR *rem_addr Remote Address (needed only for CN) */ +/* char **spdu_ptr Pointer where to return pointer to SPDU */ +/* ST_UINT *spdu_len Pointer where to return the SPDU len */ +/* ST_UCHAR spdu_type COSP_SI_CONNECT or COSP_SI_ACCEPT */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_enc_cn_ac (ACSE_CONN *con, PRES_ADDR *rem_addr, + char **spdu_ptr, ST_UINT *spdu_len, + ST_UCHAR spdu_type) +{ +ST_UINT envelope_len; +ST_UINT udata_len; +ST_UINT udata_max_len; +ST_UCHAR ssel_len; +ST_UCHAR *ssel; +ST_UCHAR *enc_buf; +ST_UINT enc_len; +ST_UINT idx; + + /*------------------------------------------------------------*/ + /* make sure data len is OK (User Data presence is mandatory) */ + /*------------------------------------------------------------*/ + udata_len = con->ppdu_len; + if (rem_addr) + envelope_len = cosp_envelope_len (con, rem_addr->ssel_len, spdu_type); + else + envelope_len = cosp_envelope_len (con, 0, spdu_type); + + if (spdu_type == COSP_SI_CONNECT) + udata_max_len = COSP_MAX_UDATA_CON; + else + udata_max_len = COSP_MAX_UDATA; /* for ACCEPT SPDU */ + if (udata_len == 0 || udata_len > udata_max_len) + { + COSP_LOG_ERR2 ("COSP-ERROR: Encoding CN/AC: Invalid User Data length=%u (0ppdu_ptr - envelope_len; + if (enc_buf < cosp_buf) + { + COSP_LOG_ERR0 ("COSP-ERROR: Encoding CN/AC: Invalid pointer to Global Encoding Buffer."); + return (COSP_ERR_INV_POINTER); + } + idx = 0; + + /*--------------------------------------------*/ + /* Encode CN or AC code and total SPDU len */ + /*--------------------------------------------*/ + /* SPDU length to encode does not include 1 byte for SPDU code and */ + /* 1 or 3 bytes for total len */ + + if (envelope_len-2 + udata_len <= 254) + enc_len = envelope_len-2 + udata_len; /* len enc on 1 byte */ + else + enc_len = envelope_len-4 + udata_len; /* len enc on 3 bytes */ + + enc_buf [idx++] = spdu_type; + idx += cosp_enc_len ((ST_UINT16) enc_len, &enc_buf [idx]); + + /*--------------------------------------------*/ + /* no Connection Identifier PGI encoded */ + /*--------------------------------------------*/ + + /*--------------------------------------------*/ + /* encode Connect/Accept PGI: */ + /* - extended concatination not supported, */ + /* - COSP Version2 supported */ + /* encode Session User Requirements PI: */ + /* - duplex functional unit (FU) supported */ + /*--------------------------------------------*/ + memcpy (&enc_buf [idx], cosp_cn_ac_fixed, sizeof (cosp_cn_ac_fixed)); + idx += sizeof (cosp_cn_ac_fixed); + + /*----------------------------------------------*/ + /* encode Calling SSEL - (CN only) */ + /*----------------------------------------------*/ + ssel_len = 0; + ssel = NULL; /* Just to avoid "uninitialized" warning. */ + if (spdu_type == COSP_SI_CONNECT) + { + /* Calling SSEL - optional (only if needed) */ + ssel_len = cosp_only_ssel [0]; + ssel = &cosp_only_ssel [1]; + } + if (ssel_len > 0) + { + enc_buf [idx++] = 51; /* encode PI code */ + enc_buf [idx++] = ssel_len; /* encode PI len */ + memcpy (&enc_buf [idx], ssel, (ST_UINT) ssel_len); + idx += ssel_len; + } + + /*------------------------------------*/ + /* encode Called/Responding SSEL (CN only) */ + /*------------------------------------*/ + ssel_len = 0; + ssel = NULL; /* Just to avoid "uninitialized" warning. */ + if (spdu_type == COSP_SI_CONNECT && rem_addr != NULL) + { + /* Called SSEL - mandatory */ + ssel_len = (ST_UCHAR) rem_addr->ssel_len; + ssel = (ST_UCHAR *) rem_addr->ssel; + } + if (ssel_len > 0) + { + enc_buf [idx++] = 52; /* PI code */ + enc_buf [idx++] = ssel_len; /* PI len */ + memcpy (&enc_buf [idx], ssel, (ST_UINT) ssel_len); + idx += ssel_len; + } + + /*--------------------------------------------------------------------*/ + /* encode User Data (length only), SS-user Data should be already */ + /* in the enc_buf (in proper position). */ + /*--------------------------------------------------------------------*/ + if (spdu_type == COSP_SI_CONNECT) + { + if (udata_len <= 512) + enc_buf [idx++] = 193; /* encode PGI code */ + else + enc_buf [idx++] = 194; /* if 512 < udata_len <= 10240)*/ + } + else + { + /* ACCEPT SPDU */ + enc_buf [idx++] = 193; /* encode PGI code */ + } + idx += cosp_enc_len ((ST_UINT16) udata_len, &enc_buf [idx]); + /* udata should be already in enc_buf */ + + + /*-----------------------------------------------*/ + /* set values to be returned to calling function */ + /*-----------------------------------------------*/ + *spdu_len = envelope_len + udata_len; + *spdu_ptr = (char *) enc_buf; + + return (SD_SUCCESS); +} + + +/************************************************************************/ +/* cosp_enc_rf */ +/*----------------------------------------------------------------------*/ +/* Function to encode a REFUSE SPDU. */ +/* This function assumed that there is enough place in the enc_buf for */ +/* the RF SPDU encoding. The function cosp_envelope_len can be used */ +/* to compute exact envelope encoding length. */ +/* Note that this function assumes that the SS-user data (refuse reason)*/ +/* has been already copied into the enc_buf in proper position. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Connection info parameters */ +/* charE **spdu_ptr Pointer where to return pointer to SPDU */ +/* ST_UINT *spdu_len Pointer where to return the SPDU len */ +/* ST_UCHAR reason Reason code for refuse */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_enc_rf (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len, + ST_UCHAR reason) +{ +ST_UINT envelope_len; +ST_UINT udata_len; +ST_UCHAR *enc_buf; +ST_UINT enc_len; +ST_UINT idx; + + /*--------------------------------------------*/ + /* make sure data len is OK */ + /*--------------------------------------------*/ + udata_len = con->ppdu_len; + envelope_len = cosp_envelope_len (con, 0, COSP_SI_REFUSE); + + if (udata_len > COSP_MAX_UDATA) + { + COSP_LOG_ERR2 ("COSP-ERROR: Encoding RF: Invalid User Data length=%u (length<=%u).", + udata_len, COSP_MAX_UDATA); + return (COSP_ERR_INV_UDATA_LEN); + } + /* set the pointer to beginning of encoding in the buffer (global buf)*/ + enc_buf = con->ppdu_ptr - envelope_len; + if (enc_buf < cosp_buf) + { + COSP_LOG_ERR0 ("COSP-ERROR: Encoding RF: Invalid pointer to Global Encoding Buffer."); + return (COSP_ERR_INV_POINTER); + } + + idx = 0; + + /*------------------------------------*/ + /* Encode RF code and total SPDU len */ + /*------------------------------------*/ + /* SPDU length to encode does not include 1 byte for SPDU code and */ + /* 1 or 3 bytes for total len */ + + if (envelope_len-2 + udata_len <= 254) + enc_len = envelope_len-2 + udata_len; /* len enc on 1 byte */ + else + enc_len = envelope_len-4 + udata_len; /* len enc on 3 bytes */ + + enc_buf [idx++] = COSP_SI_REFUSE; + idx += cosp_enc_len ((ST_UINT16) enc_len, &enc_buf [idx]); + + /*--------------------------------------------*/ + /* no Connection Identifier PGI encoded */ + /*--------------------------------------------*/ + + /*--------------------------------------------*/ + /* encode Session User Requirements PI: */ + /* - duplex functional unit (FU) supported */ + /* encode COSP Version PI: */ + /* - Version2 supported */ + /*--------------------------------------------*/ + memcpy (&enc_buf [idx], cosp_rf_fixed, sizeof (cosp_rf_fixed)); + idx += sizeof (cosp_rf_fixed); + + /*--------------------------------------------------------------------*/ + /* encode Reason Code. SS-user Data (if any) should be already in the */ + /* enc_buf (in proper position). */ + /*--------------------------------------------------------------------*/ + enc_buf [idx++] = 50; /* PI code */ + idx += cosp_enc_len ((ST_UINT16) (udata_len+1), &enc_buf [idx]); /* len */ + enc_buf [idx++] = reason; /* Reason code */ + /* udata may follow if reason=COSP_RF_REASON_U_REJECT */ + + /*-----------------------------------------------*/ + /* set values to be returned to calling function */ + /*-----------------------------------------------*/ + *spdu_len = envelope_len + udata_len; + *spdu_ptr = (char *) enc_buf; + + return (SD_SUCCESS); +} + + +/************************************************************************/ +/* cosp_enc_fn_dn */ +/*----------------------------------------------------------------------*/ +/* Function to encode a FINISH or DISCONNECT SPDU. */ +/* This function assumed that there is enough place in the enc_buf for */ +/* the FN or DN SPDU encoding. The function cosp_envelope_len can be */ +/* used to compute exact envelope encoding length. */ +/* Note that this function assumes that the SS-user data (RLRQ or RLRE */ +/* APDU) have been already copied into the enc_buf in proper position. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Connection info parameters */ +/* char **spdu_ptr Pointer where to return pointer to SPDU */ +/* ST_UINT *spdu_len Pointer where to return the SPDU len */ +/* ST_UCHAR spdu_type COSP_SI_FINISH or COSP_SI_DISCON */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_enc_fn_dn (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len, + ST_UCHAR spdu_type) +{ +ST_UINT envelope_len; +ST_UINT udata_len; +ST_UCHAR *enc_buf; +ST_UINT enc_len; +ST_UINT idx; + + /*------------------------------------------------------------*/ + /* make sure data len is OK (User Data mandatory) */ + /*------------------------------------------------------------*/ + udata_len = con->ppdu_len; + envelope_len = cosp_envelope_len (con, 0, spdu_type); + + if (udata_len == 0 || udata_len > COSP_MAX_UDATA) + { + COSP_LOG_ERR2 ("COSP-ERROR: Encoding FN/DN: Invalid User Data length=%u (0ppdu_ptr - envelope_len; + if (enc_buf < cosp_buf) + { + COSP_LOG_ERR0 ("COSP-ERROR: Encoding FN/DN: Invalid pointer to Global Encoding Buffer."); + return (COSP_ERR_INV_POINTER); + } + + idx = 0; + + /*------------------------------------------*/ + /* Encode FN or DN code and total SPDU len */ + /*------------------------------------------*/ + /* SPDU length to encode does not include 1 byte for FN or DN code */ + /* and 1 or 3 bytes for total len */ + + if (envelope_len-2 + udata_len <= 254) + enc_len = envelope_len-2 + udata_len; /* len enc on 1 byte */ + else + enc_len = envelope_len-4 + udata_len; /* len enc on 3 bytes */ + + enc_buf [idx++] = spdu_type; + idx += cosp_enc_len ((ST_UINT16) enc_len, &enc_buf [idx]); + + /*--------------------------------------------------------------------*/ + /* encode User Data (length only), SS-user Data should be already in */ + /* the enc_buf (in proper position). */ + /*--------------------------------------------------------------------*/ + enc_buf [idx++] = 193; /* PI code */ + idx += cosp_enc_len ((ST_UINT16) udata_len, &enc_buf [idx]); + + /*-----------------------------------------------*/ + /* set values to be returned to calling function */ + /*-----------------------------------------------*/ + *spdu_len = envelope_len + udata_len; + *spdu_ptr = (char *) enc_buf; + + return (SD_SUCCESS); +} + + +/************************************************************************/ +/* cosp_enc_u_ab */ +/*----------------------------------------------------------------------*/ +/* Function to encode a SS-user generated ABORT SPDU */ +/* This function assumed that there is enough place in the enc_buf for */ +/* the AB SPDU encoding. The function cosp_envelope_len can be used */ +/* to compute exact envelope encoding length. */ +/* Note that this function assumes that the SS-user data (ARP /ATU PPDU)*/ +/* has been already copied into the enc_buf in proper position. */ +/* */ +/* Parameters: */ +/* ACSE_CON *con Connection info parameters */ +/* char **spdu_ptr Pointer where to return pointer to SPDU */ +/* ST_UINT *spdu_len Pointer where to return the SPDU len */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_enc_u_ab (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len) +{ +ST_UINT envelope_len; +ST_UINT udata_len; +ST_UCHAR *enc_buf; +ST_UINT enc_len; +ST_UINT idx; + + /*------------------------------------------------------------*/ + /* make sure data len is OK (depending on the reason the User */ + /* Data or the Reflect Parameter presence is mandatory) */ + /*------------------------------------------------------------*/ + udata_len = con->ppdu_len; + envelope_len = cosp_envelope_len (con, 0, COSP_SI_ABORT); + +//envelope_len = cosp_envelope_len (con, 0, COSP_SI_AB_ACCEPT); //renxiaobao2022 mod + + + + if (udata_len == 0 || udata_len > COSP_MAX_UDATA) + { + COSP_LOG_ERR2 ("COSP-ERROR: Encoding U-AB: Invalid User Data length=%u (0ppdu_ptr - envelope_len; + if (enc_buf < cosp_buf) + { + COSP_LOG_ERR0 ("COSP-ERROR: Encoding U-AB: Invalid pointer to Global Encoding Buffer."); + return (COSP_ERR_INV_POINTER); + } + + idx = 0; + + /*------------------------------------*/ + /* Encode AB code and total SPDU len */ + /*------------------------------------*/ + /* SPDU length to encode does not include 1 byte for AB code and */ + /* 1 or 3 bytes for total len */ + + if (envelope_len-2 + udata_len <= 254) + enc_len = envelope_len-2 + udata_len; /* len enc on 1 byte */ + else + enc_len = envelope_len-4 + udata_len; /* len enc on 3 bytes */ + + enc_buf [idx++] = COSP_SI_ABORT; + + //enc_buf [idx++] = COSP_SI_AB_ACCEPT;; //renxiaobao2022 mod + + + + idx += cosp_enc_len ((ST_UINT16) enc_len, &enc_buf [idx]); + + /*----------------------------------------------------*/ + /* Encode Transport Disonnect PI (release TP conn) */ + /*----------------------------------------------------*/ + enc_buf [idx++] = 17; /* PI code */ + enc_buf [idx++] = 1; /* PI len */ + enc_buf [idx++] = COSP_TCONN_RELEASE | COSP_AB_REASON_USER_ABORT; + + /*--------------------------------------------------------------------*/ + /* encode User Data (length only), SS-user Data should be already */ + /* in the enc_buf (in proper position). */ + /*--------------------------------------------------------------------*/ + if (udata_len > 0) + { + /* encode User Data */ + enc_buf [idx++] = 193; /* PGI code */ + idx += cosp_enc_len ((ST_UINT16) udata_len, &enc_buf [idx]); + /* udata should be already in enc_buf */ + } + + /*-----------------------------------------------*/ + /* set values to be returned to calling function */ + /*-----------------------------------------------*/ + *spdu_len = envelope_len + udata_len; + *spdu_ptr = (char *) enc_buf; + + return (SD_SUCCESS); +} + +/************************************************************************/ +/* cosp_enc_p_ab */ +/*----------------------------------------------------------------------*/ +/* Function to encode a SS-provider generated ABORT SPDU */ +/* This function assumed that there is enough place in the enc_buf for */ +/* the AB SPDU encoding (COSP_P_AB_LEN bytes). */ +/* */ +/* Parameters: */ +/* char *spdu_ptr Pointer to encode buffer for SPDU */ +/* ST_INT err_code This value will be passed for AB reason */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_enc_p_ab (char *spdu_ptr, ST_INT err_code) +{ + + /*------------------------------------*/ + /* Encode AB code and total SPDU len */ + /*------------------------------------*/ + + + + + spdu_ptr [0] = COSP_SI_ABORT; + spdu_ptr [1] = 3 + 4; + + + + + /*----------------------------------------------------*/ + /* Encode Transport Disonnect PI (release TP conn) */ + /*----------------------------------------------------*/ + spdu_ptr [2] = 17; /* PI code */ + spdu_ptr [3] = 1; /* PI len */ + spdu_ptr [4] = COSP_TCONN_RELEASE | COSP_AB_REASON_PROT_ERROR; + + /* encode the Reflect Parameter PI */ + spdu_ptr [5] = 49; /* PI code */ + spdu_ptr [6] = (ST_UCHAR) 2; /* PI len (0-9) */ + spdu_ptr [7] = (ST_UCHAR) ((err_code >> 8) & 0x00FF); + spdu_ptr [8] = (ST_UCHAR) (err_code & 0x00FF); + + /* !!! if number of encoded bytes changes make sure that the define */ + /* !!! COSP_P_AB_SPDU_LEN is changed accordingly. */ + + return (SD_SUCCESS); +} + + +/************************************************************************/ +/* cosp_enc_dt */ +/*----------------------------------------------------------------------*/ +/* Function to encode a DATA SPDU */ +/* This function assumed that there is enough place in the enc_buf for */ +/* the GIVE-TOKEN ans DT SPDU encoding. */ +/* The function cosp_envelope_len can be used to compute exact envelope */ +/* encoding length. */ +/* Note that this function assumes that the SS-user data have been */ +/* already copied into the enc_buf in proper position. */ +/* */ +/* Parameters: */ +/* ACSE_CON *con Connection info parameters */ +/* char **spdu_ptr Pointer where to return pointer to SPDU */ +/* ST_UINT *spdu_len Pointer where to return the SPDU len */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_enc_dt (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len) +{ +ST_UINT envelope_len; +ST_UINT udata_len; +ST_UCHAR *enc_buf; +ST_UINT idx; + + /*------------------------------------------------------------*/ + /* make sure data len is OK */ + /*------------------------------------------------------------*/ + udata_len = con->ppdu_len; + envelope_len = cosp_envelope_len (con, 0, COSP_SI_DATA); + + if (udata_len == 0) + { + COSP_LOG_ERR2 ("COSP-ERROR: Encoding DT: Invalid User Data length=%u (0ppdu_ptr - envelope_len; + if (enc_buf < cosp_buf) + { + COSP_LOG_ERR0 ("COSP-ERROR: Encoding DT: Invalid pointer to Global Encoding Buffer."); + return (COSP_ERR_INV_POINTER); + } + + idx = 0; + + /*--------------------------------------------*/ + /* Encode GIVE-TOKEN code and params len LI=0 */ + /*--------------------------------------------*/ + + enc_buf [idx++] = COSP_SI_GIVE_TOKEN; + enc_buf [idx++] = 0; /* no parameters present LI=0 */ + + /*------------------------------------*/ + /* Encode DT code and params len LI=0 */ + /*------------------------------------*/ + + enc_buf [idx++] = COSP_SI_DATA; + enc_buf [idx++] = 0; /* no parameters present LI=0 */ + /* udata should be already in enc_buf */ + + /*-----------------------------------------------*/ + /* set values to be returned to calling function */ + /*-----------------------------------------------*/ + *spdu_len = envelope_len + udata_len; + *spdu_ptr = (char *) enc_buf; + + return (SD_SUCCESS); +} + + +/************************************************************************/ +/* cosp_enc_len */ +/*----------------------------------------------------------------------*/ +/* Function to encode a parameter's len. If len<=254 then 1 byte */ +/* will be used to encode the length. If len>254 then 3 bytes will */ +/* be used to encode the length. */ +/* */ +/* Parameters: */ +/* ST_UINT16 len Parameter's length to encode */ +/* ST_UCHAR *buf Pointer where to encode the len */ +/* */ +/* Return: */ +/* ST_UINT Number of bytes used in encoding of len */ +/************************************************************************/ +static ST_UINT cosp_enc_len (ST_UINT16 len, ST_UCHAR *buf) +{ +ST_UINT bytes; + + if (len <= 254) + { + buf [0] = (ST_UCHAR) len; + bytes = 1; + } + else + { + buf [0] = (ST_UCHAR) 0xFF; /* indicates len>254 */ + buf [1] = (ST_UCHAR)((len >> 8) & 0x00FF); /* high order byte */ + buf [2] = (ST_UCHAR) (len & 0x00FF); /* low order byte */ + bytes = 3; + } + + return (bytes); +} + diff --git a/mmslib/ositcps/cospmain.c b/mmslib/ositcps/cospmain.c new file mode 100644 index 0000000..b70ec55 --- /dev/null +++ b/mmslib/ositcps/cospmain.c @@ -0,0 +1,2043 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2005, All Rights Reserved */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : cospmain.c */ +/* PRODUCT(S) : MOSI Stack (over TP4) */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file implements functions common to CALLING and */ +/* CALLED side of the COSP protocol. */ +/* */ +/* For information see the: */ +/* ISO 8326 "Information processing systems - Open Systems */ +/* Interconnection - Basic connection oriented session service */ +/* definition. */ +/* ISO 8327 "Information processing systems - Open Systems */ +/* Interconnection - Basic connection oriented session protocol */ +/* specification. */ +/* ISO 8327/ADD.2 (Draft for Version2). */ +/* */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* cosp_bind */ +/* cosp_unbind */ +/* */ +/* cosp_con_req */ +/* cosp_con_rsp_pos */ +/* cosp_con_rsp_neg */ +/* */ +/* cosp_rel_req */ +/* cosp_rel_rsp_pos */ +/* */ +/* cosp_u_abort_req */ +/* */ +/* cosp_data_req */ +/* */ +/* tp4_bind_cnf */ +/* tp4_unbind_cnf */ +/* */ +/* tp4_connect_ind */ +/* tp4_connect_cnf */ +/* tp4_disconnect_ind */ +/* tp4_data_ind */ +/* tp4_expdata_ind */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/30/08 JRB 21 Chg log msg from ERR to ENC. */ +/* 04/28/08 GLB 20 Removed CALLED_ONLY and CALLING_ONLY */ +/* 04/09/08 JRB 19 Fix log message for unsupported SPDU. */ +/* 05/05/05 EJV 18 cosp_con_req: copy new port param. */ +/* 09/17/04 JRB 17 cosp_con_req: save tp4_conn_id returned from */ +/* modified tp4_connect (need for abort fix). */ +/* cosp_u_abort_req: if waiting for T-CONNECT.cnf,*/ +/* call tp4_disconnect (correct ISO 8327 action).*/ +/* 01/20/04 EJV 16 acse_free_con: add a_free_part_security_info.*/ +/* 11/14/03 JRB 15 Save encrypt_ctrl ONLY for TP0 (not for TP4).*/ +/* 08/25/03 EJV 14 Added param to tp4_connect(). */ +/* tp4_connect_ind, cnf: save encrypt_ctrl */ +/* 06/20/02 JRB 13 Chg addr args to tp4_connect_ind & */ +/* copy them to ACSE_CONN. */ +/* 06/05/02 JRB 12 Allow Called SSEL=NULL (0 length) on conn req*/ +/* 09/10/01 JRB 11 Remove last change but fix cosp_cn_ptr free. */ +/* 08/01/01 JRB 10 Del rem_addr from cosp_enc_cn_ac calls. */ +/* Del use of cosp_cn_ptr, cosp_cn_len. */ +/* 05/09/01 JRB 09 On S-CONNECT.ind, save SSELs in ACSE_CONN. */ +/* 03/14/01 JRB 08 Use new SMEM allocation functions. */ +/* Add global variable "session_cfg". */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 08/13/98 JRB 06 Lint cleanup. */ +/* 06/17/98 JRB 05 Allow second call to cosp_bind if SSEL same. */ +/* 12/30/97 JRB 04 cosp_bind return same as tp4_bind if it fails*/ +/* 07/31/97 JRB 03 cosp_bind & cosp_con_req: set "tp_type" in */ +/* tp4_addr. */ +/* Don't set NSAP on tp4_bind call (ignored). */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/20/97 EJV 02 Enhanced logging and collision handling. */ +/* 02/07/97 EJV 01 Created */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; /* Define for SLOG mechanism */ +#endif + +#include "mem_chk.h" +#include "tp4api.h" +#include "tp4.h" /* need MIN_TP0_CONN_ID definition */ +#include "acse2.h" + +#include "cosp_log.h" +#include "cosp.h" +#include "cosp_usr.h" + + + /*======================================================*/ + /* */ + /* L O C A L V A R I A B L E S */ + /* A N D */ + /* F U N C T I O N S P R O T O T Y P E S */ + /* */ + /*======================================================*/ + +/* define actions to perform after return from one of decode functions */ +#define COSP_S_P_ABORT_IND 1 +#define COSP_SEND_ABORT_SPDU 2 +#define COSP_T_DISCONNECT 4 + + +ST_RET cosp_send_abort (ACSE_CONN *con, ST_INT err_code); + +static ST_RET cosp_process_connect (ACSE_CONN *con, ST_UINT spdu_len, char *spdu_buf); +static ST_RET cosp_process_finish (ACSE_CONN *con, ST_UINT spdu_len, char *spdu_buf); +static ST_RET cosp_process_accept (ACSE_CONN *con, ST_UINT spdu_len, char *spdu_buf); +static ST_RET cosp_process_refuse (ACSE_CONN *con, ST_UINT spdu_len, char *spdu_buf); +static ST_RET cosp_process_discon (ACSE_CONN *con, ST_UINT spdu_len, char *spdu_buf); +static ST_RET cosp_process_abort (ACSE_CONN *con, ST_UINT spdu_len, char *spdu_buf); +static ST_RET cosp_process_data (ACSE_CONN *con, ST_UINT spdu_len, char *spdu_buf); + + +/************************************************************************/ +/* Global and static variables. */ +/************************************************************************/ +/* flag below prevents calling acse_free_con twice (if we are in func */ +/* tp4_connect and tp4_disconnect_ind is called) */ + +static ST_BOOLEAN cosp_in_tp4_func; + +static ST_BOOLEAN cosp_bind_called; /* only 1 binding allowed */ + +ST_UCHAR cosp_only_ssel [1+MAX_SSEL_LEN]; +SESSION_CFG session_cfg; /* Session layer configuration */ + + /*======================================================*/ + /* */ + /* B I N D I N G F U N C T I O N S */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* cosp_bind */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to bind to local Session Address. */ +/* The SS-user should implement the u_cosp_bind_cnf function. */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_user_bind_id COSP User's id for this binding.*/ +/* PRES_ADDR *loc_addr Local Address to bind to */ +/* ST_INT sharable Ignored, (for compatibility with*/ +/* ST_INT max_conns Ignored, previous versions) */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if bind successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_bind (ST_LONG cosp_user_bind_id, PRES_ADDR *loc_addr, + ST_INT sharable, ST_INT max_conns) +{ +ST_INT ret; +TP4_ADDR tp4_addr; +ST_LONG user_bind_id; /* TP4 user bind id */ + + COSP_LOG_ENC1 ("S-BIND.req: cosp_user_bind_id =0x%08X", cosp_user_bind_id); + + ret = SD_SUCCESS; + + + + + + /* Check SSEL. If OK, save it. */ + if (!cosp_bind_called) + { + /* If local SSEL len is legal, save SSEL. */ + if (loc_addr->ssel_len <= MAX_SSEL_LEN) + { + if ((cosp_only_ssel [0] = (ST_UCHAR) loc_addr->ssel_len) > 0) + memcpy (&cosp_only_ssel [1], loc_addr->ssel, loc_addr->ssel_len); + } + else + { + ret = COSP_ERR_INV_SSEL; /* invalid loc SSEL */ + COSP_LOG_ERR1 ("COSP-ERROR: S-BIND.req: Invalid length=%d of SSEL.", + loc_addr->ssel_len); + } + } + else + { /* Second Bind. Only allow it if the SSEL is the same. */ + if (cosp_only_ssel [0] != (ST_UCHAR) loc_addr->ssel_len || + (loc_addr->ssel_len != 0 && + memcmp (&cosp_only_ssel [1], loc_addr->ssel, loc_addr->ssel_len))) + { + COSP_LOG_ERR0 ("COSP-ERROR: Cannot BIND to different SSEL"); + ret = COSP_ERR_INV_SSEL; + } + } + + + /* Bind to Transport. */ + if (ret == SD_SUCCESS) + { + /* Copy tsel from pres_addr to tp4_addr struct. Don't copy nsap */ + /* because tp4_bind ignores it anyway. */ + if (loc_addr->tsel_len <= sizeof (tp4_addr.tp4_sel)) + { + tp4_addr.tp4_sel_len = loc_addr->tsel_len; + memcpy (tp4_addr.tp4_sel, loc_addr->tsel, loc_addr->tsel_len); + tp4_addr.tp_type = loc_addr->tp_type; /* TP4 or TCP? */ + + user_bind_id = cosp_user_bind_id; /* pass bind id down */ + + + + if ((ret = tp4_bind (user_bind_id, &tp4_addr, sharable, max_conns)) + != SD_SUCCESS) + { + COSP_LOG_ERR0 ("COSP-ERROR: S-BIND.req: T-BIND.req failed."); + } + } + else + { + ret = COSP_ERR_INV_TP4_ADDR; /* TP4 bind failed */ + COSP_LOG_ERR2 ("COSP-ERROR: S-BIND.req: Invalid TSEL length=%d or NSAP length=%d.", + loc_addr->tsel_len, loc_addr->nsap_len); + } + } /* end Transport binding section */ + + + + /* If successful, set called flag. Otherwise, treat next bind like first.*/ + if (ret == SD_SUCCESS) + cosp_bind_called = SD_TRUE; + + return (ret); +} + + +/************************************************************************/ +/* tp4_bind_cnf */ +/*----------------------------------------------------------------------*/ +/* This function is called by the TP-provider to indicate the result of */ +/* the bind operation (see cosp_bind func). */ +/* */ +/* Parameters: */ +/* ST_LONG user_bind_id User's id (COSP id) for this binding. */ +/* ST_LONG tp4_bind_id TP4 assigned ID for this binding. */ +/* ST_INT result Indicates if the bind was successful: */ +/* = 0 Success */ +/* <> 0 Error code */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID tp4_bind_cnf (ST_LONG user_bind_id, ST_LONG tp4_bind_id, ST_RET result) +{ +ST_LONG cosp_user_bind_id; +ST_LONG cosp_bind_id; + + cosp_user_bind_id = user_bind_id; /* we passing same bind id up */ + cosp_bind_id = tp4_bind_id; /* COSP bind id same as TP4 */ + + COSP_LOG_DEC3 ("S-BIND.cnf: cosp_user_bind_id =0x%08X cosp_bind_id =%9ld result =%d", + cosp_user_bind_id, cosp_bind_id, result); + + u_cosp_bind_cnf (cosp_user_bind_id, cosp_bind_id, result); +} + + +/************************************************************************/ +/* cosp_unbind */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to unbind from local Session Address. */ +/* The SS-user should implement the u_cosp_unbind_cnf function. */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_bind_id COSP's id to unbind. */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if unbind successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_unbind (ST_LONG cosp_bind_id) +{ +ST_LONG tp4_bind_id; + + COSP_LOG_ENC1 ("S-UNBIND.req: cosp_bind_id =%9ld", cosp_bind_id); + + tp4_bind_id = cosp_bind_id; + + /* unbind the transport */ + if (tp4_unbind (tp4_bind_id) != SD_SUCCESS) + { + COSP_LOG_ERR0 ("COSP-ERROR: S-UNBIND.req: T-UNBIND.req failed."); + return (COSP_ERR_TP4_RET); + } + return (SD_SUCCESS); +} + + +/************************************************************************/ +/* tp4_unbind_cnf */ +/*----------------------------------------------------------------------*/ +/* This function is called by the TP4-provider to indicate that the */ +/* unbind operation completed. */ +/* */ +/* Parameters: */ +/* ST_LONG user_bind_id User's id for this binding. */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID tp4_unbind_cnf (ST_LONG user_bind_id) +{ +ST_LONG cosp_user_bind_id; + + cosp_user_bind_id = user_bind_id; + + COSP_LOG_DEC1 ("S-UNBIND.cnf: cosp_user_bind_id =0x%08X", cosp_user_bind_id); + + u_cosp_unbind_cnf (cosp_user_bind_id); +} + + +/************************************************************************/ +/* acse_free_con */ +/*----------------------------------------------------------------------*/ +/* This function will free the pointer to connection info. */ +/* In most cases the COSP engine is responsible for releasing the con */ +/* pointer. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info struct */ +/* */ +/* Return: */ +/* ST_VOID none */ +/************************************************************************/ +ST_VOID acse_free_con (ACSE_CONN *con) +{ + + + if (con) + { + /* free partner Authentication Info */ + + a_free_part_security_info ((ST_LONG) con); + + if (con->cosp_cn_ptr) + M_FREE (MSMEM_COSP_CN, con->cosp_cn_ptr); /* free saved encoded CN SPDU */ + + M_FREE (MSMEM_ACSE_CONN, con); + } + +} + + /*======================================================*/ + /* */ + /* C O N N E C T (CALLED SIDE) F U N C T I O N S */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* tp4_connect_ind */ +/*----------------------------------------------------------------------*/ +/* This function is called by the TP4-provider to indicate that a */ +/* remote node wishes to establish a connection. */ +/* */ +/* Parameters: */ +/* ST_LONG user_bind_id User's id for this binding. */ +/* ST_LONG tp4_conn_id COSP connection id for this connect. */ +/* ST_UCHAR *loc_tsel Local (called) TSEL. */ +/* ST_UCHAR *rem_tsel Remote (calling) TSEL. */ +/* ST_UCHAR *rem_nsap Remote (calling) NSAP (TP4) or */ +/* ST_ULONG rem_ip Remote (calling) IP addr(TP0) */ +/* ST_INT conndata_len Length of opt connect data <= 32 bytes */ +/* char *conndata Pointer to opt connect data. */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID tp4_connect_ind (ST_LONG user_bind_id, ST_LONG tp4_conn_id, + ST_UCHAR *loc_tsel, ST_UCHAR *rem_tsel, + ST_UCHAR *rem_nsap, ST_ULONG rem_ip, + ST_INT conndata_len, char *conndata) +{ +ACSE_CONN *con; + + tp4_reldata (conndata); /* !!! we ignoring conndata */ + + con = (ACSE_CONN *) M_CALLOC (MSMEM_ACSE_CONN, 1, sizeof (ACSE_CONN)); + + /* accept incomming transport connection */ + if (tp4_accept (tp4_conn_id, (ST_LONG) con, 0, NULL) == SD_SUCCESS) + { + con->cosp_state = COSP_CSTATE_IDLE_TCON; + con->cosp_bind_id = user_bind_id; /* save the id to pass to COPP */ + con->cosp_vtca = SD_TRUE; /* transport conn acceptor */ + con->tp4_conn_id = tp4_conn_id; + /* Save TSELs, NSAP in ACSE_CONN struct. */ + memcpy (con->loc_tsel, loc_tsel, loc_tsel [0]+1); + memcpy (con->rem_tsel, rem_tsel, rem_tsel [0]+1); + if (tp4_conn_id >= MIN_TP0_CONN_ID) /* This is TP0 conn. Save IP addr*/ + { + con->remNetAddr.ip = rem_ip; +#if defined (TP0_ENABLED) + /* If connection is TP0, save encrypt_ctrl. */ + if (tp4_conn_id >= MIN_TP0_CONN_ID) + { /* this is TP0 connection */ + TP0_CONN *tp0_conn = &tp0_conn_arr [tp4_conn_id-MIN_TP0_CONN_ID]; + /* save the encryption info in ACSE_CONN */ + con->encrypt_ctrl = tp0_conn->sock_info->encrypt_ctrl; + } +#endif + } + else /* This is TP4 conn. Save NSAP */ + memcpy (con->remNetAddr.nsap, rem_nsap, rem_nsap [0]+1); + } + else + { + COSP_LOG_ERR0 ("COSP-ERROR: T-CONNECT.ind: T-ACCEPT.req connection failed."); + + M_FREE (MSMEM_STARTUP, con); + + /* reject incomming transport connection, accept failed */ + tp4_disconnect (tp4_conn_id, 0, NULL); + } +} + + +/************************************************************************/ +/* cosp_con_rsp_pos */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to Accept an incomming connection. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to con info struct */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_con_rsp_pos (ACSE_CONN *con) +{ +ST_INT ret; +ST_UINT spdu_len; +char *spdu_ptr; + + COSP_LOG_ENC2 ("S-CONNECT.rsp+: acse_conn_id =0x%08X user_conn_id =%4ld", + con, con->user_conn_id); + COSP_LOG_ENCC1 ("User data length: %d", con->ppdu_len); + COSP_LOG_ENCH (con->ppdu_len, con->ppdu_ptr); + + ret = SD_SUCCESS; + + if (con->cosp_state == COSP_CSTATE_WAIT_CON_RSP) + { + /* encode ACCEPT SPDU */ + ret = cosp_enc_cn_ac (con, NULL, &spdu_ptr, &spdu_len, COSP_SI_ACCEPT); + if (ret == SD_SUCCESS) + { + if (tp4_data (con->tp4_conn_id, SD_TRUE, spdu_len, spdu_ptr) == SD_SUCCESS) + { + con->cosp_state = COSP_CSTATE_DATA_XFER; + con->cosp_vcoll = SD_FALSE; + con->cosp_vdnr = SD_FALSE; + } + else + { + ret = COSP_ERR_TP4_RET; + COSP_LOG_ERR1 ("COSP-ERROR: S-CONNECT.rsp+ acse_conn_id=0x%08X: T-DATA.req failed.", + con); + } + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: S-CONNECT.rsp+ acse_conn_id=0x%08X: Encoding ACCEPT SPDU failed.", + con); + } + } + else + { + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: S-CONNECT.rsp+ acse_conn_id=0x%08X: Invalid state=%d.", + con, con->cosp_state); + } + + return (ret); +} + + +/************************************************************************/ +/* cosp_con_rsp_neg */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to Reject an incomming connection. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to con info struct */ +/* ST_INT reason Reason for reject COSP_CON_RSP_U_... */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_con_rsp_neg (ACSE_CONN *con, ST_INT reason) +{ +ST_INT ret; +ST_UINT spdu_len; +char *spdu_ptr; +ST_UCHAR reason_code; + + COSP_LOG_ENC3 ("S-CONNECT.rsp-: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d", + con, con->user_conn_id, reason); + COSP_LOG_ENCC1 ("User data length: %d", con->ppdu_len); + COSP_LOG_ENCH (con->ppdu_len, con->ppdu_ptr); + + ret = SD_SUCCESS; + + if (con->cosp_state == COSP_CSTATE_WAIT_CON_RSP) + { + /* encode REFUSE SPDU */ + switch (reason) + { + case COSP_CON_RSP_U_CONGESTION: + reason_code = COSP_RF_REASON_U_CONGESTION; + break; + + case COSP_CON_RSP_U_IN_UDATA: + reason_code = COSP_RF_REASON_U_REJECT; + /* SS-user data should be present in this case */ + break; + + case COSP_CON_RSP_U_NOT_SPECIFIED: + default: + reason_code = COSP_RF_REASON_U_NOT_SPECIFIED; + } + + /* check if user data present */ + if (reason == COSP_CON_RSP_U_IN_UDATA) + { + /* SS-user data should be present in this case */ + if (con->ppdu_len == 0) + ret = COSP_ERR_INV_UDATA_LEN; + } + else + { + /* SS-user data should NOT be present in this case */ + if (con->ppdu_len != 0) + ret = COSP_ERR_INV_UDATA_LEN; + } + + if (ret == SD_SUCCESS) + { + ret = cosp_enc_rf (con, &spdu_ptr, &spdu_len, reason_code); + if (ret == SD_SUCCESS) + { + if (tp4_data (con->tp4_conn_id, SD_TRUE, spdu_len, spdu_ptr) == SD_SUCCESS) + { + con->cosp_state = COSP_CSTATE_WAIT_TDISCON_IND; + tp4_session_timer (con->tp4_conn_id, SD_TRUE); /* start timer */ + } + else + { + ret = COSP_ERR_TP4_RET; + COSP_LOG_ERR1 ("COSP-ERROR: S-CONNECT.rsp- acse_conn_id=0x%08X: T-DATA.req failed.", + con); + } + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: S-CONNECT.rsp- acse_conn_id=0x%08X: Encoding REFUSE SPDU failed.", + con); + } + } + else + { + COSP_LOG_ERR3 ("COSP-ERROR: S-CONNECT.rsp- acse_conn_id=0x%08X: Invalid SS-UserData length=%u for Reason=%d.", + con, con->ppdu_len, reason); + } + } + else + { + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: S-CONNECT.rsp- acse_conn_id=0x%08X: Invalid state=%d.", + con, con->cosp_state); + } + + return (ret); +} + + /*======================================================*/ + /* */ + /* C O N N E C T (CALLING SIDE) F U N C T I O N S */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* cosp_con_req */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to establish Session Layer connection. */ +/* SS-user should implement the u_cosp_con_cnf_pos & u_cosp_con_cnf_neg */ +/* functions to receive confirm for this request. */ +/* If this function returns value other then SD_SUCCESS then the function */ +/* u_cosp_con_cnf_xxx will not be called. */ +/* */ +/* Parameters: */ +/* ST_LONG cosp_bind_id COSP bind id */ +/* PRES_ADDR *rem_addr Remote Address */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_con_req (ST_LONG cosp_bind_id, PRES_ADDR *rem_addr, ACSE_CONN *con) +{ +ST_RET ret; +TP4_ADDR tp4_addr; +ST_UINT spdu_len; +char *spdu_ptr; +ST_LONG tp4_user_bind_id; + + COSP_LOG_ENC3 ("S-CONNECT.req: acse_conn_id =0x%08X user_conn_id =%4ld cosp_bind_id =%9ld", + con, con->user_conn_id, cosp_bind_id); + COSP_LOG_ENCC1 ("User data length: %d", con->ppdu_len); + COSP_LOG_ENCH (con->ppdu_len, con->ppdu_ptr); + + if (con->cosp_state != COSP_CSTATE_IDLE) + { + ret = COSP_ERR_INV_CON_STATE; /* invalid connect state*/ + COSP_LOG_ERR2 ("COSP-ERROR: S-CONNECT.req acse_conn_id=0x%08X: Invalid state=%d.", + con, con->cosp_state); + return (ret); + } + + tp4_user_bind_id = cosp_bind_id; /* we using only one id */ + + /* Check "Called" SSEL. May be NULL (i.e. length=0) */ + if (rem_addr->ssel_len <= MAX_SSEL_LEN) + { + /* Save SSEL in ACSE_CONN struct. */ + con->rem_ssel[0] = rem_addr->ssel_len; /* first byte is len */ + memcpy (&con->rem_ssel[1], rem_addr->ssel, rem_addr->ssel_len); + + ret = cosp_enc_cn_ac (con, rem_addr, &spdu_ptr, &spdu_len, COSP_SI_CONNECT); + if (ret == SD_SUCCESS) + { + /* we always will initiate new transport connection for every new */ + /* session connection, so find empty spot for con info */ + + /* Copy tsel and nsap from pres_addr to tp4_addr struct */ + tp4_addr.tp4_sel_len = rem_addr->tsel_len; + memcpy (tp4_addr.tp4_sel, rem_addr->tsel, rem_addr->tsel_len); + tp4_addr.tp_type = rem_addr->tp_type; + if (rem_addr->tp_type == TP_TYPE_TP4) + { + tp4_addr.net_addr_len = rem_addr->nsap_len; + memcpy (tp4_addr.netAddr.nsap, rem_addr->netAddr.nsap, rem_addr->nsap_len); + } + else + { + tp4_addr.netAddr.ip = rem_addr->netAddr.ip; /* IP Addr */ + tp4_addr.port = rem_addr->port; + } + + /* Note: !!! the tp4_disconnect_ind may be called before the */ + /* tp4_connect function returns (SD_FAILURE), we want to log the err */ + /* only in one place (here) */ + cosp_in_tp4_func = SD_TRUE; /* prevents logging err */ + + /* request transport connection (no connect data) */ + if ((con->tp4_conn_id = tp4_connect (tp4_user_bind_id, (ST_LONG) con, &tp4_addr, 0, NULL, + &con->encrypt_ctrl)) >= 0) + { + /* save the encoded CN until T-CONNECT.cnf received */ + con->cosp_state = COSP_CSTATE_WAIT_TCON_CNF; + con->cosp_cn_len = spdu_len; + con->cosp_cn_ptr = (ST_CHAR *) M_MALLOC (MSMEM_COSP_CN, spdu_len); + memcpy (con->cosp_cn_ptr, spdu_ptr, spdu_len); + con->cosp_vtca = SD_FALSE; /* transport conn initiator */ + } + else + { + ret = COSP_ERR_TP4_RET; + COSP_LOG_ENC1 ("COSP-ERROR: S-CONNECT.req acse_conn_id=0x%08X: T-CONNECT.req failed.", + con); + } + + cosp_in_tp4_func = SD_FALSE; /* turn off the flag */ + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: S-CONNECT.req acse_conn_id=0x%08X: Encoding CONNECT SPDU failed.", + con); + } + } + else + { + ret = COSP_ERR_INV_SSEL; /* invalid SSEL (length) */ + COSP_LOG_ERR2 ("COSP-ERROR: S-CONNECT.req acse_conn_id=0x%08X: Invalid remote SSEL length=%d.", + con, rem_addr->ssel_len); + } + + return (ret); +} + + +/************************************************************************/ +/* tp4_connect_cnf */ +/*----------------------------------------------------------------------*/ +/* This function is called by the TP4-provider to indicate that the */ +/* transport connection has been established. */ +/* NOTE: cosp_con_req saved the TP4 connection ID in con->tp4_conn_id. */ +/* It should match the tp4_conn_id passed to this function. */ +/* */ +/* Parameters: */ +/* ST_LONG user_conn_id User's connection id for this connect. */ +/* ST_LONG tp4_conn_id TP4 connection id for this connect. */ +/* ST_INT conndata_len Length of optional connect data. */ +/* char *conndata Pointer to optional connect data. */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID tp4_connect_cnf (ST_LONG user_conn_id, ST_LONG tp4_conn_id, + ST_INT conndata_len, char *conndata) +{ +ACSE_CONN *con; + + tp4_reldata (conndata); /* !!! we ignoring conndata */ + + con = (ACSE_CONN *) user_conn_id; + + if (con->cosp_state == COSP_CSTATE_WAIT_TCON_CNF) + { +#if defined (TP0_ENABLED) + /* If connection is TP0, save encrypt_ctrl. */ + if (tp4_conn_id >= MIN_TP0_CONN_ID) + { /* this is TP0 connection */ + TP0_CONN *tp0_conn = &tp0_conn_arr [tp4_conn_id-MIN_TP0_CONN_ID]; + /* save the encryption info in ACSE_CONN */ + con->encrypt_ctrl = tp0_conn->sock_info->encrypt_ctrl; + } +#endif + + /* send the CN (already encoded) on the established transport connection */ + if (tp4_data (tp4_conn_id, SD_TRUE, con->cosp_cn_len, con->cosp_cn_ptr) + == SD_SUCCESS) + { + con->cosp_state = COSP_CSTATE_WAIT_AC; /* wait AC or RF */ + + /* we are done with the encoding buffer for CN */ + if (con->cosp_cn_ptr) + { + M_FREE (MSMEM_COSP_CN, con->cosp_cn_ptr); + con->cosp_cn_len = 0; + con->cosp_cn_ptr = NULL; + } + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: T-CONNECT.cnf acse_conn_id=0x%08X: T-DATA.req failed", + con); + } + } + else + { + COSP_LOG_ERR2 ("COSP-ERROR: T-CONNECT.cnf acse_conn_id=0x%08X: Invalid state=%d.", + con, con->cosp_state); + } +} + + /*======================================================*/ + /* */ + /* C O N N E C T I O N R E L E A S E (CALLED SIDE) */ + /* */ + /*======================================================*/ + +/************************************************************************/ +/* cosp_rel_rsp_pos */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to Accept a release of connection. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_rel_rsp_pos (ACSE_CONN *con) +{ +ST_INT ret; +ST_UINT spdu_len; +char *spdu_ptr; + + COSP_LOG_ENC2 ("S-RELEASE.rsp+: acse_conn_id =0x%08X user_conn_id =%4ld", + con, con->user_conn_id); + COSP_LOG_ENCC1 ("User data length: %d", con->ppdu_len); + COSP_LOG_ENCH (con->ppdu_len, con->ppdu_ptr); + + if (con->cosp_state == COSP_CSTATE_WAIT_REL_RSP) + { + /* some additional predicates must be also true */ + if (!con->cosp_vcoll || + (con->cosp_vcoll && con->cosp_vdnr) || /* collision but DN received */ + (con->cosp_vcoll && !con->cosp_vtca)) /* collision and we are con initiator */ + { + /* connection released confirmed by COPP, encode and send DISCONNECT SPDU */ + /* Transport connections are not reused. */ + ret = cosp_enc_fn_dn (con, &spdu_ptr, &spdu_len, COSP_SI_DISCON); + if (ret == SD_SUCCESS) + { + if (tp4_data (con->tp4_conn_id, SD_TRUE, spdu_len, spdu_ptr) == SD_SUCCESS) + { + if (!con->cosp_vcoll || + (con->cosp_vcoll && con->cosp_vdnr)) /* collision but DN received */ + { + con->cosp_state = COSP_CSTATE_WAIT_TDISCON_IND; + tp4_session_timer (con->tp4_conn_id, SD_TRUE); /* start timer */ + } + else + { + /* collision and we are the con initiator */ + con->cosp_state = COSP_CSTATE_WAIT_DN; + } + } + else + { + ret = COSP_ERR_TP4_RET; + COSP_LOG_ERR1 ("COSP-ERROR: S-RELEASE.rsp+ acse_conn_id=0x%08X: T-DATA.req failed.", + con); + } + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: S-RELEASE.rsp+ acse_conn_id=0x%08X: Encoding DISCONNECT SPDU failed.", + con); + } + } + else + { + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR1 ("COSP-ERROR: S-RELEASE.rsp+ acse_conn_id=0x%08X: Connection Release Collision\n" + " (DN not received or not a connection initiator).", + con); + } + } + else + { + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: S-RELEASE.rsp+ acse_conn_id=0x%08X: Invalid state=%d.", + con, con->cosp_state); + } + + return (ret); +} + + + /*======================================================*/ + /* */ + /* C O N N E C T I O N R E L E A S E (CALLING SIDE)*/ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* cosp_rel_req */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to release a Session connection. */ +/* SS-user should implement the u_cosp_rel_cnf_pos function to receive */ +/* confirm for this request. Negative confirm is not implemented. */ +/* If this function returns value other then SD_SUCCESS then the function */ +/* u_cosp_rel_cnf_pos will not be called. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_rel_req (ACSE_CONN *con) +{ +ST_INT ret; +ST_UINT spdu_len; +char *spdu_ptr; + + COSP_LOG_ENC2 ("S-RELEASE.req: acse_conn_id =0x%08X user_conn_id =%4ld", + con, con->user_conn_id); + COSP_LOG_ENCC1 ("User data length: %d", con->ppdu_len); + COSP_LOG_ENCH (con->ppdu_len, con->ppdu_ptr); + + ret = SD_SUCCESS; + + if (con->cosp_state == COSP_CSTATE_WAIT_REL_RSP || + con->cosp_state == COSP_CSTATE_DATA_XFER) + { + /* connection is beeing released, encode and send FINISH SPDU */ + ret = cosp_enc_fn_dn (con, &spdu_ptr, &spdu_len, COSP_SI_FINISH); + if (ret == SD_SUCCESS) + { + if (tp4_data (con->tp4_conn_id, SD_TRUE, spdu_len, spdu_ptr) == SD_SUCCESS) + { + if (con->cosp_state == COSP_CSTATE_WAIT_REL_RSP) + { + /* collision occurred, request to release con while waiting */ + /* for resp to S-RELEASE.ind */ + con->cosp_vcoll = SD_TRUE; + /* remain in the same state */ + } + else + con->cosp_state = COSP_CSTATE_WAIT_DN; + } + else + { + ret = COSP_ERR_TP4_RET; + COSP_LOG_ERR1 ("COSP-ERROR: S-RELEASE.req acse_conn_id=0x%08X: T-DATA.req failed.", + con); + } + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: S-RELEASE.req acse_conn_id=0x%08X: Encoding FINISH SPDU failed.", + con); + } + } + else + { + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: S-RELEASE.req acse_conn_id=0x%08X: Invalid state=%d.", + con, con->cosp_state); + } + + return (ret); +} + + +/************************************************************************/ +/* tp4_disconnect_ind */ +/*----------------------------------------------------------------------*/ +/* This function is called by the TP4-provider to indicate that a */ +/* transport connection is beeing released. */ +/* */ +/* Parameters: */ +/* ST_LONG user_conn_id User's connection id for this connect. */ +/* ST_INT reason Reason for disconnect */ +/* ST_INT conndata_len Length of opt connect data <= 32 bytes */ +/* char *conndata Pointer to opt connect data. */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID tp4_disconnect_ind (ST_LONG user_conn_id, ST_INT reason, + ST_INT conndata_len, char *conndata) +{ +ACSE_CONN *con; + + tp4_reldata (conndata); /* !!! we ignoring conndata */ + + con = (ACSE_CONN *) user_conn_id; + + switch (con->cosp_state) + { + case COSP_CSTATE_IDLE: + /* ignore this tp4_disconnect_ind if in tp4_connect (returns SD_FAILURE) */ + if (!cosp_in_tp4_func) + { + COSP_LOG_ERR2 ("COSP-ERROR: T-DISCONNECT.ind acse_conn_id=0x%08X: Invalid state=%d.", + con, con->cosp_state); + } + break; + + case COSP_CSTATE_IDLE_TCON: + /* disconnected before a CN has been received (COPP has no */ + /* knowledge about this connection at this point). */ + acse_free_con (con); + break; + + case COSP_CSTATE_WAIT_TCON_CNF: + case COSP_CSTATE_WAIT_AC: + case COSP_CSTATE_WAIT_DN: + case COSP_CSTATE_WAIT_CON_RSP: + case COSP_CSTATE_WAIT_REL_RSP: + case COSP_CSTATE_DATA_XFER: + + /* issue S-P-ABORT.ind to local SS-user (use code from cosp_usr.h)*/ + COSP_LOG_DEC4 ("S-P-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d (TP4 reason=0x%02x)", + con, con->user_conn_id, (ST_INT) COSP_P_AB_IND_TP_DISCON, reason); + + u_cosp_p_abort_ind (con, COSP_P_AB_IND_TP_DISCON); + acse_free_con (con); + break; + + case COSP_CSTATE_WAIT_TDISCON_IND: + tp4_session_timer (con->tp4_conn_id, SD_FALSE); /* stop timer */ + acse_free_con (con); + break; + + default: + COSP_LOG_ERR2 ("COSP-ERROR: T-DISCONNECT.ind acse_conn_id=0x%08X: Invalid state=%d.", + con, con->cosp_state); + } +} + + +/************************************************************************/ +/* tp4_session_timer_expired */ +/*----------------------------------------------------------------------*/ +/* This function is called by TP4 when the session_timer expire. */ +/* */ +/* Parameters: */ +/* ST_LONG user_conn_id COSP connection id for this connect. */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID tp4_session_timer_expired (ST_LONG user_conn_id) +{ +ACSE_CONN *con; + + con = (ACSE_CONN *) user_conn_id; + + if (con->cosp_state == COSP_CSTATE_WAIT_TDISCON_IND) + { + tp4_disconnect (con->tp4_conn_id, 0, NULL); + acse_free_con (con); + } + else + { + COSP_LOG_ERR2 ("COSP-ERROR: S-TIMER.expired acse_conn_id=0x%08X: Invalid state=%d.", + con, con->cosp_state); + } +} + + + /*======================================================*/ + /* */ + /* A B O R T F U N C T I O N S */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* cosp_u_abort_req */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to Abort a connection (S-U-ABORT) */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/* CRITICAL: this function may free the ACSE_CONN struct so the struct */ +/* MUST NOT be accessed after calling this function. */ +/************************************************************************/ +ST_RET cosp_u_abort_req (ACSE_CONN *con) +{ +ST_INT ret; + + COSP_LOG_ENC2 ("S-U-ABORT.req: acse_conn_id =0x%08X user_conn_id =%4ld", + con, con->user_conn_id); + COSP_LOG_ENCC1 ("User data length: %d", con->ppdu_len); + COSP_LOG_ENCH (con->ppdu_len, con->ppdu_ptr); + + ret = SD_SUCCESS; + + switch (con->cosp_state) + { + case COSP_CSTATE_WAIT_TCON_CNF: + tp4_disconnect (con->tp4_conn_id, 0, NULL); + acse_free_con (con); /* done with this connection */ + break; + + case COSP_CSTATE_WAIT_AC: + case COSP_CSTATE_WAIT_DN: + case COSP_CSTATE_WAIT_CON_RSP: + case COSP_CSTATE_WAIT_REL_RSP: + case COSP_CSTATE_DATA_XFER: + /* send ABORT SPDU and wait for T-DISCONNECT.ind */ + if ((ret = cosp_send_abort (con, 0)) == SD_SUCCESS) + { + con->cosp_state = COSP_CSTATE_WAIT_TDISCON_IND; + tp4_session_timer (con->tp4_conn_id, SD_TRUE); /* start timer */ + } + break; + + default: + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: S-U-ABORT.req acse_conn_id=0x%08X: Invalid state=%d.", + con, con->cosp_state); + } + + if (ret != SD_SUCCESS) + { + + + /* disconnect if we couldn't send abort */ + tp4_disconnect (con->tp4_conn_id, 0, NULL); + acse_free_con (con); + + + + } + + /* we always will return success */ + return (SD_SUCCESS); +} + + +/************************************************************************/ +/* cosp_send_abort */ +/*----------------------------------------------------------------------*/ +/* Function to sends ABORT SPDU to remote SS-user. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to conn info struct */ +/* ST_INT err_code Error code (defined by COSP) */ +/* If =0 then S-U-ABORT sent */ +/* If !=0 then S-P-ABORT sent */ +/* Return: */ +/* SD_SUCCESS (0) if abort successful */ +/* error code otherwise */ +/************************************************************************/ + ST_RET cosp_send_abort (ACSE_CONN *con, ST_INT err_code) +{ +ST_RET ret; +char spdu_buf [COSP_P_AB_SPDU_LEN]; +ST_UINT spdu_len; +char *spdu_ptr; + + if (err_code != 0) + { + /* encode S-P-ABORT (error code will be encoded and we supply encoding buffer) */ + spdu_len = sizeof (spdu_buf); + spdu_ptr = spdu_buf; + if ((ret = cosp_enc_p_ab (spdu_ptr, err_code)) == SD_SUCCESS) + { + if (tp4_data (con->tp4_conn_id, SD_TRUE, spdu_len, spdu_ptr) != SD_SUCCESS) + { + ret = COSP_ERR_TP4_RET; + COSP_LOG_ERR1 ("COSP-ERROR: S-P-ABORT acse_conn_id=0x%08X: T-DATA.req failed.", + con); + } + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: S-P-ABORT acse_conn_id=0x%08X: Encoding of P-ABORT SPDU failed.", + con); + } + } + else + { + /* encode S-U-ABORT (user data should be already encoded) */ + if ((ret = cosp_enc_u_ab (con, &spdu_ptr, &spdu_len)) == SD_SUCCESS) + { + if (tp4_data (con->tp4_conn_id, SD_TRUE, spdu_len, spdu_ptr) != SD_SUCCESS) + { + ret = COSP_ERR_TP4_RET; + COSP_LOG_ERR1 ("COSP-ERROR: S-U-ABORT.req acse_conn_id=0x%08X: T-DATA.req failed.", + con); + } + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: S-U-ABORT.req acse_conn_id=0x%08X: Encoding of U-ABORT SPDU failed.", + con); + } + } + + return (ret); +} + + + /*======================================================*/ + /* */ + /* D A T A F U N C T I O N S */ + /* */ + /*======================================================*/ + +/************************************************************************/ +/* tp4_data_ind */ +/*----------------------------------------------------------------------*/ +/* Function to process data indication. */ +/* Note that the tp4_data_ind is called when complete SPDU has been */ +/* received, so the eot flag is always SD_TRUE. */ +/* */ +/* Parameters: */ +/* ST_LONG user_conn_id User's connection id for this connect. */ +/* ST_INT eot Indicates if last part of SPDU received.*/ +/* ST_UINT data_len Length of data. */ +/* char *data Pointer to data buffer. */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +//void called_conn_disconnect(ACSE_CONN *con);//lnk编译删除,原å‰ç½®ç¨‹åºæœªä½¿ç”¨ +ST_VOID tp4_data_ind (ST_LONG user_conn_id, ST_INT eot, + ST_UINT data_len, char *data) +{ +ST_INT ret; +ST_UINT action; +ACSE_CONN *con; + + ret = SD_SUCCESS; + action = 0; + con = (ACSE_CONN *) user_conn_id; + + /* Note: the protocol requires following steps to be taken for invalid*/ + /* incomming-event/state intersection (default: in switch) or */ + /* if the incomming SPDU can't be correctly process: */ + /* - issue S-P-ABORT */ + /* - send an ABORT SPDU */ + /* - start timer */ + /* - wait for T-DISCONNECT or ABORT ACCEPT SPDU */ + + switch (data [0]) /* First byte is SPDU Session Identifier */ + { + + case COSP_SI_CONNECT: + switch (con->cosp_state) + { + case COSP_CSTATE_IDLE_TCON: + /* if we are the transport connection acceptor, process CN */ + if (con->cosp_vtca) + ret = cosp_process_connect (con, data_len, data); + else + action = COSP_T_DISCONNECT; + break; + + case COSP_CSTATE_WAIT_TDISCON_IND: + tp4_session_timer (con->tp4_conn_id, SD_FALSE); /* stop timer */ + action = COSP_T_DISCONNECT; + break; + + default: /* in invalid state */ + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for CONNECT SPDU).", + con, con->cosp_state); + } + break; + + case COSP_SI_FINISH: + switch (con->cosp_state) + { + case COSP_CSTATE_IDLE_TCON: + action = COSP_T_DISCONNECT; + break; + + case COSP_CSTATE_WAIT_DN: /* collision of conn releases */ + con->cosp_vcoll = SD_TRUE; + /* go to next case */ + case COSP_CSTATE_DATA_XFER: + ret = cosp_process_finish (con, data_len, data); + break; + + case COSP_CSTATE_WAIT_TDISCON_IND: + /* we ignore the FINISH SPDU and remain in the same state */ + break; + + default: /* in invalid state */ + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for FINISH SPDU).", + con, con->cosp_state); + } + break; + + case COSP_SI_ACCEPT: + switch (con->cosp_state) + { + case COSP_CSTATE_IDLE_TCON: + action = COSP_T_DISCONNECT; + break; + + case COSP_CSTATE_WAIT_AC: + con->cosp_vcoll = SD_FALSE; + con->cosp_vdnr = SD_FALSE; + ret = cosp_process_accept (con, data_len, data); + break; + + case COSP_CSTATE_WAIT_TDISCON_IND: + /* we ignore the ACCEPT SPDU and remain in the same state */ + break; + + default: /* in invalid state */ + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for ACCEPT SPDU).", + con, con->cosp_state); + } + break; + + case COSP_SI_REFUSE: + switch (con->cosp_state) + { + case COSP_CSTATE_IDLE_TCON: + action = COSP_T_DISCONNECT; + break; + + case COSP_CSTATE_WAIT_AC: + if ((ret = cosp_process_refuse (con, data_len, data)) == SD_SUCCESS) + action = COSP_T_DISCONNECT; + break; + + case COSP_CSTATE_WAIT_TDISCON_IND: + /* we ignore the REFUSE SPDU and remain in the same state */ + break; + + default: /* in invalid state */ + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for REFUSE SPDU).", + con, con->cosp_state); + } + break; + + case COSP_SI_DISCON: + switch (con->cosp_state) + { + case COSP_CSTATE_IDLE_TCON: + action = COSP_T_DISCONNECT; + break; + + case COSP_CSTATE_WAIT_DN: + if ((ret = cosp_process_discon (con, data_len, data)) == SD_SUCCESS) + action = COSP_T_DISCONNECT; + break; + + case COSP_CSTATE_WAIT_REL_RSP: /* collision */ + if (con->cosp_vcoll && con->cosp_vtca) + { + con->cosp_vdnr = SD_TRUE; + ret = cosp_process_discon (con, data_len, data); + /* remain in the same state */ + } + else + { + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Collision flag not set or not a connection acceptor.", + con); + } + break; + + case COSP_CSTATE_WAIT_TDISCON_IND: + /* we ignore the DN SPDU and remain in the same state */ + break; + + default: /* in invalid state */ + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for DISCONNECT SPDU).", + con, con->cosp_state); + } + break; + + case COSP_SI_ABORT: /* !always! disconnect transport */ + /* otherwise we may loop sending ABORTs */ + action = COSP_T_DISCONNECT; + + switch (con->cosp_state) + { + case COSP_CSTATE_IDLE_TCON: + break; + + case COSP_CSTATE_WAIT_AC: + case COSP_CSTATE_WAIT_DN: + case COSP_CSTATE_WAIT_CON_RSP: + case COSP_CSTATE_WAIT_REL_RSP: + case COSP_CSTATE_DATA_XFER: + if ((ret = cosp_process_abort (con, data_len, data)) != SD_SUCCESS) + { + /* even if we failed to decode abort we still will generate S-P-ABORT */ + action |= COSP_S_P_ABORT_IND; + } + break; + + case COSP_CSTATE_WAIT_TDISCON_IND: + tp4_session_timer (con->tp4_conn_id, SD_FALSE); /* stop timer */ + break; + + default: /* in invalid state */ + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for ABORT SPDU).", + con, con->cosp_state); + action |= COSP_S_P_ABORT_IND; + } + break; + + case COSP_SI_AB_ACCEPT: + /* this SPDU may be sent by remote COSP engine even if the */ + /* transport connection is not to be kept */ + + action = COSP_T_DISCONNECT; /* !always! disconnect transport */ + + switch (con->cosp_state) + { + case COSP_CSTATE_IDLE_TCON: + break; + + case COSP_CSTATE_WAIT_TDISCON_IND: + tp4_session_timer (con->tp4_conn_id, SD_FALSE); /* stop timer */ + break; + + default: /* in invalid state */ + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for ABORT ACCEPT SPDU).", + con, con->cosp_state); + /* ABORT ACCEPT can be received only in response to already */ + /* sent ABORT, so we will not send another one here */ + } + break; + +/* case COSP_SI_GIVE_TOKEN: !!! GIVE-TOKEN is concatinated with DATA*/ + case COSP_SI_DATA: /* SPDU and both have the same code=1 */ + switch (con->cosp_state) + { + case COSP_CSTATE_IDLE_TCON: + action = COSP_T_DISCONNECT; + break; + + case COSP_CSTATE_WAIT_DN: + if (con->cosp_vcoll) + { + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for DATA SPDU).", + con, con->cosp_state); + break; + } + /* process the received DATA SPDU and remain in the same state */ + /* go to next case */ + case COSP_CSTATE_DATA_XFER: + ret = cosp_process_data (con, data_len, data); + break; + + case COSP_CSTATE_WAIT_TDISCON_IND: + /* we ignore the DATA SPDU and remain in the same state */ + break; + + default: /* in invalid state */ + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for DATA SPDU).", + con, con->cosp_state); + } + break; + + default: + ret = COSP_ERR_DEC_INV_SPDU; + COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Unsupported SPDU SI code=%d received.", + con, (ST_INT)(data [0])); + action = COSP_S_P_ABORT_IND | COSP_SEND_ABORT_SPDU; + } /* end of switch */ + + tp4_reldata (data); /* we are done with the TP4 data buffer */ + + if (ret != SD_SUCCESS) + { + /* if error occurred and SPDU other then an ABORT or ABORT ACCEPT */ + /* received then issue S-P-ABORT and SEND an ABORT SPDU. */ + + if ((data [0] != COSP_SI_ABORT) && (data [0] != COSP_SI_AB_ACCEPT)) + action = COSP_S_P_ABORT_IND | COSP_SEND_ABORT_SPDU; + } + + /*--------------------------------------------------------------------*/ + /* abort/disconnect if processing of received SPDU failed or this is */ + /* the protocol specification */ + /*--------------------------------------------------------------------*/ + + if (action & COSP_SEND_ABORT_SPDU) + { + /* encode and send ABORT SPDU to remote SS-user, ret is the error code */ + if (cosp_send_abort (con, ret) == SD_SUCCESS) + { + con->cosp_state = COSP_CSTATE_WAIT_TDISCON_IND; + tp4_session_timer (con->tp4_conn_id, SD_TRUE); /* start timer */ + } + else + { + con->cosp_state = COSP_CSTATE_IDLE; + action |= COSP_T_DISCONNECT; /* disconnect if we can't abort */ + } + } + + if (action & COSP_S_P_ABORT_IND) + { + /* issue S-P-ABORT.ind to local SS-user (use code from cosp_usr.h) */ + + COSP_LOG_DEC3 ("S-P-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d", + con, con->user_conn_id, (ST_INT) COSP_P_AB_IND_PROT_ERR); + + u_cosp_p_abort_ind (con, COSP_P_AB_IND_PROT_ERR); + } + + if (action & COSP_T_DISCONNECT) + { + tp4_disconnect (con->tp4_conn_id, 0, NULL); + /*renxiaobao20220831 °²È«¼ì²â*/ + //called_conn_disconnect(con);//lnk编译删除,原å‰ç½®ç¨‹åºæœªä½¿ç”¨ + + acse_free_con (con); /* we are disconnected, free con struct */ + } +} + + +/************************************************************************/ +/* tp4_expdata_ind */ +/*----------------------------------------------------------------------*/ +/* Function to process a expedited S-DATA.ind. */ +/* */ +/* Parameters: */ +/* ST_LONG user_conn_id User's connection id for this connect. */ +/* ST_UINT data_len Length of data. */ +/* char *data Pointer to data buffer. */ +/* */ +/* Return: */ +/* ST_VOID */ +/************************************************************************/ +ST_VOID tp4_expdata_ind (ST_LONG user_conn_id, ST_UINT data_len, char *data) +{ + /* Treat like normal data. Assume "eot" = 1 */ + tp4_data_ind (user_conn_id, 1, data_len, data); +} + + +/************************************************************************/ +/* cosp_data_req */ +/*----------------------------------------------------------------------*/ +/* Function called by SS-user to transfer normal data on a previously */ +/* established connection. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to connection info */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET cosp_data_req (ACSE_CONN *con) +{ +ST_INT ret; +ST_UINT spdu_len; +char *spdu_ptr; + + COSP_LOG_ENC2 ("S-DATA.req: acse_conn_id =0x%08X user_conn_id =%4ld", + con, con->user_conn_id); + COSP_LOG_ENCC1 ("User data length: %d", con->ppdu_len); + COSP_LOG_ENCH (con->ppdu_len, con->ppdu_ptr); + + ret = SD_SUCCESS; + + if ((con->cosp_state == COSP_CSTATE_DATA_XFER) || + (con->cosp_state == COSP_CSTATE_WAIT_REL_RSP && !con->cosp_vcoll)) + { + if ((ret = cosp_enc_dt (con, &spdu_ptr, &spdu_len)) == SD_SUCCESS) + { + if (tp4_data (con->tp4_conn_id, SD_TRUE, spdu_len, spdu_ptr) != SD_SUCCESS) + { + ret = COSP_ERR_TP4_RET; + COSP_LOG_ERR0 ("COSP-ERROR: S-DATA.req acse_conn_id=0x%08X: T-DATA.req failed."); + } + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: S-DATA.req acse_conn_id=0x%08X: Encoding of DATA SPDU failed.", + con); + } + } + else + { + ret = COSP_ERR_INV_CON_STATE; + COSP_LOG_ERR2 ("COSP-ERROR: S-DATA.req acse_conn_id=0x%08X: Invalid state=%d (or collision flag set).", + con, con->cosp_state); + } + + return (ret); +} + + + /*======================================================*/ + /* */ + /* L O C A L S P D U P R O C E S S I N G F U N C */ + /* */ + /*======================================================*/ + + +/************************************************************************/ +/* cosp_process_connect */ +/*----------------------------------------------------------------------*/ +/* This function will decode the CONNECT SPDU and call SS-user's funct */ +/* u_cosp_con_ind to indicate to the SS-user incomming connection req. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to con info struct */ +/* ST_UINT spdu_len Length of SPDU */ +/* char *spdu_buf Pointer to SPDU buffer */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +static ST_RET cosp_process_connect (ACSE_CONN *con, ST_UINT spdu_len, + char *spdu_buf) +{ +ST_INT ret; +COSP_CN_AC dec_par; /* decoded connection params */ +ST_LONG cosp_user_bind_id; + + /*----------------------------*/ + /* decode the CONNECT SPDU */ + /*----------------------------*/ + + ret = cosp_dec_cn_ac (&dec_par, spdu_buf, spdu_len, COSP_SI_CONNECT); + if (ret == SD_SUCCESS) + { + /* Save SSELs in ACSE_CONN struct. */ + memcpy (con->loc_ssel, dec_par.loc_ssel, dec_par.loc_ssel [0]+1); + memcpy (con->rem_ssel, dec_par.rem_ssel, dec_par.rem_ssel [0]+1); + + /* generate S-CONNECT.ind to the SS-user */ + + con->cosp_state = COSP_CSTATE_WAIT_CON_RSP; + con->ppdu_len = dec_par.udata_len; + con->ppdu_ptr = dec_par.udata_ptr; + + /* user_conn_id (created by ACSE-user) is invalid at this point, */ + /* we probably should set it to -1 (an invalid value). Note that 0 */ + /* is a valid id. */ + con->user_conn_id = -1L; + + cosp_user_bind_id = con->cosp_bind_id; /* COSP id = COSP User's bind id */ + + COSP_LOG_DEC1 ("S-CONNECT.ind: acse_conn_id =0x%08X", con); + COSP_LOG_DECC1 ("User data length: %d", con->ppdu_len); + COSP_LOG_DECH (con->ppdu_len, con->ppdu_ptr); + + u_cosp_con_ind (cosp_user_bind_id, con); + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Decoding of CONNECT SPDU failed.", + con); + } + + return (ret); +} + + +/************************************************************************/ +/* cosp_process_finish */ +/*----------------------------------------------------------------------*/ +/* This function will decode the FINISH SPDU and call SS-user's function*/ +/* u_cosp_rel_ind to indicate to the SS-user that the remote wants to */ +/* release connection. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to con info struct */ +/* ST_UINT spdu_len Length of SPDU */ +/* char *spdu_buf Pointer to SPDU buffer */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +static ST_RET cosp_process_finish (ACSE_CONN *con, ST_UINT spdu_len, + char *spdu_buf) +{ +ST_INT ret; +COSP_FN_DN dec_par; /* decoded con rel params */ + + /*------------------------------------*/ + /* decode and check the FINISH SPDU */ + /*------------------------------------*/ + + ret = cosp_dec_fn_dn (&dec_par, spdu_buf, spdu_len, COSP_SI_FINISH); + if (ret == SD_SUCCESS) + { + /* generate S-RELEASE.ind */ + + con->cosp_state = COSP_CSTATE_WAIT_REL_RSP; + con->ppdu_len = dec_par.udata_len; + con->ppdu_ptr = dec_par.udata_ptr; + + COSP_LOG_DEC2 ("S-RELEASE.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + con, con->user_conn_id); + COSP_LOG_DECC1 ("User data length: %d", con->ppdu_len); + COSP_LOG_DECH (con->ppdu_len, con->ppdu_ptr); + + u_cosp_rel_ind (con); + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Decoding of FINISH SPDU failed.", + con); + } + + return (ret); +} + + +/************************************************************************/ +/* cosp_process_accept */ +/*----------------------------------------------------------------------*/ +/* This function will decode the ACCEPT SPDU and call SS-user's funct */ +/* u_cosp_con_cnf_pos to indicate to the SS-user that the connection has*/ +/* been established. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to con info struct */ +/* ST_UINT spdu_len Length of SPDU */ +/* char *spdu_buf Pointer to SPDU buffer */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +static ST_RET cosp_process_accept (ACSE_CONN *con, ST_UINT spdu_len, + char *spdu_buf) +{ +ST_INT ret; +COSP_CN_AC dec_par; /* decoded accept params */ + + /*----------------------------------*/ + /* decode and check the ACCEPT SPDU */ + /*----------------------------------*/ + + ret = cosp_dec_cn_ac (&dec_par, spdu_buf, spdu_len, COSP_SI_ACCEPT); + if (ret == SD_SUCCESS) + { + /* generate S-CONNECT.cnf+ */ + + con->cosp_state = COSP_CSTATE_DATA_XFER; + con->ppdu_len = dec_par.udata_len; + con->ppdu_ptr = dec_par.udata_ptr; + + COSP_LOG_DEC2 ("S-CONNECT.cnf+: acse_conn_id =0x%08X user_conn_id =%4ld", + con, con->user_conn_id); + COSP_LOG_DECC1 ("User data length: %d", con->ppdu_len); + COSP_LOG_DECH (con->ppdu_len, con->ppdu_ptr); + + u_cosp_con_cnf_pos (con); + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Decoding of ACCEPT SPDU failed.", + con); + } + + return (ret); +} + + +/************************************************************************/ +/* cosp_process_refuse */ +/*----------------------------------------------------------------------*/ +/* This function will decode the REFUSE SPDU and call SS-user's function*/ +/* u_cosp_con_cnf_neg to indicate to the SS-user that the establishment */ +/* of connection failed. */ +/* Note that this implementation will not reuse the transport connection*/ +/* for another session connect (transport will be disconnected). */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to con info struct */ +/* ST_UINT spdu_len Length of SPDU */ +/* char *spdu_buf Pointer to SPDU buffer */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +static ST_RET cosp_process_refuse (ACSE_CONN *con, ST_UINT spdu_len, + char *spdu_buf) +{ +ST_INT ret; +COSP_RF dec_par; /* decoded refuse connection params */ +ST_INT result; +ST_INT reason; + + /*----------------------------------*/ + /* decode and check the REFUSE SPDU */ + /*----------------------------------*/ + + ret = cosp_dec_rf (&dec_par, spdu_buf, spdu_len); + if (ret == SD_SUCCESS) + { + con->cosp_state = COSP_CSTATE_IDLE; + + /* generate S-CONNECT.cnf- */ + + if (dec_par.reason <= 2) + result = COSP_CON_CNF_U_REJECT; /* remote SS-user reject */ + else + result = COSP_CON_CNF_P_REJECT; /* remote SS-provider reject */ + + /* convert the reason code from SPDU to reason codes in cosp_usr.h */ + switch ((ST_UINT) dec_par.reason) + { + case 0: /* rejection by called SS-user??, reason not specified */ + reason = COSP_CON_CNF_U_NOT_SPECIFIED; + break; + + case 1: /* rejection by called SS-user, tmp congestion */ + reason = COSP_CON_CNF_U_CONGESTION; + break; + + case 2: /* rejection by called SS-user, user data may follow */ + reason = COSP_CON_CNF_U_IN_UDATA; + con->ppdu_len = dec_par.udata_len; + con->ppdu_ptr = dec_par.udata_ptr; + break; + + case 128+1: /* rejection by called SS-prov, SSEL unknown */ + reason = COSP_CON_CNF_P_INV_SSEL; + break; + + case 128+2: /* rejection by called SS-prov, SS-user not attached */ + reason = COSP_CON_CNF_P_NOT_ATTACHED; + break; + + case 128+3: /* rejection by called SS-prov, congestion */ + reason = COSP_CON_CNF_P_CONGESTION; + break; + + case 128+4: /* rejection by called SS-prov, prot version not supported */ + case 128+5: /* rejection by called SS-prov, reason not specified */ + case 128+6: /* rejection by called SS-prov, implementation restriction stated in PICS */ + default: + reason = COSP_CON_CNF_P_NOT_SPECIFIED; + } /* end of switch */ + + COSP_LOG_DEC4 ("S-CONNECT.cnf-: acse_conn_id =0x%08X user_conn_id =%4ld result =%d reason =%d", + con, con->user_conn_id, result, reason); + COSP_LOG_DECC1 ("User data length: %d", con->ppdu_len); + COSP_LOG_DECH (con->ppdu_len, con->ppdu_ptr); + + /* S-CONNECT.cnf- */ + u_cosp_con_cnf_neg (con, result, reason); + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Decoding of REFUSE SPDU failed.", + con); + } + + return (ret); +} + + +/************************************************************************/ +/* cosp_process_discon */ +/*----------------------------------------------------------------------*/ +/* This function will decode the DN SPDU and call SS-user's function */ +/* u_cosp_rel_cnf_pos to indicate to the SS-user the result of session */ +/* release request. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to con info struct */ +/* ST_UINT spdu_len Length of SPDU */ +/* char *spdu_buf Pointer to SPDU buffer */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +static ST_RET cosp_process_discon (ACSE_CONN *con, ST_UINT spdu_len, + char *spdu_buf) +{ +ST_INT ret; +COSP_FN_DN dec_par; /* decoded con rel params */ + + /*------------------------------------*/ + /* decode and check the DN SPDU */ + /*------------------------------------*/ + + ret = cosp_dec_fn_dn (&dec_par, spdu_buf, spdu_len, COSP_SI_DISCON); + if (ret == SD_SUCCESS) + { + /* do not change here the state, new state depends on previous */ + /* state and if collision of S-RELEASEs occurred. */ + + /* generate S-RELEASE.cnf+ */ + + con->ppdu_len = dec_par.udata_len; + con->ppdu_ptr = dec_par.udata_ptr; + + COSP_LOG_DEC2 ("S-RELEASE.cnf+: acse_conn_id =0x%08X user_conn_id =%4ld", + con, con->user_conn_id); + COSP_LOG_DECC1 ("User data length: %d", con->ppdu_len); + COSP_LOG_DECH (con->ppdu_len, con->ppdu_ptr); + + u_cosp_rel_cnf_pos (con); /* currently only positive cnf possible */ + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Decoding of DISCONNECT SPDU failed.", + con); + } + + return (ret); +} + + +/************************************************************************/ +/* cosp_process_abort */ +/*----------------------------------------------------------------------*/ +/* This function will decode the ABORT SPDU and call SS-user's function */ +/* u_cosp_abort_ind to indicate to the SS-user that the session */ +/* connection has been aborted by remote. */ +/* Note that this implementation will not reuse the transport connection*/ +/* for another session connect (transport will be disconnected). */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to con info struct */ +/* ST_UINT spdu_len Length of SPDU */ +/* char *spdu_buf Pointer to SPDU buffer */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +static ST_RET cosp_process_abort (ACSE_CONN *con, ST_UINT spdu_len, + char *spdu_buf) +{ +ST_INT ret; +COSP_AB dec_par; /* decoded abort connection params */ +ST_INT reason; +ST_INT err_code; + + /*------------------------------------*/ + /* decode and check the ABORT SPDU */ + /*------------------------------------*/ + + ret = cosp_dec_ab (&dec_par, spdu_buf, spdu_len); + if (ret == SD_SUCCESS) + { + con->cosp_state = COSP_CSTATE_IDLE; + + /* generate S-U-ABORT.ind or S-P-ABORT.ind */ + + if (dec_par.reason & COSP_AB_REASON_USER_ABORT) + { + /* remote SS-user abort */ + con->ppdu_len = dec_par.udata_len; + con->ppdu_ptr = dec_par.udata_ptr; + + COSP_LOG_DEC2 ("S-U-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + con, con->user_conn_id); + COSP_LOG_DECC1 ("User data length: %d", con->ppdu_len); + COSP_LOG_DECH (con->ppdu_len, con->ppdu_ptr); + + u_cosp_u_abort_ind (con); + } + else + { + /* SS-provider abort */ + if (dec_par.reason & COSP_AB_REASON_PROT_ERROR) + { + reason = COSP_P_AB_IND_PROT_ERR; + err_code = 0; + + /* Log the ABORT error code */ + if (dec_par.reflect_par_len == 2) + err_code = ((ST_UINT16) dec_par.reflect_par [0] << 8) + + (ST_UINT16) dec_par.reflect_par [1]; + + COSP_LOG_DEC4 ("S-P-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d err_code =0x%04X", + con, con->user_conn_id, reason, err_code); + } + else + { + reason = COSP_P_AB_IND_UNDEFINED; + + COSP_LOG_DEC3 ("S-P-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d", + con, con->user_conn_id, reason); + } + + u_cosp_p_abort_ind (con, reason); + } + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Decoding of ABORT SPDU failed.", + con); + } + + return (ret); +} + + +/************************************************************************/ +/* cosp_process_data */ +/*----------------------------------------------------------------------*/ +/* This function will decode a DATA SPDU and generate a S-DATA.ind. */ +/* */ +/* Parameters: */ +/* ACSE_CONN *con Pointer to con info struct */ +/* ST_UINT spdu_len Length of SPDU */ +/* char *spdu_buf Pointer to SPDU buffer */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code otherwise */ +/************************************************************************/ +static ST_RET cosp_process_data (ACSE_CONN *con, ST_UINT spdu_len, + char *spdu_buf) +{ +ST_INT ret; +COSP_DT dec_par; /* decoded refuse connection params */ + + /*------------------------------------*/ + /* decode and check the DATA SPDU */ + /*------------------------------------*/ + ret = cosp_dec_dt (&dec_par, spdu_buf, spdu_len); + if (ret == SD_SUCCESS) + { + /* generate S-DATA.ind */ + con->ppdu_len = dec_par.udata_len; + con->ppdu_ptr = dec_par.udata_ptr; + + COSP_LOG_DEC2 ("S-DATA.ind: acse_conn_id =0x%08X user_conn_id =%4ld", + con, con->user_conn_id); + COSP_LOG_DECC1 ("User data length: %d", con->ppdu_len); + COSP_LOG_DECH (con->ppdu_len, con->ppdu_ptr); + + u_cosp_data_ind (con); + } + else + { + COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Decoding of DATA SPDU failed.", + con); + } + + return (ret); +} + + + diff --git a/mmslib/ositcps/lean_cfg.c b/mmslib/ositcps/lean_cfg.c new file mode 100644 index 0000000..22611e2 --- /dev/null +++ b/mmslib/ositcps/lean_cfg.c @@ -0,0 +1,1271 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2002 All Rights Reserved */ +/* */ +/* MODULE NAME : lean_cfg.c */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module implements parsing of the Lean-T Stack */ +/* configuration file. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/27/02 JRB 28 Add tp0_sock.h. */ +/* 06/20/02 JRB 27 Chg to use new netAddr union in PRES_ADDR. */ +/* 07/17/00 JRB 26 Set DriverID only if TP4_ENABLED defined. */ +/* 06/15/00 JRB 25 Set DriverID only if MOSI defined. */ +/* 05/02/00 JRB 24 Added DriverID for WIN32. */ +/* 01/25/00 MDE 23 Fixed compile problem for DEBUG version */ +/* 12/10/99 JRB 22 Fix save_dib_table when AP Title or AE Qual */ +/* NOT CONFIGURED or AP Title parse fails. */ +/* Fix parseObjId for invalid data. */ +/* 06/08/99 JRB 21 Chg max_num_conns to ST_UINT16. */ +/* 09/18/98 JRB 20 Del all logging cfg. Use "log_cfg.c" instead.*/ +/* 08/13/98 JRB 19 Lint cleanup. */ +/* 08/06/98 JRB 18 Use new cfg_get_octet_string function & */ +/* delete parseSelector. */ +/* 06/19/98 JRB 17 Allow TP_TYPE_TPX for multiple stack support.*/ +/* 03/11/98 JRB 16 Del "max_spdu_length" param from tp4c_kwtbl..*/ +/* Add "rfc1006_keepalive" param to tp4c_kwtbl..*/ +/* 02/16/98 JRB 15 Clean up some #ifs. */ +/* 08/26/97 JRB 14 RFC1006 changes: */ +/* - Use new DIB_ENTRY with embedded PRES_ADDR. */ +/* - Include "lean_a.h" instead of "suicacse.h" */ +/* - Add "rfc1006_*" params to "tp4c_kwtbl". */ +/* - Add "tranport", "ip_addr" to "dibc_kwtbl.."*/ +/* - If !TP4_ENABLED, ignore TP4/CLNP config */ +/* - If TP0_ENABLED, save TP0 config */ +/* - parseSelector: chg arg back to (ST_INT *) */ +/* - parseSelector: don't ignore maxSelLen arg */ +/* - parseObjId: add default "return" statement.*/ +/* 07/09/97 JRB 13 Deleted obsolete clnp_err.h include. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 03/03/97 EJV 12 Removed CLNP_LOG_ALWAYS */ +/* 11/19/96 MDE 11 Now handle 0 dib entries w/o mem error */ +/* 11/13/96 JRB 10 Don't init globals unless they are constant. */ +/* 10/04/96 JRB 09 Add ak_delay to TP4 config. */ +/* 10/04/96 JRB 08 Chg parseSelector arg to (ST_INT16 *). */ +/* 10/04/96 JRB 07 Chg funct name to "save_loc_rem_dib_tables" */ +/* and modify for reconfig. */ +/* 10/04/96 JRB 06 Add init_dirser_called flag for reconfig. */ +/* 10/04/96 JRB 05 If MCGW defined, don't config TP4, and add */ +/* adlcAddr to DIB config. */ +/* 09/04/96 EJV 04 Fixed keyword table (_ENC_ instead of _END_) */ +/* 07/24/96 EJV 03 Combined CLNP, TP4 and DIB configuration */ +/* files into one. */ +/* 07/22/96 JRB 02 Fixed up names, etc. for Lean-T. */ +/* 07/22/96 MDE 01 Created from rs_cfg.c */ +/************************************************************************/ +#ifdef DEBUG_SISCO +static char *thisFileName = __FILE__; +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "gen_list.h" +#include "cfg_util.h" +#include "cfglog.h" + + +#if defined (MCGW) +/* For the MCGW, the following global variables and function names */ +/* are renamed by macro so they don't conflict with names in OSI SUIC. */ +#define num_loc_dib_entries num_loc_dib_entries_clt7 +#define num_rem_dib_entries num_rem_dib_entries_clt7 +#define loc_dib_table loc_dib_table_clt7 +#define rem_dib_table rem_dib_table_clt7 +#define init_dirser init_dirser_clt7 +#endif /* defined (MCGW) */ + +#include "clnp_usr.h" +#include "tp4api.h" +#include "tp0_sock.h" /* portable "sockets" interface */ +#include "lean_a.h" /* DIB_ENTRY definition. */ +#include "acse2log.h" + +#if defined (_WIN32) +#include "ethsub.h" +#endif + +/************************************************************************/ +/* Local variables in this module */ +/************************************************************************/ + +static ST_CHAR *cfg_file_name = "lean.cfg"; +static ST_BOOLEAN init_dirser_called; + +static ST_RET save_loc_rem_dib_tables (void); + +/*----------------------------------------------------------------------*/ +/* Base configuration keyword table for major sections in cfg file. */ +/* Functions and keyword tables related to parsing specific section */ +/* are defined in respective part of this module. */ +/*----------------------------------------------------------------------*/ +static void clnpc_begin (void); +static void tp4c_begin (void); +static void dibc_begin (void); + +static CFG_KW_EL cfg_base_kwtbl [] = + { + {"%Clnp_Begin", clnpc_begin, NULL }, +#if !defined (MCGW) + { "%Tp4_Begin", tp4c_begin, NULL }, +#endif /* !defined (MCGW) */ + { "%Dib_Begin", dibc_begin, NULL }, + { NULL, NULL, NULL} + }; + +/************************************************************************/ +/* init_dirser */ +/*----------------------------------------------------------------------*/ +/* This function will initialize the LEAN-T Stack parameters from */ +/* configuration file. */ +/* */ +/* Parameters: */ +/* ST_VOID none */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if configuration successful */ +/* SD_FAILURE (1) otherwise */ +/************************************************************************/ + +ST_RET init_dirser (ST_VOID) + { +ST_RET ret; + + ret = SD_FAILURE; + + /* This function will initialize the state table for reading the */ + /* configuration file and parse the file until EOF or end flag is set */ + + /* Read the configuration file */ + ret = cfg_process_file (cfg_file_name, cfg_base_kwtbl); + + if (ret == SD_SUCCESS) + { + save_loc_rem_dib_tables (); + } + else + { + ST_UINT cfg_log_mask_save = cfg_log_mask; + + /* parsing cfg file failed, turn on cfg logging and parse file again */ + cfg_log_mask = CFG_LOG_ERR | CFG_LOG_FLOW; + cfg_process_file (cfg_file_name, cfg_base_kwtbl); + cfg_log_mask = cfg_log_mask_save; + } + + /* Set flag to prevent reconfiguring of critical parameters. */ + init_dirser_called = SD_TRUE; + return (ret); + } + + +/*======================================================================*/ +/************************************************************************/ +/*======================================================================*/ +/* */ +/* Functions and keyword tables for parsing the CLNP section */ +/* from configuration file. */ +/* */ +/*======================================================================*/ +/************************************************************************/ +/*======================================================================*/ + +#if defined(_WIN32) && defined(MOSI) && defined(TP4_ENABLED) +static void clnpc_driverid (void); +#endif +static void clnpc_lifetime (void); +static void clnpc_lifetime_dec (void); +static void clnpc_cfg_timer (void); +static void clnpc_esh_delay (void); +static void clnpc_loc_mac (void); +static void clnpc_loc_nsap (void); + +static void clnpc_end (void); + + +/* CLNP section keyword tables */ + +static CFG_KW_EL clnpc_kwtbl [] = + { +#if defined(_WIN32) && defined(MOSI) && defined(TP4_ENABLED) + {"DriverID", clnpc_driverid, NULL }, +#endif + {"Lifetime", clnpc_lifetime, NULL }, + {"Lifetime_Decrement", clnpc_lifetime_dec, NULL }, + {"Cfg_Timer", clnpc_cfg_timer, NULL }, + {"Esh_Delay", clnpc_esh_delay, NULL }, + {"Local_MAC", clnpc_loc_mac, NULL }, + {"Local_NSAP", clnpc_loc_nsap, NULL }, + {"%Clnp_End", clnpc_end, NULL }, + { NULL, NULL, NULL} + }; + +/*----------------------------------------------------------------------*/ +/* clnpc_begin */ +/* keyword '%Clnp_Begin' */ +/*----------------------------------------------------------------------*/ +static void clnpc_begin (void) + { + if (cfg_tbl_push (clnpc_kwtbl) != SD_SUCCESS) + cfg_set_config_err (); + } + +/*----------------------------------------------------------------------*/ +/* clnpc_end */ +/* keyword '%Clnp_End' */ +/*----------------------------------------------------------------------*/ +static void clnpc_end (void) + { + if (cfg_tbl_pop (1) != SD_SUCCESS) + cfg_set_config_err (); + } + +#if defined(_WIN32) && defined(MOSI) && defined(TP4_ENABLED) +/*----------------------------------------------------------------------*/ +/* clnpc_driverid */ +/* keyword 'driverid' */ +/*----------------------------------------------------------------------*/ +static void clnpc_driverid (void) + { +ST_INT iVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_int (&iVal) == SD_SUCCESS) + { + DriverID = iVal; + } + else + cfg_set_config_err(); + } +#endif /* _WIN32 && MOSI && TP4_ENALBED */ + +/*----------------------------------------------------------------------*/ +/* clnpc_lifetime */ +/* keyword 'Lifetime' */ +/*----------------------------------------------------------------------*/ +static void clnpc_lifetime (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ + clnp_param.pdu_lifetime = (ST_UCHAR) sVal; +#endif /* TP4_ENABLED */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* clnpc_lifetime_dec */ +/* keyword 'Lifetime_Decrement' */ +/*----------------------------------------------------------------------*/ +static void clnpc_lifetime_dec (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ + clnp_param.pdu_lifetime_dec = (ST_UCHAR) sVal; +#endif /* TP4_ENABLED */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* clnpc_cfg_timer */ +/* keyword 'Cfg_Timer' */ +/*----------------------------------------------------------------------*/ +static void clnpc_cfg_timer (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ + clnp_param.esh_cfg_timer = sVal; +#endif /* TP4_ENABLED */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* clnpc_esh_delay */ +/* keyword 'Esh_Delay' */ +/*----------------------------------------------------------------------*/ +static void clnpc_esh_delay (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ + clnp_param.esh_delay = sVal; +#endif /* TP4_ENABLED */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* clnpc_loc_mac */ +/* keyword 'Local_MAC' */ +/*----------------------------------------------------------------------*/ +static void clnpc_loc_mac (void) + { +#if defined (TP4_ENABLED) +ST_UINT mac_len; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_octet_string (clnp_param.loc_mac, &mac_len, CLNP_MAX_LEN_MAC)) + cfg_set_config_err(); +#else /* !TP4_ENABLED */ + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ +#endif /* !TP4_ENABLED */ + } + +/*----------------------------------------------------------------------*/ +/* clnpc_loc_nsap */ +/* keyword 'Local_NSAP' */ +/*----------------------------------------------------------------------*/ +static void clnpc_loc_nsap (void) + { +#if defined (TP4_ENABLED) +ST_UINT nsap_len; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_octet_string (&clnp_param.loc_nsap[1], &nsap_len, CLNP_MAX_LEN_NSAP) + == SD_SUCCESS) + { + if (nsap_len > 0) + clnp_param.loc_nsap[0] = (ST_UCHAR) nsap_len; + } + else + cfg_set_config_err(); +#else /* !TP4_ENABLED */ + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ +#endif /* !TP4_ENABLED */ + } + + +#if !defined (MCGW) +/*======================================================================*/ +/************************************************************************/ +/*======================================================================*/ +/* */ +/* Functions and keyword tables for parsing the TP4 section */ +/* from configuration file. */ +/* */ +/*======================================================================*/ +/************************************************************************/ +/*======================================================================*/ + +static void tp4c_end (void); + +static void tp4c_max_tpdu_len (void); +static void tp4c_max_rem_cdt (void); +static void tp4c_loc_cdt (void); +static void tp4c_max_num_conns (void); +static void tp4c_max_spdu_outst (void); +static void tp4c_window_time (void); +static void tp4c_inact_time (void); +static void tp4c_retrans_time (void); +static void tp4c_max_trans (void); +static void tp4c_ak_delay (void); + +static void rfc1006_max_tpdu_len (void); +static void rfc1006_max_num_conns (void); +static void rfc1006_keepalive (void); + +/* TP4 section keyword tables */ + +static CFG_KW_EL tp4c_kwtbl [] = + { + {"Max_Tpdu_Length", tp4c_max_tpdu_len, NULL }, + {"Max_Remote_Cdt", tp4c_max_rem_cdt, NULL }, + {"Local_Cdt", tp4c_loc_cdt, NULL }, + {"Max_Num_Connections", tp4c_max_num_conns, NULL }, + {"Max_Spdu_Outstanding", tp4c_max_spdu_outst, NULL }, + {"Window_Time", tp4c_window_time, NULL }, + {"Inactivity_Time", tp4c_inact_time, NULL }, + {"Retransmission_Time", tp4c_retrans_time, NULL }, + {"Max_Transmissions", tp4c_max_trans, NULL }, + {"ak_delay", tp4c_ak_delay, NULL }, + {"RFC1006_Max_Tpdu_Len", rfc1006_max_tpdu_len, NULL }, + {"RFC1006_Max_Num_Conns", rfc1006_max_num_conns, NULL }, + {"rfc1006_keepalive", rfc1006_keepalive, NULL }, + {"%Tp4_End", tp4c_end, NULL }, + { NULL, NULL, NULL} + }; + +/*----------------------------------------------------------------------*/ +/* tp4c_begin */ +/* keyword '%Tp4_Begin' */ +/*----------------------------------------------------------------------*/ +static void tp4c_begin (void) + { + if (cfg_tbl_push (tp4c_kwtbl) != SD_SUCCESS) + cfg_set_config_err (); + } + +/*----------------------------------------------------------------------*/ +/* tp4c_end */ +/* keyword '%Tp4_End' */ +/*----------------------------------------------------------------------*/ +static void tp4c_end (void) + { + if (cfg_tbl_pop (1) != SD_SUCCESS) + cfg_set_config_err (); + } + +/*----------------------------------------------------------------------*/ +/* tp4c_max_tpdu_len */ +/* keyword 'Max_Tpdu_Length' */ +/*----------------------------------------------------------------------*/ +static void tp4c_max_tpdu_len (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ + tp_cfg.max_tpdu_len = sVal; +#endif /* TP4_ENABLED */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* tp4c_max_rem_cdt */ +/* keyword 'Max_Remote_Cdt' */ +/*----------------------------------------------------------------------*/ +static void tp4c_max_rem_cdt (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ + tp_cfg.max_rem_cdt = (ST_UCHAR) sVal; +#endif /* TP4_ENABLED */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* tp4c_loc_cdt */ +/* keyword 'Local_Cdt' */ +/*----------------------------------------------------------------------*/ +static void tp4c_loc_cdt (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ + tp_cfg.loc_cdt = (ST_UCHAR) sVal; +#endif /* TP4_ENABLED */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* tp4c_max_num_conns */ +/* keyword 'Max_Num_Connections' */ +/*----------------------------------------------------------------------*/ +static void tp4c_max_num_conns (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ + tp_cfg.max_num_conns = sVal; +#endif /* TP4_ENABLED */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* tp4c_max_spdu_outst */ +/* keyword 'Max_Spdu_Outstanding' */ +/*----------------------------------------------------------------------*/ +static void tp4c_max_spdu_outst (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ + tp_cfg.max_spdu_outst = (ST_UCHAR) sVal; +#endif /* TP4_ENABLED */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* tp4c_window_time */ +/* keyword 'Window_Time' */ +/*----------------------------------------------------------------------*/ +static void tp4c_window_time (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ + tp_cfg.window_time = sVal; +#endif /* TP4_ENABLED */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* tp4c_inact_time */ +/* keyword 'Inactivity_Time' */ +/*----------------------------------------------------------------------*/ +static void tp4c_inact_time (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ + tp_cfg.inact_time = sVal; +#endif /* TP4_ENABLED */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* tp4c_retrans_time */ +/* keyword 'Retransmission_Time' */ +/*----------------------------------------------------------------------*/ +static void tp4c_retrans_time (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ + tp_cfg.retrans_time = sVal; +#endif /* TP4_ENABLED */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* tp4c_max_trans */ +/* keyword 'Max_Transmissions' */ +/*----------------------------------------------------------------------*/ +static void tp4c_max_trans (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ + tp_cfg.max_trans = (ST_UCHAR) sVal; +#endif /* TP4_ENABLED */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* tp4c_ak_delay */ +/* keyword 'ak_delay' */ +/*----------------------------------------------------------------------*/ +static void tp4c_ak_delay (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ + tp_cfg.ak_delay = (ST_UCHAR) sVal; +#endif /* TP4_ENABLED */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* rfc1006_max_tpdu_len */ +/* keyword 'RFC1006_Max_Tpdu_Len' */ +/*----------------------------------------------------------------------*/ +static void rfc1006_max_tpdu_len (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP0_ENABLED) /* Just ignore if not enabled. */ + tp0_cfg.max_tpdu_len = sVal; +#endif /* defined (TP0_ENABLED) */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* rfc1006_max_num_conns */ +/* keyword 'RFC1006_Max_Num_Conns' */ +/*----------------------------------------------------------------------*/ +static void rfc1006_max_num_conns (void) + { +ST_UINT16 sVal; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_ushort (&sVal) == SD_SUCCESS) + { +#if defined (TP0_ENABLED) /* Just ignore if not enabled. */ + tp0_cfg.max_num_conns = sVal; +#endif /* defined (TP0_ENABLED) */ + } + else + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +/* rfc1006_keepalive */ +/* keyword 'rfc1006_keepalive' */ +/*----------------------------------------------------------------------*/ +static void rfc1006_keepalive (void) + { +#if defined (TP0_ENABLED) /* Just ignore if not enabled. */ + tp0_cfg.keepalive = SD_TRUE; +#endif /* defined (TP0_ENABLED) */ + } + +#endif /* !defined (MCGW) */ + + +/*======================================================================*/ +/************************************************************************/ +/*======================================================================*/ +/* */ +/* Functions and keyword tables for parsing the Local and */ +/* Remote DIB sections from configuration file. */ +/* */ +/*======================================================================*/ +/************************************************************************/ +/*======================================================================*/ + + +#define CFG_MAX_AR_NAME 64 +#define CFG_MAX_AP_TITLE 80 +#define CFG_MAX_AE_QUAL 32 + +typedef struct _tagTransDevInfo + { + DBL_LNK l; + ST_CHAR name[CFG_MAX_AR_NAME +1]; + ST_CHAR apTitle[CFG_MAX_AP_TITLE +1]; + ST_CHAR aeQual[CFG_MAX_AE_QUAL +1]; + PRES_ADDR pres_addr; + ST_CHAR ip_addr [MAX_IP_ADDR_LEN]; /* Overwrite pres_addr->nsap */ + /* with this if tp_type = TCP */ + } TRANS_DEV_INFO; + +static void dibc_end (void); + +static void dibc_begin_local (void); +static void dibc_begin_remote (void); +static void dibc_common_name (void); +static void dibc_ap_title (void); +static void dibc_ae_qualifier (void); +static void dibc_psel (void); +static void dibc_ssel (void); +static void dibc_tsel (void); +static void dibc_nsap (void); +static void dibc_tp_type (void); +static void dibc_ip_addr (void); +#if defined (MCGW) +static void dibc_adlcaddr (void); +#endif /* defined (MCGW) */ +static void dibc_end_local (void); +static void dibc_end_remote (void); + +static ST_RET parseObjId (MMS_OBJ_ID *o, ST_CHAR *buff); +static ST_VOID save_dib_table (TRANS_DEV_INFO *, DIB_ENTRY *); + + + +static CFG_KW_EL dibc_kwtbl[] = + { + {"Begin_Local", dibc_begin_local, NULL }, + {"Begin_Remote", dibc_begin_remote, NULL }, + {"%Dib_End", dibc_end, NULL }, + { NULL, NULL, NULL} + }; + +static CFG_KW_EL dibc_kwtbl_param[] = + { + {"Common_Name", dibc_common_name, NULL }, + {"AP_Title", dibc_ap_title, NULL }, + {"AE_Qualifier", dibc_ae_qualifier, NULL }, + {"Psel", dibc_psel, NULL }, + {"Ssel", dibc_ssel, NULL }, + {"Tsel", dibc_tsel, NULL }, + {"NSAP", dibc_nsap, NULL }, + {"Transport", dibc_tp_type, NULL }, + {"IP_Addr", dibc_ip_addr, NULL }, +#if defined (MCGW) + {"AdlcAddr", dibc_adlcaddr, NULL }, +#endif /* defined (MCGW) */ + {"End_Local", dibc_end_local, NULL }, + {"End_Remote", dibc_end_remote, NULL }, + { NULL, NULL, NULL} + }; + +static TRANS_DEV_INFO *localTransList; +static TRANS_DEV_INFO *remoteTransList; +static TRANS_DEV_INFO *currTransEl; + +static ST_BOOLEAN rem_section_flag; + +/*----------------------------------------------------------------------*/ +/* dibc_begin */ +/* keyword '%Dib_Begin' */ +/*----------------------------------------------------------------------*/ +static void dibc_begin (void) + { + /* CRITICAL: Always start with empty temporary DIB Table linked lists */ + /* (may be reconfiguring). */ + localTransList = NULL; + remoteTransList = NULL; + + if (cfg_tbl_push (dibc_kwtbl) != SD_SUCCESS) + cfg_set_config_err (); + } + +/*----------------------------------------------------------------------*/ +/* dibc_end */ +/* keyword '%Dib_End' */ +/*----------------------------------------------------------------------*/ +static void dibc_end (void) + { + if (cfg_tbl_pop (1) != SD_SUCCESS) + cfg_set_config_err (); + + cfg_set_endfile_ok (); /* this is the end of configuration */ + } + +/*----------------------------------------------------------------------*/ +/* dibc_begin_local */ +/* keyword 'Begin_Local' */ +/*----------------------------------------------------------------------*/ + +static void dibc_begin_local (void) + { + if (!init_dirser_called) + { /* Don't alloc if reconfiguring. */ + currTransEl = (TRANS_DEV_INFO *) chk_calloc (1, sizeof(TRANS_DEV_INFO)); + currTransEl->pres_addr.tp_type = TP_TYPE_TP4; /* Default=TP4 */ + list_add_last ((void**) &localTransList, currTransEl); + } + + cfg_tbl_push (dibc_kwtbl_param); + } + +/*----------------------------------------------------------------------*/ +/* dibc_begin_remote */ +/* keyword 'Begin_Remote' */ +/*----------------------------------------------------------------------*/ +static void dibc_begin_remote (void) + { + currTransEl = (TRANS_DEV_INFO *) chk_calloc (1, sizeof(TRANS_DEV_INFO)); + currTransEl->pres_addr.tp_type = TP_TYPE_TP4; /* Default=TP4 */ + list_add_last ((void**) &remoteTransList, currTransEl); + cfg_tbl_push (dibc_kwtbl_param); + rem_section_flag = SD_TRUE; + } + +/*----------------------------------------------------------------------*/ +/* Processing of keywords found in one of sub-section: */ +/* Local_Begin ... Local_End */ +/* Remote_Begin ... Remote_End */ +/*----------------------------------------------------------------------*/ + +static void dibc_common_name (void) + { +ST_CHAR *p; + + if (init_dirser_called && rem_section_flag == SD_FALSE) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + p = cfg_get_string_ptr (); + if (!p) + cfg_set_config_err(); + else if (strlen (p) > CFG_MAX_AR_NAME) + cfg_set_config_err(); + else + strcpy (currTransEl->name, p); + } + +/*----------------------------------------------------------------------*/ +static void dibc_ap_title (void) + { +ST_CHAR *p; + + if (init_dirser_called && rem_section_flag == SD_FALSE) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + p = cfg_get_string_ptr (); + if (!p) + cfg_set_config_err(); + else if (strlen (p) > CFG_MAX_AP_TITLE) + cfg_set_config_err(); + else + strcpy (currTransEl->apTitle, p); + } + +/*----------------------------------------------------------------------*/ +static void dibc_ae_qualifier (void) + { +ST_CHAR *p; + + if (init_dirser_called && rem_section_flag == SD_FALSE) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + p = cfg_get_string_ptr (); + if (!p) + cfg_set_config_err(); + else if (strlen (p) > CFG_MAX_AE_QUAL) + cfg_set_config_err(); + else + strcpy (currTransEl->aeQual, p); + } + +/*----------------------------------------------------------------------*/ +static void dibc_psel (void) + { + if (init_dirser_called && rem_section_flag == SD_FALSE) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_octet_string (currTransEl->pres_addr.psel, + &currTransEl->pres_addr.psel_len, MAX_PSEL_LEN) != SD_SUCCESS) + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +static void dibc_ssel (void) + { + if (init_dirser_called && rem_section_flag == SD_FALSE) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_octet_string (currTransEl->pres_addr.ssel, + &currTransEl->pres_addr.ssel_len, MAX_SSEL_LEN) != SD_SUCCESS) + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +static void dibc_tsel (void) + { + if (init_dirser_called && rem_section_flag == SD_FALSE) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + if (cfg_get_octet_string (currTransEl->pres_addr.tsel, + &currTransEl->pres_addr.tsel_len, MAX_TSEL_LEN) != SD_SUCCESS) + cfg_set_config_err(); + } + +/*----------------------------------------------------------------------*/ +static void dibc_nsap (void) + { + if (rem_section_flag) + { + /* NSAP only in remote DIB is valid */ + /* NOTE: array size is MAX_IP_ADDR_LEN. Must be >= CLNP_MAX_LEN_NSAP.*/ + if (cfg_get_octet_string (currTransEl->pres_addr.netAddr.nsap, + &currTransEl->pres_addr.nsap_len, CLNP_MAX_LEN_NSAP) != SD_SUCCESS) + cfg_set_config_err(); + } + else + { + cfg_set_config_err(); + } + } + +/*----------------------------------------------------------------------*/ +static void dibc_tp_type (void) + { +ST_CHAR *p; + + p = cfg_get_string_ptr (); + if (!p) + cfg_set_config_err(); + else + { + if (strcmp (p, "TCP") == 0) + currTransEl->pres_addr.tp_type = TP_TYPE_TCP; + else if (strcmp (p, "TP4") == 0) + currTransEl->pres_addr.tp_type = TP_TYPE_TP4; + else if (strcmp (p, "TPX") == 0) + currTransEl->pres_addr.tp_type = TP_TYPE_TPX; /* Both. Only for Local*/ + else + cfg_set_config_err(); /* too long to fit. */ + } + } + +/*----------------------------------------------------------------------*/ +static void dibc_ip_addr (void) + { +ST_CHAR *p; + + if (rem_section_flag) + { + /* IP Addr only valid in remote DIB entry */ + p = cfg_get_string_ptr (); + if (!p) + cfg_set_config_err(); + else + { + if (strlen (p) < MAX_IP_ADDR_LEN) /* must fit with NULL terminator*/ + strcpy (currTransEl->ip_addr, p); + else + cfg_set_config_err(); /* too long to fit. */ + } + } + else + { + cfg_set_config_err(); + } + } + +#if defined (MCGW) +/*----------------------------------------------------------------------*/ +static void dibc_adlcaddr (void) + { +ST_CHAR *p; +ST_LONG longval; + + if (init_dirser_called) + { + cfg_get_string_ptr (); /* Get rest of line and ignore it. */ + return; /* Don't allow reconfiguring. */ + } + + p = cfg_get_string_ptr (); + if (!p) + cfg_set_config_err(); + else + { + longval = atol (p); + /* Make sure it's a legal ST_UINT16 before casting it. */ + if (longval < 0 || longval > 0xffff) + cfg_set_config_err(); + else + currTransEl->pres_addr.adlcAddr = (ST_UINT16) longval; + } + } +#endif /* defined (MCGW) */ + +/*----------------------------------------------------------------------*/ +/* dibc_end_local */ +/* keyword 'Local_End' */ +/*----------------------------------------------------------------------*/ +static void dibc_end_local (void) + { + cfg_tbl_pop (1); + } + +/*----------------------------------------------------------------------*/ +/* dibc_end_remote */ +/* keyword 'Remote_End' */ +/*----------------------------------------------------------------------*/ +static void dibc_end_remote (void) + { + if (currTransEl->pres_addr.tp_type == TP_TYPE_TCP) + { + if ((currTransEl->pres_addr.netAddr.ip = tp0_convert_ip (currTransEl->ip_addr)) + == htonl(INADDR_NONE)) + cfg_set_config_err(); /* IP Addr invalid. */ + } + + cfg_tbl_pop (1); + rem_section_flag = SD_FALSE; + } + + +/************************************************************************/ +/* parseObjId */ +/*----------------------------------------------------------------------*/ +/* Parses components of the 'ApTitle'. */ +/************************************************************************/ + +static ST_RET parseObjId (MMS_OBJ_ID *objId, ST_CHAR *buff) + { +char *numStr; + + /* Found keyword 'ApTitle', read the components */ + objId->num_comps = 0; + numStr = strtok (buff, " \t"); + while (numStr && strlen (numStr) > 0) + { + if (objId->num_comps >= MAX_OBJID_COMPONENTS) + { + return (SD_FAILURE); + } + objId->comps[objId->num_comps] = (ST_INT16) atoi (numStr); + numStr = strtok (NULL, " \t"); + ++objId->num_comps; + } + if (objId->num_comps == 0) /* couldn't parse anything */ + return (SD_FAILURE); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* save_loc_rem_dib_tables */ +/*----------------------------------------------------------------------*/ +/* This function will initialize local and remote dib entries tables. */ +/* */ +/* Parameters: */ +/* void none */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if initialization successful. */ +/* SD_FAILURE (1) otherwise */ +/* NOTES: Does not allow reconfiguration of loc_dib_table. */ +/* Allows reconfiguration of rem_dib_table, but only after */ +/* freeing the old table. */ +/************************************************************************/ + +static ST_RET save_loc_rem_dib_tables (void) + { +ST_RET ret; +ST_INT j; + + ret = SD_SUCCESS; + + if (!init_dirser_called) /* Don't allow reconfiguring. */ + { + num_loc_dib_entries = list_get_sizeof (localTransList); + if (num_loc_dib_entries) + { + loc_dib_table = (DIB_ENTRY *) chk_calloc (num_loc_dib_entries, sizeof (DIB_ENTRY)); + save_dib_table (localTransList, loc_dib_table); + } + } + + /* If Remote DIB table already configured, free old before allocating new.*/ + if (init_dirser_called) + { + for (j = 0; j < num_rem_dib_entries; j++) + chk_free (rem_dib_table [j].name); + chk_free (rem_dib_table); + } + + num_rem_dib_entries = list_get_sizeof (remoteTransList); + if (num_rem_dib_entries) + { + rem_dib_table = (DIB_ENTRY *) chk_calloc (num_rem_dib_entries, sizeof (DIB_ENTRY)); + save_dib_table (remoteTransList, rem_dib_table); + } + return (ret); + } + + +/************************************************************************/ +/* save_dib_table */ +/*----------------------------------------------------------------------*/ +/* This function copies the temporary DIB Table to the permanent */ +/* DIB Table. It may be used for the Local as well as the Remote DIB */ +/* Tables. */ +/* */ +/* Parameters: */ +/* TRANS_DEV_INFO * temporary table (linked list of structs)*/ +/* DIB_ENTRY * permanent table (array of structs) */ +/* */ +/************************************************************************/ + +static ST_VOID save_dib_table (TRANS_DEV_INFO *TransList, DIB_ENTRY *de) + { +TRANS_DEV_INFO *toFree; +TRANS_DEV_INFO *d; + + d = TransList; /* Point to first in linked list */ + while (d) + { + de->name = (ST_CHAR *) chk_malloc (strlen(d->name) + 1); + strcpy (de->name, d->name); + if (strlen (d->apTitle)) + { + if (parseObjId (&de->AP_title, d->apTitle)) + { + ACSELOG_ERR1 ("Invalid AP Title '%s'. Ignored.", d->apTitle); + } + else + de->AP_title_pres = SD_TRUE; /* defaults to FALSE */ + } + + if (strlen (d->aeQual)) + { + de->AE_qual_pres = SD_TRUE; /* defaults to FALSE */ + de->AE_qual = atol (d->aeQual); + } + + de->AP_inv_id_pres = SD_FALSE; + de->AE_inv_id_pres = SD_FALSE; + + memcpy (&de->pres_addr, &d->pres_addr, sizeof (PRES_ADDR)); + + toFree = d; + d = (TRANS_DEV_INFO *) list_get_next (TransList, d); /* Point to next TRANS_DEV_INFO */ + chk_free (toFree); + ++de; /* Point to next DIB_ENTRY */ + } /* End "while" */ + + TransList = NULL; /* CRITICAL: clean up in case reconfigure later.*/ + } diff --git a/mmslib/ositcps/lean_var.c b/mmslib/ositcps/lean_var.c new file mode 100644 index 0000000..9486782 --- /dev/null +++ b/mmslib/ositcps/lean_var.c @@ -0,0 +1,163 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 - 2008 All Rights Reserved */ +/* */ +/* MODULE NAME : lean_var.c */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* Global variables used by the stack components are placed here, */ +/* so that when they are referenced, the linker is NOT forced */ +/* to pull in a lot of code. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* None */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/24/07 EJV 08 Ported for SNAP-Lite. */ +/* 02/11/08 EJV 07 Turned ON the COPP_LOG_ERR and COSP_LOG_ERR. */ +/* 10/04/07 MDE 06 Tweaked LOGCFG_VALUE_GROUP/LOGCFGX_VALUE_MAP */ +/* 12/13/06 JRB 05 hPktSock moved here (avail on any system). */ +/* 08/18/06 JRB 04 Init *_debug_sel with appropriate *_ERR. */ +/* 05/24/05 EJV 03 Moved xxxLogMaskMapCtrl from logcfgx.c */ +/* 02/01/05 JRB 02 Remove DEBUG_SISCO around *_debug_sel so old */ +/* apps link without problems. */ +/* 01/24/05 JRB 01 Created. */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "acse2usr.h" /* for ACSE_LOG_xxx */ +#include "acse2log.h" +#include "tp4_log.h" +#if defined(MMS_LITE) +#include "clnp_log.h" +#endif + +/************************************************************************/ +/* Global Variables for ACSE, COPP, COSP layer logging. */ +/************************************************************************/ +ST_UINT acse_debug_sel = (ACSE_LOG_ERR | COPP_LOG_ERR | COSP_LOG_ERR); + +#if defined(DEBUG_SISCO) +SD_CONST ST_CHAR *SD_CONST _acse_err_logstr = "ACSE_LOG_ERR"; +SD_CONST ST_CHAR *SD_CONST _acse_enc_logstr = "ACSE_LOG_ENC"; +SD_CONST ST_CHAR *SD_CONST _acse_dec_logstr = "ACSE_LOG_DEC"; +SD_CONST ST_CHAR *SD_CONST _acse_dib_logstr = "ACSE_LOG_DIB"; + +SD_CONST ST_CHAR *SD_CONST _copp_err_logstr = "COPP_LOG_ERR"; +SD_CONST ST_CHAR *SD_CONST _copp_dec_logstr = "COPP_LOG_DEC"; +SD_CONST ST_CHAR *SD_CONST _copp_dec_hex_logstr = "COPP_LOG_DEC_HEX"; +SD_CONST ST_CHAR *SD_CONST _copp_enc_logstr = "COPP_LOG_ENC"; +SD_CONST ST_CHAR *SD_CONST _copp_enc_hex_logstr = "COPP_LOG_ENC_HEX"; + +SD_CONST ST_CHAR *SD_CONST _cosp_err_logstr = "COSP_LOG_ERR"; +SD_CONST ST_CHAR *SD_CONST _cosp_dec_logstr = "COSP_LOG_DEC"; +SD_CONST ST_CHAR *SD_CONST _cosp_dec_hex_logstr = "COSP_LOG_DEC_HEX"; +SD_CONST ST_CHAR *SD_CONST _cosp_enc_logstr = "COSP_LOG_ENC"; +SD_CONST ST_CHAR *SD_CONST _cosp_enc_hex_logstr = "COSP_LOG_ENC_HEX"; + +LOGCFGX_VALUE_MAP acseLogMaskMaps[] = + { + {"ACSE_LOG_ERR", ACSE_LOG_ERR, &acse_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "AcseError"}, + {"ACSE_LOG_ENC", ACSE_LOG_ENC, &acse_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "AcseEncode"}, + {"ACSE_LOG_DEC", ACSE_LOG_DEC, &acse_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "AcseDecode"}, + {"ACSE_LOG_DIB", ACSE_LOG_DIB, &acse_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "DIB"}, + {"COPP_LOG_ERR", COPP_LOG_ERR, &acse_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "CoppError"}, + {"COPP_LOG_DEC", COPP_LOG_DEC, &acse_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "CoppDecode"}, + {"COPP_LOG_DEC_HEX",COPP_LOG_DEC_HEX, &acse_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "CoppDecodeHex"}, + {"COPP_LOG_ENC", COPP_LOG_ENC, &acse_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "CoppEncode"}, + {"COPP_LOG_ENC_HEX",COPP_LOG_ENC_HEX, &acse_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "CoppEncodeHex"}, + {"COSP_LOG_ERR", COSP_LOG_ERR, &acse_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "CoppError"}, + {"COSP_LOG_DEC", COSP_LOG_DEC, &acse_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "CoppDecode"}, + {"COSP_LOG_DEC_HEX",COSP_LOG_DEC_HEX, &acse_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "CoppDecodeHex"}, + {"COSP_LOG_ENC", COSP_LOG_ENC, &acse_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "CoppEncode"}, + {"COSP_LOG_ENC_HEX",COSP_LOG_ENC_HEX, &acse_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "CoppEncodeHex"} + }; + +LOGCFG_VALUE_GROUP acseLogMaskMapCtrl = + { + {NULL,NULL}, + "AcseLogMasks", /* Parent Tag */ + sizeof(acseLogMaskMaps)/sizeof(LOGCFGX_VALUE_MAP), + acseLogMaskMaps + }; +#endif /* DEBUG_SISCO */ + +/************************************************************************/ +/* Global Variables for TP4 layer logging. */ +/************************************************************************/ +ST_UINT tp4_debug_sel = TP4_LOG_ERR; + +#if defined(DEBUG_SISCO) +SD_CONST ST_CHAR *SD_CONST _tp4_err_logstr = "TP4_LOG_ERR"; +SD_CONST ST_CHAR *SD_CONST _tp4_flowup_logstr = "TP4_LOG_FLOWUP"; +SD_CONST ST_CHAR *SD_CONST _tp4_flowdown_logstr = "TP4_LOG_FLOWDOWN"; + +LOGCFGX_VALUE_MAP tp4LogMaskMaps[] = + { + {"TP4_LOG_ERR", TP4_LOG_ERR, &tp4_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Tp4Error"}, + {"TP4_LOG_FLOWUP", TP4_LOG_FLOWUP, &tp4_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Tp4FlowUp"}, + {"TP4_LOG_FLOWDOWN", TP4_LOG_FLOWDOWN, &tp4_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Tp4FlowDown"}, + /* for TP0 use different names in xml file */ + {"TP_LOG_ERR", TP4_LOG_ERR, &tp4_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "TpError"}, + {"TP_LOG_FLOWUP", TP4_LOG_FLOWUP, &tp4_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "TpFlowUp"}, + {"TP_LOG_FLOWDOWN", TP4_LOG_FLOWDOWN, &tp4_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "TpFlowDown"} + }; + +LOGCFG_VALUE_GROUP tp4LogMaskMapCtrl = + { + {NULL,NULL}, + "TransportLogMasks", /* Parent Tag */ + sizeof(tp4LogMaskMaps)/sizeof(LOGCFGX_VALUE_MAP), + tp4LogMaskMaps + }; +#endif /* DEBUG_SISCO */ + +#if defined(MMS_LITE) +/************************************************************************/ +/* Global Variables for CLNP layer logging. */ +/************************************************************************/ +ST_UINT clnp_debug_sel = CLNP_LOG_ERR; + +#if defined(DEBUG_SISCO) +SD_CONST ST_CHAR *SD_CONST _clnp_err_logstr = "CLNP_LOG_ERR"; +SD_CONST ST_CHAR *SD_CONST _clnp_nerr_logstr = "CLNP_LOG_NERR"; +SD_CONST ST_CHAR *SD_CONST _clnp_req_logstr = "CLNP_LOG_REQ"; +SD_CONST ST_CHAR *SD_CONST _clnp_ind_logstr = "CLNP_LOG_IND"; +SD_CONST ST_CHAR *SD_CONST _clnp_enc_dec_logstr = "CLNP_LOG_ENC_DEC"; +SD_CONST ST_CHAR *SD_CONST _clnp_llc_enc_dec_logstr = "CLNP_LOG_LLC_ENC_DEC"; +SD_CONST ST_CHAR *SD_CONST _clsns_req_logstr = "CLSNS_LOG_REQ"; +SD_CONST ST_CHAR *SD_CONST _clsns_ind_logstr = "CLSNS_LOG_IND"; + +LOGCFGX_VALUE_MAP clnpLogMaskMaps[] = + { + {"CLNP_LOG_ERR", CLNP_LOG_ERR, &clnp_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Error"}, + {"CLNP_LOG_NERR", CLNP_LOG_NERR, &clnp_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Notice"}, + {"CLNP_LOG_REQ", CLNP_LOG_REQ, &clnp_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "ClnpRequest"}, + {"CLNP_LOG_IND", CLNP_LOG_IND, &clnp_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "ClnpIndication"}, + {"CLNP_LOG_ENC_DEC", CLNP_LOG_ENC_DEC, &clnp_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "EncodeDecode"}, + {"CLNP_LOG_LLC_ENC_DEC", CLNP_LOG_LLC_ENC_DEC, &clnp_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "EncodeDecode"}, + {"CLSNS_LOG_REQ", CLSNS_LOG_REQ, &clnp_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "ClnsRequest"}, + {"CLSNS_LOG_IND", CLSNS_LOG_IND, &clnp_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "ClnsIndication"} + }; + +LOGCFG_VALUE_GROUP clnpLogMaskMapCtrl = + { + {NULL,NULL}, + "ClnpLogMasks", /* Parent Tag */ + sizeof(clnpLogMaskMaps)/sizeof(LOGCFGX_VALUE_MAP), + clnpLogMaskMaps + }; +#endif /* DEBUG_SISCO */ + +/************************************************************************/ +/* hPktSock is used in LINUX subnetwork code (see clnp_linux.c) and it */ +/* may be used on new systems. */ +/************************************************************************/ +int hPktSock = -1; /* Packet Socket handle: initialized to invalid value*/ + +#endif /* defined(MMS_LITE) */ diff --git a/mmslib/ositcps/osicfgx.c b/mmslib/ositcps/osicfgx.c new file mode 100644 index 0000000..9b93e82 --- /dev/null +++ b/mmslib/ositcps/osicfgx.c @@ -0,0 +1,1822 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2000 - 2005, All Rights Reserved */ +/* */ +/* MODULE NAME : osicfgx.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : This routine parses the osicfg.xml */ +/* configuration file for the Lean-T Stack */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/18/08 JRB 40 Parse Network_Device. */ +/* 02/07/08 JRB 39 Chg strtok to thread-safe get_next_string. */ +/* Ignore obsolete Max_Num_Connections & */ +/* Rfc1006_Max_Num_Conns. */ +/* 01/12/07 JRB 38 If RemoteAddress NetAddr Type is illegal, */ +/* ignore addr, log error, but continue parsing.*/ +/* 07/08/05 EJV 37 MMSEASE_MOSI: allow only TCP tp_type. */ +/* _netAddr_EFun: re-arranged NSAP with IPADDR */ +/* 05/23/05 JRB 36 Del CFLOW logging (sx_dec logs similar info).*/ +/* 05/18/05 DWL 35 Move "SX_PUSH (networkAddr..)" inside "if". */ +/* 05/05/05 EJV 34 Added Rfc1006_Listen_Port, remote Port */ +/* 04/06/05 JRB 33 MMSEASE_MOSI: set def tp_type to TP_TYPE_TCP */ +/* 09/20/04 JRB 32 Always allow session_cfg.disconnect_timeout */ +/* to be configured (not just for TP4). */ +/* 08/13/04 JRB 31 Use thread-safe sx_parseExx_mt. */ +/* Del unneeded system includes. */ +/* 04/31/04 MDE 30 Now use sx_parseExx */ +/* 02/02/04 JRB 29 Set err flag if IPADDR entered & !TP0_ENABLED*/ +/* OR NSAP entered & !TP4_ENABLED. Clarify logs.*/ +/* 01/14/04 EJV 28 Added rfc1006MaxSpduOutstanding. */ +/* 12/09/03 JRB 27 Init all 5 members of SX_ELEMENT structs. */ +/* 10/24/03 JRB 26 Lint. */ +/* 09/09/03 EJV 25 Use the XML element names in ERR, FLOW logs. */ +/* 12/16/02 ASK 24 Wrap ifdef TP0_ENABLED around inet_ntoa calls*/ +/* 07/18/02 JRB 23 Move ifdefs to skip more unneeded code. */ +/* 06/27/02 JRB 22 Add tp0_sock.h. */ +/* 06/20/02 JRB 21 Chg to use new netAddr union in PRES_ADDR. */ +/* 05/03/02 MDE 20 Now set max_bind_ctrl */ +/* 02/27/02 GLB 19 Changed ascii_t_.. to asciiTo.. */ +/* 02/25/02 MDE 18 More changes to MVL_CFG_INFO */ +/* 02/20/02 MDE 17 Changes for new MVL_CFG_INFO */ +/* 02/11/02 JRB 16 Don't reparse w/ logging. Let user do it. */ +/* 02/08/02 JRB 15 Add MVL_CFG.. arg & pass along to sx_parseEx.*/ +/* 02/05/02 GLB 14 Made optional: Rfc1006_Max_Num_Conns, */ +/* LocalAddressList, RemoteAddressList */ +/* 01/22/02 JRB 13 Move mvl_set_num_connections call so it does */ +/* not depend on order of params in XML file. */ +/* 01/10/02 GLB 12 Update optional/mandatory flags */ +/* Add sx_pop to allow check for mandatory */ +/* elements */ +/* Make Session optional */ +/* 11/28/01 MDE 11 Use new mvl_acse functions */ +/* 11/28/01 MDE 10 Allocate mmsl_enc_buf */ +/* 11/06/01 GLB 09 Added MMS section */ +/* 05/25/01 GLB 08 Removed getFileSize */ +/* 05/11/01 JRB 07 Use new sx_parseEx. Del osiCfgParse & */ +/* LOG_DEC_CTRL (not used for anything useful). */ +/* Save "called" flag to use on 2nd pass so same*/ +/* data parsed on 2nd pass. Chg MVL_LOG to */ +/* SXLOG, mvl log mask not initialized yet. */ +/* Use correct defines for SSEL TSEL len. */ +/* 03/15/01 JRB 06 Added Session group w/ Disconnect_Timeout. */ +/* 01/25/01 JRB 05 Use stricmp. */ +/* Chg sx_deb.. again: do NOT set SX_LOG_DEBUG. */ +/* 01/15/01 EJV 04 Chnaged sx_debug_sel in cfg parsing. */ +/* 01/09/01 GLB 03 Changed logBufParse to osiCfgParse */ +/* 01/03/01 EJV 02 Don't use O_TEXT in open() on non _WIN32 sys.*/ +/* Changed _getFileSize to use stat(). */ +/* Changed sx_debug_sel to 'or' flags. */ +/* Deleted duplicate code in _netAddr_EFun. */ +/* 08/31/00 GLB 01 Module created from existing lean_cfg.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "mvl_acse.h" + +#include "sx_defs.h" +#include "sx_log.h" + +#include "cfg_util.h" +#include "str_util.h" +#include "cfglog.h" +#include "slog.h" +#include "acse2log.h" +#include "lean_a.h" +#include "tp0_sock.h" /* portable "sockets" interface */ + +#if !defined(MMSEASE_MOSI) +#include "mmsldefs.h" /* for MMS section */ +#include "mvl_defs.h" /* for MMS section */ +#endif + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +#define REMOTE_DIB_TABLE 0 +#define LOCAL_DIB_TABLE 1 + +#define CFG_MAX_AR_NAME 64 +#define CFG_MAX_AP_TITLE 80 +#define CFG_MAX_AE_QUAL 32 + +typedef struct _tagTransDevInfo + { + DBL_LNK l; + ST_CHAR name[CFG_MAX_AR_NAME +1]; + ST_CHAR apTitle[CFG_MAX_AP_TITLE +1]; + ST_CHAR aeQual[CFG_MAX_AE_QUAL +1]; + PRES_ADDR pres_addr; + } TRANS_DEV_INFO; + +static ST_BOOLEAN init_dirser_called; +static ST_BOOLEAN rem_section_flag; + +/************************************************************************/ + +static ST_VOID _logStart_SEFun (SX_DEC_CTRL *sxDecCtrl); + +static ST_VOID _mms_SFun (SX_DEC_CTRL *sxDecCtrl); + +static ST_VOID _maxMmsPduLength_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _maxCallingConnections_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _maxCalledConnections_EFun (SX_DEC_CTRL *sxDecCtrl); + +static ST_VOID _network_SFun (SX_DEC_CTRL *sxDecCtrl); + +static ST_VOID _networkDevice_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _clnp_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _lifetime_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _lifetimeDecrement_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _cfgTimer_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _eshDelay_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _localNsap_EFun (SX_DEC_CTRL *sxDecCtrl); + +static ST_VOID _transport_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _session_SFun (SX_DEC_CTRL *sxDecCtrl); + +static ST_VOID _tp4_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _maxTpduLength_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _maxRemoteCdt_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _localCdt_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _maxNumConnections_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _maxSpduOutstanding_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _windowTime_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _inactivityTime_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _retransmissionTime_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _maxTransmissions_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _akDelay_EFun (SX_DEC_CTRL *sxDecCtrl); + +static ST_VOID _tcp_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _rfc1006MaxTpduLen_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _rfc1006MaxNumConns_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _rfc1006MaxSpduOutstanding_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _rfc1006ListenPort_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _disconnectTimeout_EFun (SX_DEC_CTRL *sxDecCtrl); + +static ST_VOID _networkAddressing_SFun (SX_DEC_CTRL *sxDecCtrl); + +static ST_VOID _localAddresses_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _remoteAddresses_SFun (SX_DEC_CTRL *sxDecCtrl); + +static ST_VOID _localArName_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _arname_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _apTitle_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _aeQualifier_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _psel_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _ssel_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _tsel_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _transportType_EFun (SX_DEC_CTRL *sxDecCtrl); + +static ST_VOID _remoteArName_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _netAddr_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _port_EFun (SX_DEC_CTRL *sxDecCtrl); + +static TRANS_DEV_INFO *localTransList; +static TRANS_DEV_INFO *remoteTransList; +static TRANS_DEV_INFO *currTransEl; + +static ST_RET save_loc_rem_dib_tables (void); +static ST_VOID save_dib_table (TRANS_DEV_INFO *, DIB_ENTRY *); +static ST_RET parseObjId (MMS_OBJ_ID *o, ST_CHAR *buff); + +static ST_VOID printDibEntry (ST_VOID); +static ST_VOID printDibStruct (DIB_ENTRY *de,ST_INT table_type); + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +SX_ELEMENT cfgStartElements[] = +{ + {"STACK_CFG", SX_ELF_CSTART | SX_ELF_CEND, _logStart_SEFun, NULL, 0} +}; + +SX_ELEMENT cfgElements[] = +{ + {"MMS", SX_ELF_CSTART|SX_ELF_OPT, _mms_SFun, NULL, 0}, + {"Network", SX_ELF_CSTART|SX_ELF_OPT, _network_SFun, NULL, 0}, + {"Transport", SX_ELF_CSTART, _transport_SFun, NULL, 0}, + {"Session", SX_ELF_CSTART|SX_ELF_OPT, _session_SFun, NULL, 0}, + {"NetworkAddressing", SX_ELF_CSTARTEND, _networkAddressing_SFun, NULL, 0} +}; + +SX_ELEMENT mmsElements[] = +{ + {"Max_Mms_Pdu_Length", SX_ELF_CEND, _maxMmsPduLength_EFun, NULL, 0}, + {"Max_Calling_Connections", SX_ELF_CEND, _maxCallingConnections_EFun, NULL, 0}, + {"Max_Called_Connections", SX_ELF_CEND, _maxCalledConnections_EFun, NULL, 0}, +}; + +SX_ELEMENT networkElements[] = +{ + {"Network_Device", SX_ELF_CEND|SX_ELF_OPT, _networkDevice_EFun, NULL, 0}, + {"Clnp", SX_ELF_CSTART|SX_ELF_OPT, _clnp_SFun, NULL, 0} +}; + +SX_ELEMENT clnpElements[] = +{ + {"Lifetime", SX_ELF_CEND|SX_ELF_OPT, _lifetime_EFun, NULL, 0}, + {"Lifetime_Decrement", SX_ELF_CEND|SX_ELF_OPT, _lifetimeDecrement_EFun, NULL, 0}, + {"Cfg_Timer", SX_ELF_CEND|SX_ELF_OPT, _cfgTimer_EFun, NULL, 0}, + {"Esh_Delay", SX_ELF_CEND|SX_ELF_OPT, _eshDelay_EFun, NULL, 0}, + {"Local_NSAP", SX_ELF_CEND|SX_ELF_OPT, _localNsap_EFun, NULL, 0} +}; + + +SX_ELEMENT transportElements[] = +{ + {"Tp4", SX_ELF_CSTART|SX_ELF_OPT, _tp4_SFun, NULL, 0}, + {"Tcp", SX_ELF_CSTART|SX_ELF_OPT, _tcp_SFun, NULL, 0} +}; + +SX_ELEMENT Tp4Elements[] = +{ + {"Max_Tpdu_Length", SX_ELF_CEND|SX_ELF_OPT, _maxTpduLength_EFun, NULL, 0}, + {"Max_Remote_Cdt", SX_ELF_CEND|SX_ELF_OPT, _maxRemoteCdt_EFun, NULL, 0}, + {"Local_Cdt", SX_ELF_CEND|SX_ELF_OPT, _localCdt_EFun, NULL, 0}, + {"Max_Num_Connections", SX_ELF_CEND|SX_ELF_OPT, _maxNumConnections_EFun, NULL, 0}, + {"Max_Spdu_Outstanding", SX_ELF_CEND|SX_ELF_OPT, _maxSpduOutstanding_EFun, NULL, 0}, + {"Window_Time", SX_ELF_CEND|SX_ELF_OPT, _windowTime_EFun, NULL, 0}, + {"Inactivity_Time", SX_ELF_CEND|SX_ELF_OPT, _inactivityTime_EFun, NULL, 0}, + {"Retransmission_Time", SX_ELF_CEND|SX_ELF_OPT, _retransmissionTime_EFun, NULL, 0}, + {"Max_Transmissions", SX_ELF_CEND|SX_ELF_OPT, _maxTransmissions_EFun, NULL, 0}, + {"Ak_Delay", SX_ELF_CEND|SX_ELF_OPT, _akDelay_EFun, NULL, 0} +}; + +SX_ELEMENT TcpElements[] = +{ + {"Rfc1006_Max_Tpdu_Len", SX_ELF_CEND|SX_ELF_OPT, _rfc1006MaxTpduLen_EFun, NULL, 0}, + {"Rfc1006_Max_Num_Conns", SX_ELF_CEND|SX_ELF_OPT, _rfc1006MaxNumConns_EFun, NULL, 0}, + {"Rfc1006_Max_Spdu_Outstanding", SX_ELF_CEND|SX_ELF_OPT, _rfc1006MaxSpduOutstanding_EFun, NULL, 0}, + {"Rfc1006_Listen_Port", SX_ELF_CEND|SX_ELF_OPT, _rfc1006ListenPort_EFun, NULL, 0} +}; + + +SX_ELEMENT sessionElements[] = +{ + {"Disconnect_Timeout", SX_ELF_CEND|SX_ELF_OPT, _disconnectTimeout_EFun, NULL, 0} +}; + +SX_ELEMENT networkAddressingElements[] = +{ + {"LocalAddressList", SX_ELF_CSTART|SX_ELF_OPT, _localAddresses_SFun, NULL, 0}, + {"RemoteAddressList", SX_ELF_CSTART|SX_ELF_OPT, _remoteAddresses_SFun, NULL, 0} +}; + +SX_ELEMENT LocalAddressesElements[] = +{ + {"LocalAddress", SX_ELF_CSTART|SX_ELF_RPT, _localArName_SFun, NULL, 0} +}; + +SX_ELEMENT LocalArNameElements[] = +{ + {"AR_Name", SX_ELF_CEND, _arname_EFun, NULL, 0}, + {"AP_Title", SX_ELF_CEND|SX_ELF_OPT, _apTitle_EFun, NULL, 0}, + {"AE_Qualifier", SX_ELF_CEND|SX_ELF_OPT, _aeQualifier_EFun, NULL, 0}, + {"Psel", SX_ELF_CEND, _psel_EFun, NULL, 0}, + {"Ssel", SX_ELF_CEND, _ssel_EFun, NULL, 0}, + {"Tsel", SX_ELF_CEND, _tsel_EFun, NULL, 0}, + {"TransportType", SX_ELF_CEND, _transportType_EFun, NULL, 0} +}; + +SX_ELEMENT RemoteAddressesElements[] = +{ + {"RemoteAddress", SX_ELF_CSTART | SX_ELF_RPT, _remoteArName_SFun, NULL, 0} +}; + +SX_ELEMENT RemoteArNameElements[] = +{ + {"AR_Name", SX_ELF_CEND, _arname_EFun, NULL, 0}, + {"AP_Title", SX_ELF_CEND|SX_ELF_OPT, _apTitle_EFun, NULL, 0}, + {"AE_Qualifier", SX_ELF_CEND|SX_ELF_OPT, _aeQualifier_EFun, NULL, 0}, + {"Psel", SX_ELF_CEND, _psel_EFun, NULL, 0}, + {"Ssel", SX_ELF_CEND, _ssel_EFun, NULL, 0}, + {"Tsel", SX_ELF_CEND, _tsel_EFun, NULL, 0}, + {"NetAddr", SX_ELF_CEND, _netAddr_EFun, NULL, 0}, + {"Port", SX_ELF_CEND|SX_ELF_OPT, _port_EFun, NULL, 0} +}; + +/************************************************************************/ +/* osicfgx */ +/************************************************************************/ + +ST_RET osicfgx (ST_CHAR *logFileName, MVL_CFG_INFO *mvlCfg) + { +ST_RET rc; + + rc = sx_parseExx_mt (logFileName, + sizeof (cfgStartElements)/sizeof(SX_ELEMENT), cfgStartElements, + mvlCfg, NULL, NULL); + + /* Here we save the bind information */ + if (loc_dib_table != NULL) + { +#ifdef MAP30_ACSE /* Select bind mode */ + mvlCfg->use_bind_ctrl = SD_TRUE; + mvlCfg->max_bind_ctrl = 1; + mvlCfg->num_bind_ctrl = 1; + mvlCfg->bind_ctrl = chk_calloc (1, sizeof (NET_BIND_CTRL)); + mvlCfg->bind_ctrl[0].ar_name = loc_dib_table->name; + mvlCfg->bind_ctrl[0].tp_type = loc_dib_table->pres_addr.tp_type; +#else + strcpy (mvlCfg->local_ar_name, loc_dib_table->name); +#endif + } + + if (rc == SD_SUCCESS) + init_dirser_called = SD_TRUE; + + return (rc); + } + +/************************************************************************/ +/************************************************************************/ +/* _logStart_SEFun */ +/************************************************************************/ + +static ST_VOID _logStart_SEFun (SX_DEC_CTRL *sxDecCtrl) + { + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + SX_PUSH (cfgElements); + } + else + { + while (sxDecCtrl->itemStackLevel > 0) + sx_pop (sxDecCtrl); + } + } +/************************************************************************/ +/* _mms_SFun */ +/************************************************************************/ + +static ST_VOID _mms_SFun (SX_DEC_CTRL *sxDecCtrl) + { + SX_PUSH (mmsElements); + } + +/************************************************************************/ +/* _maxMmsPduLength_EFun */ +/************************************************************************/ + +static ST_VOID _maxMmsPduLength_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; +MVL_CFG_INFO *mvlCfg = (MVL_CFG_INFO *) sxDecCtrl->usr; + +ST_INT sInt; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + + sInt = 0; + if (strlen(str) == 0) + { + SXLOG_ERR0 ("ERROR: Max_Mms_Pdu_Length required but not present "); + sxDecCtrl->errCode = SX_USER_ERROR; + } + else if ((asciiToSint(str,&sInt) != SD_SUCCESS) || (strchr(str,'-')) ) + { + SXLOG_ERR1 ("ERROR: Max_Mms_Pdu_Length Data Conversion Error on value: %s", str); + sxDecCtrl->errCode = SX_USER_ERROR; + } + else + mvlCfg->max_msg_size = sInt; + } + } + +/************************************************************************/ +/* _maxCallingConnections_EFun */ +/************************************************************************/ + +static ST_VOID _maxCallingConnections_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; +ST_INT sInt; +MVL_CFG_INFO *mvlCfg = (MVL_CFG_INFO *) sxDecCtrl->usr; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + + sInt = 0; + + if (strlen(str) == 0) + { + SXLOG_ERR0 ("ERROR: Max_Calling_Connections required but not present "); + sxDecCtrl->errCode = SX_USER_ERROR; + } + else if ((asciiToSint(str,&sInt) != SD_SUCCESS) || (strchr(str,'-')) ) + { + SXLOG_ERR1 ("ERROR: Max_Calling_Connections Data Conversion Error on value: %s", str); + sxDecCtrl->errCode = SX_USER_ERROR; + } + else + { + mvlCfg->num_calling = sInt; + } + + } + } + +/************************************************************************/ +/* _maxCalledConnections_EFun */ +/************************************************************************/ + +static ST_VOID _maxCalledConnections_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; +ST_INT sInt; +MVL_CFG_INFO *mvlCfg = (MVL_CFG_INFO *) sxDecCtrl->usr; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + sInt = 0; + if (strlen(str) == 0) + { + SXLOG_ERR0 ("ERROR: Max_Called_Connections required but not present "); + sxDecCtrl->errCode = SX_USER_ERROR; + } + else if ((asciiToSint(str,&sInt) != SD_SUCCESS) || (strchr(str,'-')) ) + { + SXLOG_ERR1 ("ERROR: Max_Called_Connections Data Conversion Error on value: %s", str); + sxDecCtrl->errCode = SX_USER_ERROR; + } + else + { + mvlCfg->num_called = sInt; + } + } + } + +/************************************************************************/ +/************************************************************************/ +/* _network_SFun */ +/************************************************************************/ + +static ST_VOID _network_SFun (SX_DEC_CTRL *sxDecCtrl) + { + SX_PUSH (networkElements); + } + +/************************************************************************/ +/* _networkDevice_EFun */ +/************************************************************************/ +static ST_VOID _networkDevice_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + clnp_param.network_device = chk_malloc (strLen + 1); + strcpy (clnp_param.network_device, str); + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/************************************************************************/ +/* _clnp_SFun */ +/************************************************************************/ + +static ST_VOID _clnp_SFun (SX_DEC_CTRL *sxDecCtrl) + { + SX_PUSH (clnpElements); + } + +/************************************************************************/ +/* _lifetime_EFun */ +/************************************************************************/ + +static ST_VOID _lifetime_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT16 uShortInt = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Lifetime Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + clnp_param.pdu_lifetime = (ST_UCHAR) uShortInt; + } + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/* _lifetimeDecrement_EFun */ +/************************************************************************/ + +static ST_VOID _lifetimeDecrement_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT16 uShortInt = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Lifetime_Decrement Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + clnp_param.pdu_lifetime_dec = (ST_UCHAR) uShortInt; + } + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/* _cfgTimer_EFun */ +/************************************************************************/ + +static ST_VOID _cfgTimer_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT16 uShortInt = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Cfg_Timer Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + clnp_param.esh_cfg_timer = uShortInt; + } + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/* _eshDelay_EFun */ +/************************************************************************/ + +static ST_VOID _eshDelay_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT16 uShortInt = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Esh_Delay Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + clnp_param.esh_delay = uShortInt; + } + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/* _localNsap_EFun */ +/************************************************************************/ + +static ST_VOID _localNsap_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; +ST_UINT hexStrLen = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (ascii_to_hex_str (&clnp_param.loc_nsap[1],&hexStrLen,CLNP_MAX_LEN_NSAP,str) + == SD_SUCCESS) + { + if (hexStrLen > 0) + clnp_param.loc_nsap[0] = (ST_UCHAR) hexStrLen; + } + else + { + /*cfg_set_config_err();*/ + SXLOG_ERR0 ("ERROR: Clnp Local_NSAP Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/************************************************************************/ +/* _transport_SFun */ +/************************************************************************/ + +static ST_VOID _transport_SFun (SX_DEC_CTRL *sxDecCtrl) + { + SX_PUSH (transportElements); + } + +/************************************************************************/ +/************************************************************************/ +/* _tp4_SFun */ +/************************************************************************/ + +static ST_VOID _tp4_SFun (SX_DEC_CTRL *sxDecCtrl) + { + SX_PUSH (Tp4Elements); + } + +/************************************************************************/ +/* _maxTpduLength_EFun */ +/************************************************************************/ + +static ST_VOID _maxTpduLength_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT16 uShortInt = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Max_Tpdu_Length Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + tp_cfg.max_tpdu_len = uShortInt; + } + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/* _maxRemoteCdt_EFun */ +/************************************************************************/ + +static ST_VOID _maxRemoteCdt_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT16 uShortInt = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Max_Remote_Cdt Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + tp_cfg.max_rem_cdt = (ST_UCHAR) uShortInt; + } + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/* _localCdt_EFun */ +/************************************************************************/ + +static ST_VOID _localCdt_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT16 uShortInt = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Local_Cdt Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + tp_cfg.loc_cdt = (ST_UCHAR) uShortInt; + } + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/* _maxNumConnections_EFun */ +/************************************************************************/ + +static ST_VOID _maxNumConnections_EFun (SX_DEC_CTRL *sxDecCtrl) + { + SXLOG_ERR0 ("Max_Num_Connections element is OBSOLETE. Ignored."); + return; + } + +/************************************************************************/ +/* _maxSpduOutstanding_EFun */ +/************************************************************************/ + +static ST_VOID _maxSpduOutstanding_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT16 uShortInt = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Max_Spdu_Outstanding Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + tp_cfg.max_spdu_outst = (ST_UCHAR) uShortInt; + } + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/* _windowTime_EFun */ +/************************************************************************/ + +static ST_VOID _windowTime_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT16 uShortInt = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Window_Time Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + tp_cfg.window_time = uShortInt; + } + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/* _inactivityTime_EFun */ +/************************************************************************/ + +static ST_VOID _inactivityTime_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT16 uShortInt = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Inactivity_Time Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + tp_cfg.inact_time = uShortInt; + } + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/* _retransmissionTime_EFun */ +/************************************************************************/ + +static ST_VOID _retransmissionTime_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT16 uShortInt = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Retransmission_Time Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + tp_cfg.retrans_time = uShortInt; + } + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/* _maxTransmissions_EFun */ +/************************************************************************/ + +static ST_VOID _maxTransmissions_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT16 uShortInt = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Max_Transmissions Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + tp_cfg.max_trans = (ST_UCHAR) uShortInt; + } + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/* _akDelay_EFun */ +/************************************************************************/ + +static ST_VOID _akDelay_EFun (SX_DEC_CTRL *sxDecCtrl) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT16 uShortInt = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Ak_Delay Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + tp_cfg.ak_delay = (ST_UCHAR) uShortInt; + } + } +#endif /* TP4_ENABLED */ + } + +/************************************************************************/ +/************************************************************************/ +/* _tcp_SFun */ +/************************************************************************/ + +static ST_VOID _tcp_SFun (SX_DEC_CTRL *sxDecCtrl) + { + SX_PUSH (TcpElements); + } + +/************************************************************************/ +/* _rfc1006MaxTpduLen_EFun */ +/************************************************************************/ + +static ST_VOID _rfc1006MaxTpduLen_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + +#if defined (TP0_ENABLED) /* Just ignore if disabled. */ + if (!init_dirser_called) + { + ST_UINT16 uShortInt = 0; + + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Rfc1006_Max_Tpdu_Len Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + tp0_cfg.max_tpdu_len = uShortInt; + } + } +#endif /* TP0_ENABLED */ + } + +/************************************************************************/ +/* _rfc1006MaxNumConns_EFun */ +/************************************************************************/ + +static ST_VOID _rfc1006MaxNumConns_EFun (SX_DEC_CTRL *sxDecCtrl) + { + SXLOG_ERR0 ("Rfc1006_Max_Num_Conns element is OBSOLETE. Ignored."); + return; + } + +/************************************************************************/ +/* _rfc1006MaxSpduOutstanding_EFun */ +/************************************************************************/ + +static ST_VOID _rfc1006MaxSpduOutstanding_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + +#if defined (TP0_ENABLED) /* Just ignore if disabled. */ + if (!init_dirser_called) + { + ST_UINT uInt = 0; + + if (asciiToUint(str,&uInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Rfc1006_Max_Spdu_Outstanding Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + tp0_cfg.max_spdu_outst = uInt; + } + } +#endif /* TP0_ENABLED */ + } + +/************************************************************************/ +/* _rfc1006ListenPort_EFun */ +/************************************************************************/ + +static ST_VOID _rfc1006ListenPort_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + +#if defined (TP0_ENABLED) /* Just ignore if disabled. */ + if (!init_dirser_called) + { + ST_UINT16 uShortInt = 0; + + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Rfc1006_Listen_Port Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + tp0_cfg.rfc1006_listen_port = uShortInt; + } + } +#endif /* TP0_ENABLED */ + } + +/************************************************************************/ +/************************************************************************/ +/* _session_SFun */ +/************************************************************************/ + +static ST_VOID _session_SFun (SX_DEC_CTRL *sxDecCtrl) + { + SX_PUSH (sessionElements); + } + +/************************************************************************/ +/* _disconnectTimeout_EFun */ +/************************************************************************/ + +static ST_VOID _disconnectTimeout_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT16 uShortInt = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (!init_dirser_called) + { + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Session Disconnect_Timeout Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + session_cfg.disconnect_timeout = uShortInt; + } + } + } + +/************************************************************************/ +/************************************************************************/ +/* _networkAddressing_SFun */ +/************************************************************************/ + +static ST_VOID _networkAddressing_SFun (SX_DEC_CTRL *sxDecCtrl) + { + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + /* CRITICAL: Always start with empty temporary DIB Table linked lists */ + /* (may be reconfiguring). */ + localTransList = NULL; + remoteTransList = NULL; + + SX_PUSH (networkAddressingElements); + } + + if (sxDecCtrl->reason == SX_ELEMENT_END) + { + /* save link list data from configuartion file parse in tables */ + save_loc_rem_dib_tables (); + printDibEntry (); + + rem_section_flag = SD_FALSE; + init_dirser_called = SD_TRUE; + } + } + +/************************************************************************/ +/* _localAddresses_SFun */ +/************************************************************************/ + +static ST_VOID _localAddresses_SFun (SX_DEC_CTRL *sxDecCtrl) + { + SX_PUSH (LocalAddressesElements); + } + +/************************************************************************/ +/************************************************************************/ +/* _localArName_SFun */ +/************************************************************************/ + +static ST_VOID _localArName_SFun (SX_DEC_CTRL *sxDecCtrl) + { + SX_PUSH (LocalArNameElements); + + if (!init_dirser_called) + { /* Don't alloc if reconfiguring. */ + currTransEl = (TRANS_DEV_INFO *) chk_calloc (1, sizeof(TRANS_DEV_INFO)); +#if defined(MMSEASE_MOSI) + currTransEl->pres_addr.tp_type = TP_TYPE_TCP; /* Default=TCP */ + /* preset IP addr to be local system (used in loop back connection) */ + if ((currTransEl->pres_addr.netAddr.ip = tp0_convert_ip ("127.0.0.1")) + == htonl(INADDR_NONE)) + { + SXLOG_ERR1 ("NetAddr Type=IPADDR '%s' invalid", "127.0.0.1"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } +#else + currTransEl->pres_addr.tp_type = TP_TYPE_TP4; /* Default=TP4 */ +#endif + list_add_last (&localTransList, currTransEl); + } + } + +/************************************************************************/ +/* _arname_EFun */ +/************************************************************************/ + +static ST_VOID _arname_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + + if ((!init_dirser_called) || + (init_dirser_called && rem_section_flag == SD_TRUE)) + { + if (!str) + { + SXLOG_ERR0 ("ERROR: AR_Name Error"); + } + else if (strlen (str) > CFG_MAX_AR_NAME) + { + SXLOG_ERR0 ("ERROR: AR_Name Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + strcpy (currTransEl->name, str); + } + } + +/************************************************************************/ +/* _apTitle_EFun */ +/************************************************************************/ + +static ST_VOID _apTitle_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if ((!init_dirser_called) || + (init_dirser_called && rem_section_flag == SD_TRUE)) + { + if (!str) + { + SXLOG_ERR0 ("ERROR: AP_Title Error"); + } + else if (strlen (str) > CFG_MAX_AR_NAME) + { + SXLOG_ERR0 ("ERROR: AP_Title Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + strcpy (currTransEl->apTitle, str); + } + } + +/************************************************************************/ +/* _aeQualifier_EFun */ +/************************************************************************/ + +static ST_VOID _aeQualifier_EFun (SX_DEC_CTRL *sxDecCtrl) +{ +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + + if ((!init_dirser_called) || + (init_dirser_called && rem_section_flag == SD_TRUE)) + { + if (!str) + { + SXLOG_ERR0 ("ERROR: AE_Qualifier Error"); + } + else if (strlen (str) > CFG_MAX_AR_NAME) + { + SXLOG_ERR0 ("ERROR: AE_Qualifier Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + strcpy (currTransEl->aeQual, str); + } + } + +/************************************************************************/ +/* _psel_EFun */ +/************************************************************************/ + +static ST_VOID _psel_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT hexStrLen = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if ((!init_dirser_called) || + (init_dirser_called && rem_section_flag == SD_TRUE)) + { + if (ascii_to_hex_str (currTransEl->pres_addr.psel,&hexStrLen,MAX_PSEL_LEN,str) + == SD_SUCCESS) + { + currTransEl->pres_addr.psel_len = hexStrLen; + } + else + { + /*cfg_set_config_err();*/ + SXLOG_ERR0 ("ERROR: Psel Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + } + } + +/************************************************************************/ +/* _ssel_EFun */ +/************************************************************************/ + +static ST_VOID _ssel_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT hexStrLen = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if ((!init_dirser_called) || + (init_dirser_called && rem_section_flag == SD_TRUE)) + { + if (ascii_to_hex_str (currTransEl->pres_addr.ssel,&hexStrLen,MAX_SSEL_LEN,str) + == SD_SUCCESS) + { + currTransEl->pres_addr.ssel_len = hexStrLen; + } + else + { + SXLOG_ERR0 ("ERROR: Ssel Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + } + } + +/************************************************************************/ +/* _tsel_EFun */ +/************************************************************************/ + +static ST_VOID _tsel_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + +ST_UINT hexStrLen = 0; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if ((!init_dirser_called) || + (init_dirser_called && rem_section_flag == SD_TRUE)) + { + if (ascii_to_hex_str (currTransEl->pres_addr.tsel,&hexStrLen,MAX_TSEL_LEN,str) + == SD_SUCCESS) + { + currTransEl->pres_addr.tsel_len = hexStrLen; + } + else + { + SXLOG_ERR0 ("ERROR: Tsel Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + } + } + +/************************************************************************/ +/* _transportType_EFun */ +/************************************************************************/ + +static ST_VOID _transportType_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + + if (!str) + { + SXLOG_ERR0 ("ERROR: TransportType Data Conversion Error"); + } + else + { + if (stricmp (str, "TCP") == 0) + currTransEl->pres_addr.tp_type = TP_TYPE_TCP; +#if !defined(MMSEASE_MOSI) + else if (stricmp (str, "TP4") == 0) + currTransEl->pres_addr.tp_type = TP_TYPE_TP4; + else if (stricmp (str, "TPX") == 0) + { + currTransEl->pres_addr.tp_type = TP_TYPE_TPX; + } +#endif /* !defined(MMSEASE_MOSI) */ + else + { + SXLOG_ERR0 ("ERROR: Invalid TransportType Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + } + + } + +/************************************************************************/ +/************************************************************************/ +/* _remoteAddresses_SFun */ +/************************************************************************/ + +static ST_VOID _remoteAddresses_SFun (SX_DEC_CTRL *sxDecCtrl) + { + SX_PUSH (RemoteAddressesElements); + } + +/************************************************************************/ +/* _remoteArName_SFun */ +/************************************************************************/ + +static ST_VOID _remoteArName_SFun (SX_DEC_CTRL *sxDecCtrl) + { + SX_PUSH (RemoteArNameElements); + + currTransEl = (TRANS_DEV_INFO *) chk_calloc (1, sizeof(TRANS_DEV_INFO)); +#if defined(MMSEASE_MOSI) + currTransEl->pres_addr.tp_type = TP_TYPE_TCP; /* Default=TCP */ +#else + currTransEl->pres_addr.tp_type = TP_TYPE_TP4; /* Default=TP4 */ +#endif + list_add_last (&remoteTransList, currTransEl); + + rem_section_flag = SD_TRUE; + } + +/************************************************************************/ +/* _netAddr_EFun */ +/************************************************************************/ + +static ST_VOID _netAddr_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + + if (stricmp(sxDecCtrl->sxDecElInfo.attr[0].value, "IPADDR")==0) + { +#if defined (TP0_ENABLED) /* Just ignore if disabled. */ + if (!str) + { + SXLOG_ERR0 ("NetAddr Type=IPADDR Data Conversion Error: null string"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + currTransEl->pres_addr.tp_type = TP_TYPE_TCP; + if ((currTransEl->pres_addr.netAddr.ip = tp0_convert_ip (str)) + == htonl(INADDR_NONE)) + { + SXLOG_ERR1 ("NetAddr Type=IPADDR '%s' invalid", str); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + } +#else + SXLOG_ERR1 ("NetAddr Type=IPADDR not allowed in RemoteAddress='%s' (TCP not supported). This entry ignored.", currTransEl->name); + list_unlink (&remoteTransList, currTransEl); /* discard this address*/ +#endif + } + +#if !defined(MMSEASE_MOSI) + else if (stricmp(sxDecCtrl->sxDecElInfo.attr[0].value, "NSAP")==0) + { +#if defined (TP4_ENABLED) /* Just ignore if disabled. */ +ST_UINT hexStrLen=0; + /* NSAP valid only for remote DIB */ + /* NOTE: array size is MAX_IP_ADDR_LEN. Must be >= CLNP_MAX_LEN_NSAP.*/ + if (ascii_to_hex_str (currTransEl->pres_addr.netAddr.nsap,&hexStrLen,CLNP_MAX_LEN_NSAP,str) + == SD_SUCCESS) + { + currTransEl->pres_addr.nsap_len = hexStrLen; + currTransEl->pres_addr.tp_type = TP_TYPE_TP4; + } + else + { + /*cfg_set_config_err();*/ + SXLOG_ERR0 ("NetAddr Type=NSAP Data Conversion Error"); + } +#else + SXLOG_ERR1 ("NetAddr Type=NSAP not allowed in RemoteAddress='%s' (OSI not supported). This entry ignored.", currTransEl->name); + list_unlink (&remoteTransList, currTransEl); /* discard this address*/ +#endif + } +#endif /* !defined(MMSEASE_MOSI) */ + + else + { + SXLOG_ERR1 ("NetAddr Type='%s' invalid", sxDecCtrl->sxDecElInfo.attr[0].value); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + } + +/************************************************************************/ +/* _port_EFun */ +/************************************************************************/ + +static ST_VOID _port_EFun (SX_DEC_CTRL *sxDecCtrl) + { +ST_BOOLEAN rc; +ST_CHAR *str; +ST_INT strLen; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return; + +#if defined (TP0_ENABLED) /* Just ignore if disabled. */ + if (!init_dirser_called) + { + ST_UINT16 uShortInt = 0; + + if (asciiToUint16(str,&uShortInt) != SD_SUCCESS) + { + SXLOG_ERR0 ("ERROR: Port Data Conversion Error"); + sxDecCtrl->errCode = SX_ERR_CONVERT; + } + else + { + currTransEl->pres_addr.port = uShortInt; + } + } +#endif /* TP0_ENABLED */ + } + + +/************************************************************************/ +/* save_loc_rem_dib_tables */ +/*----------------------------------------------------------------------*/ +/* This function will initialize local and remote dib entries tables. */ +/* */ +/* Parameters: */ +/* void none */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if initialization successful. */ +/* SD_FAILURE (1) otherwise */ +/* NOTES: Does not allow reconfiguration of loc_dib_table. */ +/* Allows reconfiguration of rem_dib_table, but only after */ +/* freeing the old table. */ +/************************************************************************/ + +static ST_RET save_loc_rem_dib_tables (void) + { +ST_RET ret; +ST_INT j; + + ret = SD_SUCCESS; + + if (!init_dirser_called) /* Don't allow reconfiguring. */ + { + num_loc_dib_entries = list_get_sizeof (localTransList); + if (num_loc_dib_entries) + { + loc_dib_table = (DIB_ENTRY *) chk_calloc (num_loc_dib_entries, sizeof (DIB_ENTRY)); + save_dib_table (localTransList, loc_dib_table); + } + } + + /* If Remote DIB table already configured, FREE OLD BEFORE ALLOCATING NEW!*/ + if (init_dirser_called) + { + for (j = 0; j < num_rem_dib_entries; j++) + chk_free (rem_dib_table [j].name); + chk_free (rem_dib_table); + } + + num_rem_dib_entries = list_get_sizeof (remoteTransList); + if (num_rem_dib_entries) + { + rem_dib_table = (DIB_ENTRY *) chk_calloc (num_rem_dib_entries, sizeof (DIB_ENTRY)); + save_dib_table (remoteTransList, rem_dib_table); + } + return (ret); + } + +/************************************************************************/ +/* save_dib_table */ +/*----------------------------------------------------------------------*/ +/* This function copies the temporary DIB Table to the permanent */ +/* DIB Table. It may be used for the Local as well as the Remote DIB */ +/* Tables. */ +/* */ +/* Parameters: */ +/* TRANS_DEV_INFO * temporary table (linked list of structs) */ +/* DIB_ENTRY * permanent table (array of structs) */ +/* */ +/************************************************************************/ + +static ST_VOID save_dib_table (TRANS_DEV_INFO *TransList, DIB_ENTRY *de) + { +TRANS_DEV_INFO *toFree; +TRANS_DEV_INFO *d; + + d = TransList; /* Point to first in linked list */ + while (d) + { + de->name = (ST_CHAR *) chk_malloc (strlen(d->name) + 1); + strcpy (de->name, d->name); + if (strlen (d->apTitle)) + { + if (parseObjId (&de->AP_title, d->apTitle)) + { + ACSELOG_ERR1 ("Invalid AP Title '%s'. Ignored.", d->apTitle); + } + else + de->AP_title_pres = SD_TRUE; /* defaults to FALSE */ + } + + if (strlen (d->aeQual)) + { + de->AE_qual_pres = SD_TRUE; /* defaults to FALSE */ + de->AE_qual = atol (d->aeQual); + } + + de->AP_inv_id_pres = SD_FALSE; + de->AE_inv_id_pres = SD_FALSE; + + memcpy (&de->pres_addr, &d->pres_addr, sizeof (PRES_ADDR)); + + toFree = d; + d = (TRANS_DEV_INFO *) list_get_next (TransList, d); /* Point to next TRANS_DEV_INFO */ + chk_free (toFree); + ++de; /* Point to next DIB_ENTRY */ + } /* End "while" */ + + TransList = NULL; /* CRITICAL: clean up in case reconfigure later.*/ + } + +/************************************************************************/ +/* parseObjId */ +/*----------------------------------------------------------------------*/ +/* Parses components of the 'ApTitle'. */ +/************************************************************************/ + +static ST_RET parseObjId (MMS_OBJ_ID *objId, ST_CHAR *buff) + { +char *numStr; +ST_CHAR *seps = " \t"; /* delimiters to search for */ + + /* Found keyword 'ApTitle', read the components */ + objId->num_comps = 0; + numStr = get_next_string (&buff, seps); /* "buff" ptr changes */ + while (numStr && strlen (numStr) > 0) + { + if (objId->num_comps >= MAX_OBJID_COMPONENTS) + { + return (SD_FAILURE); + } + objId->comps[objId->num_comps] = (ST_INT16) atoi (numStr); + numStr = get_next_string (&buff, seps); /* "buff" ptr changes */ + ++objId->num_comps; + } + if (objId->num_comps == 0) /* couldn't parse anything */ + return (SD_FAILURE); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* printDibEntry */ +/************************************************************************/ +static ST_VOID printDibEntry (ST_VOID) +{ +DIB_ENTRY *de; +ST_INT i; +ST_INT table_type; + + SXLOG_DEBUG0 (" LOCAL DIB TABLE"); + + for (i = 0; i < num_loc_dib_entries; i++) + { + table_type = LOCAL_DIB_TABLE; + de = &loc_dib_table[i]; + printDibStruct(de,table_type); + } + + SXLOG_DEBUG0 (" REMOTE DIB TABLE"); + + for (i = 0; i < num_rem_dib_entries; i++) + { + table_type = REMOTE_DIB_TABLE; + de = &rem_dib_table[i]; + printDibStruct(de,table_type); + } + + } + +/************************************************************************/ +/* printDibStruct */ +/************************************************************************/ +static ST_VOID printDibStruct (DIB_ENTRY *de,ST_INT table_type) + { +ST_INT i; +ST_UINT k; + + SXLOG_CDEBUG0 (" "); + SXLOG_CDEBUG1 (" Common_Name = %s",de->name); + SXLOG_CDEBUG1 (" local = %s ",de->local ? "SD_TRUE":"SD_FALSE"); + SXLOG_CDEBUG1 (" AP_title_pres = %s", de->AP_title_pres ? "SD_TRUE":"SD_FALSE"); + for (i = 0; i < de->AP_title.num_comps; ++i) + SXLOG_CDEBUG2 (" AP_title.comps[%d] = %d",i,de->AP_title.comps[i]); + SXLOG_CDEBUG2 (" AE_qual_pres = %s AE_qual = %ld", + de->AE_qual_pres ? "SD_TRUE":"SD_FALSE",de->AE_qual); + SXLOG_CDEBUG2 (" AP_inv_id_pres = %s AP_invoke_id = %ld", + de->AP_inv_id_pres ? "SD_TRUE":"SD_FALSE",de->AP_invoke_id); + SXLOG_CDEBUG2 (" AE_inv_id_pres = %s AE_invoke_id = %ld", + de->AE_inv_id_pres ? "SD_TRUE":"SD_FALSE",de->AE_invoke_id); + + SXLOG_CDEBUG1 (" psel_len = %d psel =",de->pres_addr.psel_len); + for (k = 0; k < de->pres_addr.psel_len; k++) + SXLOG_CDEBUG1 (" %02x",de->pres_addr.psel[k]); + + SXLOG_CDEBUG1 (" ssel_len = %d ssel =",de->pres_addr.ssel_len); + for (k = 0; k < de->pres_addr.ssel_len; k++) + SXLOG_CDEBUG1 (" %02x",de->pres_addr.ssel[k]); + + SXLOG_CDEBUG1 (" tsel_len = %d tsel =",de->pres_addr.tsel_len); + for (k = 0; k < de->pres_addr.tsel_len; k++) + SXLOG_CDEBUG1 (" %02x",de->pres_addr.tsel[k]); + + if (de->pres_addr.tp_type == TP_TYPE_TCP) + { + SXLOG_CDEBUG1 (" tp_type = %s ","TCP"); + } + else if (de->pres_addr.tp_type == TP_TYPE_TP4) + { + SXLOG_CDEBUG1 (" tp_type = %s ","TP4"); + } + else if (de->pres_addr.tp_type == TP_TYPE_TPX) + { + SXLOG_CDEBUG1 (" tp_type = %s ","TPX"); + } + + + if (table_type == REMOTE_DIB_TABLE) + { + if (de->pres_addr.tp_type == TP_TYPE_TP4) + { + SXLOG_CDEBUG1 (" nsap_len = %d nsap =",de->pres_addr.nsap_len); + for (k = 0; k < de->pres_addr.nsap_len; k++) + SXLOG_CDEBUG1 (" %02x",de->pres_addr.netAddr.nsap[k]); + } + +#if defined(TP0_ENABLED) + if (de->pres_addr.tp_type == TP_TYPE_TCP) + { + struct in_addr sin_addr; /* inet_ntoa needs this addr format*/ + sin_addr.s_addr = de->pres_addr.netAddr.ip; + SXLOG_CDEBUG1 (" ip_addr (s) = %s",inet_ntoa (sin_addr)); + SXLOG_CDEBUG1 (" port = %s",de->pres_addr.port); + } +#endif + } + + } +/*#endif*/ /* if defined 0 */ diff --git a/mmslib/ositcps/tp0_dec.c b/mmslib/ositcps/tp0_dec.c new file mode 100644 index 0000000..735aabc --- /dev/null +++ b/mmslib/ositcps/tp0_dec.c @@ -0,0 +1,181 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997 All Rights Reserved */ +/* */ +/* MODULE NAME : tp0_dec.c */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* TP0 decode functions. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* np_data_ind () */ +/* np_disconnect_ind () */ +/* np_connect_cnf_pos () */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/22/08 JRB 06 TPDU must be at least 2 bytes to decode. */ +/* Chg tp_decode_er to really decode ER TPDU. */ +/* 04/07/03 JRB 05 Add SPDU_RX_NO_PREALLOCATE option. */ +/* 04/13/00 JRB 04 Lint cleanup. */ +/* 08/13/98 JRB 03 Lint cleanup. */ +/* 09/25/97 JRB 02 Don't generate exception for invalid state. */ +/* 08/01/97 JRB 01 Created (compatible with MMS-EASE 7.0). */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "tp4api.h" /* User definitions for tp4 */ +#include "tp4.h" /* Internal definitions for tp4 */ +#include "tp4_encd.h" +#include "tp4_log.h" + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* np_data_ind */ +/* This "np_data_ind" funct is similar to "tp_decode_nsdu" used for TP4.*/ +/* It calls one function to decode the PDU, then another function to */ +/* process it. The "decode" functions are shared with TP4. */ +/************************************************************************/ +ST_VOID np_data_ind (SOCK_INFO *sock_info, ST_UCHAR *pdu_ptr, ST_UINT16 pdu_len) + { +ST_UCHAR type; +ST_UINT16 len; /* len of processed TPDU by a dec func */ +TPDU_CX tpdu_cx_rx; /* tpdu_cr_rx or tpdu_cc_rx */ +TPDU_DR tpdu_dr_rx; +TPDU_DT tpdu_dt_rx; +TPDU_ER tpdu_er_rx; + + /* TP0 TPDU starts after TPKT hdr (RFC1006_HEAD_LEN bytes). */ + /* TPDU must be at least 2 bytes (len and TPDU code) to safely decode.*/ + if (pdu_len < RFC1006_HEAD_LEN + 2) + { + TP_LOG_ERR0 ("TP0 TPDU too short to decode. Ignored."); + return; + } + + /* Strip off TPKT header. */ + pdu_len -= RFC1006_HEAD_LEN; + pdu_ptr += RFC1006_HEAD_LEN; + + /* get the TPDU type (from the second octet, bits 4-7) */ + type = pdu_ptr [1] & TP_PDU_MASK_CDT; + + /* Based on type of TPDU (CR, CC, DT, etc.) call appropriate decode */ + /* subfunction. */ + + switch (type) + { + case TP_PDU_TYPE_CR: + case TP_PDU_TYPE_CC: + if ((len = tp_decode_cx (&tpdu_cx_rx, pdu_ptr, pdu_len, type, + TP_PDU_MAX_SIZE_65531)) != 0) /* Default TPDU size=65531*/ + { + tpdu_cx_rx.sock_info = sock_info; + + tp_log_tsdu ((ST_VOID *) &tpdu_cx_rx, type, TP_IND); + /* This is the only step different in processing CR or CC. */ + if (type == TP_PDU_TYPE_CR) + tp0_process_cr (&tpdu_cx_rx); + else + tp0_process_cc (&tpdu_cx_rx); + } + break; + + case TP_PDU_TYPE_DR: + if ((len = tp_decode_dr (&tpdu_dr_rx, pdu_ptr, pdu_len)) != 0) + { + tpdu_dr_rx.sock_info = sock_info; + + tp_log_tsdu ((ST_VOID *) &tpdu_dr_rx, TP_PDU_TYPE_DR, TP_IND); + tp0_process_dr (&tpdu_dr_rx); + } + break; + + case TP_PDU_TYPE_DT: + if ((len = tp0_decode_dt (&tpdu_dt_rx, pdu_ptr, pdu_len)) != 0) + { + tpdu_dt_rx.sock_info = sock_info; + + tp_log_tsdu ((ST_VOID *) &tpdu_dt_rx, TP_PDU_TYPE_DT, TP_IND); + tp0_process_dt (&tpdu_dt_rx); + } + break; + + case TP_PDU_TYPE_ER: + /* NOTE: the last arg indicates this is Transport Class 0. */ + if ((len = tp_decode_er (&tpdu_er_rx, pdu_ptr, pdu_len, 0)) > 0) + { + /* decode succeeded but we ignore ER TPDU. Log so user knows.*/ + TP_LOG_ERR0 ("DEBUG: processing of TPDU-ER.ind not implemented yet."); + } + break; + + case TP_PDU_TYPE_ED: /* we do not support expedited data */ + case TP_PDU_TYPE_EA: + TP_LOG_ERR0 ("TP-ERROR: decode ED or EA TPDU failed (not supported)"); + break; /* Do nothing */ + + default: /* type unknown, we should exit decoding */ + TP_LOG_ERR1 ("TP-ERROR: decode TPDU failed (invalid type 0x%2.2X)", + (unsigned) type); + break; + } /* end "switch" */ + } +/************************************************************************/ +/* np_disconnect_ind */ +/************************************************************************/ +ST_VOID np_disconnect_ind (SOCK_INFO *sock_info) + { +TP0_CONN *tp_conn; +ST_INT reason; /* Transport Disconnect reason */ + + if (sock_info->user_conn_id == INVALID_CONN_ID) + return; /* Transport doesn't know about connection yet. IGNORE. */ + + tp_conn = (TP0_CONN *) sock_info->user_conn_id; + switch (tp_conn->state) + { + case TP_STATE_WFNC: + case TP_STATE_WFCC: + case TP_STATE_OPEN: + case TP_STATE_WFTRESP: + reason = 0; /* Normal disconnection */ + /* NOTE: To save memory, user data is never passed up to user. */ + tp4_disconnect_ind (tp_conn->user_conn_id, reason, + 0, NULL); /* No user data passed up. */ + tp_conn->state = TP_STATE_CLOSED; +#if defined(SPDU_RX_NO_PREALLOCATE) + M_FREE (MSMEM_STARTUP, tp_conn->spdu_rx.spdu_ptr); +#endif + break; + default: + TP_LOG_ERR1 ("TP-ERROR: invalid state (%d) for N-DISCONNECT.ind. Ignored.", + tp_conn->state); + break; + } + } +/************************************************************************/ +/* np_connect_cnf_pos */ +/************************************************************************/ +ST_VOID np_connect_cnf_pos (SOCK_INFO *sock_info, ST_LONG user_conn_id) + { +TP0_CONN *tp_conn = (TP0_CONN *) user_conn_id; + + /* Save sock_info ptr in tp_conn. */ + tp_conn->sock_info = sock_info; + + /* CRITICAL: Save sock_info in tp_conn->tpdu_cx before calling tp0_send_cr*/ + tp_conn->tpdu_cx.sock_info = tp_conn->sock_info; + + /* Send T-CONNECT.req */ + tp0_send_cr (&tp_conn->tpdu_cx); + tp_conn->state = TP_STATE_WFCC; + } diff --git a/mmslib/ositcps/tp0_socks.c b/mmslib/ositcps/tp0_socks.c new file mode 100644 index 0000000..22ba69c --- /dev/null +++ b/mmslib/ositcps/tp0_socks.c @@ -0,0 +1,1937 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003-2008, All Rights Reserved */ +/* */ +/* MODULE NAME : tp0_socks.c */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* TP0 functions for dealing with secured sockets interface (SSL). */ +/* Uses "gensock2" as intermediate interface to sockets. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/10/08 JRB 38 _uSockHunt: make sure len is legal. */ +/* Ignore empty msg (len=RFC1006_HEAD_LEN). */ +/* 02/21/08 EJV 37 _uSockHunt: corr lenOut for 0x8000-0xFFFF len*/ +/* 09/10/07 MDE 36 Updated to use new SOCK_LOG_ macros */ +/* 02/16/07 JRB 35 Use new sockEventPut, sockEventGet functions */ +/* and new "uSockConnectInd/Conf" funct ptrs. */ +/* 01/30/07 JRB 34 readyToFree flag was deleted so don't use it.*/ +/* 01/15/07 JRB 33 Del poll_mode arg to sockStart. */ +/* 01/15/07 EJV 32 Rpl TP0_SOCKS_MUTEX_* with S_LOCK_UTIL_RESOURCES */ +/* due to mutex changes in gensock2.c. */ +/* TP0_SOCK_CTX: rem listsMutex create/destroy. */ +/* 12/11/06 EJV 31 rfc1006_listener_connect: chg nonblock_on */ +/* from ST_LONG to int. */ +/* Needed on 64-bit UNIX, Linux systems. */ +/* 11/29/06 EJV 30 recvwait_fd: chg __hpux to use the SCM_RIGHTS*/ +/* 11/17/06 EJV 29 socket funs: added (int) cast, the HP-UX */ +/* ssize_t is long. */ +/* recvwait_fd: impl timeout for recvmsg loop */ +/* 11/07/06 EJV 28 MMSEASE_MOSI:init tp0Ctx.tcpEventWakeupPort=0*/ +/* 07/10/06 EJV 27 MMSEASE_MOSI: finished GEN_SOCK_CTXT work. */ +/* Use sysincs.h for system includes. */ +/* Changed sun to s_un (err on Sun Solaris) */ +/* 01/30/06 GLB 26 Integrated porting changes for VMS */ +/* 12/15/05 EJV 24 _processDisconnectInd: call list_find_node */ +/* 12/07/05 EJV 23 _processDisconnectInd: unlink if on the list */ +/* _processConnectDone: moved secEnable code to */ +/* case for SOCK_STATE_CONNECTED state. */ +/* 10/04/05 EJV 22 Implemented GEN_SOCK_CTXT and other changes: */ +/* Renamed orginal SOCK_CTX to TP0_SOCK_CTX, */ +/* sockCtx to tp0Ctx. */ +/* _uSockDisconnectInd: mk errptr more readable */ +/* _addSockInd: chg to ST_RET from ST_VOID */ +/* _sockClose: moved code to _sockCloseAllListen*/ +/* np_end: added new call to _sockCloseAllListen*/ +/* Rpl GSOCK_MUTEX_* with TP0_SOCKS_MUTEX_*. */ +/* Folded some glb vars into the TP0_SOCK_CTX. */ +/* Reversed Rev 21 change, not needed anymore. */ +/* 08/03/05 EJV 20 Reworked rekeyTime to be per connection. */ +/* Use sockCtx glb (instead saving it in usr1). */ +/* 07/19/05 EJV 19 _processConnectInd: set usr2 back to NULL. */ +/* _processConnectDone: if secEnable don't free */ +/* sock_info. Check state. */ +/* np_disconnect_req:check other states, add log*/ +/* 07/01/05 EJV 18 _uSockWritable CORR: removed state chg. */ +/* 06/24/05 EJV 17 Added code to prevent queues buildup. */ +/* 05/02/05 JRB 16 Add RFC1006_LISTENER task code (MMSEASE_MOSI)*/ +/* EJV Added _sockSetDefaults. */ +/* 05/05/05 EJV 15 Use rfc1006_listen_port if configured */ +/* 04/21/05 JRB 14 Fix logging of sin_port (use ntohs). */ +/* Del unused vars. */ +/* 04/13/05 EJV 13 Corr EADDRINUSE to SOCK_EADDRINUSE */ +/* 03/22/05 EJV 12 LINUX (MMSEASE_MOSI): implemented events. */ +/* _sockInitListen: allow to SO_REUSEADDR. */ +/* Added indTypeStr. Added/chg logging. */ +/* 03/16/05 JRB 11 _uSockHunt: allow any val for 2nd byte & */ +/* ret ..HUNT_DISCONNECT on err to cause disconn*/ +/* For speed, set ptr to strings instead of strcpy.*/ +/* Use RFC1006 defines from tp0_sock.h. */ +/* 03/07/05 EJV 10 Fixed queuing bug where connectInd sometimes */ +/* processed AFTER disconnectInd by moving */ +/* sec cleanup from _uSockDisconnectInd to */ +/* _processDisconnectInd. */ +/* Moved sec code from _uSockConnectDone to */ +/* _processConnectDone,for consistency w/con ind*/ +/* Use secEnable (in place of other sec fields) */ +/* 02/19/04 EJV 09 np_end: chg sleep from 1000 to 100 ms */ +/* 02/18/04 JRB 08 _uSockDisconnectInd: DON'T chk state, only */ +/* safe from main thread (_processDisconnectInd)*/ +/* np_end: allow disconnects to finish. */ +/* 02/06/04 JRB 07 np_disconnect_req:Chg assert to log & ret err*/ +/* 01/28/04 EJV 06 _handleRekeying:chk if connected before rekey*/ +/* 01/23/04 EJV 05 np_data_req: sockTxMsg will free sockData. */ +/* 01/21/04 JRB 04 Do most disconnect processing in callback */ +/* _uSockDisconnectInd. */ +/* EJV Change test for rekey to '>=' */ +/* 01/14/04 EJV 03 np_data_req: added eot param. */ +/* Free buff if sockTxMsg fails. */ +/* Added np_get_tx_queue_cnt func. */ +/* 10/16/03 JRB 02 Port to LINUX. Chg SOCKET to (GEN_SOCK *). */ +/* Compare (GEN_SOCK *) to NULL, not INVALID_...*/ +/* 07/29/03 EJV 01 New. Replacement for tp0_sock.c using */ +/* gensock2 to interface to sockets. */ +/* Used tp0_sock2.c and snapmain.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" + +#include "mem_chk.h" +#include "ssec.h" +#include "ssec_int.h" +#include "tp4api.h" /* User definitions for tp4 */ +#include "tp4.h" /* Internal definitions for tp4 */ +#include "tp4_log.h" +#include "tp0_sock.h" +#include "sock_log.h" +#if defined(MMSEASE_MOSI) +#include "gensock2.h" +#endif + +#ifdef MMS_LITE +#include "mvl_acse.h" /* Need "mvl_num_called". */ +#endif + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/* This many messages can accumulate in the receiving ind queue */ +/* for given socket before we stop receiving, start receiving after */ +/* we reach low mark. */ +#define SOCK_RX_QUE_HIGH_MARK 10 /* >= stop receiving */ +#define SOCK_RX_QUE_LOW_MARK 1 /* <= start receiving */ + +ST_CHAR *eventTypeStr[5] = + { + "UNKNOWN", + "CONNECT_IND", + "CONNECT_CONF", + "DISCONNECT", + "RXDATA" + }; + +/* Similar to sock_info_alloc but uses GEN_SOCK. */ +SOCK_INFO *sock_info_alloc2 (GEN_SOCK *genSock, ST_INT state, ST_LONG user_conn_id); + +/* Functions to process indications/events. */ +static ST_RET _setSecInfo (GEN_SOCK *pSock, S_SEC_ENCRYPT_CTRL *encrypt_ctrl); +static ST_VOID _processConnectInd (GEN_SOCK *pSock); +static ST_VOID _processConnectDone (GEN_SOCK *pSock); +static ST_VOID _processDisconnectInd (GEN_SOCK *pSock); +static ST_VOID _processRxInd (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData); + +/* gensock2 callback functions */ +static ST_RET _uSockConnectDone (GEN_SOCK *pSock); +static ST_RET _uSockConnectInd (GEN_SOCK *pSock); +static ST_VOID _uSockDisconnectInd (GEN_SOCK *pSock); +static ST_VOID _uSockRxInd (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData); +static ST_VOID _uSockWritable (GEN_SOCK *pSock); +static ST_VOID _uSockHunt (GEN_SOCK *pSock, ST_INT *huntStateIo, + ST_CHAR *buf, ST_INT bufCount, ST_INT *lenOut); +static ST_VOID _uSockDataAlloc (GEN_SOCK *pSock, ST_INT dataLen, + GEN_SOCK_DATA **sockDataOut); +static ST_VOID _uSockDataFree (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData); + +/* misc functions */ +static ST_RET _addSockInd (GEN_SOCK *pSock, ST_INT indType, + GEN_SOCK_DATA *sockData); +static ST_RET _handleRekeying (ST_VOID); + +#define SOCK_REKEY_TIME 1000 /* check every 1000 ms if we need to rekey */ + + +/************************************************************************/ +/* Global variables. */ +/************************************************************************/ +int pipe_to_main; /* Linker needs this, but it is never used. */ + +#if defined(_WIN32) +ST_EVENT_SEM hTcpEvent; /* to notify user about network events */ +#endif + +#if defined(MMSEASE_MOSI) +/*----------------------------------------------------------------------*/ +/* NOTES: */ +/* 1. We set SO_KEEPALIVE opt on TCP sockets (in/out connections). */ +/* 2. We set SO_REUSEADDR on TCP sockets (in connections). */ +/* 3. The domain socket and TCP sockets are all non-blocking. */ +/* 4. How many fds we can FD_SET (for TCP connections in gensock2) ? */ +/* From the Linux: in the /usr/include/linux/posix_types.h the */ +/* __FD_SETSIZE is 1024 (FD_SETSIZE) */ +/* In gensock2.c there will be one service thread for every */ +/* GS_MAX_SOCK_PER_SERVICE defined to be (FD_SETSIZE - 1). */ +/*----------------------------------------------------------------------*/ + +#if !defined(GENSOCK_THREAD_SUPPORT) +#error GENSOCK_THREAD_SUPPORT must be defined for MMSEASE_MOSI +#endif + +/* NOTE: These two sockets below need to be added to user's application */ +/* select() statement. */ +/* The mms_event_fd must always be added since it indicates events on */ +/* all the TCP connections. */ +/* The domsock_listener need to be added only if the flag */ +/* use_rfc1006_listener_task=SD_TRUE. */ +SOCKET mms_event_fd = INVALID_SOCKET; /* wakeup socket, indicating TCP Events */ +SOCKET domsock_listener = INVALID_SOCKET; /* domain socket connected to the */ + /* RFC1006_LISTENER task. */ +ST_BOOLEAN use_rfc1006_listener_task = SD_TRUE; /*DEBUG:: add to tp0_cfg struct? */ +#else /* !defined(MMSEASE_MOSI) */ +ST_BOOLEAN use_rfc1006_listener_task = SD_FALSE; +#endif /* !defined(MMSEASE_MOSI) */ + +/* use macro to simplify the code */ +#define CLOSE_THIS_SOCKET(hSock) \ + { \ + if (hSock != INVALID_SOCKET) \ + { \ + CLOSE_SOCKET (hSock); \ + hSock = INVALID_SOCKET; \ + } \ + } + +/* listening socket types */ +#define SOCK_LISTEN_NON_SSL 1 +#define SOCK_LISTEN_SSL 2 + +/* Ctx state */ +#define TP0_SOCK_CTX_STATE_IDLE 0 +#define TP0_SOCK_CTX_STATE_ACTIVE 1 +#define TP0_SOCK_CTX_STATE_TERMINATING 2 + +/* struct to hold configuration and communication info for secured and */ +/* non-secured connections. */ +typedef struct tag_tp0_sock_ctx + { + ST_UINT state; /* TP0_SOCK_CTX_STATE_xxx */ + S_SEC_CONFIG *secCfg; /* ptr to global configuration */ + ST_UINT16 rfc1006Port; /* save the listen port used for RFC1006 connections */ + GEN_SOCK *remListenSock; /* listen socket for non-secured cons from remotes */ + GEN_SOCK *remListenSockSSL[S_SSL_MAX_LISTEN_PORTS]; /* tbl of secure listen sockets for */ + /* connections from remotes */ + SOCK_INFO *secureSockList; /* list of secured sockets */ + + #if defined(MMSEASE_MOSI) + ST_UINT16 tcpEventWakeupPortBase; /* base listen port */ + ST_UINT tcpEventWakeupPortRange; /* range to search for free port */ + ST_UINT16 tcpEventWakeupPort; /* actual wakeup port */ + SOCKET hTcpEventSender; /* signaled by gensock2 service thread */ + ST_CHAR listenerIPCDir[256]; /* IPC directory (where to find domsock file); */ + /* set by calling setListenerIPCDir fun. If it */ + /* is not set by user appl the default dir */ + /* RFC1006_LISTENER_IPC_PATH will be used. */ + #endif /* defined(MMSEASE_MOSI) */ + + + GEN_SOCK_CTXT *sockCtx; /* this is gensock2 context for tp0_socks.c */ + } TP0_SOCK_CTX; + +TP0_SOCK_CTX tp0Ctx; /* must be global for !GENSOCK_THREAD_SUPPORT in event2.c */ + + +static ST_RET _sockSetDefaults (GEN_SOCK_CONFIG *sockCfg); +static ST_RET _sockInitListen (ST_UINT type, ST_UINT idx, ST_INT max_num_conns); +static ST_RET _sockCloseAllListen (ST_VOID); +static ST_RET _sockClean (ST_VOID); + + /*----------------------------------------------*/ + /* MMSEASE_MOSI - RFC1006 Listener funcs */ + /*----------------------------------------------*/ + +#if defined(MMSEASE_MOSI) + +/************************************************************************/ +/* setListenerIPCDir */ +/* This function would be called by user application to set the */ +/* RFC1006_LISTENER daemon IPC directory where UNIX domain socket */ +/* should be created. If this function is not called the default path */ +/* RFC1006_LISTENER_IPC_PATH will be used. */ +/************************************************************************/ +ST_RET setListenerIPCDir (ST_CHAR *dirPath) + { +ST_RET rtn = SD_FAILURE; + + if (dirPath && strlen (dirPath) > 0) + { + strcpy (tp0Ctx.listenerIPCDir, dirPath); /* path to domsock file */ + rtn = SD_SUCCESS; + } + return (rtn); + } + + +/* This section copied exactly from tp0_unix.c */ + +/************************************************************************/ +/* This a special recv function only for receiving the socket handle */ +/* from the "rfc1006_listener" task. It waits as long as the error is */ +/* SOCK_WOULDBLOCK. On any other error, it stops waiting and returns. */ +/* This function needs to take in account that the sender may fail in */ +/* the sendmsg() by implementing timeout when waiting for the socket fd.*/ +/************************************************************************/ +ssize_t recvwait_fd (int fd, void *ptr, size_t nbytes, int *recvfd) + { +struct msghdr msg; +struct iovec iov[1]; +ssize_t ret; +int err; +ST_DOUBLE recvmsg_start; + +#define RECVMSG_TIMEOUT 10000 /* in milliseconds */ + +#if defined (OLD_WAY) + /* NOTE: On HP-UX to use the msg_accrights fields compile without */ + /* defining the -D_XOPEN_SOURCE_EXTENDED, -D_OPEN_SOURCE and */ + /* without linking the -lxnet library). */ +#else + /* NOTE: On HP-UX to use the SCM_RIGHTS msg type compile with the */ + /* -D_XOPEN_SOURCE_EXTENDED, -D_OPEN_SOURCE and link with the */ + /* -lxnet library. Without linking the libxnet.* library the */ + /* sendmsg() fails with EBADF error. */ + /* See Richard Stevens "UNIX Network Programming" book. */ + +/* this just helps get alignment right */ +union + { + struct cmsghdr cm; + char control [CMSG_SPACE(sizeof(int))]; + } control_un; +struct cmsghdr *cmptr; +#endif + + SOCK_LOG_FLOW1 ("domsock %d: in recvwait_fd()", fd); + + *recvfd = -1; /* init to invalid handle just in case the receive fails*/ + +#if defined (OLD_WAY) + msg.msg_accrights = (caddr_t) recvfd; + msg.msg_accrightslen = sizeof (int); /* must be int */ +#else + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof (control_un.control); +#endif + + msg.msg_name = NULL; + msg.msg_namelen = 0; + + iov[0].iov_base = ptr; + iov[0].iov_len = nbytes; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + + /* Wait for data as long as error is SOCK_WOULDBLOCK. Stop on any other error.*/ + /* NOTE: at this time there is only 1 byte of dummy data sent with this */ + /* special message, but if this is changed to more bytes then the */ + /* non-blocking recvmsg function may return with partial bytes. */ + recvmsg_start = sGetMsTime(); + while ((ret = recvmsg(fd, &msg, 0)) < 0) + { + err = SOCKET_ERRORNO; + if (!(err == SOCK_WOULDBLOCK || err == SOCK_INTR || + err == SOCK_TIMEDOUT || err == SOCK_INPROGRESS)) + break; /* some non-recoverable socket error */ + + /* check is we want to still wait longer for the msg */ + if ((sGetMsTime() - recvmsg_start) >= RECVMSG_TIMEOUT) + { + SOCK_LOG_NERR3 ("domsock %d: timed out in recvmsg(), errno = %d, timeout=%d", fd, err, RECVMSG_TIMEOUT); + return (ret); /* timeout, other side failed to send the socket handle */ + } + sMsSleep(20); /* sleep for a moment while waiting for the msg */ + } + if (ret <= 0) + { + SOCK_LOG_NERR2 ("domsock %d: recvmsg() failed, errno = %d", fd, err); + return (ret); /* error we can't handle */ + } + +#if defined (OLD_WAY) + +#else + if ((cmptr = CMSG_FIRSTHDR(&msg)) != NULL && + cmptr->cmsg_len == CMSG_LEN(sizeof(int))) + { + if (cmptr->cmsg_level != SOL_SOCKET) + { + SOCK_LOG_NERR1 ("domsock %d: cmsg_level != SOL_SOCKET", fd); + *recvfd = -1; /* DEBUG: error. Book uses err_quit.*/ + } + else if (cmptr->cmsg_type != SCM_RIGHTS) + { + SOCK_LOG_NERR1 ("domsock %d: cmsg_type != SCM_RIGHTS", fd); + *recvfd = -1; /* DEBUG: error. Book uses err_quit. */ + } + else + *recvfd = *((int *) CMSG_DATA(cmptr)); + } + else + *recvfd = -1; /* descriptor was not passed */ +#endif + + if (*recvfd == -1) + SOCK_LOG_NERR1 ("domsock %d: DID NOT receive socket handle from RFC1006_LISTENER task", fd); + else + SOCK_LOG_FLOW2 ("domsock %d: received socket handle = %d from RFC1006_LISTENER task", + fd, *recvfd); + return (ret); + } + +/************************************************************************/ +/* check_domsock */ +/* This function checks if the there are any events pending from */ +/* RFC1006_LISTENER task. */ +/* Note that this function does not non-blocking select. */ +/************************************************************************/ +ST_RET check_domsock (int domsock) + { +fd_set rset, allset; +int nready; +int maxfd = 0; +struct timeval stTimeVal; + + if (domsock == INVALID_SOCKET) + return (SD_FALSE); + + FD_ZERO (&allset); + FD_SET (domsock, &allset); + maxfd = max (maxfd, domsock); + + rset = allset; + /* 0 timeout on select. Don't want to wait here. */ + stTimeVal.tv_sec = 0; + stTimeVal.tv_usec = 0; + nready = select (maxfd + 1, &rset, NULL, NULL, &stTimeVal); + if (nready > 0 && FD_ISSET (domsock, &rset)) + return (SD_TRUE); + return (SD_FALSE); + } + +/************************************************************************/ +/* rfc1006_listener_connect */ +/* Connects to the UNIX domain socket of the RFC1006 Listener task. */ +/* Stores the connected socket handle at the address pointed to by */ +/* domsock. */ +/************************************************************************/ +ST_RET rfc1006_listener_connect (SOCKET *domsock) + { +struct sockaddr_un s_un; +#if defined(__hpux) || defined(_AIX) || defined(sun) || defined(linux) +int nonblock_on=1; /* CRITICAL: must be non-zero to enable non-blocking*/ +#else +/* _WIN32 */ +ST_ULONG nonblock_on=1; /* CRITICAL: must be non-zero to enable non-blocking*/ +#endif +int retcode; + + *domsock = socket (AF_LOCAL, SOCK_STREAM, 0); /*DEBUG: why does some code use AF_UNIX */ + if (*domsock == INVALID_SOCKET) + { + SOCK_LOG_ERR1 ("Cannot create UNIX domain socket(), errno=%d", SOCKET_ERRORNO); + return (SD_FAILURE); + } + + s_un.sun_family = AF_LOCAL; + if (strlen (tp0Ctx.listenerIPCDir) == 0) + sprintf (s_un.sun_path, "%s/%s", RFC1006_LISTENER_IPC_PATH, RFC1006_LISTENER_DOMSOCK); + else + /* use the IPC directory that user set with call to setListenerIPCDir */ + sprintf (s_un.sun_path, "%s/%s", tp0Ctx.listenerIPCDir, RFC1006_LISTENER_DOMSOCK); + retcode = connect (*domsock, (struct sockaddr *) &s_un, sizeof (s_un)); + if (retcode == 0) + { + SOCK_LOG_FLOW2 ("domsock %d: connected to RFC1006_LISTENER task (DomSockFile=%s)", + *domsock, s_un.sun_path); + /* make the socket non-blocking */ + if (ioctlsocket (*domsock, FIONBIO, &nonblock_on) == -1) + SOCK_LOG_ERR2 ("domsock %d: cannot set socket to non-blocking mode, errno = %d.", + *domsock, SOCKET_ERRORNO); + } + else + { + SOCK_LOG_ERR3 ("domsock %d: cannot connect() to RFC1006_LISTENER task (DomSockFile=%s), errno=%d, closing socket.", + *domsock, s_un.sun_path, SOCKET_ERRORNO); + CLOSE_SOCKET (*domsock); + *domsock = INVALID_SOCKET; + } + + return (retcode); + } + +/************************************************************************/ +/* sockAcceptFromListenerTask */ +/************************************************************************/ +ST_RET sockAcceptFromListenerTask (SOCKET hNewSock, + char *tpkt_buf, /* ptr to TP0 connect.ind received from rfc1006_listener */ + int tpkt_len) + { +ST_RET rc; +GEN_SOCK_CONFIG sockCfg; +GEN_SOCK *pSock; + +#if !defined(_WIN32) + if (hNewSock >= FD_SETSIZE) + { /* Can't use this socket because illegal to use in "select" call*/ + SOCK_LOG_ERR1 ("sockAcceptFromListenerTask: socket num %d > FD_SETSIZE", hNewSock); + CLOSE_SOCKET (hNewSock); + return (SD_FAILURE); + } +#endif + + /* Usually get sockCfg from pListenSock, but don't have that here, so just init local var*/ + rc = _sockSetDefaults (&sockCfg); + + /* OK, we have a go ... */ + pSock = _sockAllocSock (tp0Ctx.sockCtx, GS_ROLE_CALLED, GS_STATE_CONNECTED, hNewSock, &sockCfg); + pSock->listenSocket = NULL; /* "listenSocket" not used with rfc1006_listener task */ + + SOCK_LOG_FLOW2 ("%s: new TCP connection passed from RFC1006_LISTENER, socket handle = %d", + pSock->sockIdStr, hNewSock); + + /* Set callingAddr and callingAddrLen. */ + pSock->callingAddrLen = sizeof (SOCKADDR_IN); + if (sockGetRemAddrInfo (pSock, &pSock->callingAddr, NULL, NULL) != SD_SUCCESS) + { + SOCK_LOG_ERR1 ("%s: error getting remote address info", pSock->sockIdStr); + } + + /* only non-secured TCP connections */ + rc = (*pSock->sockCfg.uSockConnectInd)(pSock); + + if (rc == SD_SUCCESS) + _sockAddSock (pSock); /* Add to a service list */ + else + { + CLOSE_SOCKET (hNewSock); + chk_free (pSock); + } + + SOCK_LOG_FLOW2 ("%s: first packet received len = %d", pSock->sockIdStr, tpkt_len); + + /* Allocate pSock->sockData and copy packet data to it. */ + (*pSock->sockCfg.uSockRxBufAlloc) (pSock, tpkt_len, &pSock->sockData); + memcpy (pSock->sockData->data, tpkt_buf, tpkt_len); + pSock->sockData->dataLen = tpkt_len; + pSock->sockData->result = SD_SUCCESS; + + /* Pass packet up to user just like normal packet. */ + (*pSock->sockCfg.uSockRx)(pSock, pSock->sockData); + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* rfc1006_listener_event */ +/************************************************************************/ +ST_BOOLEAN rfc1006_listener_event (ST_VOID) + { +char tpkt_buf [1024]; /* this buffer is big enough for TP0 CR (per JRB) */ +int tpkt_len; +int recv_ret; +ST_RET retcode; +SOCKET hSockConnected; +RFC1006_IPC_MSG ipc_msg; +char dummy_byte; /* one byte msg to read with recvwait_fd */ + +ST_BOOLEAN activityFlag = SD_FALSE; /* assume no events processed */ + + if (check_domsock (domsock_listener)) + { + /* received msg on domain socket. Process it completely here. */ + /* receiwait & recvwait_fd read TP0 connect.ind pdu from the listener task. + * It also gets the socket handle in hSockConnected. + */ + SOCK_LOG_FLOW1 ("domsock %d: receiving msg from RFC1006_LISTENER...", domsock_listener); + recv_ret = recvwait (domsock_listener, &ipc_msg, sizeof (RFC1006_IPC_MSG), 0); + if (recv_ret == sizeof (RFC1006_IPC_MSG)) + { /* NOTE: other opcodes maybe implemeted later */ + if (ipc_msg.opcode != RFC1006_IPC_OP_CONNECT) + { + SOCK_LOG_ERR2 ("domsock %d: received invalid opcode=%u", + domsock_listener, (ST_UINT) ipc_msg.opcode); + return (activityFlag); + } + /* recvwait_fd waits for the socket handle in hSockConnected. */ + recv_ret = (int) recvwait_fd (domsock_listener, &dummy_byte, 1, &hSockConnected); + if (recv_ret > 0) + { + assert (recv_ret == 1); /* must ALWAYS be this size */ + /* This recvwait reads TP0 connect.ind pdu from the listener task.*/ + /* NOTE: read (data_len-1) because 1 byte already read with recvwait_fd.*/ + assert (ipc_msg.data_len-1 <= sizeof (tpkt_buf)); + tpkt_len = recv_ret = recvwait (domsock_listener, tpkt_buf, ipc_msg.data_len-1, 0); + if (tpkt_len > 0 && hSockConnected >= 0) + { + /* rfc1006_listener task already did the "accept". */ + /* This funct should get the whole machine running. */ + retcode = sockAcceptFromListenerTask (hSockConnected, tpkt_buf, tpkt_len); + activityFlag = SD_TRUE; + } + } + } + +/* DEBUG: In the future we could add code to reconnect to the RFC1006_LISTENER task */ +/* and bind our selectors. For now just let the application to continue working.*/ + if (recv_ret == 0) + { + SOCK_LOG_ERR1 ("domsock %d: recvwait() detected RFC1006_LISTENER socket disconnect", domsock_listener); + CLOSE_THIS_SOCKET(domsock_listener); + } + else if (recv_ret < 0) + { + SOCK_LOG_ERR2 ("domsock %d: recvwait() detected error (errno=%d), closing RFC1006_LISTENER socket", + domsock_listener, SOCKET_ERRORNO); + CLOSE_THIS_SOCKET(domsock_listener); + } + } + return (activityFlag); + } +#endif /* defined(MMSEASE_MOSI) */ + + /*----------------------------------------------*/ + /* Initialization / Cleanup */ + /*----------------------------------------------*/ + +/************************************************************************/ +/* np_init */ +/* NOTE: max_num_conns arg used only by listen sockets. */ +/************************************************************************/ +ST_RET np_init (ST_INT max_num_conns) + { +ST_RET rc; +ST_INT i; + +#if defined(MMSEASE_MOSI) + tp0Ctx.tcpEventWakeupPortBase = 55051; /* base listen port */ + tp0Ctx.tcpEventWakeupPortRange = 100; /* range to search for free port*/ + tp0Ctx.tcpEventWakeupPort = 0; /* actual wakeup port */ + tp0Ctx.hTcpEventSender = INVALID_SOCKET; /* set by gensock2 service thread*/ +#endif + + if (tp0Ctx.state != TP0_SOCK_CTX_STATE_IDLE) + { + SOCK_LOG_NERR0 (tp0Ctx.sockCtx, "np_init: TP0 Context State not IDLE."); + return (SD_FAILURE); + } + + SOCK_LOG_FLOW1 (tp0Ctx.sockCtx, "np_init: initializing Network layer ... TCP max_num_conns = %d.", max_num_conns); + + /* Create "TCP" Event Semaphore. */ +#if defined(_WIN32) + if (!(hTcpEvent = gs_get_event_sem (SD_FALSE))) + { + SOCK_LOG_ERR0 (tp0Ctx.sockCtx, "np_init: error creating TCP Event Semaphore."); + return (SD_FAILURE); + } +#endif + + /* initialize gensock2 before calling any of the socket functions */ + rc = sockStart ("TP0_SOCKS", &tp0Ctx.sockCtx); + if (rc != SD_SUCCESS) + { + SOCK_LOG_ERR1 (tp0Ctx.sockCtx, "np_init: sockStart() failed, rc=%d", rc); +#if defined(_WIN32) + gs_free_event_sem (hTcpEvent); +#endif + return (rc); + } + +#if defined(MMSEASE_MOSI) + if ((rc = sockCreateWakeupSockets ( tp0Ctx.sockCtx, + tp0Ctx.tcpEventWakeupPortBase, tp0Ctx.tcpEventWakeupPortRange, + &tp0Ctx.tcpEventWakeupPort, + &tp0Ctx.hTcpEventSender, &mms_event_fd)) != SD_SUCCESS) + { + sockEnd (tp0Ctx.sockCtx); + tp0Ctx.sockCtx = NULL; + return (rc); + } +#endif /* defined(MMSEASE_MOSI) */ + + /* start the security components */ + rc = sSecStart (&tp0Ctx.secCfg); + if (rc != SD_SUCCESS) + { + SOCK_LOG_ERR1 (tp0Ctx.sockCtx, "np_init: sSecStart() failed, rc=%d", rc); + _sockClean (); + return (rc); + } + +#if defined(MMSEASE_MOSI) + /* MMSEASE_MOSI uses the RFC1006_LISTENER task to listen for TCP connections, */ + /* but it is not required to do so. Instead the application could listen for */ + /* TCP connections itself if it is the only RFC1006 port listener in the system.*/ + /* This is an undocumented option that maybe exposed in the future to */ + /* selected customers when need arises. */ + if (use_rfc1006_listener_task) + { + /* NOTE: if RFC1006_LITENER task is used then the UNIX domain socket will */ + /* handle only non-secure connections. */ + rc = rfc1006_listener_connect (&domsock_listener); + if (rc != SD_SUCCESS) + _sockClean (); + return (rc); + } +#endif /* defined(MMSEASE_MOSI) */ + /* If !use_rfc1006_listener_task, continue with default code. */ +#if !defined(MMSEASE_MOSI) + /* only MMS_LITE configures num_called */ + if (mvl_cfg_info->num_called) +#endif + { + /* start listening for non-secured connections from remotes */ + if (!tp0Ctx.secCfg->secureModeEnabled || tp0Ctx.secCfg->encryptReqCalled == SD_FALSE) + { + rc = _sockInitListen (SOCK_LISTEN_NON_SSL, 0, max_num_conns); + if (rc != SD_SUCCESS) + { + _sockClean (); + return (rc); + } + } + + /* start listening for secured connections from remotes (multiple ports maybe configured) */ + if (tp0Ctx.secCfg->secureModeEnabled) + { + for (i=0; inumSslListenPorts; ++i) + { + rc = _sockInitListen (SOCK_LISTEN_SSL, i, max_num_conns); + if (rc != SD_SUCCESS) + { + rc = _sockClean (); + return (SD_FAILURE); + } + } + } + } + + if (rc == SD_SUCCESS) + { + tp0Ctx.state = TP0_SOCK_CTX_STATE_ACTIVE; + SOCK_LOG_FLOW0 (tp0Ctx.sockCtx, "np_init: initialization successful."); + } + + return (rc); + } + +/************************************************************************/ +/* _sockSetDefaults */ +/*----------------------------------------------------------------------*/ +/* Initialize socket cfg params (used for secure/non-secure connections)*/ +/************************************************************************/ +static ST_RET _sockSetDefaults (GEN_SOCK_CONFIG *sockCfg) + +{ +ST_RET rc = SD_SUCCESS; + + SOCK_LOG_FLOW0 (tp0Ctx.sockCtx, "in _sockSetDefaults()"); + + memset (sockCfg, 0, sizeof (GEN_SOCK_CONFIG)); /* start clean */ + + /* set socket parameters */ + + sockCfg->hdrSize = RFC1006_HEAD_LEN; /* RFC1006 header len */ + + /* set sockopt parameters */ + sockCfg->setSockOpts = SD_TRUE; + sockCfg->noDelay = SD_TRUE; + sockCfg->keepAlive = SD_TRUE; + sockCfg->reuseAddr = SD_TRUE; /* SO_REUSEADDR for quick restart */ + sockCfg->rcvBufSize = 0; /* use default socket buffer size */ + sockCfg->sndBufSize = 0; /* use default socket buffer size */ + + sockCfg->pauseRecv = SD_FALSE; /* used to apply back pressure */ + sockCfg->listenBacklog = 0; /* if 0, SOMAXCONN used */ + + /* set callback funcs for non-secured connections from remotes */ + + sockCfg->uSockConnectInd = &_uSockConnectInd; + sockCfg->uSockConnectConf= &_uSockConnectDone; + sockCfg->uSockDisconnect = &_uSockDisconnectInd; + sockCfg->uSockRx = &_uSockRxInd; + sockCfg->uSockWritable = &_uSockWritable; + sockCfg->uSockHunt = &_uSockHunt; + sockCfg->uSockRxBufAlloc = &_uSockDataAlloc; + sockCfg->uSockTxBufFree = &_uSockDataFree; + + /* sockCfg->recvEvent = not used */ + /* sockCfg->usr1 = not used */ + + return (rc); +} + +/************************************************************************/ +/* _sockInitListen */ +/*----------------------------------------------------------------------*/ +/* Initialize listen socket. */ +/************************************************************************/ +int cfg_61850_tcp_port=102; +static ST_RET _sockInitListen (ST_UINT type, + ST_UINT idx, + ST_INT max_num_conns) + +{ +ST_RET rc; +GEN_SOCK_CONFIG sockCfg; +ST_UINT16 listenPort; +ST_UINT maxActive; +GEN_SOCK **pListenSock; + + SOCK_LOG_FLOW1 (tp0Ctx.sockCtx, "%s: in _sockInitListen()", tp0Ctx.sockCtx->ctxName); + + /* set socket parameters */ + + rc = _sockSetDefaults (&sockCfg); + + if (type == SOCK_LISTEN_SSL) + { + /* set callback functions for secure connections from remotes */ + setGenSockSSL (&sockCfg); /* sets sockCfg.secEnable=SD_TRUE & secure fun ptrs */ + listenPort = tp0Ctx.secCfg->sslListenPorts[idx]; + maxActive = max_num_conns; + pListenSock = &tp0Ctx.remListenSockSSL[idx]; + } + else + { + /* SOCK_LISTEN_NON_SSL */ + if (tp0_cfg.rfc1006_listen_port) + listenPort = tp0_cfg.rfc1006_listen_port; + else + { + listenPort = IPPORT_RFC1006; /* use the default port */ + if(cfg_61850_tcp_port) + listenPort = cfg_61850_tcp_port; + } + tp0Ctx.rfc1006Port = listenPort; /* save the port used */ + maxActive = max_num_conns; + pListenSock = &tp0Ctx.remListenSock; + } + + /* init the listening socket */ + rc = sockInitListen (tp0Ctx.sockCtx, &sockCfg, listenPort, maxActive, pListenSock); + if (rc != SD_SUCCESS) + { + SOCK_LOG_ERR4 (tp0Ctx.sockCtx, "%s: sockInitListen() failed for port=%u, rc=%d %s", + tp0Ctx.sockCtx->ctxName, (ST_UINT) listenPort, rc, + (rc== SOCK_EADDRINUSE) ? "(port already used)" : ""); + *pListenSock = NULL; /* need to be set if bind fails */ + return (SD_FAILURE); + } + + SOCK_LOG_FLOW2 (tp0Ctx.sockCtx, "%s: listening on port=%u", (*pListenSock)->sockIdStr, (ST_UINT) listenPort); + + return (SD_SUCCESS); +} + +/************************************************************************/ +/* _sockCloseAllListen */ +/* Closes all listen sockets. Currently the only return is SD_SUCCESS. */ +/************************************************************************/ +static ST_RET _sockCloseAllListen (ST_VOID) +{ +ST_INT i; + +#if defined(MMSEASE_MOSI) + /* disconnect domain socket to avoid incoming connections */ + if (use_rfc1006_listener_task) + CLOSE_THIS_SOCKET(domsock_listener); +#endif + + /* Close all listen sockets to avoid handling incoming connections */ + if (tp0Ctx.secCfg) + for (i=0; inumSslListenPorts; ++i) + if (tp0Ctx.remListenSockSSL[i]) + { + SOCK_LOG_FLOW2 (tp0Ctx.sockCtx, "%s: closing secure listening port=%d", + tp0Ctx.remListenSockSSL[i]->sockIdStr, tp0Ctx.secCfg->sslListenPorts[i]); + sockClose (tp0Ctx.remListenSockSSL[i]); + } + + if (tp0Ctx.remListenSock) + { + SOCK_LOG_FLOW2 (tp0Ctx.sockCtx, "%s: closing listening port=%d", + tp0Ctx.remListenSock->sockIdStr, tp0Ctx.rfc1006Port); + sockClose (tp0Ctx.remListenSock); + } + + return SD_SUCCESS; +} + +/************************************************************************/ +/* _sockClean */ +/************************************************************************/ +static ST_RET _sockClean (ST_VOID) +{ +ST_RET rc; + + SOCK_LOG_FLOW1 (tp0Ctx.sockCtx, "%s: in _sockClean()", tp0Ctx.sockCtx->ctxName); + + /* CRITICAL: release resources in reverse order. */ + + /* close all listen sockets to avoid handling incoming connections */ + _sockCloseAllListen (); + + /* terminate Security Manager */ + rc = sSecEnd (); + + /* cleanup gensock2 resources, terminate threads,... */ + rc = sockEnd (tp0Ctx.sockCtx); + tp0Ctx.sockCtx = NULL; + + /* free events and mutexes */ +#if defined(_WIN32) + gs_free_event_sem (hTcpEvent); +#endif +#if defined(MMSEASE_MOSI) + CLOSE_THIS_SOCKET(domsock_listener); + CLOSE_THIS_SOCKET(tp0Ctx.hTcpEventSender); + CLOSE_THIS_SOCKET(mms_event_fd); +#endif + + return (SD_SUCCESS); +} + +/************************************************************************/ +/* np_end */ +/* This function will terminate the operation of the Network layer */ +/* */ +/* Parameters: */ +/* ST_VOID none */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if termination successful */ +/* error code otherwise */ +/************************************************************************/ +ST_RET np_end (ST_VOID) + { +ST_RET rc; +GEN_SOCK_EVENT *sdi; + + SOCK_LOG_FLOW1 (tp0Ctx.sockCtx, "%s: in np_end()", tp0Ctx.sockCtx->ctxName); + + tp0Ctx.state = TP0_SOCK_CTX_STATE_TERMINATING; + + /* close all listen sockets to avoid handling incoming connections */ + _sockCloseAllListen (); + + /* Finish processing of disconnect events. Ignore all other events. */ + sMsSleep (100); /* let other threads finish disconnects */ + + /* Get all events off list and process them. */ + while ((sdi = sockEventGet (tp0Ctx.sockCtx)) != NULL) + { + if (sdi->eventType == GS_EVENT_DISCONNECT) + { + SOCK_LOG_FLOW1 (tp0Ctx.sockCtx, "%s: np_end: processing Event Indication IndType=DISCONNECT.", + sdi->pSock->sockIdStr); + _processDisconnectInd (sdi->pSock); + } + else if (sdi->eventType == GS_EVENT_CONNECT_IND) + { + SOCK_LOG_FLOW1 (tp0Ctx.sockCtx, "%s: np_end: IGNORING Event Indication IndType=CONNECT (closing socket).", + sdi->pSock->sockIdStr); + sockClose (sdi->pSock); + } + else if (sdi->eventType == GS_EVENT_DATA_IND) + { + SOCK_LOG_FLOW1 (tp0Ctx.sockCtx, "%s: np_end: IGNORING Event Indication IndType=RXDATA (closing socket).", + sdi->pSock->sockIdStr); + _uSockDataFree (sdi->pSock, sdi->sockData); + } + else + SOCK_LOG_FLOW3 (tp0Ctx.sockCtx, "%s: np_end: IGNORING Event Indication IndType=%d (%s).", + sdi->pSock->sockIdStr, sdi->eventType, + (sdi->eventType < sizeof(eventTypeStr)) ? eventTypeStr[sdi->eventType] : "UNKNOWN"); + + chk_free (sdi); + } /* end loop processing all events */ + + rc = _sockClean (); + + tp0Ctx.state = TP0_SOCK_CTX_STATE_IDLE; + return (rc); + } + + /*----------------------------------------------*/ + /* Event/Indication Handling */ + /*----------------------------------------------*/ + +#if defined(MMSEASE_MOSI) +ST_VOID drain_wakeup_sock (ST_VOID) + { +ST_CHAR dataBucket[256]; +ST_INT recvRet; +ST_INT err; + + /* Non-blocking receive, dump wakeup data */ + if (mms_event_fd != INVALID_SOCKET) + { + recvRet = (ST_INT) recv (mms_event_fd, dataBucket, sizeof (dataBucket), 0); + if (recvRet > 0) + { + SOCK_LOG_FLOW3 ("%s: XSocket received %d wakeup bytes, byte[0]=%d", + tp0Ctx.sockCtx->ctxName, recvRet, (ST_UINT) ((ST_UCHAR) dataBucket[0])); + } + else if (recvRet == 0) + { + SOCK_LOG_ERR1 ("%s: XSocket disconnected", tp0Ctx.sockCtx->ctxName); + CLOSE_THIS_SOCKET(mms_event_fd); + } + else + { + err = SOCKET_ERRORNO; + if (err == SOCK_WOULDBLOCK || err == SOCK_INTR || + err == SOCK_TIMEDOUT || err == SOCK_INPROGRESS) + { + /* recoverable error or nothing received */ + } + else + { + SOCK_LOG_ERR3 ("%s: XSocket error, recv() returned %d, errno = %d", + tp0Ctx.sockCtx->ctxName, recvRet, err); + CLOSE_THIS_SOCKET(mms_event_fd); + } + } + } + } +#endif /* defined(MMSEASE_MOSI) */ + +/************************************************************************/ +/* np_event */ +/* This function is called to process network events. */ +/************************************************************************/ +ST_BOOLEAN np_event (ST_VOID) + { +GEN_SOCK_EVENT *sdi; +ST_BOOLEAN activityFlag = SD_FALSE; /* assume no events processed */ + +#if defined(MMSEASE_MOSI) + if (use_rfc1006_listener_task) + rfc1006_listener_event (); +#endif /* defined(MMSEASE_MOSI) */ + +#if !defined(GENSOCK_THREAD_SUPPORT) + /* Service all sockets. */ + /* NOTE: this may add "many" entries to the linked list. */ + /* User should have already waited for event, so use timeout=0 here. */ + sockServiceAll (tp0Ctx.sockCtx, 0); /* arg is timeout in milliseconds*/ +#endif /* !GENSOCK_THREAD_SUPPORT */ + +#if defined(MMSEASE_MOSI) + drain_wakeup_sock (); +#endif + + /* CRITICAL: Get one and only one entry off linked list. If we get more,*/ + /* MVL queue fills up, and user can't process other events, including TP4.*/ + if ((sdi = sockEventGet (tp0Ctx.sockCtx)) != NULL) + { + activityFlag = SD_TRUE; /* 1 event processed */ + S_LOCK_UTIL_RESOURCES (); + /* check if we need to enable reception of data (we have flow control to */ + /* prevent excessive memory allocations when data messages are received */ + /* faster than the application can process) */ + if (sdi->eventType == GS_EVENT_DATA_IND) + { + SOCK_INFO *sock_info = (SOCK_INFO *) sdi->pSock->sockCfg.usr2; /* get (SOCK_INFO *) from GEN_SOCK */ + if (sock_info->recvCnt > 0) + --sock_info->recvCnt; + if (sock_info->recvCnt <= SOCK_RX_QUE_LOW_MARK && sdi->pSock->sockCfg.pauseRecv == SD_TRUE) + { + sdi->pSock->sockCfg.pauseRecv = SD_FALSE; + SOCK_LOG_FLOW2 (tp0Ctx.sockCtx, "%s: recvCnt=%u setting pauseRecv=SD_FALSE", sdi->pSock->sockIdStr, sock_info->recvCnt); + sockServiceWakeAll (tp0Ctx.sockCtx); + } + } + S_UNLOCK_UTIL_RESOURCES (); + SOCK_LOG_FLOW3 (tp0Ctx.sockCtx, "%s: processing Event Indication IndType=%d (%s).", + sdi->pSock->sockIdStr, sdi->eventType, + (sdi->eventType < sizeof(eventTypeStr)) ? eventTypeStr[sdi->eventType] : "UNKNOWN"); + + switch (sdi->eventType) + { + case GS_EVENT_CONNECT_IND: + //logprint("Sokect_GetConnect_rec(IP:%s)",inet_ntoa(sdi->pSock->callingAddr.sin_addr)); + _processConnectInd (sdi->pSock); + break; + + case GS_EVENT_CONNECT_CONF: + _processConnectDone (sdi->pSock); + break; + + case GS_EVENT_DISCONNECT: + //logprint("Sokect_DisConnect_rec(IP:%s)",inet_ntoa(sdi->pSock->callingAddr.sin_addr)); + _processDisconnectInd (sdi->pSock); + break; + + case GS_EVENT_DATA_IND: + _processRxInd (sdi->pSock, sdi->sockData); + break; + + default: + assert (0); /* Unknown eventType */ + } + chk_free (sdi); + } + + /* we have to take care of rekeying every once a while, since this */ + /* function is called periodically (at least once every 1 sec) we */ + /* use it to do the job */ + _handleRekeying (); + + return (activityFlag); + } + +/************************************************************************/ +/* _setSecInfo */ +/************************************************************************/ +static ST_RET _setSecInfo (GEN_SOCK *pSock, S_SEC_ENCRYPT_CTRL *encrypt_ctrl) +{ +ST_RET rc; + + rc = sSecGetCipherSuite (pSock, &encrypt_ctrl->u.ssl.cipherSuite); + if (rc != SD_SUCCESS) + { + SOCK_LOG_NERR2 (tp0Ctx.sockCtx, "%s: failed to obtain Cipher Suite (rc=%d)", pSock->sockIdStr, rc); + return (rc); + } + + rc = sSecGetCertCtrl (pSock, &encrypt_ctrl->u.ssl.sslCert); + if (rc == SD_SUCCESS) + { + /* SD_SUCCESS means that this is a secured connection */ + encrypt_ctrl->encryptMode = S_SEC_ENCRYPT_SSL; + + /* if the remote certificate is not config the function above may return */ + /* NULL for the sslCert pointer */ + if (encrypt_ctrl->u.ssl.sslCert) + encrypt_ctrl->u.ssl.sslCertMatched = SD_TRUE; + else + encrypt_ctrl->u.ssl.sslCertMatched = SD_FALSE; + } + else + SOCK_LOG_NERR2 (tp0Ctx.sockCtx, "%s: failed to obtain Certificate Ctrl (rtn=%d)", pSock->sockIdStr, rc); + + return (rc); +} + +/************************************************************************/ +/* _processConnectInd */ +/* Accepted new socket connection, let user know. */ +/************************************************************************/ +static ST_VOID _processConnectInd (GEN_SOCK *pSock) + { +ST_RET rc; +SOCK_INFO *sock_info; +S_SEC_ENCRYPT_CTRL *encrypt_ctrl; + + /* For a listening socket we will attach the GEN_SOCK to our user ctrl*/ + /* Pass (GEN_SOCK *) instead of SOCKET as first arg. */ + /* This saves (GEN_SOCK *) in SOCK_INFO. */ + sock_info = sock_info_alloc2 (pSock, SOCK_STATE_ACCEPTED, + INVALID_CONN_ID); + sock_info->ip_addr = pSock->callingAddr.sin_addr.s_addr; /* Save remote IP addr */ + pSock->sockCfg.usr2 = sock_info; /* Save (SOCK_INFO *) in GEN_SOCK*/ + encrypt_ctrl = &sock_info->encrypt_ctrl; + + /* if secured connection extract encryption info */ + if (pSock->sockCfg.secEnable) + { + rc = _setSecInfo (pSock, encrypt_ctrl); + if (rc != SD_SUCCESS) + { + pSock->sockCfg.usr2 = NULL; /* to prevent use of invalid sock_info */ + sock_info_free (sock_info); + sockClose (pSock); + return; + } + sock_info->rekeyTime = sGetMsTime() + SOCK_REKEY_TIME; + /* add sock_info to list of secured sockets */ + S_LOCK_UTIL_RESOURCES (); + list_add_last (&tp0Ctx.secureSockList, sock_info); + S_UNLOCK_UTIL_RESOURCES (); + } + + handle_accepted_conn (sock_info); + } + +/************************************************************************/ +/* handle_accepted_conn */ +/************************************************************************/ +ST_VOID handle_accepted_conn (SOCK_INFO *sock_info) + { + /* User only cares about T-CONNECT.ind. Just log this. */ + SOCK_LOG_RX1 (tp0Ctx.sockCtx, "N-CONNECT.ind: sock_info = 0x%X", sock_info); + sock_info->state = SOCK_STATE_CONNECTED; + } + +/************************************************************************/ +/* _processConnectDone */ +/* Socket connection established, let user know. */ +/************************************************************************/ +static ST_VOID _processConnectDone (GEN_SOCK *pSock) + { +ST_RET rc; +SOCK_INFO *sock_info = (SOCK_INFO *) pSock->sockCfg.usr2; /* get (SOCK_INFO *) from GEN_SOCK */ +S_SEC_ENCRYPT_CTRL *encrypt_ctrl; + + assert (sock_info); + sock_info->genSock = pSock; /* CRITICAL: save pSock now */ + + /* it is possible that if the connection took long time then the application */ + /* called already np_disconnect_req */ + if (sock_info->state == SOCK_STATE_CONNECT_CANCELLED) + sockClose (pSock); /* couldn't call this function from np_disconnect_req */ + else if (sock_info->state == SOCK_STATE_CONNECTING) + { + /* if secured connection extract encryption info */ + if (pSock->sockCfg.secEnable) + { + encrypt_ctrl = &sock_info->encrypt_ctrl; + rc = _setSecInfo (pSock, encrypt_ctrl); + if (rc != SD_SUCCESS) + { + sockClose (pSock); + return; + } + sock_info->rekeyTime = sGetMsTime() + SOCK_REKEY_TIME; + /* add sock_info to list of secured sockets */ + S_LOCK_UTIL_RESOURCES (); + list_add_last (&tp0Ctx.secureSockList, sock_info); + S_UNLOCK_UTIL_RESOURCES (); + } + + handle_connect_success (sock_info); + } + else + SOCK_LOG_ERR2 (tp0Ctx.sockCtx, "%s: _processConnectDone invalid state=%d", pSock->sockIdStr, sock_info->state); + } + +/************************************************************************/ +/* handle_connect_success */ +/************************************************************************/ +ST_VOID handle_connect_success (SOCK_INFO *sock_info) + { + /* Pass up N-CONNECT.cnf+ to user. */ + SOCK_LOG_RX1 (tp0Ctx.sockCtx, "N-CONNECT.cnf+ (pos): user_conn=%d", sock_info->user_conn_id); + np_connect_cnf_pos (sock_info, sock_info->user_conn_id); + sock_info->state = SOCK_STATE_CONNECTED; + } + +/************************************************************************/ +/* _processDisconnectInd */ +/************************************************************************/ +static ST_VOID _processDisconnectInd (GEN_SOCK *pSock) + { +SOCK_INFO *sock_info = (SOCK_INFO *) pSock->sockCfg.usr2; + + if (pSock->sockCfg.secEnable) + { + if (sock_info) + { + S_LOCK_UTIL_RESOURCES (); + if (list_find_node (tp0Ctx.secureSockList, sock_info) == SD_SUCCESS) + /* del sock_info from list of secured sockets */ + list_unlink (&tp0Ctx.secureSockList, sock_info); + S_UNLOCK_UTIL_RESOURCES (); + } + else + { + /* in this case a remote node attempted to connect on a secured port */ + /* but for some SSL reason the socket connection need to be terminated */ + sockClose (pSock); + sockFree (pSock); + return; /* can't do anything else */ + } + } + + if (sock_info) + { + /* If we disconnected, don't call handle_disconnect. */ + if (!(sock_info->state == SOCK_STATE_DISCONNECTING || + sock_info->state == SOCK_STATE_CONNECT_CANCELLED)) + handle_disconnect (sock_info); + + sock_info_free (sock_info); + } + else + SOCK_LOG_ERR1 (tp0Ctx.sockCtx, "%s: _processDisconnectInd sock_info=NULL", pSock->sockIdStr); + + sockFree (pSock); /* Totally done with this socket now. */ + } + +/************************************************************************/ +/* handle_disconnect */ +/************************************************************************/ +ST_VOID handle_disconnect (SOCK_INFO *sock_info) + { + SOCK_LOG_RX2 (tp0Ctx.sockCtx, "N-DISCONNECT.ind: sock_info = 0x%X, user_conn = %d", + sock_info, sock_info->user_conn_id); + np_disconnect_ind (sock_info); + } + +/************************************************************************/ +/* _processRxInd */ +/************************************************************************/ +static ST_VOID _processRxInd (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData) + { + /* data is only valid if result==SD_SUCCESS */ + if (sockData->result == SD_SUCCESS) + { + /* rxData->data includes 4-byte RFC-1006 header. That's what handle_data wants.*/ + assert (sockData->dataLen <= 65535); /* RFC-1006 limit */ + handle_data ((SOCK_INFO *)pSock->sockCfg.usr2, sockData->data, + (ST_UINT16)sockData->dataLen); + } + _uSockDataFree (pSock, sockData); + } + +/************************************************************************/ +/* handle_data */ +/* Parameters: */ +/* sock_info ptr to socket tracking struct */ +/* tpkt_ptr ptr to RFC1006 TPKT. */ +/* tpkt_len len of RFC1006 TPKT. */ +/************************************************************************/ +ST_VOID handle_data (SOCK_INFO *sock_info, ST_UCHAR *tpkt_ptr, ST_UINT16 tpkt_len) + { + SOCK_LOG_RX3 (tp0Ctx.sockCtx, "N-DATA.ind: sock_info = 0x%X, user_conn = %d tpkt_len = %d", + sock_info, sock_info->user_conn_id, tpkt_len); + SOCK_LOG_RXH (tp0Ctx.sockCtx, tpkt_len, tpkt_ptr); + np_data_ind (sock_info, tpkt_ptr, tpkt_len); + } + + /*----------------------------------------------*/ + /* Connection Request / Indication */ + /*----------------------------------------------*/ + +/************************************************************************/ +/* np_connect_req */ +/* RETURNS: */ +/* SOCK_INFO * ptr to socket info for new socket, OR */ +/* NULL if connect fails immediately. */ +/************************************************************************/ +int win_61850_tcp_port=102; +SOCK_INFO *np_connect_req (ST_LONG user_conn_id, ST_ULONG ipAddr, ST_UINT16 rem_port, + S_SEC_ENCRYPT_CTRL *encrypt_ctrl) + { +ST_RET rc; +SOCK_INFO *sock_info; /* new tracking struct for this conn. */ +struct in_addr sin_addr; /* inet_ntoa needs this addr format */ +ST_CHAR *tmp_ptr; +ST_CHAR addr_string [32]; /* local copy of addr */ +GEN_SOCK_CONFIG sockCfg = {0}; +ST_UINT16 port; +GEN_SOCK *pGenSock; + + SOCK_LOG_TX1 (tp0Ctx.sockCtx, "N-CONNECT.req: user_conn=%d", user_conn_id); + + /* MMS Lite stores IP Addr as ULONG. Must convert back to string. */ + sin_addr.s_addr = ipAddr; + tmp_ptr = inet_ntoa (sin_addr); + assert (strlen (tmp_ptr) < sizeof (addr_string)); + strcpy (addr_string, tmp_ptr); + + /* Must do this first, because connect ind callback may be called + * before returning from sockInitCalling! + */ + sock_info = sock_info_alloc2 (NULL, SOCK_STATE_CONNECTING, user_conn_id); + + + /* setup rem socket params and connect to the rem IP Addr, Port */ + _sockSetDefaults (&sockCfg); + sockCfg.reuseAddr = SD_FALSE; /* Override setting from _sockSetDefaults.*/ + + /* save our control ptr (used in callback functions) */ + sockCfg.usr2 = (ST_VOID *) sock_info; + + if (encrypt_ctrl->encryptMode == S_SEC_ENCRYPT_SSL) + { + /* secure connection requested, set the security functions hooks */ + setGenSockSSL (&sockCfg); /* sets sockCfg.secEnable=SD_TRUE & secure fun ptrs */ + port = encrypt_ctrl->u.ssl.port; + } + else + { + /* non-secured connection */ + if (rem_port) + port = rem_port; /* use configured remote port */ + else + port = IPPORT_RFC1006; + } + + +#ifdef WIN32 + port = win_61850_tcp_port; +#endif + + /* connect to Remote */ + /* NOTE: The callback may be called before + * sockInitCalling returns, so just save the (GEN_SOCK *) to "sock_info->genSock" + * in the callback function (_uSockConnectInd). + */ + SOCK_LOG_TX4 (tp0Ctx.sockCtx, "N-CONNECT.req: sock_info=0x%X, connection pending to IP Address='%s' Port=%u %s", + sock_info, addr_string, port, + (encrypt_ctrl->encryptMode==S_SEC_ENCRYPT_SSL) ? "(SSL)" : ""); + + rc = sockInitCalling (tp0Ctx.sockCtx, &sockCfg, port, addr_string, &pGenSock); + /* DEBUG Note: the pGenSock may need to be in the SOCK_INFO struct */ + + if (rc != SD_SUCCESS) + { /* failed, clean up */ + sock_info_free (sock_info); + sock_info = NULL; + } + + return (sock_info); + } + +/************************************************************************/ +/* _uSockConnectDone */ +/* This is gensock2 callback function called when socket connection */ +/* to the remote has been established. */ +/************************************************************************/ + +static ST_RET _uSockConnectDone (GEN_SOCK *pSock) + { +ST_RET rtn; + + SOCK_LOG_FLOW1 (tp0Ctx.sockCtx, "%s: in _uSockConnectDone()", pSock->sockIdStr); + + rtn = _addSockInd (pSock, GS_EVENT_CONNECT_CONF, NULL); + return (rtn); + } + +/************************************************************************/ +/* _uSockConnectInd */ +/* This is gensock2 callback function when a socket connection has been */ +/* accepted from remote. */ +/************************************************************************/ + +static ST_RET _uSockConnectInd (GEN_SOCK *pSock) + { +ST_RET rtn; +ST_CHAR *SSLstr; + + if (pSock->sockCfg.secEnable) + SSLstr = "SSL"; + else + SSLstr = ""; + SOCK_LOG_FLOW4 (tp0Ctx.sockCtx, "%s: in _uSockConnectInd(), received %s connection from" + " IP Address=%s Port=%u", pSock->sockIdStr, SSLstr, + inet_ntoa (pSock->callingAddr.sin_addr), (ST_UINT) ntohs (pSock->callingAddr.sin_port)); + + rtn = _addSockInd (pSock, GS_EVENT_CONNECT_IND, NULL); + return (rtn); + } + + /*----------------------------------------------*/ + /* Disconnection Request / Indication */ + /*----------------------------------------------*/ + +/************************************************************************/ +/* np_disconnect_req */ +/* This function is called by the user to break connection */ +/************************************************************************/ + +ST_RET np_disconnect_req (SOCK_INFO *sock_info) + { +ST_RET retCode; + SOCK_LOG_TX2 (tp0Ctx.sockCtx, "N-DISCONNECT.req: sock_info = 0x%X, user_conn = %d", + sock_info, sock_info->user_conn_id); + + + if (sock_info->genSock == NULL) + { + /* this is the case when application issues connect request but calls disconnect */ + /* before the socket connection gets established (for example because of timeout). */ + SOCK_LOG_NERR3 (tp0Ctx.sockCtx, "N-DISCONNECT.req: disconnect delayed (connect pending), \n" + " sock_info = 0x%X, user_conn = %d, state = %d", + sock_info, sock_info->user_conn_id, sock_info->state); + /* change the state to avoid calling any transport functions from this point on */ + sock_info->state = SOCK_STATE_CONNECT_CANCELLED; + retCode = SD_FAILURE; + } + else + { + /* change the state to avoid calling any transport functions from this point on */ + sock_info->state = SOCK_STATE_DISCONNECTING; + retCode = sockClose (sock_info->genSock); + } + + return (retCode); + /* sock_info is not freed until _processDisconnectInd. */ + } + +/************************************************************************/ +/* _uSockDisconnectInd */ +/* This is gensock2 callback function when socket gets disconnected or */ +/* we call sockClose. */ +/************************************************************************/ +static ST_VOID _uSockDisconnectInd (GEN_SOCK *pSock) + { +ST_RET rtn; +ST_CHAR *errptr; +ST_INT i; + + switch (pSock->disconnectReason) + { + case GS_DISCONNECT_CONNECT_FAILED: errptr= "CONNECT_FAILED"; break; + case GS_DISCONNECT_USR_REFUSED: errptr= "USER_REFUSED"; break; + case GS_DISCONNECT_SEND_FAILURE: errptr= "SEND_FAILURE"; break; + case GS_DISCONNECT_RECV_FAILED: errptr= "RECEIVE_FAILED"; break; + case GS_DISCONNECT_ACCEPT_FAILED: errptr= "ACCEPT_FAILED"; break; + case GS_DISCONNECT_CLOSED: errptr= "SOCKET_CLOSED"; break; + case GS_DISCONNECT_TERMINATING: errptr= "TERMINATING"; break; + case GS_DISCONNECT_RESOURCES_ERROR: errptr= "RESOURCES_ERROR"; break; + case GS_DISCONNECT_INTERNAL_ERROR: errptr= "INTERNAL_ERROR"; break; + + case GS_DISCONNECT_UNKNOWN: + default: errptr= "UNKNOWN"; break; + } + SOCK_LOG_FLOW2 (tp0Ctx.sockCtx, "%s: in _uSockDisconnectInd() reason=%s", pSock->sockIdStr, errptr); + + /* CRITICAL: deal with GS_ROLE_LISTENING now. This happens when server is + * exiting. _processDisconnectInd may not be called again. + */ + if (pSock->role == GS_ROLE_LISTENING) + { + if (pSock == tp0Ctx.remListenSock) + { + SOCK_LOG_FLOWC1 (tp0Ctx.sockCtx, " for non-secured listening port=%d", tp0Ctx.rfc1006Port); + tp0Ctx.remListenSock = NULL; + } + else + { + for (i=0; isslListenPorts[i]); + tp0Ctx.remListenSockSSL[i] = NULL; + break; + } + } + } + sockFree (pSock); + return; + } + + rtn = _addSockInd (pSock, GS_EVENT_DISCONNECT, NULL); + if (rtn != SD_SUCCESS && tp0Ctx.state == TP0_SOCK_CTX_STATE_TERMINATING) + { + SOCK_INFO *sock_info = pSock->sockCfg.usr2; + /* since we will not pass the disconnect ind to the main thread clean the */ + /* sock_info here */ + if (sock_info) + sock_info_free (sock_info); + + sockFree (pSock); + } + } + + /*----------------------------------------------*/ + /* Data Request / Indication */ + /*----------------------------------------------*/ + +/************************************************************************/ +/* np_data_req */ +/* Parameters: */ +/* eot SD_TRUE if last TPDU msg in a SPDU. */ +/* RETURN CODES: */ +/* SD_SUCCESS or SD_FAILURE */ +/************************************************************************/ +/*renxiaobao ±¨ÎÄ·¢ËÍ*/ +ST_RET np_data_req (SOCK_INFO *sock_info, ST_INT tpkt_len, ST_UCHAR *tpkt_ptr, + ST_BOOLEAN eot) + { +GEN_SOCK_DATA *sockData; +ST_RET rc; + +/*//static int qqq=0; + +//assert (sock_info->genSock != NULL); +*/ if(sock_info->genSock == NULL) + { + printf("sock_info->genSock == NULL\n"); + return (SD_FAILURE); + } + /*// if(qqq++>500) + //{ +// qqq=0; + // sockClose (sock_info->genSock); + // sockFree (sock_info->genSock); + // return (SD_FAILURE); + //} +*/ /* check if queueing limit has been reached to prevent the excessive */ + /* growth of the outbound queue in gensock2.c */ + if (sockTxQueueGroupCntGet (sock_info->genSock) >= tp0_cfg.max_spdu_outst) + { + SOCK_LOG_ERR2 (tp0Ctx.sockCtx, "N-DATA.req: sock_info = 0x%X, error sending (queue limit = %u reached)", + sock_info, tp0_cfg.max_spdu_outst); + /*renxiaobao ±¨ÎÄ·¢ËÍʧ°Ü + printf(tp0Ctx.sockCtx, "N-DATA.req: sock_info = 0x%X, error sending (queue limit = %u reached)", + sock_info, tp0_cfg.max_spdu_outst);*/ + return (SD_FAILURE); + } + + /* _uSockDataAlloc allocs "sockData" (plus space for data) and initializes it.*/ + _uSockDataAlloc (sock_info->genSock, tpkt_len, &sockData); + memcpy (sockData->data, tpkt_ptr, tpkt_len); /* copy the data */ + sockData->eot = eot; + + rc = sockTxMsg (sock_info->genSock, sockData); + + if (rc == SD_SUCCESS) + { + SOCK_LOG_TX3 (tp0Ctx.sockCtx, "N-DATA.req: sock_info = 0x%X, user_conn = %d tpkt_len = %d", + sock_info, sock_info->user_conn_id, tpkt_len); + SOCK_LOG_TXH (tp0Ctx.sockCtx, tpkt_len, tpkt_ptr); + } + else + { + SOCK_LOG_ERR1 (tp0Ctx.sockCtx, "N-DATA.req: sock_info = 0x%X, error sending", sock_info); + /*printf (tp0Ctx.sockCtx, "N-DATA.req: sock_info = 0x%X, error sending", sock_info);*/ + } + + return (rc); + } + +/************************************************************************/ +/* np_get_tx_queue_cnt */ +/* Returns number of queued SPDUs. */ +/************************************************************************/ +ST_UINT np_get_tx_queue_cnt (SOCK_INFO *sock_info) + { + assert (sock_info->genSock != NULL); + return (sockTxQueueGroupCntGet (sock_info->genSock)); + } + +/************************************************************************/ +/* _uSockWritable */ +/* This function is called by gensock2 when the socket becomes writable.*/ +/************************************************************************/ +static ST_VOID _uSockWritable (GEN_SOCK *pSock) + { +ST_RET rc; + + SOCK_LOG_FLOW1 (tp0Ctx.sockCtx, "%s: in _uSockWritable()", pSock->sockIdStr); + + /* the socket is writable, so send something from the transmit queue. */ + rc = sockTxQueueProc (pSock); + if (rc != SD_SUCCESS) + { + SOCK_LOG_ERR1 (tp0Ctx.sockCtx, "%s: sockTxQueueProc failed, closing socket", pSock->sockIdStr); + /* DEBUG: this change of state will cause problem, */ + /* app will not be notified about disconnect */ + /* sock_info->state = SOCK_STATE_DISCONNECTING; */ + sockClose (pSock); + } + } + +/************************************************************************/ +/* _uSockRxInd */ +/************************************************************************/ +static ST_VOID _uSockRxInd (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData) + { +ST_RET rtn; + + if (pSock && sockData) + SOCK_LOG_FLOW3 (tp0Ctx.sockCtx, "%s: in _uSockRxInd() result=%s, bytes=%d", pSock->sockIdStr, + (sockData->result == SD_SUCCESS) ? "SD_SUCCESS" : "SD_FAILURE", sockData->dataLen); + else + { + SOCK_LOG_ERR2 (tp0Ctx.sockCtx, "%s: in _uSockRxInd() sockData=%08lx", pSock->sockIdStr, sockData); + if (sockData) + _uSockDataFree (pSock, sockData); + return; + } + + if (sockData->result != SD_SUCCESS) + { + /* socket is disconnecting, any received data buffers need to be free */ + _uSockDataFree (pSock, sockData); + return; + } + + /* If no data (len=RFC1006_HEAD_LEN) ignore msg. */ + if (sockData->dataLen <= RFC1006_HEAD_LEN) + { + /* Should NEVER be '<' because _uSockHunt checks for illegal len, but just in case...*/ + if (sockData->dataLen < RFC1006_HEAD_LEN) + SOCK_LOG_ERR1 (tp0Ctx.sockCtx, "Illegal TPKT len = %d", sockData->dataLen); + + /* May be '='. NOT normal, but some bad apps could send just header.*/ + /* Either way, do NOT put on queue. */ + _uSockDataFree (pSock, sockData); + return; + } + + /* received data on the socket, queue indication for user */ + rtn = _addSockInd (pSock, GS_EVENT_DATA_IND, sockData); + if (rtn != SD_SUCCESS) + _uSockDataFree (pSock, sockData); + } + +/************************************************************************/ +/* uSockHunt */ +/* This function will get the length of received message on a socket. */ +/* We expect the size field to be RFC1006_HEAD_LEN bytes. */ +/************************************************************************/ + +static ST_VOID _uSockHunt (GEN_SOCK *pSock, ST_INT *huntStateIo, + ST_CHAR *buf, ST_INT bufCount, ST_INT *lenOut) + { +ST_UINT16 u16len; + + /* Better get our 4 byte RFC-1006 header ... */ + if (bufCount != RFC1006_HEAD_LEN) + { + /* This should NEVER happen. gensock2 state machine must be corrupted.*/ + SOCK_LOG_ERR1 (tp0Ctx.sockCtx, "%s: Socket Hunt for start of message failed.\n" + " Error could be unrecoverable.", pSock->sockIdStr); + *huntStateIo = GENSOCK_HUNT_DISCONNECT; + return; + } + + if (buf[0] != RFC1006_VERSION) + { + SOCK_LOG_ERR1 (tp0Ctx.sockCtx, "%s: Received RFC 1006 header with invalid version (first byte). Header:", + pSock->sockIdStr); + SOCK_LOG_ERRH (tp0Ctx.sockCtx, 4, buf); + *huntStateIo = GENSOCK_HUNT_DISCONNECT; + return; + } + + /* Ignore 2nd byte (reserved). */ + + /* len is in 3rd/4th bytes, in network byte order, and includes len of header. + * Convert to host byte order, & subtract header len. + * CRITICAL: cast to ST_UCHAR before ST_UINT16 to avoid sign extension. + */ + u16len = (((ST_UINT16)(ST_UCHAR) buf[2]) << 8) | (ST_UINT16)(ST_UCHAR) buf[3]; + /* CRITICAL: make sure len is at least RFC1006_HEAD_LEN so subtracting*/ + /* does not create negative number. */ + if (u16len < RFC1006_HEAD_LEN) + { + SOCK_LOG_ERR2 (tp0Ctx.sockCtx, "%s: Received RFC 1006 header with invalid length (%u). Header:", + pSock->sockIdStr, u16len); + SOCK_LOG_ERRH (tp0Ctx.sockCtx, RFC1006_HEAD_LEN, buf); + *huntStateIo = GENSOCK_HUNT_DISCONNECT; + return; + } + u16len -= RFC1006_HEAD_LEN; /* subtract header len */ + /* NOTE: cast to ST_UINT before ST_INT to avoid sign extension. */ + *lenOut = (ST_INT)(ST_UINT)u16len; + *huntStateIo = GENSOCK_HUNT_DONE; + } + + /*----------------------------------------------*/ + /* Alloc / Free */ + /*----------------------------------------------*/ + +/************************************************************************/ +/* sock_info_alloc2 */ +/* Allocate a SOCK_INFO struct and fill it in. */ +/************************************************************************/ +SOCK_INFO *sock_info_alloc2 (GEN_SOCK *genSock, ST_INT state, ST_LONG user_conn_id) + { +SOCK_INFO *sock_info; + + /* Allocate SOCK_INFO struct. */ + sock_info = (SOCK_INFO *) M_CALLOC (MSMEM_SOCK_INFO, 1, sizeof (SOCK_INFO)); + /* Fill in SOCK_INFO struct. */ + /* NOTE: sock_info->hSock is NOT used. sock_info->genSock is used instead.*/ + sock_info->genSock = genSock; + sock_info->state = state; + sock_info->user_conn_id = user_conn_id; + sock_info->encrypt_ctrl.encryptMode = S_SEC_ENCRYPT_NONE; + sock_info->recvCnt = 0; + return (sock_info); + } + +/************************************************************************/ +/* sock_info_free */ +/* Free a SOCK_INFO struct. */ +/************************************************************************/ +ST_VOID sock_info_free (SOCK_INFO *sock_info) + { + /* NOTE: gensock2 handles closing of the socket. */ + M_FREE (MSMEM_SOCK_INFO, sock_info); + } + +/************************************************************************/ +/* _uSockDataAlloc */ +/************************************************************************/ +static ST_VOID _uSockDataAlloc (GEN_SOCK *pSock, ST_INT dataLen, + GEN_SOCK_DATA **sockDataOut) + { +GEN_SOCK_DATA *sockData; + + sockData = (GEN_SOCK_DATA *) chk_malloc (sizeof (GEN_SOCK_DATA) + dataLen); + sockData->data = (ST_UCHAR *) (sockData + 1); + sockData->dataLen = dataLen; + /* We don't use sockData->usrBufBase, sockData->usrBufLen */ + + *sockDataOut = sockData; + } +/************************************************************************/ +/* _uSockDataFree */ +/************************************************************************/ +static ST_VOID _uSockDataFree (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData) + { + /* Allocated in _uSockDataAlloc using "chk_malloc", so use "chk_free".*/ + chk_free (sockData); + } + + /*----------------------------------------------*/ + /* Misc */ + /*----------------------------------------------*/ + +/************************************************************************/ +/* _addSockInd */ +/************************************************************************/ +static ST_RET _addSockInd (GEN_SOCK *pSock, ST_INT eventType, GEN_SOCK_DATA *sockData) + { +GEN_SOCK_EVENT *sdi; +#if defined(MMSEASE_MOSI) +static ST_UCHAR tcpEventWakeupData = 1; +ST_INT numSent = 0; +#endif + + if (tp0Ctx.state == TP0_SOCK_CTX_STATE_TERMINATING) + { + SOCK_LOG_FLOW1 (tp0Ctx.sockCtx, "%s: in _addSockInd failed - context terminating", pSock->sockIdStr); + return (SD_FAILURE); + } + else + SOCK_LOG_FLOW1 (tp0Ctx.sockCtx, "%s: in _addSockInd", pSock->sockIdStr); + + sdi = (GEN_SOCK_EVENT *) chk_calloc (1, sizeof (GEN_SOCK_EVENT)); + sdi->eventType = eventType; + sdi->pSock = pSock; + + sdi->sockData = sockData; + sockEventPut (tp0Ctx.sockCtx, sdi); /* let gensock save on list*/ + S_LOCK_UTIL_RESOURCES (); + /* if application can't process incoming data msgs as fast as they are*/ + /* received by the socket then the best way to prevent uncontrolled */ + /* growth of the receiving queue is to apply back pressure to the */ + /* sending socket. */ + if (eventType == GS_EVENT_DATA_IND) + { +SOCK_INFO *sock_info = (SOCK_INFO *) pSock->sockCfg.usr2; + /* this is a bit tricky, if we accept connection from rfc1006listener */ + /* then the first packet will be queued before the sock_info is allocated */ + /* so we must check here if the ptr is NULL */ + if (sock_info) + { + ++sock_info->recvCnt; + if (sock_info->recvCnt >= SOCK_RX_QUE_HIGH_MARK && pSock->sockCfg.pauseRecv == SD_FALSE) + { + pSock->sockCfg.pauseRecv = SD_TRUE; + SOCK_LOG_FLOWC2 (tp0Ctx.sockCtx, "%s: recvCnt=%u, setting pauseRecv=SD_TRUE", + pSock->sockIdStr, sock_info->recvCnt); + } + } + } + S_UNLOCK_UTIL_RESOURCES (); + + /* wake up main thread */ +#if defined(_WIN32) + gs_signal_event_sem (hTcpEvent); /* wake up main thread */ + SOCK_LOG_FLOW2 (tp0Ctx.sockCtx, "%s: in _addSockInd() signaled hTcpEvent=%lu", pSock->sockIdStr, (ST_ULONG) hTcpEvent); +#endif + +#if defined(MMSEASE_MOSI) + if (tp0Ctx.hTcpEventSender != INVALID_SOCKET) + { + numSent = (ST_INT) send (tp0Ctx.hTcpEventSender, &tcpEventWakeupData, sizeof(tcpEventWakeupData), 0); + if (numSent == sizeof (tcpEventWakeupData)) + { + SOCK_LOG_FLOW3 ("%s: XSocket sent %d Wakeup data (value=%u)", + tp0Ctx.sockCtx->ctxName, numSent, (ST_UINT) tcpEventWakeupData); + } + else + { + /* when a lot of indications are received in short time, EWOULDBLOCK and EAGAIN */ + /* errors could happen often with this 1-byte packets */ + SOCK_LOG_FLOW3 ("%s: XSocket Wakeup data send() error (numSent=%d), errno=%d", + tp0Ctx.sockCtx->ctxName, numSent, SOCKET_ERRORNO); + /* ignore any errors */ + } + ++tcpEventWakeupData; + } +#endif /* defined(MMSEASE_MOSI) */ + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _handleRekeying */ +/* Call function driving security rekeying on every secured socket. */ +/************************************************************************/ +static ST_RET _handleRekeying (ST_VOID) +{ +ST_RET rc; +S_SEC_CONFIG *pSecCfg; + + rc = secManAccessCfg (&pSecCfg); + if (rc != SD_SUCCESS) + return (rc); + + /* we have to drive the checking for periodic rekeying, to do that call */ + /* the TX func with no data to send */ + if (pSecCfg->secureModeEnabled) + { + SOCK_INFO *sock_info; + + S_LOCK_UTIL_RESOURCES (); + sock_info = tp0Ctx.secureSockList; + while (sock_info) + { + if (sGetMsTime () >= sock_info->rekeyTime && + sock_info->genSock != NULL && sock_info->genSock->sockState == GS_STATE_CONNECTED) + { + GEN_SOCK_DATA sockData={{0}}; /* first in struct is struct, so need double braces */ + ST_INT numSent; + sockTx (sock_info->genSock, &sockData, &numSent); + /* set the time for next check */ + sock_info->rekeyTime = sGetMsTime() + SOCK_REKEY_TIME; + } + sock_info = list_get_next (tp0Ctx.secureSockList, sock_info); + } + S_UNLOCK_UTIL_RESOURCES (); + } + + secManReleaseCfg(); + return (rc); +} + diff --git a/mmslib/ositcps/tp0calld.c b/mmslib/ositcps/tp0calld.c new file mode 100644 index 0000000..61b9af9 --- /dev/null +++ b/mmslib/ositcps/tp0calld.c @@ -0,0 +1,210 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997 - 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : tp0calld.c */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* TP0 functions for handling of "Called" side of connections. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* tp0_accept () */ +/* tp0_process_cr () */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/30/08 JRB 08 Use DR reason codes valid for TP0. */ +/* 03/29/05 EJV 07 Added MMSEASE_MOSI support. */ +/* 06/20/02 JRB 06 Chg addr args to tp4_connect_ind. */ +/* 05/09/01 JRB 05 On T-CONNECT.ind, save TSAPs in TP0_CONN. */ +/* 04/25/00 JRB 04 Lint cleanup. */ +/* 06/08/99 JRB 03 Chg to support 1024 connections. */ +/* 08/13/98 JRB 02 Lint cleanup. */ +/* 08/01/97 JRB 01 Created (compatible with MMS-EASE 7.0). */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "tp4api.h" /* User definitions for tp4 */ +#include "tp4.h" /* Internal definitions for tp4 */ +#include "tp4_encd.h" /* Encode/decode defs for tp4 */ +#include "tp4_log.h" + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/*======================================================================*/ +/*======================================================================*/ +/* FUNCTIONS BELOW CALLED BY USER TO ENCODE AND SEND TPDUs. */ +/*======================================================================*/ +/*======================================================================*/ + +/************************************************************************/ +/* tp0_accept */ +/* This function is called by the user to accept a connect request from */ +/* a remote node */ +/************************************************************************/ + +ST_RET tp0_accept (ST_LONG tp0_conn_id, ST_LONG user_conn_id, + ST_INT conndata_len, + char *conndata) + { +TP0_CONN *tp_conn; + + if ((ST_ULONG) (tp0_conn_id-MIN_TP0_CONN_ID) >= tp0_cfg.max_num_conns) + return (TP4E_BADCONN); + + tp_conn = &tp0_conn_arr [tp0_conn_id-MIN_TP0_CONN_ID]; + if (tp_conn->state != TP_STATE_WFTRESP) + return (TP4E_BADCONN); + + tp_conn->user_conn_id = user_conn_id; /* Save User's ID */ + + /* Save User Data in tp_conn for retransmission. */ + /* DEBUG: Can we blow this off to save space? */ + tp_conn->tpdu_cx.udata_len = min ((ST_UINT16) conndata_len, TP_MAX_CONN_UDATA); + memcpy (tp_conn->tpdu_cx.udata_buf, conndata, tp_conn->tpdu_cx.udata_len); + + tp_conn->state = TP_STATE_OPEN; + tp0_send_cc (&tp_conn->tpdu_cx); + return (SD_SUCCESS); + } + +/*======================================================================*/ +/*======================================================================*/ +/* FUNCTIONS BELOW CALLED BY TP0 TO PROCESS TPDUs RECEIVED */ +/* (TPDUs ALREADY DECODED BY TP0). */ +/*======================================================================*/ +/*======================================================================*/ + +/************************************************************************/ +/* tp0_process_cr */ +/* Process a CR (Connection Request) TPDU. */ +/************************************************************************/ +ST_VOID tp0_process_cr (TPDU_CX *tpdu_cr_rx) + { +ST_UINT16 conn_id; /* index into "tp0_conn_arr" array (Unsigned so */ + /* no sign-extension on compare to tp0_cfg.max_num_conns).*/ +TP0_CONN *tp_conn; /* ptr to struct in "tp0_conn_arr" array. */ +TPDU_DR tpdu_dr; +ST_LONG tp0_user_bind_id; + + /* Fill in TPDU_DR struct in case DR needs to be sent. */ + /* Do not fill in "reason" yet. */ + tpdu_dr.loc_ref = 0; /* src-ref = 0 (always) */ + tpdu_dr.rem_ref = tpdu_cr_rx->rem_ref; + tpdu_dr.sock_info = tpdu_cr_rx->sock_info; + + /* Check if Local TSAP is correct. */ +#if defined(MMSEASE_MOSI) + if (tp0_check_tsel (tpdu_cr_rx->loc_tsap, &tp0_user_bind_id) != SD_SUCCESS) +#else + tp0_user_bind_id = only_tp0_user_bind_id; + if (memcmp (tpdu_cr_rx->loc_tsap, only_tp0_loc_tsap, only_tp0_loc_tsap[0]+1)) +#endif + { + TP_LOG_ERR0 ("TP-ERROR: received CR with invalid TSAP. Sending DR."); + TP_LOGH_ERR (tpdu_cr_rx->loc_tsap[0], &tpdu_cr_rx->loc_tsap[1]); + tpdu_dr.reason = TP_DR_ADDR_UNKNOWN; + tp0_send_dr (&tpdu_dr); + return; + } + + /* Check for Transport Class 0. Don't allow any other. */ + if (tpdu_cr_rx->preferred_class != 0) + { + TP_LOG_ERR1 ("TP-ERROR: received CR with invalid class %d. Sending DR.", + tpdu_cr_rx->preferred_class); + /* NOTE: this DR "reason" is not legal for Class 0, but caller */ + /* proposed different class, so they should recognize this reason. */ + tpdu_dr.reason = TP_DR_CLASS_UNSUPPORTED; /* illegal for TP0 but OK here*/ + tp0_send_dr (&tpdu_dr); + return; + } + + /* Local Ref must equal 0. If not, it is protocol error. */ + if (tpdu_cr_rx->loc_ref != 0) + { + TP_LOG_ERR0 ("TP-ERROR: received CR with invalid reference. Sending DR."); + tpdu_dr.reason = TP_DR_NO_REASON; + tp0_send_dr (&tpdu_dr); + return; + } + + /* Look for a position in "tp0_conn_arr" where state = TP_STATE_CLOSED */ + tp_conn = &tp0_conn_arr [0]; + for (conn_id = 0; conn_id < tp0_cfg.max_num_conns; conn_id++, tp_conn++) + { + if (tp_conn->state == TP_STATE_CLOSED) + { + tp0_conn_clean (tp_conn); /* Good time to clean up conn struct. */ + inc_loc_ref_offset (tp_conn->loc_ref_offset); + + /* Save sock_info in "tp_conn". */ + tp_conn->sock_info = tpdu_cr_rx->sock_info; + /* Save tp_conn (as user_conn_id) in "sock_info". */ + tp_conn->sock_info->user_conn_id = (ST_LONG) tp_conn; + + /* Copy the CR info to the tp_conn struct and modify it for the CC.*/ + /* Most parameters we send back exactly as received (all except */ + /* max_tpdu_len, loc_ref, cdt, udata_buf/len). */ + /* NOTE: udata_buf/len not changed until tp0_accept. */ + + memcpy (&tp_conn->tpdu_cx, tpdu_cr_rx, sizeof (TPDU_CX)); + tp_conn->tpdu_cx.max_tpdu_len_enc = min (tp0_cfg.max_tpdu_len_enc, + tpdu_cr_rx->max_tpdu_len_enc); + /* Save negotiated TPDU len in tp_conn. */ + switch (tp_conn->tpdu_cx.max_tpdu_len_enc) + { /* code for PDU size */ + case TP_PDU_MAX_SIZE_128 : tp_conn->max_tpdu_len = 128; break; + case TP_PDU_MAX_SIZE_256 : tp_conn->max_tpdu_len = 256; break; + case TP_PDU_MAX_SIZE_512 : tp_conn->max_tpdu_len = 512; break; + case TP_PDU_MAX_SIZE_1024 : tp_conn->max_tpdu_len = 1024; break; + case TP_PDU_MAX_SIZE_2048 : tp_conn->max_tpdu_len = 2048; break; + case TP_PDU_MAX_SIZE_4096 : tp_conn->max_tpdu_len = 4096; break; + case TP_PDU_MAX_SIZE_8192 : tp_conn->max_tpdu_len = 8192; break; + case TP_PDU_MAX_SIZE_65531: tp_conn->max_tpdu_len = 65531; break; + default: + TP_LOG_ERR0 ("TP-ERROR: received CR with illegal TPDU size. Sending DR."); + tpdu_dr.reason = TP_DR_NO_REASON; + tp0_send_dr (&tpdu_dr); + return; + } /* end "switch" */ + + tp_conn->tpdu_cx.loc_ref = calc_loc_ref (conn_id, tp_conn->loc_ref_offset); + tp_conn->tpdu_cx.cdt = 0; /* CDT always 0 for Class 0 */ + + /* Set "tp_conn" parameters for new connection. */ + tp_conn->rem_ref = tpdu_cr_rx->rem_ref; /* need for sending AKs */ + tp_conn->state = TP_STATE_WFTRESP; + + /* Save TSAPs in TP0_CONN struct. */ + memcpy (tp_conn->loc_tsap, tpdu_cr_rx->loc_tsap, tpdu_cr_rx->loc_tsap[0]+1); + memcpy (tp_conn->rem_tsap, tpdu_cr_rx->rem_tsap, tpdu_cr_rx->rem_tsap[0]+1); + + tp4_connect_ind (tp0_user_bind_id, conn_id+MIN_TP0_CONN_ID, + tpdu_cr_rx->loc_tsap, + tpdu_cr_rx->rem_tsap, + NULL, /* NSAP: not used */ + tp_conn->sock_info->ip_addr, + (ST_INT) tpdu_cr_rx->udata_len, + tpdu_cr_rx->udata_buf); + break; /* BREAK OUT OF LOOP. Only want 1 connection!!! */ + } + } /* end "for" loop */ + if (conn_id >= tp0_cfg.max_num_conns) + { /* Did not find an available conn_id. */ + TP_LOG_ERR0 ("TP-ERROR: not enough resources for received CR. Sending DR."); + tpdu_dr.reason = TP_DR_CONGESTION_AT_TSAP; /* legal for TP0 */ + tp0_send_dr (&tpdu_dr); + return; + } + return; + } + + diff --git a/mmslib/ositcps/tp0callg.c b/mmslib/ositcps/tp0callg.c new file mode 100644 index 0000000..0718d66 --- /dev/null +++ b/mmslib/ositcps/tp0callg.c @@ -0,0 +1,243 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2005 All Rights Reserved */ +/* */ +/* MODULE NAME : tp0callg.c */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* TP0 functions for handling of "Calling" side of connections. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* tp0_connect */ +/* tp0_process_cc */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/12/08 MDE 15 Added tpdu_cc->sock_info->user_conn_id check */ +/* 07/30/08 JRB 14 Use DR reason codes valid for TP0. */ +/* 05/06/05 EJV 13 Added port param to np_connect_req call. */ +/* 03/29/05 EJV 12 Added MMSEASE_MOSI support. */ +/* 09/17/04 JRB 11 Chg tp0_connect to return connection ID. */ +/* 02/02/04 JRB 10 tp0_connect: fix tp_type, bind_id checks. */ +/* 07/30/03 EJV 09 Added encrypt_ctrl to tp0_connect. */ +/* 04/07/03 JRB 08 Add SPDU_RX_NO_PREALLOCATE option. */ +/* 06/20/02 JRB 07 Pass ip addr as ulong to np_connect_req. */ +/* 06/08/99 JRB 06 Chg to support 1024 connections. */ +/* 08/13/98 JRB 05 Lint cleanup. */ +/* 06/17/98 JRB 04 Increment loc_ref_offset before encoding CR */ +/* to avoid sending duplicate CR. */ +/* 12/04/97 JRB 03 Don't chk TSAPs on CC (may not be sent). */ +/* 09/25/97 JRB 02 Don't generate exception for invalid state. */ +/* 08/01/97 JRB 01 Created (compatible with MMS-EASE 7.0). */ +/************************************************************************/ +static char *thisFileName = __FILE__; /* For TP4_EXCEPT and slog macros*/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "tp4api.h" /* User definitions for tp4 */ +#include "tp4.h" /* Internal definitions for tp4 */ +#include "tp4_encd.h" /* Encode/decode defs for tp4 */ +#include "tp4_log.h" + +/************************************************************************/ +/* tp0_connect */ +/* This function is called by the user to initiate a connect request to */ +/* a remote node */ +/* RETURNS: connection ID if successful, (-1) on error */ +/* CRITICAL: connection ID = (conn_id+MIN_TP0_CONN_ID). Remember that */ +/* this is hoe we distinguish between TP0 and TP4 connections. */ +/************************************************************************/ + +ST_LONG tp0_connect (ST_LONG tp0_bind_id, ST_LONG user_conn_id, + TP4_ADDR *rem_tp4_addr, + ST_INT conndata_len, + char *conndata, + S_SEC_ENCRYPT_CTRL *encrypt_ctrl) + { +ST_UINT16 conn_id; /* index into "tp0_conn_arr" array. */ +TP0_CONN *tp_conn; +TPDU_CX *tpdu_cr; +ST_UCHAR *tp0_loc_tsap; + + if (rem_tp4_addr->tp_type == TP_TYPE_TCP) + { +#if defined(MMSEASE_MOSI) + if (tp0_check_bind_id (tp0_bind_id, &tp0_loc_tsap) != SD_SUCCESS) +#else + tp0_loc_tsap = only_tp0_loc_tsap; + if (tp0_bind_id != only_tp0_bind_id) +#endif + { + TP_LOG_ERR1 ("tp0_connect: bind id %ld invalid. TCP must be enabled in config.", tp0_bind_id); + return (-1); + } + } + else /* Transport type not TP0, this is error. */ + { + TP_LOG_ERR0 ("tp0_connect: invalid transport type"); + return (-1); + } + + if (rem_tp4_addr->tp4_sel_len > MAX_TSEL_LEN) + { + TP4_EXCEPT (); /* If this happens, user code is invalid. */ + return (-1); + } + + /* Look for available connection. */ + tp_conn = &tp0_conn_arr [0]; + for (conn_id = 0; conn_id < tp0_cfg.max_num_conns; conn_id++, tp_conn++) + { + if (tp_conn->state == TP_STATE_CLOSED) + break; /* Found one!! "tp_conn" points to it now. */ + } /* end "for" */ + if (conn_id >= tp0_cfg.max_num_conns) + { /* Didn't find one!! */ + TP_LOG_ERR0 ("TP-ERROR: tp0_connect: all connections in use"); + return (-1); + } + /* "tp_conn" now points to a connection in TP_STATE_CLOSED state. */ + tp0_conn_clean (tp_conn); /* Good time to clean up conn struct. */ + + /* Increment "loc_ref_offset" to avoid duplicate CR. */ + inc_loc_ref_offset (tp_conn->loc_ref_offset); + + /* Set "tpdu_cr" pointing to "tp_conn->tpdu_cx" and fill in. */ + /* Info stored in "tp_conn" in case retransmissions needed. */ + tpdu_cr = &tp_conn->tpdu_cx; + memcpy (tpdu_cr->loc_tsap, tp0_loc_tsap, tp0_loc_tsap [0]+1); + tpdu_cr->rem_tsap [0] = (ST_UCHAR) rem_tp4_addr->tp4_sel_len; + memcpy (&tpdu_cr->rem_tsap [1], rem_tp4_addr->tp4_sel, rem_tp4_addr->tp4_sel_len); + tpdu_cr->loc_ref = calc_loc_ref (conn_id, tp_conn->loc_ref_offset); + tpdu_cr->rem_ref = 0; + tpdu_cr->max_tpdu_len_enc = tp0_cfg.max_tpdu_len_enc; + tpdu_cr->preferred_class = 0; + tpdu_cr->cdt = 0; + tpdu_cr->udata_len = min ((ST_UINT16) conndata_len, TP_MAX_CONN_UDATA); + memcpy (tpdu_cr->udata_buf, conndata, tpdu_cr->udata_len); + + /* Set state before calling np_connect_req (may complete immediately).*/ + tp_conn->user_conn_id = user_conn_id; /* Save User's ID for confirm. */ + tp_conn->state = TP_STATE_WFNC; + if ((tp_conn->sock_info = np_connect_req ((ST_LONG) tp_conn, rem_tp4_addr->netAddr.ip, + rem_tp4_addr->port, encrypt_ctrl)) == NULL) + { + tp_conn->state = TP_STATE_CLOSED; /* CRITICAL: so tp_conn can be reused.*/ +#if defined(SPDU_RX_NO_PREALLOCATE) + M_FREE (MSMEM_STARTUP, tp_conn->spdu_rx.spdu_ptr); +#endif + return (-1); /* Network connect failed immediately. */ + } + + /* CRITICAL: For TP0, connection ID = (conn_id+MIN_TP0_CONN_ID). */ + return (conn_id+MIN_TP0_CONN_ID); + } + +/************************************************************************/ +/* tp0_process_cc */ +/************************************************************************/ +ST_VOID tp0_process_cc (TPDU_CX *tpdu_cc) + { +ST_ULONG conn_id; /* index into "tp0_conn_arr" array (Unsigned so */ + /* no sign-extension on compare to tp0_cfg.max_num_conns).*/ +TP0_CONN *tp_conn; /* ptr to struct in "tp0_conn_arr" array. */ +TPDU_DR tpdu_dr; +ST_INT unacceptable_cc = SD_FALSE; +ST_INT reason; + + + /* Fill in TPDU_DR struct in case DR needs to be sent. */ + /* Do not fill in "reason" yet. */ + tpdu_dr.loc_ref = tpdu_cc->loc_ref; + tpdu_dr.rem_ref = tpdu_cc->rem_ref; + tpdu_dr.sock_info = tpdu_cc->sock_info; + + /* Check connection ID. */ + if (tpdu_cc->sock_info->user_conn_id == INVALID_CONN_ID) + { + /* Invalid ID means CR has not been sent, so this CC is unexpected. */ + /* CC most likely received from "abnormal" application. */ + TP_LOG_ERR0 ("TP-ERROR: tp0_process_cc: Invalid tp_conn"); + /* May be intentional attack, so disconnect immediately. */ + np_disconnect_req (tpdu_cc->sock_info); + return; + } + + /* Find the correct "tp_conn". It should have been saved in sock_info.*/ + tp_conn = (TP0_CONN *) tpdu_cc->sock_info->user_conn_id; + + + conn_id = tp_conn - tp0_conn_arr; /* conn_id = index into array */ + + switch (tp_conn->state) + { + case TP_STATE_CLOSED: + tpdu_dr.reason = TP_DR_NO_SESSION; /* We're not trying to connect*/ + tp0_send_dr (&tpdu_dr); + break; + case TP_STATE_WFCC: + /* Check for Transport Class 0. Don't allow any other. */ + if (tpdu_cc->preferred_class != 0) + { + unacceptable_cc = SD_TRUE; + } + /* Save negotiated TPDU len in tp_conn->max_tpdu_len. */ + switch (tpdu_cc->max_tpdu_len_enc) + { + case TP_PDU_MAX_SIZE_128 : tp_conn->max_tpdu_len = 128; break; + case TP_PDU_MAX_SIZE_256 : tp_conn->max_tpdu_len = 256; break; + case TP_PDU_MAX_SIZE_512 : tp_conn->max_tpdu_len = 512; break; + case TP_PDU_MAX_SIZE_1024 : tp_conn->max_tpdu_len = 1024; break; + case TP_PDU_MAX_SIZE_2048 : tp_conn->max_tpdu_len = 2048; break; + case TP_PDU_MAX_SIZE_4096 : tp_conn->max_tpdu_len = 4096; break; + case TP_PDU_MAX_SIZE_8192 : tp_conn->max_tpdu_len = 8192; break; + case TP_PDU_MAX_SIZE_65531: tp_conn->max_tpdu_len = 65531; break; + /* Default to ILLEGAL value (i.e. 0) */ + default: tp_conn->max_tpdu_len = 0; break; + } /* end "switch" */ + /* If max_tpdu_len ILLEGAL or ">" proposed, this is protocol error.*/ + if (tp_conn->max_tpdu_len == 0 || /* ILLEGAL */ + tp_conn->max_tpdu_len > tp0_cfg.max_tpdu_len) /* ">" proposed */ + { + tpdu_dr.reason = TP_DR_NO_REASON; + unacceptable_cc = SD_TRUE; + } + + if (unacceptable_cc) + { /* UN-ACCEPTABLE CLASS 0 CC TPDU. */ + reason = 0xff; /* Local user error */ + tp4_disconnect_ind (tp_conn->user_conn_id, reason, + 0, NULL); /* No user data passed up. */ + np_disconnect_req (tp_conn->sock_info); + tp_conn->state = TP_STATE_CLOSED; +#if defined(SPDU_RX_NO_PREALLOCATE) + M_FREE (MSMEM_STARTUP, tp_conn->spdu_rx.spdu_ptr); +#endif + } + else + { /* ACCEPTABLE CLASS 0 CC TPDU. */ + /* Save "rem_ref" in "tp_conn". */ + tp_conn->rem_ref = tpdu_cc->rem_ref; + + /* CRITICAL: set state before tp4_connect_cnf because may */ + /* send first Transport data from within tp4_connect_cnf. */ + tp_conn->state = TP_STATE_OPEN; + tp4_connect_cnf (tp_conn->user_conn_id, conn_id+MIN_TP0_CONN_ID, + (ST_UINT) tpdu_cc->udata_len, tpdu_cc->udata_buf); + tp_conn->state = TP_STATE_OPEN; + } + break; + + default: + TP_LOG_ERR1 ("TP-ERROR: invalid state (%d) for received CC. Ignored.", + tp_conn->state); + break; + } /* end "switch" */ + return; + } + diff --git a/mmslib/ositcps/tp0main.c b/mmslib/ositcps/tp0main.c new file mode 100644 index 0000000..1b24f38 --- /dev/null +++ b/mmslib/ositcps/tp0main.c @@ -0,0 +1,1173 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2005 All Rights Reserved */ +/* */ +/* MODULE NAME : tp0main.c */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* Main processsing functions for TP0. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* tp0_initialize () */ +/* tp0_terminate () */ +/* tp0_bind () */ +/* tp0_unbind () */ +/* tp0_session_timer () */ +/* tp0_timer_tick () */ +/* tp0_buffers_avail () */ +/* tp0_event () */ +/* tp0_data () */ +/* tp0_disconnect () */ +/* tp0_process_dt () */ +/* tp0_process_dr () */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/30/08 JRB 27 Use DR reason codes valid for TP0. */ +/* 06/23/06 JRB 26 Fix calc_loc_ref problem (conn_id wrong type)*/ +/* 06/06/05 EJV 25 MMSEASE_MOSI: add rfc1006_listener_* funcs. */ +/* 04/06/05 EJV 24 Added MMSEASE_MOSI support. */ +/* tp0_terminate: check for valid tp0_conn_arr. */ +/* 03/11/05 JRB 23 Ignore DT.ind or DR.ind if waiting for CR.ind*/ +/* 02/22/05 JRB 22 tp0_data: fix return value. */ +/* 01/24/05 JRB 21 Move tp4_debug_sel & "*_logstr" to lean_var.c*/ +/* 09/17/04 JRB 20 tp0_session_timer: chk state only if starting*/ +/* Use session_cfg.disconnect_timeout. */ +/* 01/13/04 EJV 19 tp0_initialize: set tp0_cfg.max_spdu_outst. */ +/* Changed tp0_send_... funcs to return value. */ +/* np_data_req: added eot param. */ +/* 04/07/03 JRB 18 Add SPDU_RX_NO_PREALLOCATE option. */ +/* 07/10/02 JRB 17 tp0_buffers_avail return INT_MAX (no limit). */ +/* 06/20/02 JRB 16 Add tp0_convert_ip function. */ +/* 05/08/02 JRB 15 Add tp0_connect_outstanding_count function. */ +/* 01/22/02 JRB 14 Add max_conns arg to tp0_initialize. */ +/* 05/25/01 JRB 13 Fix thisFile.. warning. */ +/* 03/15/00 JRB 12 Alloc tp_conn->spdu_rx.spdu_ptr once at */ +/* startup for each conn. Free before exit. */ +/* 03/15/00 JRB 11 If spdu_rx exceeds max, disconnect. */ +/* 01/05/01 EJV 10 tp0_initialize: corrected logging. */ +/* 03/14/00 JRB 09 tp0_terminate: fake DR.ind so stack cleans up*/ +/* 09/13/99 MDE 08 Added SD_CONST modifiers */ +/* 06/08/99 JRB 07 Chg to support 1024 connections. */ +/* 08/13/98 JRB 06 Lint cleanup. */ +/* 03/23/98 NAV 05 Free g_tpkt_enc_buf on termination */ +/* 02/16/98 JRB 04 Cast args. */ +/* 09/25/97 JRB 03 Don't generate exception for invalid state. */ +/* 09/23/97 JRB 02 tp0_terminate: disconnect all TP0 conns. */ +/* 08/01/97 JRB 01 Created (compatible with MMS-EASE 7.0). */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "tp4api.h" /* User definitions for tp4 */ +#include "tp4.h" /* Internal definitions for tp4 */ +#include "tp4_encd.h" +#include "tp4_log.h" + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif +/************************************************************************/ +/* Local function Prototypes */ +/************************************************************************/ + +/************************************************************************/ +/* Global Configuration Structure */ +/* This structure must be filled in by user BEFORE tp0_initialize (). */ +/* It MUST NOT change after tp0_initialize (). */ +/* DEBUG: should tp0_initialize make it's own copy of this struct */ +/* so that the user CAN NOT screw it up????? */ +/************************************************************************/ +TP0_CFG tp0_cfg; + +/************************************************************************/ +/* Global Variables initialized by tp0_initialize (). */ +/* Not accessible to user. */ +/************************************************************************/ +TP0_CONN *tp0_conn_arr; /* ptr to array of "max_num_conns" structs */ +ST_UCHAR *g_tpkt_enc_buf; /* Buffer for encoding TPKTs. */ +static ST_UINT g_tp0_max_spdu_len; /* Max SPDU size to send or receive */ + +/************************************************************************/ +/* Global Variables initialized by tp0_bind (). */ +/* Not accessible to user. */ +/************************************************************************/ +#if defined(MMSEASE_MOSI) +/* multiple binds allowed, tp0_bind_id = index into the bind_tsel_tbl */ +typedef struct tagBIND_TSEL + { + ST_LONG user_bind_id; /* = session bind id */ + ST_UCHAR tsel [1+MAX_TSEL_LEN]; /* Local len & TSEL */ + } BIND_TSEL; + +ST_UINT bind_tsel_tbl_max; /* for now use max_conns */ +BIND_TSEL *bind_tsel_tbl; /* entry 0 unused! */ +#else /* !defined(MMSEASE_MOSI) */ +/* DEBUG: should we check tp0_bind_called before any calls to user? */ +static ST_INT tp0_bind_called; /* Flag to prevent multiple bind calls. */ +/* CRITICAL: only_tp0_bind_id must be different from only_tp4_bind_id, */ +/* because either may be passed up to user in tp4_bind_cnf. */ +ST_LONG only_tp0_bind_id = 199; /* Only one tp0_bind_id. */ +ST_LONG only_tp0_user_bind_id; /* Only one user_bind_id. */ +ST_UCHAR only_tp0_loc_tsap [1+MAX_TSEL_LEN]; /* Local len & TSAP addr*/ +#endif /* !defined(MMSEASE_MOSI) */ + +/*======================================================================*/ +/*======================================================================*/ +/* INITIALIZATION AND TERMINATION FUNCTIONS */ +/*======================================================================*/ +/*======================================================================*/ + +/************************************************************************/ +/* tp0_initialize */ +/* Initialize the TP0 service provider. */ +/* NOTE: the configuration parameters in the "tp0_cfg" struct must be */ +/* set BEFORE calling this function. */ +/* WARNING: tp0_cfg MUST NOT be modified after this function called. */ +/* NOTE: the value of tp0_cfg.max_num_conns is overwritten with the */ +/* value passed in the argument max_conns. */ +/* Return: */ +/* SD_SUCCESS or */ +/* error code (TP4E_* or error code returned from np_init) */ +/************************************************************************/ +ST_RET tp0_initialize (ST_UINT max_conns, ST_UINT max_spdu_len) + { +ST_RET errcode; +ST_UINT16 max_tpkt_len; /* Max len of RFC1006 TPKT. */ +ST_UINT j; + + if (max_conns > TP_MAX_NUM_CONNS) + { + TP_LOG_ERR1 ("TP-ERROR: number of requested TCP connections (%d) exceeds max", + max_conns); + return (TP4E_INVAL_NUM_CONNS); + } + tp0_cfg.max_num_conns = max_conns; /* overwrite configured value */ + +#if !defined (TP4_ENABLED) /* Otherwise, done in tp4_initialize */ +#if defined(DEBUG_SISCO) + tp4_debug_sel |= TP4_LOG_ERR; /* Always enable error logging. */ +#endif + tp4_init_timer (); +#endif /* !TP4_ENABLED */ + + /* Save arg in global for later use. */ + g_tp0_max_spdu_len = max_spdu_len; + + /* Check that all configured parameter values are legal. */ + + /* init the max number of SPDUs that can be queued in gensock2 */ + if (tp0_cfg.max_spdu_outst == 0) + tp0_cfg.max_spdu_outst = 50; + + /* Check max_tpdu_len. If legal, save binary encoding in global NOW. */ + switch (tp0_cfg.max_tpdu_len) + { /* code for PDU size */ + case 128: tp0_cfg.max_tpdu_len_enc = TP_PDU_MAX_SIZE_128 ; break; + case 256: tp0_cfg.max_tpdu_len_enc = TP_PDU_MAX_SIZE_256 ; break; + case 512: tp0_cfg.max_tpdu_len_enc = TP_PDU_MAX_SIZE_512 ; break; + case 1024: tp0_cfg.max_tpdu_len_enc = TP_PDU_MAX_SIZE_1024 ; break; + case 2048: tp0_cfg.max_tpdu_len_enc = TP_PDU_MAX_SIZE_2048 ; break; + case 4096: tp0_cfg.max_tpdu_len_enc = TP_PDU_MAX_SIZE_4096 ; break; + case 8192: tp0_cfg.max_tpdu_len_enc = TP_PDU_MAX_SIZE_8192 ; break; + case 65531: tp0_cfg.max_tpdu_len_enc = TP_PDU_MAX_SIZE_65531; break; + default: + TP_LOG_ERR1 ("TP-ERROR: configured rfc1006_max_tpdu_len (%d) illegal", + tp0_cfg.max_tpdu_len); + return (TP4E_INVAL_TPDU_LEN); + } + + /* Compute Max TPKT len & allocate TPKT encode buffer. */ + max_tpkt_len = tp0_cfg.max_tpdu_len + RFC1006_HEAD_LEN; + g_tpkt_enc_buf = (ST_UCHAR *) M_MALLOC (MSMEM_STARTUP, max_tpkt_len); + + /* Initialize the Network layer (i.e. RFC1006). */ + + + + + if ((errcode = np_init (max_conns)) != SD_SUCCESS) + return (errcode); + + tp0_conn_arr = (TP0_CONN *) M_CALLOC (MSMEM_STARTUP, max_conns, sizeof (TP0_CONN)); + for (j=0; jtp_type != TP_TYPE_TCP) + { /* Not for TP0 */ + /* No other TP provider to pass to. This is error. */ + TP_LOG_ERR0 ("TP-ERROR: tp0_bind: invalid transport type"); + return (SD_FAILURE); + } + + if (max_conns > tp0_cfg.max_num_conns) + { + TP_LOG_ERR2 ("TP-ERROR: tp0_bind: requested TP conns (%d) greater than number configured (%d)", + max_conns, tp0_cfg.max_num_conns); + return (TP4E_INVAL_NUM_CONNS); + } + +/* DEBUG:: the tbl alloc may need to be moved to tp0_initialize, and free */ +/* in tp0_terminate. */ + if (!bind_tsel_tbl) + { + bind_tsel_tbl_max = tp0_cfg.max_num_conns + 1; /* entry 0 unused */ + bind_tsel_tbl = (BIND_TSEL *) chk_calloc (bind_tsel_tbl_max, sizeof(BIND_TSEL)); + } + + /* Make sure Local TSAP len is legal before copying. */ + if (tp4_addr->tp4_sel_len > 0 && tp4_addr->tp4_sel_len <= MAX_TSEL_LEN) + { + /* find a spot in the bind_tsel_tbl (entry 0 unused) */ + for (idx=1; idxtsel[0] == 0) /* if available */ + { + ST_UCHAR tmp_tsel[MAX_TSEL_LEN+1]; + tmp_tsel[0] = (ST_UCHAR) tp4_addr->tp4_sel_len; + memcpy (&tmp_tsel[1], tp4_addr->tp4_sel, tp4_addr->tp4_sel_len); + if (tp0_check_tsel (tmp_tsel, NULL) == SD_SUCCESS) + { + TP_LOG_ERR0 ("TP-ERROR: tp0_bind: TSEL already bound"); + TP_LOGH_ERR (tp4_addr->tp4_sel_len, tp4_addr->tp4_sel); + return (TP4E_INVAL_TSEL); + } + ret = rfc1006_listener_bind (tmp_tsel); + if (ret != SD_SUCCESS) + return (ret); + tp0_bind_id = idx; + bind_tsel->user_bind_id = user_bind_id; + memcpy (bind_tsel->tsel, tmp_tsel, tp4_addr->tp4_sel_len+1); + TP_LOG_REQ1 ("tp0_bind: Bound TSEL to tp0_bind_id=%d", tp0_bind_id); + TP_LOGH_REQ (tp4_addr->tp4_sel_len, tp4_addr->tp4_sel); + break; + } + } + if (idx == bind_tsel_tbl_max) + { + TP_LOG_ERR0 ("TP-ERROR: too many binds"); + return (TP4E_TOO_MANY_BINDS); + } + } + else + { + TP_LOG_ERR2 ("TP-ERROR: tp0_bind: invalid TSEL length=%d octets (len>0 && len<=%d)", + tp4_addr->tp4_sel_len, MAX_TSEL_LEN); + return (TP4E_INVAL_TSEL); + } + + tp4_bind_cnf (user_bind_id, tp0_bind_id, SD_SUCCESS); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* rfc1006_listener_unbind */ +/* Function to unbind TSAP in rfc1006_listener task. Passed through */ +/* UNIX domain socket. Waits for the response, discarding any non */ +/* RFC1006_IPC_OP_UNBIND messages. */ +/************************************************************************/ +ST_RET rfc1006_listener_unbind (ST_UCHAR *tsap) + { +ST_UINT tsap_len = (ST_UINT) ((ST_UINT8) tsap [0]+1); +RFC1006_IPC_MSG ipc_msg; +int count; +ST_CHAR *tmp_buf; +char resp; + + ipc_msg.magic = RFC1006_IPC_MAGIC_NUM; + ipc_msg.opcode = RFC1006_IPC_OP_UNBIND; + ipc_msg.data_len = 0; + + /* send the UNBIND msg header */ + count = sendwait (domsock_listener, &ipc_msg, sizeof (RFC1006_IPC_MSG), 0); + if (count != sizeof (RFC1006_IPC_MSG)) + { + TP_LOG_ERR0 ("TP-ERROR: rfc1006_listener_unbind: send UNBIND header failed."); + return (SD_FAILURE); + } + + /* send the TSAP to unbind */ + count = sendwait (domsock_listener, tsap, tsap_len, 0); + if (count != tsap_len) + { + TP_LOG_ERR0 ("TP-ERROR: rfc1006_listener_unbind: send UNBIND TSAP failed."); + return (SD_FAILURE); + } + + /* Keep trying to read until RFC1006_IPC_OP_UNBIND response arrives. */ + do + { /* read and drop any other IPC_MSG */ + count = recvwait (domsock_listener, &ipc_msg, sizeof (RFC1006_IPC_MSG), 0); + if (count != sizeof (RFC1006_IPC_MSG)) + { + TP_LOG_ERR0 ("TP-ERROR: rfc1006_listener_unbind: failed to receive UNIBIND response."); + return (SD_FAILURE); + } + if (ipc_msg.magic != RFC1006_IPC_MAGIC_NUM) + { + TP_LOG_ERR1 ("TP-ERROR: rfc1006_listener_unbind: received invalid magic='%X'", + ipc_msg.magic); + return (SD_FAILURE); + } + if (ipc_msg.opcode != RFC1006_IPC_OP_UNBIND) + { + TP_LOG_IND2 ("rfc1006_listener_unbind: waiting for UNBIND response.\n Ignoring message with opcode=%d, len=%d", + ipc_msg.opcode, ipc_msg.data_len); + if (ipc_msg.data_len > 0) /* read and discard data if present */ + { + tmp_buf = chk_malloc (ipc_msg.data_len); + count = read (domsock_listener, tmp_buf, ipc_msg.data_len); + chk_free (tmp_buf); + } + } + } while (ipc_msg.opcode != RFC1006_IPC_OP_UNBIND); + + if (ipc_msg.data_len != 1) + { + TP_LOG_ERR1 ("TP-ERROR: rfc1006_listener_unbind: received invalid data_len=%u (expecting 1 byte)", + (ST_UINT) ipc_msg.data_len); + return (SD_FAILURE); + } + + count = recvwait (domsock_listener, &resp, 1, 0); + if (count != 1) + { + TP_LOG_ERR0 ("TP-ERROR: rfc1006_listener_unbind: failed to receive expected 1 byte UNBIND response"); + return (SD_FAILURE); + } + + if (resp != SD_SUCCESS) + { + TP_LOG_ERR1 ("TP-ERROR: rfc1006_listener_unbind: UNBIND failed resp=%d.", + (ST_UINT) resp); + return (SD_FAILURE); + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* tp0_unbind */ +/************************************************************************/ +ST_RET tp0_unbind (ST_LONG tp0_bind_id) + { +ST_RET ret = SD_FAILURE; +BIND_TSEL *bind_tsel; + + if (bind_tsel_tbl && tp0_bind_id > 0 && tp0_bind_id <= bind_tsel_tbl_max) + { + /* tp0_bind_id is the index into the bind table */ + bind_tsel = &bind_tsel_tbl[tp0_bind_id]; + if (bind_tsel->tsel[0] != 0) + { + ret = rfc1006_listener_unbind (bind_tsel->tsel); + TP_LOG_REQ1 ("tp0_unbind: tp0_bind_id=%d", tp0_bind_id); + tp4_unbind_cnf (bind_tsel->user_bind_id); + bind_tsel->tsel[0] = 0; + bind_tsel->user_bind_id = 0; + ret = SD_SUCCESS; + } + else + TP_LOG_ERR0 ("TP-ERROR: TP0 UNBIND failed (not bound)."); + } + else + TP_LOG_ERR1 ("TP-ERROR: TP0 UNBIND failed (invalid tp0_bind_id=%ld).", tp0_bind_id); + + return (ret); + } + +/************************************************************************/ +/* tp0_check_tsel */ +/* Checks if given tsel was bound and sets the user_bind_id if tsel OK. */ +/* Returns: */ +/* SD_SUCCESS if tsel bound */ +/* SD_FAILURE otherwise */ +/************************************************************************/ +ST_RET tp0_check_tsel (ST_UCHAR *tsel, ST_LONG *user_bind_id) + { +ST_RET ret = SD_FAILURE; +ST_UINT idx; +BIND_TSEL *bind_tsel; + + /* find tsel (entry 0 unused) */ + for (idx=1; idxtsel[0] > 0 && + memcmp (tsel, bind_tsel->tsel, bind_tsel->tsel[0]+1) == 0) + { + if (user_bind_id) + *user_bind_id = bind_tsel->user_bind_id; + ret = SD_SUCCESS; /* tsel is bound */ + break; + } + } + return (ret); + } + +/************************************************************************/ +/* tp0_check_bind_id */ +/* Checks if given bind_id is valid and sets the tsel if bind_id OK. */ +/* Returns: */ +/* SD_SUCCESS if bind_id valid */ +/* SD_FAILURE otherwise */ +/************************************************************************/ +ST_RET tp0_check_bind_id (ST_LONG bind_id, ST_UCHAR **tsel) + { +ST_RET ret = SD_FAILURE; +ST_UINT idx; +BIND_TSEL *bind_tsel; + + /* check bind_id (entry 0 unused) */ + for (idx=1; idxtsel[0] > 0 && (ST_LONG) idx == bind_id) + { + *tsel = bind_tsel->tsel; + ret = SD_SUCCESS; /* bind_id valid */ + break; + } + } + return (ret); + } + +#else /* !defined(MMSEASE_MOSI) */ +/************************************************************************/ +/* tp0_bind */ +/* This function substitutes for "tp4_bind" when TP0/RFC1006 is being */ +/* used. See "tp4_bind" header for more info. */ +/************************************************************************/ +ST_RET tp0_bind (ST_LONG user_bind_id, + TP4_ADDR *tp4_addr, + ST_INT sharable, + ST_INT max_conns) + { + + + + + if (tp4_addr->tp_type != TP_TYPE_TCP) + { /* Not for TP0 */ + /* No other TP provider to pass to. This is error. */ + TP_LOG_ERR0 ("TP-ERROR: tp0_bind: invalid transport type"); + return (SD_FAILURE); + } + + if (tp0_bind_called) + { + TP_LOG_ERR0 ("TP-ERROR: too many binds"); + return (TP4E_TOO_MANY_BINDS); + } + + if (max_conns > tp0_cfg.max_num_conns) + { + TP_LOG_ERR2 ("TP-ERROR: requested TP conns (%d) greater than number configured (%d)", + max_conns, tp0_cfg.max_num_conns); + return (TP4E_INVAL_NUM_CONNS); + } + + /* Save user_bind_id in Global. Use in all calls to user functions. */ + only_tp0_user_bind_id = user_bind_id; + + /* Make sure Local TSAP len is legal before copying. */ + if (tp4_addr->tp4_sel_len > MAX_TSEL_LEN) + { + TP_LOG_ERR0 ("TP-ERROR: TSEL too long"); + return (TP4E_INVAL_TSEL); + } + + /* Save Local TSAP (only do memcpy if len != 0). */ + if ((only_tp0_loc_tsap [0] = (ST_UCHAR) tp4_addr->tp4_sel_len) != 0) + memcpy (&only_tp0_loc_tsap [1], tp4_addr->tp4_sel, tp4_addr->tp4_sel_len); + + + + tp4_bind_cnf (user_bind_id, only_tp0_bind_id, SD_SUCCESS); + tp0_bind_called = SD_TRUE; /* Only set if successful. */ + + + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* tp0_unbind */ +/************************************************************************/ +ST_RET tp0_unbind (ST_LONG tp0_bind_id) + { + if (tp0_bind_id != only_tp0_bind_id) + return (SD_FAILURE); /* Invalid bind id. */ + if (tp0_bind_called == SD_FALSE) + return (SD_FAILURE); /* Bind never made. Cannot unbind. */ + tp0_bind_called = SD_FALSE; /* Clear flag so user can bind again. */ + tp4_unbind_cnf (only_tp0_user_bind_id); + return (SD_SUCCESS); + } +#endif /* !defined(MMSEASE_MOSI) */ + +/*======================================================================*/ +/*======================================================================*/ +/* TIMER FUNCTIONS */ +/*======================================================================*/ +/*======================================================================*/ + +/************************************************************************/ +/* tp0_session_timer */ +/*----------------------------------------------------------------------*/ +/* This function starts the session timer (for MOSI implementation). */ +/* The user function tp4_session_timer_expired will be called if the */ +/* timer expires. */ +/* */ +/* Parameters: */ +/* ST_LONG tp_conn_id TP0 connection id for this connect. */ +/* ST_BOOLEAN start SD_TRUE if timer should be started, */ +/* SD_FALSE if timer should be stopped. */ +/* */ +/* Return: */ +/* SD_SUCCESS (0) if successful */ +/* error code if not successful */ +/************************************************************************/ +ST_RET tp0_session_timer (ST_LONG tp_conn_id, ST_BOOLEAN start) +{ +TP0_CONN *tp_conn = &tp0_conn_arr [tp_conn_id-MIN_TP0_CONN_ID]; + + if (start) + { + if (tp_conn->state != TP_STATE_OPEN) + { + TP_LOG_ERR1 ("TP-ERROR: illegal connection state = %d", tp_conn->state); + return (TP4E_CONN_STATE); + } + + /* If configured, use configured val. It not, use reasonable val.*/ + if (session_cfg.disconnect_timeout) + tp_conn->session_timer = session_cfg.disconnect_timeout; + else + tp_conn->session_timer = 60; + } + else + tp_conn->session_timer = 0; /* stopping the session timer */ + + return (SD_SUCCESS); +} + +/************************************************************************/ +/* tp0_timer_tick */ +/*----------------------------------------------------------------------*/ +/* This function is called on 1 second intervals by the TP0-user */ +/* When this function is called, TP0 decrements all of the timers */ +/* for all outstanding transport connections. */ +/* */ +/* Parameters: */ +/* ST_VOID none */ +/* */ +/* Return: */ +/* ST_VOID none */ +/************************************************************************/ +ST_VOID tp0_timer_tick () + { +ST_UINT conn_id; +TP0_CONN *tp_conn; + + /* Because this function is called often and the entire tp0_conn_arr */ + /* must be checked, it must be very efficient. Therefore, tp_conn */ + /* is used to point to each element of array (instead of */ + /* tp0_conn_arr[conn_id]). */ + for (conn_id = 0, tp_conn = &tp0_conn_arr[0]; + conn_id < tp0_cfg.max_num_conns; + conn_id++, tp_conn++) + { + /* Handle "session timer" (MOSI implementation only) */ + /* Only decrement it if it's not 0 and state is legal. */ + if (tp_conn->state == TP_STATE_OPEN && + tp_conn->session_timer) + { + if (--tp_conn->session_timer == 0) + tp4_session_timer_expired (tp_conn->user_conn_id); + } /* End "session timer" handling */ + } /* End "for" loop */ + } + +/************************************************************************/ +/* tp0_buffers_avail */ +/*----------------------------------------------------------------------*/ +/* This function returns the number of buffers available for sending */ +/* SPDUs. This may be used, for example, when sending Information */ +/* Reports, to make sure there are always enough buffers for sending */ +/* responses to incoming requests. */ +/* */ +/* Parameters: */ +/* ST_LONG tp_conn_id Transport Connection ID */ +/* */ +/* Return: */ +/* ST_INT # of SPDU transmit buffers available */ +/************************************************************************/ +ST_INT tp0_buffers_avail (ST_LONG tp_conn_id) + { +TP0_CONN *tp_conn = &tp0_conn_arr [tp_conn_id-MIN_TP0_CONN_ID]; +ST_UINT spdu_que_cnt; + + spdu_que_cnt = np_get_tx_queue_cnt (tp_conn->sock_info); + return (tp0_cfg.max_spdu_outst - spdu_que_cnt); + } + +/************************************************************************/ +/* tp0_event */ +/* Receive a n_unitdata NSDU, decode it, process it, and free it. */ +/************************************************************************/ +ST_BOOLEAN tp0_event () + { + tp4_check_timer (); + + return (np_event ()); + } + +/*======================================================================*/ +/*======================================================================*/ +/* FUNCTIONS BELOW CALLED BY USER TO ENCODE AND SEND TPDUs. */ +/*======================================================================*/ +/*======================================================================*/ + +/************************************************************************/ +/* tp0_data */ +/* RETURN CODES: */ +/* SD_SUCCESS (if SPDU successfully queued for sending) */ +/* TP4E_CONN_STATE (connection not in proper state for this) */ +/* OR error returned from tp0_send_dt. */ +/************************************************************************/ +ST_RET tp0_data (ST_LONG tp_conn_id, ST_INT eot, ST_UINT spdu_len, ST_CHAR *spdu_ptr) + { +ST_RET ret = SD_SUCCESS; +TP0_CONN *tp_conn = &tp0_conn_arr [tp_conn_id-MIN_TP0_CONN_ID]; +ST_UINT spdu_offset; +TPDU_DT tpdu_dt_tx; /* ptr to TPDU of interest. */ + + if (tp_conn->state != TP_STATE_OPEN) + { + TP_LOG_ERR1 ("TP-ERROR: illegal connection state = %d", tp_conn->state); + return (TP4E_CONN_STATE); + } + + tpdu_dt_tx.dst_ref = tp_conn->rem_ref; + tpdu_dt_tx.sock_info = tp_conn->sock_info; + + /* Set up TPDU user data by pointing into SPDU. */ + for (spdu_offset = 0; spdu_offset < spdu_len; ) + { + tpdu_dt_tx.udata_ptr = spdu_ptr + spdu_offset; + if (spdu_len - spdu_offset <= (ST_UINT)(tp_conn->max_tpdu_len - TP0_HEAD_LEN_DT)) + { + tpdu_dt_tx.udata_len = spdu_len - spdu_offset; + tpdu_dt_tx.eot = SD_TRUE; + } + else + { + TP_LOG_REQ0 ("TP-INFO: SPDU being segmented. Should increase TPDU size."); + /* Send largest allowed TPDU, taking header size into account. */ + tpdu_dt_tx.udata_len = (tp_conn->max_tpdu_len - TP0_HEAD_LEN_DT); + tpdu_dt_tx.eot = SD_FALSE; + } + spdu_offset += tpdu_dt_tx.udata_len; + + ret = tp0_send_dt (&tpdu_dt_tx); + if (ret != SD_SUCCESS) + break; + } /* end "for" */ + + return (ret); + } + +/************************************************************************/ +/* tp0_disconnect */ +/* This function is called by the user to break connection */ +/************************************************************************/ +ST_RET tp0_disconnect (ST_LONG tp0_conn_id, + ST_INT conndata_len, + char *conndata) + { +TP0_CONN *tp_conn; /* ptr to struct in "tp0_conn_arr" array. */ +TPDU_DR tpdu_dr; +ST_UINT16 conn_id = (ST_UINT16) tp0_conn_id - MIN_TP0_CONN_ID; + + if (conn_id >= tp0_cfg.max_num_conns) + return (TP4E_BADCONN); + + tp_conn = &tp0_conn_arr [conn_id]; + + /* Fill in TPDU_DR struct in case DR needs to be sent. */ + tpdu_dr.loc_ref = calc_loc_ref (conn_id, tp_conn->loc_ref_offset); + tpdu_dr.rem_ref = tp_conn->rem_ref; + tpdu_dr.sock_info = tp_conn->sock_info; + tpdu_dr.reason = TP_DR_NO_REASON; + + switch (tp_conn->state) + { + case TP_STATE_OPEN: + case TP_STATE_WFCC: + case TP_STATE_WFNC: + np_disconnect_req (tp_conn->sock_info); + tp_conn->state = TP_STATE_CLOSED; +#if defined(SPDU_RX_NO_PREALLOCATE) + M_FREE (MSMEM_STARTUP, tp_conn->spdu_rx.spdu_ptr); +#endif + break; + case TP_STATE_WFTRESP: + /* Overwrite assumed "loc_ref". Not valid in this state. */ + tpdu_dr.loc_ref = 0; + tp0_send_dr (&tpdu_dr); + tp_conn->state = TP_STATE_CLOSED; +#if defined(SPDU_RX_NO_PREALLOCATE) + M_FREE (MSMEM_STARTUP, tp_conn->spdu_rx.spdu_ptr); +#endif + break; + default: + TP_LOG_ERR1 ("TP-ERROR: invalid state (%d) for sending DR. Not sent.", + tp_conn->state); + return (SD_FAILURE); + } /* end "switch" */ + return (SD_SUCCESS); + } + +/*======================================================================*/ +/*======================================================================*/ +/* FUNCTIONS BELOW CALLED BY TP0 TO PROCESS TPDUs RECEIVED */ +/* (TPDUs ALREADY DECODED BY TP0). */ +/*======================================================================*/ +/*======================================================================*/ + +/************************************************************************/ +/* tp0_process_dt */ +/* Only one SPDU per connection is ever being processed. As soon as */ +/* the EOT is received, the SPDU is passed up to the Transport-user. */ +/************************************************************************/ +ST_VOID tp0_process_dt (TPDU_DT *tpdu_dt_rx) + { +TP0_CONN *tp_conn; + + if (tpdu_dt_rx->sock_info->user_conn_id == INVALID_CONN_ID) + { + TP_LOG_ERR0 ("TP-ERROR: unexpected TPDU-DT.ind ignored. Waiting for TPDU-CR.ind."); + return; + } + + tp_conn = (TP0_CONN *) tpdu_dt_rx->sock_info->user_conn_id; + if (tp_conn - tp0_conn_arr > tp0_cfg.max_num_conns) /* check "conn_id"*/ + { + TP_LOG_ERR0 ("TP-ERROR: illegal connection id"); + return; /* conn_id is invalid. Ignore this TPDU. */ + } + + switch (tp_conn->state) + { + case TP_STATE_CLOSED: + return; /* Ignore this DT. */ + case TP_STATE_OPEN: + break; /* Continue */ + default: + TP_LOG_ERR1 ("TP-ERROR: invalid state (%d) for received DT. Ignored.", + tp_conn->state); + return; + } + + /* If this is beginning of SPDU, initialize buffer for it. */ + if (tp_conn->spdu_rx_start) /* init when CR rcvd or CR sent */ + { /* Last TPDU contained EOT. This TPDU starts new SPDU. */ + /* We can freely overwrite "spdu_rx.spdu_ptr" because the user */ + /* is now responsible for the last one. */ + tp_conn->spdu_rx.spdu_len = 0; + } + + if ((ST_UINT) (tp_conn->spdu_rx.spdu_len + tpdu_dt_rx->udata_len) + > g_tp0_max_spdu_len) + { + /* Would exceed max SPDU size. CAN'T DO memcpy. WON'T FIT IN BUFFER.*/ + /* No good recovery, so just disconnect. */ + /* NOTE: This is really a Session problem, but we handle it here. */ + + TP_LOG_ERR1 ("Received msg exceeds max_spdu_len (%d)", g_tp0_max_spdu_len); + + /* Pass up disconnect indication. */ + tp4_disconnect_ind (tp_conn->user_conn_id, TP_DR_NO_REASON, + 0, NULL); + /* Send disconnect request (compute conn_id from tp_conn. */ + tp0_disconnect (tp_conn - tp0_conn_arr + MIN_TP0_CONN_ID, 0, NULL); + return; /* DO NOT CONTINUE */ + } + + memcpy (tp_conn->spdu_rx.spdu_ptr + tp_conn->spdu_rx.spdu_len, tpdu_dt_rx->udata_ptr, + tpdu_dt_rx->udata_len); + tp_conn->spdu_rx.spdu_len += tpdu_dt_rx->udata_len; + + if (tpdu_dt_rx->eot) + { /* This TPDU contains EOT. This TPDU ends SPDU. */ + tp_conn->spdu_rx_start = SD_TRUE; /* Next TPDU will begin a SPDU. */ + + /* Pass up SPDU to user. Note that we always pass up complete SPDU */ + /* so eot is always SD_TRUE. */ + /* "tp4_data_ind" must completely process the data at spdu_ptr. */ + /* When it returns, the buffer may be reused. */ + + tp4_data_ind (tp_conn->user_conn_id, tpdu_dt_rx->eot, tp_conn->spdu_rx.spdu_len, + tp_conn->spdu_rx.spdu_ptr); + } + else + tp_conn->spdu_rx_start = SD_FALSE; /* Next TPDU is part of this SPDU*/ + } + +/************************************************************************/ +/* tp0_process_dr */ +/* Process a DR (Disconnect Request) TPDU. */ +/************************************************************************/ +ST_VOID tp0_process_dr (TPDU_DR *tpdu_dr) + { +TP0_CONN *tp_conn; +ST_INT reason; + + if (tpdu_dr->sock_info->user_conn_id == INVALID_CONN_ID) + { + TP_LOG_ERR0 ("TP-ERROR: unexpected TPDU-DR.ind ignored. Waiting for TPDU-CR.ind."); + return; + } + + /* tp_conn was saved in "sock_info" (as user_conn_id) when CR sent/rcvd*/ + tp_conn = (TP0_CONN *) tpdu_dr->sock_info->user_conn_id; + + switch (tp_conn->state) + { + case TP_STATE_CLOSED: + break; + case TP_STATE_WFCC: + reason = 0; /* Normal disconnection */ + /* NOTE: To save memory, user data is never passed up to user. */ + tp4_disconnect_ind (tp_conn->user_conn_id, reason, + 0, NULL); /* No user data passed up. */ + np_disconnect_req (tp_conn->sock_info); /* Disconnect network conn.*/ + tp_conn->state = TP_STATE_CLOSED; /* Skip REFWAIT state. */ +#if defined(SPDU_RX_NO_PREALLOCATE) + M_FREE (MSMEM_STARTUP, tp_conn->spdu_rx.spdu_ptr); +#endif + break; + case TP_STATE_OPEN: + TP_LOG_ERR0 ("TP-ERROR: Received TP0 DR in OPEN state. Ignoring."); + break; + default: + TP_LOG_ERR1 ("TP-ERROR: invalid state (%d) for received DR. Ignored.", + tp_conn->state); + break; + } + return; + } + +/*======================================================================*/ +/*======================================================================*/ +/* INTERNAL TP0 FUNCTIONS */ +/*======================================================================*/ +/*======================================================================*/ + +/************************************************************************/ +/* tp0_conn_clean */ +/* Initialize connection struct for a new connection. */ +/************************************************************************/ +ST_VOID tp0_conn_clean (TP0_CONN *tp_conn) + { + tp_conn->spdu_rx_start = SD_TRUE; /* CRITICAL: Initialize flag. */ +#if defined(SPDU_RX_NO_PREALLOCATE) + tp_conn->spdu_rx.spdu_ptr = (ST_CHAR *) M_MALLOC (MSMEM_STARTUP, g_tp0_max_spdu_len); +#endif + return; + } + +/************************************************************************/ +/* tp0_send_dt */ +/* Send a DT (Data) TPDU. */ +/************************************************************************/ +ST_RET tp0_send_dt (TPDU_DT *tpdu_dt) + { +ST_RET ret = SD_FAILURE; +ST_UINT16 data_len; + + tp_log_tsdu ((ST_VOID *) tpdu_dt, (ST_UCHAR) TP_PDU_TYPE_DT, TP_REQ); + + /* Fill in g_tpkt_enc_buf with TPDU */ + data_len = tp0_encode_dt (g_tpkt_enc_buf + RFC1006_HEAD_LEN, tpdu_dt); + if (data_len > 0) + { + /* Fill in g_tpkt_enc_buf HEADER */ + data_len += RFC1006_HEAD_LEN; /* include header in len */ + g_tpkt_enc_buf [0] = 3; /* vrsn */ + g_tpkt_enc_buf [1] = 0; /* reserved */ + g_tpkt_enc_buf [2] = (ST_UCHAR) (data_len >> 8); /* high byte */ + g_tpkt_enc_buf [3] = (ST_UCHAR) (data_len & 0xff); /* low byte */ + ret = np_data_req (tpdu_dt->sock_info, data_len, g_tpkt_enc_buf, tpdu_dt->eot); + } + return (ret); + } + +/************************************************************************/ +/* tp0_send_cr */ +/* Send a CR (Connect Request) TPDU. */ +/************************************************************************/ +ST_RET tp0_send_cr (TPDU_CX *tpdu_cr) + { +ST_RET ret = SD_FAILURE; +ST_UINT16 data_len; + + tp_log_tsdu ((ST_VOID *) tpdu_cr, (ST_UCHAR) TP_PDU_TYPE_CR, TP_REQ); + + /* Fill in g_tpkt_enc_buf with TPDU */ + data_len = tp_encode_cx (g_tpkt_enc_buf + RFC1006_HEAD_LEN, tpdu_cr, + TP_PDU_TYPE_CR); + if (data_len > 0) + { + /* Fill in g_tpkt_enc_buf HEADER */ + data_len += RFC1006_HEAD_LEN; /* include header in len */ + g_tpkt_enc_buf [0] = 3; /* vrsn */ + g_tpkt_enc_buf [1] = 0; /* reserved */ + g_tpkt_enc_buf [2] = (ST_UCHAR) (data_len >> 8); /* high byte */ + g_tpkt_enc_buf [3] = (ST_UCHAR) (data_len & 0xff); /* low byte */ + ret = np_data_req (tpdu_cr->sock_info, data_len, g_tpkt_enc_buf, SD_TRUE); + } + return (ret); + } + +/************************************************************************/ +/* tp0_send_cc */ +/* Send a CC (Connect Confirm) TPDU. */ +/************************************************************************/ +ST_RET tp0_send_cc (TPDU_CX *tpdu_cc) + { +ST_RET ret = SD_FAILURE; +ST_UINT16 data_len; + + tp_log_tsdu ((ST_VOID *) tpdu_cc, (ST_UCHAR) TP_PDU_TYPE_CC, TP_REQ); + + /* Fill in g_tpkt_enc_buf with TPDU */ + data_len = tp_encode_cx (g_tpkt_enc_buf + RFC1006_HEAD_LEN, tpdu_cc, + TP_PDU_TYPE_CC); + if (data_len > 0) + { + /* Fill in g_tpkt_enc_buf HEADER */ + data_len += RFC1006_HEAD_LEN; /* include header in len */ + g_tpkt_enc_buf [0] = 3; /* vrsn */ + g_tpkt_enc_buf [1] = 0; /* reserved */ + g_tpkt_enc_buf [2] = (ST_UCHAR) (data_len >> 8); /* high byte */ + g_tpkt_enc_buf [3] = (ST_UCHAR) (data_len & 0xff); /* low byte */ + ret = np_data_req (tpdu_cc->sock_info, data_len, g_tpkt_enc_buf, SD_TRUE); + } + return (ret); + } + +/************************************************************************/ +/* tp0_send_dr */ +/* Send a DR (Disconnect Request) TPDU. */ +/************************************************************************/ +int cotp_test_mode=0; +ST_RET tp0_send_dr (TPDU_DR *tpdu_dr) + { +ST_RET ret = SD_FAILURE; +ST_UINT16 data_len; + + + if(cotp_test_mode) return SD_FAILURE; /*renxiaobao °²È«¼ì²â*/ + + tp_log_tsdu ((ST_VOID *) tpdu_dr, TP_PDU_TYPE_DR, TP_REQ); + + /* Fill in g_tpkt_enc_buf with TPDU */ + data_len = tp_encode_dr (g_tpkt_enc_buf + RFC1006_HEAD_LEN, tpdu_dr); + if (data_len > 0) + { + /* Fill in g_tpkt_enc_buf HEADER */ + data_len += RFC1006_HEAD_LEN; /* include header in len */ + g_tpkt_enc_buf [0] = 3; /* vrsn */ + g_tpkt_enc_buf [1] = 0; /* reserved */ + g_tpkt_enc_buf [2] = (ST_UCHAR) (data_len >> 8); /* high byte */ + g_tpkt_enc_buf [3] = (ST_UCHAR) (data_len & 0xff); /* low byte */ + ret = np_data_req (tpdu_dr->sock_info, data_len, g_tpkt_enc_buf, SD_TRUE); + } + return (ret); + } + +/************************************************************************/ +/* tp0_connect_outstanding_count */ +/* NOTE: can't presently use tp4Addr for anything, but in the future */ +/* we may use it to check only for outstanding connections to the same */ +/* IP Address. */ +/************************************************************************/ +ST_INT tp0_connect_outstanding_count (TP4_ADDR *tp4Addr) + { +ST_INT connectOutstandingCount = 0; +ST_INT j; + + for (j=0; jh_addr); +#endif /* !VXWORKS */ + } + return (ipAddr); + } diff --git a/mmslib/ositcps/tp4_enc.c b/mmslib/ositcps/tp4_enc.c new file mode 100644 index 0000000..03585b2 --- /dev/null +++ b/mmslib/ositcps/tp4_enc.c @@ -0,0 +1,539 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : tp4_enc.c */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module implements the encoding of the TPDUs. */ +/* */ +/* For information see the: */ +/* ISO 8073 "Information processing systems - Open Systems */ +/* Interconnections - Connection oriented transport protocol */ +/* specification. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* tp_encode_cx */ +/* tp_encode_dr */ +/* tp_encode_dc */ +/* tp_encode_dt */ +/* tp0_encode_dt */ +/* tp_encode_ak */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/13/98 JRB 04 Fix indenting. */ +/* 08/26/97 JRB 03 RFC1006 changes: */ +/* - add TP0 encode */ +/* - tp_encode_cx: if TPDU size = 65531, don't */ +/* encode it. Peer should default to 65531. */ +/* - Use TP_PDU_TYPE_* everywhere. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 10/04/96 JRB 02 Use max_tpdu_len_enc (binary encoded value). */ +/* 06/20/96 EJV 01 Created */ +/************************************************************************/ +static char *thisFileName = __FILE__; /* For TP4_EXCEPT and slog macros*/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "checksum.h" +#include "tp4api.h" /* User definitions for tp4 */ +#include "tp4.h" +#include "tp4_encd.h" +#include "tp4_log.h" + + + +/* local functions prototypes */ + +static ST_VOID tp_enc_par_checksum (ST_UCHAR *buf, ST_UINT16 buf_len, ST_UINT16 par_pos); + + + +/************************************************************************/ +/* tp_encode_cx */ +/*----------------------------------------------------------------------*/ +/* This function is used to encode a CR or CC TPDU. */ +/* */ +/* Parameters: */ +/* ST_UCHAR *enc_buf Pointer where to encode the CX TPDU */ +/* TPDU_CX *tpdu_cx Pointer to info struct for CX TPDU */ +/* ST_UCHAR pdu_type TP_PDU_TYPE_CR or TP_PDU_TYPE_CC */ +/* */ +/* Return: */ +/* ST_UINT16 The actual length of encoded TPDU */ +/************************************************************************/ +ST_UINT16 tp_encode_cx (ST_UCHAR *enc_buf, TPDU_CX *tpdu_cx, ST_UCHAR pdu_type) +{ +ST_UINT16 enc_len; /* The actual length of encoded TPDU */ +TP_FHDR_CX *pdu; +TP_PAR *param; /* generic struct for a parameter */ +ST_UINT16 idx; /* points to current offset into enc_buf*/ + + enc_len = 0; + + /*------------------------------------*/ + /* encode TPDU header, fixed part */ + /*------------------------------------*/ + + pdu = (TP_FHDR_CX *) enc_buf; + + /* compute actual header length (do not count the hdr_len byte) */ + if (tpdu_cx->preferred_class == 0) + pdu->hdr_len = + (ST_UCHAR) (TP_FHDR_CX_LEN - sizeof(pdu->hdr_len)+ /* fixed part of header */ + TP_PAR_FIX_LEN + tpdu_cx->loc_tsap [0] + /* local TSAP parameter */ + TP_PAR_FIX_LEN + tpdu_cx->rem_tsap [0]); /* remote TSAP parameter*/ + else + pdu->hdr_len = + (ST_UCHAR) (TP_FHDR_CX_LEN - sizeof(pdu->hdr_len)+ /* fixed part of header */ + TP_PAR_FIX_LEN + tpdu_cx->loc_tsap [0] + /* local TSAP parameter */ + TP_PAR_FIX_LEN + tpdu_cx->rem_tsap [0] + /* remote TSAP parameter*/ + TP_PAR_LEN_VERSION + /* TP version parameter */ + TP_PAR_LEN_ADD_OPTIONS + /* additional opt param */ + TP_PAR_LEN_CHECKSUM); /* checksum parameter */ + /* NOTE: if TPDU size gets encoded hdr_len must be increased. */ + + /* set TPDU type */ + if (pdu_type == TP_PDU_TYPE_CR || pdu_type == TP_PDU_TYPE_CC) + pdu->type_cdt = pdu_type; + else + { + TP_LOG_ERR1 ("TP-ERROR: Encode CR or CC failed (invalid pdu_type %u passed to func)", + pdu_type); + TP4_EXCEPT (); + return (enc_len); /* valid types are CR and CC */ + } + + /* set CDT, if specified CDT is greater then max default to max */ + if (tpdu_cx->cdt <= TP_MAX_CDT) + pdu->type_cdt |= tpdu_cx->cdt; + else + pdu->type_cdt |= TP_MAX_CDT; + + /* copy to dest ref remote connection reference */ + if (pdu_type == TP_PDU_TYPE_CR) + pdu->dest_ref [0] = pdu->dest_ref [1] = 0; /* always 0 */ + else + memcpy (pdu->dest_ref, (ST_UCHAR *) &tpdu_cx->rem_ref, sizeof (pdu->dest_ref)); + + /* copy to src ref local connection reference */ + memcpy (pdu->src_ref, (ST_UCHAR *) &tpdu_cx->loc_ref, sizeof (pdu->src_ref)); + + if (tpdu_cx->preferred_class == 4) + pdu->class_opt = TP_CLASS_4_NORMAL; /* set the TP class */ + else if (tpdu_cx->preferred_class == 0) + pdu->class_opt = TP_CLASS_0; /* set the TP class */ + else + { + /* only class 4 (normal format) implemented */ + TP_LOG_ERR1 ("TP-ERROR: Encode CR or CC failed (not implemented class %u)", + tpdu_cx->preferred_class); + TP4_EXCEPT (); + return (enc_len); + } + + idx = TP_FHDR_CX_LEN; + + /*------------------------------------*/ + /* encode calling TSAP parameter */ + /*------------------------------------*/ + + param = (TP_PAR *) &enc_buf [idx]; + + param->code = TP_PAR_CODE_TSAP_CALLING; /* parameter code */ + if (pdu_type == TP_PDU_TYPE_CR) + { + /* Copy len and local TSAP to enc_buf */ + memcpy (¶m->len, tpdu_cx->loc_tsap, 1 + tpdu_cx->loc_tsap [0]); + idx += (ST_UINT16) (TP_PAR_FIX_LEN + tpdu_cx->loc_tsap [0]); + } + else + { + /* for CC copy len and remote TSAP to enc_buf */ + memcpy (¶m->len, tpdu_cx->rem_tsap, 1 + tpdu_cx->rem_tsap [0]); + idx += (ST_UINT16) (TP_PAR_FIX_LEN + tpdu_cx->rem_tsap [0]); + } + + /*------------------------------------*/ + /* encode called TSAP parameter */ + /*------------------------------------*/ + + param = (TP_PAR *) &enc_buf [idx]; + + param->code = TP_PAR_CODE_TSAP_CALLED; /* parameter code */ + if (pdu_type == TP_PDU_TYPE_CR) + { + /* Copy len and remote TSAP to enc_buf */ + memcpy (¶m->len, tpdu_cx->rem_tsap, 1 + tpdu_cx->rem_tsap [0]); + idx += (ST_UINT16) (TP_PAR_FIX_LEN + tpdu_cx->rem_tsap [0]); + } + else + { + /* for CC copy len and local TSAP to enc_buf */ + memcpy (¶m->len, tpdu_cx->loc_tsap, 1 + tpdu_cx->loc_tsap [0]); + idx += (ST_UINT16) (TP_PAR_FIX_LEN + tpdu_cx->loc_tsap [0]); + } + + /*------------------------------------*/ + /* encode TPDU size parameter */ + /*------------------------------------*/ + + /* Can't encode 65531. If not encoded, other side defaults to 65531. */ + if (tpdu_cx->max_tpdu_len_enc != TP_PDU_MAX_SIZE_65531) + { + pdu->hdr_len += TP_PAR_LEN_TPDU_SIZE; /* Adjust "hdr_len" */ + + param = (TP_PAR *) &enc_buf [idx]; + + param->code = TP_PAR_CODE_TPDU_SIZE; /* parameter code */ + param->len = 1; /* parameter len */ + + if (tpdu_cx->max_tpdu_len_enc < TP_PDU_MAX_SIZE_128 || + tpdu_cx->max_tpdu_len_enc > TP_PDU_MAX_SIZE_8192) + { + TP_LOG_ERR1 ("TP-ERROR: Encode CR or CC failed (invalid TPDU size %u)", + tpdu_cx->max_tpdu_len_enc); + TP4_EXCEPT (); + return (enc_len); + } + else + param->value[0] = tpdu_cx->max_tpdu_len_enc; + + idx += TP_PAR_LEN_TPDU_SIZE; + } + + /*------------------------------------*/ + /* encode TP version */ + /*------------------------------------*/ + + if (tpdu_cx->preferred_class != 0) + { + param = (TP_PAR *) &enc_buf [idx]; + + param->code = TP_PAR_CODE_VERSION; /* parameter code */ + param->len = 1; /* parameter len */ + param->value [0] = TP_VERSION; /* version number */ + + idx += TP_PAR_LEN_VERSION; + } + + /*------------------------------------*/ + /* encode TP additional options */ + /*------------------------------------*/ + + if (tpdu_cx->preferred_class != 0) + { + param = (TP_PAR *) &enc_buf [idx]; + + param->code = TP_PAR_CODE_ADD_OPTIONS;/* parameter code */ + param->len = 1; /* parameter len */ + param->value [0] = TP_OPT_CHECKSUM_USE | TP_OPT_EXPEDITED_NON_USE; + /* this param is 0 for our selected options */ + idx += TP_PAR_LEN_ADD_OPTIONS; + /* next param is checksum */ + } + + /*-----------------------------------------------------*/ + /* copy the user data (if any) after the last parameter*/ + /* (in our case the last param will be checksum param) */ + /*-----------------------------------------------------*/ + + enc_len = (ST_UINT16) (pdu->hdr_len+1); /* set the TPDU size and add to it */ + /* user data len (if any); add 1 for the*/ + /* len byte we didn't counted in hdr_len*/ + if (tpdu_cx->udata_len > 0) + { + if (tpdu_cx->preferred_class == 4) /* leave room for checksum */ + memcpy (&enc_buf [idx + TP_PAR_LEN_CHECKSUM], tpdu_cx->udata_buf, tpdu_cx->udata_len); + else + memcpy (&enc_buf [idx], tpdu_cx->udata_buf, tpdu_cx->udata_len); + + enc_len += tpdu_cx->udata_len; + } + + /*------------------------------------*/ + /* encode the checksum parameter */ + /*------------------------------------*/ + + if (tpdu_cx->preferred_class == 4) + { + tp_enc_par_checksum (enc_buf, enc_len, idx); + } + return (enc_len); +} + + +/************************************************************************/ +/* tp_encode_dr */ +/*----------------------------------------------------------------------*/ +/* This function is used to encode a DR TPDU. */ +/* */ +/* Parameters: */ +/* ST_UCHAR *enc_buf Pointer where to encode the DR TPDU */ +/* TPDU_DR *tpdu_dr Pointer to info struct for DR TPDU */ +/* */ +/* Return: */ +/* ST_UINT16 The actual length of encoded TPDU */ +/************************************************************************/ +ST_UINT16 tp_encode_dr (ST_UCHAR *enc_buf, TPDU_DR *tpdu_dr) +{ +ST_UINT16 enc_len; /* The actual length of encoded TPDU */ +TP_FHDR_DR *pdu; + + enc_len = TP_MAX_LEN_DR; + + /*------------------------------------*/ + /* encode the TPDU header, fixed part */ + /*------------------------------------*/ + + pdu = (TP_FHDR_DR *) enc_buf; + + pdu->hdr_len = TP_MAX_LEN_DR - sizeof (pdu->hdr_len); + /* header length */ + /* don't count the hdr_len byte */ + pdu->type = TP_PDU_TYPE_DR; /* TPDU type */ + memcpy (pdu->dest_ref, (ST_UCHAR *) &tpdu_dr->rem_ref, sizeof (pdu->dest_ref)); + /* Remote connection reference */ + memcpy (pdu->src_ref, (ST_UCHAR *) &tpdu_dr->loc_ref, sizeof (pdu->src_ref)); + /* Local connection reference */ + pdu->reason = tpdu_dr->reason; /* reason for DR */ + + /*------------------------------------*/ + /* encode the checksum parameter */ + /*------------------------------------*/ + + tp_enc_par_checksum (enc_buf, /* buf on which checksum is computed */ + enc_len, /* len of buffer (length of TPDU) */ + TP_FHDR_DR_LEN); /* position of checksum param in enc_buf*/ + + return (enc_len); +} + + +/************************************************************************/ +/* tp_encode_dc */ +/*----------------------------------------------------------------------*/ +/* This function is used to encode a DC TPDU. */ +/* */ +/* Parameters: */ +/* ST_UCHAR *enc_buf Pointer where to encode the DC TPDU */ +/* TPDU_DR *tpdu_dc Pointer to info struct for DC TPDU */ +/* */ +/* Return: */ +/* ST_UINT16 The actual length of encoded TPDU */ +/************************************************************************/ +ST_UINT16 tp_encode_dc (ST_UCHAR *enc_buf, TPDU_DC *tpdu_dc) +{ +ST_UINT16 enc_len; /* The actual length of encoded TPDU */ +TP_FHDR_DC *pdu; + + enc_len = TP_MAX_LEN_DC; + + /*------------------------------------*/ + /* encode the TPDU header, fixed part */ + /*------------------------------------*/ + + pdu = (TP_FHDR_DC *) enc_buf; + + pdu->hdr_len = TP_MAX_LEN_DC - sizeof (pdu->hdr_len); + /* header length */ + /* don't count the hdr_len byte */ + pdu->type = TP_PDU_TYPE_DC; /* TPDU type */ + memcpy (pdu->dest_ref, (ST_UCHAR *) &tpdu_dc->rem_ref, sizeof (pdu->dest_ref)); + /* Remote connection reference */ + memcpy (pdu->src_ref, (ST_UCHAR *) &tpdu_dc->loc_ref, sizeof (pdu->src_ref)); + /* Local connection reference */ + + /*------------------------------------*/ + /* encode the checksum parameter */ + /*------------------------------------*/ + + tp_enc_par_checksum (enc_buf, /* buf on which checksum is computed */ + enc_len, /* len of buffer (length of TPDU) */ + TP_FHDR_DC_LEN); /* position of checksum param in enc_buf*/ + return (enc_len); +} + + +/************************************************************************/ +/* tp_encode_dt */ +/*----------------------------------------------------------------------*/ +/* This function is used to encode a DT TPDU. */ +/* */ +/* Parameters: */ +/* ST_UCHAR *enc_buf Pointer to buffer where the TPDU should */ +/* be encoded. */ +/* TPDU_DT *tpdu_dt Pointer data info structure */ +/* */ +/* Return: */ +/* ST_UINT16 The actual length of encoded TPDU */ +/************************************************************************/ +ST_UINT16 tp_encode_dt (ST_UCHAR *enc_buf, TPDU_DT *tpdu_dt) +{ +ST_UINT16 enc_len; /* The actual length of encoded TPDU */ +TP_FHDR_DT *pdu; + + enc_len = (ST_UINT16) (TP_HEAD_LEN_DT + tpdu_dt->udata_len); + + /*------------------------------------*/ + /* encode the TPDU header, fixed part */ + /*------------------------------------*/ + + pdu = (TP_FHDR_DT *) enc_buf; + + pdu->hdr_len = TP_HEAD_LEN_DT - sizeof (pdu->hdr_len); + /* header length */ + /* don't count the hdr_len byte */ + pdu->type = TP_PDU_TYPE_DT; /* TPDU type */ + memcpy (pdu->dest_ref, (ST_UCHAR *) &tpdu_dt->dst_ref, sizeof (pdu->dest_ref)); + /* Remote connection reference */ + + /* set sequence number (make sure that bit 8 is not set) */ + pdu->eot_sn = (ST_UCHAR) (tpdu_dt->sn & TP_PDU_MASK_EOF); + if (tpdu_dt->eot) + pdu->eot_sn |= TP_PDU_EOF; /* set EOT flag */ + + /*------------------------------------*/ + /* copy the udata to enc_buf */ + /*------------------------------------*/ + + memcpy (&enc_buf [TP_HEAD_LEN_DT], tpdu_dt->udata_ptr, tpdu_dt->udata_len); + + /*------------------------------------*/ + /* encode the checksum parameter */ + /*------------------------------------*/ + + tp_enc_par_checksum (enc_buf, /* buf on which checksum is computed */ + enc_len, /* len of buffer (length of TPDU) */ + TP_FHDR_DT_LEN); /* position of checksum param in enc_buf*/ + return (enc_len); +} + +/************************************************************************/ +/* tp0_encode_dt */ +/* This function is used to encode a Class 0 DT TPDU. */ +/* Same as tp_encode_dt except dest_ref and Checksum NOT encoded. */ +/************************************************************************/ +ST_UINT16 tp0_encode_dt (ST_UCHAR *enc_buf, TPDU_DT *tpdu_dt) +{ +ST_UINT16 enc_len; /* The actual length of encoded TPDU */ +TP0_FHDR_DT *tp0_fhdr_dt; + + enc_len = (ST_UINT16) (TP0_HEAD_LEN_DT + tpdu_dt->udata_len); + + /*------------------------------------*/ + /* encode the TPDU header, fixed part */ + /*------------------------------------*/ + + tp0_fhdr_dt = (TP0_FHDR_DT *) enc_buf; + + tp0_fhdr_dt->hdr_len = TP0_HEAD_LEN_DT - 1; /* header length */ + /* don't count the hdr_len byte */ + tp0_fhdr_dt->type = TP_PDU_TYPE_DT; /* TPDU type */ + + /* set sequence number (make sure that bit 8 is not set) */ + tp0_fhdr_dt->eot_sn = (ST_UCHAR) 0; /* sequence number always 0 */ + if (tpdu_dt->eot) + tp0_fhdr_dt->eot_sn |= TP_PDU_EOF; /* set EOT flag */ + + /*------------------------------------*/ + /* copy the udata to enc_buf */ + /*------------------------------------*/ + + memcpy (&enc_buf [TP0_HEAD_LEN_DT], tpdu_dt->udata_ptr, tpdu_dt->udata_len); + return (enc_len); +} + +/************************************************************************/ +/* tp_encode_ak */ +/*----------------------------------------------------------------------*/ +/* This function is used to encode an AK TPDU. */ +/* */ +/* Parameters: */ +/* ST_UCHAR *enc_buf Pointer to buffer where the TPDU should */ +/* be encoded. */ +/* TPDU_AK *tpdu_ak Pointer to AK info struct */ +/* */ +/* Return: */ +/* ST_UINT16 The actual length of encoded TPDU */ +/************************************************************************/ +ST_UINT16 tp_encode_ak (ST_UCHAR *enc_buf, TPDU_AK *tpdu_ak) +{ +ST_UINT16 enc_len; /* The actual length of encoded TPDU */ +TP_FHDR_AK *pdu; + + enc_len = TP_MAX_LEN_AK; + + /*------------------------------------*/ + /* encode the TPDU header, fixed part */ + /*------------------------------------*/ + + pdu = (TP_FHDR_AK *) enc_buf; + + pdu->hdr_len = TP_MAX_LEN_AK - sizeof (pdu->hdr_len); + /* header length */ + /* don't count the hdr_len byte */ + pdu->type_cdt = TP_PDU_TYPE_AK; /* TPDU type */ + + /* encode the CDT (from cfg struct) */ + if (tpdu_ak->cdt <= TP_MAX_CDT) + pdu->type_cdt |= tpdu_ak->cdt; + else + pdu->type_cdt |= TP_MAX_CDT; + memcpy (pdu->dest_ref, (ST_UCHAR *) &tpdu_ak->dst_ref, sizeof (pdu->dest_ref)); + /* Remote connection reference */ + pdu->sn = tpdu_ak->sn; /* set next expected seq number */ + + /*------------------------------------*/ + /* encode the checksum parameter */ + /*------------------------------------*/ + + tp_enc_par_checksum (enc_buf, /* buf on which checksum is computed */ + enc_len, /* len of buffer (length of TPDU) */ + TP_FHDR_AK_LEN); /* position of checksum param in enc_buf*/ + return (enc_len); +} + + +/*======================================================================*/ +/* LOCAL FUNCTIONS for ENCODING */ +/*======================================================================*/ + + +/************************************************************************/ +/* tp_enc_par_checksum */ +/*----------------------------------------------------------------------*/ +/* This function is used to encode the checksum parameter in TPDU. */ +/* */ +/* Parameters: */ +/* ST_UCHAR *buf Ptr to encoding buffer on which checksum*/ +/* will be computed. */ +/* ST_UINT16 buf_len Length of the buffer (TPDU). */ +/* ST_UINT16 par_pos Position of checksum parameter in buf. */ +/* */ +/* Return: */ +/* ST_VOID none */ +/************************************************************************/ +static ST_VOID tp_enc_par_checksum (ST_UCHAR *buf, ST_UINT16 buf_len, ST_UINT16 par_pos) +{ +TP_PAR *param; + + param = (TP_PAR *) &buf [par_pos]; + + param->code = TP_PAR_CODE_CHECKSUM; /* parameter code */ + param->len = 2; /* Parameter length */ + + /* compute the checksum of the entire TPDU, the position of the */ + /* checksum first byte in the buf is computed as the difference */ + /* between pointers */ + + checksum_insert (buf, buf_len, (ST_UINT16) (param->value - buf)); +} diff --git a/mmslib/ositcps/tp4port.c b/mmslib/ositcps/tp4port.c new file mode 100644 index 0000000..6c6f50a --- /dev/null +++ b/mmslib/ositcps/tp4port.c @@ -0,0 +1,100 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2003 All Rights Reserved */ +/* */ +/* MODULE NAME : tp4port.c */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* Functions for porting to new operating systems. */ +/* The purpose of these functions is to cause "tp4_timer_tick" */ +/* to be called on 1 second intervals. These functions are */ +/* appropriate for MS-DOS or any other single tasking OS. */ +/* They may be replaced by any Operating System appropriate code */ +/* which causes the same result. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* tp4_init_timer () */ +/* tp4_check_timer () */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 12/19/03 JRB 04 Use sGetMsTime instead of "time" function to */ +/* avoid problems when system time changed. */ +/* 09/11/00 JRB 03 Make sure tp4_check_timer called at least */ +/* once a second. If NOT, write msg to log. */ +/* 08/13/98 JRB 02 Lint cleanup. */ +/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ +/* 07/17/96 JRB 01 Created */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "tp4api.h" /* User definitions for tp4 */ +#include "tp4_log.h" + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +static ST_DOUBLE oldtime; /* milliseconds */ +static ST_DOUBLE newtime; /* milliseconds */ + +/************************************************************************/ +/* tp4_init_timer */ +/************************************************************************/ +ST_VOID tp4_init_timer (ST_VOID) + { + oldtime = sGetMsTime (); + } + +/************************************************************************/ +/* tp4_check_timer */ +/************************************************************************/ +ST_VOID tp4_check_timer (ST_VOID) + { +#ifdef DEBUG_SISCO +static ST_BOOLEAN time_problem; /* Timing problem detected. */ +#endif + + newtime = sGetMsTime (); + +#ifdef DEBUG_SISCO /* Don't check for problem if can't log it. */ + /* Check time since last call. */ + /* This function should be called at least every second, so time diff */ + /* should be < 1000 ms. If difference is > 3000 ms, service loop may */ + /* be too slow. */ + /* //renxiaobao ͨѶ³¬Ê± +//if (newtime - oldtime > 3000.0) +*/ if (newtime - oldtime > 10000.0) + { + TP_LOG_ERR1 ("WARNING: stack not serviced for %.3f seconds.", (newtime-oldtime)/1000.0); + if (!time_problem) + { + /* Log this message only the first time it happens. */ + TP_LOGC_ERR0 ("MAY CAUSE UNEXPECTED TIMEOUTS, DISCONNECTS, ABORTS."); + time_problem = SD_TRUE; + } + } +#endif + + /* Increment "oldtime" by 1000 ms increments as much as possible */ + /* without exceeding "newtime". */ + /* Call "tp4_timer_tick" once for each increment. */ + /*renxiaobao ͨѶ³¬Ê±*/ + while (oldtime + 5000.0 < newtime) + { + tp4_timer_tick (); /* Call function to process timer tick. */ + oldtime += 5000.0; + } +/* //while (oldtime + 1000.0 < newtime) + //{ +// tp4_timer_tick (); Call function to process timer tick. + // oldtime += 1000.0; + //} +*/ +} + diff --git a/mmslib/ositcps/tpx_dec.c b/mmslib/ositcps/tpx_dec.c new file mode 100644 index 0000000..1709104 --- /dev/null +++ b/mmslib/ositcps/tpx_dec.c @@ -0,0 +1,1053 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1996-2008, All Rights Reserved. */ +/* */ +/* PROPRIETARY AND CONFIDENTIAL */ +/* */ +/* MODULE NAME : tpx_dec.c */ +/* PRODUCT(S) : Lean-T Stack */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module implements the decoding of the TPDUs. */ +/* */ +/* For information see the: */ +/* ISO 8073 "Information processing systems - Open Systems */ +/* Interconnections - Connection oriented transport protocol */ +/* specification. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* tp_decode_nsdu */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/23/08 JRB 11 Add casts to fix warnings. */ +/* 10/22/08 JRB 10 Add many length checks & return immediately */ +/* on any error. */ +/* Allow any class in CR, CC (caller checks it).*/ +/* Chg decode of DC, DT variable part like others*/ +/* Chg tp_decode_er to really decode ER TPDU. */ +/* Delete tp_decode_rj (not used in TP0 or TP4) */ +/* Fix byte order in logging of dst_ref, src_ref*/ +/* 11/01/07 EJV 09 Chg TSAP to TSEL in slogs. */ +/* tp_log_tsdu: added mutex. */ +/* 08/29/00 JRB 08 Don't return error if checksum NOT received */ +/* in DR or DC (maybe not negotiated yet). */ +/* 04/25/00 JRB 07 Lint cleanup. */ +/* 06/08/99 JRB 06 Chg src_ref, dst_ref logs to HEX. */ +/* 08/13/98 JRB 05 Lint cleanup. */ +/* 01/16/98 JRB 04 Chg unrecognixed param logs to "IND" logs. */ +/* 12/04/97 JRB 03 Clarify casts. Log unrecognized params. */ +/* 07/31/97 JRB 02 tp_decode_cx: pass default max_tpdu_len_enc */ +/* as arg because TP0/RFC1006 and TP4 need */ +/* different defaults. */ +/* 07/31/97 JRB 01 Created. Moved all tp_decode_* functions */ +/* from tp4_dec.c to here and changed arguments */ +/* so TP0 can use them too. */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "checksum.h" +#include "tp4.h" +#include "tp4_encd.h" +#include "tp4_log.h" + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/* local functions prototypes */ + +static ST_BOOLEAN tp_checksum_verified (ST_UCHAR *buf, ST_UINT16 buf_len, ST_UINT16 par_pos); + +/************************************************************************/ +/* get_hdr_len */ +/* Get the total length of the TPDU header. */ +/************************************************************************/ +static ST_UINT16 get_hdr_len (ST_UCHAR *pdu_ptr, ST_UINT16 pdu_len, ST_UINT16 min_len) + { +ST_UINT16 hdr_len; + if (pdu_len < min_len) + return (0); /* error */ + /* First byte is always header len but doesn't include itself, so add 1.*/ + hdr_len = (ST_UINT16) pdu_ptr[0] + 1; + if (hdr_len < min_len || hdr_len > pdu_len) + return (0); /* error */ + return (hdr_len); + } +/************************************************************************/ +/* get_next_param */ +/* Must have at least 2 bytes to get param len. If 2 bytes available, */ +/* get param len (2nd byte) and make sure it doesn't go past end of */ +/* header. */ +/* WARNING: Assumes (len_proc < hdr_len). Caller must check. */ +/************************************************************************/ +static TP_PAR *get_next_param (ST_UCHAR *pdu_ptr, + ST_UINT16 len_proc, /* num bytes already processed */ + ST_UINT16 hdr_len) /* num bytes in header */ + { +ST_UCHAR *cur_ptr; +ST_UINT16 len_left; /* num bytes remaining in header */ + + /* len_proc < hdr_len, so this calc can't be messed up by underflow */ + len_left = hdr_len - len_proc; + cur_ptr = pdu_ptr + len_proc; + if (len_left < 2 || + (ST_UINT16) cur_ptr[1] + 2 > len_left) /* cur_ptr[1]=param len*/ + return (NULL); + return ((TP_PAR *) cur_ptr); + } + +/************************************************************************/ +/* tp_decode_cx */ +/*----------------------------------------------------------------------*/ +/* Function used to decode a received CR or CC TPDU. Because n_unitdata */ +/* may contain multiple TPDUs, the offset parameter will tell us where */ +/* the CR or CC TPDU starts in the data_buf (n_unitdata). */ +/* */ +/* NOTE: Default value of "max_tpdu_len_enc" is passed as arg because */ +/* TP4 and TP0/RFC1006 need different defaults. */ +/* */ +/* Parameters: */ +/* TPDU_CX *tpdu_cx_rx Struct to fill in with decoded info. */ +/* ST_UCHAR *pdu_ptr Pointer to TPDU. */ +/* ST_UINT16 pdu_len Len of TPDU. */ +/* ST_UCHAR pdu_type TP_PDU_TYPE_CR or TP_PDU_TYPE_CC */ +/* ST_UCHAR max_tpdu_len_enc Binary encoded Max TPDU len */ +/* */ +/* Return: */ +/* ST_UINT16 Length of CR or CC TPDU. */ +/* 0 if decoding failed */ +/* NOTE: many ways to fail so return 0 IMMEDIATELY after any error. */ +/************************************************************************/ +ST_UINT16 tp_decode_cx (TPDU_CX *tpdu_cx_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len, ST_UCHAR pdu_type, ST_UCHAR def_max_tpdu_len_enc) +{ +TP_FHDR_CX *pdu; +ST_UINT16 len_proc; /* length of CR or CC TPDU processed */ +TP_PAR *param; +ST_BOOLEAN checksum_present; +ST_UINT16 hdr_len; + + hdr_len = get_hdr_len (pdu_ptr, pdu_len, TP_FHDR_CX_LEN); + if (hdr_len == 0) + { + TP_LOG_ERR0 ("TPDU-CR.ind or CC.ind invalid header len. TPDU Ignored."); + return (0); + } + + checksum_present = SD_FALSE; /* it is error if checksum is not */ + /* present in CR or TPDU */ + + /* make sure the struct is cleared */ + memset (tpdu_cx_rx, 0, sizeof (TPDU_CX)); + + pdu = (TP_FHDR_CX *) pdu_ptr; + + /* everything in data_buf starting from offset should be the CR or CC */ + + /* Set TPDU size to default in case not encoded. */ + tpdu_cx_rx->max_tpdu_len_enc = def_max_tpdu_len_enc; + + /*----------------------------------------------------*/ + /* Process the fixed part of CR or CC TPDU header */ + /*----------------------------------------------------*/ + + tpdu_cx_rx->cdt = (ST_UCHAR) (pdu->type_cdt & TP_PDU_MASK_TYPE); + /* remote CDT */ + tpdu_cx_rx->loc_ref = *((ST_UINT16 *) pdu->dest_ref); /* local conn reference */ + tpdu_cx_rx->rem_ref = *((ST_UINT16 *) pdu->src_ref); /* remote conn reference*/ + + /* get the preferred class option */ + /* Class is in high nibble of class_opt. */ + tpdu_cx_rx->preferred_class = pdu->class_opt >> 4; + + /*----------------------------------------------------*/ + /* Process the variable part of CR or CC TPDU header. */ + /* Extract parameters in which we are interested into */ + /* the tpdu_cx_rx. */ + /* The ISO 8073 states that is if a parameter is not */ + /* present in CR or CC and the standard defines a */ + /* default value for it, then the default value should*/ + /* be used (equivalent to present parameter). */ + /* Following parameters have default value: */ + /* TPDU size: 128 bytes */ + /* TP version 0x01 */ + /* Additional options 0x01 (checksum used and */ + /* support expedited */ + /* data transfer) */ + /*----------------------------------------------------*/ + + len_proc = TP_FHDR_CX_LEN; /* we processed already the fixed part */ + + while (len_proc < hdr_len) + { + if ((param = get_next_param (pdu_ptr, len_proc, hdr_len)) == NULL) + { + TP_LOG_ERR0 ("TPDU-CR.ind or CC.ind invalid param len. TPDU Ignored."); + return (0); + } + + switch (param->code) + { + case TP_PAR_CODE_TSAP_CALLING: /* copy the len & remote TSAP */ + if (param->len <= MAX_TSEL_LEN) + { + if (pdu_type == TP_PDU_TYPE_CR) + /* CR TPDU, we are called (remote TSAP in this field) */ + memcpy (tpdu_cx_rx->rem_tsap, (ST_CHAR *) ¶m->len, 1 + param->len); + else + /* CC TPDU, we are calling (local TSAP in this field) */ + memcpy (tpdu_cx_rx->loc_tsap, (ST_CHAR *) ¶m->len, 1 + param->len); + } + else + { + TP_LOG_ERR1 ("TP-ERROR: decode CR or CC TPDU failed (TSEL length %u not supported)", + (unsigned) param->len); + return (0); /* bad TSAP length, ignore this TPDU */ + } + break; + + case TP_PAR_CODE_TSAP_CALLED: + /* copy the length and local TSAP */ + if (param->len <= MAX_TSEL_LEN) + { + if (pdu_type == TP_PDU_TYPE_CR) + /* CR TPDU, we are called (local TSAP in this field) */ + memcpy (tpdu_cx_rx->loc_tsap, (ST_CHAR *) ¶m->len, 1 + param->len); + else + /* CC TPDU, we are calling (remote TSAP in this field) */ + memcpy (tpdu_cx_rx->rem_tsap, (ST_CHAR *) ¶m->len, 1 + param->len); + } + else + { + TP_LOG_ERR1 ("TP-ERROR: decode CR or CC TPDU failed (TSEL length %u not supported)", + (unsigned) param->len); + return (0); /* bad TSAP length, ignore this TPDU */ + } + break; + + case TP_PAR_CODE_TPDU_SIZE: + if (param->len != 1) + { + TP_LOG_ERR0 ("TPDU-CR.ind or CC.ind invalid param len. TPDU Ignored."); + return (0); + } + if (param->value [0] < TP_PDU_MAX_SIZE_128 || + param->value [0] > TP_PDU_MAX_SIZE_8192) + { + TP_LOG_ERR1 ("TP-ERROR: decode CR TPDU failed (invalid TPDU size %u)", + (unsigned) param->value[0]); + return (0); /* invalid TPDU size, ignore this TPDU */ + } + else + tpdu_cx_rx->max_tpdu_len_enc = param->value [0]; + break; + + case TP_PAR_CODE_VERSION: + if (param->len != 1) + { + TP_LOG_ERR0 ("TPDU-CR.ind or CC.ind invalid param len. TPDU Ignored."); + return (0); + } + if (param->value [0] != TP_VERSION) + { + TP_LOG_ERR1 ("TP-ERROR: decode CR TPDU failed (invalid TPDU version %u)", + (unsigned) param->value[0]); + return (0); /* invalid TP version, ignore this TPDU */ + } + break; + + case TP_PAR_CODE_ADD_OPTIONS: + /* Following proposed protocol parameters can be in */ + /* additional options (for class 4): */ + /* non-use of checksum, use/non-use of expedited data. */ + /* We will reject non-use of checksum and we will not */ + /* support expedited data service (see encoding of CC). */ + /* There is no processing needed of this parameter. */ + break; + + case TP_PAR_CODE_CHECKSUM: + checksum_present = SD_TRUE; + if (!tp_checksum_verified (pdu_ptr, pdu_len, len_proc)) + return (0); /* bad checksum, ignore this TPDU */ + break; + + default: + /* ignore this parameter */ + TP_LOG_IND1 ("TP-WARNING: decode CR or CC TPDU: Unrecognized param code (0x%X) ignored", + param->code); + break; + } /* end switch */ + + /* add len of currently processed parameter to len_proc */ + len_proc += (ST_UINT16) (TP_PAR_FIX_LEN + param->len); + } /* end while */ + + if (checksum_present==SD_FALSE && tpdu_cx_rx->preferred_class==4) + { + TP_LOG_ERR0 ("TP-ERROR: decode CR TPDU failed (checksum parameter not present)"); + return (0); + } + + /*----------------------------------------------------*/ + /* If decoding of header successful copy user data */ + /* and call proceess function. */ + /*----------------------------------------------------*/ + + /* check if user data are present */ + + if (hdr_len < pdu_len) + { + ST_UINT16 udata_len = pdu_len - hdr_len; + + if ( udata_len <= TP_MAX_CONN_UDATA) + { + memcpy (tpdu_cx_rx->udata_buf, &pdu_ptr [hdr_len], udata_len); + tpdu_cx_rx->udata_len = udata_len; + } + else + TP_LOG_ERR1 ("TP-ERROR: invalid user data length (%u) in received CR or CC TPDU", + udata_len); + } + + return (pdu_len); +} + + +/************************************************************************/ +/* tp_decode_dr */ +/*----------------------------------------------------------------------*/ +/* Function used to decode a received DR TPDU. Because the n_unitdata */ +/* may contain multiple TPDUs, the offset parameter will tell us where */ +/* the DR TPDU starts in the data_buf (n_unitdata). */ +/* This function does NOT return a decode error if the checksum is */ +/* not present. Use of checksum may not have been negotiated yet. */ +/* */ +/* Parameters: */ +/* TPDU_DR *tpdu_dr_rx Struct to fill in with decoded info. */ +/* ST_UCHAR *pdu_ptr Pointer to TPDU. */ +/* ST_UINT16 pdu_len Len of TPDU. */ +/* */ +/* Return: */ +/* ST_UINT16 Length of DR TPDU. */ +/* 0 if decoding failed */ +/* NOTE: many ways to fail so return 0 IMMEDIATELY after any error. */ +/************************************************************************/ +ST_UINT16 tp_decode_dr (TPDU_DR *tpdu_dr_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len) +{ +TP_FHDR_DR *pdu; +ST_UINT16 len_proc; /* length of DR TPDU already processed */ +TP_PAR *param; +ST_UINT16 hdr_len; + + hdr_len = get_hdr_len (pdu_ptr, pdu_len, TP_FHDR_DR_LEN); + if (hdr_len == 0) + { + TP_LOG_ERR0 ("TPDU-DR.ind invalid header len. TPDU Ignored."); + return (0); + } + + /* make sure the struct is cleared */ + memset (tpdu_dr_rx, 0, sizeof (TPDU_DR)); + + pdu = (TP_FHDR_DR *) pdu_ptr; + + /* everything in data_buf starting from offset should be the DR TPDU */ + + /*--------------------------------------------*/ + /* Process the fixed part of DR TPDU header */ + /*--------------------------------------------*/ + + tpdu_dr_rx->loc_ref = *((ST_UINT16 *) pdu->dest_ref); /* local conn reference */ + tpdu_dr_rx->rem_ref = *((ST_UINT16 *) pdu->src_ref); /* remote conn reference*/ + tpdu_dr_rx->reason = pdu->reason; /* reson for disconnect */ + + /*----------------------------------------------------*/ + /* Process the variable part of DR TPDU header. */ + /*----------------------------------------------------*/ + + len_proc = TP_FHDR_DR_LEN; /* we processed already the fixed part */ + + while (len_proc < hdr_len) + { + if ((param = get_next_param (pdu_ptr, len_proc, hdr_len)) == NULL) + { + TP_LOG_ERR0 ("TPDU-DR.ind invalid param len. TPDU Ignored."); + return (0); + } + + switch (param->code) + { + case TP_PAR_CODE_CHECKSUM: + if (!tp_checksum_verified (pdu_ptr, pdu_len, len_proc)) + return (0); /* bad checksum, ignore this TPDU */ + break; + + default: + /* ignore other parameters */ + TP_LOG_IND1 ("TP-WARNING: decode DR TPDU: Unrecognized param code (0x%X) ignored", + param->code); + break; + } /* end switch */ + + /* add len of currently processed parameter to len_proc */ + len_proc += (ST_UINT16) (TP_PAR_FIX_LEN + param->len); + } /* end while */ + + return (pdu_len); +} + + +/************************************************************************/ +/* tp_decode_dc */ +/*----------------------------------------------------------------------*/ +/* Function used to decode a received DC TPDU. */ +/* This function does NOT return a decode error if the checksum is */ +/* not present. Use of checksum may not have been negotiated yet. */ +/* */ +/* Parameters: */ +/* TPDU_DC *tpdu_dc_rx Struct to fill in with decoded info. */ +/* ST_UCHAR *pdu_ptr Pointer to TPDU. */ +/* */ +/* Return: */ +/* ST_UINT16 Length of DC TPDU. */ +/* 0 if decoding failed */ +/* NOTE: many ways to fail so return 0 IMMEDIATELY after any error. */ +/************************************************************************/ +ST_UINT16 tp_decode_dc (TPDU_DC *tpdu_dc_rx, + ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len) +{ +TP_FHDR_DC *pdu; +TP_PAR *param; +ST_UINT16 len_proc; /* length of TPDU already processed */ +ST_UINT16 hdr_len; + + hdr_len = get_hdr_len (pdu_ptr, pdu_len, TP_FHDR_DC_LEN); + if (hdr_len == 0) + { + TP_LOG_ERR0 ("TPDU-DC.ind invalid header len. TPDU Ignored."); + return (0); + } + + /* make sure the struct is cleared */ + memset (tpdu_dc_rx, 0, sizeof (TPDU_DC)); + + pdu = (TP_FHDR_DC *) pdu_ptr; + + /*--------------------------------------------*/ + /* Process the fixed part of DC TPDU header */ + /*--------------------------------------------*/ + + tpdu_dc_rx->loc_ref = *((ST_UINT16 *) pdu->dest_ref); /* local conn reference */ + tpdu_dc_rx->rem_ref = *((ST_UINT16 *) pdu->src_ref); /* remote conn reference*/ + + /*----------------------------------------------------*/ + /* Process the variable part of DC TPDU header. */ + /*----------------------------------------------------*/ + + len_proc = TP_FHDR_DC_LEN; /* we processed already the fixed part */ + + while (len_proc < hdr_len) + { + if ((param = get_next_param (pdu_ptr, len_proc, hdr_len)) == NULL) + { + TP_LOG_ERR0 ("TPDU-DC.ind invalid param len. TPDU Ignored."); + return (0); + } + + switch (param->code) + { + case TP_PAR_CODE_CHECKSUM: + if (!tp_checksum_verified (pdu_ptr, pdu_len, len_proc)) + return (0); /* bad checksum, ignore this TPDU */ + break; + + default: + /* Other parameters not allowed. */ + TP_LOG_ERR1 ("TPDU-DC.ind unrecognized param code (0x%X). Protocol error.", + param->code); + return (0); + break; + } /* end switch */ + + /* add len of currently processed parameter to len_proc */ + len_proc += (ST_UINT16) (TP_PAR_FIX_LEN + param->len); + } /* end while */ + + return (pdu_len); +} + + +/************************************************************************/ +/* tp_decode_dt */ +/*----------------------------------------------------------------------*/ +/* Function used to decode a received DT TPDU. */ +/* */ +/* Parameters: */ +/* TPDU_DT *tpdu_dt_rx Struct to fill in with decoded info. */ +/* ST_UCHAR *pdu_ptr Pointer to TPDU. */ +/* ST_UINT16 pdu_len Len of TPDU. */ +/* */ +/* Return: */ +/* ST_UINT16 Length of DT TPDU. */ +/* 0 if decoding failed */ +/* NOTE: many ways to fail so return 0 IMMEDIATELY after any error. */ +/************************************************************************/ +ST_UINT16 tp_decode_dt (TPDU_DT *tpdu_dt_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len) +{ +TP_FHDR_DT *pdu; +ST_BOOLEAN checksum_present; +ST_UINT16 hdr_len; +ST_UINT16 len_proc; /* length of TPDU already processed */ +TP_PAR *param; + + hdr_len = get_hdr_len (pdu_ptr, pdu_len, TP_FHDR_DT_LEN); + if (hdr_len == 0) + { + TP_LOG_ERR0 ("TPDU-DT.ind invalid header len. TPDU Ignored."); + return (0); + } + + checksum_present = SD_FALSE; /* it is error if checksum is missing */ + + /* make sure the struct is cleared */ + memset (tpdu_dt_rx, 0, sizeof (TPDU_DT)); + + pdu = (TP_FHDR_DT *) pdu_ptr; + + /*--------------------------------------------*/ + /* Process the fixed part of DT TPDU header */ + /*--------------------------------------------*/ + + /* udata is everything after the header */ + tpdu_dt_rx->udata_ptr = (ST_CHAR *) pdu_ptr + hdr_len; + tpdu_dt_rx->udata_len = pdu_len - hdr_len; + + if (pdu->eot_sn & TP_PDU_MASK_SN) + tpdu_dt_rx->eot = SD_TRUE; /* set the EOF flag */ + else + tpdu_dt_rx->eot = SD_FALSE; + + tpdu_dt_rx->dst_ref = *((ST_UINT16 *) pdu->dest_ref); /* local conn reference */ + tpdu_dt_rx->sn = (ST_UCHAR) (pdu->eot_sn & TP_PDU_MASK_EOF); /* sn of received TPDU */ + + /*----------------------------------------------------*/ + /* Process the variable part of DT TPDU header. */ + /*----------------------------------------------------*/ + + len_proc = TP_FHDR_DT_LEN; /* we processed already the fixed part */ + + while (len_proc < hdr_len) + { + if ((param = get_next_param (pdu_ptr, len_proc, hdr_len)) == NULL) + { + TP_LOG_ERR0 ("TPDU-DT.ind invalid param len. TPDU Ignored."); + return (0); + } + switch (param->code) + { + /* Checksum is the only allowed parameter*/ + case TP_PAR_CODE_CHECKSUM: + checksum_present = SD_TRUE; + if (!tp_checksum_verified (pdu_ptr, pdu_len, len_proc)) + return (0); /* bad checksum, ignore this TPDU */ + break; + + default: + /* Other parameters not allowed. */ + TP_LOG_ERR1 ("TPDU-DT.ind unrecognized param code (0x%X). Protocol error.", + param->code); + return (0); + break; + } /* end switch */ + + /* add len of currently processed parameter to len_proc */ + len_proc += (ST_UINT16) (TP_PAR_FIX_LEN + param->len); + } /* end while */ + + if (!checksum_present) + { + TP_LOG_ERR0 ("TP-ERROR: decode DT TPDU failed (checksum parameter not present)"); + return (0); + } + + return (pdu_len); +} + + +/************************************************************************/ +/* tp0_decode_dt */ +/*----------------------------------------------------------------------*/ +/* This function is used to decode a Class 0 DT TPDU. */ +/* Same as tp_decode_dt except dest_ref and Checksum NOT encoded. */ +/* NOTE: many ways to fail so return 0 IMMEDIATELY after any error. */ +/************************************************************************/ +ST_UINT16 tp0_decode_dt (TPDU_DT *tpdu_dt_rx, ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len) +{ +TP0_FHDR_DT *tp0_fhdr_dt; +ST_UINT16 hdr_len; + + hdr_len = get_hdr_len (pdu_ptr, pdu_len, TP0_FHDR_DT_LEN); + if (hdr_len == 0) + { + TP_LOG_ERR0 ("TPDU-DT.ind invalid header len. TPDU Ignored."); + return (0); + } + if (hdr_len != TP0_FHDR_DT_LEN) + { + /* Variable part not allowed. */ + TP_LOG_ERR1 ("TPDU-DT.ind header len (%u) != 3. Protocol error.", + hdr_len); + return (0); + } + + /* make sure the struct is cleared */ + memset (tpdu_dt_rx, 0, sizeof (TPDU_DT)); + + tp0_fhdr_dt = (TP0_FHDR_DT *) pdu_ptr; + + /*--------------------------------------------*/ + /* Process the fixed part of DT TPDU header */ + /*--------------------------------------------*/ + + /* udata is everything after the header */ + tpdu_dt_rx->udata_ptr = (ST_CHAR *) pdu_ptr + hdr_len; + tpdu_dt_rx->udata_len = pdu_len - hdr_len; + + if (tp0_fhdr_dt->eot_sn & TP_PDU_MASK_SN) + tpdu_dt_rx->eot = SD_TRUE; /* set the EOF flag */ + else + tpdu_dt_rx->eot = SD_FALSE; + + tpdu_dt_rx->sn = (ST_UCHAR) (tp0_fhdr_dt->eot_sn & TP_PDU_MASK_EOF); /* sn of received TPDU */ + + return (pdu_len); +} + + +/************************************************************************/ +/* tp_decode_ak */ +/*----------------------------------------------------------------------*/ +/* Function used to decode a received AK TPDU. Because the n_unitdata */ +/* may contain multiple TPDUs, the offset parameter will tell us where */ +/* the AK TPDU starts in the data_buf (n_unitdata). */ +/* */ +/* Parameters: */ +/* TPDU_AK *tpdu_ak_rx Struct to fill in with decoded info. */ +/* ST_UCHAR *pdu_ptr Pointer to TPDU. */ +/* */ +/* Return: */ +/* ST_UINT16 Length of AK TPDU. */ +/* 0 if decoding failed */ +/* NOTE: many ways to fail so return 0 IMMEDIATELY after any error. */ +/************************************************************************/ +ST_UINT16 tp_decode_ak (TPDU_AK *tpdu_ak_rx, + ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len) +{ +TP_FHDR_AK *pdu; +ST_UINT16 len_proc; /* length of AK TPDU already processed */ +TP_PAR *param; +ST_BOOLEAN checksum_present; +ST_UINT16 hdr_len; + + hdr_len = get_hdr_len (pdu_ptr, pdu_len, TP_FHDR_AK_LEN); + if (hdr_len == 0) + { + TP_LOG_ERR0 ("TPDU-AK.ind invalid header len. TPDU Ignored."); + return (0); + } + + checksum_present = SD_FALSE; /* it is error if checksum is missing */ + + /* make sure the struct is cleared */ + memset (tpdu_ak_rx, 0, sizeof (TPDU_AK)); + + pdu = (TP_FHDR_AK *) pdu_ptr; + + /*--------------------------------------------*/ + /* Process the fixed part of AK TPDU header */ + /*--------------------------------------------*/ + + tpdu_ak_rx->dst_ref = *((ST_UINT16 *) pdu->dest_ref); /* local conn reference */ + tpdu_ak_rx->sn = (ST_UCHAR) (pdu->sn & TP_PDU_MASK_BIT8); /* next expected DT sn */ + tpdu_ak_rx->cdt = (ST_UCHAR) (pdu->type_cdt & TP_PDU_MASK_TYPE); /* remote CDT */ + + /*----------------------------------------------------*/ + /* Process the variable part of AK TPDU. */ + /*----------------------------------------------------*/ + + len_proc = TP_FHDR_AK_LEN; /* we processed already the fixed part */ + + while (len_proc < hdr_len) + { + if ((param = get_next_param (pdu_ptr, len_proc, hdr_len)) == NULL) + { + TP_LOG_ERR0 ("TPDU-AK.ind invalid param len. TPDU Ignored."); + return (0); + } + + switch (param->code) + { + case TP_PAR_CODE_CHECKSUM: + checksum_present = SD_TRUE; + if (!tp_checksum_verified (pdu_ptr, pdu_len, len_proc)) + return (0); /* bad checksum, ignore this TPDU */ + break; + + default: + /* ignore other parameters */ + TP_LOG_IND1 ("TP-WARNING: decode AK TPDU: Unrecognized param code (0x%X) ignored", + param->code); + break; + } /* end switch */ + + /* add len of currently processed parameter to len_proc */ + len_proc += (ST_UINT16) (TP_PAR_FIX_LEN + param->len); + } /* end while */ + + if (!checksum_present) + { + TP_LOG_ERR0 ("TP-ERROR: decode AK TPDU failed (checksum parameter not present)"); + return (0); + } + + /* NOTE: len_proc may be less than pdu_len if multiple TPDU in NSDU. */ + return (len_proc); +} + + +/************************************************************************/ +/* tp_decode_er */ +/*----------------------------------------------------------------------*/ +/* Function used to decode a received ER TPDU. Because the n_unitdata */ +/* may contain multiple TPDUs, the offset parameter will tell us where */ +/* the ER TPDU starts in the data_buf (n_unitdata). */ +/* */ +/* Parameters: */ +/* TPDU_ER *tpdu_er_rx Struct to fill in with decoded info. */ +/* ST_UCHAR *pdu_ptr Pointer to TPDU. */ +/* ST_UINT16 pdu_len Len of TPDU. */ +/* ST_INT tp_classs Transport class (must be 0 or 4). */ +/* */ +/* Return: */ +/* ST_UINT16 Length of ER TPDU. */ +/* 0 if decoding failed */ +/* NOTE: many ways to fail so return 0 IMMEDIATELY after any error. */ +/************************************************************************/ +ST_UINT16 tp_decode_er (TPDU_ER *tpdu_er_rx, + ST_UCHAR *pdu_ptr, + ST_UINT16 pdu_len, + ST_INT tp_class) /* must be 0 or 4 */ +{ +TP_FHDR_ER *pdu; +ST_UINT16 len_proc; /* length of TPDU already processed */ +TP_PAR *param; +ST_UINT16 hdr_len; +ST_BOOLEAN checksum_present; + + hdr_len = get_hdr_len (pdu_ptr, pdu_len, TP_FHDR_ER_LEN); + if (hdr_len == 0) + { + TP_LOG_ERR0 ("TPDU-ER.ind invalid header len. TPDU Ignored."); + return (0); + } + + /* If class 4 (tp_class=4), checksum must be present. */ + checksum_present = SD_FALSE; + + /* make sure the struct is cleared */ + memset (tpdu_er_rx, 0, sizeof (TPDU_ER)); + + pdu = (TP_FHDR_ER *) pdu_ptr; + + /*--------------------------------------------*/ + /* Process the fixed part of ER TPDU header */ + /*--------------------------------------------*/ + tpdu_er_rx->dst_ref = *((ST_UINT16 *) pdu->dest_ref); /* local conn reference */ + tpdu_er_rx->reject_cause = pdu->reason; + + /*----------------------------------------------------*/ + /* Process the variable part of ER TPDU header. */ + /*----------------------------------------------------*/ + + len_proc = TP_FHDR_ER_LEN; /* we processed already the fixed part */ + + while (len_proc < hdr_len) + { + if ((param = get_next_param (pdu_ptr, len_proc, hdr_len)) == NULL) + { + TP_LOG_ERR0 ("TPDU-ER.ind invalid param len. TPDU Ignored."); + return (0); + } + + switch (param->code) + { + case TP_PAR_CODE_ER_INVAL_TPDU: /* Invalid TPDU */ + /* Set ptr to Invalid TPDU part of message & set len. */ + tpdu_er_rx->invalid_tpdu_ptr = ¶m->value[0]; + tpdu_er_rx->invalid_tpdu_len = param->len; + break; + + case TP_PAR_CODE_CHECKSUM: + checksum_present = SD_TRUE; + if (!tp_checksum_verified (pdu_ptr, pdu_len, len_proc)) + return (0); /* bad checksum, ignore this TPDU */ + break; + + default: + /* Other parameters not allowed. */ + TP_LOG_ERR1 ("TPDU-ER.ind unrecognized param code (0x%X). Protocol error.", + param->code); + return (0); + break; + } /* end switch */ + + /* add len of currently processed parameter to len_proc */ + len_proc += (ST_UINT16) (TP_PAR_FIX_LEN + param->len); + } /* end while */ + + /* For Class 0, invalid_tpdu_ptr must be set during decode. */ + if (tpdu_er_rx->invalid_tpdu_ptr == NULL && tp_class == 0) + { + TP_LOG_ERR0 ("TPDU-ER.ind 'Invalid TPDU' not present for Class 0"); + return (0); + } + + /* For Class 4, checksum must be found during decode. */ + if (!checksum_present && tp_class == 4) + { + TP_LOG_ERR0 ("TPDU-ER.ind checksum not present for Class 4"); + return (0); + } + + /* NOTE: len_proc may be less than pdu_len if multiple TPDU in NSDU. */ + return (len_proc); +} + + +/************************************************************************/ +/* tp_checksum_verified */ +/*----------------------------------------------------------------------*/ +/* This function is used to decode and verify the checksum parameter in */ +/* TPDU. */ +/* */ +/* Parameters: */ +/* ST_UCHAR *buf Ptr to TPDU buffer */ +/* ST_UINT16 buf_len Length of the buffer (TPDU). */ +/* ST_UINT16 par_pos Position of checksum parameter in TPDU. */ +/* */ +/* Return: */ +/* ST_BOOLEAN SD_TRUE if checksum verified. */ +/* SD_FALSE otherwise */ +/************************************************************************/ +static ST_BOOLEAN tp_checksum_verified (ST_UCHAR *buf, ST_UINT16 buf_len, ST_UINT16 par_pos) +{ +ST_BOOLEAN verified; +TP_PAR *param; + + /* NOTE: len checked before calling, so we know param fits in TPDU, */ + /* but here we make sure param len == 2 before continuing. */ + + verified = SD_FALSE; + + param = (TP_PAR *) (&buf [par_pos]); /* point to start of param*/ + + if (param->code == TP_PAR_CODE_CHECKSUM) + { + if (param->len == 2) + { + /* compute the checksum of the entire TPDU, the position of the */ + /* checksum first byte in the buf is computed as the difference */ + /* between pointers */ + + verified = checksum_verified (buf, buf_len, + (ST_UINT16) (param->value - buf), SD_FALSE); + + if (!verified) + TP_LOG_ERR0 ("TP-ERROR: decode TPDU failed (verification of checksum failed)"); + } + else + TP_LOG_ERR1 ("TP-ERROR: decode TPDU failed (invalid length=%u for checksum parameter)", + param->len); + } + else + TP_LOG_ERR0 ("TP-ERROR: decode TPDU failed (checksum parameter missing)"); + + return (verified); +} + +#if defined(DEBUG_SISCO) +/************************************************************************/ +/* tp_log_tsdu */ +/*----------------------------------------------------------------------*/ +/* Function used to log Transport Service data unit. */ +/* */ +/* Parameters: */ +/* ST_VOID *tsdu Pointer to data unit struct */ +/* ST_UCHAR type TSDU type (TP_PDU_TYPE_CR, etc.) */ +/* ST_UCHAR mask logging mask: */ +/* TP_IND (indication) or TP_REQ (request) */ +/* */ +/* Return: */ +/* ST_VOID none */ +/* NOTE: all src_ref & dst_ref stored in network byte order. Converted */ +/* to "host byte order" using "ntohs" only in this function. */ +/************************************************************************/ +ST_VOID tp_log_tsdu (ST_VOID *tsdu, ST_UCHAR type, ST_UCHAR mask) +{ +char *buf; /* ptr to msg header (i.e. TPDU type) */ + /* set before passing to log function */ + + S_LOCK_UTIL_RESOURCES (); + switch (type) + { + case TP_PDU_TYPE_CR: + case TP_PDU_TYPE_CC: + { /*block*/ + TPDU_CX *tpdu = (TPDU_CX *) tsdu; + + if (mask == TP_IND) + { + if (type == TP_PDU_TYPE_CR) + buf = "TPDU-CR.ind:"; + else + buf = "TPDU-CC.ind:"; + + /* For IND, dst_ref is loc_ref */ + TP_LOG_RI6 (mask,"%s dst_ref=0x%04X src_ref=0x%04X max_len=%4u class=%u cdt=%2u", + buf, ntohs(tpdu->loc_ref), ntohs(tpdu->rem_ref), 1 << tpdu->max_tpdu_len_enc, + (unsigned) tpdu->preferred_class, (unsigned) tpdu->cdt); + } + else + { + if (type == TP_PDU_TYPE_CR) + buf = "TPDU-CR.req:"; + else + buf = "TPDU-CC.req:"; + + /* For REQ, dst_ref is rem_ref */ + TP_LOG_RI6 (mask,"%s dst_ref=0x%04X src_ref=0x%04X max_len=%4u class=%u cdt=%2u", + buf, ntohs(tpdu->rem_ref), ntohs(tpdu->loc_ref), 1 << tpdu->max_tpdu_len_enc, + (unsigned) tpdu->preferred_class, (unsigned) tpdu->cdt); + } + + TP_LOGC_RI0 (mask,"Local TSEL:"); + TP_LOGHC_RI (mask,(ST_UINT) tpdu->loc_tsap [0], &tpdu->loc_tsap [1]); + TP_LOGC_RI0 (mask,"Remote TSEL:"); + TP_LOGHC_RI (mask,(ST_UINT) tpdu->rem_tsap [0], &tpdu->rem_tsap [1]); + +#if 0 + TP_LOGC_RI0 (mask,"Remote MAC:"); + TP_LOGHC_RI (mask,(ST_UINT) CLNP_MAX_LEN_MAC, tpdu->rem_mac); + TP_LOGC_RI0 (mask,"Remote NSAP:"); + TP_LOGHC_RI (mask,(ST_UINT) tpdu->rem_nsap [0], &tpdu->rem_nsap [1]); +#endif + TP_LOGC_RI1 (mask,"User data length: %u", tpdu->udata_len); + if (tpdu->udata_len > 0) + TP_LOGHC_RI (mask,(ST_UINT) tpdu->udata_len, tpdu->udata_buf); + } + break; + + case TP_PDU_TYPE_DR: + case TP_PDU_TYPE_DC: + { /*block*/ + TPDU_DR *tpdu = (TPDU_DR *) tsdu; /* we use DR struct for both */ + + if (mask == TP_IND) + { + if (type == TP_PDU_TYPE_DR) + buf = "TPDU-DR.ind:"; + else + buf = "TPDU-DC.ind:"; + + /* For IND, dst_ref is loc_ref */ + TP_LOG_RI3 (mask,"%s dst_ref=0x%04X src_ref=0x%04X", + buf, ntohs(tpdu->loc_ref), ntohs(tpdu->rem_ref)); + } + else + { + if (type == TP_PDU_TYPE_DR) + buf = "TPDU-DR.req:"; + else + buf = "TPDU-DC.req:"; + + /* For REQ, dst_ref is rem_ref */ + TP_LOG_RI3 (mask,"%s dst_ref=0x%04X src_ref=0x%04X", + buf, ntohs(tpdu->rem_ref), ntohs(tpdu->loc_ref)); + } + + if (type == TP_PDU_TYPE_DR) + TP_LOGC_RI1 (mask,"Disconnect reason: 0x%2.2X", (unsigned) tpdu->reason); +#if 0 + TP_LOGC_RI0 (mask,"Remote MAC:"); + TP_LOGHC_RI (mask,(ST_UINT) CLNP_MAX_LEN_MAC, tpdu->rem_mac); + TP_LOGC_RI0 (mask,"Remote NSAP:"); + TP_LOGHC_RI (mask,(ST_UINT) tpdu->rem_nsap [0], &tpdu->rem_nsap [1]); +#endif + } + break; + + case TP_PDU_TYPE_DT: + { /*block*/ + TPDU_DT *tpdu = (TPDU_DT *) tsdu; + + if (mask == TP_IND) + buf = "TPDU-DT.ind:"; + else + buf = "TPDU-DT.req:"; + + TP_LOG_RI4 (mask,"%s dst_ref=0x%04X sn=%3u eot=%u", + buf, ntohs(tpdu->dst_ref), (unsigned) tpdu->sn, (unsigned) tpdu->eot); + +#if 0 + TP_LOGC_RI0 (mask,"Remote MAC:"); + TP_LOGHC_RI (mask,(ST_UINT) CLNP_MAX_LEN_MAC, tpdu->rem_mac); + TP_LOGC_RI0 (mask,"Remote NSAP:"); + TP_LOGHC_RI (mask,(ST_UINT) tpdu->rem_nsap [0], &tpdu->rem_nsap [1]); +#endif + TP_LOGC_RI1 (mask,"User data length: %u", tpdu->udata_len); + TP_LOGHC_RI (mask,(ST_UINT) tpdu->udata_len, tpdu->udata_ptr); + } + break; + + case TP_PDU_TYPE_AK: + { /*block*/ + TPDU_AK *tpdu = (TPDU_AK *) tsdu; + + if (mask == TP_IND) + buf = "TPDU-AK.ind:"; + else + buf = "TPDU-AK.req:"; + + TP_LOG_RI4 (mask,"%s dst_ref=0x%04X sn=%3u cdt=%2u", + buf, ntohs(tpdu->dst_ref), (unsigned) tpdu->sn, (unsigned) tpdu->cdt); +#if 0 + TP_LOGC_RI0 (mask,"Remote MAC:"); + TP_LOGHC_RI (mask,(ST_UINT) CLNP_MAX_LEN_MAC, tpdu->rem_mac); + TP_LOGC_RI0 (mask,"Remote NSAP:"); + TP_LOGHC_RI (mask,(ST_UINT) tpdu->rem_nsap [0], &tpdu->rem_nsap [1]); +#endif + } + break; + default: + TP_LOG_ERR1 ("TP-ERROR: unknown TPDU type %d", type); + break; + } + + S_UNLOCK_UTIL_RESOURCES (); +} +#else /* function if DEBUG_SISCO not defined */ +ST_VOID tp_log_tsdu (ST_VOID *tsdu, ST_UCHAR type, ST_UCHAR mask) +{ + return; +} +#endif diff --git a/mmslib/slog/qmem.c b/mmslib/slog/qmem.c new file mode 100644 index 0000000..139fce2 --- /dev/null +++ b/mmslib/slog/qmem.c @@ -0,0 +1,166 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993-2007, All Rights Reserved */ +/* */ +/* MODULE NAME : qmem.c */ +/* PRODUCT(S) : Quick Memory Allocator */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/15/07 EJV 08 Chg S_LOCK_RESOURCES to S_LOCK_UTIL_RESOURCES*/ +/* 03/11/04 GLB 07 Remove "thisFileName" */ +/* 06/06/03 JRB 06 Use S_LOCK_RESOURCES (new util mutex). */ +/* 04/14/03 JRB 05 Eliminate compiler warnings. */ +/* 05/24/01 JRB 04 Chg chk_calloc to calloc. This always compiled*/ +/* with !DEBUG_SISCO, screws up link. */ +/* 09/24/99 JRB 03 added: #include "sysincs.h" */ +/* 09/13/99 MDE 02 Added SD_CONST modifiers */ +/* 04/14/99 MDE 01 Removed unnecessary include files */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#include "mem_chk.h" +#include "qmem.h" + +#if defined(MSDOS) +#define HUGE _huge +#else +#define HUGE +#define halloc(a,b) calloc(a,b) +#endif + +ST_INT qMemElemSize; /* should be ((power of 2)-2) */ + +static ST_INT initialized; +static ST_CHAR HUGE *qMemBuf; +static ST_CHAR *qMemUsed; +static ST_INT16 qMemIndex; +static ST_INT qNumElem; +static ST_INT qShift; + +/************************************************************************/ +/* qMemInit */ +/* Initialization function */ +/************************************************************************/ + +ST_RET qMemInit (ST_INT NumElem) + { +ST_INT size; +ST_RET ret; + + S_LOCK_UTIL_RESOURCES (); + if (!initialized) + { + if (qMemElemSize == 0) + qMemElemSize = 126; + qMemBuf = (ST_CHAR HUGE *) halloc ((ST_INT32) NumElem, qMemElemSize + 2); + qMemUsed = (ST_CHAR *) calloc (NumElem, 1); + qMemIndex = 0; + qNumElem = NumElem; + + qShift = -1; + size = qMemElemSize + 2; /* 2 for the header! */ + while (size) /* determine the size of the buffer (power of 2)*/ + { + size >>= 1; /* size = (size/2) */ + qShift++; /* Need to multiply buffer index by 2 later */ + } + initialized = SD_TRUE; + } + + if (!qMemBuf || !qMemUsed) + ret = SD_FAILURE; + else + ret = SD_SUCCESS; + + S_UNLOCK_UTIL_RESOURCES (); + return (ret); + } + +/************************************************************************/ +/* qMemAlloc */ +/* Allocation function */ +/************************************************************************/ + +ST_VOID *qMemAlloc (ST_INT size) + { +ST_INT32 offset; +ST_CHAR HUGE *ptr; +register ST_INT i; + + S_LOCK_UTIL_RESOURCES (); + if (!initialized) + qMemInit (qNumElem == 0 ? 1024 : qNumElem); + + if (qMemIndex == -1 || size > qMemElemSize) + { + S_UNLOCK_UTIL_RESOURCES (); + return (NULL); + } + +/* qMemIndex is the index into the array of buffers to the one that */ +/* we will return this time */ + + offset = ((ST_INT32) qMemIndex) << qShift; /* multiply by buffer size */ + ptr = qMemBuf + offset; + * (ST_INT16 *) ptr = qMemIndex; /* save index into used array */ + + qMemUsed[qMemIndex] = SD_TRUE; /* mark used */ + +/* Now get ready for next time */ + qMemIndex++; + if (qMemIndex == qNumElem) + qMemIndex = 0; + + for (i = 0; i < qNumElem; i++) /* find available buffer */ + { + if (qMemUsed[qMemIndex] == SD_FALSE) + break; + else + { + qMemIndex++; + if (qMemIndex == qNumElem) + qMemIndex = 0; + } + } + if (i == qNumElem) /* no more buffers */ + qMemIndex = -1; + + S_UNLOCK_UTIL_RESOURCES (); + return ((ST_VOID *) (ptr + 2)); + } + + +/************************************************************************/ +/* qMemFree */ +/* Free function */ +/************************************************************************/ + +ST_VOID qMemFree (ST_VOID *vp) + { +ST_INT16 index; +ST_CHAR *ptr; + +/* recover the index into the 'used' flag array & set SD_FALSE */ + S_LOCK_UTIL_RESOURCES (); + ptr = (ST_CHAR *) vp; + ptr -= 2; + index = * (ST_INT16 *) ptr; + qMemUsed[index] = SD_FALSE; + + qMemIndex = index; + S_UNLOCK_UTIL_RESOURCES (); + } + diff --git a/mmslib/slog/slog.c b/mmslib/slog/slog.c new file mode 100644 index 0000000..c4a2995 --- /dev/null +++ b/mmslib/slog/slog.c @@ -0,0 +1,1004 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993-2008, All Rights Reserved */ +/* */ +/* MODULE NAME : slog.c */ +/* PRODUCT(S) : SLOG */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/27/08 EJV 61 Use S_MAX_PATH instead of MAX_PATH. */ +/* slog_get_index_file_name: added destLen param*/ +/* and changed to return result. */ +/* 02/06/08 EJV 60 Moved MAX_PATH define to sysincs.h */ +/* _slogSetTimeTextElapsed _WIN32 only. */ +/* 12/14/07 DSF 59 Added sNonStandardLogMode to support .NET */ +/* Logger class */ +/* 11/16/07 MDE 58 Fixed LINUX compile problems */ +/* 10/23/07 MDE 57 Added ElapsedTime option for Windows */ +/* 01/15/07 EJV 56 Chg S_LOCK_RESOURCES to S_LOCK_UTIL_RESOURCES*/ +/* 01/08/07 EJV 55 slogIpcStop: added lc param. */ +/* 09/13/06 DSF 54 No calls to ExceptionReport */ +/* 08/18/06 JRB 53 Chk _slog_remote_fun along with other ptrs. */ +/* 08/02/06 EJV 52 Corr: chg logMissed to ST_INT to avoid */ +/* repeated logging when IPC_LOG_EN is set. */ +/* 06/20/06 RLH 51 Added parameter checks and other robustness */ +/* features to _slogXML */ +/* 03/14/06 CRM 50 Added _slogXML to log XML strings */ +/* 02/13/06 DSF 49 Migrate to VS.NET 2005 */ +/* 01/23/06 EJV 48 doSlog: clarified buf overrun log for WIN32. */ +/* 11/01/05 EJV 47 slog_end: added S_LOCK_RESOURCES. */ +/* 10/31/05 MDE 46 Tweaked slog_end to stop IPC, disable */ +/* 10/31/05 MDE 45 Default logging now disabled, log missed */ +/* 10/21/05 MDE 44 Fixed slog_end path size */ +/* 08/10/05 MDE 43 Added slog_start, slog_end */ +/* 08/02/05 MDE 42 Fixed compile warning */ +/* 05/23/05 EJV 40 doSlog corr: replaced LOG_IPC_EN with */ +/* LOG_IPC_LISTEN_EN || LOG_IPC_CALL_EN */ +/* Moved sock_debug_sel to gensock2.c */ +/* Moved gs_debug_sel to glbsem.c */ +/* 04/21/05 EJV 39 doSlog: use vsnprintf on Linux; */ +/* Reworked the code assembling log in msg_buf.*/ +/* 02/23/05 JRB 38 slogSetTimeText: fix for VXWORKS. */ +/* 01/26/05 JRB 37 Move clnp_debug_sel to lean_var.c */ +/* 01/24/05 MDE 36 Fixed tweak */ +/* 01/20/05 MDE 35 Minor tweak for fileName & logtype checks */ +/* 11/22/04 JRB 34 Add & use slog_max_msg_size_set funct. */ +/* Ignore sl_max_msg_size if chged after first log.*/ +/* Del static slog_buf, use new lc->msg_buf. */ +/* slogDelBuf: add (LOG_CTRL *) arg. */ +/* 08/04/04 EJV 33 Del slogTime, slogMs global variables. */ +/* 07/09/04 EJV 32 All systems: one time/date format in slog hdr*/ +/* 06/24/04 DSF 31 For Windows, log milliseconds */ +/* 05/18/04 MDE 30 Removed LOG_IPC_SUPPORT #ifdef's */ +/* 05/13/04 EJV 29 Added slogSetHdr, slogHdr. */ +/* 03/11/04 GLB 28 Remove "thisFileName" */ +/* 02/10/04 KCR 27 Added slogDelBuf() */ +/* 01/12/04 EJV 26 Moved sock_debug_sel from gensock2.c */ +/* 10/24/03 JRB 25 Move gs_debug_sel from glbsem.c to here. */ +/* Move clnp_debug_sel to here. */ +/* 10/13/03 EJV 24 Del MSOS2 (old), _WINDOWS. */ +/* 05/07/03 DSF 23 Added support for sErrLogCtrl */ +/* 03/28/02 EJV 22 vnsprintf: use it on Tru64 UNIX v5.0 and up */ +/* 02/11/02 DSF 21 Call ExpRaiseDebugException () to log the */ +/* call stack */ +/* 10/18/01 JRB 20 Fix sprintf calls. */ +/* 09/28/01 EJV 19 Added vnsprintf for systems that support it. */ +/* 05/18/00 JRB 18 More Lint cleanup. */ +/* 04/19/00 JRB 17 Lint cleanup. */ +/* 09/24/99 JRB 16 added: #include "sysincs.h" */ +/* 09/13/99 MDE 15 Added SD_CONST modifiers */ +/* 07/15/99 RKR 14 16-bit version needs stdarg.h */ +/* 04/14/99 MDE 13 Removed unnecessary include files */ +/* 11/11/98 DSF 12 Minor changes to _slog_dyn_log_fun */ +/* 10/08/98 MDE 11 Migrated to updated SLOG interface */ +/* 08/25/98 IKE 10 Prevent buffer overrun by vsprintf for some */ +/* platforms */ +/* 08/13/98 MDE 09 Now log buffer overruns */ +/* 06/15/98 MDE 08 Changes to allow compile under C++ */ +/* 06/02/98 DSF 07 LOG_TIME_EN on by default */ +/* 01/09/98 EJV 06 SUN Solaris 2.5 uses now ANSI vsprintf */ +/* 11/05/97 DSF 05 Added SYSTIME_EN */ +/* 10/06/97 DSF 04 Added thisFileName */ +/* 09/12/97 DSF 03 Expose slogSetTimeText () */ +/* 08/19/97 DSF 02 Initialize sLogCtrlDefault to default */ +/* settings */ +/* 05/27/97 DSF 01 Added IPC logging capability */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#if defined(__OS2__) +#pragma data_seg(alldata) +#define INCL_BASE +#define INCL_DOS +#define INCL_DOSMISC +#define INCL_ERRORS +#define INCL_DOSPROCESS +#define INCL_DOSQUEUES +#define INCL_DOSSEMAPHORES +#define INCL_DOSMEMMGR +#define INCL_DOSFILEMGR +#define INCL_DOSDATETIME +#define INCL_DOSDEVICES +#include +#include +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "slog.h" +#include "stime.h" +#include "str_util.h" +#include "sx_defs.h" + +#if defined (_WIN32) +#include +#endif + +#define XML_NO_TAG 0 +#define XML_DOCUMENT 1 +#define XML_COMMENT 2 +#define XML_START 3 +#define XML_END 4 +#define XML_EMPTY 5 + +ST_CHAR *_slogXMLLogTypeStr = "SLOGXML"; + +/************************************************************************/ +/* Other prototypes. */ +/************************************************************************/ + +static ST_VOID doSlog (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_CHAR *SD_CONST format, va_list ap); +ST_VOID slogSetTimeText (LOG_CTRL *lc); +#if defined (_WIN32) +static ST_VOID _slogSetTimeTextElapsed (LOG_CTRL *lc); +#endif + +/************************************************************************/ +/* Global variables used by the SLOG library. */ +/************************************************************************/ + + +LOG_CTRL *sErrLogCtrl = NULL; + +LOG_CTRL sLogCtrlDefault = {LOG_TIME_EN, + {1000000, "mms.log", + FIL_CTRL_WIPE_EN | + FIL_CTRL_WRAP_EN | + FIL_CTRL_MSG_HDR_EN, + 0, 0, NULL}}; + +LOG_CTRL *sLogCtrl = &sLogCtrlDefault; +ST_CHAR slogTimeText[TIME_BUF_LEN]; +ST_INT sl_max_msg_size = MAX_LOG_SIZE; +ST_UINT32 slogRemoteFlags; +ST_BOOLEAN sNonStandardLogMode = SD_FALSE; + +ST_VOID (*slog_service_fun) (ST_VOID); + +ST_CHAR *_slogAlwaysLogTypeStr = "SLOGALWAYS"; + +/* dynamic logging function */ +ST_VOID (*slog_dyn_log_fun) (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); +ST_VOID (*_slog_dyn_log_fun) (LOG_CTRL *lc, + SD_CONST ST_CHAR *timeStr, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); + +/* remote logging function */ +/* Assign to this fun pointer a function which handles the logging to */ +/* remote log file. For the slog_remote_flags parameter reference the */ +/* description for slog_remote_fun function. */ + +ST_VOID (*slog_remote_fun) (ST_UINT32 slog_remote_flags, + LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); + +ST_VOID (*_slog_remote_fun) (ST_UINT32 slog_remote_flags, + LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, + SD_CONST ST_CHAR *buf); + +/************************************************************************/ +/* _slog */ +/* Main general message logging function, typically called via macro */ +/* Just print the message to be logged, pass to memory & file logging */ +/* functions if enabled */ +/************************************************************************/ + +ST_VOID _slogc (LOG_CTRL *lc, SD_CONST ST_CHAR *format, ...) + { +va_list ap; + + + + va_start (ap, format); + doSlog (lc, SLOG_CONT, NULL, NULL, 0, format, ap); + va_end(ap); + } + + +ST_VOID _slog (LOG_CTRL *lc, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_CHAR *format, ...) + { +va_list ap; + + va_start (ap, format); + doSlog (lc, SLOG_NORMAL, logTypeStr, sourceFile, lineNum, format, ap); + va_end(ap); + } + +/************************************************************************/ +/* slog */ +/************************************************************************/ + +ST_VOID slog (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_CHAR *format, ...) + { +va_list ap; + + va_start (ap, format); + doSlog (lc, logType, NULL, sourceFile, lineNum, format, ap); + va_end(ap); + } + +/************************************************************************/ +/* slogx */ +/* Extended message logging function. */ +/* Same as slog, except one more argument to determine if this type of */ +/* logging is enabled. This function allows one macro to be used */ +/* for any number of arguments. */ +/* This function is designed so that the first 5 arguments are passed */ +/* to this function via macro. For example: */ +/* #define SLOG_ACSE_IND s_debug_sel & ACSE_IND_PRINT, s_sLogCtrl,\ */ +/* ACSE_IND_PRINT_TYPE,THISFILE,__LINE__ */ +/* slogx (SLOG_ACSE_IND, "Indication PDU ptr=" S_FMT_PTR ", len=%d", ptr, len); */ +/************************************************************************/ + +ST_VOID slogx (ST_UINT32 doit, LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_CHAR *format, ...) + { +va_list ap; + +/* Make sure "doit" flag is set. */ + if (!doit) + return; + + va_start (ap, format); + doSlog (lc, logType, NULL, sourceFile, lineNum, format, ap); + va_end(ap); + } + + +/************************************************************************/ +/* doSlog */ +/* Main logging function, called from slog or slogx. */ +/* Just print the message to be logged, pass to memory & file logging */ +/* functions if enabled */ +/************************************************************************/ + +#define SLOG_MISSED_LOG_MSG "Warning: SLOG Log messages missed" + +static ST_VOID doSlog (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_CHAR *SD_CONST format, va_list ap) + { +ST_INT count; +ST_CHAR tmpBuf[128]; +static ST_INT logMissed = 0; +static ST_CHAR *missedSourceFile; +static ST_INT missedLineNum; + + S_GS_INIT (); + S_LOCK_UTIL_RESOURCES (); + +/* Make sure the LOG_CTRL pointer is not NULL */ + if (!lc) + { + S_UNLOCK_UTIL_RESOURCES (); + return; + } + +/* Check to see if any logging is enabled AND dynamic user logging */ +/* function pointer not set */ + + if (!(lc->logCtrl & (LOG_FILE_EN | LOG_MEM_EN | LOG_IPC_EN)) && + !slog_dyn_log_fun && !_slog_dyn_log_fun && + !slog_remote_fun && !_slog_remote_fun) + { + if (logMissed == 0) + { + logMissed = 1; + missedSourceFile = sourceFile; + missedLineNum = lineNum; + } + S_UNLOCK_UTIL_RESOURCES (); + return; + } + +/* Allocate a slog_buffer the first time this function is called. This */ +/* allows us to make the size of the slog message buffer larger than */ +/* the default. */ + + if (lc->msg_buf == NULL) + { + /* NOTE: this code only for backward compatibility with apps that */ + /* control buffer size by setting the global var "sl_max_msg_size". */ + /* New apps should call "slog_max_msg_size_set" directly. */ + /* Use value of sl_max_msg_size NOW. Don't care if user changes it later.*/ + if (slog_max_msg_size_set (lc, sl_max_msg_size) != SD_SUCCESS) + { + fprintf(stderr, "\nslog: error setting max msg size"); + S_UNLOCK_UTIL_RESOURCES (); + return; + } + } + +/* It is OK to pass in a NULL format string when using the dynamic */ +/* logging functions - no vsprintf if so */ + + if (format == NULL) + { + /* make buf a zero length string just in case */ + count = 0; + lc->msg_buf[0] = 0; + } + else + { +#if defined(_WIN32) + count = _vsnprintf(lc->msg_buf,lc->max_msg_size,format,ap); +#elif defined(__QNX__) && defined(__WATCOMC__) + count = _vbprintf(lc->msg_buf,lc->max_msg_size,format,ap); +#elif defined(_AIX) || defined(sun) || defined(_hpux) || defined(__alpha) || defined(linux) + count = vsnprintf(lc->msg_buf,lc->max_msg_size,format,ap); +#else /* other systems: VXWORKS, ... */ + count = vsprintf (lc->msg_buf, format, ap); +#endif + lc->msg_buf[lc->max_msg_size-1] = 0; /* terminate the buffer, Win and UNIX */ + /* functions don't behave the same */ + /* NOTE: On _WIN32 count could be negative because of error or too small buffer. */ + /* On other systems count is negative because of error, too small buffer is */ + /* indicated by return of count larger than buf_size supplied to the function.*/ +#if defined(_WIN32) + if (count < 0) + { + sprintf (tmpBuf,"*** LOG ERROR: LOG BUFFER OVERRUN (lc->max_msg_size=%d bytes) or _vsnprintf function error", + lc->max_msg_size); + strncpy_safe (lc->msg_buf, tmpBuf, lc->max_msg_size-1); + count = strlen (lc->msg_buf); /* count = len of this log message */ + } +#else /* !defined(_WIN32) */ + if (count < 0) + { + sprintf (tmpBuf,"*** LOG ERROR: _vbprintf(QNX), vsnprintf(UNIX,LINUX), or vsprintf(other sys) function failed"); + strncpy_safe (lc->msg_buf, tmpBuf, lc->max_msg_size-1); + count = strlen (lc->msg_buf); /* count = len of this log message */ + } + else if (count >= lc->max_msg_size) + { + sprintf (tmpBuf,"*** LOG ERROR: LOG BUFFER OVERRUN: message len=%d bytes (lc->max_msg_size=%d bytes)", + count, lc->max_msg_size); + strncpy_safe (lc->msg_buf, tmpBuf, lc->max_msg_size-1); + count = strlen (lc->msg_buf); /* set count to len of this log message */ + } +#endif /* !defined(_WIN32) */ + + count++; /* allow for null terminator */ + } + +/* If time stamping is desired, get the time string from the user */ + if (lc->logCtrl & LOG_TIME_EN) + slogSetTimeText (lc); + else + slogTimeText[0] = 0; /* Init to empty time/date string. */ + +/* Check for type for special logging ('continuation' or dynamic */ +/* logging format commands) - */ +/* All standard log types are >= 0 */ +/* Continuation logging is SLOG_CONT (-1) */ +/* Dynamic logging format commands are other negative numbers, */ +/* reserved are - */ +/* SLOG_DYN_PAUSE = -10 */ +/* SLOG_DYN_LF = -11 */ +/* SLOG_DYN_CLRSCR = -12 */ + + if (logType >=0 || logType == SLOG_CONT) + { + if (lc->logCtrl & LOG_FILE_EN) /* File Logging enabled */ + { + if (logMissed == 1) + { + logMissed = 2; /* to prevent logging this msg again */ + /* when slogIpc turns off all masks */ + slogFile (lc, 0, "INTERNAL_SLOG", missedSourceFile, missedLineNum, strlen (SLOG_MISSED_LOG_MSG), SLOG_MISSED_LOG_MSG); + } + slogFile (lc, logType, logTypeStr, sourceFile, lineNum, count, lc->msg_buf); + } + if (lc->logCtrl & LOG_MEM_EN) /* File Logging enabled */ + slogMem (lc, logType, logTypeStr, sourceFile, lineNum, count, lc->msg_buf); + } + if ((lc->logCtrl & LOG_IPC_LISTEN_EN) || (lc->logCtrl & LOG_IPC_CALL_EN)) + /* IPC Logging enabled (listen, calling, or both modes) */ + slogIpc (lc, logType, logTypeStr, sourceFile, lineNum, count, lc->msg_buf); + +/* If the user has set up a dynamic log display function, call it */ + if (slog_dyn_log_fun) + (*slog_dyn_log_fun)(lc, logType, sourceFile, lineNum, count, lc->msg_buf); + if (_slog_dyn_log_fun) + (*_slog_dyn_log_fun)(lc, slogTimeText, logType, logTypeStr, sourceFile, + lineNum, count, lc->msg_buf); + + /* If the user has set up a remote logging function, call it */ + if (slog_remote_fun) + { + (*slog_remote_fun)(slogRemoteFlags, lc, logType, sourceFile, lineNum, + count, lc->msg_buf); + } + if (_slog_remote_fun) + { + (*_slog_remote_fun)(slogRemoteFlags, lc, logType, logTypeStr, + sourceFile, lineNum, count, lc->msg_buf); + } + + S_UNLOCK_UTIL_RESOURCES (); + } + +/************************************************************************/ +/* slogSetTimeText */ +/* Set the time string per the lc control information */ +/************************************************************************/ +ST_VOID slogSetTimeText (LOG_CTRL *lc) + { + slogTimeText[0] = 0; /* Init to empty. */ + + if (lc->logCtrl & LOG_TIME_EN) + { +#if defined (_WIN32) + SYSTEMTIME systime; + + if ((lc->logCtrl & LOG_ELAPSEDTIME_EN) == 0) + { + GetLocalTime (&systime); + sprintf (slogTimeText, "%04d-%02d-%02d %02d:%02d:%02d.%03d", + systime.wYear, systime.wMonth, systime.wDay, + systime.wHour, systime.wMinute, systime.wSecond, systime.wMilliseconds); + } + else + _slogSetTimeTextElapsed (lc); + +#elif defined (VXWORKS) + /* Does not support gettimeofday. */ + time_t curTime; + struct tm *locTime; + + curTime = time (NULL); + locTime = localtime (&curTime); + sprintf (slogTimeText, "%04d-%02d-%02d %02d:%02d:%02d", + locTime->tm_year+1900, locTime->tm_mon+1, locTime->tm_mday, + locTime->tm_hour, locTime->tm_min, locTime->tm_sec); +#else + /* UNIX, Linux, QNX,... */ + struct timeval tp; + time_t curTime; + struct tm *locTime; + + gettimeofday (&tp, NULL); + curTime = (time_t) tp.tv_sec; + locTime = localtime (&curTime); + sprintf (slogTimeText, "%04d-%02d-%02d %02d:%02d:%02d.%03ld", + locTime->tm_year+1900, locTime->tm_mon+1, locTime->tm_mday, + locTime->tm_hour, locTime->tm_min, locTime->tm_sec, tp.tv_usec/1000); +#endif /* UNIX, Linux, QNX,... */ + } + } + + +/************************************************************************/ + +#if defined (_WIN32) +static ST_VOID _slogSetTimeTextElapsed (LOG_CTRL *lc) +{ +static ST_BOOLEAN firstTime = SD_TRUE; +static LARGE_INTEGER ticksPerSec; +static LARGE_INTEGER startTicks; +static double dTicksPerSec; +LARGE_INTEGER ticks; +double dDeltaTicks; +double dSec; + + if (firstTime == SD_TRUE) + { + /* See if supported, and if so how many ticks per second */ + if (QueryPerformanceFrequency(&ticksPerSec)) + { + /* Mark the start of time for us */ + QueryPerformanceCounter (&startTicks); + + /* We want to work with double precision floating point */ + dTicksPerSec = (double) ticksPerSec.QuadPart; + } + else + { + strncpy_safe (slogTimeText, "Elapsed Time Not Available", sizeof (slogTimeText) - 1); + return; + } + firstTime = SD_FALSE; + } + + +/* Get the current tick count */ + QueryPerformanceCounter (&ticks); + +/* Get delta from start of logging */ + dDeltaTicks = (double) (ticks.QuadPart - startTicks.QuadPart); + +/* Calculate the elapsed time */ + dSec = dDeltaTicks/dTicksPerSec; + + sprintf (slogTimeText, "%.6f", dSec); + } +#endif /* defined (_WIN32) */ + + + +/************************************************************************/ +/* slogTrimFileName */ +/************************************************************************/ + +ST_VOID slogTrimFileName (ST_CHAR *dest, SD_CONST ST_CHAR *fullName) + { +ST_INT i,s; +ST_CHAR c; + + s = 0; + i = 0; + while ((c = fullName[i])) + { + if (c == '\\' || c == '/' || c == ':' || c == ']' ) + s = i+1; /* remember the last path seperator character position */ + i++; + } + strncpy (dest,&fullName[s], SLOG_MAX_FNAME); + dest[SLOG_MAX_FNAME] = 0; + } + +/************************************************************************/ +/* slogSetHdr */ +/* Set the header string per the lc control information. */ +/* The slogHdr needs to be SLOG_MAX_HDR+1 bytes long (in worst case). */ +/************************************************************************/ + +ST_VOID slogSetHdr (LOG_CTRL *lc, SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + ST_CHAR *slogHdr, ST_CHAR *lineBreak) + { +ST_CHAR fname[SLOG_MAX_FNAME+1]; +ST_CHAR tmp[SLOG_MAX_FNAME+14+1]; /* 14 for line nubmer & () */ + + sprintf (slogHdr, lineBreak); + + if ((lc->fc.ctrl & FIL_CTRL_MSG_HDR_EN) && (logType != SLOG_CONT)) + { + if (!(lc->logCtrl & LOG_NO_HEADER_CR)) + strcat (slogHdr, lineBreak); + + if (lc->logCtrl & LOG_TIME_EN) /* user wants time stamp */ + { + strcat (slogHdr, slogTimeText); + strcat (slogHdr, " "); + } + + if (!(lc->logCtrl & LOG_LOGTYPE_SUPPRESS)) + { + if (logTypeStr != NULL && logTypeStr[0] != 0) + { + strncat (slogHdr, logTypeStr, min (strlen(logTypeStr), SLOG_MAX_LOGTYPESTR)); + strcat (slogHdr, " "); + } + else + { + sprintf (tmp, "LogType:% 2d ", logType); + strcat (slogHdr, tmp); + } + } + + if ((sourceFile != NULL && sourceFile[0] != 0) && !(lc->logCtrl & LOG_FILENAME_SUPPRESS)) + { + slogTrimFileName (fname, sourceFile); + sprintf (tmp, "(%s %d) ", fname, lineNum); + strcat (slogHdr, tmp); + } + if (!(lc->logCtrl & LOG_NO_HEADER_CR)) + { + strcat (slogHdr, lineBreak); + strcat (slogHdr," "); + } + } + if (logType == SLOG_CONT) + strcat (slogHdr," "); + } + +/************************************************************************/ +/* dumpCallingStack */ +/************************************************************************/ + +#if defined(MSDOS) && !defined(_WINDOWS) +ST_VOID main (ST_VOID); +#endif + +ST_VOID slogCallStack (LOG_CTRL *lc, SD_CONST ST_CHAR *txt) + { +#if !defined(CODAN) +#if defined(MSDOS) && !defined(TC) +static ST_UINT32 ptr_to_abs (ST_VOID *ptr); +ST_UINT16 os,sg; +ST_UINT16 os2,sg2; +ST_UINT16 os3,sg3; +ST_UINT16 os4,sg4; +ST_UINT16 os5,sg5; +#endif + +/* For DOS we can save the caller's return address */ +#if defined(MSDOS) && !defined(TC) + _asm { + push si ; save SI + + mov si, bp ; first BP frame + mov ax, ss:[si+2] ; get return address "offset" from stack + mov os, ax ; store in "offset" variable + mov ax, ss:[si+4] ; get return address "segment" from stack + mov sg, ax ; store in "segment" variable + + mov si, ss:[si] ; second BP frame + mov ax, ss:[si+2] ; get return address "offset" from stack + mov os2, ax ; store in "offset" variable + mov ax, ss:[si+4] ; get return address "segment" from stack + mov sg2, ax ; store in "segment" variable + + mov si, ss:[si] ; third BP frame + mov ax, ss:[si+2] ; get return address "offset" from stack + mov os3, ax ; store in "offset" variable + mov ax, ss:[si+4] ; get return address "segment" from stack + mov sg3, ax ; store in "segment" variable + + mov si, ss:[si] ; fourth BP frame + mov ax, ss:[si+2] ; get return address "offset" from stack + mov os4, ax ; store in "offset" variable + mov ax, ss:[si+4] ; get return address "segment" from stack + mov sg4, ax ; store in "segment" variable + + mov si, ss:[si] ; fifth BP frame + mov ax, ss:[si+2] ; get return address "offset" from stack + mov os5, ax ; store in "offset" variable + mov ax, ss:[si+4] ; get return address "segment" from stack + mov sg5, ax ; store in "segment" variable + + pop si ; restore SI + } +#endif + +#endif + + if (txt != NULL) + slog(lc, 0, NULL, 0, "%s", txt); + +#if defined(MSDOS) && !defined(TC) + slog(lc,SLOG_CONT,NULL,0,"Calling Address (1st frame): 0x%04X:%04X (0x%lX)", + sg,os,((ST_UINT32)sg << 4) + (ST_UINT32)os); + slog(lc,SLOG_CONT,NULL,0,"Calling Address (2nd frame): 0x%04X:%04X (0x%lX)", + sg2,os2,((ST_UINT32)sg2 << 4) + (ST_UINT32)os2); + slog(lc,SLOG_CONT,NULL,0,"Calling Address (3rd frame): 0x%04X:%04X (0x%lX)", + sg3,os3,((ST_UINT32)sg3 << 4) + (ST_UINT32)os3); + slog(lc,SLOG_CONT,NULL,0,"Calling Address (4th frame): 0x%04X:%04X (0x%lX)", + sg4,os4,((ST_UINT32)sg4 << 4) + (ST_UINT32)os4); + slog(lc,SLOG_CONT,NULL,0,"Calling Address (5th frame): 0x%04X:%04X (0x%lX)", + sg5,os5,((ST_UINT32)sg5 << 4) + (ST_UINT32)os5); + slog(lc,SLOG_CONT,NULL,0,"Main Address : %08lx (0x%lX)", + main,ptr_to_abs ((ST_VOID *)main)); + +#endif + +#if !defined(CODAN) +#endif + } + +/************************************************************************/ +/* ptr_to_abs (ptr) */ +/* Convert buffer address to long real address */ +/************************************************************************/ + +#if defined(MSDOS) && !defined(TC) +static ST_UINT32 ptr_to_abs (ST_VOID *ptr) + { +ST_UINT32 temp1; +ST_UINT32 temp2; + + temp1 = (ST_UINT32) ptr; + temp2 = temp1 >> 12; /* Microsoft/Xenix use seg/off */ + temp1 &= 0xFFFF; + temp2 &= 0xFFFF0; + return (temp1 + temp2); /* find real address */ + } +#endif + + +/************************************************************************/ +/* slog */ +/************************************************************************/ + +ST_VOID slogDelBuf (LOG_CTRL *lc) + { + S_LOCK_UTIL_RESOURCES (); + if (lc->msg_buf) + free (lc->msg_buf); + lc->msg_buf = NULL; + S_UNLOCK_UTIL_RESOURCES (); + } + +/************************************************************************/ +/* slog_max_msg_size_set */ +/* Set the maximum message size and allocate a buffer of this size. */ +/* This function sets "max_msg_size" and "msg_buf" in LOG_CTRL. */ +/************************************************************************/ +ST_RET slog_max_msg_size_set (LOG_CTRL *lc, ST_INT max_msg_size) + { +ST_RET retcode = SD_SUCCESS; + + S_LOCK_UTIL_RESOURCES (); + lc->max_msg_size = max_msg_size; /* save size in LOG_CTRL */ + + if (lc->msg_buf != NULL) + free (lc->msg_buf); /* buf already allocated by previous call, so free it first*/ + + /* Alloc "lc->msg_buf". chk_malloc calls slog so use malloc here! */ + /* This is the only place "lc->msg_buf" is allocated. */ + lc->msg_buf = (ST_CHAR *) malloc (lc->max_msg_size + 1); + if (lc->msg_buf == NULL) + { /* this should almost never happen */ + lc->max_msg_size = 0; /* no buffer so can't log anything */ + retcode = SD_FAILURE; + } + S_UNLOCK_UTIL_RESOURCES (); + return (retcode); + } + +/************************************************************************/ +/* slog_start */ +/************************************************************************/ + +ST_RET slog_start (LOG_CTRL *lc, ST_INT max_msg_size) + { +ST_RET rc; + + rc = slog_max_msg_size_set (lc, max_msg_size); + rc = slogIpcInit (lc); + return (rc); + } + +/************************************************************************/ +/* slog_end */ +/************************************************************************/ + +ST_RET slog_end (LOG_CTRL *lc) + { +ST_CHAR idxFileName[S_MAX_PATH]; +FILE *fh; +ST_RET rc; + + slogIpcStop (lc); + rc = slog_get_index_file_name (lc, idxFileName, sizeof(idxFileName)); + + S_LOCK_UTIL_RESOURCES (); + if (rc == SD_SUCCESS) + { + fh = fopen (idxFileName,"w+"); + if (fh) + { + fprintf (fh,"%ld", lc->fc.wipeFilePos); + fclose (fh); + rc = SD_SUCCESS; + } + else + rc = SD_FAILURE; + } + +/* No more file or IPC logging after end ... */ + lc->logCtrl &= ~(LOG_FILE_EN | LOG_IPC_EN); + S_UNLOCK_UTIL_RESOURCES (); + + return (rc); + } + +/************************************************************************/ +/* _slogXML */ +/* Formats XML strings and logs them if file logging is enabled. */ +/************************************************************************/ +ST_VOID _slogXML (LOG_CTRL *lc, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + ST_UINT numBytes, + SD_CONST ST_CHAR *textData) + { +ST_UINT filCtrlSave; +ST_UINT tabLevel = 0; +ST_UINT index, i, j; +ST_CHAR xmlBuffer[SX_MAX_ELEM_LEN+1]; +ST_INT eleLength[SX_MAX_XML_NEST]; +ST_INT prevTag; +ST_INT tag = XML_NO_TAG; + + + + S_GS_INIT (); + S_LOCK_UTIL_RESOURCES (); + + /* Make sure the LOG_CTRL and textData pointers are not NULL */ + if ((!lc) || (!textData)) + { + S_UNLOCK_UTIL_RESOURCES (); + return; + } + + /* Check to see if any logging is enabled AND dynamic user logging */ + /* function pointer not set */ + if (!(lc->logCtrl & LOG_FILE_EN) && + !slog_dyn_log_fun && !_slog_dyn_log_fun && + !slog_remote_fun && !_slog_remote_fun) + { + S_UNLOCK_UTIL_RESOURCES (); + return; + } + + /* Remember the state of the wipe/wrap/header enable flags */ + /* so that we can restore them later */ + filCtrlSave = lc->fc.ctrl & (FIL_CTRL_WIPE_EN | + FIL_CTRL_WRAP_EN | + FIL_CTRL_MSG_HDR_EN); + + if (!numBytes) + { + lc->fc.ctrl |= (filCtrlSave & FIL_CTRL_WIPE_EN); + } + + if (lc->logCtrl & LOG_FILE_EN) /* File Logging enabled */ + { + for (i=0; i= SX_MAX_XML_NEST) /* Log error if maximum nesting level is exceeded */ + { + slogFile (lc, SLOG_NORMAL, logTypeStr, sourceFile, lineNum, 0, "XML nesting exceeds maximum level"); + break; + } + + if (eleLength[tabLevel] >= SX_MAX_ELEM_LEN) /* Log error if maximum element length is exceeded */ + { + slogFile (lc, SLOG_NORMAL, logTypeStr, sourceFile, lineNum, 0, "XML element exceeds maximum length"); + break; + } + + eleLength[tabLevel]++; + + /* Skip control characters */ + /* cast the chars as ST_UCHAR so data > 0x7F will not look negative */ + + if (iscntrl((ST_UCHAR) textData[i]) || (textData[i] == ' ' && index == 0)) + { + index = 0; + continue; + } + + /* Determine tag value */ + if (textData[i] == '/' && textData[i+1] == '>') + tag = XML_EMPTY; + + if (textData[i] == '<') + { + prevTag = tag; + + if (textData[i] == '<' && textData[i+1] == '?') + tag = XML_DOCUMENT; + else if (textData[i] == '<' && textData[i+1] == '!') + tag = XML_COMMENT; + else if (textData[i] == '<' && textData[i+1] == '/') + tag = XML_END; + else if(textData[i] == '<') + tag = XML_START; + + /* Increment/decrement tabLevel */ + if (prevTag == XML_START && (tag == XML_START || tag == XML_COMMENT)) + tabLevel++; + else if (tag == XML_END && (prevTag == XML_END || prevTag == XML_EMPTY)) + tabLevel--; + + /* Format tab level */ + if (index == 0) + { + xmlBuffer[0] = '\0'; + + if (tabLevel) + { + for (j=0; j' && ( + textData[i+1] == '<' || + textData[i+1] == ' ' || + iscntrl ((ST_UCHAR) textData[i+1]) || + i == numBytes-1 || + tag != XML_START)) + { + slogFile (lc, SLOG_CONT, logTypeStr, sourceFile, lineNum, strlen(xmlBuffer), xmlBuffer); + index = 0; + + /* If the user has set up a dynamic log display function, call it */ + if (slog_dyn_log_fun) + { + (*slog_dyn_log_fun)(lc, SLOG_CONT, NULL, 0, strlen(xmlBuffer), xmlBuffer); + } + if (_slog_dyn_log_fun) + { + (*_slog_dyn_log_fun)(lc, slogTimeText, SLOG_CONT, NULL, NULL, 0, strlen(xmlBuffer), xmlBuffer); + } + + /* If the user has set up a remote logging function, call it */ + if (slog_remote_fun) + { + (*slog_remote_fun)(slogRemoteFlags, lc, SLOG_CONT, NULL, 0, strlen(xmlBuffer), xmlBuffer); + } + if (_slog_remote_fun) + { + (*_slog_remote_fun)(slogRemoteFlags, lc, SLOG_CONT, NULL, NULL, 0, strlen(xmlBuffer), xmlBuffer); + } + } + } + } + + /* All done, restore the flag state bits */ + lc->fc.ctrl |= filCtrlSave; + + S_UNLOCK_UTIL_RESOURCES (); + } + + diff --git a/mmslib/slog/slogfil.c b/mmslib/slog/slogfil.c new file mode 100644 index 0000000..a61c25b --- /dev/null +++ b/mmslib/slog/slogfil.c @@ -0,0 +1,741 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993-2008, All Rights Reserved */ +/* */ +/* MODULE NAME : slogfil.c */ +/* PRODUCT(S) : SLOG */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/27/08 EJV 22 Elim warning from previous changes. */ +/* 03/27/08 EJV 21 Use S_MAX_PATH instead of MAX_PATH. */ +/* slog_get_index_file_name: added destLen param*/ +/* and changed to return result. */ +/* 10/08/07 EJV 20 Moved MAX_PATH define to sysincs.h */ +/* 01/15/07 EJV 19 Chg S_LOCK_RESOURCES to S_LOCK_UTIL_RESOURCES*/ +/* 02/13/06 DSF 18 Migrate to VS.NET 2005 */ +/* 10/31/05 MDE 17 Tweaked index tile name creation */ +/* 09/23/05 MDE 16 Tweaked size of idxFileName in */ +/* 09/14/05 DSF 15 Increased size of idxFileName in */ +/* 08/26/05 MDE 14 Fixed startup w/wo */ +/* 08/10/05 MDE 13 Added index file, wrap cleanup, etc. */ +/* 06/07/04 EJV 12 slogFil: chg state if reopen err (HARD_FLUSH)*/ +/* 05/13/04 EJV 11 Moved log header formatting to slogSetHdr. */ +/* 03/11/04 GLB 10 Remove "thisFileName" */ +/* 02/20/03 JRB 09 Del PSOS code. */ +/* 10/13/00 EJV 08 Moved glbsem.h below sysincs.h. */ +/* 08/22/00 KCR 07 Added FIL_CTRL_NO_LOG_HDR */ +/* 09/13/99 MDE 06 Added SD_CONST modifiers */ +/* 04/14/99 MDE 05 Removed unnecessary include files */ +/* 10/23/98 MDE 04 No blank line bet. logs if LOG_NO_HEADER_CR */ +/* 10/16/98 DSF 03 Spelling */ +/* 10/08/98 MDE 02 Migrated to updated SLOG interface */ +/* 10/06/97 DSF 01 Added thisFileName */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#if defined (_WIN32) +#pragma warning(disable : 4996) +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include +#if defined(_WIN32) +#include "io.h" +#endif + +#include "slog.h" + +/************************************************************************/ + +/* Do not change w/o testing */ +#define OLDEST_STRING " OLDEST DATA STARTS BELOW" + +/************************************************************************/ +/* Local function prototypes */ +/************************************************************************/ + +static ST_VOID printWipe (FILE *fh); +static ST_VOID printWrap (FILE *fh); +static ST_VOID printStart (FILE *fh); +static ST_VOID slogFileErrorPrint(ST_CHAR *text, ST_CHAR *fname); +static ST_LONG findOldestMessage(LOG_CTRL *lc, FILE *fh); +static ST_INT copy_named_files (LOG_CTRL *lc, SD_CONST ST_CHAR *SD_CONST dest, + SD_CONST ST_CHAR *SD_CONST src); +static ST_INT copy_named_files_ex (LOG_CTRL *lc, SD_CONST ST_CHAR *SD_CONST dest, + SD_CONST ST_CHAR *SD_CONST src); +static ST_VOID chk_slog_service (LOG_CTRL *lc); + +/************************************************************************/ +/* slogFile */ +/************************************************************************/ + +ST_VOID slogFile (LOG_CTRL *lc, SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT bufLen, SD_CONST ST_CHAR *buf) + + { +FILE *fh; +struct stat fileStat; +ST_LONG seekPos; +ST_LONG currPos; +ST_ULONG fileSize; +ST_CHAR slogHdr[SLOG_MAX_HDR + 1]; +/*ST_INT wrap; */ + + if (!(lc->fc.state & FIL_STATE_OPEN)) /* if not already opened */ + { + /* Need to open the file */ + if (lc->fc.ctrl & FIL_CTRL_NO_APPEND) /* If overwrite is requested */ + fh = NULL; + else + lc->fc.fp = fh = fopen (lc->fc.fileName,"r+"); + + if (!fh) /* File must not exist, or overwrite requested */ + { /* try creating it */ + lc->fc.fp = fh = fopen (lc->fc.fileName,"w+"); + if (!fh) + { + slogFileErrorPrint ("OPEN",lc->fc.fileName); + return; + } + } + + /* We have successfully opened the log file */ + lc->fc.state = FIL_STATE_OPEN; + if (lc->fc.ctrl & FIL_CTRL_SETBUF_EN) /* If setbuf desired */ + setbuf (fh,NULL); /* no buffering, please */ + + /* If appending, need to get to the start write position */ + if ((lc->fc.ctrl & FIL_CTRL_NO_APPEND) == 0) + { + /* Check the current file size, see if we can just append */ + if (fstat (fileno(fh), &fileStat)) + { + slogFileErrorPrint ("SEEK",lc->fc.fileName); + return; + } + fileSize = fileStat.st_size; + if (fileSize < lc->fc.maxSize) + seekPos = (ST_LONG) fileSize; + else + { + seekPos = findOldestMessage (lc, fh); + lc->fc.state |= FIL_STATE_NEED_WIPE; /* flag to show we wrapped */ + } + if (fseek (fh,seekPos,SEEK_SET)) + { + slogFileErrorPrint ("SEEK",lc->fc.fileName); + return; + } + } + +/* Print the 'started' message */ + if (!(lc->fc.ctrl & FIL_CTRL_NO_LOG_HDR)) /* log file header */ + printStart (fh); + }/* File not opened */ + else + { /* The file has already been opened for logging */ + fh = lc->fc.fp; + if (lc->fc.ctrl & FIL_CTRL_WRAP_EN) /* if wrap allowed */ + { + +/* Check to see the position of the file to see if we need to wrap it */ + + currPos = ftell (fh); + if (currPos == -1L) + { + slogFileErrorPrint ("TELL",lc->fc.fileName); + return; + } + +/* Check to see if we need to wrap - currPos is where we would write */ + + if (((ST_ULONG) currPos > lc->fc.maxSize)) + { + +/* Yep, need to wrap - cut off the rest of the file to avoid trailing */ + +#if defined(MSDOS) || defined(__OS2__) || defined(_WIN32) + if (chsize (fileno(fh), currPos)) + { + slogFileErrorPrint ("CHSIZE",lc->fc.fileName); + } +#else + #ifndef __ECOS + if (ftruncate (fileno(fh), currPos)) + { + slogFileErrorPrint ("FTRUNCATE",lc->fc.fileName); + } + #endif +#endif + +/* Seek to start of file */ + if (fseek (fh,0L,SEEK_SET)) + { + slogFileErrorPrint ("SEEK",lc->fc.fileName); + return; + } + +/* Print wrap message at top */ + + seekPos = 0; + printWrap (fh); + lc->fc.state |= FIL_STATE_NEED_WIPE; /* flag to show we wrapped */ + } /* need to wrap */ + } /* Wrap not disabled */ + } /* File already opened */ + +/* Ok, the file is open and the pointer set to where we log the next */ +/* message, any wrap has been printed - time to log the info */ + +/* Now print the message header */ + slogSetHdr (lc, logType, logTypeStr, sourceFile, lineNum, slogHdr, "\n"); + fprintf (fh,"%s", slogHdr); + +/* Now print the message buffer */ + fprintf (fh,"%s", buf); + +/* Now print 'wipe bar', if file has wrapped some time in the past */ +/* and if we are supposed to do the wipe */ + + if (lc->fc.state & FIL_STATE_NEED_WIPE && + lc->fc.ctrl & FIL_CTRL_WIPE_EN) + { + currPos = ftell (fh); + if (currPos == -1L) + { + slogFileErrorPrint ("TELL",lc->fc.fileName); + return; + } + +/* Print the wipe bar */ + lc->fc.wipeFilePos = currPos; + printWipe (fh); + +/* Seek to the current write position */ + + if (fseek (fh,currPos,SEEK_SET)) + { + slogFileErrorPrint ("SEEK",lc->fc.fileName); + return; + } + } /* Need to print wipe bar */ + +/* Try to not lose log data */ + + fflush (fh); + +/* Check for paranoid user - wants to close && reopen */ + + if (lc->fc.ctrl & FIL_CTRL_HARD_FLUSH) + { + currPos = ftell (fh); + if (currPos == -1L) + { + slogFileErrorPrint ("TELL",lc->fc.fileName); + return; + } + +/* Close the file */ + + fclose (fh); + +/* Re-open the file */ + + lc->fc.fp = fh = fopen (lc->fc.fileName,"r+"); + if (!fh) /* better exist */ + { + slogFileErrorPrint ("OPEN",lc->fc.fileName); + lc->fc.state &= ~FIL_STATE_OPEN; + return; + } + + if (lc->fc.ctrl & FIL_CTRL_SETBUF_EN) /* If setbuf desired */ + setbuf (fh,NULL); /* no buffering, please */ + +/* Seek to current write position */ + + if (fseek (fh,currPos,SEEK_SET)) + { + slogFileErrorPrint ("SEEK",lc->fc.fileName); + return; + } + } /* if hard flush enabled */ + } + +/************************************************************************/ +/* slogCloseFile */ +/************************************************************************/ + +ST_VOID slogCloseFile (LOG_CTRL *lc) + { + + S_GS_INIT (); + S_LOCK_UTIL_RESOURCES (); + + if (lc->fc.state & FIL_STATE_OPEN) + { + if (fclose (lc->fc.fp)) + { + fprintf (stderr,"\n *** LOG FILE CLOSE PROBLEM (%s) : ", + lc->fc.fileName); + return; + } + lc->fc.state &= ~FIL_STATE_OPEN; + } + S_UNLOCK_UTIL_RESOURCES (); + } + +/************************************************************************/ +/* slogCloneFile */ +/************************************************************************/ + +ST_VOID slogCloneFile (LOG_CTRL *lc, SD_CONST ST_CHAR *newFile) + { +ST_LONG currPos; +FILE *fh; + + S_GS_INIT (); + S_LOCK_UTIL_RESOURCES (); + + fh = lc->fc.fp; + if (lc->fc.state & FIL_STATE_OPEN) + { + currPos = ftell (fh); + if (currPos == -1L) + { + slogFileErrorPrint ("TELL",lc->fc.fileName); + S_UNLOCK_UTIL_RESOURCES (); + return; + } + +/* Close the file */ + fclose (fh); + +/* Copy the log file */ + copy_named_files (lc, newFile, lc->fc.fileName); + +/* Re-open the file at the old position */ + lc->fc.fp = fh = fopen (lc->fc.fileName,"r+"); + if (!fh) /* better exist */ + { + slogFileErrorPrint ("OPEN",lc->fc.fileName); + S_UNLOCK_UTIL_RESOURCES (); + return; + } + + if (lc->fc.ctrl & FIL_CTRL_SETBUF_EN) /* If setbuf desired */ + setbuf (fh,NULL); /* no buffering, please */ + +/* Seek to current write position */ + if (fseek (fh,currPos,SEEK_SET)) + { + slogFileErrorPrint ("SEEK",lc->fc.fileName); + S_UNLOCK_UTIL_RESOURCES (); + return; + } + } + else /* log file not opened, just copy it */ + copy_named_files (lc, newFile, lc->fc.fileName); + + S_UNLOCK_UTIL_RESOURCES (); + } + +/************************************************************************/ +/* slogCloneFileEx */ +/************************************************************************/ + +ST_VOID slogCloneFileEx (LOG_CTRL *lc, SD_CONST ST_CHAR *newFile) + { +ST_LONG currPos; +FILE *fh; + + S_GS_INIT (); + S_LOCK_UTIL_RESOURCES (); + + fh = lc->fc.fp; + if (lc->fc.state & FIL_STATE_OPEN) + { + currPos = ftell (fh); + if (currPos == -1L) + { + slogFileErrorPrint ("TELL",lc->fc.fileName); + S_UNLOCK_UTIL_RESOURCES (); + return; + } + +/* Close the file */ + fclose (fh); + +/* Copy the log file */ + copy_named_files_ex (lc, newFile, lc->fc.fileName); + +/* Re-open the file at the old position */ + lc->fc.fp = fh = fopen (lc->fc.fileName,"r+"); + if (!fh) /* better exist */ + { + slogFileErrorPrint ("OPEN",lc->fc.fileName); + S_UNLOCK_UTIL_RESOURCES (); + return; + } + + if (lc->fc.ctrl & FIL_CTRL_SETBUF_EN) /* If setbuf desired */ + setbuf (fh,NULL); /* no buffering, please */ + +/* Seek to current write position */ + if (fseek (fh,currPos,SEEK_SET)) + { + slogFileErrorPrint ("SEEK",lc->fc.fileName); + S_UNLOCK_UTIL_RESOURCES (); + return; + } + } + else /* log file not opened, just copy it */ + copy_named_files_ex (lc, newFile, lc->fc.fileName); + + S_UNLOCK_UTIL_RESOURCES (); + } + +/************************************************************************/ +/* slogDeleteFile */ +/************************************************************************/ + +ST_VOID slogDeleteFile (LOG_CTRL *lc) + { + + S_GS_INIT (); + S_LOCK_UTIL_RESOURCES (); + +/* first close the log file */ + + slogCloseFile (lc); + +/* Now delete it */ + + remove (lc->fc.fileName); + + S_UNLOCK_UTIL_RESOURCES (); + } + +/************************************************************************/ +/* findOldestMessage */ +/************************************************************************/ + +static ST_LONG findOldestMessage (LOG_CTRL *lc, FILE *fh) + { +ST_CHAR idxFileName[S_MAX_PATH]; +FILE *idxFh; +ST_CHAR buf[200]; +ST_LONG startPos; +ST_LONG currPos; +ST_INT count; +ST_INT cmpLen; + + cmpLen = strlen(OLDEST_STRING); + +/* Need to find the start position by looking for the 'OLDEST' message. */ +/* See if we have an index file and seek position ... */ + if (slog_get_index_file_name (lc, idxFileName, sizeof(idxFileName)) == SD_SUCCESS) + { + idxFh = fopen (idxFileName,"r"); + if (idxFh) + { + count = fscanf (idxFh, "%ld", &startPos); + fclose (idxFh); + if (count == 1) + { + if (fseek (fh, startPos, SEEK_SET) == 0) + { + fgets (buf,200,fh); + fgets (buf,200,fh); + fgets (buf,200,fh); + if (fgets (buf,200,fh)) + { + if (buf[10] == 'O' && !strncmp (buf,OLDEST_STRING, cmpLen)) + return (startPos); + } + } + } + } + } + +/* Darn, need to start at the top and find it */ + fseek (fh, 0, SEEK_SET); + while (SD_TRUE) + { + currPos = ftell (fh); + if (!fgets (buf,200,fh)) + break; + + chk_slog_service (lc); + + /* Is this the position with the marker string? */ + if (buf[10] == 'O' && !strncmp (buf,OLDEST_STRING, cmpLen)) + return (currPos); + } + +/* No oldest found, go to the start of the file */ + fseek (fh, 0, SEEK_END); + currPos = ftell (fh); + return (currPos); + } + +/************************************************************************/ +/* slog_get_index_file_name */ +/************************************************************************/ + +ST_RET slog_get_index_file_name (LOG_CTRL *lc, ST_CHAR *dest, ST_INT destLen) + { +ST_CHAR *src; +ST_INT srcLen; + + src = lc->fc.fileName; + srcLen = strlen(src); + + if (!src || srcLen == 0) + return (SD_FAILURE); + if (!dest || destLen < (srcLen+4)) /* +4 for len of ".sli" */ + return (SD_FAILURE); + + while (SD_TRUE) + { + *dest = *src; + if (*dest == 0) /* End of string ... */ + break; + + if (*dest == '.') + *dest = '_'; + + ++src; + ++dest; + } + + strcat (dest, ".sli"); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* printStart */ +/************************************************************************/ + +static ST_VOID printStart (FILE *fh) + { +time_t t; + + t = time(NULL); + fprintf (fh,"\n\n***********************************************************"); + fprintf (fh,"\n LOGGING STARTED %s", ctime(&t)); + fprintf (fh,"***********************************************************"); + } + +/************************************************************************/ +/* printWrap */ +/************************************************************************/ + +static ST_VOID printWrap (FILE *fh) + { +time_t t; + + t = time(NULL); + fprintf (fh,"\n***********************************************************"); + fprintf (fh,"\n FILE WRAPPED %s", ctime(&t)); + fprintf (fh,"***********************************************************"); + } + +/************************************************************************/ +/* printWipe */ +/************************************************************************/ + +static ST_VOID printWipe (FILE *fh) + { + fprintf (fh,"\n\n***********************************************************"); + fprintf (fh,"\n%s",OLDEST_STRING);; + fprintf (fh,"\n***********************************************************\n\n"); + } + +/************************************************************************/ +/* slogFileErrorPrint */ +/************************************************************************/ + +static ST_VOID slogFileErrorPrint (ST_CHAR *text, ST_CHAR *fname) + { + fprintf (stderr,"\n*** LOG FILE %s ERROR (%s) : ",text,fname); + fprintf (stderr,"%s",strerror(errno)); + } + +/************************************************************************/ +/* copy_named_files */ +/************************************************************************/ + +#define FILE_READ_SIZE 1000 + +static ST_INT copy_named_files (LOG_CTRL *lc, + SD_CONST ST_CHAR *SD_CONST dest, SD_CONST ST_CHAR *SD_CONST src) + { +FILE *dest_fp; +FILE *src_fp; +ST_INT ret; +ST_CHAR buf[FILE_READ_SIZE+1]; +ST_INT bytes_read; +ST_INT bytes_written; + + if (!(src_fp = fopen (src,"rb"))) + return (SD_FAILURE); + + if (!(dest_fp = fopen (dest,"wb"))) + { + fclose (src_fp); + return (SD_FAILURE); + } + + ret = SD_SUCCESS; + while (SD_TRUE) + { + if (!(bytes_read = fread (buf,1,FILE_READ_SIZE,src_fp))) + break; + + bytes_written = fwrite (buf,1,bytes_read,dest_fp); + if (bytes_read != bytes_written) + { + ret = SD_FAILURE; + break; + } + + chk_slog_service (lc); + } + + if (fclose (src_fp)) + ret = SD_FAILURE; + + if (fclose (dest_fp)) + ret = SD_FAILURE; + + return (ret); + } + + +/************************************************************************/ +/* copy_named_files_ex */ +/************************************************************************/ + +static ST_INT copy_named_files_ex (LOG_CTRL *lc, SD_CONST ST_CHAR *SD_CONST dest, + SD_CONST ST_CHAR *SD_CONST src) + { +FILE *dest_fp; +FILE *src_fp; +ST_INT ret; +ST_CHAR buf[200+1]; +ST_LONG currPos; +ST_LONG oldestPos; + + if (!(src_fp = fopen (src,"rb"))) + return (SD_FAILURE); + + oldestPos = findOldestMessage (lc, src_fp); + if (fseek (src_fp, oldestPos, SEEK_SET)) + { + slogFileErrorPrint ("SEEK",lc->fc.fileName); + fclose (src_fp); + return (SD_FAILURE); + } + + if (!(dest_fp = fopen (dest,"wb"))) + { + fclose (src_fp); + return (SD_FAILURE); + } + + ret = SD_SUCCESS; + while (SD_TRUE) + { + if (!fgets (buf,200,src_fp)) + break; + + fputs (buf,dest_fp); + + chk_slog_service (lc); + } + + if (fclose (src_fp)) + ret = SD_FAILURE; + + if (ret == SD_SUCCESS) + { + if (oldestPos > 0) + { + if (!(src_fp = fopen (src,"rb"))) + { + fclose (dest_fp); + return (SD_FAILURE); + } + + currPos = 0; + while (currPos < oldestPos) + { + if (!fgets (buf,200,src_fp)) + break; + + fputs (buf,dest_fp); + + currPos = ftell (src_fp); + if (currPos == -1L) + { + slogFileErrorPrint ("TELL",lc->fc.fileName); + fclose (src_fp); + fclose (dest_fp); + return (SD_FAILURE); + } + + chk_slog_service (lc); + } + } + } + + if (fclose (src_fp)) + ret = SD_FAILURE; + + if (fclose (dest_fp)) + ret = SD_FAILURE; + + return (ret); + } + + +/************************************************************************/ +/* chk_slog_service */ +/************************************************************************/ + +static ST_INT slog_service_count; + +static ST_VOID chk_slog_service (LOG_CTRL *lc) + { +ST_UINT32 logCtrlSave; + + /* Allow the application to do it's thing during a slow operation */ + if (slog_service_fun) + { + if (++slog_service_count > 10) + { + slog_service_count = 0; + + /* do not allow file logging during this operation */ + logCtrlSave = lc->logCtrl; + lc->logCtrl &= ~LOG_FILE_EN; + (*slog_service_fun) (); + lc->logCtrl = logCtrlSave; + } + } + } diff --git a/mmslib/slog/sloghex.c b/mmslib/slog/sloghex.c new file mode 100644 index 0000000..6e9af48 --- /dev/null +++ b/mmslib/slog/sloghex.c @@ -0,0 +1,362 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993-2007, All Rights Reserved */ +/* */ +/* MODULE NAME : sloghex.c */ +/* PRODUCT(S) : SLOG */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/15/07 EJV 15 Chg S_LOCK_RESOURCES to S_LOCK_UTIL_RESOURCES*/ +/* 08/18/06 JRB 14 Chk _slog_remote_fun along with other ptrs. */ +/* 05/23/05 EJV 13 doSlog corr: replaced LOG_IPC_EN with */ +/* LOG_IPC_LISTEN_EN || LOG_IPC_CALL_EN */ +/* 11/05/04 EJV 12 Added check for LOG_IPC_EN. */ +/* 05/18/04 MDE 11 Removed LOG_IPC_SUPPORT #ifdef's */ +/* 03/11/04 GLB 10 Remove "thisFileName" */ +/* 02/17/03 JRB 09 Del system includes (using sysincs.h). */ +/* 03/27/01 MDE 08 Added _slogStr */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 11/11/98 DSF 06 Minor changes to _slog_dyn_log_fun */ +/* 10/09/98 MDE 05 Put back center space per JB request */ +/* 10/08/98 MDE 04 Migrated to updated SLOG interface */ +/* 04/07/98 MDE 03 Minor warning cleanup */ +/* 10/06/97 DSF 02 Added thisFileName */ +/* 05/28/97 DSF 01 Added IPC logging capability */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "slog.h" + +#define cvt_nibble(a) ((ST_UCHAR) ((a) > 9 ? (a) + 'A' - 10 : (a) + '0')) +#define DEBUG_BUF_LEN 100 + +#define CHAR_PER_LINE 75 + +/************************************************************************/ +/* slogHex */ +/* Main HEX logging function, typically called via macro */ +/* Create the HEX strings && pass to memory & file logging */ +/* functions if enabled */ +/************************************************************************/ + +ST_VOID slogHex (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST fileName, + SD_CONST ST_INT lineNum, + SD_CONST ST_INT numBytes, + SD_CONST ST_VOID *hexData) + { + _slogHex (lc, numBytes, hexData); + } + + +ST_VOID _slogHex (LOG_CTRL *lc, + ST_INT numBytes, + SD_CONST ST_VOID *hexData) + { +ST_INT i; +ST_INT ascii_index; +ST_INT hex_index; +ST_CHAR debug_buf[DEBUG_BUF_LEN+1]; /* output buffer */ +ST_INT curlen; +ST_UCHAR ch; +ST_UCHAR hex; +ST_LONG addr; +ST_UINT filCtrlSave; +ST_UINT memCtrlSave; +ST_UCHAR *buf; + + S_GS_INIT (); + S_LOCK_UTIL_RESOURCES (); + + addr = 0; + +/* Make the compiler happy */ + buf = (ST_UCHAR *) hexData; + +/* Make sure the LOG_CTRL pointer is not NULL */ + if (!lc) + { + S_UNLOCK_UTIL_RESOURCES (); + return; + } + +/* Check to see if any logging is enabled AND dynamic user logging */ +/* function pointer not set */ + if (!(lc->logCtrl & (LOG_FILE_EN | LOG_MEM_EN | LOG_IPC_EN)) && + !slog_dyn_log_fun && !_slog_dyn_log_fun && + !slog_remote_fun && !_slog_remote_fun) + { + S_UNLOCK_UTIL_RESOURCES (); + return; + } + +/* Remember the state of the wipe/wrap/header enable flags */ +/* so that we can restore them later */ + + filCtrlSave = lc->fc.ctrl & (FIL_CTRL_WIPE_EN | + FIL_CTRL_WRAP_EN | + FIL_CTRL_MSG_HDR_EN); + + memCtrlSave = lc->mc.ctrl & MEM_CTRL_MSG_HDR_EN; + +/* No hdr or wipe during a hex dump (allow wrap for first line if req'd)*/ + lc->fc.ctrl &= ~(FIL_CTRL_WIPE_EN | FIL_CTRL_MSG_HDR_EN); + lc->mc.ctrl &= ~MEM_CTRL_MSG_HDR_EN; + +/* Also turn on HEX flag bit for memory logging */ + lc->mc.ctrl |= MEM_CTRL_HEX_LOG; + +/* OK, now start the dump, line by line */ + while (numBytes) + { + curlen = min(numBytes,16); /* # char's in current line */ + for (i = 0; i < DEBUG_BUF_LEN; ++i) + debug_buf[i] = ' '; + sprintf (debug_buf,"%05lX ",addr);/* data offset */ + hex_index = 7; /* where to put hex data */ + ascii_index = 57; /* where to put ascii conversion */ + debug_buf[ascii_index++] = '*'; + + for (i = 0; i < curlen; i++) /* for each byte in this line */ + { + ch = *buf++; /* get next character */ + + hex = (ch >> 4) & (ST_UCHAR) 0x0f;/* write HEX chars for the byte */ + hex = cvt_nibble(hex); + debug_buf[hex_index++] = hex; + hex = ch & (ST_UCHAR) 0x0f; + hex = cvt_nibble(hex); + debug_buf[hex_index++] = hex; + ++hex_index; /* space between bytes */ + if (i == 7) + ++hex_index; + + if (isprint(ch)) /* print ASCII portion */ + debug_buf[ascii_index] = ch; + else + debug_buf[ascii_index] = '.'; /* just put a '.' there */ + ascii_index++; + } + + debug_buf[ascii_index++] = '*'; + debug_buf[ascii_index++] = 0; + + addr += 16; /* prepare for next line */ + numBytes -= curlen; + +/* debug_buf now contains the hex/ascii line to be logged */ + +/* for the last line to be logged, turn wipe back on */ + if (!numBytes) + { + lc->fc.ctrl |= (filCtrlSave & FIL_CTRL_WIPE_EN); + } + + if (lc->logCtrl & LOG_FILE_EN) /* File Logging enabled */ + { + slogFile (lc, SLOG_CONT, NULL, NULL, 0, strlen(debug_buf), debug_buf); + } + + if (lc->logCtrl & LOG_MEM_EN) /* Memory Logging enabled */ + { + slogMem (lc, SLOG_CONT, NULL, NULL, 0, strlen(debug_buf), debug_buf); + } + + if ((lc->logCtrl & LOG_IPC_LISTEN_EN) || (lc->logCtrl & LOG_IPC_CALL_EN)) + /* IPC Logging enabled (listen, calling, or both modes) */ + { + slogIpc (lc, SLOG_CONT, NULL, NULL, 0, strlen(debug_buf), debug_buf); + } + +/* If the user has set up a dynamic log display function, call it */ + if (slog_dyn_log_fun) + { + (*slog_dyn_log_fun)(lc, SLOG_CONT, NULL, 0, + strlen(debug_buf), debug_buf); + } + if (_slog_dyn_log_fun) + { + (*_slog_dyn_log_fun)(lc, slogTimeText, SLOG_CONT, NULL, NULL, 0, + strlen(debug_buf), debug_buf); + } + +/* If the user has set up a remote logging function, call it */ + if (slog_remote_fun) + { + (*slog_remote_fun)(slogRemoteFlags, lc, SLOG_CONT, + NULL, 0, + strlen(debug_buf), debug_buf); + } + if (_slog_remote_fun) + { + (*_slog_remote_fun)(slogRemoteFlags, lc, SLOG_CONT, NULL, + NULL, 0, + strlen(debug_buf), debug_buf); + } + +/* Don't want to wrap the file in the middle of a hex dump */ + lc->fc.ctrl &= ~FIL_CTRL_WRAP_EN; + } + +/* All done, restore the flag state bits */ + + lc->fc.ctrl |= filCtrlSave; + lc->mc.ctrl |= memCtrlSave; + lc->mc.ctrl &= ~MEM_CTRL_HEX_LOG; + + S_UNLOCK_UTIL_RESOURCES (); + } + + +/************************************************************************/ +/* slogStr */ +/************************************************************************/ + +ST_VOID _slogStr (LOG_CTRL *lc, ST_CHAR *strData) + { +ST_INT i; +ST_INT ascii_index; +ST_CHAR debug_buf[DEBUG_BUF_LEN+1]; /* output buffer */ +ST_INT curlen; +ST_UCHAR ch; +ST_UINT filCtrlSave; +ST_UINT memCtrlSave; +ST_INT numBytes; + + S_GS_INIT (); + S_LOCK_UTIL_RESOURCES (); + +/* Make sure the LOG_CTRL pointer is not NULL */ + if (!lc) + { + S_UNLOCK_UTIL_RESOURCES (); + return; + } + +/* Check to see if any logging is enabled AND dynamic user logging */ +/* function pointer not set */ + if (!(lc->logCtrl & (LOG_FILE_EN | LOG_MEM_EN | LOG_IPC_EN)) && + !slog_dyn_log_fun && !_slog_dyn_log_fun && + !slog_remote_fun && !_slog_remote_fun) + { + S_UNLOCK_UTIL_RESOURCES (); + return; + } + +/* Remember the state of the wipe/wrap/header enable flags */ +/* so that we can restore them later */ + + filCtrlSave = lc->fc.ctrl & (FIL_CTRL_WIPE_EN | + FIL_CTRL_WRAP_EN | + FIL_CTRL_MSG_HDR_EN); + + memCtrlSave = lc->mc.ctrl & MEM_CTRL_MSG_HDR_EN; + +/* No hdr or wipe during a hex dump (allow wrap for first line if req'd)*/ + lc->fc.ctrl &= ~(FIL_CTRL_WIPE_EN | FIL_CTRL_MSG_HDR_EN); + lc->mc.ctrl &= ~MEM_CTRL_MSG_HDR_EN; + +/* OK, now start the dump, line by line */ + + numBytes = strlen (strData); + while (numBytes) + { + curlen = min (numBytes,CHAR_PER_LINE); /* # char's in current line */ + ascii_index = 0; /* where to put ascii conversion */ + for (i = 0; i < curlen; i++) /* for each byte in this line */ + { + ch = *strData++; /* get next character */ + if (isprint(ch)) /* print ASCII portion */ + debug_buf[ascii_index] = ch; + else if (ch == '\n') + { + debug_buf[ascii_index] = ch; + ++i; + break; + } /* end of this line */ + else if (ch == '\t') + debug_buf[ascii_index] = ch; + else + debug_buf[ascii_index] = '.'; /* just put a '.' there */ + ascii_index++; + } + debug_buf[ascii_index++] = 0; + + numBytes -= i; + +/* debug_buf now contains the ascii line to be logged */ +/* for the last line to be logged, turn wipe back on */ + if (!numBytes) + { + lc->fc.ctrl |= (filCtrlSave & FIL_CTRL_WIPE_EN); + } + + if (lc->logCtrl & LOG_FILE_EN) /* File Logging enabled */ + { + slogFile (lc, SLOG_CONT, NULL, NULL, 0, strlen(debug_buf), debug_buf); + } + + if (lc->logCtrl & LOG_MEM_EN) /* Memory Logging enabled */ + { + slogMem (lc, SLOG_CONT, NULL, NULL, 0, strlen(debug_buf), debug_buf); + } + + if ((lc->logCtrl & LOG_IPC_LISTEN_EN) || (lc->logCtrl & LOG_IPC_CALL_EN)) + /* IPC Logging enabled (listen, calling, or both modes) */ + { + slogIpc (lc, SLOG_CONT, NULL, NULL, 0, strlen(debug_buf), debug_buf); + } + +/* If the user has set up a dynamic log display function, call it */ + if (slog_dyn_log_fun) + { + (*slog_dyn_log_fun)(lc, SLOG_CONT, NULL, 0, + strlen(debug_buf), debug_buf); + } + if (_slog_dyn_log_fun) + { + (*_slog_dyn_log_fun)(lc, slogTimeText, SLOG_CONT, NULL, NULL, 0, + strlen(debug_buf), debug_buf); + } + +/* If the user has set up a remote logging function, call it */ + if (slog_remote_fun) + { + (*slog_remote_fun)(slogRemoteFlags, lc, SLOG_CONT, + NULL, 0, + strlen(debug_buf), debug_buf); + } + if (_slog_remote_fun) + { + (*_slog_remote_fun)(slogRemoteFlags, lc, SLOG_CONT, NULL, + NULL, 0, + strlen(debug_buf), debug_buf); + } + +/* Don't want to wrap the file in the middle of a hex dump */ + lc->fc.ctrl &= ~FIL_CTRL_WRAP_EN; + } + +/* All done, restore the flag state bits */ + + lc->fc.ctrl |= filCtrlSave; + lc->mc.ctrl |= memCtrlSave; + lc->mc.ctrl &= ~MEM_CTRL_HEX_LOG; + + S_UNLOCK_UTIL_RESOURCES (); + } + + diff --git a/mmslib/slog/slogipcs.c b/mmslib/slog/slogipcs.c new file mode 100644 index 0000000..6f34961 --- /dev/null +++ b/mmslib/slog/slogipcs.c @@ -0,0 +1,124 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2004 - 2007, All Rights Reserved */ +/* */ +/* MODULE NAME : slogipcs.c */ +/* PRODUCT(S) : SLOG */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 08/04/08 MDE 46 Added slogIpcEventEx */ +/* 07/25/08 MDE 06 Moved slogIpcCtx into LOG_CTRL */ +/* 05/30/08 JRB 05 Fix ..RawData args. */ +/* 10/04/07 MDE 04 Added slogIpcCallingEnable */ +/* 01/08/07 EJV 04 slogIpcStop: added lc param. */ +/* 11/03/05 EJV 02 Added slogIpcEvent. */ +/* 02/22/05 JRB 02 slogIpc: add SD_CONST to some args. */ +/* 05/18/04 MDE 01 Initial Release */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "stime.h" +#include "slog.h" +#include "gensock2.h" + +/************************************************************************/ +SLOGIPC_CMD *slogIpcCmdList; +ST_INT slogIpcMaxCmdPend = 1; + +/************************************************************************/ +/* slogIpcInit */ +/************************************************************************/ + +ST_RET slogIpcInit (LOG_CTRL *lc) + { + return (SD_SUCCESS); + } + +/************************************************************************/ +/* slogIpcCallingEnable */ +/************************************************************************/ + +ST_VOID slogIpcCallingEnable (ST_BOOLEAN enable) + { + } + + +ST_VOID slogIpcCallingEnableEx (struct log_ctrl *lc, ST_BOOLEAN enable) + { + } + + +/************************************************************************/ +/* slogIpcStop */ +/************************************************************************/ + +ST_RET slogIpcStop (LOG_CTRL *lc) + { + return (SD_SUCCESS); + } + +/************************************************************************/ +/* slogIpcEvent */ +/************************************************************************/ + +ST_RET slogIpcEvent (ST_VOID) +{ + return (SD_SUCCESS); +} + +ST_RET slogIpcEventEx (LOG_CTRL *lc) +{ + return (SD_SUCCESS); +} + +/************************************************************************/ +/* slogIpc */ +/************************************************************************/ + +ST_VOID slogIpc (LOG_CTRL *lc, ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + ST_INT lineNum, ST_INT bufLen, + ST_CHAR *buf) + { + } + + + +/************************************************************************/ +/* slog_ipc_std_cmd_fun */ +/************************************************************************/ + +ST_VOID slog_ipc_std_cmd_fun (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData, + ST_UINT32 msgType, ST_UINT32 msgDataLen, + ST_CHAR *msgData) + { + } + + + +/************************************************************************/ +/* slogIpcSendData */ +/************************************************************************/ + +ST_VOID slogIpcSendData (GEN_SOCK *pSock, ST_UINT32 msgType, ST_INT dataLen, ST_UCHAR *data) + { + } + +/************************************************************************/ +/* slogIpcSendRawData */ +/************************************************************************/ + +ST_VOID slogIpcSendRawData (LOG_CTRL *lc, ST_INT bufLen, ST_CHAR *buf, ST_BOOLEAN sendAlways) + { + } + diff --git a/mmslib/slog/slogmem.c b/mmslib/slog/slogmem.c new file mode 100644 index 0000000..9d562ac --- /dev/null +++ b/mmslib/slog/slogmem.c @@ -0,0 +1,434 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993-2007, All Rights Reserved */ +/* */ +/* MODULE NAME : slogmem.c */ +/* PRODUCT(S) : SLOG */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/15/07 EJV 16 Chg S_LOCK_RESOURCES to S_LOCK_UTIL_RESOURCES*/ +/* 07/13/05 JRB 15 slogGetMemMsg: skip timestamp on continuation*/ +/* logs & indent 4 chars; indent hex logs. */ +/* getMsgBuffer: make size based on max msg. */ +/* 02/25/05 MDE 14 Added \n */ +/* 01/10/05 MDE 13 Cleanup dump a bit */ +/* 07/09/04 EJV 12 All systems: one time/date format in slog hdr*/ +/* 03/12/04 GLB 11 Removed "thisFileName" */ +/* 02/17/03 JRB 10 Del system includes (using sysincs.h). */ +/* 05/24/01 JRB 09 Chg chk_calloc to calloc. This always compiled*/ +/* with !DEBUG_SISCO, screws up link. */ +/* 10/13/00 EJV 08 Moved glbsem.h below sysincs.h. */ +/* 09/13/99 MDE 07 Added SD_CONST modifiers */ +/* 02/09/99 DSF 06 Thread-safe slogMem () */ +/* Remove extraneous newline in slogMemDump() */ +/* 10/23/98 MDE 05 No blank line bet. logs if LOG_NO_HEADER_CR */ +/* 10/16/98 DSF 04 Spelling */ +/* 10/08/98 MDE 03 Migrated to updated SLOG interface */ +/* 06/15/98 MDE 02 Changes to allow compile under C++ */ +/* 09/18/97 DSF 01 In slogMemInit (), clear chk_debug_en before */ +/* calling chk_calloc () and restore it after. */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "mem_chk.h" +#include "slog.h" +#include "qmem.h" + +/************************************************************************/ +/* Some mysterious looking function pointers */ +/************************************************************************/ + +ST_VOID *(*slogAllocBuf) (ST_INT size) = qMemAlloc; +ST_VOID (*slogFreeBuf) (ST_VOID *buf) = qMemFree; + +/************************************************************************/ +/* slogMem */ +/************************************************************************/ + +ST_VOID slogMem (LOG_CTRL *lc, + SD_CONST ST_INT logType, + SD_CONST ST_CHAR *SD_CONST logTypeStr, + SD_CONST ST_CHAR *SD_CONST sourceFile, + SD_CONST ST_INT lineNum, + ST_INT bufLen, SD_CONST ST_CHAR *buf) + { +LOGMEM_ITEM *thisItem; +MEM_LOG_CTRL *mc; + + S_GS_INIT (); + S_LOCK_UTIL_RESOURCES (); + +/* get pointer to memory control structure */ + + mc = &lc->mc; + +/* Check for initialization */ + + if (!(mc->state & MEM_STATE_INIT)) + { + slogMemInit (lc); + } + +/* Get pointer to the destination item and reset the 'next put' index */ + + thisItem = &mc->item[mc->nextPut]; + + mc->nextPut++; + if (mc->nextPut >= mc->maxItems) /* check for wraparound */ + { + mc->nextPut = 0; + +/* Check for autodump && clean */ + + if (mc->ctrl & MEM_CTRL_AUTODUMP_EN) + { + slogDumpMem (lc); /* Dump memory to log file */ + slogResetMem (lc); /* Delete all contents */ + } + } + +/* Check to see if we need to free the string buffer */ + + if (thisItem->flags & LMF_USED) + { + (*slogFreeBuf) (thisItem->string); + } + +/* Set flags for this item */ + + if (mc->ctrl & MEM_CTRL_MSG_HDR_EN) + { + thisItem->flags = LMF_HEADER | LMF_USED; + thisItem->sourceFile = sourceFile; /* save source information */ + thisItem->lineNum = lineNum; + } + else + thisItem->flags = LMF_USED; + +/* If this is a HEX log, remember that it is */ + + if (mc->ctrl & MEM_CTRL_HEX_LOG) + { + thisItem->flags |= LMF_HEX; + } + +/* Save the log type information */ + + thisItem->logType = logType; + thisItem->logTypeStr = logTypeStr; + +/* If time stamping is enabled, need to save the time */ + + if (lc->logCtrl & LOG_TIME_EN) + strcpy (thisItem->slogTimeText, slogTimeText); + +/* Limit the string size (bufLen includes the null) */ + + if (bufLen > SLOG_MEM_BUF_SIZE) + { + bufLen = SLOG_MEM_BUF_SIZE; + thisItem->string = (ST_CHAR *) (*slogAllocBuf) (bufLen+1); + strncpy (thisItem->string, buf, SLOG_MEM_BUF_SIZE -1); + thisItem->string[SLOG_MEM_BUF_SIZE-1] = 0; + } + else /* no buffer size adjustments req'd */ + { + thisItem->string = (ST_CHAR *) (*slogAllocBuf) (bufLen+1); + strcpy (thisItem->string, buf); + } + + S_UNLOCK_UTIL_RESOURCES (); + } + +/************************************************************************/ +/* slogDumpMem */ +/************************************************************************/ + +ST_VOID slogDumpMem (LOG_CTRL *lc) + { +LOGMEM_ITEM *item; +LOGMEM_ITEM *tooFar; +ST_INT count; +FILE *fh; +time_t t; +ST_CHAR fname[SLOG_MAX_FNAME + 1]; +MEM_LOG_CTRL *mc; +ST_INT i; + + S_GS_INIT (); + S_LOCK_UTIL_RESOURCES (); + +/* get pointer to memory control structure */ + + mc = &lc->mc; + + if (!(mc->state & MEM_STATE_INIT)) + { + S_UNLOCK_UTIL_RESOURCES (); + return; + } + + fh = fopen(mc->dumpFileName, "a+"); + if (!fh) + fh = fopen(mc->dumpFileName, "w+"); + + if (fh) + { + +/* Print the dump header */ + + t = time(NULL); + fprintf (fh,"\n\n***********************************************************"); + fprintf (fh,"\n MEMORY LOG LIST %s", ctime(&t)); + fprintf (fh,"***********************************************************"); + + count = mc->maxItems; /* just in case, for loop escape */ + +/* start at the last logged item, which would be 'next put' */ +/* if the list has wrapped, otherwise somewhere down the list */ + + item = &mc->item[mc->nextPut]; /* Item to log */ + tooFar = &mc->item[mc->maxItems]; /* 1 past end of array */ + + for (i = 0; i < count; ++i,++item) /* for each possible item */ + { + if (item >= tooFar) /* check for wrap */ + item = mc->item; /* go to top */ + + if (item->flags & LMF_USED) /* if used .. */ + { + if (item->flags & LMF_HEADER) + { /* header info is to be used */ + if (!(lc->logCtrl & LOG_NO_HEADER_CR)) + fprintf (fh,"\n"); + + if (item->logType != SLOG_CONT) + { + if (lc->logCtrl & LOG_TIME_EN) /* user wants time stamp */ + fprintf (fh,"\n%s ", item->slogTimeText); + + if (!(lc->logCtrl & LOG_LOGTYPE_SUPPRESS)) + { + if (item->logTypeStr != NULL) + fprintf (fh,"%s ", item->logTypeStr); + else + fprintf (fh,"LogType:% 2d ", item->logType); + } + + if (item->sourceFile && !(lc->logCtrl & LOG_FILENAME_SUPPRESS)) + { + slogTrimFileName (fname,item->sourceFile); + fprintf (fh,"(%s %d) ", fname, item->lineNum); + } + if (!(lc->logCtrl & LOG_NO_HEADER_CR)) + fprintf (fh,"\n "); + } + } + if (item->logType == SLOG_CONT) + fprintf (fh," "); + + fprintf(fh,"%s",item->string); + } /* end if used */ + } /* end for each possible item */ + fclose(fh); + } + S_UNLOCK_UTIL_RESOURCES (); + } + +/************************************************************************/ +/* slogResetMem */ +/************************************************************************/ + +ST_VOID slogResetMem (LOG_CTRL *lc) + { +LOGMEM_ITEM *item; +ST_INT i; +MEM_LOG_CTRL *mc; + + S_GS_INIT (); + S_LOCK_UTIL_RESOURCES (); + +/* get pointer to memory control structure */ + mc = &lc->mc; + + if (!(mc->state & MEM_STATE_INIT)) + return; + +/* just go through the list, clear the used flag && free the str buf */ + + item = mc->item; + for (i = 0; i < mc->maxItems; ++i, ++item) + { + if (item->flags & LMF_USED) + { + item->flags &= ~LMF_USED; + (*slogFreeBuf) (item->string); + } + } + mc->nextPut = 0; + S_UNLOCK_UTIL_RESOURCES (); + } + +/************************************************************************/ +/* slogMemInit */ +/************************************************************************/ + +#define SLOG_MAX_ITEMS (0xFF00/sizeof(LOGMEM_ITEM)) + +ST_VOID slogMemInit (LOG_CTRL *lc) + { +MEM_LOG_CTRL *mc; +ST_UINT save_debug_en; + + mc = &lc->mc; + if (!mc->maxItems) + { + fprintf (stderr,"\n Memory Logging Problem - 0 Items"); + return; + } + + if (mc->maxItems > SLOG_MAX_ITEMS) + { + fprintf (stderr,"\n Memory Logging Problem - Too Many Items"); + mc->maxItems = SLOG_MAX_ITEMS; + } + + if (qMemInit (mc->maxItems)) + { + fprintf (stderr,"\n QMEM Initialization Problem"); + mc->maxItems = 0; + lc->logCtrl &= ~LOG_MEM_EN; + } + else + { +/* Allocate a zero'd memory block for the item control list */ + save_debug_en = chk_debug_en; + chk_debug_en = 0; + mc->item = + (LOGMEM_ITEM *) calloc (mc->maxItems, sizeof (LOGMEM_ITEM)); + chk_debug_en = save_debug_en; + } + + mc->state |= MEM_STATE_INIT; + } + +/************************************************************************/ +/* slogGetMemMsg */ +/************************************************************************/ + +/* Need buffer big enough for max msg plus extra space for timestamp. */ +/* 50 should leave plenty of safety margin. */ +static ST_CHAR getMsgBuffer[SLOG_MEM_BUF_SIZE + 50]; + +ST_CHAR *slogGetMemMsg (LOG_CTRL *lc, SD_CONST ST_INT msgNum) + { +ST_INT i; +MEM_LOG_CTRL *mc; +ST_INT index; + + S_GS_INIT (); + S_LOCK_UTIL_RESOURCES (); + +/* get pointer to memory control structure */ + + mc = &lc->mc; + if (!(mc->state & MEM_STATE_INIT) || msgNum > mc->maxItems) + { + S_UNLOCK_UTIL_RESOURCES (); + return (NULL); + } + +/* FInd the start index in the item array */ + + index = mc->nextPut; /* if wrapped, next put is oldest item */ + if (!(mc->item[index].flags & LMF_USED)) /* but if not wrapped */ + index = 0; /* oldest is item 0 */ + +/* Find the 'msgNum' item index (msgNum == 0 means oldest item) */ + + for (i = 0; i < msgNum; ++i) + { + ++index; + if (index >= mc->maxItems) /* check for wraparound */ + index = 0; + } + + if ((mc->item[index].flags & LMF_USED)) /* if used ... */ + { +/* too easy! return (mc->item[index].string); */ + + if (lc->logCtrl & LOG_TIME_EN) + { + if (mc->item[index].flags & LMF_HEADER) + { + if (mc->item[index].logType == SLOG_CONT) + sprintf (getMsgBuffer," %s", mc->item[index].string); /* indent 4 char*/ + else + sprintf (getMsgBuffer,"%s: %s", &mc->item[index].slogTimeText[11], + mc->item[index].string); + } + else if (mc->item[index].flags & LMF_HEX) + sprintf (getMsgBuffer," %s", mc->item[index].string); /* indent 4 char*/ + else + sprintf (getMsgBuffer," %s", mc->item[index].string); + } + else + { + if (mc->item[index].logType == SLOG_CONT) + sprintf (getMsgBuffer," %s", mc->item[index].string); /* indent 4 char*/ + else + sprintf (getMsgBuffer,"%s", mc->item[index].string); + } + + S_UNLOCK_UTIL_RESOURCES (); + return (getMsgBuffer); + } + + S_UNLOCK_UTIL_RESOURCES (); + return (NULL); + } + +/************************************************************************/ +/* slogGetMemCount */ +/************************************************************************/ + +ST_INT slogGetMemCount (LOG_CTRL *lc) + { +MEM_LOG_CTRL *mc; + + S_GS_INIT (); + S_LOCK_UTIL_RESOURCES (); + +/* get pointer to memory control structure */ + + mc = &lc->mc; + if (!(mc->state & MEM_STATE_INIT)) + { + S_UNLOCK_UTIL_RESOURCES (); + return (0); + } + + if (mc->item[mc->nextPut].flags & LMF_USED) /* if wrapped, */ + { + S_UNLOCK_UTIL_RESOURCES (); + return (mc->maxItems); + } + else + { + S_UNLOCK_UTIL_RESOURCES (); + return (mc->nextPut); + } + } + diff --git a/mmslib/ssec0/ssecusr0.c b/mmslib/ssec0/ssecusr0.c new file mode 100644 index 0000000..643ce87 --- /dev/null +++ b/mmslib/ssec0/ssecusr0.c @@ -0,0 +1,794 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2003 - 2008, All Rights Reserved */ +/* */ +/* MODULE NAME : ssecusr0.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* This file contains Security Manager NUL functions called */ +/* from an MMS or MMS-Lite application. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 07/07/08 EJV 19 Chg sSecGetCertId param to ST_UINT32. */ +/* 10/04/07 MDE 18 Tweaked LOGCFG_VALUE_GROUP/LOGCFGX_VALUE_MAP */ +/* 08/12/05 MDE 17 Added sslLogMaskMapCtrl */ +/* 08/01/05 MDE 16 Added secLogMaskMapCtrl */ +/* 02/25/05 MDE 15 Added sSecAssocConfChkEx */ +/* 08/10/04 EJV 14 secManCfgXmlFile: all lowcase "secmancfg.xml"*/ +/* 02/04/04 EJV 13 Moved maceMechId to acse2dec.c and marb_tx.c */ +/* Added secManCfgChange. */ +/* 10/23/03 EJV 12 Del sSecFreeSecParam, sSecFreePartSecParam. */ +/* Added params to sSecUpdate, sSecUsrEnd. */ +/* 10/15/03 EJV 11 MMS_LITE: added glb var secManCfgXmlFile. */ +/* 09/05/03 EJV 10 Changed defines SECLOG..._ to SEC_LOG_... */ +/* Added ssle_debug_sel. */ +/* sSecUpdate returns SD_SUCCESS. */ +/* Added few more secman.c, genssl.c NUL funcs */ +/* 08/25/03 EJV 09 Merged with recent code changes. */ +/* 08/25/03 EJV 08 Added MMS_LITE code. */ +/* Added sSecUpdate. Removed dupl sSecUsrStart. */ +/* Added maceMechId. */ +/* Added usr funcs from ssec.c */ +/* 08/05/03 ASK 07 sSecFreeSecParam: chg param to ACSE_AUTH_INFO*/ +/* 07/14/03 EJV 06 Added secman functions. */ +/* 06/20/03 EJV 05 sSecAssocConfChk added parameters. */ +/* sSecAssocIndChk added matchCtrl parameter. */ +/* 05/27/03 EJV 04 sSecAssocIndChk added srcChkDest parameter. */ +/* 05/21/03 EJV 03 Added sSecUsrStart. */ +/* 05/08/03 EJV 02 Chg params according to ne ssec.h */ +/* 04/22/03 EJV 01 Created from ssecusr.c */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "ssec.h" +#include "ssec_int.h" +#include "sslelog.h" + + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/************************************************************************/ +/* Logging */ + +/* Log type strings */ +SD_CONST ST_CHAR *SD_CONST _sec_err_logstr = "SEC_LOG_ERR"; +SD_CONST ST_CHAR *SD_CONST _sec_nerr_logstr = "SEC_LOG_NERR"; +SD_CONST ST_CHAR *SD_CONST _sec_flow_logstr = "SEC_LOG_FLOW"; +SD_CONST ST_CHAR *SD_CONST _sec_data_logstr = "SEC_LOG_DATA"; +SD_CONST ST_CHAR *SD_CONST _sec_debug_logstr = "SEC_LOG_DEBUG"; + +ST_UINT sec_debug_sel = SEC_LOG_ERR; +ST_UINT ssle_debug_sel = SSLE_LOG_ERR; +S_SEC_CONFIG _dummySecCfg; + +LOGCFG_VALUE_GROUP secLogMaskMapCtrl = + { + {NULL,NULL}, + "SecurityLogMasks", /* Parent Tag */ + 0, + NULL + }; + +LOGCFG_VALUE_GROUP ssleLogMaskMapCtrl = + { + {NULL,NULL}, + "SecurityLogMasks", /* Parent Tag */ + 0, + NULL + }; + + +#if defined(MMS_LITE) && !defined(MAP30_ACSE) +ST_CHAR *secManCfgXmlFile = "secmancfg.xml"; +#endif /* MMS_LITE over LEAN-T */ + +/************************************************************************/ +/* sSecUsrStart */ +/************************************************************************/ + +ST_RET sSecUsrStart (S_SEC_CONFIG **secCfgOut) + { + _dummySecCfg.secureModeEnabled = SD_FALSE; + *secCfgOut = &_dummySecCfg; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* secManAccessCfg */ +/************************************************************************/ + +ST_RET secManAccessCfg (S_SEC_CONFIG **secCfgOut) + { + _dummySecCfg.secureModeEnabled = SD_FALSE; + *secCfgOut = &_dummySecCfg; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* secManReleaseCfg */ +/************************************************************************/ + +ST_RET secManReleaseCfg () + { + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sSecUpdate */ +/************************************************************************/ + +ST_RET sSecUpdate(S_SEC_CONFIG *currCfg, S_SEC_CONFIG *newCfg) + { + return (SD_SUCCESS); + } + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - */ + /* Set/Get/Free Authentication Info & Encrypt Control */ + /* in stack. */ + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +#if !defined(MMS_LITE) || defined(MAP30_ACSE) +/************************************************************************/ +/* sSecSetSecParam */ +/*----------------------------------------------------------------------*/ +/* Copies the local authentication info and encryption control into the */ +/* channel info. This function must be called before MMS connection */ +/* request. */ +/* After connection terminated call the s_free_security_info() to free */ +/* the user allocated auth_value buf and cleanup the channel info. */ +/* Parameters: */ +/* ST_INT chan channel to set security info */ +/* S_SEC_PARAMS *secParams ptr to security parameters */ +/* Return: */ +/* ST_RET SD_SUCCESS if set operation succeeded */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecSetSecParam (ST_INT chan, S_SEC_SPARAMS *secParams) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecGetSecParam */ +/*----------------------------------------------------------------------*/ +/* Returns pointers to encryption control and partner's authentication */ +/* info from the specified channel info. This functions should be called*/ +/* after connection indication was received to retrieve the security */ +/* informations. */ +/* After the connection terminates call the s_free_part_security_info() */ +/* to free the allocated auth_value buf and cleanup the channel info. */ +/* Parameters: */ +/* ST_INT chan channel to get security info */ +/* S_SEC_PARAMS *secParams ptr where to return sec params */ +/* Return: */ +/* ST_RET SD_SUCCESS if get operation succeeded */ +/* SD_FAILURE or other error. */ +/************************************************************************/ + +ST_RET sSecGetSecParam (ST_INT chan, S_SEC_SPARAMS *secParams) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +#else /* defined(MMS_LITE) */ + +/************************************************************************/ +/* sSecGetSecParam */ +/*----------------------------------------------------------------------*/ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if get operation succeeded */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecGetSecParam (struct mvl_net_info *cc, S_SEC_SPARAMS *secParams) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecFreeSecParam */ +/*----------------------------------------------------------------------*/ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if free operation succeeded */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ +ST_RET sSecFreeSecParam (ACSE_AUTH_INFO *authInfo) +{ + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); +} + +/************************************************************************/ +/* sSecFreePartSecParam */ +/*----------------------------------------------------------------------*/ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if free operation succeeded */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ +ST_RET sSecFreePartSecParam (struct mvl_net_info *cc) +{ + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); +} + +/************************************************************************/ +/* secManCfgChange */ +/************************************************************************/ + +ST_VOID secManCfgChange(ST_VOID) + { + } +#endif /* defined(MMS_LITE) */ + +/************************************************************************/ +/* sSecUsrEnd */ +/*----------------------------------------------------------------------*/ +/* Called by a MACE application to free any resources allocated by the */ +/* secman and sslEngine DLLs. This function should be called before the */ +/* application terminates to ensure that all sensitive memory has been */ +/* overwritten. */ +/* */ +/* Return: */ +/* ST_RET SD_SUCCESS if shutdown was successfull */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ +ST_RET sSecUsrEnd (ST_VOID) + { + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sSecAuthChk */ +/*----------------------------------------------------------------------*/ +/* Perform security checks on a received ACSE_AUTH_INFO */ +/* 1. Get the Cipher Suite being used for the connection */ +/* 2. Decode the certificate and time seal */ +/* 3. Verify the time seal */ +/* 4. Check the Certificate validity time */ +/* 5. Verify the issuer is acceptable per secCfg */ +/* 6. Match the subject to a AR Name per secCfg */ +/* Parameters: */ +/* ST_INT chan conection channel */ +/* S_SEC_AUTHCHK_RSLT *srcChkDest pointer to authentication check */ +/* result. */ +/* Return: */ +/* ST_RET SD_SUCCESS if Authentication check succeeded */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +#if !defined(MMS_LITE) +ST_RET sSecAuthChk (ST_INT chan, S_SEC_AUTHCHK_RSLT *srcChkDest) +#else +ST_RET sSecAuthChk (struct mvl_net_info *cc, S_SEC_AUTHCHK_RSLT *srcChkDest) +#endif + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - */ + /* MACE Authentication */ + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/************************************************************************/ +/* sSecMaceAuthInfoCreate */ +/*----------------------------------------------------------------------*/ +/* Create a 'ready-to-go' ACSE_AUTH_INFO for the specified local AR */ +/* Note that the returned struct is to be free'd using */ +/* sSecMaceAuthInfoFree. */ +/* Parameters: */ +/* S_CERT_ID *certId pointer to Certificate Id */ +/* ACSE_AUTH_INFO *authInfo pointer to Authentication Info */ +/* to be created. */ +/* Return: */ +/* ST_RET SD_SUCCESS if authInfo created */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecMaceAuthInfoCreate (S_CERT_ID *certId, ACSE_AUTH_INFO *authInfo) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecMaceAuthInfoFree */ +/*----------------------------------------------------------------------*/ +/* Free ACSE_AUTH_INFO fields. */ +/* Parameters: */ +/* ACSE_AUTH_INFO *auth_info pointer to Authentication Info */ +/* to free */ +/* Return: */ +/* none */ +/************************************************************************/ + +ST_VOID sSecMaceAuthInfoFree (ACSE_AUTH_INFO *auth_info) + { + SECLOG_NERR0 ("Security functions not supported."); + } + + +/************************************************************************/ +/* sSecMaceAsn1Enc */ +/*----------------------------------------------------------------------*/ +/* Encode a ASN.1 MACE ACSE_AUTH_INFO */ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if MACE encoding succeeded */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecMaceAsn1Enc (S_MACE_INFO *maceInfo, + ST_CHAR *asn1Buf, ST_INT asn1BufLen, + ST_CHAR **maceAsn1Out, ST_INT *maceAsn1LenOut) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + + +/************************************************************************/ +/* sSecMaceAuthInfoDec */ +/*----------------------------------------------------------------------*/ +/* Decode an ACSE_AUTH_INFO into time seal and certificate info */ +/* Note that the maceInfo is to be free'd using chk_free, and the */ +/* certInfo by sSecFreeCertInfo */ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if MACE decoding succeeded */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecMaceAuthInfoDec (ACSE_AUTH_INFO *authInfo, + S_MACE_INFO **maceInfoOut, + S_CERT_INFO **certInfoOut) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecFreeCertInfo */ +/*----------------------------------------------------------------------*/ +/* Free Certificate Info. */ +/* S_CERT_INFO *certInfo pointer to Certificate to free */ +/* Parameters: */ +/* Return: */ +/* none */ +/************************************************************************/ + +ST_VOID sSecFreeCertInfo (S_CERT_INFO *certInfo) + { + SECLOG_NERR0 ("Security functions not supported."); + } + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - */ + /* AR Security Configuration */ + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/************************************************************************/ +/* sSecLocArNameToArSec */ +/*----------------------------------------------------------------------*/ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if conversion successful */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecLocArNameToArSec (ST_CHAR *arName, S_SEC_LOC_AR **arSecOut) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecRemArNameToArSec */ +/*----------------------------------------------------------------------*/ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if conversion successful */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecRemArNameToArSec (ST_CHAR *arName, S_SEC_REM_AR **arSecOut) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecAssocConfChk */ +/*----------------------------------------------------------------------*/ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if Assoc Confirm check successful */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +#if defined(MMS_LITE) +ST_RET sSecAssocConfChkEx (struct mvl_net_info *cc, DIB_MATCH_CTRL *matchCtrl, + S_SEC_REM_AR *remArSec, S_SEC_AUTHCHK_RSLT *srcChkDest) +#else +ST_RET sSecAssocConfChkEx (ST_INT chan, DIB_MATCH_CTRL *matchCtrl, + S_SEC_REM_AR *remArSec, S_SEC_AUTHCHK_RSLT *srcChkDest) +#endif + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecAssocIndChk */ +/*----------------------------------------------------------------------*/ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if Assoc Indication check successful */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +#if defined(MMS_LITE) +ST_RET sSecAssocIndChk (struct mvl_net_info *cc, DIB_MATCH_CTRL *matchCtrl, + S_SEC_REM_AR **arSecOut, S_SEC_AUTHCHK_RSLT *srcChkDest) +#else +ST_RET sSecAssocIndChk (ST_INT chan, DIB_MATCH_CTRL *matchCtrl, + S_SEC_REM_AR **arSecOut, S_SEC_AUTHCHK_RSLT *srcChkDest) +#endif + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - */ + /* Finding things in the Security Configuration */ + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/************************************************************************/ +/* sSecCertNameToLocCertCtrl */ +/*----------------------------------------------------------------------*/ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if conversion successful */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ +/* Get the configured certCtrl for the selected Cert Name */ + +ST_RET sSecCertNameToLocCertCtrl (ST_CHAR *certName, S_CERT_CTRL **certCtrlOut) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecCertNameToRemCertCtrl */ +/*----------------------------------------------------------------------*/ +/* Get the configured certCtrl for the selected Cert Name */ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if conversion successful */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecCertNameToRemCertCtrl (ST_CHAR *certName, S_CERT_CTRL **certCtrlOut) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecCertIdToRemCertCtrl */ +/*----------------------------------------------------------------------*/ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if conversion successful */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecCertIdToRemCertCtrl (S_CERT_ID *certId, S_CERT_CTRL **certCtrlOut) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecCertCfgIdToRemCertCtrl */ +/*----------------------------------------------------------------------*/ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if conversion successful */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecCertCfgIdToRemCertCtrl (ST_INT cfgId, S_CERT_CTRL **certCtrlOut) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - */ + /* Remote Certificate Validity Checking */ + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/************************************************************************/ +/* sSecChkIssuer */ +/*----------------------------------------------------------------------*/ +/* Verify that the issuer of the certificate has been configured as OK */ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if Issuer check successful */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecChkIssuer (S_CERT_INFO *certInfo) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecChkValidityTimes */ +/*----------------------------------------------------------------------*/ +/* Verify the certificate validity times are OK */ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if check Validity Times successful */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecChkValidityTimes (S_CERT_INFO *certInfo) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecChkTimeSeal */ +/*----------------------------------------------------------------------*/ +/* This function performs time seal checks, which are an anti-replay */ +/* where: */ +/* 1. The signedTimeT must match local time within */ +/* pSecCfg->timeSigWindow seconds */ +/* 2. The signedTime has not have been received within */ +/* pSecCfg->timeSigWindow seconds */ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if Time Seal check successful */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecChkTimeSeal (S_CERT_INFO *remCert, + time_t signedTimeT, + ST_UCHAR *clearTime, + S_SIGNED_TIME *signedTime) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - */ + /* Certificate Blob Handling */ + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/************************************************************************/ +/* sSecGetLocalCert */ +/*----------------------------------------------------------------------*/ +/* Retrieve local Certificate Blob from Certificate Store for the */ +/* sprecified CName. */ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if get Local Cert succeeded */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + + +ST_RET sSecGetLocalCert (S_CERT_ID *certId, S_CERT_BLOB *certBlob) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecCertDec */ +/*----------------------------------------------------------------------*/ +/* Decode an Certificate Blob into certificate info */ +/* Note that the certInfo is to be free'd using sSecFreeCertInfo */ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if Cert decode succeeded */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecCertDec (S_CERT_BLOB *certData, S_CERT_INFO **certInfoOut) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - */ + /* Signed Time Handling */ + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/************************************************************************/ +/* sSecSignedTimeDec */ +/*----------------------------------------------------------------------*/ +/* Decode an SignedTime into time_t */ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if Signed Time decode succeeded */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecSignedTimeDec (S_CERT_INFO *remCert, S_SIGNED_TIME *signedTime, time_t *timeOut) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecSignedTimeEnc */ +/*----------------------------------------------------------------------*/ +/* Encoding a Signed Time */ +/* Parameters: */ +/* Return: */ +/* ST_RET SD_SUCCESS if Signed Time encode succeeded */ +/* SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET sSecSignedTimeEnc (S_CERT_ID *localCert, time_t timeToSign, S_SIGNED_TIME *signedTime) + { + SECLOG_NERR0 ("Security functions not supported."); + return (SD_FAILURE); + } + + + + /*------------------------------------------------------*/ + /* */ + /* ssec.c NULL functions needed for MMS_LITE */ + /* */ + /*------------------------------------------------------*/ + +/************************************************************************/ +/* sSecStart */ +/************************************************************************/ +ST_RET sSecStart (S_SEC_CONFIG **secCfgOut) + { + _dummySecCfg.secureModeEnabled = SD_FALSE; + *secCfgOut = &_dummySecCfg; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sSecEnd */ +/************************************************************************/ + +ST_RET sSecEnd (ST_VOID) + { + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sSecGetCertId */ +/************************************************************************/ +/* Retrieve the remote certificate ID on a given socket */ +ST_RET sSecGetCertId (GEN_SOCK *pSock, ST_UINT32 *cfgIdOut) + { + return (SD_FAILURE); + } + +/************************************************************************/ +/* sSecGetCertCtrl */ +/************************************************************************/ +/* Retrieve a ptr to the remote certificate control on a given socket */ +ST_RET sSecGetCertCtrl (GEN_SOCK *pSock, S_CERT_CTRL **certCtrlOut) + { + return (SD_FAILURE); + } + + +/************************************************************************/ +/* sSecGetCipherSuite */ +/************************************************************************/ +/* Retrieve the cipher suite in use on a given socket */ +ST_RET sSecGetCipherSuite (GEN_SOCK *pSock, ST_INT *cipherSuiteOut) + { + return (SD_FAILURE); + } + +/************************************************************************/ +/* setGenSockSSL */ +/************************************************************************/ +/* Sets the security control and callback functions on a given socket. */ +/* Called by SNAP; always returns SD_SUCCESS. */ + +ST_RET setGenSockSSL (GEN_SOCK_CONFIG *sockCfg) + { + return (SD_FAILURE); + } + + + /*------------------------------------------------------*/ + /* */ + /* secman.c NULL functions needed for MMS_LITE */ + /* */ + /*------------------------------------------------------*/ + +/************************************************************************/ +/* secManChkNewCfgAvail */ +/************************************************************************/ + +ST_BOOLEAN secManChkNewCfgAvail() + { + return (SD_FALSE); + } + +/************************************************************************/ +/* secManLoadCfg */ +/************************************************************************/ + +ST_RET secManLoadCfg(S_SEC_CONFIG *secCfgOut) + { + _dummySecCfg.secureModeEnabled = SD_FALSE; + *secCfgOut = _dummySecCfg; + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* secManUpdateCfg */ +/************************************************************************/ + +ST_RET secManUpdateCfg(S_SEC_CONFIG *currCfg, S_SEC_CONFIG *newCfg) + { + return (SD_SUCCESS); + } + +/************************************************************************/ +/* secManFreeCfg */ +/************************************************************************/ + +ST_RET secManFreeCfg(S_SEC_CONFIG *secCfg) + { + return (SD_SUCCESS); + } + + + /*------------------------------------------------------*/ + /* */ + /* genssl.c NULL functions needed for MMS_LITE */ + /* */ + /*------------------------------------------------------*/ + + +/************************************************************************/ +/* sslUpdate */ +/************************************************************************/ + +ST_RET sslUpdate() + { + return (SD_SUCCESS); + } diff --git a/mmslib/util/cfg_util.c b/mmslib/util/cfg_util.c new file mode 100644 index 0000000..df90863 --- /dev/null +++ b/mmslib/util/cfg_util.c @@ -0,0 +1,889 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1991-2006, All Rights Reserved */ +/* */ +/* MODULE NAME : cfg_util.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/07/06 EJV 18 cfg_special_char_str: added '$'. */ +/* 02/20/03 JRB 17 Del PSOS code. */ +/* 11/29/01 EJV 16 Del code for old LATT, XENIX, ultrix, RMX86. */ +/* Removed call to strcasecmp (sun) */ +/* 10/18/01 JRB 15 Add str_util.h (for strcmpi, etc. protos) */ +/* 01/19/01 EJV 14 Moved strcmpi,stricmp,strnicmp to str_util.c */ +/* 11/07/00 JRB 13 Del QNX from ifdef. It supports stricmp, etc.*/ +/* 04/28/00 JRB 12 Lint cleanup */ +/* 09/13/99 MDE 11 Added SD_CONST modifiers */ +/* 04/14/99 MDE 10 Replaced SYSTEM_SEL with compiler defines */ +/* 10/08/98 MDE 09 Migrated to updated SLOG interface */ +/* 08/24/98 EJV 08 Added __hpux to str* cmp functions */ +/* 08/06/98 JRB 07 Added cfg_get_octet_string function. */ +/* 06/15/98 MDE 06 Changes to allow compile under C++ */ +/* 05/22/98 EJV 05 added _AIX, sun, and __alpha to */ +/* stricmp, strcmpi, strnicmp functions */ +/* 04/03/98 RKR 04 added stricmp, strcmpi, strnicmp */ +/* 12/22/97 JRB 03 Clean up PSOS code. */ +/* 12/04/97 KCR 02 Added cfg_goto_keyword function */ +/* 11/05/97 MDE 01 Added VXWORKS support */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "cfg_util.h" +#include "cfglog.h" +#include "str_util.h" +#include + +#include "slog.h" + +/************************************************************************/ + +/* #define DEBUG */ + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ + +/* Externally visable variables */ +ST_CHAR *cfg_line_buf; /* File line read buffer */ +ST_INT cfg_curr_line; /* Current line number */ +ST_INT cfg_line_offset; /* Offset into cfg_line_buf */ + +ST_CHAR *cfg_special_char_str; +ST_CHAR *cfg_end_of_rval_str; + +ST_BOOLEAN config_stop; +ST_RET config_err; +ST_BOOLEAN config_eof; + +ST_UINT cfg_log_mask; +#ifdef DEBUG_SISCO +SD_CONST ST_CHAR *SD_CONST _cfg_err_logstr = "CFG_LOG_ERR"; +SD_CONST ST_CHAR *SD_CONST _cfg_flow_logstr = "CFG_LOG_FLOW"; +#endif + +/************************************************************************/ + +/* Internal definitions */ +#define MAX_STRING_LEN 256 +#define LINE_BUF_SIZE 256 + +ST_INT cfg_max_string_len; +ST_INT cfg_line_buf_size; +ST_INT cfg_max_rval_len; + +#define MAX_CONFIG_NEST 10 + +/* Internal variables */ +static ST_CHAR *cfg_string_buf; +static struct cfg_kw_el *curr_table; +static ST_BOOLEAN cfg_need_new_line; +static FILE *config_fptr; /* Configuration file handle */ + +/* Keyword table stack control */ +static ST_INT num_on_stack; +static struct cfg_kw_el **cfg_kw_stack; + + +/* Internal funtions */ +static struct cfg_kw_el *cfg_lookup_keyword (struct cfg_kw_el *, ST_CHAR *); +static ST_RET cfg_get_next_keyword (FILE *); +static ST_CHAR *cfg_get_rval (ST_VOID); +static ST_RET cfg_end_of_rval (ST_CHAR c); +static ST_RET cfg_special_char (ST_CHAR c); + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* cfg_process_file */ +/************************************************************************/ + +ST_RET cfg_process_file (ST_CHAR *fileName, struct cfg_kw_el *root_kw_tbl) + { +ST_RET ret; + + if (cfg_special_char_str == NULL) + cfg_special_char_str = ":\\/-_ .{}[]<>@,()$"; + + if (cfg_end_of_rval_str == NULL) + cfg_end_of_rval_str = "|"; + + if (cfg_max_string_len == 0) + cfg_max_string_len = MAX_STRING_LEN; + + if (cfg_line_buf_size == 0) + cfg_line_buf_size = LINE_BUF_SIZE; + + if (cfg_max_rval_len == 0) + cfg_max_rval_len = MAX_RVAL_LEN; + +/* Open the configuration file */ + if ((config_fptr = fopen (fileName,"r"))==NULL) + { + CFG_LOG_ERR1 ("Config File (%s) Open Error",fileName); + return (SD_FAILURE); + } + + CFG_LOG_FLOW1 ("Config File (%s) Opened OK",fileName); + +/* If a previous call to the function ended in error there may be some */ +/* old keyword table pushed on the stack. The keywords table stack is */ +/* initialized to zero to process the current configuration file */ + + num_on_stack = 0; + +/* Allocate required buffers */ + + cfg_line_buf = (ST_CHAR *) chk_calloc (cfg_line_buf_size, + sizeof(ST_CHAR)); + cfg_string_buf = (ST_CHAR *) chk_calloc (cfg_max_string_len+1, + sizeof(ST_CHAR)); + cfg_kw_stack = (struct cfg_kw_el **) chk_calloc (MAX_CONFIG_NEST, + sizeof (struct cfg_kw_el *)); + +/* Start with the ROOT keyword table */ + + cfg_tbl_push (root_kw_tbl); + +/* Process the configuration file */ + + cfg_need_new_line = SD_TRUE; + cfg_line_offset = 0; + cfg_curr_line = 0; + config_err = SD_FALSE; + config_stop = SD_FALSE; + config_eof = SD_FAILURE; + +/* Process keywords while not done and no error is detected */ + + while ( ( config_stop == SD_FALSE ) && ( config_err == SD_FALSE ) ) + { + if ( cfg_get_next_keyword( config_fptr ) ) + break; + } + +/* All done, see if it went OK */ + + if ( ( config_stop == SD_TRUE ) && ( config_err == SD_FALSE ) ) + { + CFG_LOG_CFLOW0 ("Config File Read OK"); + ret = SD_SUCCESS; + } + else + { + CFG_LOG_ERR3 ("Config Error, Line %d, \"%s\", Column %d", + cfg_curr_line, cfg_line_buf, cfg_line_offset); + + ret = SD_FAILURE; + } + +/* Free allocated buffers */ + chk_free (cfg_line_buf); + chk_free (cfg_string_buf); + chk_free (cfg_kw_stack); + +/* Close the file so the calling program can reopen it if necessary. */ + + fclose( config_fptr ); + + return (ret); + } + +/************************************************************************/ +/************************************************************************/ +/* cfg_get_next_keyword */ +/************************************************************************/ +/* This function is used to get the next keyword */ + +static ST_RET cfg_get_next_keyword (FILE *fptr) + { +struct cfg_kw_el *ptr; +ST_INT i; +ST_CHAR c; + +/* Look for 'yyy =' string */ + + while (SD_TRUE) /* While looking for the next word */ + { + if (cfg_need_new_line) + { + if ( fgets( cfg_line_buf, cfg_line_buf_size - 1, fptr ) == NULL ) + { + CFG_LOG_CFLOW0 ("No More Keywords : End Of File"); + +/* The following piece of logic exists to allow the state functions to */ +/* declare when it is ok for the file to be out of keywords. If a user */ +/* state function set 'config_eof == SD_SUCCESS' then config_stop is set */ +/* to true when ENDFILE is encountered. */ + + if ( config_eof == SD_SUCCESS ) + { + config_stop = SD_TRUE; + } + return( SD_FAILURE ); + } + + /* Wack the \n */ + for (i = 0; i < cfg_line_buf_size; ++i) + { + if (cfg_line_buf[i] == '\n') + { + cfg_line_buf[i] = 0; + break; + } + } + + cfg_line_offset = 0; /* Offset is 0 for new line */ + ++cfg_curr_line; + if (cfg_line_buf[0] == '#') + continue; /* Discard comment lines */ + + cfg_need_new_line = SD_FALSE; /* Got a new line */ + } + +/* We now have a line to work on, with cfg_line_offset the 1st char */ +/* Extract the keyword from the string (alpha numeric characters) */ +/* '=' means end of rval */ +/* 0 is end of line */ + + i = 0; + c = cfg_line_buf[cfg_line_offset++]; + while (c && c != '#' && /* End of line or comment start */ + c != '=' && /* end of keyword */ + c != '|' && + i < cfg_max_string_len) + { + if (c != ' ' && c != '\t') /* Ignore spaces and tabs */ + { + cfg_string_buf[i] = c; + ++i; + } + c = cfg_line_buf[cfg_line_offset++]; + } + + if (i >= cfg_max_string_len) + { + CFG_LOG_ERR1 ("Error : Line %d too long", cfg_curr_line); + return (SD_FAILURE); + } + + if (c == '#' || !c) /* See if we need a new line next time */ + cfg_need_new_line = SD_TRUE; + +/* i is the index to the char position that terminated the scan */ + cfg_string_buf[i]=0x0; /* NULL terminate the keyword */ + +/* if we have a keyword, then search look it up in the currently active */ +/* keyword table and execute the selected function */ + + if (strlen (cfg_string_buf)) + { /* Find the keyword */ + if ((ptr = cfg_lookup_keyword (curr_table, cfg_string_buf)) != NULL) + { + CFG_LOG_CFLOW1 ("Keyword : %s",cfg_string_buf); + (*ptr->extract)(); + break; + } + else /* invalid keyword */ + { + CFG_LOG_ERR1 ("Unknown Keyword : %s",cfg_string_buf); + return (SD_FAILURE); + } + } + } /* While SD_TRUE */ + + return(SD_SUCCESS); + } + +/************************************************************************/ +/* cfg_get_rval() */ +/************************************************************************/ + +static ST_CHAR *cfg_get_rval(ST_VOID) + { +ST_INT i; +ST_CHAR c; + + cfg_string_buf[0]=0x0; + +/* Now get the rval (value). */ +/* search for 0 to note end of line */ + + i = 0; + c = cfg_line_buf[cfg_line_offset++]; + +/* First strip leading white space (' ', '\t') */ + while (c == ' ' || c == '\t') + c = cfg_line_buf[cfg_line_offset++]; + + while (c && + c != '#' && + !cfg_end_of_rval (c) && + i < cfg_max_rval_len-1) + { + if (isalnum (c) || cfg_special_char (c)) + { + cfg_string_buf[i] = c; + ++i; + } + c = cfg_line_buf[cfg_line_offset++]; + } + + if (c == '#' || !c) /* See if we need a new line next time */ + cfg_need_new_line = SD_TRUE; + +/* Strip trailing spaces and tabs */ + while (i && (cfg_string_buf[i-1] == ' ' || + cfg_string_buf[i-1] == '\t')) + i--; + +/* Null terminate the string */ + cfg_string_buf[i] = 0x0; + + if (!strlen (cfg_string_buf)) + { + CFG_LOG_ERR2 ("Bad rval, line #%d \"%s\"",cfg_curr_line,cfg_line_buf); + return (NULL); + } + + CFG_LOG_CFLOW1 ("Rval : '%s'",cfg_string_buf); + return (cfg_string_buf); + } + +/************************************************************************/ +/* cfg_lookup_keyword */ +/************************************************************************/ + +static struct cfg_kw_el *cfg_lookup_keyword(struct cfg_kw_el *tbl_ptr, + ST_CHAR *name) + { +ST_INT i; +struct cfg_kw_el *ret = NULL; + + for (i = 0; i < MAX_NUM_KEYWORDS; ++i) + { + if (tbl_ptr[i].extract == NULL) /* End of table */ + break; + else if (!strcmpi (name, tbl_ptr[i].name)) + { /* we have a match */ + if (tbl_ptr[i].valid !=NULL) /* Want to validate? */ + { + if ((*tbl_ptr[i].valid)()) + ret = &tbl_ptr[i]; + } + else + ret = &tbl_ptr[i]; + + break; + } + } + + return(ret); + } + +/************************************************************************/ +/* cfg_end_of_rval */ +/************************************************************************/ +/* CONFIG calls back to this function while looking the rval over */ +/* If this function returns SD_TRUE, CONFIG will assume that the */ +/* character is a keyword/rval pair seperator */ +/* Used to allow multiple pairs per line */ + + +static ST_RET cfg_end_of_rval (ST_CHAR c) + { +ST_INT i; +ST_INT str_len; + + str_len = strlen (cfg_end_of_rval_str); + for (i = 0; i < str_len; ++i) + { + if (c == cfg_end_of_rval_str[i]) + return (SD_TRUE); + } + return (SD_FALSE); + } + +/************************************************************************/ +/* cfg_special_char */ +/************************************************************************/ + +static ST_RET cfg_special_char (ST_CHAR c) + { +ST_INT i; +ST_INT str_len; + + str_len = strlen (cfg_special_char_str); + for (i = 0; i < str_len; ++i) + { + if (c == cfg_special_char_str[i]) + return (SD_TRUE); + } + + return (SD_FALSE); + } + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* cfg_tbl_push (new_table) */ +/************************************************************************/ + +ST_RET cfg_tbl_push (struct cfg_kw_el *new_table) + { + if (num_on_stack >= MAX_CONFIG_NEST) + { + CFG_LOG_ERR0 ("Too many pushes - configuration nesting exceeded"); + config_stop = SD_TRUE; + config_err = CFG_UTIL_ERR; + return (SD_FAILURE); + } + + cfg_kw_stack[num_on_stack] = new_table; + ++num_on_stack; + curr_table = new_table; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* cfg_tbl_pop (num_to_pop) */ +/************************************************************************/ + +ST_RET cfg_tbl_pop (ST_INT num_to_pop) + { + if ((num_on_stack-num_to_pop-1)<0) + { + CFG_LOG_ERR0 ("Too many pops off configuration stack"); + config_stop = SD_TRUE; + config_err = CFG_UTIL_ERR; + return (SD_FAILURE); + } + num_on_stack -= num_to_pop; + curr_table = cfg_kw_stack[num_on_stack-1]; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* cfg_get_short */ +/************************************************************************/ + +ST_RET cfg_get_short (ST_INT16 *out_ptr) + { +ST_INT d; +ST_INT16 ret; + + ret = cfg_get_value ("%d", &d); + if (!ret) + *out_ptr = (ST_INT16) d; + return (ret); + } + +/************************************************************************/ +/* cfg_get_ushort */ +/************************************************************************/ + +ST_RET cfg_get_ushort (ST_UINT16 *out_ptr) + { +ST_UINT d; +ST_RET ret; + + ret = cfg_get_value ("%u", &d); + if (!ret) + *out_ptr = (ST_UINT16) d; + return (ret); + } + +/************************************************************************/ +/* cfg_get_int */ +/************************************************************************/ + +ST_RET cfg_get_int (ST_INT *out_ptr) + { +ST_INT d; +ST_RET ret; + + ret = cfg_get_value ("%d", &d); + if (!ret) + *out_ptr = d; + return (ret); + } + +/************************************************************************/ +/* cfg_get_uint */ +/************************************************************************/ + +ST_RET cfg_get_uint (ST_UINT *out_ptr) + { +ST_UINT d; +ST_RET ret; + + ret = cfg_get_value ("%u", &d); + if (!ret) + *out_ptr = d; + return (ret); + } + +/************************************************************************/ +/* cfg_get_long */ +/************************************************************************/ + +ST_RET cfg_get_long (ST_LONG *out_ptr) + { + return (cfg_get_value ("%ld", out_ptr)); + } + +/************************************************************************/ +/* cfg_get_ulong */ +/************************************************************************/ + +ST_RET cfg_get_ulong (ST_ULONG *out_ptr) + { + return (cfg_get_value ("%lu", out_ptr)); + } + + +/************************************************************************/ +/* cfg_get_double */ +/************************************************************************/ + +ST_RET cfg_get_double (ST_DOUBLE *out_ptr) + { + return (cfg_get_value ("%lf", out_ptr)); + } + + +/************************************************************************/ +/* cfg_get_hex_ushort */ +/************************************************************************/ + +ST_RET cfg_get_hex_ushort (ST_UINT16 *out_ptr) + { +ST_UINT d; +ST_RET ret; + + ret = cfg_get_value ("%x", &d); + if (!ret) + *out_ptr = (ST_UINT16) d; + return (ret); + +/* return (cfg_get_value ("%x", out_ptr)); */ + } + +/************************************************************************/ +/* cfg_get_hex_uint */ +/************************************************************************/ + +ST_RET cfg_get_hex_uint (ST_UINT *out_ptr) + { +ST_UINT d; +ST_RET ret; + + ret = cfg_get_value ("%x", &d); + if (!ret) + *out_ptr = d; + return (ret); + +/* return (cfg_get_value ("%x", out_ptr)); */ + } + +/************************************************************************/ +/* cfg_get_hex_ulong */ +/************************************************************************/ + +ST_RET cfg_get_hex_ulong (ST_ULONG *out_ptr) + { + return (cfg_get_value ("%lx", out_ptr)); + } + +/************************************************************************/ +/* cfg_get_value */ +/************************************************************************/ + +ST_RET cfg_get_value (ST_CHAR *format_string, ST_VOID *out_ptr) + { +ST_CHAR *rval; + + rval = cfg_get_rval (); /* get the rvalue string */ + if (!rval) + { + config_err = CFG_GET_RVAL_ERR; + CFG_LOG_ERR0 ("Get Rval Error"); + } + else + { /* Convert to desired data format*/ + if (!sscanf (rval,format_string,out_ptr)) + { + config_err = CFG_CONVERT_ERR; + CFG_LOG_ERR0 ("Data Conversion Error"); + } + } + + if (config_err) /* if error detected ... */ + { + config_stop = SD_TRUE; + return (SD_FAILURE); + } + + return (SD_SUCCESS); + } + + +/************************************************************************/ +/************************************************************************/ +/* *cfg_get_alloc_string */ +/************************************************************************/ + +ST_CHAR *cfg_get_alloc_string (ST_VOID) + { +ST_CHAR *ret_ptr; +ST_CHAR *rval; + + rval = cfg_get_rval (); /* get the rvalue string */ + if (!rval) + { + config_stop = SD_TRUE; + config_err = CFG_GET_RVAL_ERR; + CFG_LOG_ERR0 ("Get Rval Error"); + return (NULL); + } + + /* allocate storage for string */ + ret_ptr = (ST_CHAR *) chk_calloc (1,strlen (rval) +1); + strcpy (ret_ptr,rval); + return (ret_ptr); + } + + +/************************************************************************/ +/* *cfg_get_string_ptr */ +/************************************************************************/ + +ST_CHAR *cfg_get_string_ptr (ST_VOID) + { +ST_CHAR *rval; + + rval = cfg_get_rval (); /* get the rvalue string */ + if (!rval) + { + config_stop = SD_TRUE; + config_err = CFG_GET_RVAL_ERR; + CFG_LOG_ERR0 ("Get Rval Error"); + return (NULL); + } + + return (rval); + } + +/************************************************************************/ +/* cfg_get_octet_string */ +/************************************************************************/ + +ST_RET cfg_get_octet_string (ST_UCHAR *ostr, /* ptr to user's ostr */ + ST_UINT *len_out_ptr, /* addr of len var to be set */ + ST_UINT len_max) /* maximum len to allow. */ + { +ST_UINT j; +ST_INT digit; +ST_BOOLEAN nibble; /* SD_TRUE if nibble read, SD_FALSE if whole byte read*/ +ST_CHAR *rval; + + rval = cfg_get_rval (); /* get the rvalue string */ + if (!rval) + { + config_stop = SD_TRUE; + config_err = CFG_GET_RVAL_ERR; + CFG_LOG_ERR0 ("Get Rval Error"); + return (SD_FAILURE); + } + + j = 0; + nibble = SD_FALSE; + while (isxdigit (*rval)) /* get hex number */ + { + if (j >= len_max) + return (SD_FAILURE); /* Selector longer than allowed */ + + digit = *rval++; /* separate nibbles */ + digit = isdigit (digit) ? digit - '0' : 10 + (toupper (digit) - 'A'); + if (nibble) + { + nibble = SD_FALSE; + ostr[j] = (ostr[j] | (ST_UCHAR) digit); /* set low */ + j++; + + while (isspace (*rval) && *rval != '\n') + ++rval; + } + else + { + nibble = SD_TRUE; + ostr[j] = (ST_UCHAR) digit << 4; /* set high byte */ + } + } + + if (nibble) + { /* Only got half of byte. */ + config_stop = SD_TRUE; + config_err = CFG_CONVERT_ERR; + CFG_LOG_ERR0 ("Incomplete byte in Octet string"); + return (SD_FAILURE); + } + + /* set selector length */ + *len_out_ptr = j; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* cfg_set_config_err */ +/************************************************************************/ + +ST_VOID cfg_set_config_err(ST_VOID) + { + config_err = SD_TRUE; + } + +/************************************************************************/ +/* cfg_set_endfile_ok */ +/************************************************************************/ + +ST_VOID cfg_set_endfile_ok(ST_VOID) + { + config_eof = SD_SUCCESS; + } + + + +/************************************************************************/ +/************************************************************************/ +/* cfg_goto_keyword */ +/************************************************************************/ +/* This function is used to skip over a section to the specified keyword*/ + +ST_RET cfg_goto_keyword (ST_CHAR *keyword) + { +ST_INT i, cfgStringLen, keywordLen; +ST_CHAR c; + +/* Look for 'yyy =' string */ + + keywordLen = strlen (keyword); + while (SD_TRUE) /* While looking for the specified word */ + { + if (cfg_need_new_line) + { + if ( fgets( cfg_line_buf, cfg_line_buf_size - 1, config_fptr ) == NULL ) + { + CFG_LOG_CFLOW0 ("No More Keywords : End Of File"); + +/* The following piece of logic exists to allow the state functions to */ +/* declare when it is ok for the file to be out of keywords. If a user */ +/* state function set 'config_eof == SD_SUCCESS' then config_stop is set */ +/* to true when ENDFILE is encountered. */ + + if ( config_eof == SD_SUCCESS ) + { + config_stop = SD_TRUE; + } + return( SD_FAILURE ); + } + + /* Wack the \n */ + for (i = 0; i < cfg_line_buf_size; ++i) + { + if (cfg_line_buf[i] == '\n') + { + cfg_line_buf[i] = 0; + break; + } + } + + cfg_line_offset = 0; /* Offset is 0 for new line */ + ++cfg_curr_line; + if (cfg_line_buf[0] == '#') + continue; /* Discard comment lines */ + + cfg_need_new_line = SD_FALSE; /* Got a new line */ + } + +/* We now have a line to work on, with cfg_line_offset the 1st char */ +/* Extract the keyword from the string (alpha numeric characters) */ +/* '=' means end of rval */ +/* 0 is end of line */ + + i = 0; + c = cfg_line_buf[cfg_line_offset++]; + while (c && c != '#' && /* End of line or comment start */ + c != '=' && /* end of keyword */ + c != '|' && + i < cfg_max_string_len) + { + if (c != ' ' && c != '\t') /* Ignore spaces and tabs */ + { + cfg_string_buf[i] = c; + ++i; + } + c = cfg_line_buf[cfg_line_offset++]; + } + + if (i >= cfg_max_string_len) + { + CFG_LOG_ERR1 ("Error : Line %d too long", cfg_curr_line); + return (SD_FAILURE); + } + + if (c == '#' || !c) /* See if we need a new line next time */ + cfg_need_new_line = SD_TRUE; + +/* i is the index to the char position that terminated the scan */ + cfg_string_buf[i]=0x0; /* NULL terminate the keyword */ + +/* if we have a keyword, then search look it up in the currently active */ +/* keyword table and execute the selected function */ + + if ((cfgStringLen = strlen (cfg_string_buf)) > 0) + { /* Find the keyword */ + if ((cfgStringLen == keywordLen) && !strcmpi (keyword, cfg_string_buf)) + break; + else /* keyword not found */ + cfg_need_new_line = SD_TRUE; + } + } /* While SD_TRUE */ + + return(SD_SUCCESS); + } + + + + + + + + + + + + + + + + diff --git a/mmslib/util/genlists.c b/mmslib/util/genlists.c new file mode 100644 index 0000000..708944f --- /dev/null +++ b/mmslib/util/genlists.c @@ -0,0 +1,464 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1986-2005 All Rights Reserved */ +/* */ +/* MODULE NAME : gen_list.c */ +/* PRODUCT(S) : general list handling functions */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module contains generic que manipulation routines */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/04/07 MDE 07 Tweaked LOGCFG_VALUE_GROUP/LOGCFGX_VALUE_MAP */ +/* 06/30/05 EJV 06 Add genlistDebugMaps, genlistDebugMapCtrl */ +/* for parsing logcfg.xml */ +/* 04/08/04 JRB 05 list_find_last: if head=NULL, don't log. */ +/* 12/12/02 JRB 04 list_get_first/last: if *head==NULL, return */ +/* NULL & do NOT log a message. */ +/* 11/21/01 MDE 03 Changed logging to use SLOGALWAYS */ +/* 10/09/98 JRB 02 Add list_find_prev, list_find_last. */ +/* 06/15/98 MDE 01 Changes to allow compile under C++ */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#define I_AM_THE_TRUE_GEN_LIST +#include "gen_list.h" +#include "slog.h" + +/************************************************************************/ +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +static ST_CHAR *thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* The variable below is used in selecting generic queuing debug */ +/* checking. When this variable is set to SD_TRUE all data strucutres */ +/* using the list manipulation primitives will under go this checking */ + +ST_BOOLEAN list_debug_sel; + +#ifdef DEBUG_SISCO +LOGCFGX_VALUE_MAP genlistDebugMaps[] = + { +/* Memory debugging */ + {"ListDebugSel", 0, &list_debug_sel, _LOGCFG_DATATYPE_BOOLEAN, NULL, NULL} + }; + +LOGCFG_VALUE_GROUP genlistDebugMapCtrl = + { + {NULL,NULL}, + "GenListLogMasks", /* Parent Tag */ + sizeof(genlistDebugMaps)/sizeof(LOGCFGX_VALUE_MAP), + genlistDebugMaps + }; +#endif /* DEBUG_SISCO */ + +/************************************************************************/ +/* list_unlink */ +/* Primitive to unlink a node out of a circular double linked list */ +/************************************************************************/ + +ST_RET list_unlink (DBL_LNK **list_head_ptr, DBL_LNK *node_ptr) + { +#ifdef DEBUG_SISCO + if (*list_head_ptr == NULL) + { + SLOGALWAYS0 ("GENLIST: ATTEMPT TO UNLINK A NODE FROM A NULL LIST"); + return (SD_FAILURE); + } + + if (node_ptr == NULL) + { + SLOGALWAYS0 ("GENLIST: ATTEMPT TO UNLINK A NULL ADDRESS FROM A LIST"); + return (SD_FAILURE); + } + + if (list_debug_sel == SD_TRUE) + { + if (list_find_node (*list_head_ptr, node_ptr) == SD_FAILURE) + { + SLOGALWAYS0 ("GENLIST: NODE NOT FOUND IN LIST"); + return (SD_FAILURE); + } + } +#endif + +/* If list checking is enabled and we get to here we have valid */ +/* arguments and a valid list */ + + if ((node_ptr -> next == *list_head_ptr) && + (node_ptr == *list_head_ptr)) /* only node in list? */ + { + *list_head_ptr = NULL; + } + else + { + if (node_ptr == *list_head_ptr) /* first node in a multi*/ + *list_head_ptr = node_ptr->next; /* node list */ + (node_ptr->next)->prev = node_ptr->prev; /* link cur next to prev*/ + (node_ptr->prev)->next = node_ptr->next; /* link cur prev to next*/ + } + return (SD_SUCCESS); + } + + +/************************************************************************/ +/* list_add_first */ +/* Primitive to add a node as the first node of a circular double */ +/* linked list */ +/************************************************************************/ + +ST_RET list_add_first (DBL_LNK **list_head_ptr, DBL_LNK *node_ptr) + { +DBL_LNK *list_tail_ptr; + +#ifdef DEBUG_SISCO + if (node_ptr == NULL) + { + SLOGALWAYS0 ("GENLIST: ATTEMPT TO ADD A NULL ADDRESS TO A LIST"); + return (SD_FAILURE); + } +#endif + +/* If list checking is enabled and we get to here we have valid */ +/* arguments */ + + if (*list_head_ptr == NULL) /* will this be the only node? */ + { + node_ptr->next = node_ptr; + node_ptr->prev = node_ptr; + } + else + { + list_tail_ptr = (*list_head_ptr)->prev; + node_ptr->next = *list_head_ptr; + node_ptr->prev = list_tail_ptr; + list_tail_ptr->next = node_ptr; + (*list_head_ptr)->prev = node_ptr; + } + *list_head_ptr = node_ptr; /* assign the new head of list */ + return (SD_SUCCESS); + + } + + +/************************************************************************/ +/* list_add_last */ +/* Primitive to add a node as the last node of a circular double */ +/* linked list */ +/************************************************************************/ + +ST_RET list_add_last (DBL_LNK **list_head_ptr, DBL_LNK *node_ptr) + { +DBL_LNK *list_tail_ptr; + +#ifdef DEBUG_SISCO + if (node_ptr == NULL) + { + SLOGALWAYS0 ("GENLIST: ATTEMPT TO ADD A NULL ADDRESS TO A LIST"); + return (SD_FAILURE); + } +#endif + +/* If list checking is enabled and we get to here we have valid */ +/* arguments */ + + if (*list_head_ptr == NULL) /* will this be the only node? */ + { + node_ptr->next = node_ptr; + node_ptr->prev = node_ptr; + *list_head_ptr = node_ptr; + } + else + { + list_tail_ptr = (*list_head_ptr)->prev; + list_tail_ptr->next = node_ptr; + node_ptr->prev = list_tail_ptr; + node_ptr->next = *list_head_ptr; + (*list_head_ptr)->prev = node_ptr; + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/* list_get_first */ +/* Primitive to unlink the first node out of the list and return it's */ +/* address */ +/************************************************************************/ + +#ifndef FASTLIST + +ST_VOID *list_get_first (DBL_LNK **list_head_ptr) + { +DBL_LNK *node_ptr; + + if (*list_head_ptr == NULL) + return (NULL); + + node_ptr = *list_head_ptr; + list_unlink (list_head_ptr, node_ptr); + return (node_ptr); + + } +#endif + +/************************************************************************/ +/* list_get_last */ +/* Primitive to unlink the last node out of the list and return it's */ +/* address */ +/************************************************************************/ + + +ST_VOID *list_get_last (DBL_LNK **list_head_ptr) + { +DBL_LNK *node_ptr; + + if (*list_head_ptr == NULL) + return (NULL); + + node_ptr = *list_head_ptr; + node_ptr = node_ptr->prev; + list_unlink (list_head_ptr, node_ptr); + return (node_ptr); + } + + +/************************************************************************/ +/* list_move_to_first */ +/* Primitive to unlink the first node out of the list and return it's */ +/* address */ +/************************************************************************/ + +ST_RET list_move_to_first (DBL_LNK **src_list_head_ptr, + DBL_LNK **dest_list_head_ptr, + DBL_LNK *node_ptr) + { +ST_RET ret_code; + + if (!(ret_code = list_unlink (src_list_head_ptr, node_ptr))) + { + list_add_first (dest_list_head_ptr, node_ptr); + } + return (ret_code); + } + +/************************************************************************/ +/* list_find_node */ +/* Primitive to verify that a node is in a list, returns SD_SUCCESS if it */ +/* is; SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET list_find_node (DBL_LNK *list_head_ptr, DBL_LNK *node_ptr) + { +DBL_LNK *temp_ptr; +DBL_LNK *list_tail_ptr; +ST_RET ret_code; + + if ((list_head_ptr == NULL) || (node_ptr == NULL)) + ret_code = SD_FAILURE; + else + { + temp_ptr = list_head_ptr; + list_tail_ptr = list_head_ptr->prev; + +/* search forward from the begining to the end of the list for our node */ + + while ((temp_ptr != list_tail_ptr) && (temp_ptr != node_ptr)) + { + temp_ptr = temp_ptr->next; + } + if (temp_ptr == node_ptr) + ret_code = SD_SUCCESS; + else + ret_code = SD_FAILURE; + } + return (ret_code); + } + + +/************************************************************************/ +/* list_print_links */ +/************************************************************************/ + +#if 0 + +ST_VOID list_print_links (DBL_LNK *list_head_ptr) + { +DBL_LNK *temp_ptr; +DBL_LNK *list_tail_ptr; +ST_INT i; + + i = 1; + if (list_head_ptr == NULL) + { + printf ("\nThe list is empty"); + } + else + { + temp_ptr = list_head_ptr; + list_tail_ptr = list_head_ptr->prev; + printf ("\npointer to the head of the list is: %lx",list_head_ptr); + printf ("\n"); + printf ("\npointer to node number %d is: %lx",i, temp_ptr); + printf ("\nnode number: next ptr is: %lx",temp_ptr->next); + printf ("\n prev ptr is: %lx",temp_ptr->prev); + while ((temp_ptr != list_tail_ptr)) + { + temp_ptr = temp_ptr->next; + i++; + printf ("\npointer to node number %d is: %lx",i, temp_ptr); + printf ("\nnode number: next ptr is: %lx",temp_ptr->next); + printf ("\n prev ptr is: %lx",temp_ptr->prev); + } + } + } +#endif + +/************************************************************************/ +/* list_add_node_after(list insert node prim) */ +/* Primitive to add a node to a list after the current node. This */ +/* function assumes that we are working with a non NIL list. SD_SUCCESS */ +/* is returned if the node gets added to the list; SD_FAILURE otherwise. */ +/************************************************************************/ + +ST_RET list_add_node_after (DBL_LNK *cur_node, DBL_LNK *new_node) + { +DBL_LNK *next_node; +ST_RET ret_val; + + ret_val = SD_FAILURE; + if (new_node == NULL) + { + SLOGALWAYS0 ("GENLIST: ATTEMPT TO ADD A NULL ADDRESS TO A LIST"); + } + else if (cur_node == NULL) + { + SLOGALWAYS0 ("GENLIST: ATTEMPT TO ADD A NODE TO A NULL LIST"); + } + else /* this is a good node and good predecessor */ + { + next_node = cur_node -> next; + new_node -> next = next_node; + new_node -> prev = cur_node; + next_node -> prev = new_node; + cur_node -> next = new_node; + ret_val = SD_SUCCESS; + } + return (ret_val); + } + +/************************************************************************/ +/* list_get_next */ +/* Primitive to get the node pointed to by the next component of the */ +/* current node. This function returns NULL if the list_head_ptr is */ +/* NULL, the address of the current node is NULL or the next node in the*/ +/* list is the list_head_ptr(the list has wrapped around). This */ +/* function is useful for traversing a doubly linked circular list */ +/* from begining to the end as if the list were NULL terminated. */ +/************************************************************************/ + +#ifndef FASTLIST + +ST_VOID *list_get_next (DBL_LNK *list_head_ptr, DBL_LNK *cur_node) + { +DBL_LNK *next_node = NULL; + + if (list_head_ptr == NULL) + { + SLOGALWAYS0 ("GENLIST: ATTEMPT TO REFERENCE A NULL LIST"); + } + else if (cur_node == NULL) + { + SLOGALWAYS0 ("GENLIST: ATTEMPT TO REFERENCE THROUGH A NULL PTR"); + } + else if (cur_node->next != list_head_ptr) + { + next_node = cur_node->next; + } + return (next_node); + } +#endif + +/************************************************************************/ +/* list_get_sizeof */ +/* Primitive to return the number of nodes in this generic list. */ +/************************************************************************/ + +ST_INT list_get_sizeof (DBL_LNK *list_head_ptr) + { +ST_INT count; +DBL_LNK *cur_node; + + count = 0; + cur_node = list_head_ptr; + + while (cur_node != NULL) + { + count ++; + cur_node = (DBL_LNK *) list_get_next (list_head_ptr, cur_node); + } + + return (count); + } + +/************************************************************************/ +/* list_find_prev */ +/* Primitive to find the node "before" the current node in the linked */ +/* list. This function returns NULL if the list_head_ptr is */ +/* NULL, the current node is NULL, or the current node */ +/* is the head of the linked list (i.e. does not wrap around). */ +/************************************************************************/ + +DBL_LNK *list_find_prev (DBL_LNK *list_head_ptr, DBL_LNK *cur_node) + { +DBL_LNK *prev_node = NULL; + + if (list_head_ptr == NULL) + { + SLOGALWAYS0 ("GENLIST: ATTEMPT TO REFERENCE A NULL LIST"); + } + else if (cur_node == NULL) + { + SLOGALWAYS0 ("GENLIST: ATTEMPT TO REFERENCE THROUGH A NULL PTR"); + } + else if (cur_node != list_head_ptr) + { + prev_node = cur_node->prev; + } + return (prev_node); + } + +/************************************************************************/ +/* list_find_last */ +/* Primitive to find the last node in the linked list and return it's */ +/* address. */ +/************************************************************************/ + +DBL_LNK *list_find_last (DBL_LNK *list_head_ptr) + { +DBL_LNK *last_node; + + if (list_head_ptr) + last_node = list_head_ptr->prev; + else + { /* head is NULL (i.e. list is empty) so last is NULL too. */ + last_node = NULL; + } + + return (last_node); + } + diff --git a/mmslib/util/gensock2.c b/mmslib/util/gensock2.c new file mode 100644 index 0000000..afc65d5 --- /dev/null +++ b/mmslib/util/gensock2.c @@ -0,0 +1,2814 @@ +/************************************************************************/ +/* SOFTWARE MODULE HEADER ***********************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2002 - 2008, All Rights Reserved */ +/* */ +/* MODULE NAME : gensock2.c */ +/* */ +/* MODULE DESCRIPTION : */ +/* general socket routines */ +/* */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 10/15/08 EJV 63 sockCheckForIdleConns CORR: don't close */ +/* listening socket. */ +/* 10/08/08 MDE 62 Allow variable len header, sockEventQueueFlush*/ +/* 10/06/08 JRB 61 Close socket on ANY _sockCheckRxData error */ +/* & remove sockClose calls in _sockRecv. */ +/* Del _sockCheckRxData call right after connect*/ +/* completes (almost never gets data). */ +/* 07/24/08 EJV 60 sockSelectResultProcess: check sockErrorDetected */ +/* Fix on 11/26/07 (Rev 1.59.1.0 branch). */ +/* 04/07/08 EJV 59 sockFree CORR: call sockTxQueueDestroy to */ +/* prevent memory leaks. */ +/* 02/27/08 EJV 58 sockEventGet: check before decrementing. */ +/* 01/29/08 EJV 57 Use S_FMT_PTR macro to log pointers. */ +/* sockInitCalling: added 2 return(SD_FAILURE). */ +/* 12/04/07 EJV 56 sockUsrFun: check if con secured. */ +/* Add sockCheckForIdleConns (SISCO KeepAlive). */ +/* 11/28/07 EJV 55 _WIN32: changed to Winsock version 2. */ +/* Added disconnectReason in few places. */ +/* Added sockDisconnReasonStr for slogging. */ +/* sockFree: reversed 'if' for more redability. */ +/* 02/21/08 EJV 54 sockGetRemAddrInfo: corr portOut casting for */ +/* 0x8000-0xFFFF ports. */ +/* 11/28/07 EJV 53 sockSelectResultProcess corr: added continue.*/ +/* sockClose: add pSock->hSock=INVALID_SOCKET; */ +/* 10/04/07 MDE 52 Tweaked LOGCFG_VALUE_GROUP/LOGCFGX_VALUE_MAP */ +/* 09/10/07 MDE 51 Added sockStartEx, log_disable */ +/* 02/28/07 MDE 50 Handle 'send' returning 0 (full pipe) */ +/* 02/08/07 JRB 49 Add sockEventPut, sockEventGet. */ +/* Repl uSockConnect with 2 separate pointers */ +/* uSockConnectInd, uSockConnectConf. */ +/* 02/06/07 JRB 48 Call _sockServiceDiscardSock ONLY from sockClose.*/ +/* Replace other ..DiscardSock calls w/ sockClose.*/ +/* 01/30/07 JRB 47 Fix crash in sockFree by simplifying threads */ +/* (eliminate Free thread & sockServiceFreeList).*/ +/* Call _sockServiceDiscardSock from sockClose. */ +/* Lock all access to sockList. */ +/* 01/15/07 JRB 46 Del gs_poll_mode flag & poll_mode arg to */ +/* sockStart (no longer supported). */ +/* 01/03/07 EJV 45 Rpl gensock2 mutexes with S_LOCK_UTIL_RESOURCES */ +/* to avoid potential deadlock in slogipc.c; */ +/* Del create/destroy calls for gensock2 mutexes*/ +/* 12/11/06 EJV 44 sockCreateWakeupSockets, _sockAllocSock: */ +/* chg nonblock_on from ST_LONG to int. */ +/* Needed on 64-bit UNIX, Linux systems. */ +/* 11/17/06 EJV 43 socket funs: added (int) cast, the HP-UX */ +/* ssize_t is long. */ +/* 11/06/06 EJV 42 Rem static from sockCtxList (extern in H). */ +/* 06/13/06 RKR 41 Incorporated porting changes */ +/* 04/14/06 JRB 40 Close xCallingSock, xCalledSock in sockEnd. */ +/* 02/17/06 EJV 39 __VMS: defined SOCK_OPTLEN and SOCK_ADDRLEN */ +/* in gensock2.h. */ +/* sockGetRemAddrInfo: chg len from ST_INT type */ +/* to SOCK_ADDRLEN. */ +/* 01/30/06 GLB 38 Integrated porting changes for VMS */ +/* 12/19/05 EJV 37 sockUsrFun: chg args. */ +/* 10/09/05 MDE 36 Changed connect errors NERR log to FLOW */ +/* 09/28/05 EJV 35 Implemented GEN_SOCK_CTXT & other changes: */ +/* Moved filio.h for sun to sysincs.h. */ +/* Moved MUTEX macros from gensock2.h & renamed.*/ +/* sockStart, sockEnd, _sockAddServiceThread: */ +/* add cleanup code. */ +/* _sockAddSock: chg return to ST_RET. */ +/* Added handling when _sockAddSock fails. */ +/* Protect all numActive operations. */ +/* sockInitFds: mv init code out, for non-thread*/ +/* 07/18/05 EJV 34 sockSelectResultProcess: corr UNIX,LINUX,QNX */ +/* check if socket connection successful. */ +/* 07/11/05 EJV 33 Added convertIPAddr. */ +/* 07/05/05 EJV 32 sockInitCalling, sockInitListen, _sockAccept:*/ +/* close hSock if hSock >= FD_SETSIZE */ +/* 06/17/05 EJV 31 sockTx: clearer log. */ +/* 06/10/05 JRB 30 "_sockClose" deleted. Use "sockClose". */ +/* Don't close listen socket on accept error. */ +/* 05/23/05 EJV 29 Add sockLogMaskMapCtrl for parsing logcfg.xml*/ +/* Moved sock_debug_sel from slog.c. */ +/* 05/12/05 EJV 28 MMSEASE_MOSI:listenSocket=NULL GS_ROLE_CALLED*/ +/* 05/10/05 EJV Exposed _sockAllocSock, _sockAddSock protos. */ +/* sockServiceWake: chg NERR to FLOW log. */ +/* 05/04/05 MDE 27 Changed recv NERR log to FLOW */ +/* 05/04/05 EJV 26 Corr sockGetRemAddrInfo (chg peer to pp) */ +/* 05/03/05 MDE 25 OK to get EINPROGRESS & EINTR in select */ +/* 04/15/05 ASK 24 Signed/unsigned warning cleanup. Comment chg.*/ +/* 03/23/05 EJV 23 Exposed sockCreateWakeupSockets. */ +/* 03/16/05 JRB 22 Disconnect socket if uSockHunt returns */ +/* GENSOCK_HUNT_DISCONNECT. */ +/* 02/14/05 MDE 21 _sockRecv now looks for SOCK_INPROGRESS too */ +/* 02/10/05 MDE 20 Added sockGetRemAddrInfo */ +/* 02/02/05 MDE 37 Allow header only receive (empty body) */ +/* 12/20/04 ASK 36 Change gs_wakeup_port to 55050. */ +/* _sockCreateWakeupSockets: try up to 100 ports*/ +/* in range. Change XSocket logs to ERR. */ +/* 09/22/04 JRB 35 Change "..Connect Failed.." logs to NERR. */ +/* Change "expected" select err log to FLOW. */ +/* 08/12/04 EJV 34 sockInitFds corr: do not use FD_SET directly!*/ +/* 07/22/04 EJV 33 Added filio.h for sun. */ +/* Moved _gUsrCount up (out of define). */ +/* 06/21/04 EJV 32 sockInitListen: chg to return errno. */ +/* 05/21/04 MDE 31 Added user count _gUsrCount */ +/* 05/20/04 EJV 30 Log port number when unable to bind. */ +/* 05/17/04 MDE 29 Removed send assert forcing data buffer to */ +/* be allocated as part of GEN_SOCK_DATA */ +/* 05/03/04 ASK 28 Log errno when unable to send */ +/* 04/09/04 ASK 27 sockSelectResultProcess:log SOCK_INTR as NERR*/ +/* 04/22/04 MDE 26 Minor logging cleanup */ +/* 03/19/04 MDE 25 Added broken pipe handler for QNX */ +/* 03/04/04 ASK 24 Switched code in _sockClose. */ +/* 02/26/04 EJV 23 Switched code in sockClose. */ +/* Use SOCK_OPTLEN and SOCK_ADDRLEN. */ +/* 01/30/04 EJV 22 sockSelectResultProcess: fix previous change.*/ +/* 01/27/04 EJV 21 sockSelectResultProcess: chg log to NERR. */ +/* 01/23/04 EJV 20 sockLogState: added locking semaphore. */ +/* sockTxQueueAdd: free the sockData if error. */ +/* 01/22/04 EJV 19 Replaced time() calls with sGetMsTime(). */ +/* 01/12/04 ASK 18 Don't use socket if closed in _sockAccept. */ +/* Add log msg if select() fails. */ +/* Sleep for a second if select() fails. */ +/* EJV Moved sock_debug_sel to slog.c */ +/* Add sockTxQueuedGroupCnt update. */ +/* Add sockTxQueueGroupCntGet func. */ +/* 11/04/03 JRB 17 Replace gs_sleep calls with sMsSleep. */ +/* 07/07/03 JRB 16 Fix some log macros. */ +/* 06/25/03 JRB 15 Chg log macros. Chg FLOW log to ERR. */ +/* 06/23/03 EJV 14 Added 'first' param to sockTxQueueAdd. */ +/* 06/23/03 ASK 13 Set rc to SD_SUCCESS in sockTxQueueProc */ +/* 06/20/03 EJV 12 Added sockTxQueueDestroy. Log conn errors. */ +/* 06/19/03 EJV 11 Chg some logs. Chg gSock to pSock in funs. */ +/* Moved pSock->sockStats.numSend. */ +/* 06/19/03 JRB 10 Make Rx/Tx names more consistent. */ +/* 06/19/03 JRB 09 Fix ioctlsocket calls chging to non-blocking */ +/* mode (last arg must point to non-zero ulong).*/ +/* 06/18/03 JRB 08 Chk FD_SETSIZE if !(_WIN32). */ +/* Add sockInitAllFds. */ +/* Add sockTxMsg, sockTxQueue*: these */ +/* use new txMutex & uSockTxBufFree func ptr. */ +/* Set REUSEADDR option only on listen socket. */ +/* Init totalfds,selectnfds=0 in sockInitFds. */ +/* Chg some logging. Fix some ";". */ +/* Chk for SOCK_INPROGRESS too. */ +/* 06/03/03 MDE 07 More user poll featuresAdded sockGetFds */ +/* 06/02/03 ASK 06 _sockRecv(): Log err before calling sockClose*/ +/* 05/28/03 JRB 05 Fix setting of timeout for select call. */ +/* Del unused code. */ +/* 05/14/03 MDE 04 Added sockGetFds */ +/* 05/09/03 JRB 03 Don't use SOCKET_ERROR (only defined on WIN32)*/ +/* 04/07/03 EJV 02 Preset sock_debug_sel to SOCK_LOG_ERR */ +/* 02/17/03 MDE 01 Created */ +/************************************************************************/ + +#include "string.h" + +#include "gensock2.h" +/*renxiaobao add*/ +#ifndef WIN32 +#include + +extern struct hostent *gethostbyname(const char *name); +#endif + + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* Global logging variables */ + +#define GENSOCK_MAX_HEADER_SIZE 500 + +ST_UINT sock_debug_sel; /* init in sockStart() */ + +#ifdef DEBUG_SISCO +LOGCFGX_VALUE_MAP sockLogMaskMaps[] = + { + {"SOCK_LOG_ERR", SOCK_LOG_ERR, &sock_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Error"}, + {"SOCK_LOG_NERR", SOCK_LOG_NERR, &sock_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Notice"}, + {"SOCK_LOG_FLOW", SOCK_LOG_FLOW, &sock_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Flow"}, + {"SOCK_LOG_RX", SOCK_LOG_RX, &sock_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Receive"}, + {"SOCK_LOG_TX", SOCK_LOG_TX, &sock_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Transmit"} + }; + +LOGCFG_VALUE_GROUP sockLogMaskMapCtrl = + { + {NULL,NULL}, + "SocketLogMasks", /* Parent Tag */ + sizeof(sockLogMaskMaps)/sizeof(LOGCFGX_VALUE_MAP), + sockLogMaskMaps + }; +#endif /* DEBUG_SISCO */ + +SD_CONST ST_CHAR *SD_CONST SOCK_LOG_FLOW_TEXT = "SOCK_LOG_FLOW"; +SD_CONST ST_CHAR *SD_CONST SOCK_LOG_NERR_TEXT = "SOCK_LOG_NERR"; +SD_CONST ST_CHAR *SD_CONST SOCK_LOG_ERR_TEXT = "SOCK_LOG_ERR"; +SD_CONST ST_CHAR *SD_CONST SOCK_LOG_RX_TEXT = "SOCK_LOG_RX"; +SD_CONST ST_CHAR *SD_CONST SOCK_LOG_TX_TEXT = "SOCK_LOG_TX"; + + +/************************************************************************/ +/* variables */ +GEN_SOCK_CTXT *sockCtxList; + +/* disconnectReason strings for logging */ +ST_CHAR *sockDisconnReasonStr[] = + { + "DISCONNECT REASON: UNKNOWN", /* 0 */ + "DISCONNECT REASON: CONNECT_FAILED", /* 1 */ + "DISCONNECT REASON: USR_REFUSED", /* 2 */ + "DISCONNECT REASON: SEND_FAILURE", /* 3 */ + "DISCONNECT REASON: RECV_FAILED", /* 4 */ + "DISCONNECT REASON: ACCEPT_FAILED", /* 5 */ + "DISCONNECT REASON: SOCKET CLOSED", /* 6 */ + "DISCONNECT REASON: TERMINATING", /* 7 */ + "DISCONNECT REASON: RESOURCES_ERROR", /* 8 */ + "DISCONNECT REASON: INTERNAL_ERROR", /* 9 */ + "DISCONNECT REASON: NORMAL_DISCONNECT", /* 10 */ + /* disconnectReason for SSL connection */ + "DISCONNECT REASON: SSLE_LICENSE", /* 11 */ + "DISCONNECT REASON: SSLE_INT_ERR", /* 12 */ + "DISCONNECT REASON: REKEY_FAILED", /* 13 */ + "DISCONNECT REASON: CERT_VERIFY_ERR", /* 14 */ + "DISCONNECT REASON: CERT_ON_CRL", /* 15 */ + "DISCONNECT REASON: SEC_PARAM_ERR", /* 16 */ + }; + +ST_INT sockDisconnReasonStrCnt = sizeof (sockDisconnReasonStr)/sizeof (ST_CHAR *); + +/************************************************************************/ +/* Static functions and macros */ + +#if defined(GENSOCK_THREAD_SUPPORT) + static ST_THREAD_RET ST_THREAD_CALL_CONV _sockServiceThread (ST_THREAD_ARG pArg); + static ST_RET _sockAddServiceThread (GEN_SOCK_CTRL *serviceCtrl); +#endif + + +static GEN_SOCK_CTRL *_sockAddServiceCtrl (GEN_SOCK_CTXT *sockCtx); +static ST_RET _sockAccept (GEN_SOCK *pListenSock); +static ST_INT _sockCheckRxData (GEN_SOCK *pSock); +static ST_VOID _sockServiceDiscardSock (GEN_SOCK_CTRL *serviceCtrl, GEN_SOCK *pSock); + + + +/************************************************************************/ +/* sockStart */ +/* This function initializes the gensock2 for use in new context and */ +/* sets the sockCtxOut pointer if the initialization is successful. */ +/* Returns: */ +/* SD_SUCCESS (0) context initialized */ +/* SD_FAILURE otherwise */ +/************************************************************************/ + +ST_RET sockStart (ST_CHAR *ctxName, GEN_SOCK_CTXT **sockCtxOut) + { +ST_RET rc; + + rc = sockStartEx (ctxName, sockCtxOut, SD_FALSE); + return (rc); + } + + +ST_RET sockStartEx (ST_CHAR *ctxName, GEN_SOCK_CTXT **sockCtxOut, ST_BOOLEAN log_disable) + { +static ST_UINT ctxId = 0; +GEN_SOCK_CTXT *sockCtx = NULL; +GEN_SOCK_CTRL *serviceCtrl = NULL; +ST_RET rc = SD_SUCCESS; + + if (ctxId == 0) + { + /* do not put any logging above */ + #if DEBUG_SISCO + sock_debug_sel |= SOCK_LOG_ERR; + #endif + + #ifdef _WIN32 + { + ST_INT wRet; + WSADATA wsaData; /* WinSock data */ + /* init WinSock interface */ + if (wRet = WSAStartup(0x0202, &wsaData)) + { + SOCK_LOG_ERR2 (sockCtx, "Can't initialize WinSock interface to use version 2.2 (error=%d) for context '%s'", + (ctxName ? ctxName : ""), wRet); + return (SD_FAILURE); + } + } + #else /* UNIX,... */ + signal (SIGPIPE, SIG_IGN); + #endif + + ++ctxId; + } /* if firstTime */ + + sockCtx = (GEN_SOCK_CTXT *)chk_calloc (1, sizeof (GEN_SOCK_CTXT)); + sockCtx->log_disable = log_disable; + sockCtx->ctxId = ctxId++; + sprintf(sockCtx->ctxName, "%s(ctxId=%u)", (ctxName ? ctxName : ""), sockCtx->ctxId); + #if defined(GENSOCK_THREAD_SUPPORT) + sockCtx->gs_select_timeout = 100000; /* 10 seconds */ + sockCtx->gs_wakeup_port = 55050; /* up to 100 ports will be tried starting with this one */ + /* already false + sockCtx->gTerminateService = SD_FALSE; + sockCtx->gTerminateFree = SD_FALSE; + */ + #endif /* defined(GENSOCK_THREAD_SUPPORT) */ + + SOCK_LOG_FLOW1 (sockCtx, "%s: sockStart() initialization pending...", sockCtx->ctxName); + + /* Start with one service control */ + serviceCtrl = _sockAddServiceCtrl (sockCtx); + + /*printf("GENSOCK_THREAD_SUPPORT...\n");*/ + + #if defined(GENSOCK_THREAD_SUPPORT) + /* Start the service control thread */ + //printf("_sockAddServiceThread 1...\n"); + rc = _sockAddServiceThread (serviceCtrl); + if (rc != SD_SUCCESS) + { + S_LOCK_UTIL_RESOURCES (); + list_unlink (&sockCtx->sockServiceList, serviceCtrl); + S_UNLOCK_UTIL_RESOURCES (); + chk_free (serviceCtrl); + chk_free (sockCtx); + return (rc); + } + #endif + + S_LOCK_UTIL_RESOURCES (); + list_add_last (&sockCtxList, sockCtx); + S_UNLOCK_UTIL_RESOURCES (); + + SOCK_LOG_FLOW1 (sockCtx, "%s: sockStart() successful", sockCtx->ctxName); + *sockCtxOut = sockCtx; + + return (rc); + } + +/************************************************************************/ +/* sockEnd */ +/* This function cleans up all resources aquired by the sockCtx and */ +/* removes the sockCtx from the list. */ +/* All context specific threads need to terminate before this function */ +/* will return. */ +/* Returns: */ +/* SD_SUCCESS (0) context released */ +/* SD_FAILURE otherwise */ +/************************************************************************/ + +#if defined(_WIN32) + #define MAX_THREAD_END_WAIT INFINITE +#else /* UNIX, Linux,... */ + #define MAX_THREAD_END_WAIT -1 /* gs_thread_wait ignores this param (waits indefinitely) */ +#endif + + +ST_RET sockEnd (GEN_SOCK_CTXT *sockCtx) + { +GEN_SOCK_CTRL *serviceCtrl; +#if !defined(GENSOCK_THREAD_SUPPORT) +GEN_SOCK *pSock; +#endif +#if defined(GENSOCK_THREAD_SUPPORT) +ST_RET rc; +#endif + + SOCK_LOG_FLOW1 (sockCtx, "%s: sockEnd() pending...", sockCtx->ctxName); + + sockCtx->ctxStatus = GEN_SOCK_CTX_TERMINATING; /* prevent adding new sockets to serviceCtrl(s) */ + +/* First let's terminate terminate all service threads and the free thread */ +#if defined(GENSOCK_THREAD_SUPPORT) + /* Set flag for service threads to terminate, then wake them */ + sockCtx->gTerminateService = SD_TRUE; + sockServiceWakeAll (sockCtx); + + /* Wait for all service threads to terminate */ + serviceCtrl = sockCtx->sockServiceList; + while (serviceCtrl != NULL) + { + if (serviceCtrl->tIdService) + { + rc = gs_wait_thread (serviceCtrl->thService, serviceCtrl->tIdService, MAX_THREAD_END_WAIT); + rc = gs_close_thread (serviceCtrl->thService); + serviceCtrl->tIdService = 0; + } + S_LOCK_UTIL_RESOURCES (); + list_unlink (&sockCtx->sockServiceList, serviceCtrl); + S_UNLOCK_UTIL_RESOURCES (); + if (serviceCtrl->serviceEvent) + gs_free_event_sem (serviceCtrl->serviceEvent); + CLOSE_SOCKET (serviceCtrl->xCallingSock); + CLOSE_SOCKET (serviceCtrl->xCalledSock); + chk_free (serviceCtrl); + serviceCtrl = sockCtx->sockServiceList; /* remove from front */ + } + +#else /* !defined(GENSOCK_THREAD_SUPPORT) */ + /* Polled mode */ + /* Clean up the service controls */ + serviceCtrl = sockCtx->sockServiceList; + while (serviceCtrl != NULL) + { + /* Close all sockets associated with the service control */ + while (serviceCtrl->sockList) + { + pSock = serviceCtrl->sockList; + pSock->disconnectReason = GS_DISCONNECT_TERMINATING; + sockClose (pSock); + } + + list_unlink (&sockCtx->sockServiceList, serviceCtrl); + chk_free (serviceCtrl); + serviceCtrl = sockCtx->sockServiceList; /* remove from front */ + } +#endif /* !defined(GENSOCK_THREAD_SUPPORT) */ + + SOCK_LOG_FLOW1 (sockCtx, "%s: sockEnd() complete", sockCtx->ctxName); + + /* delete the context */ + S_LOCK_UTIL_RESOURCES (); + list_unlink (&sockCtxList, sockCtx); + S_UNLOCK_UTIL_RESOURCES (); + chk_free (sockCtx); + + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* sockInitCalling */ +/************************************************************************/ + +ST_RET sockInitCalling (GEN_SOCK_CTXT *sockCtx, GEN_SOCK_CONFIG *sockCfg, + ST_UINT16 portNo, ST_CHAR *ipAddr, + GEN_SOCK **pSockOut) + { +GEN_SOCK *pSock; +SOCKET hSock; +struct hostent *pHost; +int sRet; +ST_RET rc; +int err; + + SOCK_LOG_FLOW2 (sockCtx, "in sockInitCalling() to ipAddr=%s portNo=%u", + ipAddr, (ST_UINT) portNo); + + if (sockCtx->ctxStatus == GEN_SOCK_CTX_TERMINATING) + { + /* prevent adding new sockets to serviceCtrl */ + SOCK_LOG_NERR1 (sockCtx, "sockInitCalling failed in context '%s' is terminating", sockCtx->ctxName); + return (SD_FAILURE); + } + + hSock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (hSock == INVALID_SOCKET) + { + err = SOCKET_ERRORNO; + SOCK_LOG_ERR1 (sockCtx, "socket() returned INVALID_SOCKET, errno=%d.", err); + return (err); + } +#if !defined(_WIN32) + if (hSock >= FD_SETSIZE) + { /* Can't use this socket because illegal to use in "select" call*/ + SOCK_LOG_ERR1 (sockCtx, "Socket: socket num %d >= FD_SETSIZE (can not be used in select)," + " closing socket.", hSock); + CLOSE_SOCKET (hSock); + return (SD_FAILURE); + } +#endif + + pSock = _sockAllocSock (sockCtx, GS_ROLE_CALLING, GS_STATE_CONNECTING, hSock, sockCfg); + SOCK_LOG_FLOW1 (sockCtx, "%s: socket initialized", pSock->sockIdStr); + *pSockOut = pSock; + +/* Set up the socket address */ + if (strchr(ipAddr, '.') != NULL) /* dotted address format */ + { + pSock->sockAddrIn.sin_family = AF_INET; + pSock->sockAddrIn.sin_addr.s_addr = inet_addr (ipAddr); + } + else /* host address format, get dotted address */ + { + pHost = gethostbyname (ipAddr); + if (pHost == NULL) + { + err = SOCKET_ERRORNO; + SOCK_LOG_NERR2 (sockCtx, "%s: gethostbyname() failed for host='%s'", pSock->sockIdStr, ipAddr); + CLOSE_SOCKET (pSock->hSock); + chk_free (pSock); + return (err); + } + pSock->sockAddrIn.sin_family = pHost->h_addrtype; + pSock->sockAddrIn.sin_addr.s_addr = ((struct in_addr *)(pHost->h_addr))->s_addr; + } + pSock->sockAddrIn.sin_port = htons (portNo); + +/* Do non-blocking connect */ + sRet = connect (pSock->hSock, (struct sockaddr *)&pSock->sockAddrIn, + sizeof(pSock->sockAddrIn)); + if (sRet >= 0) + { + /* DEBUG: This code probably never executes because socket is non-blocking. */ + SOCK_LOG_FLOW1 (sockCtx, "%s: socket connected", pSock->sockIdStr); + pSock->sockState = GS_STATE_CONNECTED; + pSock->sockStats.activeTime = time (NULL); + + /* add new socket to service list and then call uSockConnect fun, */ + /* the sockAddSock may start new thread that will receive data before */ + /* the uSockConnect is called, LOCK is needed to prevent this scenario */ + S_LOCK_UTIL_RESOURCES (); + rc = _sockAddSock (pSock); /* Add to a service list */ + if (rc == SD_SUCCESS) + { + if (pSock->sockCfg.secConnectProc == NULL) + rc = (*pSock->sockCfg.uSockConnectConf)(pSock); + else + rc = (*pSock->sockCfg.secConnectProc)(pSock); + if (rc != SD_SUCCESS) + { + /* user does not want this connection */ + pSock->usrCloseCalled = SD_TRUE; /* don't call uSockDisconnect */ + sockClose (pSock); + sockFree (pSock); + /* DEBUG EJV: added this return, otherwise SD_SUCCESS was returned */ + return (SD_FAILURE); + } + } + else + { + SOCK_LOG_FLOW1 (sockCtx, "%s: closing socket connections", pSock->sockIdStr); + CLOSE_SOCKET (pSock->hSock); + chk_free (pSock); + /* DEBUG EJV: added this return, otherwise SD_SUCCESS was returned */ + return (SD_FAILURE); + } + S_UNLOCK_UTIL_RESOURCES (); + } + else + { + err = SOCKET_ERRORNO; + if (err == SOCK_WOULDBLOCK || err == SOCK_INPROGRESS) + { + rc = _sockAddSock (pSock); /* Add to a service list */ + if (rc != SD_SUCCESS) + { + /* since socket is not connected we can use the system socket close */ + CLOSE_SOCKET (pSock->hSock); + chk_free (pSock); + return (SD_FAILURE); + } + } + else + { + SOCK_LOG_NERR4 (sockCtx, "%s: connect() to host=%s failed, port=%d, errno=%d", + pSock->sockIdStr, ipAddr, portNo, err); + CLOSE_SOCKET (pSock->hSock); + chk_free (pSock); + return (SD_FAILURE); + } + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* sockInitListen */ +/* Returns: */ +/* SD_SUCCESS (0) listen socket initialized */ +/* SD_FAILURE or errno otherwise */ +/************************************************************************/ +ST_RET sockInitListen (GEN_SOCK_CTXT *sockCtx, GEN_SOCK_CONFIG *sockCfg, + ST_UINT16 portNo, ST_INT maxActive, + GEN_SOCK **pListenSockOut) + { +ST_RET rc; +GEN_SOCK *pListenSock; +ST_INT listenBacklog; +int sRet; +SOCKET hSock; +struct sockaddr_in localAddr; +int err; + +int sockopt_on = 1; +int keep_idle,keep_interval,keep_count; +struct timeval TimeOut; + + + if (sockCtx->ctxStatus == GEN_SOCK_CTX_TERMINATING) + { + /* prevent adding new sockets to serviceCtrl */ + SOCK_LOG_NERR1 (sockCtx, "%s: sockInitListen() failed, context is terminating", sockCtx->ctxName); + return (SD_FAILURE); + } + + hSock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (hSock == INVALID_SOCKET) + { + err = SOCKET_ERRORNO; + SOCK_LOG_ERR2 (sockCtx, "%s: socket() failed for listen socket, errno=%d", sockCtx->ctxName, err); + return (err); + } + + /* renxiaobao ÍøÂç´æ»îʱ¼ä */ + sockopt_on = 1; /* ÊÇ·ñÆôÓÃKEEPALIVE */ + keep_idle = 30; /* µ±Ã»ÓÐÊý¾Ý°ü´«Êäºó£¬µÈ¶àÉÙÃ뿪ʼKEEPALIVE */ + keep_interval = 5; /* ·¢ËÍKEEPALIVE°üµÄʱ¼ä¼ä¸ô */ + keep_count = 5; /* Á¬Ðø¶àÉÙ¸öKEEPALIVE°üûӦ´ð¾Í¶Ï¿ªTCPÁ¬½Ó */ + if(setsockopt (hSock, SOL_SOCKET, SO_KEEPALIVE,(char *) &sockopt_on, sizeof (int))) + { + printf ("Error setting KEEPALIVE socket option"); + } +#if defined(linux) ||defined(VXWORKS) + if(setsockopt(hSock, IPPROTO_TCP, TCP_KEEPIDLE, (char *)&keep_idle, sizeof(int))) /* IPPROTO_TCP »ò SOL_TCP*/ + { + printf ("Error setting KEEPIDLE socket option"); + } + if(setsockopt(hSock, IPPROTO_TCP, TCP_KEEPCNT, (char *)&keep_count, sizeof(int))) + { + printf ("Error setting KEEPCNT socket option"); + } + if(setsockopt(hSock, IPPROTO_TCP, TCP_KEEPINTVL,(char *)&keep_interval, sizeof(int))) + { + printf ("Error setting KEEPINTVL socket option"); + } +#endif + +#if !defined(_WIN32) + if (hSock >= FD_SETSIZE) + { /* Can't use this socket because illegal to use in "select" call*/ + SOCK_LOG_ERR2 (sockCtx, "%s: socket() returned socket num %d >= FD_SETSIZE " + "(can not be used in select), closing socket.", sockCtx->ctxName, hSock); + CLOSE_SOCKET (hSock); + return (SD_FAILURE); + } +#endif + + pListenSock = _sockAllocSock (sockCtx, GS_ROLE_LISTENING, GS_STATE_LISTENING, + hSock, sockCfg); + SOCK_LOG_FLOW1 (sockCtx, "%s: initializing listen socket", pListenSock->sockIdStr); + *pListenSockOut = pListenSock; + pListenSock->maxActive = maxActive; + + memset((char *)(&localAddr), 0, sizeof(localAddr)); + localAddr.sin_family = AF_INET; + localAddr.sin_port = htons(portNo); + localAddr.sin_addr.s_addr = htonl (INADDR_ANY); + sRet = bind (pListenSock->hSock, (struct sockaddr *)&localAddr, sizeof(localAddr)); + if (sRet != 0) + { + err = SOCKET_ERRORNO; + SOCK_LOG_NERR4 (sockCtx, "%s: listen socket bind() error on port=%u, errno=%d %s", + pListenSock->sockIdStr, (ST_UINT) portNo, err, + (err == SOCK_EADDRINUSE) ? "(port in use)" : " "); + CLOSE_SOCKET (pListenSock->hSock); + chk_free (pListenSock); + return (err); + } + SOCK_LOG_FLOW1 (sockCtx, "%s: listen socket bind() OK", pListenSock->sockIdStr); + + if (pListenSock->sockCfg.listenBacklog == 0) + listenBacklog = SOMAXCONN; + else + listenBacklog = pListenSock->sockCfg.listenBacklog; + + sRet = listen (pListenSock->hSock, listenBacklog); + if (sRet != 0) + { + err = SOCKET_ERRORNO; + SOCK_LOG_NERR2 (sockCtx, "%s: listen() failed, errno=%d", pListenSock->sockIdStr, err); + CLOSE_SOCKET (pListenSock->hSock); + chk_free (pListenSock); + return (err); + } + + /* Add to a service list */ + rc = _sockAddSock (pListenSock); + if (rc != SD_SUCCESS) + { + CLOSE_SOCKET (pListenSock->hSock); + chk_free (pListenSock); + } + else + SOCK_LOG_FLOW2 (sockCtx, "%s: listen started on port=%d", pListenSock->sockIdStr, portNo); + + return (rc); + } + +/************************************************************************/ +/* sockTxMsg */ +/* Send complete message. Some data may be queued for later delivery. */ +/* "sockTxQueueProc" must be called periodically to send any data that */ +/* has been queued up. */ +/************************************************************************/ +ST_RET sockTxMsg (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData) + { +ST_RET retVal; + + retVal = sockTxQueueAdd (pSock, sockData, SD_FALSE); /* queue data */ + if (retVal==SD_SUCCESS) + retVal = sockTxQueueProc (pSock); /* send what we can from queue */ + return (retVal); + } + +/************************************************************************/ +/* sockTxQueueAdd */ +/* Queue data for later delivery. */ +/* "sockTxQueueProc" must be called periodically to send any data that */ +/* has been queued up. */ +/************************************************************************/ +ST_RET sockTxQueueAdd (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData, ST_BOOLEAN first) + { +GEN_SOCK_CTXT *sockCtx; +ST_RET retVal; + + sockCtx = pSock->sockCtx; + +/* Put on our pending send list */ + + S_LOCK_UTIL_RESOURCES (); + if (first) + retVal = list_add_first (&pSock->sockTxPend, sockData); + else + retVal = list_add_last (&pSock->sockTxPend, sockData); + if (retVal == SD_SUCCESS) + { + if (sockData->eot) + ++pSock->sockTxQueueGroupCnt; + } + else + /* user expects that sockTxMsg will free the sockData buff in any case */ + (*pSock->sockCfg.uSockTxBufFree) (pSock, sockData); + S_UNLOCK_UTIL_RESOURCES (); + + return (retVal); + } + +/************************************************************************/ +/* sockTxQueueDestroy */ +/* Free all queued messages. */ +/************************************************************************/ +ST_RET sockTxQueueDestroy (GEN_SOCK *pSock) + { +GEN_SOCK_CTXT *sockCtx; +GEN_SOCK_DATA *sockData; + + sockCtx = pSock->sockCtx; + +/* Free all queued messages from list */ + S_LOCK_UTIL_RESOURCES (); + while (pSock->sockTxPend != NULL) + { + sockData = pSock->sockTxPend; + list_unlink (&pSock->sockTxPend, sockData); + (*pSock->sockCfg.uSockTxBufFree) (pSock, sockData); + } + pSock->sockTxQueueGroupCnt = 0; + S_UNLOCK_UTIL_RESOURCES (); + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sockTxQueueProc */ +/* Must be called periodically to send any data queued up by calls to */ +/* "sockTxQueueAdd". */ +/************************************************************************/ +ST_RET sockTxQueueProc (GEN_SOCK *pSock) + { +GEN_SOCK_CTXT *sockCtx; +GEN_SOCK_DATA *sockData; +ST_INT numSent; +ST_RET rc = SD_SUCCESS; + + sockCtx = pSock->sockCtx; + + S_LOCK_UTIL_RESOURCES (); + +/* Send as much data as possible */ + while (pSock->sockTxPend != NULL) + { + sockData = pSock->sockTxPend; + rc = sockTx (pSock, sockData, &numSent); + if (rc == SD_SUCCESS) + { + if (numSent == sockData->dataLen) + { + /* OK, we were able to send the rest of the buffer */ + ++pSock->sockStats.numSend; /* num of RFC1006 msgs sent */ + list_unlink (&pSock->sockTxPend, sockData); + if (sockData->eot) + { + if (pSock->sockTxQueueGroupCnt > 0 ) + --pSock->sockTxQueueGroupCnt; /* tx last msg from a group */ + else + SOCK_LOG_ERR1 (sockCtx, "%s: tx queue count invalid.", pSock->sockIdStr); + } + (*pSock->sockCfg.uSockTxBufFree) (pSock, sockData); + } + else + { + /*printf("numSent(%d) != sockData->dataLen(%d)\n",numSent , sockData->dataLen);*/ + /* Prepare for next send attempt */ + sockData->data += numSent; + sockData->dataLen -= numSent; + /* Stop trying to send */ + break; + } + } + else /* Send error */ + { + SOCK_LOG_NERRC1 (sockCtx, "%s: sockTx() failed, emptying send queue.", pSock->sockIdStr); + /* printf(sockCtx, "%s: sockTx() failed, emptying send queue.", pSock->sockIdStr);*/ + /* Free all queued send data ... */ + sockTxQueueDestroy (pSock); + break; + } + } + S_UNLOCK_UTIL_RESOURCES (); + return (rc); + } + +/************************************************************************/ +/* sockTxQueueGroupCntGet */ +/************************************************************************/ +ST_UINT sockTxQueueGroupCntGet (GEN_SOCK *pSock) + { +GEN_SOCK_CTXT *sockCtx; +ST_UINT queCnt; + + sockCtx = pSock->sockCtx; + + S_LOCK_UTIL_RESOURCES (); + queCnt = pSock->sockTxQueueGroupCnt; + S_UNLOCK_UTIL_RESOURCES (); + + return (queCnt); + } + +/************************************************************************/ +/************************************************************************/ +/* sockTx */ +/************************************************************************/ + +ST_RET sockTx (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData, ST_INT *numSentOut) + { +GEN_SOCK_CTXT *sockCtx; +ST_RET ret; + + sockCtx = pSock->sockCtx; + + if (pSock->sockState != GS_STATE_CONNECTED) + { + SOCK_LOG_NERR2 (sockCtx, "%s: sockTx() failed, socket not connected sockState=%d", + pSock->sockIdStr, pSock->sockState); + return (SD_FAILURE); + } + + if (pSock->sockCfg.secTxProc == NULL) + ret = _sockTx (pSock, sockData, numSentOut); + else + ret = (*pSock->sockCfg.secTxProc) (pSock, sockData, numSentOut); + + return (ret); + } + +/************************************************************************/ +/* _sockTx */ +/************************************************************************/ + +ST_RET _sockTx (GEN_SOCK *pSock, GEN_SOCK_DATA *sockData, ST_INT *numSentOut) + { +GEN_SOCK_CTXT *sockCtx; +ST_INT numSent; +ST_INT err; + + sockCtx = pSock->sockCtx; + +#ifdef SOCK_FLOW_PRINT /* DEBUG: enable this to see data flow. */ + printf ("|"); +#endif + SOCK_LOG_FLOW2 (sockCtx, "%s: _sockTx() request to send %d bytes", + pSock->sockIdStr, sockData->dataLen); + numSent = (ST_INT) send (pSock->hSock, sockData->data, sockData->dataLen, 0); + if (numSent >= 0) /* Success ? */ + { + SOCK_LOG_FLOWC3 (sockCtx, "%s: _sockTx() sent %d vs. %d requested", + pSock->sockIdStr, numSent, sockData->dataLen); + if (numSent < sockData->dataLen) + { + pSock->sockCfg.chkWritable = SD_TRUE; + sockServiceWake (pSock->serviceCtrl); + } + *numSentOut = numSent; + /* save the time of last successful data transfer activity on the socket */ + if (numSent > 0 && sockCtx->maxIdleTime > 0) + pSock->sockStats.lastActivityTime = sGetMsTime(); + return (SD_SUCCESS); + } + else + { + err = SOCKET_ERRORNO; + switch (err) + { + case SOCK_WOULDBLOCK: + case SOCK_NOBUFS: + case SOCK_INTR: + case SOCK_INPROGRESS: + case SOCK_TIMEDOUT: + SOCK_LOG_FLOWC2 (sockCtx, "%s: _sockTx sent 0, error (%d), no send buffers?", + pSock->sockIdStr, err); + pSock->sockCfg.chkWritable = SD_TRUE; + sockServiceWake (pSock->serviceCtrl); + *numSentOut = 0; + return (SD_SUCCESS); + break; + + default: + SOCK_LOG_NERR2 (sockCtx, "%s: socket send() error (%d)", pSock->sockIdStr, err); + break; + } + } + + S_LOCK_UTIL_RESOURCES (); + if (pSock->sockState == GS_STATE_CONNECTED) + { + pSock->disconnectReason = GS_DISCONNECT_SEND_FAILURE; + sockClose (pSock); /* Close and wake the service thread */ + } + S_UNLOCK_UTIL_RESOURCES (); + return (SD_FAILURE); + } + +/************************************************************************/ +/* sockClose */ +/************************************************************************/ + +ST_RET sockClose (GEN_SOCK *pSock) + { +GEN_SOCK_CTXT *sockCtx; + + + sockCtx = pSock->sockCtx; + SOCK_LOG_FLOW1 (sockCtx, "%s: in sockClose()", pSock->sockIdStr); + + S_LOCK_UTIL_RESOURCES (); + if (pSock->sockState != GS_STATE_CLOSED) + { + pSock->sockState = GS_STATE_CLOSED; + + /* On AIX the close() will not return until select() returns. */ + /* Wake the service thread (or terminate the select) */ + if (pSock->serviceCtrl) /* sockClose maybe called when serviceCtrl=NULL */ + sockServiceWake (pSock->serviceCtrl); + + CLOSE_SOCKET (pSock->hSock); + pSock->hSock = INVALID_SOCKET; /* make sure handle not used anymore */ + + /* Discard all events for this socket */ + sockEventQueueFlush (sockCtx, pSock); + + /* Done with this socket. Remove it from service list. */ + _sockServiceDiscardSock (pSock->serviceCtrl, pSock); + } + S_UNLOCK_UTIL_RESOURCES (); + return SD_SUCCESS; + } + +/************************************************************************/ +/* sockFree */ +/************************************************************************/ +/* Must be called after (or from) disconnect callback */ + +ST_RET sockFree (GEN_SOCK *pSock) + { +GEN_SOCK_CTXT *sockCtx; + + sockCtx = pSock->sockCtx; + SOCK_LOG_FLOW1 (sockCtx, "%s: in sockFree()", pSock->sockIdStr); + + if (pSock->sockState != GS_STATE_CLOSED) + { + SOCK_LOG_NERR1 (sockCtx, "%s: socket state not closed, can't free", pSock->sockIdStr); + return (SD_FAILURE); + } + + if (pSock->sockCfg.secSockFree != NULL) + (*pSock->sockCfg.secSockFree) (pSock); + + /* We can free this socket if: */ + /* 1. It is not a listen socket, or */ + /* 2. It is a listen socket with no called socket references */ + + /* protect numActive */ + S_LOCK_UTIL_RESOURCES (); + /* release any queued data buffers */ + sockTxQueueDestroy (pSock); + if (pSock->role == GS_ROLE_LISTENING && pSock->numActive != 0) + { + /* can happen when exiting */ + SOCK_LOG_NERR2 (sockCtx, "%s: Can't free listening GEN_SOCK " S_FMT_PTR " (pointer still in use)", + pSock->sockIdStr, pSock); + } + else + { + SOCK_LOG_FLOW2 (sockCtx, "%s: freeing GEN_SOCK " S_FMT_PTR ".", pSock->sockIdStr, pSock); + chk_free (pSock); + } + S_UNLOCK_UTIL_RESOURCES (); + return SD_SUCCESS; + } + +/************************************************************************/ +/* _sockAddServiceCtrl */ +/************************************************************************/ + +static GEN_SOCK_CTRL *_sockAddServiceCtrl (GEN_SOCK_CTXT *sockCtx) + { +GEN_SOCK_CTRL *serviceCtrl; + + serviceCtrl = (GEN_SOCK_CTRL *) chk_calloc (1, sizeof (GEN_SOCK_CTRL)); + serviceCtrl->sockCtx = sockCtx; + S_LOCK_UTIL_RESOURCES (); + list_add_last (&sockCtx->sockServiceList, serviceCtrl); + S_UNLOCK_UTIL_RESOURCES (); + return (serviceCtrl); + } + + +/************************************************************************/ +/* sockServiceWakeAll */ +/************************************************************************/ + +ST_VOID sockServiceWakeAll (GEN_SOCK_CTXT *sockCtx) + { +#if defined(GENSOCK_THREAD_SUPPORT) +GEN_SOCK_CTRL *serviceCtrl; + + serviceCtrl = sockCtx->sockServiceList; + while (serviceCtrl != NULL) + { + sockServiceWake (serviceCtrl); + serviceCtrl = (GEN_SOCK_CTRL *) list_get_next (sockCtx->sockServiceList, serviceCtrl); + } +#endif + } + +/************************************************************************/ +/* sockServiceWake */ +/************************************************************************/ + +ST_VOID sockServiceWake (GEN_SOCK_CTRL *serviceCtrl) + { +#if defined(GENSOCK_THREAD_SUPPORT) +GEN_SOCK_CTXT *sockCtx; +ST_INT numSent; +static ST_UCHAR wakeupData = 1; + + if (!serviceCtrl) + return; + sockCtx = serviceCtrl->sockCtx; + +/* Be sure it was not set NULL */ + if (serviceCtrl == NULL) + return; + + if (serviceCtrl->serviceEvent) + gs_signal_event_sem (serviceCtrl->serviceEvent); + if (serviceCtrl->xCalledSock == 0) + return; + +/* OK, there is a wakeup port for this sock service */ + numSent = (ST_INT) send (serviceCtrl->xCalledSock, &wakeupData, sizeof(wakeupData), 0); + if (numSent == sizeof (wakeupData)) + { + SOCK_LOG_FLOW2 (sockCtx, "%s: XSocket sent %d wakeup bytes", sockCtx->ctxName, numSent); + } + else + { + /* when a lot of packets are received in short time, EWOULDBLOCK and EAGAIN */ + /* errors could happen often with this 1-byte packets */ + SOCK_LOG_FLOW3 (sockCtx, "%s: XSocket wakeup data send() error, errno=%d", + sockCtx->ctxName, numSent, SOCKET_ERRORNO); + } + ++wakeupData; +#endif + } + + +/************************************************************************/ +/* sockCheckForIdleConns */ +/*----------------------------------------------------------------------*/ +/* Check for idle connections if the tcpMaxIdleTime >0. */ +/* Calling/called connections are closed if there is no activity tx/rx */ +/* for this period of time. The checking will be performed with the */ +/* frequency of 30 seconds. */ +/************************************************************************/ +#define GS_IDLE_CON_CHECK_FREQENCY ((ST_DOUBLE)(30*1000)) /* ms */ +float sock_sts_lastCheckTimer=0; +static ST_RET sockCheckForIdleConns (GEN_SOCK_CTRL *serviceCtrl) + { +ST_DOUBLE currTime; +ST_UINT maxIdleTime; +int index=0; +GEN_SOCK *pSock; +GEN_SOCK *pSockNext; +GEN_SOCK_CTXT *sockCtx; + + + if (!serviceCtrl || !serviceCtrl->sockCtx) + return (SD_FAILURE); + + + sockCtx = serviceCtrl->sockCtx; + maxIdleTime = sockCtx->maxIdleTime; + + + + if (maxIdleTime == 0) + /* user do not want to check for idle TCP connections */ + return (SD_SUCCESS); + + if (serviceCtrl->lastCheckIdleTime == 0) + { + /* starting, initialize the lastCheckedTime */ + serviceCtrl->lastCheckIdleTime = sGetMsTime (); + return (SD_SUCCESS); + } + currTime = sGetMsTime (); + if ((currTime - serviceCtrl->lastCheckIdleTime) < GS_IDLE_CON_CHECK_FREQENCY) + return (SD_SUCCESS); + + /* it is time to check the list of sockets for idle connections */ + S_LOCK_UTIL_RESOURCES (); /* CRITICAL: lock all access to sockList*/ + pSock = serviceCtrl->sockList; + while (pSock) + { + + + pSockNext = (GEN_SOCK *) list_get_next (serviceCtrl->sockList, pSock); + if (pSock->role != GS_ROLE_LISTENING) + { + if ((ST_UINT) (currTime - pSock->sockStats.lastActivityTime) >= maxIdleTime) + { + SOCK_LOG_NERR2 (sockCtx, "%s: closing idle socket, maxIdleTime=%u seconds reached.", + pSock->sockIdStr, maxIdleTime/1000); + printf("%s: closing idle socket, maxIdleTime=%u seconds reached.\r\n", + pSock->sockIdStr, maxIdleTime/1000); + sockClose (pSock); + } + } + pSock = pSockNext; + } + S_UNLOCK_UTIL_RESOURCES (); + + serviceCtrl->lastCheckIdleTime = currTime; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sockCtrlService */ +/************************************************************************/ +int sockCtrlService_pri=0; +int test_sockClose =0; /*test_sockClose=1;*/ +int ttt_t=0; +ST_INT sockCtrlService (GEN_SOCK_CTRL *serviceCtrl, ST_LONG timeOut) + { +GENSOCK_FD_SET sockFds; +struct timeval selectTimeout; +int nfds; +ST_INT retVal; +int index=0; +GEN_SOCK *pSock; +GEN_SOCK *pSockNext; + + /* CRITICAL: start with clean sockFds. */ + sockFds.totalfds = 0; + sockFds.selectnfds = 0; + sockFds.numReadfds = 0; + sockFds.numWritefds = 0; + sockFds.numExceptfds = 0; + FD_ZERO (&sockFds.readfds); + FD_ZERO (&sockFds.writefds); + FD_ZERO (&sockFds.exceptfds); + +/* Build the set of sockets to listen to */ + sockInitFds (serviceCtrl, &sockFds); + if (sockFds.totalfds == 0) + return (GS_SELECT_NO_ACTIVE_SOCK); + +/* Now wait for some activity */ + selectTimeout.tv_sec = timeOut / 1000; + selectTimeout.tv_usec = (timeOut % 1000) * 1000; + nfds = select (sockFds.selectnfds, &sockFds.readfds, &sockFds.writefds, &sockFds.exceptfds, &selectTimeout); + /*renxiaobao ²âÊÔ*/ + if((test_sockClose)||(nfds<0)) + { + test_sockClose=0; + S_LOCK_UTIL_RESOURCES (); + pSock = serviceCtrl->sockList; + while(pSock) + { + pSockNext=(GEN_SOCK *)list_get_next (serviceCtrl->sockList, pSock); + if(pSock->sockState!=GS_STATE_LISTENING) + { + SOCK_LOG_ERR3 (serviceCtrl->sockCtx, "sockClose(%d)(selectnfds=%d pSock->sockState=%d)", ++index,sockFds.selectnfds,pSock->sockState); + printf("sockClose(%d)(selectnfds=%d pSock->sockState=%d)\r\n", index,sockFds.selectnfds,pSock->sockState); + /* sockClose(pSock);*/ + } + pSock=pSockNext; + } + S_UNLOCK_UTIL_RESOURCES (); + serviceCtrl->lastCheckIdleTime=sGetMsTime (); + return (GS_SELECT_ERROR); + } + /*end*/ +if(sockCtrlService_pri) +{ + sockCtrlService_pri--; + printf("sockCtrlService nfds=%d %d timeOut=%d \r\n",nfds,serviceCtrl->sockList->sockState,timeOut); + index=0; + pSock = serviceCtrl->sockList; + while(pSock) + { + pSockNext=(GEN_SOCK *)list_get_next (serviceCtrl->sockList, pSock); + printf("sockState(%d)(pSock->sockState=%d)\r\n", index,pSock->sockState); + pSock=pSockNext; + } +} +/* +#define GS_STATE_LISTENING 1 +#define GS_STATE_STOPPING_LISTEN 2 +#define GS_STATE_FAILED_LISTEN 3 +#define GS_STATE_CONNECTING 4 +#define GS_STATE_CONNECTED 5 +#define GS_STATE_CLOSED 6 +*/ + +#if (defined(GENSOCK_THREAD_SUPPORT) && defined(__VMS)) + if (nfds > 0) + { + sys$cantim(10000, 0); /* that is sys$cantim(MICS_AST_WAITANYEVENT, 0); */ + sys$setef (101); /* that is sys$setef (MICS_FLAG_ACTIVITY) */ + } +#endif + +#if defined(GENSOCK_THREAD_SUPPORT) + { + GEN_SOCK_CTXT *sockCtx = serviceCtrl->sockCtx; +/* Make sure we are not supposed to terminate .. */ + if (sockCtx->gTerminateService == SD_TRUE) + return (GS_SELECT_TERMINATED); + } +#endif + + retVal = sockSelectResultProcess (serviceCtrl, nfds, &sockFds); + + /* check if there are idle sockets before we return */ + sockCheckForIdleConns (serviceCtrl); + + return (retVal); + } + + +#if !defined(GENSOCK_THREAD_SUPPORT) +/************************************************************************/ +/* sockInitAllFds */ +/* Initialize the GENSOCK_FD_SET struct for "all" sockets, so that */ +/* "select" call can include all sockets. */ +/* Assume there is only one entry on the linked list "sockCtx->sockServiceList" */ +/* and just use it. */ +/************************************************************************/ +ST_VOID sockInitAllFds (GENSOCK_FD_SET *sockFds) + { +GEN_SOCK_CTXT *sockCtx; + + + /* CRITICAL: start with clean sockFds. */ + sockFds->totalfds = 0; + sockFds->selectnfds = 0; + sockFds->numReadfds = 0; + sockFds->numWritefds = 0; + sockFds->numExceptfds = 0; + FD_ZERO (&sockFds->readfds); + FD_ZERO (&sockFds->writefds); + FD_ZERO (&sockFds->exceptfds); + + sockCtx = sockCtxList; + while (sockCtx) + { + assert (sockCtx->sockServiceList->l.next == (DBL_LNK *) sockCtx->sockServiceList); /* make sure only one on list*/ + sockInitFds (sockCtx->sockServiceList, sockFds); + + sockCtx = (GEN_SOCK_CTXT *)list_get_next (sockCtxList, sockCtx); + } + } +#endif /* !defined(GENSOCK_THREAD_SUPPORT) */ + +/************************************************************************/ +/* sockInitFds */ +/************************************************************************/ + +ST_VOID sockInitFds (GEN_SOCK_CTRL *serviceCtrl, GENSOCK_FD_SET *sockFds) + { +GEN_SOCK *pSock; +GEN_SOCK *pNextSock; +GEN_SOCK_CONFIG *sockCfg; +GEN_SOCK_CTXT *sockCtx; + + sockCtx = serviceCtrl->sockCtx; + +#if defined(GENSOCK_THREAD_SUPPORT) + if (serviceCtrl->xCallingSock) + sockAddReadFds (sockFds, serviceCtrl->xCallingSock); +#endif + + S_LOCK_UTIL_RESOURCES (); + pSock = serviceCtrl->sockList; + while (pSock) + { + pNextSock = (GEN_SOCK *) list_get_next (serviceCtrl->sockList, pSock); + + if (pSock->sockState == GS_STATE_CONNECTED) + { + sockCfg = &pSock->sockCfg; + if (sockCfg->pauseRecv == SD_FALSE) + sockAddReadFds (sockFds, pSock->hSock); + if (sockCfg->chkWritable) + sockAddWriteFds (sockFds, pSock->hSock); + } + else if (pSock->sockState == GS_STATE_CONNECTING) + { + sockAddWriteFds (sockFds, pSock->hSock); + sockAddExceptFds (sockFds, pSock->hSock); + } + else if (pSock->sockState == GS_STATE_LISTENING) + sockAddReadFds (sockFds, pSock->hSock); + + pSock = pNextSock; + } + S_UNLOCK_UTIL_RESOURCES (); + } + + +/************************************************************************/ +/* sockAddReadFds */ +/************************************************************************/ + +ST_VOID sockAddReadFds (GENSOCK_FD_SET *sockFds, SOCKET hSock) + { +#if !defined(_WIN32) + assert (hSock < FD_SETSIZE); /* FD_SET assumes this is true */ +#endif + FD_SET (hSock, &sockFds->readfds); + if ((hSock+1) > (sockFds->selectnfds)) + sockFds->selectnfds = (hSock+1); + + ++sockFds->numReadfds; + ++sockFds->totalfds; + } + +/************************************************************************/ +/* sockAddWriteFds */ +/************************************************************************/ + +ST_VOID sockAddWriteFds (GENSOCK_FD_SET *sockFds, SOCKET hSock) + { +#if !defined(_WIN32) + assert (hSock < FD_SETSIZE); /* FD_SET assumes this is true */ +#endif + FD_SET (hSock, &sockFds->writefds); + if ((hSock+1) > (sockFds->selectnfds)) + sockFds->selectnfds = (hSock+1); + + ++sockFds->numWritefds; + ++sockFds->totalfds; + } + +/************************************************************************/ +/* sockAddExceptFds */ +/************************************************************************/ + +ST_VOID sockAddExceptFds (GENSOCK_FD_SET *sockFds, SOCKET hSock) + { +#if !defined(_WIN32) + assert (hSock < FD_SETSIZE); /* FD_SET assumes this is true */ +#endif + FD_SET (hSock, &sockFds->exceptfds); + if ((hSock+1) > (sockFds->selectnfds)) + sockFds->selectnfds = (hSock+1); + + ++sockFds->numExceptfds; + ++sockFds->totalfds; + } + +/************************************************************************/ +/* sockSelectResultProcess */ +/* NOTE: this function closes the socket on any error. */ +/************************************************************************/ + +ST_INT sockSelectResultProcess (GEN_SOCK_CTRL *serviceCtrl, + int nfds, GENSOCK_FD_SET *sockFds) + { +GEN_SOCK_CTXT *sockCtx; +GEN_SOCK *pSock; +GEN_SOCK *pNextSock; +GEN_SOCK_CONFIG *sockCfg; +ST_RET rc; +ST_INT startState; +ST_INT err; +ST_RET sockErrorDetected; +#if defined(GENSOCK_THREAD_SUPPORT) +ST_CHAR bitBucket[100]; +ST_INT recvRet; +#endif + + sockCtx = serviceCtrl->sockCtx; + +/* Check for timeout */ + if (nfds == 0) + return (GS_SELECT_TIMEOUT); + +/* Check for error (may happen when sockets are closed while in select) */ + if (nfds < 0) + { + /* error */ + err = SOCKET_ERRORNO; + if (err == SOCK_INPROGRESS || err == SOCK_INTR) + return (GS_SELECT_ACTIVE); + +#if defined(GENSOCK_THREAD_SUPPORT) + + if ((err == SOCK_NOTSOCK || err == SOCK_INTR)) /* ? SOCK_INTR is above */ + /* If one or more sockets were closed by another thread, this error is expected.*/ + SOCK_LOG_FLOW2 (sockCtx, "%s: select() call failed." + " Expected if one or more sockets closed by another thread, errno=%d", + sockCtx->ctxName, err); + else + SOCK_LOG_ERR2 (sockCtx, "%s: select() call failed, errno=%d", sockCtx->ctxName, err); +#else + SOCK_LOG_ERR2 (sockCtx, "%s: select() call failed, errno=%d", sockCtx->ctxName, err); +#endif + return (GS_SELECT_ERROR); + } + + /* OK now we have got some data to read from at least one of the sockets */ + S_LOCK_UTIL_RESOURCES (); /* CRITICAL: lock all access to sockList*/ + pSock = serviceCtrl->sockList; + while (pSock && nfds > 0) + { + pNextSock = (GEN_SOCK *) list_get_next (serviceCtrl->sockList, pSock); + + sockErrorDetected = SD_FALSE; + sockCfg = &pSock->sockCfg; + + if (pSock->sockState == GS_STATE_CONNECTED) + { + /* Check for data or disconnect on this socket ... */ + if (FD_ISSET (pSock->hSock, &sockFds->readfds)) + { /* We have data or a disconnect */ + --nfds; + + startState = pSock->recvState; + if (_sockCheckRxData (pSock) != SD_SUCCESS) + sockErrorDetected = SD_TRUE; + } + + /* See if we are checking for writability too */ + if (!sockErrorDetected && sockCfg->chkWritable && FD_ISSET (pSock->hSock, &sockFds->writefds)) + { + SOCK_LOG_FLOW1 (sockCtx, "%s: socket is Writable", pSock->sockIdStr); + sockCfg->chkWritable = SD_FALSE; /* one-shot */ + if (sockCfg->secEnable == SD_FALSE) + (*sockCfg->uSockWritable)(pSock); + else + (*sockCfg->secWritable)(pSock); + } + } + else if (pSock->sockState == GS_STATE_CONNECTING) + { /* Check for activity on this socket ... */ + /* NOTE: On UNIX, LINUX, QNX the writefds is used to indicate that the */ + /* connection completed or failed. Must call the getsocketopt() */ + /* to check the connection status! */ + /* On Windows writefds set indicates successful connection */ + /* (exceptfds is used to indicate failed connection). */ + if (FD_ISSET (pSock->hSock, &sockFds->writefds)) + { +#if !defined(_WIN32) + SOCK_OPTLEN optlen; + ST_INT sRet; + ST_INT connError = 0; + + optlen = sizeof(connError); + sRet = getsockopt (pSock->hSock, SOL_SOCKET, SO_ERROR, (ST_CHAR *) &connError, &optlen); + if (sRet == 0) + { + if (connError != 0) + { + SOCK_LOG_FLOW2 (sockCtx, "%s: socket Connect failed. Error = %d", pSock->sockIdStr, connError); + pSock->disconnectReason = GS_DISCONNECT_CONNECT_FAILED; + sockErrorDetected = SD_TRUE; + } + } + else + { + SOCK_LOG_ERR2 (sockCtx, "%s: getsockopt(...,SOL_SOCKET, SO_ERROR,...) failed, errno=%d.", + pSock->sockIdStr, SOCKET_ERRORNO); + pSock->disconnectReason = GS_DISCONNECT_CONNECT_FAILED; + sockErrorDetected = SD_TRUE; + } +#endif /* !defined(_WIN32) */ + + --nfds; + + if (!sockErrorDetected) + { + SOCK_LOG_FLOW1 (sockCtx, "%s: socket connected", pSock->sockIdStr); + pSock->sockState = GS_STATE_CONNECTED; + pSock->sockStats.activeTime = time (NULL); + + if (sockCfg->secConnectProc == NULL) + rc = (*sockCfg->uSockConnectConf)(pSock); + else + rc = (*sockCfg->secConnectProc)(pSock); + + if (rc == SD_SUCCESS) + { + /* Do nothing. Receive data on next call. */ + } + else /* User does not want */ + { + if (!pSock->disconnectReason) + pSock->disconnectReason = GS_DISCONNECT_USR_REFUSED; + /* No need to lock, user will not free or access anymore */ + sockClose (pSock); + sockFree (pSock); /* Allow it to be free'd */ + } + } + } + else if (FD_ISSET (pSock->hSock, &sockFds->exceptfds)) + { /* Connect failed (WNIDOWS ONLY) */ + SOCK_OPTLEN optlen; + ST_INT sRet; + ST_INT connError; + + optlen = sizeof(connError); + sRet = getsockopt (pSock->hSock, SOL_SOCKET, SO_ERROR, (ST_CHAR *) &connError, &optlen); + if (sRet == 0) + SOCK_LOG_FLOW2 (sockCtx, "%s: socket Connect Failed. Error = %d", pSock->sockIdStr, connError); + else + SOCK_LOG_ERR2 (sockCtx, "%s: getsockopt(...,SOL_SOCKET, SO_ERROR,...) failed, errno=%d.", + pSock->sockIdStr, SOCKET_ERRORNO); + --nfds; + pSock->disconnectReason = GS_DISCONNECT_CONNECT_FAILED; + sockErrorDetected = SD_TRUE; + } + } + else if (pSock->sockState == GS_STATE_LISTENING) + { /* Check for activity on this socket ... */ + if (FD_ISSET (pSock->hSock, &sockFds->readfds)) + { + --nfds; + _sockAccept (pSock); + } + } + else /* Not really interesting */ + { + if (FD_ISSET (pSock->hSock, &sockFds->readfds)) + --nfds; + } + + if (sockErrorDetected == SD_TRUE) + sockClose (pSock); /* error on this socket, so close it */ + + pSock = pNextSock; + } /* While sockets and nfds */ + S_UNLOCK_UTIL_RESOURCES (); /* CRITICAL: lock all access to sockList*/ + +#if defined(GENSOCK_THREAD_SUPPORT) + /* See if someone woke us by sending us data */ + if (nfds > 0) + { + if (FD_ISSET (serviceCtrl->xCallingSock, &sockFds->readfds)) + { + /* Non-blocking receive, dump data */ + recvRet = (ST_INT) recv (serviceCtrl->xCallingSock, bitBucket, sizeof (bitBucket), 0); + /* log only if this is not an SLOGIPC xCallingSock (otherwise looping occurs) */ + if (memcmp (sockCtx->ctxName, SLOGIPC_NAME, strlen(SLOGIPC_NAME)) != 0) + { + if (recvRet > 0) + { + SOCK_LOG_FLOW2 (sockCtx, "%s: XSocket received %d wakeup bytes", sockCtx->ctxName, recvRet); + } + else if (recvRet == 0) + { + SOCK_LOG_NERR1 (sockCtx, "%s: XSocket disconnected detected by recv()", sockCtx->ctxName); + } + } + } + } +#endif + + return (GS_SELECT_ACTIVE); + } + +/************************************************************************/ +/* _sockServiceDiscardSock */ +/* NOTE: this must be called ONLY from sockClose. */ +/************************************************************************/ +/* Remove a pSock from a service control and allow it to be free'd */ + +static ST_VOID _sockServiceDiscardSock (GEN_SOCK_CTRL *serviceCtrl, + GEN_SOCK *pSock) + { +GEN_SOCK_CTXT *sockCtx; + + sockCtx = pSock->sockCtx; + SOCK_LOG_FLOW2 (sockCtx, "%s: preparing to free GEN_SOCK " S_FMT_PTR ".", pSock->sockIdStr, pSock); + +/* The service control is done with this socket, clean it up */ +/* See if we need to return a receive buffer to the user */ + if (pSock->recvState == RECV_STATE_DATA) + { + pSock->sockData->result = SD_FAILURE; + (*pSock->sockCfg.uSockRx)(pSock, pSock->sockData); + } + + /* If the socket has not been closed, time to do so */ + /* protect numActive, numSock, sockList */ + S_LOCK_UTIL_RESOURCES (); + + /* Dec the active socket count for a called socket. Note that the */ + /* listen socket will not be free'd until numActive = 0 */ + if (pSock->role == GS_ROLE_CALLED && pSock->listenSocket) + --pSock->listenSocket->numActive; + + list_unlink (&serviceCtrl->sockList, pSock); + pSock->serviceCtrl = NULL; + --serviceCtrl->numSock; + + /* See if the user needs to be told that the socket is closed */ + if (pSock->usrCloseCalled == SD_FALSE) + { + pSock->usrCloseCalled = SD_TRUE; + if (pSock->sockCfg.secDisconnectProc == NULL) + { + SOCK_LOG_FLOW1 (sockCtx, "%s: calling uSockDisconnect()",pSock->sockIdStr); + (*pSock->sockCfg.uSockDisconnect)(pSock); + } + else + { + SOCK_LOG_FLOW1 (sockCtx, "%s: calling secDisconnectProc()", pSock->sockIdStr); + (*pSock->sockCfg.secDisconnectProc)(pSock); + } + } + S_UNLOCK_UTIL_RESOURCES (); + } + +/************************************************************************/ +/* _sockAccept */ +/************************************************************************/ + +static ST_RET _sockAccept (GEN_SOCK *pListenSock) + { +GEN_SOCK_CTXT *sockCtx = pListenSock->sockCtx; +GEN_SOCK *pSock; +SOCKET hNewSock; +ST_BOOLEAN okToAccept; +ST_INT rc = SD_SUCCESS; +SOCK_ADDRLEN callingAddrLen; +SOCKADDR_IN callingAddr; +int err; + +/* This accept should succeed immediately */ + callingAddrLen = sizeof (callingAddr); + hNewSock = accept (pListenSock->hSock, + (SOCKADDR *) &callingAddr, &callingAddrLen); + if (hNewSock == INVALID_SOCKET) + { + err = SOCKET_ERRORNO; + SOCK_LOG_NERR2 (sockCtx, "%s: socket accept() error (errno=%d)", pListenSock->sockIdStr, err); + if (pListenSock->sockState == GS_STATE_LISTENING) + { + pListenSock->disconnectReason = GS_DISCONNECT_ACCEPT_FAILED; + } + return (SD_FAILURE); + } + +#if !defined(_WIN32) + if (hNewSock >= FD_SETSIZE) + { /* Can't use this socket because illegal to use in "select" call*/ + SOCK_LOG_ERR2 (sockCtx, "%s: accept returned socket num %d >= FD_SETSIZE " + "(can not be used in select), closing socket.", pListenSock->sockIdStr, hNewSock); + CLOSE_SOCKET (hNewSock); + return (SD_FAILURE); + } +#endif + + if (sockCtx->ctxStatus == GEN_SOCK_CTX_TERMINATING) + { + /* prevent adding new sockets to serviceCtrl */ + SOCK_LOG_FLOW1 (sockCtx, "%s: can't accept socket connection, context is terminating", pListenSock->sockIdStr); + CLOSE_SOCKET (hNewSock); + return (SD_FAILURE); + } + + /* Got a connection, see if we are still listening ... */ + SOCK_LOG_FLOW4 (sockCtx, "%s: accepted connection (socket=%d) from IP Address=%s Port=%u", + pListenSock->sockIdStr, hNewSock, + inet_ntoa (callingAddr.sin_addr), (ST_UINT) ntohs (callingAddr.sin_port)); + /* protect numActive */ + S_LOCK_UTIL_RESOURCES (); + if (pListenSock->maxActive != 0 && (pListenSock->numActive >= pListenSock->maxActive)) + okToAccept = SD_FALSE; + else + okToAccept = SD_TRUE; + S_UNLOCK_UTIL_RESOURCES (); + if (okToAccept == SD_FALSE) + { + SOCK_LOG_FLOW2 (sockCtx, "%s: cannot process new socket connection, reached maxActive=%d socket connections", + pListenSock->sockIdStr, pListenSock->maxActive); + CLOSE_SOCKET (hNewSock); + return (SD_FAILURE); + } + +/* OK, we have a go ... */ + pSock = _sockAllocSock (sockCtx, GS_ROLE_CALLED, GS_STATE_CONNECTED, + hNewSock, &pListenSock->sockCfg); + + pSock->listenSocket = pListenSock; + pSock->callingAddrLen = callingAddrLen; + pSock->callingAddr = callingAddr; + + /* add new socket to service list and then call uSockConnect fun, */ + /* the sockAddSock may start new thread that will receive data before */ + /* the uSockConnect is called, LOCK is needed to prevent this scenario */ + S_LOCK_UTIL_RESOURCES (); + rc = _sockAddSock (pSock); /* Add to a service list */ + if (rc == SD_SUCCESS) + { + if (pSock->sockCfg.secConnectProc == NULL) + rc = (*pSock->sockCfg.uSockConnectInd)(pSock); + else + rc = (*pSock->sockCfg.secConnectProc)(pSock); + if (rc != SD_SUCCESS) + { + /* user does not want this connection */ + pSock->usrCloseCalled = SD_TRUE; /* don't call uSockDisconnect */ + sockClose (pSock); + sockFree (pSock); + } + } + else + { + SOCK_LOG_FLOW1 (sockCtx, "%s: closing socket connections", pSock->sockIdStr); + CLOSE_SOCKET (hNewSock); + chk_free (pSock); + } + S_UNLOCK_UTIL_RESOURCES (); + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sockCheckRxData */ +/* Receive data from the socket and check its validity. */ +/* NOTE: caller should close the socket if this function returns error. */ +/************************************************************************/ + +static ST_INT _sockCheckRxData (GEN_SOCK *pSock) + { +ST_INT numRxd; +ST_INT totalSize; +ST_INT bodySize; +ST_INT huntState; +ST_RET rc; +ST_CHAR *rxDest; +ST_INT rxBufSize; +ST_BOOLEAN secDataLeft; +ST_BOOLEAN foundHeader; +GEN_SOCK_CTXT *sockCtx; + + sockCtx = pSock->sockCtx; + secDataLeft = SD_FALSE; + do + { + foundHeader = SD_FALSE; + rxDest = pSock->recvBuf+pSock->recvCurrCount; + rxBufSize = pSock->recvDoneCount - pSock->recvCurrCount; + + /* Use a non-blocking recv to get what's there */ + /* See if we need to pass it to a receive processing subsystem */ + if (pSock->sockCfg.secRxProc == NULL) + rc = _sockRecv (pSock, rxDest, rxBufSize, 0, &numRxd); + else + rc = (*pSock->sockCfg.secRxProc) (pSock, rxDest, rxBufSize, 0, + &numRxd, &secDataLeft); + + if (rc == SD_SUCCESS) + { + if (numRxd) + { +#ifdef SOCK_FLOW_PRINT /* DEBUG: enable this to see data flow. */ + printf ("."); +#endif + SOCK_LOG_FLOW2 (sockCtx, "%s: received %d bytes", pSock->sockIdStr, numRxd); + pSock->recvCurrCount += numRxd; + if (pSock->recvDoneCount == pSock->recvCurrCount) + { + /* We got all the data we wanted, see if it is the header or data */ + if (pSock->recvState == RECV_STATE_HUNT) + { + huntState = GENSOCK_HUNT_UNDERWAY; + (*pSock->sockCfg.uSockHunt) (pSock, &huntState, + pSock->recvBuf, pSock->recvCurrCount, &bodySize); + if (huntState == GENSOCK_HUNT_DONE) + { + /* OK, the hunt is over and we have the length of the buffer to read */ + totalSize = pSock->sockCfg.hdrSize + bodySize; + SOCK_LOG_FLOWC2 (sockCtx, "%s: hunt complete, expecting %d more bytes", pSock->sockIdStr, bodySize); + (*pSock->sockCfg.uSockRxBufAlloc) (pSock, totalSize, &pSock->sockData); + pSock->sockData->dataLen = totalSize; + memcpy (pSock->sockData->data, pSock->recvBuf, pSock->sockCfg.hdrSize); + + if (bodySize) + { + pSock->recvState = RECV_STATE_DATA; + pSock->recvBuf = (ST_CHAR *) pSock->sockData->data + pSock->sockCfg.hdrSize; + pSock->recvCurrCount = 0; + pSock->recvDoneCount = bodySize; + foundHeader = SD_TRUE; + } + else /* No body, just header */ + { + ++pSock->sockStats.numRecv; + + /* Give the data to the user... */ + pSock->sockData->result = SD_SUCCESS; + (*pSock->sockCfg.uSockRx)(pSock, pSock->sockData); + + /* Now hunt for the next */ + pSock->recvState = RECV_STATE_HUNT; + pSock->recvDoneCount = pSock->sockCfg.hdrSize; + pSock->recvCurrCount = 0; + pSock->recvBuf = pSock->hdrBuf; + } + } + else if (huntState == GENSOCK_HUNT_RESET) + { + huntState = GENSOCK_HUNT_UNDERWAY; + pSock->recvCurrCount = 0; + } + else if (huntState == GENSOCK_HUNT_DISCONNECT) + { /* beginning of packet is invalid */ + pSock->recvCurrCount = 0; + rc = SD_FAILURE; /* this should cause an immediate disconnect*/ + } + } + else /* Not hunting, state is RECV_STATE_DATA */ + { + SOCK_LOG_FLOWC1 (sockCtx, "%s: got body", pSock->sockIdStr); + ++pSock->sockStats.numRecv; + + /* Give the data to the user... */ + pSock->sockData->result = SD_SUCCESS; + (*pSock->sockCfg.uSockRx)(pSock, pSock->sockData); + + /* Now hunt for the next */ + pSock->recvState = RECV_STATE_HUNT; + pSock->recvDoneCount = pSock->sockCfg.hdrSize; + pSock->recvCurrCount = 0; + pSock->recvBuf = pSock->hdrBuf; + } + } /* Got all expected data */ + } /* Got some data */ + } + } while (rc == SD_SUCCESS && (secDataLeft == SD_TRUE || foundHeader == SD_TRUE)); + return (rc); + } + +/************************************************************************/ +/* _sockRecv */ +/* Receive up to "maxRx" bytes from the socket. */ +/* NOTE: caller should close the socket if this function returns error. */ +/************************************************************************/ + +ST_RET _sockRecv (GEN_SOCK *pSock, ST_CHAR *dest, + ST_INT maxRx, ST_INT flags, ST_INT *rxCountOut) + { +ST_INT recvRet; +ST_RET retVal; +int err; +GEN_SOCK_CTXT *sockCtx; + + sockCtx = pSock->sockCtx; + +/* All socketa are non-blocking, so recv will NOT block. */ + recvRet = (ST_INT) recv (pSock->hSock, dest, maxRx, flags); + if (recvRet > 0) + { + *rxCountOut = recvRet; + /* save the time of last successful data transfer activity on the socket */ + if (sockCtx->maxIdleTime > 0) + pSock->sockStats.lastActivityTime = sGetMsTime(); + return (SD_SUCCESS); + } + +/* Not a clean receive, see if we have a disconnect */ + if (recvRet == 0) + { + pSock->disconnectReason = GS_DISCONNECT_CLOSED; + SOCK_LOG_FLOW1 (sockCtx, "%s: Socket disconnect detected by recv()", pSock->sockIdStr); + return (SD_FAILURE); + } + +/* Some kind of error */ + + + err = SOCKET_ERRORNO; + + + switch (err) /* See if recoverable */ + { + case SOCK_WOULDBLOCK: + case SOCK_INTR: + /* case SOCK_TIMEDOUT: RRRRRRRRRRRRRRRRRRRRRRRRR*/ + case SOCK_INPROGRESS: /* Seen for Solaris 8 */ + *rxCountOut = 0; + retVal = SD_SUCCESS; + break; + + default: + /* if(err==SOCK_TIMEDOUT) ͨѶ³¬Ê± 20160617 */ + //logprint("SOCK RECV FAILED ERRORNO=%d(IP:%s)",err,inet_ntoa(pSock->callingAddr.sin_addr)); + +/* + ETIMEDOUTÆóͼÁ¬ÏߵIJÙ×÷³¬¹ýÏÞ¶¨Ê±¼äÈÔδÓÐÏìÓ¦¡£ + ENETUNREACHÎÞ·¨´«ËÍÊý¾Ý°üÖÁÖ¸¶¨µÄÖ÷»ú¡£ +*/ + + SOCK_LOG_FLOW2 (sockCtx, "%s: Socket error detected by recv() errno=%d", pSock->sockIdStr, err); + pSock->disconnectReason = GS_DISCONNECT_RECV_FAILED; + retVal = SD_FAILURE; + break; + } + + return (retVal); + } + +/************************************************************************/ +/* _sockAllocSock */ +/************************************************************************/ + +GEN_SOCK *_sockAllocSock (GEN_SOCK_CTXT *sockCtx, + ST_INT role, ST_INT sockState, + SOCKET hSock, GEN_SOCK_CONFIG *sockCfg) + { +static ST_UINT sockId = 0; /* give diff id to each socket */ +GEN_SOCK *pSock; +#if defined(__hpux) || defined(_AIX) || defined(sun) || defined(linux) +int nonblock_on=1; /* CRITICAL: must be non-zero to enable non-blocking*/ +#else +/* _WIN32 */ +ST_ULONG nonblock_on=1; /* CRITICAL: must be non-zero to enable non-blocking*/ +#endif +int sRet; + +#if !defined(_WIN32) + assert (hSock < FD_SETSIZE); /* this should have already been checked*/ +#endif + + +/* Allocate enough room for the header too */ +/* 0 is OK for backward compatability */ + if (sockCfg->hdrAllocSize < sockCfg->hdrSize) + { + SOCK_LOG_FLOW1 (sockCtx, "Setting hdrAllocSize = %d", sockCfg->hdrSize); + sockCfg->hdrAllocSize = sockCfg->hdrSize; + } +/* Sanity checks */ + if ((sockCfg->hdrAllocSize > GENSOCK_MAX_HEADER_SIZE) || + (sockCfg->hdrAllocSize < 0) || + (sockCfg->hdrSize < 0)) + { + assert (0); /* these must be set correctly before now. */ + } + + pSock = (GEN_SOCK *) chk_calloc (1, sizeof (GEN_SOCK) + sockCfg->hdrAllocSize); + pSock->hdrBuf = (ST_CHAR *) (pSock+1); + + pSock->sockId = ++sockId; /* assign different gensock2 Id number to each socket */ + if (pSock->sockId == 0) + ++sockId; + sprintf (pSock->sockIdStr, "%s sockId=%5.5u%s", sockCtx->ctxName, pSock->sockId, (role == GS_ROLE_LISTENING ? "L" : "")); + pSock->sockCtx = sockCtx; + pSock->hSock = hSock; + pSock->role = role; + pSock->sockCfg = *sockCfg; /* Copy socket config */ + if (sockCfg->setSockOpts) + { + if (role == GS_ROLE_LISTENING) + { /* set REUSEADDR option ONLY if Listen socket */ + sRet = setsockopt (hSock, SOL_SOCKET, SO_REUSEADDR, + (ST_CHAR *) &sockCfg->reuseAddr, sizeof(sockCfg->reuseAddr)); + } + else + { /* set all other options ONLY if NOT Listen socket */ + sRet = setsockopt (hSock, IPPROTO_TCP, TCP_NODELAY, + (ST_CHAR *) &sockCfg->noDelay, sizeof(sockCfg->noDelay)); + + sRet = setsockopt (hSock, SOL_SOCKET, SO_KEEPALIVE, + (ST_CHAR *) &sockCfg->keepAlive, sizeof(sockCfg->keepAlive)); + + if (sockCfg->rcvBufSize > 0) + { + sRet = setsockopt (hSock, SOL_SOCKET, SO_RCVBUF, + (ST_CHAR *) &sockCfg->rcvBufSize, sizeof(sockCfg->rcvBufSize)); + } + if (sockCfg->sndBufSize > 0) + { + sRet = setsockopt (hSock, SOL_SOCKET, SO_SNDBUF, + (ST_CHAR *) &sockCfg->sndBufSize, sizeof(sockCfg->sndBufSize)); + } + } + } + + pSock->sockState = sockState; + +/* Make the socket non-blocking */ + sRet = ioctlsocket (pSock->hSock, FIONBIO, &nonblock_on); + + pSock->sockStats.createdTime = time (NULL); + pSock->sockStats.lastActivityTime = sGetMsTime(); + + SOCK_LOG_FLOW3 (sockCtx, "%s: allocated GEN_SOCK " S_FMT_PTR ", socket=%d.", + pSock->sockIdStr, pSock, pSock->hSock); + return (pSock); + } + +/************************************************************************/ +/* _sockAddSock */ +/************************************************************************/ + +ST_RET _sockAddSock (GEN_SOCK *pSock) + { +GEN_SOCK_CTXT *sockCtx = pSock->sockCtx; +GEN_SOCK_CTRL *serviceCtrl; +ST_RET rc = SD_SUCCESS; + + /* protect numActive, sockServiceList, numSock, sockList */ + S_LOCK_UTIL_RESOURCES (); + +/* Set receive mode to start hunting ... not needed for listen socks */ + pSock->recvState = RECV_STATE_HUNT; + pSock->recvDoneCount = pSock->sockCfg.hdrSize; + pSock->recvCurrCount = 0; + pSock->recvBuf = pSock->hdrBuf; + +/* Find a service thread with capacity */ + serviceCtrl = sockCtx->sockServiceList; + while (serviceCtrl != NULL) + { + if (serviceCtrl->numSock < GS_MAX_SOCK_PER_SERVICE) + break; + + serviceCtrl = (GEN_SOCK_CTRL *) list_get_next (sockCtx->sockServiceList, serviceCtrl); + } +#if defined(GENSOCK_THREAD_SUPPORT) + if (serviceCtrl == NULL) + { + /* UNIX/Linux note: theoretically we should never need to add new */ + /* thread when GS_MAX_SOCK_PER_SERVICE is (FD_SETSIZE - 1) */ + + /* add new service control (it will exist until the sockEnd() is called) */ + serviceCtrl = _sockAddServiceCtrl (sockCtx); + //printf("_sockAddServiceThread 2...\n"); + rc = _sockAddServiceThread (serviceCtrl); + if (rc != SD_SUCCESS) + { + list_unlink (&sockCtx->sockServiceList, serviceCtrl); + chk_free (serviceCtrl); + pSock->disconnectReason = GS_DISCONNECT_INTERNAL_ERROR; + } + } +#else /* !defined(GENSOCK_THREAD_SUPPORT) */ + if (serviceCtrl == NULL) + { + /* list empty or we reached max numSock */ + SOCK_LOG_NERR2 (sockCtx, "%s: Can't add GEN_SOCK to list (limit reached %d sockets)", + pSock->sockIdStr, GS_MAX_SOCK_PER_SERVICE); + rc = SD_FAILURE; + pSock->disconnectReason = GS_DISCONNECT_RESOURCES_ERROR; + } +#endif + + if (rc == SD_SUCCESS) + { + if (pSock->role == GS_ROLE_CALLED && pSock->listenSocket) + ++pSock->listenSocket->numActive; + + /* Add to the tracking list */ + list_add_last (&serviceCtrl->sockList, pSock); + pSock->serviceCtrl = serviceCtrl; + ++serviceCtrl->numSock; + sockServiceWake (serviceCtrl); + SOCK_LOG_FLOW1 (sockCtx, "%s: Added GEN_SOCK to service list", pSock->sockIdStr); + } + else + SOCK_LOG_FLOW2 (sockCtx, "%s: Add GEN_SOCK to service list failed (error=%d)", pSock->sockIdStr, rc); + + S_UNLOCK_UTIL_RESOURCES (); + + return (rc); + } + +/************************************************************************/ +/************************************************************************/ +/* POLLING MODEL SPECIFIC */ +/************************************************************************/ +/* sockServiceAll */ +/************************************************************************/ + +#if !defined(GENSOCK_THREAD_SUPPORT) +/* For use in polled environment */ +ST_VOID sockServiceAll (GEN_SOCK_CTXT *sockCtx, ST_LONG timeOut) + { +GEN_SOCK_CTRL *serviceCtrl; + + serviceCtrl = sockCtx->sockServiceList; + while (serviceCtrl != NULL) + { + sockCtrlService (serviceCtrl, timeOut); + serviceCtrl = (GEN_SOCK_CTRL *) list_get_next (sockCtx->sockServiceList, serviceCtrl); + } + } +#endif /* !defined(GENSOCK_THREAD_SUPPORT) */ + +/************************************************************************/ +/* End of polling specific functions */ +/************************************************************************/ + + + /****************************************/ + /* THREAD MODEL SPECIFIC */ + /****************************************/ + +#if defined(GENSOCK_THREAD_SUPPORT) +/************************************************************************/ +/* _sockAddServiceThread */ +/************************************************************************/ + +static ST_RET _sockAddServiceThread (GEN_SOCK_CTRL *serviceCtrl) + { +ST_RET rc = SD_SUCCESS; +GEN_SOCK_CTXT *sockCtx = serviceCtrl->sockCtx; + + SOCK_LOG_FLOW1 (sockCtx, "%s: in sockAddServiceThread()", sockCtx->ctxName); + + serviceCtrl->serviceEvent = gs_get_event_sem (SD_FALSE); + if (!serviceCtrl->serviceEvent) + { + SOCK_LOG_ERR1 (sockCtx, "%s: could not get service event", sockCtx->ctxName); + return (SD_FAILURE); + } + + /* Create a set of wakeup sockets for this service control */ + rc = sockCreateWakeupSockets (sockCtx, sockCtx->gs_wakeup_port, 100, + &serviceCtrl->wakeupPort, + &serviceCtrl->xCallingSock, &serviceCtrl->xCalledSock); + if (rc != SD_SUCCESS) + { + gs_free_event_sem (serviceCtrl->serviceEvent); + serviceCtrl->serviceEvent = NULL; + return (rc); + } + + /* start Service thread */ + rc = gs_start_thread (_sockServiceThread, serviceCtrl, + &serviceCtrl->thService, + &serviceCtrl->tIdService); + if (rc != SD_SUCCESS) + { + SOCK_LOG_ERR2 (sockCtx, "%s: could not start Service thread error=%d", sockCtx->ctxName, rc); + gs_free_event_sem (serviceCtrl->serviceEvent); + serviceCtrl->serviceEvent = NULL; + if (serviceCtrl->xCallingSock) + { + CLOSE_SOCKET (serviceCtrl->xCallingSock); + serviceCtrl->xCallingSock = 0; + } + if (serviceCtrl->xCalledSock) + { + CLOSE_SOCKET (serviceCtrl->xCalledSock); + serviceCtrl->xCalledSock = 0; + } + rc = SD_FAILURE; + } + + return (rc); + } + +/************************************************************************/ +/* _sockServiceThread */ +/************************************************************************/ + +static ST_THREAD_RET ST_THREAD_CALL_CONV _sockServiceThread (ST_THREAD_ARG pArg) + { +GEN_SOCK_CTRL *serviceCtrl = (GEN_SOCK_CTRL *) pArg; +GEN_SOCK_CTXT *sockCtx = serviceCtrl->sockCtx; +GEN_SOCK *pSock; +ST_INT ret; + + SOCK_LOG_FLOW1 (sockCtx, "%s: sockServiceThread started", sockCtx->ctxName); + + while (sockCtx->gTerminateService == SD_FALSE) + { + ret = sockCtrlService (serviceCtrl, sockCtx->gs_select_timeout); + switch (ret) + { + case GS_SELECT_NO_ACTIVE_SOCK: /* Nothing on our list */ + gs_wait_event_sem (serviceCtrl->serviceEvent, 10000); + break; + + case GS_SELECT_ACTIVE: /* Action! */ + break; + + case GS_SELECT_TIMEOUT: /* No action */ + break; + + case GS_SELECT_ERROR: /* Error */ + gs_wait_event_sem (serviceCtrl->serviceEvent, 1000); + break; + + case GS_SELECT_TERMINATED: /* Terminating */ + break; + + default: + break; + } + } /* While not terminate */ + + +/* Close all sockets associated with the service control */ + S_LOCK_UTIL_RESOURCES (); /* CRITICAL: lock all access to sockList*/ + while (serviceCtrl->sockList) + { + pSock = serviceCtrl->sockList; + pSock->disconnectReason = GS_DISCONNECT_TERMINATING; + sockClose (pSock); + } + S_UNLOCK_UTIL_RESOURCES (); /* CRITICAL: lock all access to sockList*/ + + SOCK_LOG_FLOW1 (sockCtx, "%s: sockServiceThread ended", sockCtx->ctxName); + return (0); + // return (ST_THREAD_RET_VAL); + } + +/************************************************************************/ +/************************************************************************/ +/* sockCreateWakeupSockets */ +/* This function will create pair of sockets that can be used for */ +/* signaling an event. */ +/************************************************************************/ + +ST_RET sockCreateWakeupSockets (GEN_SOCK_CTXT *sockCtx, + ST_UINT16 basePort, ST_UINT portRange, + ST_UINT16 *usedPort, + SOCKET *callingSock, SOCKET *calledSock) + { +ST_UINT16 wakeupPort = basePort; +SOCKET xCallingSock, xCalledSock; +SOCKET hListenSock; +SOCK_ADDRLEN callingAddrLen; +SOCKADDR_IN callingAddr; +#if defined(__hpux) || defined(_AIX) || defined(sun) || defined(linux) +int nonblock_on=1; /* CRITICAL: must be non-zero to enable non-blocking*/ +#else +/* _WIN32 */ +ST_ULONG nonblock_on=1; /* CRITICAL: must be non-zero to enable non-blocking*/ +#endif +struct sockaddr_in localAddr; +ST_INT noDelay; +ST_INT keepAlive; +ST_INT reuseAddr; +ST_UINT i; +int sRet; +int err; + + SOCK_LOG_FLOW1 (sockCtx, "%s: in sockCreateWakeupSockets()", sockCtx->ctxName); + +/* Step 1: Make a non-blocking listen socket */ + hListenSock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (hListenSock == INVALID_SOCKET) + { + SOCK_LOG_ERR1 (sockCtx, "%s: XSocket socket() failed", sockCtx->ctxName); + return (SD_FAILURE); + } + + sRet = ioctlsocket (hListenSock, FIONBIO, &nonblock_on); + reuseAddr = 0; + sRet = setsockopt (hListenSock, SOL_SOCKET, SO_REUSEADDR, + (ST_CHAR *) &reuseAddr, sizeof(reuseAddr)); + + memset((char *)(&localAddr), 0, sizeof(localAddr)); + localAddr.sin_family = AF_INET; + localAddr.sin_port = htons (wakeupPort); + localAddr.sin_addr.s_addr = htonl (INADDR_ANY); + + /* Try up to the next ports in this range */ + for (i = 0; i < portRange; ++i) + { + sRet = bind (hListenSock, (struct sockaddr *)&localAddr, sizeof(localAddr)); + if (sRet == 0) + { + SOCK_LOG_FLOW2 (sockCtx, "%s: XSocket bind on port=%d", sockCtx->ctxName, (ST_UINT) wakeupPort); + break; + } + + err = SOCKET_ERRORNO; + SOCK_LOG_FLOW4 (sockCtx, "%s: XSocket bind() failure on port=%d, errno=%d %s", + sockCtx->ctxName, (ST_UINT) wakeupPort, err, + (err == SOCK_EADDRINUSE) ? "(port in use)" : " "); + wakeupPort++; + localAddr.sin_port = htons(wakeupPort); + + sMsSleep (2); + } + + /* App may still function if unable to create Wakeup Socket, but let user know with ERR log */ + if (sRet != 0) + { + SOCK_LOG_ERR2 (sockCtx, "%s: XSocket bind() failed, errno=%d", sockCtx->ctxName, SOCKET_ERRORNO); + CLOSE_SOCKET (hListenSock); + return (SD_FAILURE); + } + + sRet = listen (hListenSock, SOMAXCONN); + if (sRet != 0) + { + SOCK_LOG_ERR2 (sockCtx, "%s: XSocket listen() failed, errno=%d", sockCtx->ctxName, SOCKET_ERRORNO); + CLOSE_SOCKET (hListenSock); + return (SD_FAILURE); + } + + +/* Step 2: Do a non-blocking connect */ + xCallingSock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (xCallingSock == INVALID_SOCKET) + { + SOCK_LOG_ERR1 (sockCtx, "%s: XSocket socket() failed", sockCtx->ctxName); + CLOSE_SOCKET (hListenSock); + return (SD_FAILURE); + } + + noDelay = 1; + keepAlive = 0; + sRet = setsockopt (xCallingSock, IPPROTO_TCP, TCP_NODELAY, + (ST_CHAR *) &noDelay, sizeof(noDelay)); + sRet = setsockopt (xCallingSock, SOL_SOCKET, SO_KEEPALIVE, + (ST_CHAR *) &keepAlive, sizeof(keepAlive)); + +/* Set up the socket address */ + memset((char *)(&localAddr), 0, sizeof(localAddr)); + localAddr.sin_family = AF_INET; + localAddr.sin_addr.s_addr = inet_addr ("127.0.0.1"); + localAddr.sin_port = htons (wakeupPort); + +/* Make the calling socket non-blocking */ + sRet = ioctlsocket (xCallingSock, FIONBIO, &nonblock_on); + +/* Do non-blocking connect */ + sRet = connect (xCallingSock, (struct sockaddr *)&localAddr, sizeof(localAddr)); + if (sRet >= 0) + { + SOCK_LOG_FLOW2 (sockCtx, "%s: XSocket connected on port=%d", sockCtx->ctxName, (ST_UINT) wakeupPort); + } + else + { + sRet = SOCKET_ERRORNO; + if (sRet == SOCK_WOULDBLOCK || sRet == SOCK_INPROGRESS) + { + SOCK_LOG_FLOW1 (sockCtx, "%s: XSocket connection pending", sockCtx->ctxName); + } + else + { + CLOSE_SOCKET (hListenSock); + CLOSE_SOCKET (xCallingSock); + SOCK_LOG_ERR2 (sockCtx, "%s: XSocket connect() failed, errno=%d", sockCtx->ctxName, sRet); + return (SD_FAILURE); + } + } + +/* Step 3: Do non-blocking accept */ + callingAddrLen = sizeof (callingAddr); + + for (i = 0; i < 50; ++i) + { + callingAddrLen = sizeof (callingAddr); /* set for each accept call */ + xCalledSock = accept (hListenSock, (SOCKADDR *) &callingAddr, &callingAddrLen); + if (xCalledSock != INVALID_SOCKET) + break; + sMsSleep (2); + } + + if (xCalledSock == INVALID_SOCKET) + { + sRet = SOCKET_ERRORNO; + CLOSE_SOCKET (xCallingSock); + CLOSE_SOCKET (hListenSock); + SOCK_LOG_ERR2 (sockCtx, "%s: XSocket accept() failed, errno=%d", sockCtx->ctxName, sRet); + return (SD_FAILURE); + } + + SOCK_LOG_FLOW2 (sockCtx, "%s: XSocket accept() successful on port=%d", sockCtx->ctxName, wakeupPort); + noDelay = 1; + keepAlive = 0; + sRet = setsockopt (xCalledSock, IPPROTO_TCP, TCP_NODELAY, + (ST_CHAR *) &noDelay, sizeof(noDelay)); + sRet = setsockopt (xCalledSock, SOL_SOCKET, SO_KEEPALIVE, + (ST_CHAR *) &keepAlive, sizeof(keepAlive)); + +/* Make the called socket non-blocking */ + sRet = ioctlsocket (xCalledSock, FIONBIO, &nonblock_on); + + CLOSE_SOCKET (hListenSock); + + /* wakeup sockets pair connected */ + *usedPort = wakeupPort; + *callingSock = xCallingSock; + *calledSock = xCalledSock; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* End of thread specific functions */ +#endif /* #if defined(GENSOCK_THREAD_SUPPORT */ +/************************************************************************/ + +/************************************************************************/ +/************************************************************************/ +/* sockLogState */ +/************************************************************************/ + +ST_VOID sockLogState (GEN_SOCK_CTXT *sockCtx) + { +GEN_SOCK_CTRL *serviceCtrl; +GEN_SOCK *pSock; +ST_INT serviceCount; +ST_INT sockCount; + + S_LOCK_UTIL_RESOURCES (); + + SLOGALWAYS1 ("GEN_SOCK STATE for context '%s':", sockCtx->ctxName); + SLOGCALWAYS1 (" Service Control List (%d)", list_get_sizeof (sockCtx->sockServiceList)); + serviceCtrl = sockCtx->sockServiceList; + + serviceCount = 1; + while (serviceCtrl != NULL) + { + SLOGCALWAYS1 (" %d) Service Control", serviceCount++); + SLOGCALWAYS1 (" %d sockets", serviceCtrl->numSock); +#if defined(GENSOCK_THREAD_SUPPORT) + SLOGCALWAYS3 (" Wakeup Port: %d, xCalledSock: %d xCallingSock: %d", + serviceCtrl->wakeupPort, + serviceCtrl->xCalledSock, + serviceCtrl->xCallingSock); +#endif + sockCount = 1; + pSock = serviceCtrl->sockList; + while (pSock != NULL) + { + SLOGCALWAYS1 (" %d) Socket Control", sockCount++); + sockLogSockState (pSock," "); + pSock = (GEN_SOCK *) list_get_next (serviceCtrl->sockList, pSock); + } + serviceCtrl = (GEN_SOCK_CTRL *) list_get_next (sockCtx->sockServiceList, serviceCtrl); + } + + S_UNLOCK_UTIL_RESOURCES (); + } + + +/************************************************************************/ +/* sockLogSockState */ +/************************************************************************/ + +ST_VOID sockLogSockState (GEN_SOCK *pSock, ST_CHAR *prefix) + { +ST_CHAR *str; + + if (prefix == NULL) + prefix = ""; + + switch (pSock->role) + { + case GS_ROLE_CALLED: + str = "Called"; + break; + case GS_ROLE_CALLING: + str = "Calling"; + break; + case GS_ROLE_LISTENING: /* Not valid */ + str = "Lisening"; + break; + default: + str = "Invalid"; + break; + } + SLOGCALWAYS2 ("%sRole : %s", prefix, str); + + + switch (pSock->sockState) + { + case GS_STATE_LISTENING : + str = "LISTENING"; + break; + + case GS_STATE_FAILED_LISTEN : + str = "FAILED LISTEN"; + break; + + case GS_STATE_STOPPING_LISTEN : + str = "STOPPING_LISTEN"; + + case GS_STATE_CONNECTING : + str = "CONNECTING"; + break; + + case GS_STATE_CONNECTED : + str = "CONNECTED"; + break; + + case GS_STATE_CLOSED : + str = "CLOSED"; + break; + + default: + str = "Invalid"; + break; + } + + SLOGCALWAYS2 ("%sState: %s", prefix, str); + str = ctime (&pSock->sockStats.createdTime); + str[24] = 0; + SLOGCALWAYS2 ("%sTime Created: %s", prefix, str); + if (pSock->sockStats.activeTime) + { + str = ctime (&pSock->sockStats.activeTime); + str[24] = 0; + SLOGCALWAYS2 ("%sTime Active: %s", prefix, str); + } + SLOGCALWAYS2 ("%sNum Group Msgs Queued: %d", prefix, pSock->sockTxQueueGroupCnt); + SLOGCALWAYS2 ("%sNum Msgs (RFC1006) Sent: %ld", prefix, pSock->sockStats.numSend); + SLOGCALWAYS2 ("%sNum Msgs (RFC1006) Recv: %ld", prefix, pSock->sockStats.numRecv); + } + + +/************************************************************************/ +/* sockGetRemAddrInfo */ +/************************************************************************/ + +ST_RET sockGetRemAddrInfo (GEN_SOCK *pSock, SOCKADDR_IN *remSockAddrDest, + ST_CHAR **remAddrTxtOut, ST_INT *portOut) + { +SOCKADDR_IN peer; +SOCKADDR_IN *pp; +SOCK_ADDRLEN len; +ST_RET ret; + + if (remSockAddrDest) + pp = remSockAddrDest; + else + pp = &peer; + + len = sizeof (SOCKADDR_IN); + ret = getpeername (pSock->hSock, (struct sockaddr *) pp, &len); + if (ret == SD_SUCCESS) + { + if (remAddrTxtOut != NULL) + *remAddrTxtOut = inet_ntoa (pp->sin_addr); + + if (portOut != NULL) + /* first cast to ST_UINT to prevent sign extension for 0x8000-0xFFFF ports */ + *portOut = (ST_INT) ((ST_UINT) ntohs (pp->sin_port)); + } + return (ret); + } + + + /* -------------------------------------------- */ + /* User misc */ + /* -------------------------------------------- */ + +/************************************************************************/ +/* sockUsrFun */ +/*----------------------------------------------------------------------*/ +/* This function will call user function for all connections and close */ +/* the connection if the user function does not return SD_SUCCESS. */ +/* The secCtrl parameter is passed to the user function. */ +/************************************************************************/ +ST_VOID sockUsrFun (ST_RET (*usrFun)(ST_VOID *secCtrl), ST_CHAR *errMsg) +{ +GEN_SOCK_CTXT *sockCtx; +GEN_SOCK_CTRL *serviceCtrl; +GEN_SOCK *pSock; +ST_RET ret; + + if (!usrFun) + return; + + sockCtx = sockCtxList; + while (sockCtx) + { + SOCK_LOG_FLOW0 (sockCtx, "sockUsrFun"); + S_LOCK_UTIL_RESOURCES (); + + serviceCtrl = sockCtx->sockServiceList; + while (serviceCtrl != NULL) + { + /* Check all sockets associated with the service control */ + pSock = serviceCtrl->sockList; + while (pSock) + { + /* applies only to secured connections */ + if (pSock->sockCfg.secCtrl) + { + ret = (*usrFun) (pSock->sockCfg.secCtrl); + if (ret != SD_SUCCESS) + { + SOCK_LOG_ERR2 (sockCtx, "%s: %s, closing socket.", pSock->sockIdStr, errMsg); + sockClose(pSock); + } + } + pSock = (GEN_SOCK *)list_get_next (serviceCtrl->sockList, pSock); + } + serviceCtrl = (GEN_SOCK_CTRL *)list_get_next (sockCtx->sockServiceList, serviceCtrl); + } + + S_UNLOCK_UTIL_RESOURCES (); + + sockCtx = (GEN_SOCK_CTXT *)list_get_next (sockCtxList, sockCtx); + } +} + + /* -------------------------------------------- */ + /* Misc socket related functions */ + /* -------------------------------------------- */ + +/************************************************************************/ +/* convertIpAddr */ +/*----------------------------------------------------------------------*/ +/* This function will take pointer to IP address (host string or dotted */ +/* notation string) and convert it to unsigned long value. */ +/* If the useGetHostByName is SD_TRUE the gethostbyname() function will */ +/* be called when the inet_addr(ipAddrStr) produced INADDR_NONE return. */ +/* (host name was used or dotted notation was invalid). */ +/* RETURN: */ +/* ULONG != 0 converted IP Addr to ST_ULONG value or */ +/* 0 if function failed */ +/* Note: 0.0.0.0 would be invalid because we */ +/* return 0 for conversion error. */ +/************************************************************************/ +ST_ULONG convertIPAddr (ST_CHAR *ipAddrStr, ST_BOOLEAN useGetHostByName) +{ +ST_ULONG ipAddr = 0; +ST_CHAR *dotPtr; + +#ifdef _WIN32 +/* init WinSock interface */ +static ST_BOOLEAN bWSAStarted = SD_FALSE; +WSADATA wsaData; +ST_INT wRet; + + /* make sure sockets initialized before we call any socket functions */ + if (!bWSAStarted) + { + if (wRet = WSAStartup(0x0202, &wsaData)) + { + SLOGALWAYS1 ("convertIPAddr: unable to initialize WinSock interface to use version 2.2 (error=%d)", wRet); + return (ipAddr); + } + bWSAStarted = SD_TRUE; + } +#endif /* _WIN32 */ + + if (ipAddrStr == NULL || strlen(ipAddrStr) == 0) + { + SLOGALWAYS0 ("convertIPAddr: conversion failed, ipAddrStr=NULL or ipAddrStr is empty"); + return (ipAddr); + } + + /* Since inet_addr() considers following addresses valid: + a.b.c.d (Internet addr) + a.b.c (Class B addr) + a.b (Class A addr) + a stored directly + we will pass to inet_addr only valid ipAddrStr in form of Internet Addr */ + + /* call inet_addr if we find 3 '.' in the ipAddrStr (and do not use strtok) */ + if ((dotPtr = strstr(ipAddrStr, ".")) != NULL) + if ((dotPtr+1 < ipAddrStr+strlen(ipAddrStr)) && (dotPtr = strstr(dotPtr+1, ".")) != NULL) + if ((dotPtr+1 < ipAddrStr+strlen(ipAddrStr)) && (dotPtr = strstr(dotPtr+1, ".")) != NULL) + { + ipAddr = (ST_ULONG) inet_addr (ipAddrStr); + /* NOTE: some systems return from the inet_addr() unsigned int (LINUX) */ + /* and some return unsigned long (Windows). */ + } + + if (ipAddr == 0 || ipAddr == htonl(INADDR_NONE)) + { +#if !defined (VXWORKS) /* gethostbyname not supported */ + if (useGetHostByName) + { + struct hostent *pHostEnt = NULL; /* host database entry for remote host */ + /* UNIX IEEE: the behavior of gethostbyname() when passed a numeric */ + /* address string is unspecified */ + /* DEBUG: should we check for it? */ + pHostEnt = gethostbyname(ipAddrStr); + if (pHostEnt != NULL) + ipAddr = (ST_ULONG) (*(ST_UINT32 *)(pHostEnt->h_addr)); + else + { + ipAddr = 0; + SLOGALWAYS2 ("convertIPAddr : gethostbyname IPAddr='%s'conversion errno=%d", + ipAddrStr, SOCKET_ERRORNO); + } + } + else +#endif /* !defined (VXWORKS) */ + { + ipAddr = 0; + SLOGALWAYS1 ("convertIPAddr : IPAddr='%s'conversion error", ipAddrStr); + } + } + + return (ipAddr); +} + +/************************************************************************/ +/* sockEventPut */ +/* Put socket event on list. This should be called from callback */ +/* functions to save events on the list and return immediately. Other */ +/* threads can get events from the list later and process them. */ +/************************************************************************/ +ST_VOID sockEventPut (GEN_SOCK_CTXT *sockCtx, GEN_SOCK_EVENT *sockEvent) + { + S_LOCK_UTIL_RESOURCES (); + list_add_last (&sockCtx->sockEventList, sockEvent); + sockCtx->sockEventCount++; + S_UNLOCK_UTIL_RESOURCES (); + } + +/************************************************************************/ +/* sockEventGet */ +/* Get next socket event from list (to process the event). */ +/************************************************************************/ +int sockEventGet_pri=0; +GEN_SOCK_EVENT *sockEventGet (GEN_SOCK_CTXT *sockCtx) + { +GEN_SOCK_EVENT *sockEvent; + S_LOCK_UTIL_RESOURCES (); + sockEvent = (GEN_SOCK_EVENT *)list_get_first (&sockCtx->sockEventList); + if (sockEvent) + { + if(sockEventGet_pri) + printf("sockEvent->eventType=%d sockEventCount=%d\r\n",sockEvent->eventType,sockCtx->sockEventCount); + sockCtx->sockEventCount--; + } + S_UNLOCK_UTIL_RESOURCES (); + return (sockEvent); + } + + +/************************************************************************/ +/* sockEventQueueFlush */ +/************************************************************************/ + +ST_VOID sockEventQueueFlush (GEN_SOCK_CTXT *sockCtx, GEN_SOCK *pSock) + { +GEN_SOCK_EVENT *sockEvent; +GEN_SOCK_EVENT *nextSockEvent; + + S_LOCK_UTIL_RESOURCES (); + sockEvent = (GEN_SOCK_EVENT *) sockCtx->sockEventList; + + while (sockEvent) + { + nextSockEvent = (GEN_SOCK_EVENT *) list_get_next (sockCtx->sockEventList, sockEvent); + if (sockEvent->pSock == pSock) + { + list_unlink (&sockCtx->sockEventList, sockEvent); + chk_free (sockEvent); + } + sockEvent = nextSockEvent; + } + S_UNLOCK_UTIL_RESOURCES (); + } + + diff --git a/mmslib/util/glbsem.c b/mmslib/util/glbsem.c new file mode 100644 index 0000000..a79ad6b --- /dev/null +++ b/mmslib/util/glbsem.c @@ -0,0 +1,462 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2005, All Rights Reserved */ +/* */ +/* MODULE NAME : glbsem.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : Multi-thread support. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 03/12/08 JRB 77 gs_free_semx: make sure fname initialized. */ +/* 10/04/07 MDE 76 Tweaked LOGCFG_VALUE_GROUP/LOGCFGX_VALUE_MAP */ +/* 05/23/07 NAV 75 gs_get_semx: conditionally call sGetMsTime */ +/* 02/13/06 DSF 74 Migrate to VS.NET 2005 */ +/* 06/17/05 EJV 73 UNIX, Linux: need str_util.h */ +/* 06/10/05 DSF 72 Added an array to track calls to gs_free_semx*/ +/* 06/07/05 EJV 71 Added S_MT_SUPPORT to avoid Linux errors. */ +/* 05/23/05 EJV 70 Add gsLogMaskMapCtrl for parsing logcfg.xml */ +/* Moved gs_debug_sel from slog.c. */ +/* 05/23/05 JRB 69 Move all gs_timer* functions to glbtimer.c */ +/* 02/22/05 EJV 68 gs_timer_worker_thread: eliminated warnings */ +/* 01/10/05 DSF 67 Signal timer event after timer object is */ +/* unlinked */ +/* Don't call user callback if timer is */ +/* terminated */ +/* 08/23/04 EJV 66 GS_TIMER: rpl elapsed w/ ST_DOUBLE expiration*/ +/* 07/23/04 DSF 65 Set names of timer threads */ +/* 07/22/04 DSF 64 Set timer resolution back to 10 */ +/* 07/02/04 EJV 63 gs_timer_thread: chg sleep from 10 to 0 ms. */ +/* 06/17/04 DSF 62 Reset gs_timer_thread_stop in gs_timer_init()*/ +/* 05/05/04 EJV 61 gs_timer_cleanup: added timeout parameter. */ +/* Added timer worker threads to proc callbacks.*/ +/* gs_timer_init: added min_workers, max_workers*/ +/* 04/22/04 DSF 60 Initialized timer resolution to 1000 ms */ +/* 01/21/04 EJV 59 Win Timers: changed to use UNIX code. */ +/* Win impl preserved with _WIN32_timers define */ +/* 12/01/03 EJV 58 gs_is_win_ver: chk for corr ret 1, 0, -1. */ +/* 11/17/03 EJV 57 gs_timer_end: reverted moved gs_timer_remove.*/ +/* _WIN32: reworked periodic timers >430000ms; */ +/* All timer_id will go on delayed delete list*/ +/* 10/15/03 JRB 56 Move gs_debug_sel to slog.c, slogl.c. */ +/* 10/09/03 JRB 55 Enable gs_timer* functions for ALL systems. */ +/* 07/29/03 DSF,EJV 54 gs_timer_end: moved gs_timer_remove fun up. */ +/* 06/20/03 EJV 53 Del param from gs_mutex_get, gs_get_semx. */ +/* 06/12/03 EJV 52 Redesigned mutex sems implementation. */ +/* 06/06/03 JRB 51 Move _WIN32 code to new glbsem_w32.c */ +/* Move UNIX code to new glbsem_unix.c */ +/* Del OS2 code & "default" code. */ +/* Del unused gs_*_sig functions for DEC UNIX. */ +/* Add gs_util_mutex, init it in gs_init. */ +/* Chg GLBSEM_LOG_ALWAYS* to SLOGALWAYS*. */ +/* 06/03/03 EJV 50 _WIN32: changed for 64-bit compiler: */ +/* last param cast in RaiseException */ +/* gs_timer_callback last 3 parms to DWORD_PTR*/ +/* 04/14/03 JRB 49 Del intermediate functions for mutexes, */ +/* macros in glbsem.h use gs_mutex_get/free. */ +/* assert if gs_init fails (no way to recover). */ +/* 04/04/03 JRB 48 Chg _ASSERTE calls to assert, otherwise must */ +/* link DebugMultithreaded libs on Windows. */ +/* 03/24/03 EJV 47 Removed logging from some MUTEX functions. */ +/* gs_get_sem, gs_get_semx: added ASSERTE. */ +/* 02/03/03 EJV 46 _WIN32: added gs_is_win_ver() */ +/* added gs_get_named_event_sem() */ +/* 01/24/03 EJV 45 _WIN32 gs_start_thread: added comment. */ +/* 01/14/03 EJV 44 Added gs_sleep(). */ +/* 11/01/02 EJV 43 Use SISCO's link list with timers. */ +/* 10/30/02 EJV 42 gs_timer_check_list: limit delay to 1 sec. */ +/* Check if callback pending before deleting. */ +/* 10/31/02 EJV 41 gs_wait_mult_event_sem: corr activity memset */ +/* 07/29/02 EJV 40 Added gs_timer_get_resolution(), */ +/* Corrected timer termination wait. */ +/* Reverted timer _WIN32, added ptr wait list */ +/* 02/06/02 EJV 39 Compile this module if S_MT_SUPPORT defined */ +/* 12/04/01 KCR 38 cleared activity[] in gs_wait_mult_event_sem */ +/* 10/31/01 EJV 37 _WIN32: changed to call _beginthreadex; */ +/* Added gs_close_thread, gs_pulse_event_sem. */ +/* Replaced _ALWAYS macros with _ERR or _NERR. */ +/* _WIN32: gs_wait_thread now returns SD_FAILURE*/ +/* on timeout. */ +/* UNIX: gs_reset_event_sem now clears predicate*/ +/* 10/18/01 JRB 36 Eliminate warning. */ +/* 09/20/01 EJV 35 _WIN32 gs_timer_callback: check if pending */ +/* 08/01/01 JRB 34 gs_get_semx fill in fname even if NOT logging*/ +/* 07/30/01 EJV 33 Added gs_timer_set_resolution() fun. */ +/* _WIN32: reworked gs_timer functions. */ +/* 07/25/01 EJV 32 Changed gs_timer_resolution from 1000 to 10ms*/ +/* 07/24/01 EJV 31 _WIN32: added gs_timer support. */ +/* 05/17/01 EJV 30 _WIN32: eliminated compile warnings. */ +/* 04/04/01 DSF 29 Added gs_set_thread_name for WIN32 */ +/* 03/27/01 EJV 28 UNIX: gs_wait_event_sem, mutex the whole fun */ +/* 03/16/01 EJV 27 UNIX: added check to gs_free_event_sem. */ +/* UNIX: set thread attribute to joinable. */ +/* Removed #undef NDEBUG (now in make file) */ +/* 03/12/01 EJV 26 UNIX: added/changed few FLOW slogs. */ +/* UNIX: corr gs_wait_event_sem, predicate=0 */ +/* Removed , already in sysincs.h */ +/* Changed assert to _ASSERTE - def in sysincs.h*/ +/* 03/08/01 EJV 25 UNIX: Corrected type to ST_BOOLEAN for */ +/* static var gs_timer_thread_stop. Corr logs. */ +/* 03/07/01 EJV 24 UNIX: init attr before calling create thread.*/ +/* In gs_wait_event_sem check for predicate=1 */ +/* before entering the wait. */ +/* 02/19/01 EJV 23 _AIX: eliminated need to call gs_timer_init. */ +/* 02/14/01 EJV 22 Removed some DEBUG_SISCO around slog macros */ +/* AIX: added timer functions gs_timer_xxx. */ +/* 01/16/01 EJV 21 Moved GET_THREAD_ID define to glbsem.h */ +/* 12/27/00 EJV 20 _WIN32: Renamed glbCritSetion for easy calls.*/ +/* Added check for gs_already_inited. */ +/* 12/20/00 EJV 19 Ported to AIX. Revised DEC UNIX. */ +/* 12/13/00 EJV 18 Added gs_mutex_... user mutex functions. */ +/* Added gs_track for faster SISCO MUTEX. */ +/* Removed currSemOwner, semCount */ +/* Added few DEBUG_SISCO for __alpha. */ +/* 12/06/00 EJV 17 Changed gs_get_event_sem to accept arg. */ +/* USE_MANUAL_RESET_SEM define not necessary. */ +/* 10/25/00 JRB 16 Del gs_chk_thread_id. Found better way to */ +/* prevent errors (see "_MT" chk in glbsem.h). */ +/* 10/06/00 EJV 15 Ported to DEC UNIX (__alpha) pthread funcs. */ +/* Deleted unused: myThreadId,... */ +/* 10/06/00 EJV 14 _WIN32: corrected logging statements */ +/* 04/27/00 MDE 13 Lint cleanup */ +/* 03/14/00 JRB 12 Chg to allow breakpoint before assert. */ +/* 01/21/00 JRB 11 Del gs_install. Del function pointers. */ +/* gs_get_sem call gs_init if not already done. */ +/* Add "gs_chk_thread_id". */ +/* 12/16/99 NAV 10 in gs_free_semx watch for GS_LOG_FLOW */ +/* 09/13/99 MDE 09 Added SD_CONST modifiers */ +/* 08/05/99 JRB 08 Chged "gs_get_event_sem" to "auto-reset" */ +/* unless USE_MANUAL_RESET_SEM defined. */ +/* #ifdef'd out "gs_reset_event_sem". */ +/* Added partial support for __OS2__. */ +/* 03/01/99 DSF 07 Corrected #define releaseMutexSem for */ +/* non-DEBUG_SISCO version */ +/* 01/22/99 DSF 06 Use Critical Section instead of Mutex (faster)*/ +/* 10/08/98 MDE 05 Migrated to updated SLOG interface */ +/* 06/05/98 MDE 04 Fixed uninitialized 'rc' */ +/* 05/05/98 DSF 03 Added SD_TIMEOUT */ +/* 12/11/97 KCR 02 Added gs_wait_mult_event_sem for _WIN32 */ +/* 10/27/97 EJV 01 For !_WIN32 implementations: */ +/* Added typecast to define GET_THREAD_ID(); */ +/* Changed func gs_get_event_sem return from */ +/* from SD_FAILURE to (ST_EVENT_SEM) 0. */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + +#if defined (_WIN32) +#pragma warning(disable : 4996) +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "slog.h" +#include "glbsem.h" +#include "str_util.h" + +#if defined(S_MT_SUPPORT) + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/************************************************************************/ +/* GLOBAL VARIABLES */ + +ST_UINT gs_debug_sel = GS_LOG_ERR | GS_LOG_NERR; + +#ifdef DEBUG_SISCO +SD_CONST ST_CHAR *SD_CONST _glbem_flow_logstr = "GS_LOG_FLOW"; +SD_CONST ST_CHAR *SD_CONST _glbem_err_logstr = "GS_LOG_ERR"; +SD_CONST ST_CHAR *SD_CONST _glbem_nerr_logstr = "GS_LOG_NERR"; + +LOGCFGX_VALUE_MAP gsLogMaskMaps[] = + { + {"GS_LOG_ERR", GS_LOG_ERR, &gs_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Error"}, + {"GS_LOG_NERR", GS_LOG_NERR, &gs_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Notice"}, + {"GS_LOG_FLOW", GS_LOG_FLOW, &gs_debug_sel, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Flow"}, + }; + +LOGCFG_VALUE_GROUP gsLogMaskMapCtrl = + { + {NULL,NULL}, + "SemaphoreLogMasks", /* Parent Tag */ + sizeof(gsLogMaskMaps)/sizeof(LOGCFGX_VALUE_MAP), + gsLogMaskMaps + }; +#endif /* DEBUG_SISCO */ + +/* variables to evalueate semaphores locking performance */ +ST_DOUBLE gs_hwMutexTime; +ST_DOUBLE gs_hwEventTime; + +ST_MUTEX_SEM gs_glb_mutex; /* global SISCO MUTEX semaphore */ +ST_MUTEX_SEM gs_util_mutex; /* UTILITY MUTEX semaphore: for "low-level"*/ + /* util functs (slog,mem_chk,stime,etc.)*/ + +ST_BOOLEAN gs_already_inited = SD_FALSE; + +#if defined(DEBUG_SISCO) +/* The debug version keeps a stack of sem owners call locations */ +/* which can be logged to aid in debugging. */ +/* These variables are only changed by a thread that owns the sem, but */ +/* can be read (for logging) by 'gs_log_sem_state', possibly resulting */ +/* in a 'torn' log if the called is not careful. */ + +#define MAX_SEM_NEST_TRACK 20 +ST_UINT gs_track; /* This variable when set to value >0 */ + /* during an application startup allows */ + /* tracking of MUTEX or EVENT sem. */ +ST_INT gs_currSemOwnerIndex; +ST_CHAR gs_currSemOwnerFile[MAX_SEM_NEST_TRACK][SLOG_MAX_FNAME+1]; +ST_INT gs_currSemOwnerLine[MAX_SEM_NEST_TRACK]; +ST_CHAR gs_currSemFreeFile[MAX_SEM_NEST_TRACK][SLOG_MAX_FNAME+1]; +ST_INT gs_currSemFreeLine[MAX_SEM_NEST_TRACK]; + +#endif /* DEBUG_SISCO */ + + + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + /* */ + /* SISCO's GLOBAL MUTEX SEMAPHORE FUNCTIONS */ + /* */ + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + +/************************************************************************/ +/* gs_init */ +/*----------------------------------------------------------------------*/ +/* Initialize global SISCO MUTEX semaphore. */ +/* This function will be called from the gs_get_sem or gs_get_semx, */ +/* it does not have to be called from user application. */ +/* Parameters: */ +/* none */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/************************************************************************/ + +ST_RET gs_init (ST_VOID) + { +ST_RET rc; + +/* !!! To avoid infinite loop with SLOG do not log from this function. */ + + if (gs_already_inited) + return (SD_SUCCESS); + +/* WARNING: The gs_util_mutex should not be changed to use named mutex */ +/* because logging in the code handling named mutex will cause */ +/* infinite loop. */ + +/* Initialize the MUTEX semaphores. Both must succeed, so OR the returns.*/ + rc = gs_mutex_create (&gs_glb_mutex); + rc |= gs_mutex_create (&gs_util_mutex); + +/* Set up to track the semaphore owners by nesting level */ +#if defined(DEBUG_SISCO) + gs_currSemOwnerIndex = -1; +#endif + + if (rc == SD_SUCCESS) + gs_already_inited = SD_TRUE; + else + assert (0); /* nothing will work properly if this fails. */ + + return (rc); + } + +/************************************************************************/ +/* gs_log_sem_state */ +/*----------------------------------------------------------------------*/ +/* Log the global SISCO MUTEX semaphore owner stack. */ +/* Parameters: */ +/* none */ +/* Return values: */ +/* none */ +/************************************************************************/ + +ST_VOID gs_log_sem_state (ST_VOID) + { +#if defined(DEBUG_SISCO) +ST_INT i; + + if (!gs_already_inited) /* Make sure gs is initialized. */ + return; + + SLOGALWAYS0 ("GLBSEM: Semaphore owner stack (oldest to latest) :"); + for (i = 0; i <= gs_currSemOwnerIndex && i < MAX_SEM_NEST_TRACK; ++i) + { + SLOGCALWAYS3 (" %d) File %s, Line %d", + i+1, gs_currSemOwnerFile[i], gs_currSemOwnerLine[i]); + } + if (gs_currSemOwnerIndex >= MAX_SEM_NEST_TRACK) + SLOGCALWAYS0 (" Sem's nested too deep to track further"); +#endif + } + +/************************************************************************/ +/* gs_get_semx */ +/*----------------------------------------------------------------------*/ +/* Lock (obtain ownership) the global SISCO MUTEX semaphore. */ +/* This debug version function keeps track of the sem owner stack. */ +/* If compiled without DEBUG_SISCO it just falls through to gs_get_sem. */ +/* If compiled with DEBUG_SISCO the gs_track variable need to be set to */ +/* value >0 to enable the tracking code. This way logging can be used */ +/* by an application without degradation of the MUTEX sem performance. */ +/* In addition the gs_debug_sel need to be set to GS_LOG_FLOW to */ +/* log the tracking results. */ +/* Parameters: */ +/* srcFile ptr to source code file name calling this fun */ +/* srcLineNum source code line number */ +/* Return values: */ +/* none */ +/* CRITICAL: gs_get_semx must NOT be called from any slog or stime */ +/* functions. It calls slog and stime functions which would cause */ +/* an infinite loop. Slog and stime must call gs_mutex_get. */ +/************************************************************************/ + +ST_VOID gs_get_semx (SD_CONST ST_CHAR *srcFile, ST_INT srcLineNum) + { +#if defined(DEBUG_SISCO) +ST_CHAR fname[SLOG_MAX_FNAME+1]; +ST_DOUBLE startTime; +ST_DOUBLE endTime; +ST_DOUBLE elapsedTime; + + if (!gs_already_inited) /* Make sure gs is initialized. */ + gs_init (); + + if (gs_track) + startTime = sGetMsTime (); + + gs_mutex_get (&gs_glb_mutex); + + if (gs_track) + { + endTime = sGetMsTime (); + + elapsedTime = endTime - startTime; + if (elapsedTime > gs_hwMutexTime) + gs_hwMutexTime = elapsedTime; + + if (srcFile != NULL) + slogTrimFileName (fname, srcFile); + else + strcpy (fname, "Unknown"); + + if (gs_debug_sel & GS_LOG_FLOW) + { + GLBSEM_LOG_FLOW2 ("GLBSEM: File %s, Line %d has the mutex", + fname, srcLineNum); + GLBSEM_LOG_CFLOW2 (" took %.3f sec (hw = %.3f)", + elapsedTime/1000, gs_hwMutexTime/1000); + } + + ++gs_currSemOwnerIndex; + if (gs_currSemOwnerIndex < MAX_SEM_NEST_TRACK) + { + strcpy (gs_currSemOwnerFile[gs_currSemOwnerIndex], fname); + gs_currSemOwnerLine[gs_currSemOwnerIndex] = srcLineNum; + } + else + { + GLBSEM_LOG_CFLOW0 (" Nested too deep to track"); + } + } +#else /* Not DEBUG_SISCO */ + + gs_mutex_get (&gs_glb_mutex); + +#endif /* DEBUG_SISCO */ + } + +/************************************************************************/ +/* gs_free_semx */ +/*----------------------------------------------------------------------*/ +/* Unlock (release ownership) the global SISCO MUTEX semaphore. */ +/* This debug version function keeps track of the sem owner stack. */ +/* If compiled without DEBUG_SISCO is just falls through to gs_free_sem.*/ +/* If compiled with DEBUG_SISCO the gs_track variable need to be set to */ +/* value >0 to enable the tracking code. This way logging can be used */ +/* by an application without degradation of the MUTEX sem performance. */ +/* In addition the gs_debug_sel need to be set to GS_LOG_FLOW to log */ +/* the tracking results. */ +/* Parameters: */ +/* srcFile ptr to source code file name calling this fun */ +/* srcLineNum source code line number */ +/* Return values: */ +/* none */ +/* CRITICAL: gs_free_semx must NOT be called from any slog or stime */ +/* functions. It calls slog and stime functions which would cause */ +/* an infinite loop. Slog and stime must call gs_mutex_free. */ +/************************************************************************/ + +ST_VOID gs_free_semx (SD_CONST ST_CHAR *srcFile, ST_INT srcLineNum) + { +#if defined(DEBUG_SISCO) +ST_CHAR fname[SLOG_MAX_FNAME+1]; +ST_INT idx; + + if (!gs_already_inited) /* Make sure gs is initialized. */ + { + GLBSEM_LOG_ERR0 ("GLBSEM gs_free_semx error: global mutex semaphore not initialized"); + return; + } + + if (gs_track) + { + if (srcFile != NULL) + slogTrimFileName (fname, srcFile); + else + strcpy (fname, "Unknown"); + + GLBSEM_LOG_FLOW2 ("GLBSEM: File %s, Line %d freeing the semaphore", + fname, srcLineNum); + + idx = gs_currSemOwnerIndex; + --gs_currSemOwnerIndex; + if (gs_currSemOwnerIndex == -1) + { + GLBSEM_LOG_CFLOW0 (" The semaphore should now be free"); + } + else if (gs_currSemOwnerIndex >= 0 && gs_currSemOwnerIndex < MAX_SEM_NEST_TRACK) + { + GLBSEM_LOG_CFLOW2 (" File %s, Line %d now has the semaphore", + gs_currSemOwnerFile[gs_currSemOwnerIndex], + gs_currSemOwnerLine[gs_currSemOwnerIndex]); + strcpy (gs_currSemFreeFile[idx], fname); + gs_currSemFreeLine[idx] = srcLineNum; + if (strcmpi (gs_currSemFreeFile[idx], gs_currSemOwnerFile[idx])) + { + GLBSEM_LOG_ERR2 ("Possible problem: %s (%d)", gs_currSemOwnerFile[idx], + gs_currSemOwnerLine[idx]); + } + } + else if (gs_currSemOwnerIndex >= 0 && gs_currSemOwnerIndex >= MAX_SEM_NEST_TRACK) + { + GLBSEM_LOG_CFLOW0 (" Nested too deep to track"); + } + else if (gs_currSemOwnerIndex < -1) + { + GLBSEM_LOG_ERR0 ("GLBSEM gs_free_semx error: Sem track index negative"); + gs_currSemOwnerIndex = -1; + } + } +#endif /* DEBUG_SISCO */ + + gs_mutex_free (&gs_glb_mutex); + } + +#endif /* defined(S_MT_SUPPORT) */ diff --git a/mmslib/util/glbsem_unix.c b/mmslib/util/glbsem_unix.c new file mode 100644 index 0000000..a909f10 --- /dev/null +++ b/mmslib/util/glbsem_unix.c @@ -0,0 +1,1064 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2008, All Rights Reserved */ +/* */ +/* MODULE NAME : glbsem_unix.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : Multi-thread support for UNIX-like systems ONLY.*/ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/29/08 EJV 11 Use S_FMT_* macros to log pointers & handles.*/ +/* 12/12/05 JRB 10 Disable gs_wait_mult_event_sem with #if 0 to */ +/* catch problems at compile time, not run time.*/ +/* 06/06/05 EJV 09 Added S_MT_SUPPORT to avoid Linux errors. */ +/* 11/04/03 JRB 08 Del gs_sleep (use sMsSleep). */ +/* 10/09/03 JRB 07 Use thisThreadId only if DEBUG_SISCO. */ +/* Use clock_gettime for default system. */ +/* gs_start_thread: don't init threadHandle=NULL*/ +/* 08/25/03 JRB 06 gs_sleep: use rqtp.tv_sec if ms >= 1000. */ +/* 06/20/03 EJV 05 Renamed gs_mutex_get to gs_mutex_get_tm. */ +/* Del param from gs_mutex_get calls. */ +/* 06/12/03 EJV 04 Redesigned mutex sems implementation. */ +/* 06/11/03 EJV 03 Added empty functions: gs_named_mutex_xxx */ +/* and gs_get_named_event_sem */ +/* Added thisFileName, del unmatched #if */ +/* 06/06/03 JRB 02 Del logging in gs_mutex_get, gs_mutex_free. */ +/* 06/06/03 JRB 01 NEW. Code taken out of glbsem.c */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "slog.h" +#include "glbsem.h" + +#if defined(S_MT_SUPPORT_RXB) + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +static ST_RET _gs_sig_event_sem (ST_EVENT_SEM es, ST_INT predicate); + +/*======================================================================*/ +/* UNIX FUNCTIONS complying with POSIX 1003.1c */ +/*======================================================================*/ + + + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + /* */ + /* MUTEX SEMAPHORE FUNCTIONS for */ + /* _AIX, __alpha */ + /* */ + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + + +/************************************************************************/ +/* gs_mutex_create */ +/*----------------------------------------------------------------------*/ +/* Creates and initializes MUTEX seamphore. */ +/* Parameters: */ +/* ms pointer to mutex sem struct */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/************************************************************************/ + +ST_RET gs_mutex_create (pthread_mutex_t *ms) + { +ST_RET ret; +ST_INT result; +pthread_mutexattr_t mutexattr; +#if defined(DEBUG_SISCO) +ST_THREAD_ID thisThreadId = GET_THREAD_ID(); +#endif + + ret = SD_FAILURE; + + /* Initialize the mutex attributes variable (needed only for mutex init) */ + + result = pthread_mutexattr_init (&mutexattr); + if ( result != 0 ) + { + GLBSEM_LOG_ERR3 ("GLBSEM gs_mutex_create error: Thread " S_FMT_PTR " failed to initialize" + " mutex semaphore ms=" S_FMT_PTR " attributes (error=%d).", + thisThreadId, ms, result); + return (ret); + } + + /* Set the mutex attributes (mutex type to PTHREAD_MUTEX_RECURSIVE). */ + + /* The semaphore type could not be PTHREAD_MUTEX_ERRORCHECK because */ + /* in the DEC UNIX manual there is a warning that "DECthreads does not*/ + /* currently detect deadlock conditions involving more then one mutex,*/ + /* but may in the future." Because of this restriction and the fact */ + /* that ICCP Toolkit is implementing an independent mutex semaphore */ + /* (currently PTHREAD_MUTEX_NORMAL may be changed to ERRORCHECK) or */ + /* possibility that user application may want to use the ERRORCHECK */ + /* semaphore we decided to use the PTHREAD_MUTEX_RECURSIVE. */ + + /* If the semaphore type is PTHREAD_MUTEX_ERRORCHECK then it will */ + /* return an error if the current owner of the semaphore tries */ + /* to lock the mutex again (or thread tries to unlock mutex that it */ + /* does not own). */ + + result = pthread_mutexattr_settype (&mutexattr, PTHREAD_MUTEX_RECURSIVE); + if ( result != 0 ) + { + GLBSEM_LOG_ERR3 ("GLBSEM gs_mutex_create error: thread " S_FMT_PTR " failed to set mutex" + " semaphore ms=" S_FMT_PTR " attributes (error=%d).", + thisThreadId, ms, result); + switch ( result ) + { + case EINVAL: + GLBSEM_LOG_CERR0 ("error=EINVAL (invalid mutex attribute or type)."); + break; + case ESRCH: + GLBSEM_LOG_CERR0 ("error=ESRCH (non existing mutex attributes object)."); + break; + } + + pthread_mutexattr_destroy (&mutexattr); + return (ret); + } + + /* Initialize the mutex with specific attributes. The mutex will be */ + /* in the unlocked state. */ + + result = pthread_mutex_init (ms, &mutexattr); + if ( result != 0 ) + { + GLBSEM_LOG_ERR3 ("GLBSEM gs_mutex_create error: thread " S_FMT_PTR " failed to initialize" + " mutex semaphore ms=" S_FMT_PTR " (error=%d).", + thisThreadId, ms, result); + switch ( result ) + { + case EAGAIN: + GLBSEM_LOG_CERR0 ("error=EAGAIN (system resouces not available)."); + break; + case ENOMEM: + GLBSEM_LOG_CERR0 ("error=ENOMEM (insufficient memory for mutex" + " initialization)."); + break; + case EBUSY: + GLBSEM_LOG_CERR0 ("error=EBUSY (programs requested mutex" + " reinitialization)."); + break; + case EINVAL: + GLBSEM_LOG_CERR0 ("error=EINVAL (invalid mutex argument)."); + break; + case EPERM: + GLBSEM_LOG_CERR0 ("error=EPERM (insufficient privileges)."); + break; + } + + pthread_mutexattr_destroy (&mutexattr); + return (ret); + } + + /* release the mutex attributes object - not needed anymore */ + pthread_mutexattr_destroy (&mutexattr); + + GLBSEM_LOG_FLOW2 ("GLBSEM gs_mutex_create: thread " S_FMT_PTR " initialized " + " mutex semaphore ms=" S_FMT_PTR ".", thisThreadId, ms); + + /* initialized the mutex successfully */ + ret = SD_SUCCESS; + + return (ret); + } + +/************************************************************************/ +/* gs_named_mutex_create */ +/*----------------------------------------------------------------------*/ +/* Create/Open NAMED mutex. */ +/* For each call to this function the gs_named_mutex_destroy must be */ +/* called. */ +/* Parameters: */ +/* ms pointer to mutex object */ +/* name pointer to mutex name. */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/************************************************************************/ + +#if 0 /* DEBUG: To be implemented later */ +ST_RET gs_named_mutex_create (ST_MUTEX_SEM *ms, ST_CHAR *name) + { +ST_RET ret = SD_FAILURE; + + /* To be implemented */ + return (ret); + } +#endif /* DEBUG: To be implemented later */ + +/************************************************************************/ +/* gs_mutex_get_tm */ +/*----------------------------------------------------------------------*/ +/* Lock the MUTEX semaphore ms. */ +/* Parameters: */ +/* ms pointer to mutex sem struct */ +/* timeout this parameter is ignored in UNIX implementation*/ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/* CRITICAL: gs_mutex_get_tm must NOT call any slog, stime, or mem_chk */ +/* functions. These functions call ge_mutex_get which would cause */ +/* an infinite loop. */ +/************************************************************************/ + +ST_RET gs_mutex_get_tm (ST_MUTEX_SEM *ms, ST_LONG timeout) + { +ST_INT result; + + if (!gs_already_inited) /* Make sure gs is initialized. */ + gs_init (); + + /* Because the mutex semaphore type is PTHREAD_MUTEX_RECURSIVE it */ + /* will allow to relock the mutex by the thread that owns the mutex */ + /* without blocking. The lock count is incremented for each recursive */ + /* lock within the thread. */ + /* If the mutex is locked by another thread, the calling thread will */ + /* wait until the mutex become available. */ + + result = pthread_mutex_lock (ms); + assert (result==0); /* otherwise threads will overwrite each other's data */ + + if (result == 0) + return (SD_SUCCESS); + else + return (SD_FAILURE); + } + +/************************************************************************/ +/* gs_mutex_free */ +/*----------------------------------------------------------------------*/ +/* Unlock the MUTEX semaphore ms. */ +/* Parameters: */ +/* ms pointer to mutex sem struct */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/* CRITICAL: gs_mutex_free must NOT call any slog, stime, or mem_chk */ +/* functions. These functions call ge_mutex_free which would cause */ +/* an infinite loop. */ +/************************************************************************/ +ST_RET gs_mutex_free (ST_MUTEX_SEM *ms) + { +ST_INT result; + + /* Because the mutex semaphore type is PTHREAD_MUTEX_RECURSIVE */ + /* if the calling thread owns the mutex the lock count is decremented.*/ + /* the mutex remains owned by the calling thread until the count is 0.*/ + /* When the count becomes 0 the mutex is unlocked and can be grabed by*/ + /* next waiting thread. */ + + result = pthread_mutex_unlock (ms); + assert (result==0); /* otherwise threads will overwrite each other's data */ + + if (result == 0) + return (SD_SUCCESS); + else + return (SD_FAILURE); + } + +/************************************************************************/ +/* gs_mutex_destroy */ +/*----------------------------------------------------------------------*/ +/* Free all resources allocated for the MUTEX semaphore ms. */ +/* Parameters: */ +/* ms pointer to mutex sem struct */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/************************************************************************/ +ST_RET gs_mutex_destroy (pthread_mutex_t *ms) + { +ST_RET ret; +ST_INT result; +#if defined(DEBUG_SISCO) +ST_THREAD_ID thisThreadId = GET_THREAD_ID(); +#endif + + ret = SD_FAILURE; + + /* The pthread_mutex_destroy function deinitializes the ms mutex */ + /* semaphore. THe function is successful only if the mutex is not */ + /* referenced or locked. */ + + result = pthread_mutex_destroy (ms); + if ( result != 0 ) + { + /* Log a major error here */ + GLBSEM_LOG_ERR3 ("GLBSEM gs_mutex_destroy error: thread " S_FMT_PTR + " failed to destroy mutex semaphore ms=" S_FMT_PTR " (error=%d)", + thisThreadId, ms, result); + switch ( result ) + { + case EBUSY: + GLBSEM_LOG_CERR0 ("error=EBUSY (semaphore locked or referenced)"); + break; + case EINVAL: + GLBSEM_LOG_CERR0 ("error=EINVAL (invalid mutex semaphore)"); + break; + } + + return (ret); + } + + GLBSEM_LOG_FLOW2 ("GLBSEM gs_mutex_destroy: thread " S_FMT_PTR " destroyed mutex" + " semaphore ms=" S_FMT_PTR ".", thisThreadId, ms); + + /* destroy mutex successful */ + ret = SD_SUCCESS; + + return (ret); + } + + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + /* */ + /* USER's EVENT SEMAPHORE FUNCTIONS for */ + /* _AIX, __alpha */ + /* */ + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + +/************************************************************************/ +/* gs_get_event_sem */ +/*----------------------------------------------------------------------*/ +/* Creates and initializes an event semaphore. */ +/* The event semaphore is implemented using PTHREADs Condition Variable.*/ +/* Parameters: */ +/* ST_BOOLEAN manualReset Type of event sem */ +/* Return values: */ +/* ST_EVENT_SEM handle (pointer) to event semaphore */ +/* NULL if function failed */ +/************************************************************************/ + +ST_EVENT_SEM gs_get_event_sem (ST_BOOLEAN manualReset) + { +ST_INT result; +ST_EVENT_SEM es = NULL; /* pointer to event sem struct */ +#if defined(DEBUG_SISCO) +ST_THREAD_ID thisThreadId = GET_THREAD_ID(); /* Let's see just who we are */ +#endif + + /* allocate the memory for the event sem */ + + es = (ST_EVENT_SEM) chk_calloc (1, sizeof (GS_EVENT_SEM)); + if ( es == NULL ) + { + GLBSEM_LOG_ERR1 ("GLBSEM gs_get_event_sem error: thread " S_FMT_PTR + " (allocate memory failed).", thisThreadId); + return (NULL); + } + + /* crete mutex for the condition variable */ + if ( gs_mutex_create (&es->mutex) != SD_SUCCESS ) + { + GLBSEM_LOG_ERR1 ("GLBSEM gs_get_event_sem error: thread " S_FMT_PTR + " (gs_mutex_create failed).", thisThreadId); + + chk_free (es); + return (NULL); + } + + /* Condition Variable attributes are currently not implemented, use NULL */ + result = pthread_cond_init (&es->cond, NULL); + if ( result != 0 ) + { + GLBSEM_LOG_ERR2 ("GLBSEM gs_get_event_sem error: thread " S_FMT_PTR + " (pthread_cond_init failed result=%d),", thisThreadId, result); + switch ( result ) + { + case EAGAIN: + GLBSEM_LOG_CERR0 ("result=EAGAIN (system resouces not available)."); + break; + case ENOMEM: + GLBSEM_LOG_CERR0 ("result=ENOMEM (insufficient memory for mutex" + " initialization)."); + break; + case EBUSY: + GLBSEM_LOG_CERR0 ("result=EBUSY (programs requested condition variable" + " reinitialization)."); + break; + case EINVAL: + GLBSEM_LOG_CERR0 ("result=EINVAL (invalid attr argument)."); + break; + } + gs_mutex_destroy (&es->mutex); + chk_free (es); + return (NULL); + } + + GLBSEM_LOG_FLOW2 ("GLBSEM gs_get_event_sem: thread " S_FMT_PTR " initialized event sem es=" S_FMT_PTR ".", + thisThreadId, es); + + /* successfully initialized the event semaphore */ + es->manualReset = manualReset; + return (es); + } + +/************************************************************************/ +/* gs_get_named_event_sem */ +/*----------------------------------------------------------------------*/ +/* Create a "manual-reset" or "auto-reset" NAMED event semaphore. */ +/* Parameters: */ +/* name pointer to semaphore name. */ +/* manualReset SD_TRUE or SD_FALSE */ +/* Return values: */ +/* ST_EVENT_SEM handle to named event semaphore object */ +/************************************************************************/ + +#if 0 /* DEBUG: To be implemented later */ +ST_EVENT_SEM gs_get_named_event_sem (ST_CHAR *name, ST_BOOLEAN manualReset) + { +ST_EVENT_SEM retEventSem = NULL; + + /* To be implemented */ + return (retEventSem); + } +#endif /* DEBUG: To be implemented later */ + +/************************************************************************/ +/* gs_wait_event_sem */ +/*----------------------------------------------------------------------*/ +/* Wait for event semaphore es until it becomes signaled or timeout */ +/* occurrs. */ +/* If compiled with DEBUG_SISCO the gs_track variable need to be set to */ +/* value >0 to enable the timing code. This way logging can be used */ +/* by an application without degradation of the EVENT sem performance. */ +/* Parameters: */ +/* es event semaphore object (pointer) */ +/* timeout interval in milliseconds to wait for the es to */ +/* be signaled, if -1L then the function will be */ +/* blocked indefinitely until the event semaphore */ +/* is signaled. */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/* SD_TIMEOUT timeout occurred */ +/************************************************************************/ + +ST_RET gs_wait_event_sem (ST_EVENT_SEM es, ST_LONG timeout) + { +ST_RET ret; +ST_INT result; +struct timespec tsDelta; +struct timespec tsAbstime; +#if defined(DEBUG_SISCO) +ST_DOUBLE startTime; +ST_DOUBLE endTime; +ST_DOUBLE elapsedTime; +ST_THREAD_ID thisThreadId = GET_THREAD_ID(); /* Let's see just who we are */ +#endif +#if defined(linux) +struct timeval curtimeval; /* for gettimeofday */ +#endif + + ret = SD_FAILURE; + + if (!es) + { + GLBSEM_LOG_ERR1 ("GLBSEM gs_wait_event_sem error: thread " S_FMT_PTR " (invalid es=NULL)", + thisThreadId); + return (ret); + } + + /* mutex for the specified condition variable must be locked before */ + /* going into wait or checking preedicate */ + gs_mutex_get (&es->mutex); + + /* Note: according to the docummentation we may not capture the */ + /* signaling of conditional variable if a thread was not waiting*/ + /* for it, since the signaling of the condition is not held */ + /* (AIX and maybe other UNIX systems). */ + /* Let check the predicate for the conditional variable first to*/ + /* see if it was set and act accordingly. */ + + /* To simulate Windows manual-reset semaphore if gs_signal_event_sem */ + /* was used then the semaphore remains signaled until it is exlicitly */ + /* reset to non-signaled state by calling gs_reset_event_sem. */ + /* If it is auto-reset semaphore and ge_signal_event_sem was used but */ + /* no thread was waiting then the sem remains signaled until a thread */ + /* is released. */ + + if (es->predicate == 1) + { + /* conditional variable was signaled before we entered the wait */ + if (es->manualReset == SD_FALSE) + es->predicate = 0; /* simulate release of a waiting thread */ + gs_mutex_free (&es->mutex); + GLBSEM_LOG_FLOW2 ("GLBSEM gs_wait_event_sem: thread " S_FMT_PTR + " returned from wait for es=" S_FMT_PTR " (on entry p=1)", + thisThreadId, es); + return (SD_SUCCESS); + } + /* If gs_pulse_event_sem was used the state of the semaphore should */ + /* be always in non-signaled state when this function is entered. */ + +#if defined(DEBUG_SISCO) + if (gs_track) + startTime = sGetMsTime (); +#endif + + /* set the absolute wait time */ + if ( timeout >= 0 ) + { + tsDelta.tv_sec = timeout / 1000L; + tsDelta.tv_nsec = (timeout % 1000L) * 1000000L; /* nanoseconds */ + +#if defined(_AIX) || (defined(__alpha) && !defined(__VMS)) + /* obtain abosolute time for wakeup */ + result = pthread_get_expiration_np (&tsDelta, &tsAbstime); + if ( result != 0 ) + { + GLBSEM_LOG_ERR3 ("GLBSEM gs_wait_event_sem error: thread " S_FMT_PTR ", es=" S_FMT_PTR + " (pthread_get_expiration_np failed result=%d)", + thisThreadId, es, result); + gs_mutex_free (&es->mutex); + return (ret); + } +#else /* all other systems */ + /* Get current time & add timeout to it. */ +#if defined(linux) + /* LINUX linker can't find "clock_gettime" so use "gettimeofday".*/ + gettimeofday (&curtimeval,NULL); + tsAbstime.tv_sec = curtimeval.tv_sec; /* convert timeval to timespec */ + tsAbstime.tv_nsec = curtimeval.tv_usec*1000; +#else + clock_gettime (CLOCK_REALTIME, &tsAbstime); /* gives timespec, which we want*/ +#endif + tsAbstime.tv_sec += tsDelta.tv_sec; + tsAbstime.tv_nsec += tsDelta.tv_nsec; + /* adjust if (nsec) > 1000000000 */ + if (tsAbstime.tv_nsec / 1000000000 > 0) + { /* in this case, should be EXACTLY = 1 */ + tsAbstime.tv_sec++; /* add 1 second */ + tsAbstime.tv_nsec = tsAbstime.tv_nsec % 1000000000; + } +#endif /* all other systems */ + } + + /* wait until condition signaled or timeout */ + es->predicate = 0; + while ( !es->predicate ) + { + if ( timeout < 0 ) + /* wait indefinitely */ + result = pthread_cond_wait (&es->cond, &es->mutex); + else + /* wait for a period of time, if timeout=0 then fun returns immediatelly */ + result = pthread_cond_timedwait (&es->cond, &es->mutex, &tsAbstime); + + if ( result == 0 ) + { + if (es->predicate) + { + /* if gs_signal_event_sem used then state of predicate will */ + /* remain set until exlicitly reset by gs_reset_event_sem. */ + if (es->manualReset == SD_TRUE && es->predicate == 1) + { + /* do not reset the predicate */ + } + else + es->predicate = 0; + ret = SD_SUCCESS; /* cond var was signaled */ + GLBSEM_LOG_FLOW2 ("GLBSEM gs_wait_event_sem: thread " S_FMT_PTR + " returning from wait for es=" S_FMT_PTR " (success)", + thisThreadId, es); + break; /* exit while */ + } + else + { + if (es->manualReset == SD_TRUE) + { + /* On Windows manual-reset semaphore calling PulseEvent allows*/ + /* to wake up all waiting threads. We will simulate this */ + /* behavior here by ignoring the predicate=0 because other */ + /* thread probably did reset it already. */ + ret = SD_SUCCESS; /* cond var was signaled */ + GLBSEM_LOG_FLOW2 ("GLBSEM gs_wait_event_sem: thread " S_FMT_PTR + " returning from wait for es=" S_FMT_PTR ".", + thisThreadId, es); + break; /* exit while */ + } + else + { + /* On Windows the auto-reset semaphore will allow to wake */ + /* only one thread, so we have to go back to waiting state */ + /* for this thread. */ + + GLBSEM_LOG_FLOW2 ("GLBSEM gs_wait_event_sem: thread " S_FMT_PTR + " spurious wake up for es=" S_FMT_PTR ".", + thisThreadId, es); + continue; + } + } + } + else if (result == ETIMEDOUT) + { + /* it is possible that the predicate was set shortly before timeout */ + if (es->predicate) + { + ret = SD_SUCCESS; /* cond variable signaled */ + GLBSEM_LOG_FLOW2 ("GLBSEM gs_wait_event_sem: thread " S_FMT_PTR + " returned from wait for es=" S_FMT_PTR " (timeout but p=1).", + thisThreadId, es); + } + else + { + ret = SD_TIMEOUT; /* timeout */ + GLBSEM_LOG_FLOW3 ("GLBSEM gs_wait_event_sem: thread " S_FMT_PTR ", es=" S_FMT_PTR + " (timeout of %d ms)", thisThreadId, es, timeout); + } + es->predicate = 0; /* clear for next time */ + break; /* exit while */ + } + else + { + GLBSEM_LOG_ERR3 ("GLBSEM gs_wait_event_sem error: thread " S_FMT_PTR ", es=" S_FMT_PTR + " (pthread_cond_(timed)wait failed result=%d)", + thisThreadId, es, result); + es->predicate = 0; /* clear for next time */ + break; /* exit while */ + } + } /* end while */ + + /* release the mutex semaphore for the conditional variable */ + gs_mutex_free (&es->mutex); + +#if defined(DEBUG_SISCO) + if (gs_track) + { + endTime = sGetMsTime (); + elapsedTime = endTime - startTime; + if (elapsedTime > gs_hwEventTime) + gs_hwEventTime = elapsedTime; + } +#endif /* defined(DEBUG_SISCO) */ + + return (ret); + } + +/************************************************************************/ +/* gs_wait_mult_event_sem */ +/*----------------------------------------------------------------------*/ +/* NOT IMPLEMENTED. */ +/* Wait for event semaphore es until it becomes signaled or timeout */ +/* occurrs. */ +/* Parameters: */ +/* numEvents number of event semaphores to wait for */ +/* esTable pointer to table of event semaphore objects */ +/* activity pointer to table where this function will mark */ +/* proper index entry with SD_TRUE for the event */ +/* semaphore that have been signaled */ +/* timeout interval in milliseconds to wait for the es to */ +/* be signaled, if -1L then the function will be */ +/* blocked indefinitely until the event semaphore */ +/* is signaled. */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/* SD_TIMEOUT timeout */ +/************************************************************************/ +#if 0 /* DEBUG: Not implemented on this platform. Is it needed? */ +ST_RET gs_wait_mult_event_sem (ST_INT numEvents, ST_EVENT_SEM *esTable, + ST_BOOLEAN *activity, ST_LONG timeout) + { +ST_RET ret = SD_FAILURE; + return (ret); + } +#endif + +/************************************************************************/ +/* _gs_sig_event_sem */ +/*----------------------------------------------------------------------*/ +/* Signal event semaphore es. */ +/* pthread_cond_signal wakes up at least one thread that is currently */ +/* blocked on the specified condition. The higher priority thread will */ +/* wake up first. This is like Windows auto-reset semaphore. */ +/* pthread_cond_broadcast wakes up all waiting threads on specified */ +/* condition. This is like Windows manual-reset semaphore. */ +/* Parameters: */ +/* es event semaphore object (pointer) */ +/* predicate value for the predicate to be set to. */ +/* Return values: */ +/* none */ +/************************************************************************/ + +static ST_RET _gs_sig_event_sem (ST_EVENT_SEM es, ST_INT predicate) + { +ST_INT result = SD_FAILURE; +#if defined(DEBUG_SISCO) +ST_THREAD_ID thisThreadId = GET_THREAD_ID(); /* Let's see just who we are */ +#endif + + if (!es) + { + GLBSEM_LOG_ERR1 ("GLBSEM _gs_sig_event_sem error: thread " S_FMT_PTR + " (invalid es=NULL)", thisThreadId); + return (result); + } + + /* mutex for the specified condition variable must be locked before */ + /* going changing predicate and signaling */ + gs_mutex_get (&es->mutex); + + es->predicate = predicate; + if (es->manualReset == SD_TRUE) + result = pthread_cond_broadcast (&es->cond); + else + result = pthread_cond_signal (&es->cond); + + /* release the mutex semaphore for the conditional variable */ + gs_mutex_free (&es->mutex); + + if (result != 0) + { + GLBSEM_LOG_ERR3 ("GLBSEM _gs_sig_event_sem error: thread " S_FMT_PTR ", es=" S_FMT_PTR + " (pthread_cond_signal(broadcast) failed result=%d)", + thisThreadId, es, result); + } + + return (result); + } + +/************************************************************************/ +/* gs_signal_event_sem */ +/*----------------------------------------------------------------------*/ +/* Signal event semaphore es. */ +/* This behaviour is similiar to Windows auto-reset event semaphore */ +/* when SetEvent is used to signal. */ +/* The condition's predicate will be reset by the woken thread, */ +/* see gs_wait_event_sem. */ +/* If no thread is waiting the predicate remains set but the signaling */ +/* is not held. If new thread calls gs_wait_event_sem it will return */ +/* without going to wait state because the predicate value is 1. */ +/* Parameters: */ +/* es event semaphore object (pointer) */ +/* Return values: */ +/* none */ +/************************************************************************/ + +ST_VOID gs_signal_event_sem (ST_EVENT_SEM es) + { + ST_INT result; + ST_INT predicate = 1; + + result = _gs_sig_event_sem (es, predicate); + + if (result == 0) + { + GLBSEM_LOG_FLOW2 ("GLBSEM gs_signal_event_sem: thread " S_FMT_PTR " signaled es=" S_FMT_PTR ".", + GET_THREAD_ID(), es); + } + } + +/************************************************************************/ +/* gs_pulse_event_sem */ +/*----------------------------------------------------------------------*/ +/* Signal event semaphore es. */ +/* This behaviour is similiar to Windows auto-reset event semaphore */ +/* when PulseEvent is used to signal. The condition's predicate will be */ +/* reset by the woken thread, see gs_wait_event_sem. */ +/* If no thread is waiting the predicate remains set but the signaling */ +/* is not held. If a thread calls the gs_wait_event_sem it will go */ +/* into wait state because the predicate value is 2. */ +/* Parameters: */ +/* es event semaphore object (pointer) */ +/* Return values: */ +/* none */ +/************************************************************************/ + +ST_VOID gs_pulse_event_sem (ST_EVENT_SEM es) + { + ST_INT result; + ST_INT predicate = 2; + + result = _gs_sig_event_sem (es, predicate); + + if (result == 0) + { + GLBSEM_LOG_FLOW2 ("GLBSEM gs_pulse_event_sem: thread " S_FMT_PTR " signaled es=" S_FMT_PTR ".", + GET_THREAD_ID(), es); + } + } + +/************************************************************************/ +/* gs_reset_event_sem */ +/*----------------------------------------------------------------------*/ +/* Reset event semaphore es. */ +/* Parameters: */ +/* es event semaphore object (pointer) */ +/* Return values: */ +/* none */ +/************************************************************************/ + +ST_VOID gs_reset_event_sem (ST_EVENT_SEM es) + { + /* mutex for the specified condition variable must be locked before */ + /* going changing predicate and signaling */ + gs_mutex_get (&es->mutex); + + es->predicate = 0; + + /* release the mutex semaphore for the conditional variable */ + gs_mutex_free (&es->mutex); + } + +/************************************************************************/ +/* gs_free_event_sem */ +/*----------------------------------------------------------------------*/ +/* Release resources taken by event semaphore es. */ +/* Parameters: */ +/* es event semaphore object (pointer) */ +/* Return values: none */ +/* none */ +/************************************************************************/ + +ST_VOID gs_free_event_sem (ST_EVENT_SEM es) + { +ST_RET ret; +ST_INT result; +#if defined(DEBUG_SISCO) +ST_THREAD_ID thisThreadId = GET_THREAD_ID(); /* Let's see just who we are */ +#endif + + if (!es) + { + GLBSEM_LOG_ERR1 ("GLBSEM gs_free_event_sem error: thread " S_FMT_PTR + " (invalid es=NULL)", thisThreadId); + return; + } + + /* free mutex */ + ret = gs_mutex_destroy (&es->mutex); + if ( ret != SD_SUCCESS) + return; /* mutex probably busy, a thread is in the gs_wait_event_sem */ + + /* free the conditional variable */ + result = pthread_cond_destroy (&es->cond); + if (result != 0) + { + GLBSEM_LOG_ERR3 ("GLBSEM gs_free_event_sem error: thread " S_FMT_PTR ", es=" S_FMT_PTR + " (pthread_cond_destroy failed result=%d)", + thisThreadId, es, result); + switch ( result ) + { + case EBUSY: + GLBSEM_LOG_CERR0 ("result=EBUSY (program requested to destroy" + " referenced condition variable)."); + break; + case EINVAL: + GLBSEM_LOG_CERR0 ("result=EINVAL (invalid cond argument)."); + break; + } + } + else + { + GLBSEM_LOG_FLOW2 ("GLBSEM gs_free_event_sem: thread " S_FMT_PTR + " released event sem es=" S_FMT_PTR ".", thisThreadId, es); + } + + /* free this allocated pointer */ + chk_free (es); + } + + + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + /* */ + /* USER's THREAD FUNCTIONS for _AIX, __alpha */ + /* */ + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + +/************************************************************************/ +/* gs_start_thread */ +/*----------------------------------------------------------------------*/ +/* Start a new thread. */ +/* Parameters: */ +/* threadFunc pointer to thread function to run */ +/* threadArg thread function argument */ +/* threadHandleOut pointer where to return thread handle */ +/* threadIdOut pointer where to return thread ID */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/************************************************************************/ + +ST_RET gs_start_thread (ST_THREAD_RET (*threadFunc) (ST_THREAD_ARG), + ST_THREAD_ARG threadArg, + ST_THREAD_HANDLE *threadHandleOut, + ST_THREAD_ID *threadIdOut) + { +ST_RET ret; +ST_INT result; +ST_THREAD_HANDLE threadHandle; +pthread_attr_t init_attr; + + /* set the thread parameters just in case the default are not set as */ + /* we expecting */ + result = pthread_attr_init (&init_attr); + if (result != 0 ) + { + ret = SD_FAILURE; + + GLBSEM_LOG_ERR1 ("GLBSEM error: gs_start_thread pthread_attr_init failed" + " (error=%d)", result); + switch ( result ) + { + case EINVAL: + GLBSEM_LOG_CERR0 ("errno=EINVAL (invalid attr argument)"); + break; + case ENOMEM: + GLBSEM_LOG_CERR0 ("errno=ENOMEM (insufficient memory to create thread)"); + break; + } + return (ret); + } + result = pthread_attr_setdetachstate (&init_attr, PTHREAD_CREATE_JOINABLE); + if (result != 0 ) + { + ret = SD_FAILURE; + + GLBSEM_LOG_ERR1 ("GLBSEM error: gs_start_thread pthread_attr_setdetachstate failed" + " (error=%d)", result); + switch ( result ) + { + case EINVAL: + GLBSEM_LOG_CERR0 ("errno=EINVAL (invalid detachstate)"); + break; + } + return (ret); + } + + /* The thread is created with the default attribute PTHREAD_CREATE_JOINABLE */ + /* that allows us to wait until the thread terminates in the gs_wait_thread */ + /* function. */ + + result = pthread_create (&threadHandle, /* pointer for thread pointer */ + &init_attr, /* if NULL, use default thread attr */ + threadFunc, /* thread funct to be executed */ + threadArg); /* thread funct argument */ + if (result == 0 ) + { + /* Thread created successfully */ + ret = SD_SUCCESS; + + if (threadHandleOut != NULL) + *threadHandleOut = threadHandle; + + if (threadIdOut != NULL) + *threadIdOut = threadHandle; /* use thread handle as id */ + + GLBSEM_LOG_FLOW1 ("GLBSEM: gs_start_thread created thread threadHandle=" S_FMT_THREAD_HANDLE ".", + threadHandle); + } + else + { + ret = SD_FAILURE; + + GLBSEM_LOG_ERR1 ("GLBSEM error: gs_start_thread create thread failed" + " (error=%d)", result); + switch ( result ) + { + case EAGAIN: + GLBSEM_LOG_CERR0 ("errno=EAGAIN (insufficient resources to create" + " thread, limit exceeded)"); + break; + case EINVAL: + GLBSEM_LOG_CERR0 ("errno=EINVAL (invalid attr argument)"); + break; + case ENOMEM: + GLBSEM_LOG_CERR0 ("errno=ENOMEM (insufficient memory to create thread)"); + break; + case EPERM: + GLBSEM_LOG_CERR0 ("errno=EPERM (insufficient permission to create thread)"); + break; + } + } + + return (ret); + } + +/************************************************************************/ +/* gs_wait_thread */ +/*----------------------------------------------------------------------*/ +/* Wait until thread with threadHandle terminates or timeout occurrs. */ +/* On UNIX systems the is no option for timed wait. This function will */ +/* wait until the thread is terminated. */ +/* Parameters: */ +/* threadHandle thread handle returned from gs_start_thread */ +/* threadId thread ID returned from gs_start_thread */ +/* timeout max time in milliseconds to wait for thread to */ +/* terminate. IGNORED. */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/************************************************************************/ +ST_RET gs_wait_thread (ST_THREAD_HANDLE threadHandle, + ST_THREAD_ID threadId, ST_LONG timeout) + { +ST_RET ret; +ST_INT result; + + result = pthread_join (threadHandle, NULL); + if ( result == 0 ) + { + /* thread terminated successfully */ + ret = SD_SUCCESS; + GLBSEM_LOG_FLOW1 ("GLBSEM: pthread_join SUCCESS for thread threadHandle=" S_FMT_THREAD_HANDLE ".", + threadHandle); + } + else + { + ret = SD_FAILURE; + GLBSEM_LOG_ERR2 ("GLBSEM error: pthread_join failed for thread " S_FMT_THREAD_HANDLE "." + " (error=%d)", threadHandle, result); + switch ( result ) + { + case EINVAL: + GLBSEM_LOG_CERR0 ("errno=EINVAL (thread is not joinable)"); + break; + case ESRCH: + GLBSEM_LOG_CERR0 ("errno=ESRCH (invalid thread)"); + break; + case EDEADLK: + GLBSEM_LOG_CERR0 ("errno=EDEADLK (deadlock, or thread specifies" + " the calling thread)"); + break; + } + } + + return (ret); + } + +/************************************************************************/ +/* gs_close_thread */ +/*----------------------------------------------------------------------*/ +/* Cleanup after thread terminated. */ +/* Parameters: */ +/* threadHandle thread handle ret from gs_start_thread()*/ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/************************************************************************/ + +ST_RET gs_close_thread (ST_THREAD_HANDLE threadHandle) + { +ST_RET ret = SD_SUCCESS; + + /* nothing to clean up here */ + return (ret); + } + +#endif /* defined(S_MT_SUPPORT) */ diff --git a/mmslib/util/glbsem_w32.c b/mmslib/util/glbsem_w32.c new file mode 100644 index 0000000..3b675a8 --- /dev/null +++ b/mmslib/util/glbsem_w32.c @@ -0,0 +1,1139 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1997-2008, All Rights Reserved */ +/* */ +/* MODULE NAME : glbsem_w32.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : Multi-thread support for Windows ONLY. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/10/08 EJV 21 Ported to Windows Vista. */ +/* 03/27/08 EJV 20 Use S_MAX_PATH instead of MAX_PATH. */ +/* 01/29/08 EJV 19 Use S_FMT_* macros to log pointers & handles.*/ +/* 05/23/07 DSF 18 Added dependency on advapi32.dll */ +/* 06/29/06 MDE,EJV 17 Added UNICODE support (gs_translate_name). */ +/* Del , see sysincs.h. */ +/* 04/12/05 DSF 16 Added refCount member to GS_MUTEX (Windows) */ +/* 01/06/05 DSF 15 Added owner member to GS_MUTEX (Windows) */ +/* 01/14/05 EJV 14 Reversed change. */ +/* 07/21/04 DWL 13 Added ifdef so non debug configs would build.*/ +/* 07/02/04 DSF 12 Always link in winmm.lib */ +/* 05/21/04 DSF 11 Timeout log is now FLOW instead of NERR */ +/* 04/19/04 DSF 10 gs_wait_thread () now returns SD_TIMEOUT on */ +/* timeouts */ +/* 12/29/03 ASK 09 enable logLastError, pass gle to logLastError*/ +/* 12/03/03 EJV 08 gs_is_win_ver(): chg return ST_RET to ST_INT;*/ +/* Add SD_WIN_VER_2003_AND_LATER, replaced */ +/* SD_WIN_VER_NET with SD_WIN_VER_2003; */ +/* 12/01/03 EJV 07 gs_is_win_ver: chk for corr ret 1, 0, -1. */ +/* Named mutex, event: for 2000S w/terminal serv*/ +/* chg from XP to SD_WIN_VER_2K_AND_LATER. */ +/* 11/24/03 DSF 06 Spelling */ +/* 11/04/03 JRB 05 Del gs_sleep (use sMsSleep). */ +/* 06/20/03 EJV 04 Renamed gs_mutex_get to gs_mutex_get_tm. */ +/* 06/12/03 EJV 03 Redesigned mutex sems implementation. */ +/* 06/10/03 EJV 02 Added gs_named_mutex_xxx functions. */ +/* 06/06/03 JRB 01 NEW. Code taken out of glbsem.c */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "slog.h" +#include "glbsem.h" + +#ifdef WIN32 + +#pragma comment(linker, "/defaultlib:winmm.lib") +#pragma comment(linker, "/defaultlib:advapi32.lib") + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +static ST_VOID logLastError (DWORD errCode); + + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + /* */ + /* MUTEX SEMAPHORE FUNCTIONS for _WIN32 */ + /* */ + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + +/************************************************************************/ +/* gs_mutex_create */ +/*----------------------------------------------------------------------*/ +/* Initialize the mutex semaphore ms. */ +/* CRITICAL_SECTION is used for mutex semaphore for faster operation. */ +/* Parameters: */ +/* ms pointer to mutex object */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/************************************************************************/ + +ST_RET gs_mutex_create (ST_MUTEX_SEM *ms) + { + ms->mutexType = GS_MUTEX_UNNAMED; + ms->owner = 0; + ms->refCount = 0; + InitializeCriticalSection (&ms->u.cs); + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* gs_translate_name */ +/*----------------------------------------------------------------------*/ +/* This function, if necessary, will prepend "Global\\" to the name and */ +/* convert the name to Unicode. */ +/* name ptr to name str (named mutex or sem). */ +/* newName, wideName ptr to output buffer. */ +/* bufSize output buffer size. */ +/* */ +/* !NOTE: The UNICODE was not tested. */ +/************************************************************************/ +#if defined (UNICODE) +ST_RET gs_translate_name (ST_CHAR *name, WCHAR *wideName, ST_UINT bufSize) +#else +ST_RET gs_translate_name (ST_CHAR *name, ST_CHAR *newName, ST_UINT bufSize) +#endif +{ +#if defined (UNICODE) +ST_CHAR tmpName[S_MAX_PATH]; /* max size that a mutex/sem name can have */ +#endif +ST_UINT maxLen; +ST_BOOLEAN bPrepend = SD_FALSE; + + /* NOTE: do not put any logging to this function. It is used in DLLs. */ + + /* compute the max name size that can be handled & set bPrepend flag */ + #if defined (UNICODE) + maxLen = sizeof(tmpName) - 1; + #else + maxLen = bufSize - 1; + #endif + if (gs_is_win_ver (SD_WIN_VER_2K_AND_LATER) == 1) + if (memcmp (name, "Global\\", strlen ("Global\\")) != 0) + { + /* need to prepend "Global\\" */ + maxLen = maxLen - strlen ("Global\\"); + bPrepend = SD_TRUE; + } + + /* make sure we got buffer big enough for the resulting prepended name */ + if (strlen(name) > maxLen) + return (SD_FAILURE); + +#if defined (UNICODE) + { + /* copy the name to temporary buffer and prepend "Global\\" if necessary */ + if (bPrepend) + sprintf (tmpName, "Global\\%s", name); + else + strcpy (tmpName, name); + + /* Convert ANSI name to Unicode (error will be set if bufSize is too small) */ + if (MultiByteToWideChar (CP_ACP, 0, tmpName, strlen (tmpName)+1, wideName, bufSize) == 0) + return (SD_FAILURE); + } +#else /* !defined (UNICODE) */ + if (bPrepend) + sprintf (newName, "Global\\%s", name); + else + strcpy (newName, name); +#endif /* !defined (UNICODE) */ + + return (SD_SUCCESS); +} + +/************************************************************************/ +/* gs_named_mutex_create */ +/*----------------------------------------------------------------------*/ +/* Create/Open NAMED mutex. */ +/* On Windows XP this function prepends 'Global\\' to the mutex name */ +/* and sets the security descriptor in the way that the mutex can */ +/* be accessed by processes in different user spaces (in Windows XP Fast*/ +/* User Switching). */ +/* For each call to this function the gs_named_mutex_destroy must be */ +/* called. */ +/* Parameters: */ +/* ms pointer where to return handle to named mutex */ +/* name pointer to mutex name. */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/************************************************************************/ + +ST_RET gs_named_mutex_create (ST_MUTEX_SEM *ms, ST_CHAR *name) + { +ST_RET ret = SD_SUCCESS; +HANDLE hMutex = NULL; +#if defined (UNICODE) +WCHAR mutexName[S_MAX_PATH]; +#else +ST_CHAR mutexName[S_MAX_PATH]; +#endif + + if (ms == NULL || name == NULL) + { +#if defined(DEBUG_SISCO) + GLBSEM_LOG_ERR0 ("GLBSEM error: gs_named_mutex_create() failed ms=NULL or name=NULL"); +#endif + return (SD_FAILURE); + } + + ret = gs_translate_name (name, mutexName, (ST_UINT) (sizeof(mutexName)/sizeof(mutexName[0]))); + if (ret != SD_SUCCESS) + { +#if defined(DEBUG_SISCO) + GLBSEM_LOG_ERR1 ("GLBSEM error: gs_translate_name () failed, name='%s'.", name); +#endif + return (ret); + } + + /* set the mutex type */ + ms->mutexType = GS_MUTEX_NAMED; + ms->owner = 0; + ms->refCount = 0; + + if (gs_is_win_ver (SD_WIN_VER_2K_AND_LATER) == 1) + { + PSECURITY_DESCRIPTOR psd; + SECURITY_ATTRIBUTES sa; + + /* This code allows the mutex to be accessed from different */ + /* applications in different users (Windows XP Fast User Switching). */ + psd = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); + if (psd == NULL) + return (SD_FAILURE); + if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION)) + { + LocalFree (psd); + return (SD_FAILURE); + } + if (!SetSecurityDescriptorDacl(psd, TRUE, (PACL) NULL, FALSE)) + { + LocalFree (psd); + return (SD_FAILURE); + } + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = psd; + sa.bInheritHandle = TRUE; + + hMutex = CreateMutex (&sa, /* security attributes */ + SD_FALSE, /* FALSE is initially not owned */ + mutexName); /* object name */ + if (hMutex == NULL) + { +#if defined(DEBUG_SISCO) + DWORD gle = GetLastError (); + GLBSEM_LOG_ERR2 ("GLBSEM error: CreateMutex failed GLE=%d for %s", + (unsigned int) gle, mutexName); +#endif + ret = SD_FAILURE; + } + LocalFree (psd); + } + else + { + /* this is Win 98, NT or 2000 */ + hMutex = CreateMutex (NULL, /* no security attributes */ + SD_FALSE, /* FALSE is initially not owned */ + mutexName); /* object name */ + if (hMutex == NULL) + { +#if defined(DEBUG_SISCO) + DWORD gle = GetLastError (); + GLBSEM_LOG_ERR2 ("GLBSEM error: CreateMutex failed GLE=%d for %s", + (unsigned int) gle, mutexName); +#endif + ret = SD_FAILURE; + } + } + + ms->u.hMutex = hMutex; /* return the handle to user */ + + return (ret); + } + +/************************************************************************/ +/* gs_mutex_get_tm */ +/*----------------------------------------------------------------------*/ +/* Lock the mutex semaphore ms. */ +/* This function uses the gs_wait_event_sem to wait for ownership of */ +/* the named mutex. The named mutex object can be also passed to the */ +/* gs_wait_mult_event_sem function when waiting for multiple objects is */ +/* required. */ +/* */ +/* Parameters: */ +/* ms pointer to mutex object */ +/* timeout Interval in milliseconds to wait for the named */ +/* mutex to be owned, if -1L then the function will*/ +/* be blocked indefinitely until the named mutex */ +/* is owned. */ +/* The timeout parameter is ignored for unnamed */ +/* mutex. The function will wait indefinetely until*/ +/* the mutex is owned. */ +/* Return values: */ +/* none */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/* SD_TIMEOUT timeout */ +/* */ +/* CRITICAL: gs_mutex_get_tm must NOT call any slog, stime, or mem_chk */ +/* functions. These functions call gs_mutex_get_tm causing */ +/* an infinite loop. Logging in the named mutex code is OK. */ +/************************************************************************/ + +ST_RET gs_mutex_get_tm (ST_MUTEX_SEM *ms, ST_LONG timeout) + { +ST_RET ret = SD_SUCCESS; + + if (!gs_already_inited) /* Make sure gs is initialized. */ + gs_init (); + + if (ms->mutexType == GS_MUTEX_UNNAMED) + /* ! do not put logging here to avoid infinite loop */ + EnterCriticalSection (&ms->u.cs); + else + /* named mutex */ + ret = gs_wait_event_sem ((ST_EVENT_SEM) ms->u.hMutex, timeout); + if (ret == SD_SUCCESS) + { + ms->owner = GET_THREAD_ID (); + ++ms->refCount; + } + + return (ret); + } + +/************************************************************************/ +/* gs_mutex_free */ +/*----------------------------------------------------------------------*/ +/* Unlock the mutex semaphore ms. */ +/* Parameters: */ +/* ms pointer to mutex object */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/* CRITICAL: gs_mutex_free must NOT call any slog, stime, or mem_chk */ +/* functions. These functions call ge_mutex_free which would cause */ +/* an infinite loop. Logging in the named mutex code is OK. */ +/************************************************************************/ + +ST_RET gs_mutex_free (ST_MUTEX_SEM *ms) + { +ST_RET ret = SD_SUCCESS; + + --ms->refCount; + if (ms->refCount == 0) + ms->owner = 0; + if (ms->mutexType == GS_MUTEX_UNNAMED) + /* ! do not put logging here to avoid infinite loop */ + LeaveCriticalSection (&ms->u.cs); + else + { + /* named mutex */ + if (ReleaseMutex (ms->u.hMutex) == SD_FALSE) + { +#if defined(DEBUG_SISCO) + DWORD gle = GetLastError (); + GLBSEM_LOG_ERR2 ("GLBSEM error: ReleaseMutex failed for hMutex=" S_FMT_HANDLE " (GLE=%d)", + ms->u.hMutex, (unsigned int) gle); +#endif + ret = SD_FAILURE; + } + } + + return (ret); + } + +/************************************************************************/ +/* gs_mutex_destroy */ +/*----------------------------------------------------------------------*/ +/* Free all resources allocated for the MUTEX semaphore ms. */ +/* Parameters: */ +/* ms pointer to mutex object */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/************************************************************************/ + +ST_RET gs_mutex_destroy (ST_MUTEX_SEM *ms) + { +ST_RET ret = SD_SUCCESS; + + if (ms->mutexType == GS_MUTEX_UNNAMED) + DeleteCriticalSection (&ms->u.cs); + else + { + /* named mutex */ + if (CloseHandle (ms->u.hMutex) == SD_FALSE) + { +#if defined(DEBUG_SISCO) + DWORD gle = GetLastError (); + GLBSEM_LOG_ERR2 ("GLBSEM error: CloseHandle failed for hMutex=" S_FMT_HANDLE " (GLE=%d)", + ms->u.hMutex, (unsigned int) gle); +#endif + ret = SD_FAILURE; + } + } + + return (ret); + } + + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + /* */ + /* USER's EVENT SEMAPHORE FUNCTIONS for _WIN32 */ + /* */ + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + +/************************************************************************/ +/* gs_get_event_sem */ +/*----------------------------------------------------------------------*/ +/* Create a "manual-reset" or "auto-reset" event semaphore. */ +/* Parameters: */ +/* manualReset SD_TRUE or SD_FALSE */ +/* Return values: */ +/* ST_EVENT_SEM handle to event semaphore object */ +/************************************************************************/ + +ST_EVENT_SEM gs_get_event_sem (ST_BOOLEAN manualReset) + { +ST_EVENT_SEM retEventSem; + + retEventSem = CreateEvent(NULL, // no security attributes + manualReset, // manual-reset event + FALSE, // initial state is signaled + NULL // object name + ); + if (retEventSem == NULL) + GLBSEM_LOG_ERR1 ("GLBSEM error: CreateEvent failed for event semaphore, rc = %d", GetLastError ()); + + return (retEventSem); + } + +/************************************************************************/ +/* gs_get_named_event_sem */ +/*----------------------------------------------------------------------*/ +/* Create a "manual-reset" or "auto-reset" NAMED event semaphore. */ +/* On Windows XP this function prepends 'Global\\' to the semaphore name*/ +/* and sets the security descriptor in the way that the semaphore can */ +/* be accessed by processes in different user spaces (in Windows XP Fast*/ +/* User Switching). */ +/* Parameters: */ +/* name pointer to semaphore name. */ +/* manualReset SD_TRUE or SD_FALSE */ +/* Return values: */ +/* ST_EVENT_SEM handle to named event semaphore object */ +/************************************************************************/ + +ST_EVENT_SEM gs_get_named_event_sem (ST_CHAR *name, ST_BOOLEAN manualReset) + { +ST_EVENT_SEM retEventSem = NULL; +#if defined (UNICODE) +WCHAR semName[S_MAX_PATH]; +#else +ST_CHAR semName[S_MAX_PATH]; +#endif + + /* NOTE: do not put any logging to this function. It is used in DLLs. */ + + if (gs_translate_name (name, semName, (ST_UINT) (sizeof(semName)/sizeof(semName[0]))) + != SD_SUCCESS) + return (NULL); + + if (gs_is_win_ver (SD_WIN_VER_2K_AND_LATER) == 1) + { + PSECURITY_DESCRIPTOR psd; + SECURITY_ATTRIBUTES sa; + + /* This code allows the event semaphore to be accessed from different */ + /* applications in different users (Windows XP Fast User Switching). */ + psd = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); + if (psd == NULL) + return (NULL); + if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION)) + { + LocalFree (psd); + return (NULL); + } + if (!SetSecurityDescriptorDacl(psd, TRUE, (PACL) NULL, FALSE)) + { + LocalFree (psd); + return (NULL); + } + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = psd; + sa.bInheritHandle = TRUE; + + retEventSem = CreateEvent(&sa, /* security attributes */ + manualReset, /* manual-reset event */ + SD_FALSE, /* initial state is non-signaled */ + semName); /* object name */ + LocalFree (psd); + } + else + { + /* this is Win 98, NT or 2000 */ + retEventSem = CreateEvent (NULL, manualReset, SD_FALSE, semName); + } + + return (retEventSem); + } + +/************************************************************************/ +/* gs_wait_event_sem */ +/*----------------------------------------------------------------------*/ +/* Wait for event semaphore es until it becomes signaled or timeout */ +/* occurrs. */ +/* If compiled with DEBUG_SISCO the gs_track variable need to be set to */ +/* value >0 to enable the timing code. This way logging can be used */ +/* by an application without degradation of the EVENT sem performance. */ +/* Parameters: */ +/* es event semaphore object */ +/* timeout interval in milliseconds to wait for the es to */ +/* be signaled, if -1L then the function will be */ +/* blocked indefinitely until the event semaphore */ +/* is signaled. */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/* SD_TIMEOUT timeout */ +/************************************************************************/ + +ST_RET gs_wait_event_sem (ST_EVENT_SEM es, ST_LONG timeout) + { +ST_RET ret; +DWORD rc; +#if defined(DEBUG_SISCO) +DWORD gle; +ST_DOUBLE startTime; +ST_DOUBLE endTime; +ST_DOUBLE elapsedTime; +#endif +ST_THREAD_ID thisThreadId; + + /* Let's see just who we are */ + thisThreadId = GET_THREAD_ID(); + +#if defined(DEBUG_SISCO) + if (gs_track) + startTime = sGetMsTime (); +#endif + + rc = WaitForSingleObject (es, timeout); + +#if defined(DEBUG_SISCO) + if (gs_track) + { + endTime = sGetMsTime (); + elapsedTime = endTime - startTime; + if (elapsedTime > gs_hwEventTime) + gs_hwEventTime = elapsedTime; + } +#endif + + if (rc == WAIT_FAILED) + { +#if defined(DEBUG_SISCO) + gle = GetLastError (); + GLBSEM_LOG_ERR3 ("GLBSEM error: WaitEvent rc=0x%04x, GLE=0x%04x, ThreadId=0x%08x", + (unsigned int) rc, (unsigned int)gle, thisThreadId); + logLastError (gle); +#endif + ret = SD_FAILURE; + } + else if (rc == WAIT_TIMEOUT) + ret = SD_TIMEOUT; + else + ret = SD_SUCCESS; + + return (ret); + } + +/************************************************************************/ +/* gs_wait_mult_event_sem */ +/*----------------------------------------------------------------------*/ +/* Wait for event semaphores in table esTable until one of them becomes */ +/* signaled or timeout occurrs. */ +/* If compiled with DEBUG_SISCO the gs_track variable need to be set to */ +/* value >0 to enable the timing code. This way logging can be used */ +/* by an application without degradation of the EVENT sem performance. */ +/* Parameters: */ +/* numEvents number of event semaphores to wait for */ +/* esTable pointer to table of event semaphore objects */ +/* activity pointer to table where this function will mark */ +/* proper index entry with SD_TRUE for the event */ +/* semaphore that have been signaled */ +/* timeout interval in milliseconds to wait for the es to */ +/* be signaled, if -1L then the function will be */ +/* blocked indefinitely until the event semaphore */ +/* is signaled. */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/* SD_TIMEOUT timeout */ +/************************************************************************/ + +ST_RET gs_wait_mult_event_sem (ST_INT numEvents, ST_EVENT_SEM *esTable, + ST_BOOLEAN *activity, ST_LONG timeout) + { +ST_RET ret; +DWORD rc; +ST_INT i; +#if defined(DEBUG_SISCO) +DWORD gle; +ST_DOUBLE startTime; +ST_DOUBLE endTime; +ST_DOUBLE elapsedTime; +#endif +ST_THREAD_ID thisThreadId; + + /* Let's see just who we are */ + thisThreadId = GET_THREAD_ID(); + +#if defined(DEBUG_SISCO) + if (gs_track) + startTime = sGetMsTime (); +#endif + + rc = WaitForMultipleObjects (numEvents, esTable, FALSE, timeout); + +#if defined(DEBUG_SISCO) + if (gs_track) + { + endTime = sGetMsTime (); + elapsedTime = endTime - startTime; + if (elapsedTime > gs_hwEventTime) + gs_hwEventTime = elapsedTime; + } +#endif + + /* make sure activity array is zero'd out */ + memset (activity, '\x0', sizeof (ST_BOOLEAN) * numEvents); + + i = rc - WAIT_OBJECT_0; + if ((i >= 0) && (i < numEvents)) + { + activity[i] = SD_TRUE; + ret = SD_SUCCESS; + } + else if (rc == WAIT_FAILED) + { +#if defined(DEBUG_SISCO) + gle = GetLastError (); + GLBSEM_LOG_ERR3 ("GLBSEM error: WaitEvent rc=0x%04x, GLE=0x%04x, ThreadId=0x%08x", + (unsigned int) rc, (unsigned int)gle, thisThreadId); + logLastError (gle); +#endif + ret = SD_FAILURE; + } + else if (rc == WAIT_TIMEOUT) + ret = SD_TIMEOUT; + else + ret = SD_SUCCESS; + + return (ret); + } + +/************************************************************************/ +/* gs_signal_event_sem */ +/*----------------------------------------------------------------------*/ +/* Signal event semaphore es. */ +/* Manual-Reset: all waiting threads are released, es remains signaled */ +/* until reset explicitly by call to ResetEvent. */ +/* Auto-Reset: first waiting thread is released and es will be reset */ +/* to non-signaled state. If no thread is waiting the es */ +/* remains in signaled state unless ResetEvent is called. */ +/* Parameters: */ +/* es event semaphore object */ +/* Return values: */ +/* none */ +/************************************************************************/ + +ST_VOID gs_signal_event_sem (ST_EVENT_SEM es) + { +BOOL rc; +#if defined(DEBUG_SISCO) +DWORD gle; +#endif + + rc = SetEvent(es); +#if defined(DEBUG_SISCO) + if (rc == FALSE) + { + gle = GetLastError (); + GLBSEM_LOG_ERR1 ("GLBSEM error: SetEvent GLE=0x%04x", (unsigned int) gle); + logLastError (gle); + } +#endif + } + +/************************************************************************/ +/* gs_pulse_event_sem */ +/*----------------------------------------------------------------------*/ +/* Uses PulseEvent to signal the event semaphore es. */ +/* Manual-Reset: all waiting threads are released, es state changes to */ +/* non-signaled. */ +/* Auto-Reset: first waiting thread is released and es will be reset */ +/* to non-signaled state even if no thread is waiting. */ +/* Parameters: */ +/* es event semaphore object */ +/* Return values: */ +/* none */ +/************************************************************************/ + +ST_VOID gs_pulse_event_sem (ST_EVENT_SEM es) + { +BOOL rc; +#if defined(DEBUG_SISCO) +DWORD gle; +#endif + + rc = PulseEvent(es); +#if defined(DEBUG_SISCO) + if (rc == FALSE) + { + gle = GetLastError (); + GLBSEM_LOG_ERR1 ("GLBSEM error: PulseEvent GLE=0x%04x", (unsigned int) gle); + logLastError (gle); + } +#endif + } + +/************************************************************************/ +/* gs_reset_event_sem */ +/*----------------------------------------------------------------------*/ +/* Reset event semaphore es. */ +/* This function should be called after function gs_wait_event_sem or */ +/* gs_wait_mult_event_sem return SD_SUCCESS and the signaled event */ +/* semaphore is a "manual-reset" semaphore. */ +/* Parameters: */ +/* es event semaphore object */ +/* Return values: */ +/* none */ +/************************************************************************/ + +ST_VOID gs_reset_event_sem (ST_EVENT_SEM es) + { +BOOL rc; +#if defined(DEBUG_SISCO) +DWORD gle; +#endif + + rc = ResetEvent (es); +#if defined(DEBUG_SISCO) + if (rc == FALSE) + { + gle = GetLastError (); + GLBSEM_LOG_ERR1 ("GLBSEM error: ResetEvent gle=0x%04x", (unsigned int)gle); + logLastError (gle); + } +#endif + } + +/************************************************************************/ +/* gs_free_event_sem */ +/*----------------------------------------------------------------------*/ +/* Release resources taken be event semaphore es. */ +/* Parameters: */ +/* es event semaphore object */ +/* Return values: */ +/* none */ +/************************************************************************/ + +ST_VOID gs_free_event_sem (ST_EVENT_SEM es) + { +BOOL rc; +#if defined(DEBUG_SISCO) +DWORD gle; +#endif + + rc = CloseHandle (es); +#if defined(DEBUG_SISCO) + if (rc == FALSE) + { + gle = GetLastError (); + GLBSEM_LOG_ERR1 ("GLBSEM error: CloseHandle GLE=0x%04x", (unsigned int)gle); + logLastError (gle); + } +#endif + } + + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + /* */ + /* USER's THREAD FUNCTIONS for _WIN32 */ + /* */ + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + +/************************************************************************/ +/* gs_start_thread */ +/*----------------------------------------------------------------------*/ +/* Start a new thread. The thread handle should be closed after the */ +/* thread terminates by calling the gs_close_thread(). The function */ +/* gs_wait_thread can be used to wait until a thread terminates. */ +/* Parameters: */ +/* threadFunc pointer to thread function to run */ +/* threadArg thread function argument list */ +/* threadHandleOut pointer where to return thread handle */ +/* threadIdOut pointer where to return thread ID */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/************************************************************************/ + +ST_RET gs_start_thread (ST_THREAD_RET (ST_THREAD_CALL_CONV *threadFunc) (ST_THREAD_ARG), + ST_THREAD_ARG threadArg, + ST_THREAD_HANDLE *threadHandleOut, + ST_THREAD_ID *threadIdOut) + { +ST_RET ret; +ST_THREAD_HANDLE threadHandle; +ST_THREAD_ID threadId; + + threadHandle = _beginthreadex (NULL, /* No security */ + 0, /* Use def stack size */ + threadFunc, + threadArg, /* Argument for thread */ + 0, /* Creation flags, 0 for running initial state */ + &threadId); /* Thread identifier */ + + if (threadHandle == 0) + { + GLBSEM_LOG_ERR1 ("GLBSEM error: gs_start_thread _beginthreadex failed errno=%d", + errno); + ret = SD_FAILURE; + } + else + { + ret = SD_SUCCESS; + + if (threadHandleOut != NULL) + *threadHandleOut = threadHandle; + + if (threadIdOut != NULL) + *threadIdOut = threadId; + + GLBSEM_LOG_FLOW2 ("GLBSEM: gs_start_thread created thread threadHandle=" S_FMT_THREAD_HANDLE + " threadId=0x%08x", threadHandle, threadId); + } + + return (ret); + } + + +/************************************************************************/ +/* gs_wait_thread */ +/*----------------------------------------------------------------------*/ +/* Wait until thread with threadHandle terminates or timeout occurrs. */ +/* Parameters: */ +/* threadHandle thread handle returned from gs_start_thread */ +/* threadId thread ID returned from gs_start_thread */ +/* timeout max time in milliseconds to wait for thread to */ +/* terminate. */ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/************************************************************************/ + +ST_RET gs_wait_thread (ST_THREAD_HANDLE threadHandle, + ST_THREAD_ID threadId, ST_LONG timeout) + { +ST_RET ret; +DWORD rc; +#if defined(DEBUG_SISCO) +DWORD gle; +#endif + + rc = WaitForSingleObject ((HANDLE)threadHandle, timeout); + + if (rc != WAIT_OBJECT_0) + { +#if defined(DEBUG_SISCO) + gle = GetLastError (); +#endif + if (rc == WAIT_TIMEOUT) + { + ret = SD_TIMEOUT; + /* WAIT_FAILED or WAIT_TIMEOUT */ +#if defined(DEBUG_SISCO) + GLBSEM_LOG_FLOW3 ("GLBSEM: Timeout=%d ms in Wait Thread threadHandle=" S_FMT_THREAD_HANDLE ", " + "threadId=0x%08x", timeout, threadHandle, threadId); +#endif + } + else + { +#if defined(DEBUG_SISCO) + GLBSEM_LOG_ERR3 ("GLBSEM error: Wait Thread threadHandle=" S_FMT_THREAD_HANDLE ", rc=0x%04x, GLE=0x%04x", + threadHandle, (unsigned int)rc, (unsigned int)gle); + logLastError (gle); +#endif + ret = SD_FAILURE; + } + } + else + ret = SD_SUCCESS; + + return (ret); + } + + +/************************************************************************/ +/* gs_close_thread */ +/*----------------------------------------------------------------------*/ +/* Cleanup after thread terminated. */ +/* Parameters: */ +/* threadHandle thread handle ret from gs_start_thread()*/ +/* Return values: */ +/* SD_SUCCESS function successful */ +/* SD_FAILURE error occurred */ +/************************************************************************/ + +ST_RET gs_close_thread (ST_THREAD_HANDLE threadHandle) + { +ST_RET ret = SD_SUCCESS; +#if defined(DEBUG_SISCO) +DWORD gle; +#endif + + if (threadHandle) + { + if (CloseHandle ((HANDLE)threadHandle) == 0) + { +#if defined(DEBUG_SISCO) + gle = GetLastError (); + GLBSEM_LOG_ERR1 ("GLBSEM error: Close Thread GLE=0x%04x", (unsigned int)gle); +#endif + ret = SD_FAILURE; + } + } + else + { + GLBSEM_LOG_ERR1 ("GLBSEM error: Close Thread invalid threadHandle=" S_FMT_THREAD_HANDLE ".", + threadHandle); + ret = SD_FAILURE; + } + return (ret); + } + + +/************************************************************************/ +/* gs_set_thread_name */ +/*----------------------------------------------------------------------*/ +/* Start a new thread. */ +/* Parameters: */ +/* threadId ID of Thread whose name is to be set */ +/* -1 if name is to be set for calling */ +/* thread */ +/* pThreadName Name to set */ +/************************************************************************/ + +#define THREADNAME_EXCEPT_ID 0x406D1388 +#define THREADNAME_INFO_TYPE 0x1000 + +typedef struct tagTHREADNAME_INFO + { + ST_LONG type; + ST_CHAR *pName; + ST_THREAD_ID threadId; + LONG flags; + } THREADNAME_INFO; + +ST_VOID gs_set_thread_name (ST_THREAD_ID threadId, ST_CHAR *pThreadName) + { +THREADNAME_INFO info; + + info.type = THREADNAME_INFO_TYPE; + info.pName = pThreadName; + info.threadId = threadId; + info.flags = 0; + + __try + { +#if (_MSC_VER >= 1300) + RaiseException (THREADNAME_EXCEPT_ID, 0, + sizeof (info) / sizeof (ST_LONG), (ULONG_PTR *) &info); +#else + RaiseException (THREADNAME_EXCEPT_ID, 0, + sizeof (info) / sizeof (ST_LONG), (DWORD *) &info); +#endif + } + __except (EXCEPTION_CONTINUE_EXECUTION) + { + } + } + + + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + /* */ + /* Misc. FUNCTIONS for _WIN32 */ + /* */ + /*---*---*---*---*---*---*---*---*---*---*---*---*---*--*/ + +/************************************************************************/ +/* gs_is_win_ver */ +/*----------------------------------------------------------------------*/ +/* Accesses the OS version of the running system and checks if the */ +/* version is ver. */ +/* This function is compatible with Windows 95 and above. */ +/* Parameters: */ +/* ST_UINT ver see SD_WIN_* choices in glbsem.h */ +/* Return: */ +/* 1 If OS version is ver */ +/* 0 If OS version is not ver */ +/* -1 If could not access OS version info or ver invalid */ +/************************************************************************/ +ST_INT gs_is_win_ver (ST_UINT ver) +{ +ST_INT ret = 0; +OSVERSIONINFO OsVerInfo; /* supported on Win 95 and up */ + + /* NOTE: do not put any logging to this function. It is used in DLLs. */ + + OsVerInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + if (GetVersionEx (&OsVerInfo) == 0) + return (-1); + + switch (ver) + { + case SD_WIN_VER_95_98_Me: /* 95, 98, Me */ + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + ret = 1; + break; + + case SD_WIN_VER_NT_AND_LATER: /* NT 3.51, NT 4.0 and above */ + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) + ret = 1; + break; + + case SD_WIN_VER_2K_AND_LATER: /* 2000 and above */ + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && + ((OsVerInfo.dwMajorVersion == 5 && OsVerInfo.dwMinorVersion >= 0) || + OsVerInfo.dwMajorVersion > 5)) + ret = 1; + break; + + case SD_WIN_VER_XP_AND_LATER: /* XP and above */ + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && + ((OsVerInfo.dwMajorVersion == 5 && OsVerInfo.dwMinorVersion >= 1) || + OsVerInfo.dwMajorVersion > 5)) + ret = 1; + break; + + case SD_WIN_VER_2003_AND_LATER: /* 2003 and above */ + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && + ((OsVerInfo.dwMajorVersion == 5 && OsVerInfo.dwMinorVersion >= 2) || + OsVerInfo.dwMajorVersion > 5)) + ret = 1; + break; + + case SD_WIN_VER_VISTA_AND_LATER: /* Vista and above */ + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && + ((OsVerInfo.dwMajorVersion == 6 && OsVerInfo.dwMinorVersion >= 0) || + OsVerInfo.dwMajorVersion > 6)) + ret = 1; + break; + + case SD_WIN_VER_95: + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && + OsVerInfo.dwMajorVersion == 4 && OsVerInfo.dwMinorVersion == 0) + ret = 1; + break; + + case SD_WIN_VER_98: + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && + OsVerInfo.dwMajorVersion == 4 && OsVerInfo.dwMinorVersion == 10) + ret = 1; + break; + + case SD_WIN_VER_Me: + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && + OsVerInfo.dwMajorVersion == 4 && OsVerInfo.dwMinorVersion == 90) + ret = 1; + break; + + case SD_WIN_VER_NT_351: + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && + OsVerInfo.dwMajorVersion == 3 && OsVerInfo.dwMinorVersion == 51) + ret = 1; + break; + + case SD_WIN_VER_NT_40: + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && + OsVerInfo.dwMajorVersion == 4 && OsVerInfo.dwMinorVersion == 0) + ret = 1; + break; + + case SD_WIN_VER_2000: + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && + OsVerInfo.dwMajorVersion == 5 && OsVerInfo.dwMinorVersion == 0) + ret = 1; + break; + + case SD_WIN_VER_XP: + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && + OsVerInfo.dwMajorVersion == 5 && OsVerInfo.dwMinorVersion == 1) + ret = 1; + break; + + case SD_WIN_VER_2003: + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && + OsVerInfo.dwMajorVersion == 5 && OsVerInfo.dwMinorVersion == 2) + ret = 1; + break; + + case SD_WIN_VER_VISTA: /* Vista workstation or Longhorn server */ + if (OsVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && + OsVerInfo.dwMajorVersion == 6 && OsVerInfo.dwMinorVersion == 0) + ret = 1; + break; + + default: + ret = -1; /* invalid ver */ + } + + return (ret); +} + +/************************************************************************/ +/* logLastError */ +/*----------------------------------------------------------------------*/ +/* Parameters: */ +/* Return values: */ +/************************************************************************/ + +static ST_VOID logLastError (DWORD errCode) + { +LPVOID lpMsgBuf; +DWORD len; + + len = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + errCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &lpMsgBuf, + 0, + NULL); + + if(len == 0) /* FormatMessage failed... */ + return; + + GLBSEM_LOG_CERR1 (" -> %s", lpMsgBuf); + + // Free the buffer. + LocalFree( lpMsgBuf ); + } +#endif diff --git a/mmslib/util/scl_log.c b/mmslib/util/scl_log.c new file mode 100644 index 0000000..69466e9 --- /dev/null +++ b/mmslib/util/scl_log.c @@ -0,0 +1,353 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2004-2004 All Rights Reserved */ +/* */ +/* MODULE NAME : scl_log.c */ +/* PRODUCT(S) : MMS-EASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Functions to log info parsed from SCL file. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* scl_log_all_data_types */ +/* scl_log_all_logical_devices */ +/* scl_log_all */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/08/07 JRB 02 Fix log message. */ +/* 06/10/04 DWL 01 Initial Revision. */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "scl.h" +#include "slog.h" +#include "sx_log.h" + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* scl_log_do */ +/************************************************************************/ +static ST_VOID scl_log_do (SCL_DO *scl_do) + { + SXLOG_DEC2 ("SCL LOG: ", + scl_do->name, scl_do->type); + } + +/************************************************************************/ +/* scl_log_da */ +/************************************************************************/ +static ST_VOID scl_log_da (SCL_DA *scl_da) + { +ST_CHAR dchg[6]; +ST_CHAR qchg[6]; +ST_CHAR dupd[6]; + + SXLOG_DEC8 ("SCL LOG: name, scl_da->desc, scl_da->sAddr, scl_da->bType, + scl_da->valKind, scl_da->type, scl_da->count, scl_da->fc); + + if (scl_da->dchg == SD_TRUE) + strncpy (dchg, "true", sizeof(dchg)); + else + strncpy (dchg, "false", sizeof(dchg)); + + if (scl_da->qchg == SD_TRUE) + strncpy (qchg, "true", sizeof(qchg)); + else + strncpy (qchg, "false", sizeof(qchg)); + + if (scl_da->dupd == SD_TRUE) + strncpy (dupd, "true", sizeof(dupd)); + else + strncpy (dupd, "false", sizeof(dupd)); + + SXLOG_CDEC3 ("SCL LOG: dchg='%s' qchg='%s' dupd='%s'>", + dchg, qchg, dupd); + } + +/************************************************************************/ +/* scl_log_sdo */ +/************************************************************************/ +static ST_VOID scl_log_sdo (SCL_DA *scl_da) + { + SXLOG_DEC3 ("SCL LOG: ", + scl_da->name, scl_da->desc, scl_da->type); + } + +/************************************************************************/ +/* scl_log_lntype */ +/************************************************************************/ +static ST_VOID scl_log_lntype (SCL_LNTYPE *scl_lntype) + { +SCL_DO *scl_do; + + SXLOG_DEC2 ("SCL LOG: ", + scl_lntype->id, scl_lntype->lnClass); + + for (scl_do = (SCL_DO *) list_find_last ((DBL_LNK *) scl_lntype->doHead); + scl_do != NULL; + scl_do = (SCL_DO *) list_find_prev ((DBL_LNK *) scl_lntype->doHead, (DBL_LNK *) scl_do)) + { + scl_log_do (scl_do); + } + } + +/************************************************************************/ +/* scl_log_dotype */ +/************************************************************************/ +static ST_VOID scl_log_dotype (SCL_DOTYPE *scl_dotype) + { +SCL_DA *scl_da; + + SXLOG_DEC2 ("SCL LOG: ", + scl_dotype->id, scl_dotype->cdc); + + for (scl_da = (SCL_DA *) list_find_last ((DBL_LNK *) scl_dotype->daHead); + scl_da != NULL; + scl_da = (SCL_DA *) list_find_prev ((DBL_LNK *) scl_dotype->daHead, (DBL_LNK *) scl_da)) + { + if (scl_da->objtype == SCL_OBJTYPE_SDO) + scl_log_sdo (scl_da); + else /* Must be SCL_OBJTYPE_DA */ + scl_log_da (scl_da); + } + } + +/************************************************************************/ +/* scl_log_bda */ +/************************************************************************/ +static ST_VOID scl_log_bda (SCL_BDA *scl_bda) + { + SXLOG_DEC7 ("SCL LOG: ", + scl_bda->name, scl_bda->desc, scl_bda->sAddr, + scl_bda->bType, scl_bda->valKind, scl_bda->type, + scl_bda->count); + SXLOG_DEC1 ("SCL LOG: ", scl_bda->Val); + } + +/************************************************************************/ +/* scl_log_datype */ +/************************************************************************/ +static ST_VOID scl_log_datype (SCL_DATYPE *scl_datype) + { +SCL_BDA *scl_bda; + + SXLOG_DEC1 ("SCL LOG: ", + scl_datype->id); + + for (scl_bda = (SCL_BDA *) list_find_last ((DBL_LNK *) scl_datype->bdaHead); + scl_bda != NULL; + scl_bda = (SCL_BDA *) list_find_prev ((DBL_LNK *) scl_datype->bdaHead, (DBL_LNK *) scl_bda)) + { + scl_log_bda (scl_bda); + } + } + +/************************************************************************/ +/* scl_log_enumval */ +/************************************************************************/ +static ST_VOID scl_log_enumval (SCL_ENUMVAL *scl_enumval) + { + SXLOG_DEC2 ("SCL LOG: ", + scl_enumval->ord, scl_enumval->EnumVal); + } + +/************************************************************************/ +/* scl_log_enumtype */ +/************************************************************************/ +static ST_VOID scl_log_enumtype (SCL_ENUMTYPE *scl_enumtype) + { +SCL_ENUMVAL *scl_enumval; + + SXLOG_DEC1 ("SCL LOG: ", + scl_enumtype->id); + + for (scl_enumval = (SCL_ENUMVAL *) list_find_last ((DBL_LNK *) scl_enumtype->enumvalHead); + scl_enumval != NULL; + scl_enumval = (SCL_ENUMVAL *) list_find_prev ((DBL_LNK *) scl_enumtype->enumvalHead, (DBL_LNK *) scl_enumval)) + { + scl_log_enumval (scl_enumval); + } + } + +/************************************************************************/ +/* scl_log_all_data_types */ +/************************************************************************/ +ST_VOID scl_log_all_data_types (SCL_INFO *scl_info) + { +SCL_LNTYPE *scl_lntype; +SCL_DOTYPE *scl_dotype; +SCL_DATYPE *scl_datype; +SCL_ENUMTYPE *scl_enumtype; + + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_lntype = (SCL_LNTYPE *) list_find_last ((DBL_LNK *) scl_info->lnTypeHead); + scl_lntype != NULL; + scl_lntype = (SCL_LNTYPE *) list_find_prev ((DBL_LNK *) scl_info->lnTypeHead, (DBL_LNK *) scl_lntype)) + { + scl_log_lntype (scl_lntype); + } + + for (scl_dotype = (SCL_DOTYPE *) list_find_last ((DBL_LNK *) scl_info->doTypeHead); + scl_dotype != NULL; + scl_dotype = (SCL_DOTYPE *) list_find_prev ((DBL_LNK *) scl_info->doTypeHead, (DBL_LNK *) scl_dotype)) + { + scl_log_dotype (scl_dotype); + } + + for (scl_datype = (SCL_DATYPE *) list_find_last ((DBL_LNK *) scl_info->daTypeHead); + scl_datype != NULL; + scl_datype = (SCL_DATYPE *) list_find_prev ((DBL_LNK *) scl_info->daTypeHead, (DBL_LNK *) scl_datype)) + { + scl_log_datype (scl_datype); + } + + for (scl_enumtype = (SCL_ENUMTYPE *) list_find_last ((DBL_LNK *) scl_info->enumTypeHead); + scl_enumtype != NULL; + scl_enumtype = (SCL_ENUMTYPE *) list_find_prev ((DBL_LNK *) scl_info->enumTypeHead, (DBL_LNK *) scl_enumtype)) + { + scl_log_enumtype (scl_enumtype); + } + } + +/************************************************************************/ +/* scl_log_fcda */ +/************************************************************************/ +static ST_VOID scl_log_fcda (SCL_FCDA *scl_fcda) + { + SXLOG_DEC7 ("SCL LOG: ", + scl_fcda->ldInst, scl_fcda->prefix, scl_fcda->lnInst, + scl_fcda->lnClass, scl_fcda->doName, scl_fcda->daName, + scl_fcda->fc); + } + +/************************************************************************/ +/* scl_log_dataset */ +/************************************************************************/ +static ST_VOID scl_log_dataset (SCL_DATASET *scl_dataset) + { +SCL_FCDA *scl_fcda; + + SXLOG_DEC2 ("SCL LOG: ", + scl_dataset->name, scl_dataset->desc); + + for (scl_fcda = (SCL_FCDA *) list_find_last ((DBL_LNK *) scl_dataset->fcdaHead); + scl_fcda != NULL; + scl_fcda = (SCL_FCDA *) list_find_prev ((DBL_LNK *) scl_dataset->fcdaHead, (DBL_LNK *) scl_fcda)) + { + scl_log_fcda (scl_fcda); + } + } + +/************************************************************************/ +/* scl_log_rcb */ +/************************************************************************/ +static ST_VOID scl_log_rcb (SCL_RCB *scl_rcb) + { +ST_CHAR buffered[6]; + + if (scl_rcb->buffered == SD_TRUE) + strncpy (buffered, "true", sizeof (buffered)); + else + strncpy (buffered, "false", sizeof (buffered)); + + SXLOG_DEC8 ("SCL LOG: name, scl_rcb->desc, scl_rcb->datSet, + scl_rcb->intgPd, scl_rcb->rptID, scl_rcb->confRev, + buffered, scl_rcb->bufTime); + + /* These are bitstrings. Just log as hex. */ + SXLOG_CDEC3 ("SCL LOG: TrgOps=0x%02X, OptFlds=0x%02X%02X", + (ST_UINT) scl_rcb->TrgOps [0], + (ST_UINT) scl_rcb->OptFlds[0], + (ST_UINT) scl_rcb->OptFlds[1] ); + } + +/************************************************************************/ +/* scl_log_ln */ +/************************************************************************/ +static ST_VOID scl_log_ln (SCL_LN *scl_ln) + { +SCL_DATASET *scl_dataset; +SCL_RCB *scl_rcb; + + SXLOG_DEC5 ("SCL LOG: ", + scl_ln->desc, scl_ln->lnType, scl_ln->lnClass, + scl_ln->inst, scl_ln->prefix); + + /* Log Datasets */ + for (scl_dataset = (SCL_DATASET *) list_find_last ((DBL_LNK *) scl_ln->datasetHead); + scl_dataset != NULL; + scl_dataset = (SCL_DATASET *) list_find_prev ((DBL_LNK *) scl_ln->datasetHead, (DBL_LNK *) scl_dataset)) + { + scl_log_dataset (scl_dataset); + } + + /* Log RCBs */ + for (scl_rcb = (SCL_RCB *) list_find_last ((DBL_LNK *) scl_ln->rcbHead); + scl_rcb != NULL; + scl_rcb = (SCL_RCB *) list_find_prev ((DBL_LNK *) scl_ln->rcbHead, (DBL_LNK *) scl_rcb)) + { + scl_log_rcb (scl_rcb); + } + } + +/************************************************************************/ +/* scl_log_ld */ +/************************************************************************/ +static ST_VOID scl_log_ld ( + SCL_INFO *scl_info, /* main struct where all SCL info stored*/ + SCL_LD *scl_ld) + { +SCL_LN *scl_ln; + + SXLOG_DEC2 ("SCL LOG: ", + scl_ld->desc, scl_ld->inst); + + /* Log Logical nodes */ + /* NOTE: linked lists are in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_ln = (SCL_LN *) list_find_last ((DBL_LNK *) scl_ld->lnHead); + scl_ln != NULL; + scl_ln = (SCL_LN *) list_find_prev ((DBL_LNK *) scl_ld->lnHead, (DBL_LNK *) scl_ln)) + { + scl_log_ln (scl_ln); + } + } + +/************************************************************************/ +/* scl_log_all_logical_devices */ +/* Log all Logical Devices from SCL info saved in "scl_info". */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +ST_VOID scl_log_all_logical_devices (SCL_INFO *scl_info) + { +SCL_LD *scl_ld; + + /* NOTE: linked list is in reverse order from data in SCL file, */ + /* so get off list in reverse order. */ + for (scl_ld = (SCL_LD *) list_find_last ((DBL_LNK *) scl_info->ldHead); + scl_ld != NULL; + scl_ld = (SCL_LD *) list_find_prev ((DBL_LNK *) scl_info->ldHead, (DBL_LNK *) scl_ld)) + { + scl_log_ld (scl_info, scl_ld); + } + } + +/************************************************************************/ +/* scl_log_all */ +/* Log everything from SCL info saved in "scl_info". */ +/************************************************************************/ +ST_VOID scl_log_all (SCL_INFO *scl_info) + { + scl_log_all_logical_devices (scl_info); + scl_log_all_data_types (scl_info); + } diff --git a/mmslib/util/sclparse.c b/mmslib/util/sclparse.c new file mode 100644 index 0000000..d09b3e6 --- /dev/null +++ b/mmslib/util/sclparse.c @@ -0,0 +1,2507 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2004-2006, All Rights Reserved */ +/* */ +/* MODULE NAME : sclparse.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : This routine parses XML files conforming to the */ +/* SCL object model. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 05/06/08 JRB 23 Chk ReportControl indexed attr (must be true)*/ +/* 04/23/08 JRB 22 Parse & save "SettingControl" info (SGCB). */ +/* Save dchg, qchg, dupd values in SCL_DA struct*/ +/* 01/18/08 JRB 21 Allow max LN prefix+inst=11. IEC 61850 max=7.*/ +/* Must also reduce max suffix in mvlu_rt.c to */ +/* avoid overflow. */ +/* 01/18/08 JRB 20 Chg datSet in GSEControl & LogControl to */ +/* optional to match Schema (see tControl def). */ +/* 07/10/07 JRB 19 Check length of lnClass, prefix, & inst. */ +/* 06/12/07 JRB 18 Save VLANID in SCL_GSE & SCL_SMV. */ +/* 09/08/06 JRB 17 Fix dstlen type in convert_mac. */ +/* 07/26/06 LWP/JRB 16 Parse & save GOOSE & SMV addressing info from*/ +/* "Communication" section. */ +/* 04/19/06 JRB 15 Make datSet in ReportControl "optional". */ +/* 04/19/06 JRB 14 Parse & save "RptEnabled" info. */ +/* 04/04/06 JRB 13 Parse & save "SampledValueControl" info. */ +/* 03/25/06 JRB 12 Change order of operations: call create/add */ +/* functions first, then copy data directly to */ +/* SCL structs (eliminates intermediate copy). */ +/* Repl scl_get_attr (could overflow caller buf)*/ +/* with scl_get_attr_ptr & scl_get_attr_copy. */ +/* Replace CONTROL_BLOCK with SCL_RCB & SCL_LCB,*/ +/* Fix _DA_SEFun setting of dchg, qchg, & dupd. */ +/* Fix sx_get_string calls to prevent overflow. */ +/* Fix "*_Val_*" functions. */ +/* Chg desc to ptr (allocated during parse). */ +/* 07/25/05 JRB 11 Make nameStructure optional, default=IEDName.*/ +/* 06/24/05 JRB 10 Call sx_parseExx_mt (faster). */ +/* Chg "ord" from unsigned to signed value. */ +/* 05/17/05 DWL 09 Use sx_push instead of SX_PUSH, and force */ +/* user code to call sx_pop. Eliminated some */ +/* unnecessary debug logging. */ +/* 05/17/05 JRB 08 Avoid allocating struct in scl_parse. */ +/* 02/15/05 JRB 07 Save iedName in scl_info. */ +/* Parse Header & save in scl_info. */ +/* Fix some log messages. */ +/* 12/07/04 JRB 06 Del unneeded memsets after callocs. */ +/* 08/23/04 JRB 05 Ret err if iedName or accessPoint.. not found*/ +/* 08/06/04 JRB 04 Del "sclparse.h", use "scl.h". */ +/* 07/23/04 JRB 03 Del unused static functions. */ +/* 07/15/04 DWL 02 Added LogControl & GSEControl elements */ +/* Handle LN and LN0 differently. */ +/* 06/10/04 DWL 01 Created */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "sx_defs.h" +#include "sx_log.h" +#include "str_util.h" +#include "slog.h" +#include "scl.h" /* SCL file processing structs & functions */ +#include "mvl_uca.h" +#include "smpval.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +#define SCL_ATTR_OPTIONAL 0 /* attribute is optional */ +#define SCL_ATTR_REQUIRED 1 /* attribute is required */ + +typedef struct scl_dec_ctrl + { + ST_CHAR *iedName; + ST_CHAR *accessPointName; + ST_BOOLEAN accessPointFound; /* SD_TRUE if IED and AccessPoint found */ + ST_BOOLEAN iedNameMatched; + ST_BOOLEAN accessPointMatched; + SCL_INFO *sclInfo; + SCL_GSE *scl_gse; /* Used for "GSE" in "Communication" section */ + SCL_SMV *scl_smv; /* Used for "SMV" in "Communication" section */ + SCL_LD *scl_ld; /* Used for "LDevice" */ + SCL_LN *scl_ln; /* Used for "LN" (Logical Node) */ + SCL_RCB *scl_rcb; /* alloc to store ReportControl info */ + SCL_LCB *scl_lcb; /* alloc to store LogControl info */ + ST_UINT8 TrgOps[1]; /* Used for ReportControl or LogControl. */ + /* Copied to SCL_RCB or SCL_LCB. */ + SCL_SVCB *scl_svcb; /* Used for "SampledValueControl". */ + SCL_ENUMVAL *scl_enumval; /* Used for "EnumVal". */ + SCL_DAI *scl_dai; /* Used for "DAI". */ + SCL_DA *scl_da; /* Used for "DA". */ + SCL_BDA *scl_bda; /* Used for "BDA". */ + ST_CHAR flattened[MAX_FLAT_LEN + 1]; /* Created by concatenating values*/ + /* from DOI, SDI, and DAI elements*/ + } SCL_DEC_CTRL; + +/************************************************************************/ +static ST_VOID _SCL_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _Header_SFun (SX_DEC_CTRL *sxDecCtrl); + +static ST_VOID _Communication_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _SubNetwork_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _ConnectedAP_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _GSE_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _GSE_Address_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _GSE_Address_P_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _SMV_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _SMV_Address_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _SMV_Address_P_SEFun (SX_DEC_CTRL *sxDecCtrl); +/*renxiaobao GSE ½âÎö*/ +static ST_VOID _GSE_MinTime_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _GSE_MaxTime_SEFun (SX_DEC_CTRL *sxDecCtrl); + +static ST_VOID _IED_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _AccessPoint_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _Server_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _LDevice_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _LN_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _DataSet_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _FCDA_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _ReportControl_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _LogControl_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _GSEControl_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _SettingControl_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _TrgOps_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _OptFlds_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _RptEnabled_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _DOI_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _SDI_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _DAI_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _DAI_Val_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _DataTypeTemplates_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _LNodeType_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _DO_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _DOType_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _DA_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _SDO_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _DAType_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _DA_Val_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _BDA_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _BDA_Val_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _EnumType_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _EnumVal_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_RET _scl_unknown_el_start (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag); +static ST_RET _scl_unknown_el_end (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag); +static ST_VOID _SampledValueControl_SEFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _SampledValueControl_SFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _SampledValueControl_EFun (SX_DEC_CTRL *sxDecCtrl); +static ST_VOID _SmvOpts_SFun (SX_DEC_CTRL *sxDecCtrl); + +/************************************************************************/ +/************************************************************************/ +/* Only the elements we need to extract are listed here. */ +/* The rest are handled by "unknown" element handler. */ +SX_ELEMENT sclStartElements[] = +{ + {"SCL", SX_ELF_CSTARTEND, _SCL_SEFun, NULL, 0} +}; + +SX_ELEMENT SCLElements[] = +{ + {"Header", SX_ELF_CSTART|SX_ELF_OPT, _Header_SFun, NULL, 0}, + {"Communication", SX_ELF_CSTARTEND|SX_ELF_OPT, _Communication_SEFun, NULL, 0}, + {"IED", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _IED_SEFun, NULL, 0}, + {"DataTypeTemplates", SX_ELF_CSTARTEND|SX_ELF_OPT, _DataTypeTemplates_SEFun, NULL, 0} +}; + +/************************************************************************/ +/* Tables for mapping "Communication" elements. */ +/************************************************************************/ +SX_ELEMENT CommunicationElements[] = +{ + {"SubNetwork", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _SubNetwork_SEFun, NULL, 0} +}; + +SX_ELEMENT SubNetworkElements[] = +{ + /* NOTE: "bitRate" and "Text" elements ignored. */ + {"ConnectedAP", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _ConnectedAP_SEFun, NULL, 0} +}; + +SX_ELEMENT ConnectedAPElements[] = +{ + /* DEBUG: add "Address". Ignore "PhyConn". */ + {"GSE", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _GSE_SEFun, NULL, 0}, + {"SMV", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _SMV_SEFun, NULL, 0} +}; + +SX_ELEMENT GSEElements[] = +{ + {"Address", SX_ELF_CSTARTEND|SX_ELF_OPT, _GSE_Address_SEFun, NULL, 0}, + /*renxiaobao GSE ½âÎö*/ + {"MinTime", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _GSE_MinTime_SEFun, NULL, 0}, + {"MaxTime", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _GSE_MaxTime_SEFun, NULL, 0} +}; +SX_ELEMENT GSEAddressElements[] = +{ + {"P", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _GSE_Address_P_SEFun, NULL, 0} +}; + +SX_ELEMENT SMVElements[] = +{ + {"Address", SX_ELF_CSTARTEND|SX_ELF_OPT, _SMV_Address_SEFun, NULL, 0} +}; + +SX_ELEMENT SMVAddressElements[] = +{ + {"P", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _SMV_Address_P_SEFun, NULL, 0} +}; +/************************************************************************/ +/* Tables for mapping "IED" elements. */ +/************************************************************************/ +SX_ELEMENT IEDElements[] = +{ + {"AccessPoint", SX_ELF_CSTARTEND|SX_ELF_RPT, _AccessPoint_SEFun, NULL, 0} +}; + +SX_ELEMENT AccessPointElements[] = +{ + {"Server", SX_ELF_CSTARTEND, _Server_SEFun, NULL, 0} +}; + +SX_ELEMENT ServerElements[] = +{ + {"LDevice", SX_ELF_CSTARTEND|SX_ELF_RPT, _LDevice_SEFun, NULL, 0} +}; + +SX_ELEMENT LDeviceElements[] = +{ + {"LN0", SX_ELF_CSTARTEND, _LN_SEFun, NULL, 0}, + {"LN", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _LN_SEFun, NULL, 0} +}; + +SX_ELEMENT LN0Elements[] = +{ + {"DataSet", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DataSet_SEFun, NULL, 0}, + {"ReportControl", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _ReportControl_SEFun, NULL, 0}, + {"DOI", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DOI_SEFun, NULL, 0}, + {"SampledValueControl", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _SampledValueControl_SEFun, NULL, 0}, + {"LogControl", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _LogControl_SEFun, NULL, 0}, + {"SettingControl", SX_ELF_CSTART|SX_ELF_OPTRPT, _SettingControl_SFun, NULL, 0}, + {"GSEControl", SX_ELF_CSTART|SX_ELF_OPTRPT, _GSEControl_SFun, NULL, 0} +}; + +SX_ELEMENT LNElements[] = +{ + {"DataSet", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DataSet_SEFun, NULL, 0}, + {"ReportControl", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _ReportControl_SEFun, NULL, 0}, + {"DOI", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DOI_SEFun, NULL, 0}, + {"SampledValueControl", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _SampledValueControl_SEFun, NULL, 0}, + {"LogControl", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _LogControl_SEFun, NULL, 0} +}; + +SX_ELEMENT DataSetElements[] = +{ + {"FCDA", SX_ELF_CSTART|SX_ELF_RPT, _FCDA_SFun, NULL, 0} +}; + +SX_ELEMENT ReportControlElements[] = +{ + {"TrgOps", SX_ELF_CSTART|SX_ELF_OPT, _TrgOps_SFun, NULL, 0}, + {"OptFields", SX_ELF_CSTART, _OptFlds_SFun, NULL, 0}, + {"RptEnabled", SX_ELF_CSTART|SX_ELF_OPT, _RptEnabled_SFun, NULL, 0} +}; + +SX_ELEMENT LogControlElements[] = +{ + {"TrgOps", SX_ELF_CSTART|SX_ELF_OPT, _TrgOps_SFun, NULL, 0} +}; + +SX_ELEMENT SampledValueControlElements[] = +{ + {"SmvOpts", SX_ELF_CSTART, _SmvOpts_SFun, NULL, 0} +}; + +SX_ELEMENT DOIElements[] = +{ + {"SDI", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _SDI_SEFun, NULL, 0}, + {"DAI", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DAI_SEFun, NULL, 0} +}; + +/* SDI can be nested under itself indefinitely */ +SX_ELEMENT SDIElements[] = +{ + {"SDI", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _SDI_SEFun, NULL, 0}, + {"DAI", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DAI_SEFun, NULL, 0} +}; + +SX_ELEMENT DAIElements[] = +{ + {"Val", SX_ELF_CSTARTEND|SX_ELF_OPT, _DAI_Val_SEFun, NULL, 0} +}; + +/************************************************************************/ +/* Tables for mapping "DataTypeTemplates" elements. */ +/************************************************************************/ +SX_ELEMENT DataTypeTemplatesElements[] = +{ + {"LNodeType", SX_ELF_CSTARTEND|SX_ELF_RPT, _LNodeType_SEFun, NULL, 0}, + {"DOType", SX_ELF_CSTARTEND|SX_ELF_RPT, _DOType_SEFun, NULL, 0}, + {"DAType", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DAType_SEFun, NULL, 0}, + {"EnumType", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _EnumType_SEFun, NULL, 0} +}; + +SX_ELEMENT LNodeTypeElements[] = +{ + {"DO", SX_ELF_CSTART|SX_ELF_RPT, _DO_SFun, NULL, 0} +}; + +SX_ELEMENT DOTypeElements[] = +{ + {"DA", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DA_SEFun, NULL, 0}, + {"SDO", SX_ELF_CSTART|SX_ELF_OPTRPT, _SDO_SFun, NULL, 0} +}; + +SX_ELEMENT DAElements[] = +{ + {"Val", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DA_Val_SEFun, NULL, 0} +}; + +SX_ELEMENT DATypeElements[] = +{ + {"BDA", SX_ELF_CSTARTEND|SX_ELF_RPT, _BDA_SEFun, NULL, 0} +}; + +SX_ELEMENT BDAElements[] = +{ + {"Val", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _BDA_Val_SEFun, NULL, 0} +}; + +SX_ELEMENT EnumTypeElements[] = +{ + {"EnumVal", SX_ELF_CSTARTEND|SX_ELF_RPT, _EnumVal_SEFun, NULL, 0} +}; + +/************************************************************************/ +/* convert_mac */ +/* Converts MAC string read from SCL file (like 01-02-03-04-05-06) */ +/* to 6 byte hex MAC address. */ +/************************************************************************/ +#define MAX_MAC_STRING_LEN 60 +static ST_RET convert_mac (ST_UCHAR *dst, ST_CHAR *src) + { +ST_RET retcode; +ST_CHAR tmpbuf [MAX_MAC_STRING_LEN+1]; +ST_CHAR *tmpptr; +ST_UINT dstlen; + + /* Input string may include extra blanks, so allow for fairly long string.*/ + if (strlen (src) > MAX_MAC_STRING_LEN) + retcode = SD_FAILURE; + else + { + /* Just replace each '-' with ' '. Then use ascii_to_hex_str to convert.*/ + tmpptr = tmpbuf; + /* Copy until NULL terminator but ignore '-' and spaces. */ + for ( ; *src; src++) + { + if (*src != '-' && (!isspace(*src))) + *tmpptr++ = *src; + } + *tmpptr = '\0'; /* NULL terminate temp buffer */ + retcode = ascii_to_hex_str (dst, &dstlen, 6, tmpbuf); + if (retcode == SD_SUCCESS && dstlen != 6) + retcode = SD_FAILURE; + } + return (retcode); + } + +/************************************************************************/ +/* log_notfound_attr */ +/************************************************************************/ + +static ST_VOID log_notfound_attr (ST_CHAR *attrName) + { + SXLOG_ERR1 ("SCL PARSE: Required attribute '%s' not found.", + attrName); + } + +/************************************************************************/ +/* log_attr_str */ +/************************************************************************/ + +static ST_VOID log_attr_str (ST_CHAR *name, ST_CHAR *value) + { + SXLOG_DEC2 ("SCL PARSE: Found attribute '%s', value is '%s'", name, value); + } + +/************************************************************************/ +/* log_attr_int */ +/************************************************************************/ + +static ST_VOID log_attr_int (ST_CHAR *name, ST_INT value) + { + SXLOG_DEC2 ("SCL PARSE: Found attribute '%s', value is '%d'", name, value); + } + +/************************************************************************/ +/* log_attr_uint */ +/************************************************************************/ + +static ST_VOID log_attr_uint (ST_CHAR *name, ST_UINT value) + { + SXLOG_DEC2 ("SCL PARSE: Found attribute '%s', value is '%u'", name, value); + } + +/************************************************************************/ +/* log_returned_failure */ +/************************************************************************/ + +static ST_VOID log_returned_failure (ST_CHAR *funcName, ST_LONG ret) + { + SXLOG_ERR2 ("SCL PARSE: %s returned failure, err=%ld", funcName, ret); + } + +/************************************************************************/ +/* scl_stop_parsing */ +/************************************************************************/ + +static ST_VOID scl_stop_parsing (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *offender, + ST_RET errCode) + { + sxDecCtrl->errCode = errCode; + sxDecCtrl->termFlag = SD_TRUE; + if (errCode == SX_REQUIRED_TAG_NOT_FOUND) + { + log_notfound_attr (offender); + } + else /* SX_USER_ERROR */ + { + log_returned_failure (offender, errCode); + } + } + +/************************************************************************/ +/* scl_get_attr_ptr */ +/* Get a pointer to an attr string stored in SX_DEC_CTRL. */ +/* If attr found, SD_SUCCESS returned & "*value" points to string. */ +/* NOTE: The pointer returned in "*value" might not be valid later */ +/* when parsing continues. */ +/************************************************************************/ + +static ST_RET scl_get_attr_ptr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, + ST_CHAR **value, ST_BOOLEAN required) + { +ST_RET ret; + + ret = sx_get_attr_ptr (sxDecCtrl, value, name); + if (ret != SD_SUCCESS) + { + *value = NULL; /* make sure ptr is NULL on error (better than garbage)*/ + if (required) + scl_stop_parsing (sxDecCtrl, name, SX_REQUIRED_TAG_NOT_FOUND); + } + else + log_attr_str (name, *value); + + return (ret); + } + +/************************************************************************/ +/* scl_get_attr_copy */ +/* Get a pointer to an attr string stored in SX_DEC_CTRL. */ +/* If strlen <= maxValueLen, copy string, else return error. */ +/************************************************************************/ + +static ST_RET scl_get_attr_copy (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, + ST_CHAR *value, ST_UINT maxValueLen, ST_BOOLEAN required) + { +ST_RET ret; +ST_CHAR *pValue; + + ret = scl_get_attr_ptr (sxDecCtrl, name, &pValue, required); + if (ret == SD_SUCCESS) + { + if (strlen (pValue) <= maxValueLen) + strcpy (value, pValue); /* copy string to caller's buffer */ + else + { + SXLOG_ERR3 ("Attribute Value='%s' exceeds max len '%d' for attribute '%s'", pValue, maxValueLen, name); + scl_stop_parsing (sxDecCtrl, name, SX_USER_ERROR); + ret = SD_FAILURE; + } + } + + return (ret); + } + +/************************************************************************/ +/* scl_get_int_attr */ +/************************************************************************/ + +static ST_RET scl_get_int_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, + ST_INT *value, ST_BOOLEAN required) + { +ST_RET ret; + + ret = sx_get_int_attr (sxDecCtrl, name, value); + if (ret != SD_SUCCESS) + { + if (required) + scl_stop_parsing (sxDecCtrl, name, SX_REQUIRED_TAG_NOT_FOUND); + } + else + log_attr_int (name, *value); + + return (ret); + } + +/************************************************************************/ +/* scl_get_uint_attr */ +/************************************************************************/ + +static ST_RET scl_get_uint_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, + ST_UINT *value, ST_BOOLEAN required) + { +ST_RET ret; + + ret = sx_get_uint_attr (sxDecCtrl, name, value); + if (ret != SD_SUCCESS) + { + if (required) + scl_stop_parsing (sxDecCtrl, name, SX_REQUIRED_TAG_NOT_FOUND); + } + else + log_attr_uint (name, *value); + + return (ret); + } + +/************************************************************************/ +/* construct_flattened */ +/* Construct a flattened variable name from DOI, SDI, DAI names. */ +/************************************************************************/ +ST_RET construct_flattened (ST_CHAR *flattened, size_t maxlen, ST_CHAR *name, ST_CHAR *ix) + { +size_t ixlen; +ST_RET retCode; + + /* Calc space needed for optional [ix] */ + if (ix) + ixlen = strlen(ix)+2; /* string plus brackets */ + else + ixlen = 0; + /* Make sure there is room for [ix] and "$" */ + if (strlen (flattened) + strlen(name) + ixlen + 1 <= maxlen) + { + /* If flattened is now empty, just copy name, else add "$" then name.*/ + if (strlen(flattened) == 0) + strcpy (flattened, name); + else + { + strcat (flattened, "$"); + strcat (flattened, name); + } + if (ix) + { /* Add 'ix' to flattened if necessary. */ + strcat (flattened, "["); + strcat (flattened, ix); + strcat (flattened, "]"); + } + retCode = SD_SUCCESS; + } + else + { /* flattened is big, so this error should never occur with normal SCL.*/ + SXLOG_ERR2 ("ERROR: not enough space to add name '%s' to flattened name '%s'", name, flattened); + retCode = SD_FAILURE; + } + return (retCode); + } + +/************************************************************************/ +/* scl_parse */ +/************************************************************************/ + +ST_RET scl_parse (ST_CHAR *xmlFileName, ST_CHAR *iedName, + ST_CHAR *accessPointName, SCL_INFO *sclInfo) + { +ST_RET ret; +SCL_DEC_CTRL sclDecCtrl = {0}; /* start with clean struct. */ + + memset (sclInfo, 0, sizeof (SCL_INFO)); /* CRITICAL: start with clean struct*/ + + /* Save iedName in sclInfo for later use. */ + strncpy_safe (sclInfo->iedName, iedName, MAX_IDENT_LEN); + + sclDecCtrl.iedName = iedName; + sclDecCtrl.accessPointName = accessPointName; + sclDecCtrl.accessPointFound = SD_FALSE; + sclDecCtrl.sclInfo = sclInfo; + + ret = sx_parseExx_mt (xmlFileName, + sizeof (sclStartElements)/sizeof(SX_ELEMENT), sclStartElements, + &sclDecCtrl, _scl_unknown_el_start, _scl_unknown_el_end); + + /* NOTE: sx_parseEx_mt doesn't log error if file open fails, so log here*/ + /* It may not log some other errors, so log any other error here too. */ + if (ret == SX_FILE_NOT_FOUND) + SXLOG_ERR1 ("XML File (%s) Open Error",xmlFileName); + else if (ret != SD_SUCCESS) + SXLOG_ERR2 ("Error 0x%X parsing SCL file (%s)", ret, xmlFileName); + + /* If parsing successful, check if requested AccessPoint was found. */ + if (ret == SD_SUCCESS && sclDecCtrl.accessPointFound == SD_FALSE) + { + SXLOG_ERR3 ("IED='%s' or AccessPoint='%s' not found in input file (%s)", + iedName, accessPointName, xmlFileName); + ret = SX_REQUIRED_TAG_NOT_FOUND; /* new error code could be clearer*/ + } + + return (ret); + } + +/************************************************************************/ +/************************************************************************/ +/* SCL_SEFun */ +/************************************************************************/ + +static ST_VOID _SCL_SEFun (SX_DEC_CTRL *sxDecCtrl) + { + if (sxDecCtrl->reason == SX_ELEMENT_START) + sx_push (sxDecCtrl, sizeof(SCLElements)/sizeof(SX_ELEMENT), SCLElements, SD_FALSE); + + else + { + while (sxDecCtrl->itemStackLevel > 0) + sx_pop (sxDecCtrl); + } + } + +/************************************************************************/ +/* _Header_SFun */ +/************************************************************************/ + +static ST_VOID _Header_SFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_CHAR *nameStructure; +ST_RET ret; +SCL_INFO *sclInfo; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + sclInfo = sclDecCtrl->sclInfo; + + /* Get required attributes */ + ret = scl_get_attr_copy (sxDecCtrl, "id", sclInfo->Header.id, + (sizeof(sclInfo->Header.id)-1), SCL_ATTR_REQUIRED); + if (ret != SD_SUCCESS) + return; /* At least one required attr not found. Stop now. */ + + /* Handle optional "nameStructure". */ + if (scl_get_attr_ptr (sxDecCtrl, "nameStructure", &nameStructure, SCL_ATTR_OPTIONAL) == SD_SUCCESS) + { + if (strcmp (nameStructure, "IEDName") != 0) + SXLOG_ERR1 ("Header attribute nameStructure='%s' not allowed. Assuming nameStructure='IEDName' (i.e. 'Product Naming')", nameStructure); + } + /* Always assume nameStructure="IEDName" (i.e. "Product Naming") */ + sclInfo->Header.nameStructure = SCL_NAMESTRUCTURE_IEDNAME; + } + +/************************************************************************/ +/* _Communication_SEFun */ +/************************************************************************/ +static ST_VOID _Communication_SEFun (SX_DEC_CTRL *sxDecCtrl) + { + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + sx_push (sxDecCtrl, sizeof(CommunicationElements)/sizeof(SX_ELEMENT), + CommunicationElements, SD_FALSE); + } + else + { + sx_pop (sxDecCtrl); + } + } +/************************************************************************/ +/* _SubNetwork_SEFun */ +/************************************************************************/ +static ST_VOID _SubNetwork_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; +ST_RET ret; +ST_CHAR *desc; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + SCL_SUBNET *scl_subnet; + scl_subnet = scl_subnet_add (sclDecCtrl->sclInfo); + if (scl_subnet == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_subnet_add", SX_USER_ERROR); + return; + } + /* Get required attributes. */ + ret = scl_get_attr_copy (sxDecCtrl, "name", scl_subnet->name, (sizeof(scl_subnet->name)-1), SCL_ATTR_REQUIRED); + if (ret) + { + scl_stop_parsing (sxDecCtrl, "SubNetwork", SX_USER_ERROR); + return; + } + /* Get optional attributes. */ + ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, SCL_ATTR_OPTIONAL); + if (ret == SD_SUCCESS) + scl_subnet->desc = chk_strdup (desc); /* Alloc & copy desc string */ + ret = scl_get_attr_copy (sxDecCtrl, "type", scl_subnet->type, (sizeof(scl_subnet->type)-1), SCL_ATTR_OPTIONAL); + + sx_push (sxDecCtrl, sizeof(SubNetworkElements)/sizeof(SX_ELEMENT), + SubNetworkElements, SD_FALSE); + } + else + { + sx_pop (sxDecCtrl); + } + } +/************************************************************************/ +/* _ConnectedAP_SEFun */ +/************************************************************************/ +static ST_VOID _ConnectedAP_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; +ST_RET ret; +ST_CHAR *desc; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + SCL_CAP *scl_cap; + scl_cap = scl_cap_add (sclDecCtrl->sclInfo); + if (scl_cap == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_cap_add", SX_USER_ERROR); + return; + } + /* Get required attributes */ + ret = scl_get_attr_copy (sxDecCtrl, "iedName", scl_cap->iedName, (sizeof(scl_cap->iedName)-1), SCL_ATTR_REQUIRED); + ret |= scl_get_attr_copy (sxDecCtrl, "apName", scl_cap->apName, (sizeof(scl_cap->apName)-1), SCL_ATTR_REQUIRED); + if (ret) + { + scl_stop_parsing (sxDecCtrl, "ConnectedAP", SX_USER_ERROR); + return; + } + /* Get optional attributes. */ + ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, SCL_ATTR_OPTIONAL); + if (ret == SD_SUCCESS) + scl_cap->desc = chk_strdup (desc); /* Alloc & copy desc string */ + + sx_push (sxDecCtrl, sizeof(ConnectedAPElements)/sizeof(SX_ELEMENT), + ConnectedAPElements, SD_FALSE); + } + else + { + sx_pop (sxDecCtrl); + } + } +/************************************************************************/ +/* _GSE_SEFun */ +/************************************************************************/ +static ST_VOID _GSE_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; +ST_RET ret; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + /* NOTE: save ptr in sclDecCtrl->scl_gse to use later in parsing. */ + sclDecCtrl->scl_gse = scl_gse_add (sclDecCtrl->sclInfo); + if (sclDecCtrl->scl_gse == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_gse_add", SX_USER_ERROR); + return; + } + ret = scl_get_attr_copy (sxDecCtrl, "ldInst", sclDecCtrl->scl_gse->ldInst, (sizeof(sclDecCtrl->scl_gse->ldInst)-1), SCL_ATTR_REQUIRED); + ret |= scl_get_attr_copy (sxDecCtrl, "cbName", sclDecCtrl->scl_gse->cbName, (sizeof(sclDecCtrl->scl_gse->cbName)-1), SCL_ATTR_REQUIRED); + if (ret) + { + scl_stop_parsing (sxDecCtrl, "GSE", SX_USER_ERROR); + return; + } + else + sx_push (sxDecCtrl, sizeof(GSEElements)/sizeof(SX_ELEMENT), + GSEElements, SD_FALSE); + } + else + { + sx_pop (sxDecCtrl); + } + } +/************************************************************************/ +/* _GSE_Address_SEFun */ +/************************************************************************/ +static ST_VOID _GSE_Address_SEFun (SX_DEC_CTRL *sxDecCtrl) + { + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + sx_push (sxDecCtrl, sizeof(GSEAddressElements)/sizeof(SX_ELEMENT), + GSEAddressElements, SD_FALSE); + } + else + { + sx_pop (sxDecCtrl); + } + } +/************************************************************************/ +/* _GSE_Address_P_SEFun */ +/************************************************************************/ +static ST_VOID _GSE_Address_P_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; +ST_CHAR *str; +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; +ST_CHAR *strOut; +ST_INT strLen; + + if (sxDecCtrl->reason == SX_ELEMENT_END) + { + ret = scl_get_attr_ptr (sxDecCtrl, "type", &str, required); + if (!strcmpi(str,"MAC-Address")) + { + ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen); + if (ret == SD_SUCCESS) + { + if (convert_mac (sclDecCtrl->scl_gse->MAC,strOut)) + { + SXLOG_ERR1 ("Illegal MAC Address '%s'", strOut); + scl_stop_parsing (sxDecCtrl, "_GSE_Address_P_SEFun", SX_USER_ERROR); + } + } + } + else if (!strcmpi(str,"APPID")) + { + ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen); + if (ret == SD_SUCCESS) + sclDecCtrl->scl_gse->APPID = atoi(strOut); + } + else if (!strcmpi(str,"VLAN-PRIORITY")) + { + ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen); + if (ret == SD_SUCCESS) + sclDecCtrl->scl_gse->VLANPRI = atoi(strOut); + } + else if (!strcmpi(str,"VLAN-ID")) + { + ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen); + if (ret == SD_SUCCESS) + sclDecCtrl->scl_gse->VLANID = atoi(strOut); + } + } + } + +/*renxiaobao GSE ½âÎö*/ +/************************************************************************/ +/* _GSE_MinTime_SEFun */ +/************************************************************************/ +static ST_VOID _GSE_MinTime_SEFun (SX_DEC_CTRL *sxDecCtrl) +{ + SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + ST_CHAR *str; + ST_RET ret; + ST_BOOLEAN required = SD_FALSE; + ST_CHAR *strOut; + ST_INT strLen; + if (sxDecCtrl->reason == SX_ELEMENT_END) + { + ret = scl_get_attr_ptr (sxDecCtrl, "unit", &str, required); + /*if (!strcmpi(str,"s"))*/ + { + ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen); + if (ret == SD_SUCCESS) + sclDecCtrl->scl_gse->MinTime = atoi(strOut); + } + } +} +static ST_VOID _GSE_MaxTime_SEFun (SX_DEC_CTRL *sxDecCtrl) +{ + SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + ST_CHAR *str; + ST_RET ret; + ST_BOOLEAN required = SD_FALSE; + ST_CHAR *strOut; + ST_INT strLen; + if (sxDecCtrl->reason == SX_ELEMENT_END) + { + ret = scl_get_attr_ptr (sxDecCtrl, "unit", &str, required); + /*if (!strcmpi(str,"s"))*/ + { + ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen); + if (ret == SD_SUCCESS) + sclDecCtrl->scl_gse->MaxTime = atoi(strOut); + } + } +} +/************************************************************************/ +/* _SMV_SEFun */ +/************************************************************************/ +static ST_VOID _SMV_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; +ST_RET ret; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + /* NOTE: save ptr in sclDecCtrl->scl_smv to use later in parsing. */ + sclDecCtrl->scl_smv = scl_smv_add (sclDecCtrl->sclInfo); + if (sclDecCtrl->scl_smv == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_smv_add", SX_USER_ERROR); + return; + } + ret = scl_get_attr_copy (sxDecCtrl, "ldInst", sclDecCtrl->scl_smv->ldInst, (sizeof(sclDecCtrl->scl_smv->ldInst)-1), SCL_ATTR_REQUIRED); + ret |= scl_get_attr_copy (sxDecCtrl, "cbName", sclDecCtrl->scl_smv->cbName, (sizeof(sclDecCtrl->scl_smv->cbName)-1), SCL_ATTR_REQUIRED); + if (ret) + { + scl_stop_parsing (sxDecCtrl, "SMV", SX_USER_ERROR); + return; + } + else + sx_push (sxDecCtrl, sizeof(SMVElements)/sizeof(SX_ELEMENT), + SMVElements, SD_FALSE); + } + else + { + sx_pop (sxDecCtrl); + } + } +/************************************************************************/ +/* _SMV_Address_SEFun */ +/************************************************************************/ +static ST_VOID _SMV_Address_SEFun (SX_DEC_CTRL *sxDecCtrl) + { + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + sx_push (sxDecCtrl, sizeof(SMVAddressElements)/sizeof(SX_ELEMENT), + SMVAddressElements, SD_FALSE); + } + else + { + sx_pop (sxDecCtrl); + } + } +/************************************************************************/ +/* _SMV_Address_P_SEFun */ +/************************************************************************/ +static ST_VOID _SMV_Address_P_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; +ST_CHAR *str; +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; +ST_CHAR *strOut; +ST_INT strLen; + + if (sxDecCtrl->reason == SX_ELEMENT_END) + { + ret = scl_get_attr_ptr (sxDecCtrl, "type", &str, required); + if (!strcmpi(str,"MAC-Address")) + { + ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen); + if (ret == SD_SUCCESS) + { + if (convert_mac (sclDecCtrl->scl_smv->MAC,strOut)) + { + SXLOG_ERR1 ("Illegal MAC Address '%s'", strOut); + scl_stop_parsing (sxDecCtrl, "_SMV_Address_P_SEFun", SX_USER_ERROR); + } + } + } + else if (!strcmpi(str,"APPID")) + { + ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen); + if (ret == SD_SUCCESS) + sclDecCtrl->scl_smv->APPID = atoi(strOut); + } + else if (!strcmpi(str,"VLAN-PRIORITY")) + { + ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen); + if (ret == SD_SUCCESS) + sclDecCtrl->scl_smv->VLANPRI = atoi(strOut); + } + else if (!strcmpi(str,"VLAN-ID")) + { + ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen); + if (ret == SD_SUCCESS) + sclDecCtrl->scl_smv->VLANID = atoi(strOut); + } + } + } +/************************************************************************/ +/* IED_SEFun */ +/************************************************************************/ +char icd_ied_type[65]; +static ST_VOID _IED_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_CHAR *str; /* ptr set by scl_get_attr_ptr */ +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_ptr (sxDecCtrl, "name", &str, required); + if (ret != SD_SUCCESS) + { + return; + } + if (strcmp(str, sclDecCtrl->iedName) == 0) + { + icd_ied_type[0] = 0; + scl_get_attr_copy (sxDecCtrl, "type", &icd_ied_type[0], 64, 0); /*renxiaobao add 20151218*/ + SXLOG_CDEC1 ("SCL PARSE: IED 'name' match found: %s", str); + sclDecCtrl->iedNameMatched = SD_TRUE; + sx_push (sxDecCtrl, sizeof(IEDElements)/sizeof(SX_ELEMENT), IEDElements, SD_FALSE); + } + else + { + SXLOG_CDEC1 ("SCL PARSE: IED 'name' found (%s), not a match", str); + } + /* end required attributes */ + } + else + { + if (sclDecCtrl->iedNameMatched == SD_TRUE) + { + sclDecCtrl->iedNameMatched = SD_FALSE; + sx_pop (sxDecCtrl); + } + } + } + +/************************************************************************/ +/* _AccessPoint_SEFun */ +/************************************************************************/ + +static ST_VOID _AccessPoint_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_CHAR *str; /* ptr set by scl_get_attr_ptr */ +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_ptr (sxDecCtrl, "name", &str, required); + if (ret != SD_SUCCESS) + { + return; + } + if (strcmp(str, sclDecCtrl->accessPointName) == 0) + { + SXLOG_CDEC1 ("SCL PARSE: AccessPoint 'name' match found: %s", str); + sclDecCtrl->accessPointFound = SD_TRUE; /*NOTE: only get here if IED also found*/ + sclDecCtrl->accessPointMatched = SD_TRUE; + sx_push (sxDecCtrl, sizeof(AccessPointElements)/sizeof(SX_ELEMENT), AccessPointElements, SD_FALSE); + } + else + { + SXLOG_CDEC1 ("SCL PARSE: AccessPoint 'name' found (%s), not a match", str); + } + /* end required attributes */ + } + else + { + if (sclDecCtrl->accessPointMatched == SD_TRUE) + { + sclDecCtrl->accessPointMatched = SD_FALSE; + sx_pop (sxDecCtrl); + } + } + } + +/************************************************************************/ +/* _Server_SEFun */ +/************************************************************************/ + +static ST_VOID _Server_SEFun (SX_DEC_CTRL *sxDecCtrl) + { + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + sx_push (sxDecCtrl, sizeof(ServerElements)/sizeof(SX_ELEMENT), ServerElements, SD_FALSE); + } + else + sx_pop (sxDecCtrl); + } + +/************************************************************************/ +/* _LDevice_SEFun */ +/************************************************************************/ +static ST_VOID _LDevice_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; +SCL_INFO *scl_info; +SCL_LD *scl_ld; +ST_CHAR *desc; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + scl_ld = sclDecCtrl->scl_ld = scl_ld_create (sclDecCtrl->sclInfo); + if (scl_ld == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_ld_create", SX_USER_ERROR); + return; + } + + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required); + if (ret == SD_SUCCESS) + scl_ld->desc = chk_strdup (desc); /* Alloc & copy desc string */ + /* end optional attributes */ + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "inst", scl_ld->inst, (sizeof(scl_ld->inst)-1), required); + if (ret != SD_SUCCESS) + return; /* At least one required attr not found. Stop now. */ + /* end required attributes */ + + sx_push (sxDecCtrl, sizeof(LDeviceElements)/sizeof(SX_ELEMENT), LDeviceElements, SD_FALSE); + } + else + { /* reason == SX_ELEMENT_END */ + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + scl_info = sclDecCtrl->sclInfo; + scl_ld = sclDecCtrl->scl_ld; + /* Construct MMS Domain name from scl info. */ + /* ASSUME nameStructure="IEDName" (domain name = IED name + LDevice inst)*/ + /* nameStructure="FuncName" is OBSOLETE. */ + if (strlen(scl_info->iedName) + strlen(scl_ld->inst) <= MAX_IDENT_LEN) + { + strcpy (scl_ld->domName, scl_info->iedName); /* construct domain name*/ + strcat (scl_ld->domName, scl_ld->inst); + } + else + { + SXLOG_ERR0 ("Cannot create LD: constructed domain name too long"); + scl_stop_parsing (sxDecCtrl, "_LDevice_SEFun", SX_USER_ERROR); + } + sx_pop (sxDecCtrl); + } + } + +/************************************************************************/ +/* _LN_SEFun */ +/************************************************************************/ + +static ST_VOID _LN_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_RET ret,ret1; +ST_BOOLEAN required = SD_FALSE; +SCL_LN *scl_ln; +ST_CHAR *desc; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + scl_ln = sclDecCtrl->scl_ln = scl_ln_add (sclDecCtrl->sclInfo); + if (scl_ln == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_ln_add", SX_USER_ERROR); + return; + } + + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required); + if (ret == SD_SUCCESS) + scl_ln->desc = chk_strdup (desc); /* Alloc & copy desc string */ + ret = scl_get_attr_copy (sxDecCtrl, "prefix", scl_ln->prefix, (sizeof(scl_ln->prefix)-1), required); + /* end optional attributes */ + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "lnType", scl_ln->lnType, (sizeof(scl_ln->lnType)-1), required); + + + /* ret |= scl_get_attr_copy (sxDecCtrl, "inst", scl_ln->inst, (sizeof(scl_ln->inst)-1), required); renxiaobao remove*/ +/* scl_ln->inst ="";*/ +/* ret |= */ + scl_get_attr_copy (sxDecCtrl, "inst", scl_ln->inst, (sizeof(scl_ln->inst)-1), SD_FALSE); + + + ret |= scl_get_attr_copy (sxDecCtrl, "lnClass", scl_ln->lnClass, (sizeof(scl_ln->lnClass)-1), required); + + if (ret != SD_SUCCESS) + return; + + if (stricmp(sxDecCtrl->sxDecElInfo.tag, "LN0") == 0 && + stricmp(scl_ln->lnClass, "LLN0") != 0) + { + sxDecCtrl->errCode = SX_USER_ERROR; + sxDecCtrl->termFlag = SD_TRUE; + SXLOG_ERR0 ("SCL PARSE: Attribute 'lnClass' of element 'LN0' has a value other then 'LLN0' (schema violation)."); + return; + } + /* end required attributes */ + + if (stricmp(sxDecCtrl->sxDecElInfo.tag, "LN0") == 0) + sx_push (sxDecCtrl, sizeof(LN0Elements)/sizeof(SX_ELEMENT), LN0Elements, SD_FALSE); + else + sx_push (sxDecCtrl, sizeof(LNElements)/sizeof(SX_ELEMENT), LNElements, SD_FALSE); + } + else + { /* reason == SX_ELEMENT_END */ + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + scl_ln = sclDecCtrl->scl_ln; + /* Construct MMS Variable name from scl info. */ + if (strlen (scl_ln->lnClass) != 4) + { + SXLOG_ERR1 ("Illegal lnClass='%s'. Must be exactly 4 char", + scl_ln->lnClass); + scl_stop_parsing (sxDecCtrl, "_LN_SEFun", SX_USER_ERROR); + } + else if (strlen (scl_ln->prefix) + strlen (scl_ln->inst) > 11) + { + /* NOTE: standard only allows max=7, but we want to be more forgiving.*/ + SXLOG_ERR3 ("Illegal definition for lnClass='%s': prefix (%s) plus inst (%s) > 11 char.", + scl_ln->lnClass, scl_ln->prefix, scl_ln->inst); + scl_stop_parsing (sxDecCtrl, "_LN_SEFun", SX_USER_ERROR); + } + else + { + strcpy (scl_ln->varName, scl_ln->prefix); + strcat (scl_ln->varName, scl_ln->lnClass); + strcat (scl_ln->varName, scl_ln->inst); + } + sx_pop (sxDecCtrl); + } + } + +/************************************************************************/ +/* _DataSet_SEFun */ +/************************************************************************/ + +static ST_VOID _DataSet_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; +SCL_DATASET *scl_dataset; +ST_CHAR *desc; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + scl_dataset = scl_dataset_add (sclDecCtrl->sclInfo); + if (scl_dataset == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_dataset_add", SX_USER_ERROR); + return; + } + + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required); + if (ret == SD_SUCCESS) + scl_dataset->desc = chk_strdup (desc); /* Alloc & copy desc string */ + /* end optional attributes */ + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "name", scl_dataset->name, (sizeof(scl_dataset->name)-1), required); + if (ret != SD_SUCCESS) + return; + /* end required attributes */ + + sx_push (sxDecCtrl, sizeof(DataSetElements)/sizeof(SX_ELEMENT), DataSetElements, SD_FALSE); + } + else + sx_pop (sxDecCtrl); + } + +/************************************************************************/ +/* _FCDA_SFun */ +/************************************************************************/ + +static ST_VOID _FCDA_SFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; +SCL_INFO *scl_info; +SCL_FCDA *scl_fcda; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + scl_info = sclDecCtrl->sclInfo; + + scl_fcda = scl_fcda_add (scl_info); + if (scl_fcda == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_fcda_add", SX_USER_ERROR); + return; + } + + /* start optional attributes */ + ret = scl_get_attr_copy (sxDecCtrl, "ldInst", scl_fcda->ldInst, (sizeof(scl_fcda->ldInst)-1), required); + ret = scl_get_attr_copy (sxDecCtrl, "prefix", scl_fcda->prefix, (sizeof(scl_fcda->prefix)-1), required); + ret = scl_get_attr_copy (sxDecCtrl, "lnInst", scl_fcda->lnInst, (sizeof(scl_fcda->lnInst)-1), required); + ret = scl_get_attr_copy (sxDecCtrl, "lnClass", scl_fcda->lnClass, (sizeof(scl_fcda->lnClass)-1), required); + ret = scl_get_attr_copy (sxDecCtrl, "doName", scl_fcda->doName, (sizeof(scl_fcda->doName)-1), required); + ret = scl_get_attr_copy (sxDecCtrl, "daName", scl_fcda->daName, (sizeof(scl_fcda->daName)-1), required); + /* end optional attributes */ + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "fc", scl_fcda->fc, (sizeof(scl_fcda->fc)-1), required); + if (ret != SD_SUCCESS) + return; + /* end required attributes */ + + /* Construct domain name from SCL info */ + /* ASSUME nameStructure="IEDName" (domain name = IED name + LDevice inst)*/ + /* nameStructure="FuncName" is OBSOLETE. */ + if (strlen(scl_info->iedName) + strlen(scl_fcda->ldInst) <= MAX_IDENT_LEN) + { + strcpy (scl_fcda->domName, scl_info->iedName); + strcat (scl_fcda->domName, scl_fcda->ldInst); + } + else + { + SXLOG_ERR0 ("Cannot add FCDA: constructed domain name too long"); + scl_stop_parsing (sxDecCtrl, "_FCDA_SFun", SX_USER_ERROR); + } + } + +/************************************************************************/ +/* _ReportControl_SEFun */ +/************************************************************************/ + +static ST_VOID _ReportControl_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_CHAR *str; /* ptr set by scl_get_attr_ptr */ +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; +ST_CHAR *desc; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + /* Alloc struct, save ptr in sclDecCtrl, & set local ptr to it. */ + SCL_RCB *scl_rcb = sclDecCtrl->scl_rcb = scl_rcb_add (sclDecCtrl->sclInfo); + if (scl_rcb == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_rcb_add", SX_USER_ERROR); + return; + } + + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required); + if (ret == SD_SUCCESS) + scl_rcb->desc = chk_strdup (desc); /* Alloc & copy desc string */ + ret = scl_get_attr_copy (sxDecCtrl, "datSet", scl_rcb->datSet, (sizeof(scl_rcb->datSet)-1), required); + ret = scl_get_uint_attr (sxDecCtrl, "intgPd", &scl_rcb->intgPd, required); + ret = scl_get_uint_attr (sxDecCtrl, "bufTime", &scl_rcb->bufTime, required); + ret = scl_get_attr_ptr (sxDecCtrl, "buffered", &str, required); + + scl_rcb->buffered = SD_FALSE; /* default */ + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + scl_rcb->buffered = SD_TRUE; + } + /* NOTE: we only accept default value of indexed="true". */ + ret = scl_get_attr_ptr (sxDecCtrl, "indexed", &str, required); + if (ret == SD_SUCCESS && stricmp(str, "false") == 0) + { + SXLOG_ERR0 ("ReportControl attribute indexed='false' not supported"); + scl_stop_parsing (sxDecCtrl, "scl_rcb_add", SX_USER_ERROR); + return; + } + /* end optional attributes */ + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "name", scl_rcb->name, (sizeof(scl_rcb->name)-1), required); + ret |= scl_get_attr_copy (sxDecCtrl, "rptID", scl_rcb->rptID, (sizeof(scl_rcb->rptID)-1), required); + ret |= scl_get_uint_attr (sxDecCtrl, "confRev", &scl_rcb->confRev, required); + if (ret != SD_SUCCESS) + return; + /* end required attributes */ + + sx_push (sxDecCtrl, sizeof(ReportControlElements)/sizeof(SX_ELEMENT), ReportControlElements, SD_FALSE); + } + else /* reason = SX_ELEMENT_END */ + { + /* CRITICAL: Copy TrgOps to scl_rcb. */ + sclDecCtrl->scl_rcb->TrgOps[0] = sclDecCtrl->TrgOps[0]; + /* If "RptEnabled max" not configured, set default value*/ + if (sclDecCtrl->scl_rcb->maxClient == 0) + sclDecCtrl->scl_rcb->maxClient = 1; /* default */ + /* NOTE: scl_rcb is all filled in now */ + sx_pop (sxDecCtrl); + } + } + +/************************************************************************/ +/* _LogControl_SEFun */ +/************************************************************************/ + +static ST_VOID _LogControl_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_CHAR *str; /* ptr set by scl_get_attr_ptr */ +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; +ST_CHAR *desc; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + /* Alloc struct, save ptr in sclDecCtrl, & set local ptr to it. */ + SCL_LCB *scl_lcb = sclDecCtrl->scl_lcb = scl_lcb_add (sclDecCtrl->sclInfo); + if (scl_lcb == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_lcb_add", SX_USER_ERROR); + return; + } + + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required); + if (ret == SD_SUCCESS) + scl_lcb->desc = chk_strdup (desc); /* Alloc & copy desc string */ + ret = scl_get_uint_attr (sxDecCtrl, "intgPd", &scl_lcb->intgPd, required); + ret = scl_get_attr_copy (sxDecCtrl, "datSet", scl_lcb->datSet, (sizeof(scl_lcb->datSet)-1), required); + ret = scl_get_attr_ptr (sxDecCtrl, "logEna", &str, required); + scl_lcb->logEna = SD_FALSE; /* default */ + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + scl_lcb->logEna = SD_TRUE; + } + + ret = scl_get_attr_ptr (sxDecCtrl, "reasonCode", &str, required); + scl_lcb->reasonCode = SD_FALSE; /* default */ + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + scl_lcb->reasonCode = SD_TRUE; + } + /* end optional attributes */ + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "name", scl_lcb->name, (sizeof(scl_lcb->name)-1), required); + ret |= scl_get_attr_copy (sxDecCtrl, "logName", scl_lcb->logName, (sizeof(scl_lcb->logName)-1), required); + if (ret != SD_SUCCESS) + return; + /* end required attributes */ + + sx_push (sxDecCtrl, sizeof(LogControlElements)/sizeof(SX_ELEMENT), LogControlElements, SD_FALSE); + } + else /* reason = SX_ELEMENT_END */ + { + /* CRITICAL: Copy TrgOps to scl_lcb. */ + sclDecCtrl->scl_lcb->TrgOps[0] = sclDecCtrl->TrgOps[0]; + /* NOTE: scl_lcb is all filled in now */ + sx_pop (sxDecCtrl); + } + } + +/************************************************************************/ +/* _GSEControl_SFun */ +/************************************************************************/ + +static ST_VOID _GSEControl_SFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; +ST_CHAR *type; /* ptr set by scl_get_attr_ptr */ +SCL_GCB *scl_gcb; +ST_CHAR *desc; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + scl_gcb = scl_gcb_add (sclDecCtrl->sclInfo); + if (scl_gcb == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_gcb_add", SX_USER_ERROR); + return; + } + + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required); + if (ret == SD_SUCCESS) + scl_gcb->desc = chk_strdup (desc); /* Alloc & copy desc string */ + ret = scl_get_uint_attr (sxDecCtrl, "confRev", &scl_gcb->confRev, required); + ret = scl_get_attr_copy (sxDecCtrl, "datSet", scl_gcb->datSet, (sizeof(scl_gcb->datSet)-1), required); + ret = scl_get_attr_ptr (sxDecCtrl, "type", &type, required); + if (ret == SD_SUCCESS && strcmp(type, "GSSE") == 0) + scl_gcb->isGoose = SD_FALSE; + else + scl_gcb->isGoose = SD_TRUE; + /* end optional attributes */ + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "name", scl_gcb->name, (sizeof(scl_gcb->name)-1), required); + ret |= scl_get_attr_copy (sxDecCtrl, "appID", scl_gcb->appID, (sizeof(scl_gcb->appID)-1), required); + if (ret != SD_SUCCESS) + return; + /* end required attributes */ + } + +/************************************************************************/ +/* _SettingControl_SFun */ +/************************************************************************/ + +static ST_VOID _SettingControl_SFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_RET ret; +ST_BOOLEAN required; +SCL_SGCB *scl_sgcb; +ST_CHAR *desc; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + scl_sgcb = scl_sgcb_add (sclDecCtrl->sclInfo); + if (scl_sgcb == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_sgcb_add", SX_USER_ERROR); + return; + } + + /* start optional attributes */ + required = SD_FALSE; + ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required); + if (ret == SD_SUCCESS) + scl_sgcb->desc = chk_strdup (desc); /* Alloc & copy desc string */ + ret = scl_get_uint_attr (sxDecCtrl, "actSG", &scl_sgcb->actSG, required); + if (ret) + scl_sgcb->actSG = 1; /* default value */ + /* end optional attributes */ + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_uint_attr (sxDecCtrl, "numOfSGs", &scl_sgcb->numOfSGs, required); + /* end required attributes */ + } + +/************************************************************************/ +/* _TrgOps_SFun */ +/* Save all TrgOps bits in sclDecCtrl->TrgOps. */ +/************************************************************************/ + +static ST_VOID _TrgOps_SFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_CHAR *str; /* ptr set by scl_get_attr_ptr */ +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + sclDecCtrl->TrgOps[0] = 0; /* Start with all bits=0 */ + + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "dchg", &str, required); + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(sclDecCtrl->TrgOps, TRGOPS_BITNUM_DATA_CHANGE); + } + } + + ret = scl_get_attr_ptr (sxDecCtrl, "qchg", &str, required); + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(sclDecCtrl->TrgOps, TRGOPS_BITNUM_QUALITY_CHANGE); + } + } + + ret = scl_get_attr_ptr (sxDecCtrl, "dupd", &str, required); + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(sclDecCtrl->TrgOps, TRGOPS_BITNUM_DATA_UPDATE); + } + } + + ret = scl_get_attr_ptr (sxDecCtrl, "period", &str, required); + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(sclDecCtrl->TrgOps, TRGOPS_BITNUM_INTEGRITY); + } + } + /* end optional attributes */ + } + +/************************************************************************/ +/* _OptFlds_SFun */ +/* Save all OptFlds bits in sclDecCtrl->scl_rcb->OptFlds. */ +/************************************************************************/ + +static ST_VOID _OptFlds_SFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_CHAR *str; /* ptr set by scl_get_attr_ptr */ +ST_RET ret; +SCL_RCB *scl_rcb; +ST_BOOLEAN required = SD_FALSE; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + scl_rcb = sclDecCtrl->scl_rcb; + + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "seqNum", &str, required); + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_SQNUM); + } + } + + ret = scl_get_attr_ptr (sxDecCtrl, "timeStamp", &str, required); + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_TIMESTAMP); + } + } + + ret = scl_get_attr_ptr (sxDecCtrl, "dataSet", &str, required); + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_DATSETNAME); + } + } + + ret = scl_get_attr_ptr (sxDecCtrl, "reasonCode", &str, required); + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_REASON); + } + } + + ret = scl_get_attr_ptr (sxDecCtrl, "dataRef", &str, required); + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_DATAREF); + } + } + + ret = scl_get_attr_ptr (sxDecCtrl, "bufOvfl", &str, required); + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_BUFOVFL); + } + } + + ret = scl_get_attr_ptr (sxDecCtrl, "entryID", &str, required); + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_ENTRYID); + } + } + + ret = scl_get_attr_ptr (sxDecCtrl, "configRef", &str, required); + if (ret == SD_SUCCESS) + { + if (stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_CONFREV); + } + } + /* end optional attributes */ + } + +/************************************************************************/ +/* _RptEnabled_SFun */ +/* Save RptEnabled info in sclDecCtrl->scl_rcb. */ +/************************************************************************/ +static ST_VOID _RptEnabled_SFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; +ST_RET ret; +SCL_RCB *scl_rcb; + + assert (sxDecCtrl->reason == SX_ELEMENT_START); + scl_rcb = sclDecCtrl->scl_rcb; + + /* start optional attributes */ + ret = scl_get_uint_attr (sxDecCtrl, "max", &scl_rcb->maxClient, SCL_ATTR_OPTIONAL); + /* If configured, check for legal value. */ + if (ret == SD_SUCCESS) + { + if (scl_rcb->maxClient <= 0 || scl_rcb->maxClient > 99) + { + SXLOG_ERR1 ("RptEnabled max=%d is not valid. Must be value between 1 and 99", scl_rcb->maxClient); + scl_stop_parsing (sxDecCtrl, "RptEnabled", SX_USER_ERROR); + scl_rcb->maxClient = 1; /* set to default just in case user ignores error*/ + } + } + } + +/************************************************************************/ +/* _DOI_SEFun */ +/************************************************************************/ + +static ST_VOID _DOI_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_CHAR *ix; +ST_CHAR *name; +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "ix", &ix, required); + if (ret) + ix = NULL; + /* end optional attributes */ + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_ptr (sxDecCtrl, "name", &name, required); + if (ret != SD_SUCCESS) + { + return; + } + /* end required attributes */ + + /* Start creation of flattened name */ + sclDecCtrl->flattened[0] = '\0'; /* CRITICAL: start with empty flatname*/ + if (construct_flattened (sclDecCtrl->flattened, sizeof(sclDecCtrl->flattened), name, ix) + != SD_SUCCESS) + { /* error already logged. */ + scl_stop_parsing (sxDecCtrl, "_DOI_SEFun", SX_USER_ERROR); + return; + } + + + SXLOG_CDEC1 ("SCL PARSE: Created flattened variable: '%s'", sclDecCtrl->flattened); + + sx_push (sxDecCtrl, sizeof(DOIElements)/sizeof(SX_ELEMENT), DOIElements, SD_FALSE); + } + else + { + sx_pop (sxDecCtrl); + } + } + +/************************************************************************/ +/* _SDI_SEFun */ +/************************************************************************/ + +static ST_VOID _SDI_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_CHAR *ix; +ST_CHAR *name; +ST_RET ret; +ST_CHAR *p; +ST_BOOLEAN required = SD_FALSE; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "ix", &ix, required); + if (ret) + ix = NULL; + /* end optional attributes */ + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_ptr (sxDecCtrl, "name", &name, required); + if (ret != SD_SUCCESS) + { + return; + } + /* end required attributes */ + + /* Continue creation of flattened name */ + if (construct_flattened (sclDecCtrl->flattened, sizeof(sclDecCtrl->flattened), name, ix) + != SD_SUCCESS) + { /* error already logged. */ + scl_stop_parsing (sxDecCtrl, "_SDI_SEFun", SX_USER_ERROR); + return; + } + + SXLOG_CDEC1 ("SCL PARSE: Appended to flattened variable: '%s'", sclDecCtrl->flattened); + + sx_push (sxDecCtrl, sizeof(SDIElements)/sizeof(SX_ELEMENT), SDIElements, SD_FALSE); + } + else /* reason = SX_ELEMENT_END */ + { + /* Remove the last item from the flattened string */ + p = strrchr(sclDecCtrl->flattened, '$'); + if (p != NULL) + *p = 0; + SXLOG_CDEC1 ("SCL PARSE: Removed last item from flattened variable: '%s'", sclDecCtrl->flattened); + sx_pop (sxDecCtrl); + } + } + +/************************************************************************/ +/* _DAI_SEFun */ +/************************************************************************/ + +static ST_VOID _DAI_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_CHAR *ix; +ST_CHAR *name; +ST_RET ret; +ST_CHAR *p; +ST_BOOLEAN required = SD_FALSE; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + SCL_DAI *scl_dai; + if ((scl_dai = sclDecCtrl->scl_dai = scl_dai_add (sclDecCtrl->sclInfo)) == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_enumtype_create", SX_USER_ERROR); + return; + } + + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "ix", &ix, required); + if (ret) + ix = NULL; + ret = scl_get_attr_copy (sxDecCtrl, "sAddr", scl_dai->sAddr, (sizeof(scl_dai->sAddr)-1), required); + ret = scl_get_attr_copy (sxDecCtrl, "valKind", scl_dai->valKind, (sizeof(scl_dai->valKind)-1), required); + if (ret) + strcpy (scl_dai->valKind, "Set"); /* default */ + /* end optional attributes */ + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_ptr (sxDecCtrl, "name", &name, required); + if (ret != SD_SUCCESS) + { + return; + } + /* end required attributes */ + + /* Continue creation of flattened name */ + if (construct_flattened (sclDecCtrl->flattened, sizeof(sclDecCtrl->flattened), name, ix) + != SD_SUCCESS) + { /* error already logged. */ + scl_stop_parsing (sxDecCtrl, "_DAI_SEFun", SX_USER_ERROR); + return; + } + + SXLOG_CDEC1 ("SCL PARSE: Appended to flattened variable: '%s'", sclDecCtrl->flattened); + strcpy (scl_dai->flattened, sclDecCtrl->flattened); + sx_push (sxDecCtrl, sizeof(DAIElements)/sizeof(SX_ELEMENT), DAIElements, SD_FALSE); + } + else /* reason = SX_ELEMENT_END */ + { + /* Remove the last item from the flattened string */ + p = strrchr(sclDecCtrl->flattened, '$'); + if (p != NULL) + *p = 0; + SXLOG_CDEC1 ("SCL PARSE: Removed last item from flattened variable: '%s'", sclDecCtrl->flattened); + sx_pop (sxDecCtrl); + } + } + +/************************************************************************/ +/* _DAI_Val_SEFun */ +/* Sets "sGroup" and "Val" in sclDecCtrl->scl_dai. */ +/************************************************************************/ + +static ST_VOID _DAI_Val_SEFun (SX_DEC_CTRL *sxDecCtrl) + { + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + /* start optional attributes (don't care about return) */ + scl_get_uint_attr (sxDecCtrl, "sGroup", &sclDecCtrl->scl_dai->sGroup, SCL_ATTR_OPTIONAL); + /* end optional attributes */ + } + else /* reason = SX_ELEMENT_END */ + { + SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + ST_RET ret; + ST_INT strLen; + ST_CHAR *Val; + ret = sx_get_string_ptr (sxDecCtrl, &Val, &strLen); + if (ret==SD_SUCCESS) + sclDecCtrl->scl_dai->Val = chk_strdup (Val); /* alloc & store Val*/ + else + scl_stop_parsing (sxDecCtrl, "DAI Val", SX_USER_ERROR); + } + } + +/************************************************************************/ +/* _DataTypeTemplates_SEFun */ +/************************************************************************/ + +static ST_VOID _DataTypeTemplates_SEFun (SX_DEC_CTRL *sxDecCtrl) + { + if (sxDecCtrl->reason == SX_ELEMENT_START) + sx_push (sxDecCtrl, sizeof(DataTypeTemplatesElements)/sizeof(SX_ELEMENT), DataTypeTemplatesElements, SD_FALSE); + else + sx_pop (sxDecCtrl); + } + +/************************************************************************/ +/* _LNodeType_SEFun */ +/************************************************************************/ + +static ST_VOID _LNodeType_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; +SCL_LNTYPE *scl_lntype; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + scl_lntype = scl_lntype_create (sclDecCtrl->sclInfo); + if (scl_lntype == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_lntype_create", SX_USER_ERROR); + return; + } + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "id", scl_lntype->id, (sizeof(scl_lntype->id)-1), required); + ret |= scl_get_attr_copy (sxDecCtrl, "lnClass", scl_lntype->lnClass, (sizeof(scl_lntype->lnClass)-1), required); + if (ret != SD_SUCCESS) + { + return; + } + /* end required attributes */ + + sx_push (sxDecCtrl, sizeof(LNodeTypeElements)/sizeof(SX_ELEMENT), LNodeTypeElements, SD_FALSE); + } + else + sx_pop (sxDecCtrl); + } + +/************************************************************************/ +/* _DO_SFun */ +/************************************************************************/ + +static ST_VOID _DO_SFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; +SCL_DO *scl_do; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + scl_do = scl_lntype_add_do (sclDecCtrl->sclInfo); + if (scl_do == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_lntype_add_do", SX_USER_ERROR); + return; + } + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "name", scl_do->name, (sizeof(scl_do->name)-1), required); + ret |= scl_get_attr_copy (sxDecCtrl, "type", scl_do->type, (sizeof(scl_do->type)-1), required); + if (ret != SD_SUCCESS) + { + return; + } + /* end required attributes */ + } + +/************************************************************************/ +/* _DOType_SEFun */ +/************************************************************************/ + +static ST_VOID _DOType_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; +SCL_DOTYPE *scl_dotype; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + scl_dotype = scl_dotype_create (sclDecCtrl->sclInfo); + if (scl_dotype == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_dotype_create", SX_USER_ERROR); + return; + } + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "id", scl_dotype->id, (sizeof(scl_dotype->id)-1), required); + ret |= scl_get_attr_copy (sxDecCtrl, "cdc", scl_dotype->cdc, (sizeof(scl_dotype->cdc)-1), required); + if (ret != SD_SUCCESS) + { + return; + } + /* end required attributes */ + + sx_push (sxDecCtrl, sizeof(DOTypeElements)/sizeof(SX_ELEMENT), DOTypeElements, SD_FALSE); + } + else + sx_pop (sxDecCtrl); + } + +/************************************************************************/ +/* _DA_SEFun */ +/************************************************************************/ + +static ST_VOID _DA_SEFun (SX_DEC_CTRL *sxDecCtrl) + { + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + SCL_DEC_CTRL *sclDecCtrl; + ST_CHAR *str; /* use for dchg, qchg, dupd */ + ST_RET ret; + ST_BOOLEAN required = SD_FALSE; + SCL_DA *scl_da; + ST_CHAR *desc; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + scl_da = sclDecCtrl->scl_da = scl_dotype_add_da (sclDecCtrl->sclInfo); + if (scl_da == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_dotype_add_da", SX_USER_ERROR); + return; + } + + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required); + if (ret == SD_SUCCESS) + scl_da->desc = chk_strdup (desc); /* Alloc & copy desc string */ + ret = scl_get_attr_copy (sxDecCtrl, "sAddr", scl_da->sAddr, (sizeof(scl_da->sAddr)-1), required); + ret = scl_get_attr_copy (sxDecCtrl, "valKind", scl_da->valKind, (sizeof(scl_da->valKind)-1), required); + if (ret) + strcpy (scl_da->valKind, "Set"); /* default */ + ret = scl_get_attr_copy (sxDecCtrl, "type", scl_da->type, (sizeof(scl_da->type)-1), required); + ret = scl_get_uint_attr (sxDecCtrl, "count", &scl_da->count, required); + ret = scl_get_attr_ptr (sxDecCtrl, "dchg", &str, required); + if (ret == SD_SUCCESS && stricmp(str, "true") == 0) + scl_da->dchg = SD_TRUE; + + ret = scl_get_attr_ptr (sxDecCtrl, "qchg", &str, required); + if (ret == SD_SUCCESS && stricmp(str, "true") == 0) + scl_da->qchg = SD_TRUE; + + ret = scl_get_attr_ptr (sxDecCtrl, "dupd", &str, required); + if (ret == SD_SUCCESS && stricmp(str, "true") == 0) + scl_da->dupd = SD_TRUE; + /* end optional attributes */ + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "name", scl_da->name, (sizeof(scl_da->name)-1), required); + ret |= scl_get_attr_copy (sxDecCtrl, "bType", scl_da->bType, (sizeof(scl_da->bType)-1), required); + ret |= scl_get_attr_copy (sxDecCtrl, "fc", scl_da->fc, (sizeof(scl_da->fc)-1), required); + if (ret != SD_SUCCESS) + { + return; + } + /* end required attributes */ + sx_push (sxDecCtrl, sizeof(DAElements)/sizeof(SX_ELEMENT), DAElements, SD_FALSE); + } + else + sx_pop (sxDecCtrl); + } + +/************************************************************************/ +/* _SDO_SFun */ +/************************************************************************/ + +static ST_VOID _SDO_SFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; +SCL_DA *scl_da; +ST_CHAR *desc; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + scl_da = scl_dotype_add_sdo (sclDecCtrl->sclInfo); + if (scl_da == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_dotype_add_sdo", SX_USER_ERROR); + return; + } + + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required); + if (ret == SD_SUCCESS) + scl_da->desc = chk_strdup (desc); /* Alloc & copy desc string */ + /* end optional attributes */ + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "name", scl_da->name, (sizeof(scl_da->name)-1), required); + ret |= scl_get_attr_copy (sxDecCtrl, "type", scl_da->type, (sizeof(scl_da->type)-1), required); + if (ret != SD_SUCCESS) + { + return; + } + /* end required attributes */ + } + +/************************************************************************/ +/* _DA_Val_SEFun */ +/************************************************************************/ + +static ST_VOID _DA_Val_SEFun (SX_DEC_CTRL *sxDecCtrl) + { + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + /* start optional attributes (don't care about return) */ + scl_get_uint_attr (sxDecCtrl, "sGroup", &sclDecCtrl->scl_da->sGroup, SCL_ATTR_OPTIONAL); + /* end optional attributes */ + } + else /* reason = SX_ELEMENT_END */ + { + SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + ST_RET ret; + ST_INT strLen; + ST_CHAR *Val; + ret = sx_get_string_ptr (sxDecCtrl, &Val, &strLen); + if (ret==SD_SUCCESS) + sclDecCtrl->scl_da->Val = chk_strdup (Val); /* alloc & store Val*/ + else + scl_stop_parsing (sxDecCtrl, "DA Val", SX_USER_ERROR); + } + } + +/************************************************************************/ +/* _DAType_SEFun */ +/************************************************************************/ + +static ST_VOID _DAType_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; +SCL_DATYPE *scl_datype; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + scl_datype = scl_datype_create (sclDecCtrl->sclInfo); + if (scl_datype == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_datype_create", SX_USER_ERROR); + return; + } + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "id", scl_datype->id, (sizeof(scl_datype->id)-1), required); + if (ret != SD_SUCCESS) + { + return; + } + /* end required attributes */ + + sx_push (sxDecCtrl, sizeof(DATypeElements)/sizeof(SX_ELEMENT), DATypeElements, SD_FALSE); + } + else + sx_pop (sxDecCtrl); + } + +/************************************************************************/ +/* _BDA_SEFun */ +/************************************************************************/ + +static ST_VOID _BDA_SEFun (SX_DEC_CTRL *sxDecCtrl) + { + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + SCL_DEC_CTRL *sclDecCtrl; + ST_RET ret; + ST_BOOLEAN required = SD_FALSE; + SCL_BDA *scl_bda; + ST_CHAR *desc; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + scl_bda = sclDecCtrl->scl_bda = scl_datype_add_bda (sclDecCtrl->sclInfo); + if (scl_bda == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_datype_add_bda", SX_USER_ERROR); + return; + } + + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required); + if (ret == SD_SUCCESS) + scl_bda->desc = chk_strdup (desc); /* Alloc & copy desc string */ + ret = scl_get_attr_copy (sxDecCtrl, "sAddr", scl_bda->sAddr, (sizeof(scl_bda->sAddr)-1), required); + ret = scl_get_attr_copy (sxDecCtrl, "valKind", scl_bda->valKind, (sizeof(scl_bda->valKind)-1), required); + if (ret) + strcpy (scl_bda->valKind, "Set"); /* default */ + ret = scl_get_attr_copy (sxDecCtrl, "type", scl_bda->type, (sizeof(scl_bda->type)-1), required); + ret = scl_get_uint_attr (sxDecCtrl, "count", &scl_bda->count, required); + /* end optional attributes */ + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "name", scl_bda->name, (sizeof(scl_bda->name)-1), required); + ret |= scl_get_attr_copy (sxDecCtrl, "bType", scl_bda->bType, (sizeof(scl_bda->bType)-1), required); + if (ret != SD_SUCCESS) + { + return; + } + /* end required attributes */ + sx_push (sxDecCtrl, sizeof(BDAElements)/sizeof(SX_ELEMENT), BDAElements, SD_FALSE); + } + else + sx_pop (sxDecCtrl); + } + +/************************************************************************/ +/* _BDA_Val_SEFun */ +/************************************************************************/ + +static ST_VOID _BDA_Val_SEFun (SX_DEC_CTRL *sxDecCtrl) + { + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + /* start optional attributes (don't care about return) */ + scl_get_uint_attr (sxDecCtrl, "sGroup", &sclDecCtrl->scl_bda->sGroup, SCL_ATTR_OPTIONAL); + /* end optional attributes */ + } + else /* reason = SX_ELEMENT_END */ + { + SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + ST_RET ret; + ST_INT strLen; + ST_CHAR *Val; + ret = sx_get_string_ptr (sxDecCtrl, &Val, &strLen); + if (ret==SD_SUCCESS) + sclDecCtrl->scl_bda->Val = chk_strdup (Val); /* alloc & store Val*/ + else + scl_stop_parsing (sxDecCtrl, "BDA Val", SX_USER_ERROR); + } + } + +/************************************************************************/ +/* _EnumType_SEFun */ +/************************************************************************/ + +static ST_VOID _EnumType_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_RET ret; +ST_BOOLEAN required = SD_FALSE; +SCL_ENUMTYPE *scl_enumtype; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + if ((scl_enumtype = scl_enumtype_create (sclDecCtrl->sclInfo)) == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_enumtype_create", SX_USER_ERROR); + return; + } + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_attr_copy (sxDecCtrl, "id", scl_enumtype->id, (sizeof(scl_enumtype->id)-1), required); + if (ret != SD_SUCCESS) + { + return; + } + /* end required attributes */ + + sx_push (sxDecCtrl, sizeof(EnumTypeElements)/sizeof(SX_ELEMENT), EnumTypeElements, SD_FALSE); + } + else + sx_pop (sxDecCtrl); + } + +/************************************************************************/ +/* _EnumVal_SEFun */ +/************************************************************************/ + +static ST_VOID _EnumVal_SEFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_RET ret; +ST_INT strLen; +ST_BOOLEAN required = SD_FALSE; +SCL_ENUMVAL *scl_enumval; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + if (sxDecCtrl->reason == SX_ELEMENT_START) + { + if ((scl_enumval = sclDecCtrl->scl_enumval = scl_enumtype_add_enumval (sclDecCtrl->sclInfo)) == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_enumtype_add_enumval", SX_USER_ERROR); + return; + } + + /* start required attributes */ + required = SD_TRUE; + ret = scl_get_int_attr (sxDecCtrl, "ord", &scl_enumval->ord, required); + if (ret != SD_SUCCESS) + { + return; + } + /* end required attributes */ + } + else /* reason = SX_ELEMENT_END */ + { + scl_enumval = sclDecCtrl->scl_enumval; + /* CRITICAL: Init strLen = max len. After sx_get_string, strLen = actual len*/ + strLen = sizeof(scl_enumval->EnumVal)-1; + ret = sx_get_string (sxDecCtrl, scl_enumval->EnumVal, &strLen); + if (ret != SD_SUCCESS) + scl_stop_parsing (sxDecCtrl, "_EnumVal_SEFun", SX_USER_ERROR); + } + } + +/************************************************************************/ +/* _scl_unknown_el_start */ +/************************************************************************/ + +static ST_RET _scl_unknown_el_start (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag) + { + SXLOG_DEC1 ("SCL PARSE: Unneeded or unknown element '%s'", tag); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _scl_unknown_el_end */ +/************************************************************************/ + +static ST_RET _scl_unknown_el_end (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag) + { + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _SampledValueControl_SEFun */ +/* DEBUG: if parser called separate start and end functions, the lower */ +/* functs could be called directly & this funct would not be needed. */ +/************************************************************************/ +static ST_VOID _SampledValueControl_SEFun (SX_DEC_CTRL *sxDecCtrl) + { + if (sxDecCtrl->reason == SX_ELEMENT_START) + _SampledValueControl_SFun (sxDecCtrl); + else + _SampledValueControl_EFun (sxDecCtrl); + } +/************************************************************************/ +/* _SampledValueControl_SFun */ +/* Handle Start tag */ +/************************************************************************/ +static ST_VOID _SampledValueControl_SFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_CHAR *str; /* ptr set by scl_get_attr_ptr */ +ST_RET ret; +SCL_SVCB *scl_svcb; +ST_CHAR *desc; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + + /* Alloc struct, save in sclDecCtrl, & set local ptr to it. */ + scl_svcb = sclDecCtrl->scl_svcb = scl_svcb_add (sclDecCtrl->sclInfo); + if (scl_svcb == NULL) + { + scl_stop_parsing (sxDecCtrl, "scl_svcb_add", SX_USER_ERROR); + return; + } + + /* start required attributes */ + ret = scl_get_attr_copy (sxDecCtrl, "name", scl_svcb->name, (sizeof(scl_svcb->name)-1), SCL_ATTR_REQUIRED); + ret |= scl_get_attr_copy (sxDecCtrl, "smvID", scl_svcb->smvID, (sizeof(scl_svcb->smvID)-1), SCL_ATTR_REQUIRED); + ret |= scl_get_uint_attr (sxDecCtrl, "smpRate", &scl_svcb->smpRate, SCL_ATTR_REQUIRED); + ret |= scl_get_uint_attr (sxDecCtrl, "nofASDU", &scl_svcb->nofASDU, SCL_ATTR_REQUIRED); + if (ret != SD_SUCCESS) + return; /* At least one required attr not found. Stop now. */ + /* end required attributes */ + + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, SCL_ATTR_OPTIONAL); + if (ret == SD_SUCCESS) + scl_svcb->desc = chk_strdup (desc); /* Alloc & copy desc string */ + ret = scl_get_attr_copy (sxDecCtrl, "datSet", scl_svcb->datSet, (sizeof(scl_svcb->datSet)-1), SCL_ATTR_OPTIONAL); + ret = scl_get_uint_attr (sxDecCtrl, "confRev", &scl_svcb->confRev, SCL_ATTR_OPTIONAL); + ret = scl_get_attr_ptr (sxDecCtrl, "multicast", &str, SCL_ATTR_OPTIONAL); /* chk "str" below*/ + if (ret == SD_SUCCESS && stricmp(str, "false") == 0) + scl_svcb->multicast = SD_FALSE; + else + scl_svcb->multicast = SD_TRUE; /* default value */ + /* end optional attributes */ + + sx_push (sxDecCtrl, sizeof(SampledValueControlElements)/sizeof(SX_ELEMENT), SampledValueControlElements, SD_FALSE); + } +/************************************************************************/ +/* _SampledValueControl_EFun */ +/* Handle End tag */ +/************************************************************************/ +static ST_VOID _SampledValueControl_EFun (SX_DEC_CTRL *sxDecCtrl) + { + sx_pop (sxDecCtrl); + } + +/************************************************************************/ +/* _SmvOpts_SFun */ +/************************************************************************/ +static ST_VOID _SmvOpts_SFun (SX_DEC_CTRL *sxDecCtrl) + { +SCL_DEC_CTRL *sclDecCtrl; +ST_CHAR *str; /* ptr set by scl_get_attr_ptr */ +ST_RET ret; +SCL_SVCB *scl_svcb; + + sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr; + scl_svcb = sclDecCtrl->scl_svcb; + + /* start optional attributes */ + ret = scl_get_attr_ptr (sxDecCtrl, "sampleRate", &str, SCL_ATTR_OPTIONAL); + if (ret == SD_SUCCESS && stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(scl_svcb->OptFlds, SVOPT_BITNUM_SMPRATE); + } + + ret = scl_get_attr_ptr (sxDecCtrl, "refreshTime", &str, SCL_ATTR_OPTIONAL); + if (ret == SD_SUCCESS && stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(scl_svcb->OptFlds, SVOPT_BITNUM_REFRTM); + } + + ret = scl_get_attr_ptr (sxDecCtrl, "sampleSynchronized", &str, SCL_ATTR_OPTIONAL); + if (ret == SD_SUCCESS && stricmp(str, "true") == 0) + { + BSTR_BIT_SET_ON(scl_svcb->OptFlds, SVOPT_BITNUM_SMPSYNCH); + } + + ret = scl_get_attr_ptr (sxDecCtrl, "security", &str, SCL_ATTR_OPTIONAL); + if (ret == SD_SUCCESS && stricmp(str, "true") == 0) + scl_svcb->securityPres = SD_TRUE; /* scl_svcb calloced so init val is FALSE*/ + + /* NOTE: SCL calls this "dataRef", but 7-2 & 9-2 call it "DatSet". */ + ret = scl_get_attr_ptr (sxDecCtrl, "dataRef", &str, SCL_ATTR_OPTIONAL); + if (ret == SD_SUCCESS && stricmp(str, "true") == 0) + scl_svcb->dataRefPres = SD_TRUE; /* scl_svcb calloced so init val is FALSE*/ + /* end optional attributes */ + } diff --git a/mmslib/util/sclstore.c b/mmslib/util/sclstore.c new file mode 100644 index 0000000..5974aa2 --- /dev/null +++ b/mmslib/util/sclstore.c @@ -0,0 +1,737 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2004-2006 All Rights Reserved */ +/* */ +/* MODULE NAME : sclstore.c */ +/* PRODUCT(S) : MMS-EASE-LITE */ +/* */ +/* MODULE DESCRIPTION : */ +/* Functions to store information parsed from SCL file. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* scl_lntype_create */ +/* scl_lntype_add_do */ +/* scl_dotype_create */ +/* scl_dotype_add_da */ +/* scl_dotype_add_sdo */ +/* scl_datype_create */ +/* scl_datype_add_bda */ +/* scl_enumtype_create */ +/* scl_enumtype_add_enumval */ +/* scl_fcda_add */ +/* scl_dai_add */ +/* scl_dataset_add */ +/* scl_rcb_add */ +/* scl_lcb_add */ +/* scl_gcb_add */ +/* scl_ln_add */ +/* scl_ld_create */ +/* scl_info_destroy */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 04/23/08 JRB 11 Add scl_sgcb_add. */ +/* 07/26/06 JRB 10 Add scl_subnet_add, scl_cap_add, scl_gse_add,*/ +/* scl_smv_add. */ +/* 04/04/06 JRB 09 Add scl_svcb_add: alloc SCL_SVCB & add to list.*/ +/* 03/15/06 JRB 08 Simplify functions: Do not copy data. */ +/* Most functions take only (SCL_INFO *) arg & */ +/* just alloc struct and add to linked list. */ +/* Del scl_dotype_add_da_val, */ +/* scl_datype_add_bda_val, scl_header_save. */ +/* 01/30/06 GLB 07 Integrated porting changes for VMS */ +/* 07/25/05 JRB 06 If nameStructure!=IEDName, ignore it and */ +/* assume nameStructure=IEDName anyway. */ +/* 06/29/05 CRM 05 Add scl_info_destroy. */ +/* 06/24/05 JRB 04 Chg "ord" from unsigned to signed value. */ +/* 02/15/05 JRB 03 Chg scl_ld_create to generate scl_ld->domName.*/ +/* Chg scl_fcda_add to generate scl_fcda->domName.*/ +/* Chg scl_ln_add to generate scl_ln->varName. */ +/* Add scl_header_save. */ +/* 07/19/04 JRB 02 Add scl_lcb_add, scl_gcb_add. */ +/* 06/10/04 JRB 01 Initial Revision. */ +/************************************************************************/ +#include "glbtypes.h" +#include "sysincs.h" +#include "scl.h" +#include "sx_log.h" +#include "str_util.h" + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/* NOTE: + * Functions with "scl_" prefix used while parsing SCL file to + * store data in linked lists. + * Functions with "scl2_" prefix (see sclproc.c) used to read info from + * linked lists and create MMS objects (Domains, variables, NVLs, etc.). + */ + +/************************************************************************/ +/* scl_lntype_create */ +/* Begin creation of a Logical Node Type (LNodeType). */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +SCL_LNTYPE *scl_lntype_create ( + SCL_INFO *scl_info) /* struct to store all SCL info */ + { +SCL_LNTYPE *scl_lntype; + + scl_lntype = (SCL_LNTYPE *) chk_calloc (1, sizeof (SCL_LNTYPE)); + /* Add LNType to front of LNType List. */ + list_add_first (&scl_info->lnTypeHead, scl_lntype); + return (scl_lntype); + } + +/************************************************************************/ +/* scl_lntype_add_do */ +/* Add a Data Object (DO) to a Logical Node Type (LNodeType). */ +/* Adds to lntype created by most recent call to "scl_lntype_create". */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +SCL_DO *scl_lntype_add_do ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_DO *scl_do = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->lnTypeHead) + { + scl_do = (SCL_DO *) chk_calloc (1, sizeof (SCL_DO)); + /* Add DO to front of DO List in first entry of LNType list */ + list_add_first (&scl_info->lnTypeHead->doHead, scl_do); + } + else + SXLOG_ERR0 ("Cannot add DO to NULL LNTYPE"); + return (scl_do); + } + +/************************************************************************/ +/* scl_dotype_create */ +/* Begin creation of a Data Object Type (DOType). */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +SCL_DOTYPE *scl_dotype_create ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_DOTYPE *scl_dotype; + + scl_dotype = (SCL_DOTYPE *) chk_calloc (1, sizeof (SCL_DOTYPE)); + /* Add DOType to front of DOType List. */ + list_add_first (&scl_info->doTypeHead, scl_dotype); + return (scl_dotype); + } + +/************************************************************************/ +/* scl_dotype_add_da */ +/* Add a Data Attribute (DA) to a Data Object Type (DOType). */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +SCL_DA *scl_dotype_add_da ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_DA *scl_da = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->doTypeHead) + { + scl_da = (SCL_DA *) chk_calloc (1, sizeof (SCL_DA)); + /* CRITICAL: DA and SDO use same struct, "objtype" tells which one it is.*/ + scl_da->objtype = SCL_OBJTYPE_DA; + /* Add DA to front of DA List in first entry of DOType list */ + list_add_first (&scl_info->doTypeHead->daHead, scl_da); + } + else + SXLOG_ERR0 ("Cannot add DA to NULL DO"); + return (scl_da); + } + +/************************************************************************/ +/* scl_dotype_add_sdo */ +/* Add a (SDO) to a Data Object Type (DOType). */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +SCL_DA *scl_dotype_add_sdo ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_DA *scl_da = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->doTypeHead) + { + scl_da = (SCL_DA *) chk_calloc (1, sizeof (SCL_DA)); + /* CRITICAL: DA and SDO use same struct, "objtype" tells which one it is. + * NOTE: Because this is SDO, the sAddr, bType, and valKind members of + * the scl_da structure are NOT used. + */ + scl_da->objtype = SCL_OBJTYPE_SDO; + /* Add DA to front of DA List in first entry of DOType list */ + list_add_first (&scl_info->doTypeHead->daHead, scl_da); + } + else + SXLOG_ERR0 ("Cannot add SDO to NULL DO"); + return (scl_da); + } + +/************************************************************************/ +/* scl_datype_create */ +/* Begin creation of a Data Attribute Type (DAType). */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +SCL_DATYPE *scl_datype_create ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_DATYPE *scl_datype; + + scl_datype = (SCL_DATYPE *) chk_calloc (1, sizeof (SCL_DATYPE)); + /* Add DAType to front of DAType List. */ + list_add_first (&scl_info->daTypeHead, scl_datype); + return (scl_datype); + } +/************************************************************************/ +/* scl_datype_add_bda */ +/* Add a Basic Data Attribute (BDA) to a Data Attribute Type (DAType). */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +SCL_BDA *scl_datype_add_bda ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_BDA *scl_bda = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->daTypeHead) + { + scl_bda = (SCL_BDA *) chk_calloc (1, sizeof (SCL_BDA)); + /* Add BDA to front of BDA List in first entry of DAType list */ + list_add_first (&scl_info->daTypeHead->bdaHead, scl_bda); + } + else + SXLOG_ERR0 ("Cannot add BDA to NULL DATYPE"); + return (scl_bda); + } + +/************************************************************************/ +/* scl_enumtype_create */ +/* Begin creation of an EnumType. */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +SCL_ENUMTYPE *scl_enumtype_create ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_ENUMTYPE *scl_enumtype; + + scl_enumtype = (SCL_ENUMTYPE *) chk_calloc (1, sizeof (SCL_ENUMTYPE)); + /* Add EnumType to front of EnumType List. */ + list_add_first (&scl_info->enumTypeHead, scl_enumtype); + return (scl_enumtype); + } + + +/************************************************************************/ +/* scl_enumtype_add_enumval */ +/* Add an EnumVal to an EnumType. */ +/* Add to EnumType created by most recent call to scl_enumtype_create. */ +/* RETURNS: SD_SUCCESS or error code */ +/************************************************************************/ +SCL_ENUMVAL *scl_enumtype_add_enumval ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_ENUMVAL *scl_enumval = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->enumTypeHead) + { + scl_enumval = (SCL_ENUMVAL *) chk_calloc (1, sizeof (SCL_ENUMVAL)); + /* Add EnumVal to front of EnumVal List in first entry of EnumType list */ + list_add_first (&scl_info->enumTypeHead->enumvalHead, scl_enumval); + } + else + SXLOG_ERR0 ("Cannot add ENUMVAL to NULL ENUMTYPE"); + return (scl_enumval); + } + + +/************************************************************************/ +/* scl_fcda_add */ +/* Allocates a SCL_FCDA struct */ +/* and adds it to the linked list "fcdaHead" in SCL_DATASET. */ +/************************************************************************/ +SCL_FCDA *scl_fcda_add ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_FCDA *scl_fcda = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->ldHead + && scl_info->ldHead->lnHead + && scl_info->ldHead->lnHead->datasetHead) + { + scl_fcda = (SCL_FCDA *) chk_calloc (1, sizeof (SCL_FCDA)); + /* Add FCDA to front of FCDA List. */ + list_add_first (&scl_info->ldHead->lnHead->datasetHead->fcdaHead, scl_fcda); + } + else + SXLOG_ERR0 ("Cannot add FCDA to NULL DATASET"); + + return (scl_fcda); + } + +/************************************************************************/ +/* scl_dai_add */ +/* Allocates a SCL_DAI struct */ +/* and adds it to the linked list "daiHead" in SCL_LN. */ +/************************************************************************/ +SCL_DAI *scl_dai_add ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_DAI *scl_dai = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->ldHead + && scl_info->ldHead->lnHead) + { + scl_dai = (SCL_DAI *) chk_calloc (1, sizeof (SCL_DAI)); + /* Add DAI to front of DAI List. */ + list_add_first (&scl_info->ldHead->lnHead->daiHead, scl_dai); + } + else + SXLOG_ERR0 ("Cannot add DAI to NULL LN"); + return (scl_dai); + } + +/************************************************************************/ +/* scl_dataset_add */ +/* Allocates a SCL_DATASET struct */ +/* and adds it to the linked list "datasetHead" in SCL_LN. */ +/************************************************************************/ +SCL_DATASET *scl_dataset_add ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + /* TRUNCATED if longer than buffer */ + { +SCL_DATASET *scl_dataset = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->ldHead + && scl_info->ldHead->lnHead) + { + scl_dataset = (SCL_DATASET *) chk_calloc (1, sizeof (SCL_DATASET)); + /* Add DATASET to front of DATASET List. */ + list_add_first (&scl_info->ldHead->lnHead->datasetHead, scl_dataset); + } + else + SXLOG_ERR0 ("Cannot add DATASET to NULL LN"); + return (scl_dataset); + } + +/************************************************************************/ +/* scl_rcb_add */ +/* Alloc & add SCL_RCB struct to the linked list "rcbHead" in SCL_LN. */ +/* NOTE: struct is not filled in yet. */ +/* NOTE: the RptEnabled element of the SCL file is ignored. SISCO software*/ +/* does not need to know which clients may access the RCB. */ +/************************************************************************/ +SCL_RCB *scl_rcb_add ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_RCB *scl_rcb = NULL; + + /* All higher level linked lists must be initialized. */ + if (scl_info->ldHead + && scl_info->ldHead->lnHead) + { + scl_rcb = (SCL_RCB *) chk_calloc (1, sizeof (SCL_RCB)); + /* Add RCB to front of RCB List. */ + list_add_first (&scl_info->ldHead->lnHead->rcbHead, scl_rcb); + } + else + SXLOG_ERR0 ("Cannot add RCB to NULL LN"); + return (scl_rcb); + } + +/************************************************************************/ +/* scl_lcb_add */ +/* Alloc & add a SCL_LCB struct to the linked list "lcbHead" in SCL_LN. */ +/* NOTE: struct is not filled in yet. */ +/************************************************************************/ +SCL_LCB *scl_lcb_add ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_LCB *scl_lcb = NULL; + + /* All higher level linked lists must be initialized. */ + if (scl_info->ldHead + && scl_info->ldHead->lnHead) + { + scl_lcb = (SCL_LCB *) chk_calloc (1, sizeof (SCL_LCB)); + /* Add LCB to front of LCB List. */ + list_add_first (&scl_info->ldHead->lnHead->lcbHead, scl_lcb); + } + else + SXLOG_ERR0 ("Cannot add LCB to NULL LN"); + return (scl_lcb); + } + +/************************************************************************/ +/* scl_gcb_add */ +/* Add a GOOSE Control Block (GCB). */ +/* Allocates a SCL_GCB struct */ +/* and adds it to the linked list "gcbHead" in SCL_LN. */ +/* NOTE: The SCL file may also contain one or more "IEDName" elements to*/ +/* indicate IEDs that should subscribe for GOOSE data. We have no */ +/* way to use this information, so it is ignored. */ +/************************************************************************/ +SCL_GCB *scl_gcb_add ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_GCB *scl_gcb = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->ldHead + && scl_info->ldHead->lnHead) + { + scl_gcb = (SCL_GCB *) chk_calloc (1, sizeof (SCL_GCB)); + /* Add GCB to front of GCB List. */ + list_add_first (&scl_info->ldHead->lnHead->gcbHead, scl_gcb); + } + else + SXLOG_ERR0 ("Cannot add GCB (GOOSE Control Block) to NULL LN"); + return (scl_gcb); + } + +/************************************************************************/ +/* scl_sgcb_add */ +/* Add a Setting Group Control Block (SGCB). */ +/* Allocates a SCL_SGCB struct, stores ptr in "sgcb" in SCL_LN. */ +/************************************************************************/ +SCL_SGCB *scl_sgcb_add ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_SGCB *scl_sgcb = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->ldHead + && scl_info->ldHead->lnHead) + { + /* Only one SGCB allowed. Make sure not already set. */ + if (scl_info->ldHead->lnHead->sgcb != NULL) + { + SXLOG_ERR0 ("Duplicate SGCB (Setting Group Control Block) not allowed"); + return (NULL); + } + else + scl_info->ldHead->lnHead->sgcb = scl_sgcb = (SCL_SGCB *) chk_calloc (1, sizeof (SCL_SGCB)); + } + else + SXLOG_ERR0 ("Cannot add SGCB (Setting Group Control Block) to NULL LN"); + return (scl_sgcb); + } + +/************************************************************************/ +/* scl_svcb_add */ +/* Alloc & add SCL_SVCB struct to the linked list "svcbHead" in SCL_LN. */ +/* NOTE: struct is not filled in yet. */ +/************************************************************************/ +SCL_SVCB *scl_svcb_add ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_SVCB *scl_svcb = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->ldHead + && scl_info->ldHead->lnHead) + { + scl_svcb = (SCL_SVCB *) chk_calloc (1, sizeof(SCL_SVCB)); + /* Add to front of list. */ + list_add_first (&scl_info->ldHead->lnHead->svcbHead, scl_svcb); + } + else + SXLOG_ERR0 ("Cannot add SVCB to NULL LN"); + return (scl_svcb); + } + +/************************************************************************/ +/* scl_ln_add */ +/* Allocates a SCL_LN struct */ +/* and adds it to the linked list "lnHead" in SCL_LD. */ +/************************************************************************/ +SCL_LN *scl_ln_add ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_LN *scl_ln = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->ldHead) + { + scl_ln = (SCL_LN *) chk_calloc (1, sizeof (SCL_LN)); + /* Add LN to front of LN List. */ + list_add_first (&scl_info->ldHead->lnHead, scl_ln); + } + else + SXLOG_ERR0 ("Cannot add LN to NULL LD"); + return (scl_ln); + } + +/************************************************************************/ +/* scl_ld_create */ +/* Allocates SCL_LD struct */ +/* and adds it to the linked list "ldHead" in SCL_INFO. */ +/************************************************************************/ +SCL_LD *scl_ld_create ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_LD *scl_ld = NULL; /* assume failure */ + + scl_ld = (SCL_LD *) chk_calloc (1, sizeof (SCL_LD)); + /* Add LD to front of LD List. */ + list_add_first (&scl_info->ldHead, scl_ld); + + return (scl_ld); + } + +/************************************************************************/ +/* scl_subnet_add */ +/* Allocates SCL_SUBNET struct */ +/* and adds it to the linked list "subnetHead" in SCL_INFO. */ +/************************************************************************/ +SCL_SUBNET *scl_subnet_add ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_SUBNET *scl_subnet = NULL; /* assume failure */ + + scl_subnet = (SCL_SUBNET *) chk_calloc (1, sizeof (SCL_SUBNET)); + /* Add to front of list. */ + list_add_first (&scl_info->subnetHead, scl_subnet); + + return (scl_subnet); + } + +/************************************************************************/ +/* scl_cap_add */ +/* Allocates a SCL_CAP struct */ +/* and adds it to the linked list "capHead" in SCL_SUBNET. */ +/************************************************************************/ +SCL_CAP *scl_cap_add ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_CAP *scl_cap = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->subnetHead) + { + scl_cap = (SCL_CAP *) chk_calloc (1, sizeof (SCL_CAP)); + /* Add to front of list. */ + list_add_first (&scl_info->subnetHead->capHead, scl_cap); + } + else + SXLOG_ERR0 ("Cannot add CAP to NULL SUBNET"); + return (scl_cap); + } + +/************************************************************************/ +/* scl_gse_add */ +/* Allocates a SCL_GSE struct */ +/* and adds it to the linked list "gseHead" in SCL_CAP. */ +/************************************************************************/ +SCL_GSE *scl_gse_add ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_GSE *scl_gse = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->subnetHead->capHead) + { + scl_gse = (SCL_GSE *) chk_calloc (1, sizeof (SCL_GSE)); + /* Add to front of list. */ + list_add_first (&scl_info->subnetHead->capHead->gseHead, scl_gse); + } + else + SXLOG_ERR0 ("Cannot add GSE to NULL CAP"); + return (scl_gse); + } + +/************************************************************************/ +/* scl_smv_add */ +/* Allocates a SCL_SMV struct */ +/* and adds it to the linked list "smvHead" in SCL_CAP. */ +/************************************************************************/ +SCL_SMV *scl_smv_add ( + SCL_INFO *scl_info) /* main struct where all SCL info stored*/ + { +SCL_SMV *scl_smv = NULL; /* assume failure */ + + /* All higher level linked lists must be initialized. */ + if (scl_info->subnetHead->capHead) + { + scl_smv = (SCL_SMV *) chk_calloc (1, sizeof (SCL_SMV)); + /* Add to front of list. */ + list_add_first (&scl_info->subnetHead->capHead->smvHead, scl_smv); + } + else + SXLOG_ERR0 ("Cannot add SMV to NULL CAP"); + return (scl_smv); + } + +/************************************************************************/ +/* scl_info_destroy */ +/* Destroy all info stored in the SCL_INFO structure by "scl_parse". */ +/* NOTE: most buffers were allocated by functions in this module. The */ +/* elements "Val" and "desc" in several structures were allocated */ +/* by functions in "sclparse.c". */ +/************************************************************************/ +ST_VOID scl_info_destroy (SCL_INFO *scl_info) + { +SCL_LNTYPE *lnType; +SCL_DO *scl_do; +SCL_LD *scl_ld; +SCL_LN *scl_ln; +SCL_RCB *scl_rcb; +SCL_LCB *scl_lcb; +SCL_GCB *scl_gcb; +SCL_SVCB *scl_svcb; +SCL_DAI *scl_dai; +SCL_DATASET *scl_dataset; +SCL_FCDA *scl_fcda; +SCL_DATYPE * scl_daType; +SCL_BDA *scl_bda; +SCL_ENUMTYPE *scl_enum; +SCL_ENUMVAL *scl_enumval; +SCL_DOTYPE *scl_doType; +SCL_DA *scl_da; +SCL_SUBNET *scl_subnet; +SCL_CAP *scl_cap; +SCL_GSE *scl_gse; +SCL_SMV *scl_smv; + + while ((scl_subnet = (SCL_SUBNET *) list_get_first(&scl_info->subnetHead)) != NULL) + { + while ((scl_cap = (SCL_CAP *) list_get_first(&scl_subnet->capHead)) != NULL) + { + while ((scl_gse = (SCL_GSE *) list_get_first(&scl_cap->gseHead)) != NULL) + { + chk_free(scl_gse); + } + while ((scl_smv = (SCL_SMV *) list_get_first(&scl_cap->smvHead)) != NULL) + { + chk_free(scl_smv); + } + if (scl_cap->desc) + chk_free (scl_cap->desc); + chk_free (scl_cap); + } + if (scl_subnet->desc) + chk_free (scl_subnet->desc); + chk_free (scl_subnet); + } + + while ((scl_daType = (SCL_DATYPE *) list_get_first (&scl_info->daTypeHead)) != NULL) + { + while ((scl_bda = (SCL_BDA *) list_get_first (&scl_daType->bdaHead)) != NULL) + { + if (scl_bda->desc) + chk_free (scl_bda->desc); + if (scl_bda->Val) + chk_free (scl_bda->Val); + chk_free (scl_bda); + } + chk_free (scl_daType); + } + + while ((lnType = (SCL_LNTYPE *) list_get_first (&scl_info->lnTypeHead)) != NULL) + { + while ((scl_do = (SCL_DO *) list_get_first (&lnType->doHead)) != NULL) + { + chk_free (scl_do); + } + chk_free (lnType); + } + while ((scl_doType = (SCL_DOTYPE *) list_get_first (&scl_info->doTypeHead)) != NULL) + { + while ((scl_da = (SCL_DA *) list_get_first (&scl_doType->daHead)) != NULL) + { + if (scl_da->desc) + chk_free (scl_da->desc); + if (scl_da->Val) + chk_free (scl_da->Val); + chk_free (scl_da); + } + chk_free (scl_doType); + } + while ((scl_enum = (SCL_ENUMTYPE *) list_get_first (&scl_info->enumTypeHead)) != NULL) + { + while ((scl_enumval = (SCL_ENUMVAL *) list_get_first (&scl_enum->enumvalHead)) != NULL) + { + chk_free (scl_enumval); + } + chk_free (scl_enum); + } + while ((scl_ld = (SCL_LD *) list_get_first (&scl_info->ldHead)) != NULL) + { + while ((scl_ln = (SCL_LN *) list_get_first (&scl_ld->lnHead)) != NULL) + { + while ((scl_dai = (SCL_DAI *) list_get_first (&scl_ln->daiHead)) != NULL) + { + if (scl_dai->Val) + chk_free (scl_dai->Val); + chk_free (scl_dai); + } + + while ((scl_dataset = (SCL_DATASET *) list_get_first (&scl_ln->datasetHead)) != NULL) + { + while ((scl_fcda = (SCL_FCDA *) list_get_first (&scl_dataset->fcdaHead)) != NULL) + { + chk_free (scl_fcda); + } + if (scl_dataset->desc) + chk_free (scl_dataset->desc); + chk_free (scl_dataset); + } + + while ((scl_rcb = (SCL_RCB *) list_get_first (&scl_ln->rcbHead)) != NULL) + { + if (scl_rcb->desc) + chk_free (scl_rcb->desc); + chk_free (scl_rcb); + } + + while ((scl_lcb = (SCL_LCB *) list_get_first (&scl_ln->lcbHead)) != NULL) + { + if (scl_lcb->desc) + chk_free (scl_lcb->desc); + chk_free (scl_lcb); + } + + while ((scl_gcb = (SCL_GCB *) list_get_first (&scl_ln->gcbHead)) != NULL) + { + if (scl_gcb->desc) + chk_free (scl_gcb->desc); + chk_free (scl_gcb); + } + while ((scl_svcb = (SCL_SVCB *) list_get_first (&scl_ln->svcbHead)) != NULL) + { + if (scl_svcb->desc) + chk_free (scl_svcb->desc); + chk_free (scl_svcb); + } + /* Only one SGCB allowed (no linked list) */ + if (scl_ln->sgcb) + { + if (scl_ln->sgcb->desc) + chk_free (scl_ln->sgcb->desc); + chk_free (scl_ln->sgcb); + } + if (scl_ln->desc) + chk_free (scl_ln->desc); + chk_free (scl_ln); + } + if (scl_ld->desc) + chk_free (scl_ld->desc); + chk_free (scl_ld); + } + } + + diff --git a/mmslib/util/stdtime.c b/mmslib/util/stdtime.c new file mode 100644 index 0000000..91c1022 --- /dev/null +++ b/mmslib/util/stdtime.c @@ -0,0 +1,3815 @@ +/*+***************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/* ***************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtime.c */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Implementation of Standard Time Management Library Functions */ +/* */ +/* Note: Most functions a produce a return-code value STDTIME_RC. */ +/* The return code is zero if successful, otherwise it is a structured */ +/* value in which the low-order 10 bits enumerates an error reason, */ +/* and the upper 20 bits enumerates the high-level and low-level */ +/* functions where the error was detected. */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 02/20/08 JRB 14 Make STDTIME same as FILETIME (simplifies a lot). */ +/* Delete MANY unused functions. */ +/* Simplified TimeTypeEx & StructTmEx functions. */ +/* Del rounding code and PVT_STDTIME_ROUND macro. */ +/* Rewrote "Date" functions (simpler)(only for WIN32). */ +/* Del all STDTIME_LOCAL_USES_TZDB code. */ +/* Rewrote StdTimeToStdTimeStringA (much simpler). */ +/* Several functions ONLY for _WIN32 now. */ +/* 04/03/07 RLH 13 Improve performance of local vs. GMT conversions */ +/* 03/18/07 RLH 12 Correct bug in new normalization code. */ +/* 03/16/07 RLH 11 Normalize struct tm, SYSTEMTIME, and STDTIME_FIELDS */ +/* after rounding is applied; no rounding for formatting */ +/* functions. */ +/* 02/16/07 RLH 10 Clean up minor warnings under Linux */ +/* 01/11/07 RLH 09 Perform generalized rounding when creating outside */ +/* data types and extra (Ex) fields are not written. */ +/* This supersedes the Rev 08 changes. */ +/* Also, add TruncStdTimeString functions. */ +/* 01/10/07 RLH 08 Perform rounding at msec level when creating HpDate */ +/* 11/22/06 RLH 07 Ensure DelimitStdTimeString does not pad a trimmed */ +/* string value with trailing blanks. */ +/* 11/21/06 RLH 06 Remove unused variable to silence a warning msg */ +/* 10/27/06 RLH 05 Correct rounding in Rc_ArgDateExToStdTime */ +/* 10/18/06 RLH 04 Enhanced capabilities for timezone rules */ +/* 09/13/06 RLH 03 Ensure local time conversions work when TZ not set */ +/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */ +/* 01/18/06 RLH 01 Created */ +/*+***************************************************************************/ + +/* define list of error-code descriptions */ +/* this is done by temporary macro and include file */ + +#define STDTIME_ENUM_ERR(x) #x , + +static char * enum_stdtime_err_text[] = + { + "", /* dummy 0 entry */ +#include "stdtime_enum_err.h" + "" + }; + +/* temporary macro has served its purpose, so undefine it */ +#undef STDTIME_ENUM_ERR + + +/* create function name table from enum_stdtime_func.h */ +/* this is done by temporary macro and include file */ + +#define STDTIME_ENUM_FUNC(x) #x , + +static char * enum_stdtime_func_text[] = + { + "", /* dummy 0 entry */ +#include "stdtime_enum_func.h" + "" + }; + +/* temporary macro has served its purpose, so undefine it */ +#undef STDTIME_ENUM_FUNC + + +#include "stdtime.h" +#include "time_str.h" +#include +#include + +/*** private (helper) macros and static areas ********************************/ + +#define STDTIME_IF(x) ((rc=(x)) == STDTIME_OK) +#define STDTIME_IFNOT(x) ((rc=(x)) != STDTIME_OK) + +#define STDTIME_IN_RANGE(x,lo,hi) (((x) >= (lo)) && ((x) <= (hi))) + +#define PVT_STDTIME_FORMAT_BUFSIZE 256 +#define PVT_STDTIME_FORMAT_DEFAULT "%a %b %d %H:%M:%S %Y" + +/* standard delimiters for ISO 8601-formatted time strings */ +/* allow for user to redefine the standard delimiter string */ +/* this change must be done carefully */ + +#ifndef STDTIME_ISO_DLM_STR +#define STDTIME_ISO_DLM_STR "-T:." +#endif + +#if defined(_WIN32) + static char Pvt_StdTime_UserDelimString[5] = STDTIME_ISO_DLM_STR; +#endif + +#define PVT_STDTIME_ISO_DLM_DATE (STDTIME_ISO_DLM_STR[0]) +#define PVT_STDTIME_ISO_DLM_SEP (STDTIME_ISO_DLM_STR[1]) +#define PVT_STDTIME_ISO_DLM_TIME (STDTIME_ISO_DLM_STR[2]) +#define PVT_STDTIME_ISO_DLM_FRAC (STDTIME_ISO_DLM_STR[3]) + +#define PVT_STDTIME_USR_DLM_DATE (Pvt_StdTime_UserDelimString[0]) +#define PVT_STDTIME_USR_DLM_SEP (Pvt_StdTime_UserDelimString[1]) +#define PVT_STDTIME_USR_DLM_TIME (Pvt_StdTime_UserDelimString[2]) +#define PVT_STDTIME_USR_DLM_FRAC (Pvt_StdTime_UserDelimString[3]) + +#define PVT_STDTIME_SCALE_FILETIME 10000000 + +/* value of 11644473600000000 in hex, split into high/low 32-bit values */ +#define PVT_STDTIME_U32_TIMET_BASE_HI 0x019DB1DE +#define PVT_STDTIME_U32_TIMET_BASE_LO 0xD53E8000 + +/* value of 2650467743999999999 in hex, split into high/low 32-bit values */ +#define PVT_STDTIME_MAX_FILETIME_HI 0x24C85A5E +#define PVT_STDTIME_MAX_FILETIME_LO 0xD1C03FFF + +/* value of 864000000000 in hex, split into high/low 32-bit values */ +#define PVT_STDTIME_100NS_PERDAY_HI 0x000000C9 +#define PVT_STDTIME_100NS_PERDAY_LO 0x2A69C000 + + +/* form value of 1899-12-30 00:00:00.0000000 as a FILETIME equivalent */ +/* value of 94353120000000000 in hex, split into high/low 32-bit values */ +#define PVT_STDTIME_U32_COMDATE_BASE_HI 0x014F35A9 +#define PVT_STDTIME_U32_COMDATE_BASE_LO 0xA90CC000 + + +#define PVT_STDTIME_COMPARE(x) \ + if (pOne->x < pTwo->x) return STDTIME_LT; \ + if (pOne->x > pTwo->x) return STDTIME_GT /**/ + + +#define PVT_STDTIME_EXPORT_TZOA(x) \ + { \ + if ((x)->embTzo[0] != 0) \ + { \ + strncpy ((x)->extTzo.str, (x)->embTzo, STDTIME_TZO_LEN); \ + (x)->extTzo.str[STDTIME_TZO_LEN] = 0; \ + (x)->embTzo[0] = 0; \ + } \ + } /**/ + +#define PVT_STDTIME_IMPORT_TZOA(x) \ + { \ + if ((x)->extTzo.str[0] != 0) \ + { \ + strncpy ((x)->embTzo, (x)->extTzo.str, STDTIME_TZO_LEN); \ + (x)->embTzo[STDTIME_TZO_LEN] = 0; \ + (x)->extTzo.str[0] = 0; \ + } \ + } /**/ + + +/*** private (helper) functions **********************************************/ + + +/* NOTE: function names beginning with Rc_, Int_, Char_, Wchar_ and Bool_ */ +/* are private functions; the prefix identifies the return type. */ + + +/*-***************************************************************************/ +/* StdTimeRet */ +/* assemble a STDTIME return code */ +/* when basic error code is 0, always return 0 */ +/* (used to be static, but was needed in multiple modules) */ +/*****************************************************************************/ + + +STDTIME_RC StdTimeRet ( + const STDTIME_RC /*I*/ func, + const STDTIME_RC /*I*/ ec) + { + if (ec == 0) return 0; + return ((func & STDTIME_10_BITS) << 20) | (ec & STDTIME_20_BITS); + } + +/*-***************************************************************************/ +/* Bool_StdTime_IsBlankA - PRIVATE FUNCTION */ +/* Return STDTIME_TRUE if string is nul or whitespace only */ +/*****************************************************************************/ + +static STDTIME_BOOL Bool_StdTime_IsBlankA ( + const char * /*I*/ str) + { + if (str == NULL) + { + return STDTIME_FALSE; + } + + for (; *str; str++) + { + if (*str == 0) + { + break; + } + + if (*str > (char) ' ') + { + return STDTIME_FALSE; + } + } + + return STDTIME_TRUE; + + } /* Bool_StdTime_IsBlankA */ + + +#if 0 /* OBSOLETE: delete next release */ +/*-***************************************************************************/ +/* Rc_NormalizeStdTimeFields */ +/* ensure a STDTIME_FIELDS value is normalized, adjusting fields as needed. */ +/*****************************************************************************/ + + +#define PVT_STDTIME_NORMALIZE_FIELD(curr,num,next) \ + while ((curr) < 0) \ + { \ + (curr) += num; \ + (next)--; \ + } \ + if ((curr) >= num) \ + { \ + (next) += (curr) / num; \ + (curr) = (curr) % num; \ + } + + +STDTIME_RC Rc_NormalizeStdTimeFields ( + STDTIME_FIELDS * pFields) + { + STDTIME_DELTA delta = {0}; + int32_t new_day = 0; + int32_t max_day; + + STDTIME_ENUM_FUNC (Rc_NormalizeStdTimeFields) + + if (pFields == NULL) + { + STDTIME_RET_EC (null_argument); + } + + PVT_STDTIME_NORMALIZE_FIELD (pFields->nsec, 1000, pFields->usec) + PVT_STDTIME_NORMALIZE_FIELD (pFields->usec, 1000, pFields->msec) + PVT_STDTIME_NORMALIZE_FIELD (pFields->msec, 1000, pFields->sec ) + PVT_STDTIME_NORMALIZE_FIELD (pFields->sec, 60, pFields->min ) + PVT_STDTIME_NORMALIZE_FIELD (pFields->min, 60, pFields->hour) + PVT_STDTIME_NORMALIZE_FIELD (pFields->hour, 24, delta.day) + + if (delta.day == 0) + { + /* did not change the day, so no calendar normalization needed */ + STDTIME_RET_OK; + } + + /* easy normalization: just day, within current month */ + + max_day = StdTimeDaysInYearMon (pFields->year, pFields->mon); + new_day = pFields->day + delta.day; + + if ((new_day >= 1) + && (new_day <= max_day) + && (pFields->mon >= 1) + && (pFields->mon <= 12)) + { + /* month was good, and day did not overflow the month */ + pFields->day = new_day; + STDTIME_RET_OK; + } + + /* hard normalization: do full AddDelta processing */ + + STDTIME_RET (StdTimeFields_AddDelta (pFields, &delta)); + + } /* Rc_NormalizeStdTimeFields */ + +#undef PVT_STDTIME_NORMALIZE_FIELD + +/*-***************************************************************************/ +/* Rc_StdTime_NormalizeSystemTimeEx */ +/* ensure a SYSTEMTIME value is normalized, adjusting fields as needed. */ +/* method: convert to STDTIME_FIELDS, normalize that, and convert back. */ +/*****************************************************************************/ + +STDTIME_RC Rc_StdTime_NormalizeSystemTimeEx ( + STDTIME_WIN_SYSTEMTIME * /*IO*/ pSystemTime, + int32_t * /*IO*/ pUsec, + int32_t * /*IO*/ pNsec) + { + STDTIME_FIELDS fields = {0}; + STDTIME_ENUM_FUNC (Rc_StdTime_NormalizeSystemTimeEx) + + if (pSystemTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + fields.year = (int32_t) pSystemTime->wYear; + fields.mon = (int32_t) pSystemTime->wMonth; + fields.day = (int32_t) pSystemTime->wDay; + + fields.hour = (int32_t) pSystemTime->wHour; + fields.min = (int32_t) pSystemTime->wMinute; + fields.sec = (int32_t) pSystemTime->wSecond; + + fields.msec = (int32_t) pSystemTime->wMilliseconds; + + if (pUsec != NULL) + { + fields.usec = *pUsec; + } + + if (pNsec != NULL) + { + fields.nsec = *pNsec; + } + + rc = Rc_NormalizeStdTimeFields (&fields); + + pSystemTime->wYear = (STDTIME_WIN_WORD) fields.year; + pSystemTime->wMonth = (STDTIME_WIN_WORD) fields.mon ; + pSystemTime->wDay = (STDTIME_WIN_WORD) fields.day ; + + pSystemTime->wHour = (STDTIME_WIN_WORD) fields.hour; + pSystemTime->wMinute = (STDTIME_WIN_WORD) fields.min ; + pSystemTime->wSecond = (STDTIME_WIN_WORD) fields.sec ; + + pSystemTime->wMilliseconds = (STDTIME_WIN_WORD) fields.msec; + + if (pUsec != NULL) + { + *pUsec = fields.usec; + } + + if (pNsec != NULL) + { + *pNsec = fields.nsec; + } + + return rc; + + } /* Rc_StdTime_NormalizeSystemTimeEx */ + + +/*-***************************************************************************/ +/* Rc_StdTime_NormalizeStructTmEx */ +/* ensure a struct tm value is normalized, adjusting fields as needed. */ +/* method: convert to STDTIME_FIELDS, normalize that, and convert back. */ +/*****************************************************************************/ + +STDTIME_RC Rc_StdTime_NormalizeStructTmEx ( + struct tm * /*IO*/ pStructTm, + int32_t * /*IO*/ pMsec, + int32_t * /*IO*/ pUsec, + int32_t * /*IO*/ pNsec) + { + STDTIME_FIELDS fields = {0}; + + STDTIME_ENUM_FUNC (Rc_StdTime_NormalizeStructTmEx) + + if (pStructTm == NULL) + { + STDTIME_RET_EC (null_argument); + } + + + fields.year = (int32_t) pStructTm->tm_year + 1900; + fields.mon = (int32_t) pStructTm->tm_mon + 1; + fields.day = (int32_t) pStructTm->tm_mday; + + fields.hour = (int32_t) pStructTm->tm_hour; + fields.min = (int32_t) pStructTm->tm_min; + fields.sec = (int32_t) pStructTm->tm_sec; + + if (pMsec != NULL) + { + fields.msec = *pMsec; + } + + if (pUsec != NULL) + { + fields.usec = *pUsec; + } + + if (pNsec != NULL) + { + fields.nsec = *pNsec; + } + + rc = Rc_NormalizeStdTimeFields (&fields); + + pStructTm->tm_year = (int) fields.year - 1900; + pStructTm->tm_mon = (int) fields.mon - 1; + pStructTm->tm_mday = (int) fields.day; + + pStructTm->tm_hour = (int) fields.hour; + pStructTm->tm_min = (int) fields.min; + pStructTm->tm_sec = (int) fields.sec; + + if (pMsec != NULL) + { + *pMsec = fields.msec; + } + + if (pUsec != NULL) + { + *pUsec = fields.usec; + } + + if (pNsec != NULL) + { + *pNsec = fields.nsec; + } + + return rc; + + } /* Rc_StdTime_NormalizeStructTmEx */ +#endif /* OBSOLETE: delete next release */ + +/*-***************************************************************************/ +/* Rc_StdTime_FileTimeToSystemTimeEx - PRIVATE FUNCTION */ +/* convert FILETIME to SYSTEMTIME, extracting and storing fractional */ +/* seconds not available in a SYSTEMTIME structure, if pointers provided. */ +/*****************************************************************************/ + +static STDTIME_RC Rc_StdTime_FileTimeToSystemTimeEx ( + const STDTIME_WIN_FILETIME * /*I*/ pFileTime, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime, + int32_t * /*O*/ pUsec, + int32_t * /*O*/ pNsec) + { + /* helper function to convert FILETIME to SYSTEMTIME and capture */ + /* fractional milliseconds */ + + QUADLIB_I64 qFileTime; + QUADLIB_I64 work; + int32_t frac; + int32_t msec; + int32_t usec; + int32_t nsec; + + STDTIME_ENUM_FUNC (Rc_StdTime_FileTimeToSystemTimeEx) + + if (pSystemTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pSystemTime = StdTimeApiZeroSystemTime(); + + if (pFileTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + /* extract fractional seconds (units of 100 nanoseconds) */ + + QUADLIB_U64_HI(qFileTime) = pFileTime->dwHighDateTime; + QUADLIB_U64_LO(qFileTime) = pFileTime->dwLowDateTime; + + work = QUADLIB_U64_MOD ( + qFileTime, QUADLIB_U64_CASTU32 (PVT_STDTIME_SCALE_FILETIME)); + + frac = QUADLIB_U64_LO(work); + + if (! STDTIME_API_FILETIMETOSYSTEMTIME (pFileTime, pSystemTime)) + { + STDTIME_RET_EC (failure_in_api_FileTimeToSystemTime); + } + + /* extract 1 digit of nanoseconds, but make it a 3-digit value */ + + nsec = (frac % STDTIME_PREC_NSEC) * STDTIME_SCALE_NSEC; + frac /= STDTIME_PREC_NSEC; + usec = frac % 1000; + frac /= 1000; + msec = (frac % 1000); + + /* If pointers not NULL, copy values there. */ + if (pNsec) + *pNsec = nsec; + if (pUsec) + *pUsec = usec; + + pSystemTime->wMilliseconds = (STDTIME_WIN_WORD) msec; + +#if 0 /* OBSOLETE: delete next release */ + STDTIME_RET (Rc_StdTime_NormalizeSystemTimeEx (pSystemTime, pNsec, pUsec)); +#endif + STDTIME_RET_OK; + } /* Rc_StdTime_FileTimeToSystemTimeEx */ + + +/*-***************************************************************************/ +/* Rc_StdTime_SystemTimeExToFileTime - PRIVATE FUNCTION */ +/* convert SYSTEMTIME to FILETIME, incorporating additional parameters */ +/* to account for fractional seconds not available in a SYSTEMTIME. */ +/*****************************************************************************/ + +static STDTIME_RC Rc_StdTime_SystemTimeExToFileTime ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec, + STDTIME_WIN_FILETIME * /*O*/ pFileTime) + { + STDTIME_ENUM_FUNC (Rc_StdTime_SystemTimeExToFileTime) + + /* helper function to convert SYSTEMTIME to FILETIME and add in */ + /* fractional milliseconds */ + + if (pFileTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pFileTime = StdTimeApiZeroFileTime(); + + if (pSystemTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + if (! STDTIME_API_SYSTEMTIMETOFILETIME (pSystemTime, pFileTime)) + { + STDTIME_RET_EC (failure_in_api_SystemTimeToFileTime); + } + + if ((nUsec != 0) || (nNsec != 0)) + { + /* add in fractional seconds */ + STDTIME_DELTA delta = {0}; + STDTIME_SPAN span; + QUADLIB_I64 qFileTime; + + FILETIME_TO_QUADLIB_I64 (pFileTime, &qFileTime); + delta.usec = nUsec; + delta.nsec = nNsec; + StdTimeDeltaToStdTimeSpan (&delta, &span); + QUADLIB_I64_ADD_EQ (qFileTime, span.value); + QUADLIB_I64_TO_FILETIME (&qFileTime, pFileTime); + } + + STDTIME_RET_OK; + + } /* Rc_StdTime_SystemTimeExToFileTime */ + + +#if defined(_WIN32) +/*-***************************************************************************/ +/* Int_StdTime_GetNumField - PRIVATE FUNCTION */ +/* extract a fixed-length decimal string and Return int32_t value or -1 */ +/*****************************************************************************/ + +static int32_t Int_StdTime_GetNumField ( + const char * /*I*/ str, + int32_t /*I*/ len) + { + /* extract a decimal string and Return int32_t value */ + /* an exact number of digits must be present */ + /* string is delimited by length, not by null terminator */ + /* on error, Return -1 */ + + int32_t result = 0; + int32_t i; + int32_t c; + + if ((str == NULL) || (len < 1)) + { + return -1; + } + + for (i=0; i < len; i++) + { + c = str[i]; + + if ((c < '0') || (c > '9')) + { + return -1; + } + + result = (result * 10) + (c - '0'); + } + + return result; + + } /* Int_StdTime_GetNumField */ +#endif /* defined(_WIN32) */ + +/*-***************************************************************************/ +/* StdTimeYearIsLeap */ +/* Return 1 if year is leapyear, else Return 0 */ +/*****************************************************************************/ + +int32_t StdTimeYearIsLeap ( + int32_t /*I*/ year) + { + /* no assertions made about invalid years */ + + if ((year < STDTIME_YEAR_MIN) || (year > STDTIME_YEAR_MAX)) + { + return 0; + } + + if ((year % 4000) == 0) + { + return 0; /* multiples of 4000 are not leap years */ + } + + if ((year % 400) == 0) + { + return 1; /* multiples of 400 are leap years */ + } + + if ((year % 100) == 0) + { + return 0; /* multiples of 100 are not leap years */ + } + + if ((year % 4) == 0) + { + return 1; /* multiples of 4 are leap years */ + } + + return 0; /* all others are not leap years */ + + } /* StdTimeYearIsLeap */ + + +/*-***************************************************************************/ +/* StdTimeDaysInYearMon */ +/* calendar function: get maximum number of days in month for a given year */ +/*****************************************************************************/ + +static int32_t StdTimeDaysPerMonTab [13] = + { 00, + 31, /* JAN */ + 28, /* FEB */ + 31, /* MAR */ + 30, /* APR */ + 31, /* MAY */ + 30, /* JUN */ + 31, /* JUL */ + 31, /* AUG */ + 30, /* SEP */ + 31, /* OCT */ + 30, /* NOV */ + 31 /* DEC */ + }; + +int32_t StdTimeDaysInYearMon ( + int32_t /*I*/ year, + int32_t /*I*/ mon) + { + int32_t leap = 0; + + if ((year < STDTIME_YEAR_MIN) + || (year > STDTIME_YEAR_MAX) + || (mon < 1) + || (mon > 12)) + { + return 0; /* argument error */ + } + + if (mon == 2) + { + leap = StdTimeYearIsLeap (year); + } + + return leap + StdTimeDaysPerMonTab [mon]; + + } /* StdTimeDaysInYearMon */ + + +#if defined(_WIN32) +/*-***************************************************************************/ +/* Rc_StdTime_FileTimeSplit - PRIVATE FUNCTION */ +/* split FILETIME into FILETIME, usec and nsec. */ +/*****************************************************************************/ + +static STDTIME_RC Rc_StdTime_FileTimeSplit ( + STDTIME_WIN_FILETIME * /*IO*/ pFileTime, + int32_t * /*IO*/ pUsec, + int32_t * /*IO*/ pNsec) + { + QUADLIB_I64 qFileTime; + QUADLIB_I64 qFactor; + QUADLIB_I64 qResult; + QUADLIB_I64 qRemainder; + + STDTIME_ENUM_FUNC (Rc_StdTime_FileTimeSplit) + + if ((pFileTime == NULL) || (pUsec == NULL) || (pNsec == NULL)) + { + STDTIME_RET_EC (null_argument); + } + + /* divide 64-bit filetime by 10000 to extract usec,nsec */ + /* then Return these values */ + + FILETIME_TO_QUADLIB_I64 (pFileTime, &qFileTime); + QUADLIB_U64_HI (qFactor) = 0; + QUADLIB_U64_LO (qFactor) = 10000; + + qResult = QuadLibI64DivMod (qFileTime, qFactor, &qRemainder); + qFileTime = QUADLIB_I64_MUL (qResult, qFactor); + QUADLIB_I64_TO_FILETIME (&qFileTime, pFileTime); + + *pUsec = QUADLIB_I64_LO (qRemainder) / 10; + *pNsec = (QUADLIB_I64_LO (qRemainder) % 10) * 100; + + STDTIME_RET_OK; + + } /* Rc_StdTime_FileTimeSplit */ +#endif /* defined(_WIN32) */ + + +/*** StdTime/StdTimeFields conversions ***************************************/ + +#if defined(_WIN32) +/*-***************************************************************************/ +/* StdTimeToStdTimeFields */ +/* convert: StdTime structure to StdTimeFields structure */ +/* method: StdTime -> FILETIME -> SYSTEMTIME -> StdTimeFields */ +/*****************************************************************************/ + +STDTIME_RC StdTimeToStdTimeFields ( + const STDTIME * /*I*/ pStdTime, + STDTIME_FIELDS * /*O*/ pStdTimeFields) + { + STDTIME_WIN_FILETIME ft; + STDTIME_WIN_SYSTEMTIME st; + int32_t usec; + int32_t nsec; + + STDTIME_ENUM_FUNC (StdTimeToStdTimeField) + + if (pStdTimeFields == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pStdTimeFields = ZeroStdTimeFields (); + + if (pStdTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + if STDTIME_IF (StdTimeToFileTime (pStdTime, &ft)) + { + if STDTIME_IF (Rc_StdTime_FileTimeSplit (&ft, &usec, &nsec)) + { + if (STDTIME_API_FILETIMETOSYSTEMTIME (&ft, &st)) + { + STDTIME_RET (SystemTimeExToStdTimeFields ( + &st, usec, nsec, pStdTimeFields)); + } + else + { + STDTIME_RET_EC (failure_in_api_FileTimeToSystemTime); + } + } + } + + STDTIME_RET_RC; + + } /* StdTimeToStdTimeFields */ + + +/*-***************************************************************************/ +/* StdTimeFieldsToStdTime */ +/* convert: StdTimeFields structure to StdTime structure */ +/* method: StdTimeFields -> SYSTEMTIME -> FILETIME -> StdTime */ +/*****************************************************************************/ + +STDTIME_RC StdTimeFieldsToStdTime ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME * /*O*/ pStdTime) + { + STDTIME_WIN_FILETIME ft; + STDTIME_WIN_SYSTEMTIME st; + int32_t usec; + int32_t nsec; + + STDTIME_ENUM_FUNC (StdTimeFieldsToStdTime) + + if (pStdTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pStdTime = ZeroStdTime (); + + if (pStdTimeFields == NULL) + { + STDTIME_RET_EC (null_argument); + } + + if STDTIME_IF (StdTimeFieldsToSystemTimeEx ( + pStdTimeFields, &st, &usec, &nsec)) + { + if STDTIME_IF (Rc_StdTime_SystemTimeExToFileTime (&st, usec, nsec, &ft)) + { + *pStdTime = ft; + } + } + + STDTIME_RET_RC; + + } /* StdTimeFieldsToStdTime */ +#endif /* defined(_WIN32) */ + +/*** StdTime/external conversions ********************************************/ + +/*-***************************************************************************/ +/* StdTimeToStdTimeStringA */ +/* convert: StdTime structure to String formatted like this: */ +/* 2007-11-19T16:59:59.1234567 */ +/*****************************************************************************/ +STDTIME_RC StdTimeToStdTimeStringA ( + const STDTIME * /*I*/ pStdTime, + STDTIME_STRINGA * /*O*/ pStdTimeString) + { + struct tm tms; + int32_t fraction; /* number of 100-nanosecond intervals*/ + char sfraction [10]; + /* DEBUG: would be simpler if arg just changed to (char *) */ + char *string = (char *) pStdTimeString; /* cast arg to (char *) */ + size_t maxsize=28; /* caller buffer must be at least this big */ + int32_t nsec; + + STDTIME_ENUM_FUNC (StdTimeToStdTimeStringA) + + if (string == NULL) + { + STDTIME_RET_EC (null_argument); + } + /* Convert to "struct tm" for strftime. */ + rc = StdTimeToStructTmEx (pStdTime, &tms, &nsec); + if (rc) + return (rc); + + fraction = nsec / 100; /* reduce to 7 digits */ + sprintf (sfraction, ".%07d", fraction); /* include '.' in this string*/ + + /* CRITICAL: leave room to add 8 char suffix (fraction of second) */ + if (strftime (string, maxsize-8, "%Y-%m-%dT%H:%M:%S", &tms) == 0) + { + STDTIME_RET_EC (argument_out_of_range); /* maxsize too small */ + } + strcat (string, sfraction); + assert (strlen (string) < maxsize); + STDTIME_RET_RC; + } + + +/*** external/StdTime conversions ********************************************/ + +#if defined(_WIN32) +/*-***************************************************************************/ +/* StdTimeStringAToStdTime */ +/* convert: StdTimeStringA structure to StdTime structure */ +/*****************************************************************************/ + +STDTIME_RC StdTimeStringAToStdTime ( + const STDTIME_STRINGA * /*I*/ pStdTimeString, + STDTIME * /*O*/ pStdTime) + { + STDTIME_FIELDS f; + + STDTIME_ENUM_FUNC (StdTimeStringAToStdTime) + + if (pStdTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pStdTime = ZeroStdTime (); + + if STDTIME_IF (StdTimeStringAToStdTimeFields (pStdTimeString, &f)) + { + /* StdTimeStringAToStdTimeFields will apply embTzo to form GMT */ + + STDTIME_RET (StdTimeFieldsToStdTime (&f, pStdTime)); + } + + STDTIME_RET_RC; + + } /* StdTimeStringAToStdTime */ + +/*** external/StdTimeFields conversions **************************************/ + +/*-***************************************************************************/ +/* StdTimeStringAToStdTimeFields */ +/* convert: StdTimeStringA structure to StdTimeFields structure */ +/*****************************************************************************/ + +/* string format: yyyy-mm-ddThh:mi:ss.fffffff */ +/* 0123456789012345678901234567 */ + +STDTIME_RC StdTimeStringAToStdTimeFields ( + const STDTIME_STRINGA * /*I*/ pStdTimeString, + STDTIME_FIELDS * /*O*/ pStdTimeFields) + { + /* method: validate delimiters, then extract numeric values */ + /* into a STDTIME_FIELDS structure. if a timezone offset is present */ + /* then validate it, and apply its value to the time fields */ + + STDTIME_STRINGA s; + STDTIME_TZOA tzo; + char c; + + STDTIME_ENUM_FUNC (StdTimeStringAToStdTimeFields) + + if (pStdTimeFields == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pStdTimeFields = ZeroStdTimeFields (); + + if (pStdTimeString == NULL) + { + STDTIME_RET_EC (null_argument); + } + + s = *pStdTimeString; + + /* check for some reasonable delimiters */ + + c = s.str[STDTIME_STRING_DLM_D1]; /* date delim between yyyy and mm */ + + if ( (c != PVT_STDTIME_ISO_DLM_DATE) /* normally '-' */ + && (c != PVT_STDTIME_USR_DLM_DATE) + && (c != '/') /* common but nonstandard delimiter */ + && (c != ' ') + && (c != 0 ) ) + { + STDTIME_RET_EC (invalid_delimiter); + } + + c = s.str[STDTIME_STRING_DLM_D2]; /* date delim between mo and dd */ + + if ( (c != PVT_STDTIME_ISO_DLM_DATE) /* normally '-' */ + && (c != PVT_STDTIME_USR_DLM_DATE) + && (c != '/') /* common but nonstandard delimiter */ + && (c != ' ') + && (c != 0 ) ) + { + STDTIME_RET_EC (invalid_delimiter); + } + + c = s.str[STDTIME_STRING_DLM_S1]; /* separator between dd and hh */ + + if ( (c != PVT_STDTIME_ISO_DLM_SEP) /* normally 'T' */ + && (c != PVT_STDTIME_USR_DLM_SEP) + && (c != ' ') + && (c != 0 ) ) + { + STDTIME_RET_EC (invalid_delimiter); + } + + c = s.str[STDTIME_STRING_DLM_T1]; /* time delim between hh and mi */ + + if ( (c != PVT_STDTIME_ISO_DLM_TIME) /* normally ':' */ + && (c != PVT_STDTIME_USR_DLM_TIME) + && (c != ' ') + && (c != 0 ) ) + { + STDTIME_RET_EC (invalid_delimiter); + } + + c = s.str[STDTIME_STRING_DLM_T2]; /* time delim between mi and ss */ + + if ( (c != PVT_STDTIME_ISO_DLM_TIME) /* normally ':' */ + && (c != PVT_STDTIME_USR_DLM_TIME) + && (c != ' ') + && (c != 0 ) ) + { + STDTIME_RET_EC (invalid_delimiter); + } + + c = s.str[STDTIME_STRING_DLM_F1]; /* fraction delim between ss and fffffff */ + + if ( (c != PVT_STDTIME_ISO_DLM_FRAC) /* normally '.' */ + && (c != PVT_STDTIME_USR_DLM_FRAC) + && (c != ' ') + && (c != ',') /* iso 8601 also allows comma here */ + && (c != 0 ) ) + { + STDTIME_RET_EC (invalid_delimiter); + } + + /* string may be followed by optional embTzo field */ + /* if so, we need to extract its value and adjust the time accordingly */ + /* it is valid for an embTzo to be empty (null string) */ + + strncpy (tzo.str, s.embTzo, STDTIME_TZO_LEN); + + if STDTIME_IFNOT (NormalizeStdTimeTzoA (&tzo)) /* normalize also validates */ + { + STDTIME_RET_RC; + } + + /* Int_StdTime_GetNumField Returns -1 on error */ + /* this will be detected via ValidStdTimeFields */ + + pStdTimeFields->year = Int_StdTime_GetNumField (s.str+0, 4); + pStdTimeFields->mon = Int_StdTime_GetNumField (s.str+5, 2); + pStdTimeFields->day = Int_StdTime_GetNumField (s.str+8, 2); + pStdTimeFields->hour = Int_StdTime_GetNumField (s.str+11, 2); + pStdTimeFields->min = Int_StdTime_GetNumField (s.str+14, 2); + pStdTimeFields->sec = Int_StdTime_GetNumField (s.str+17, 2); + pStdTimeFields->msec = Int_StdTime_GetNumField (s.str+20, 3); + pStdTimeFields->usec = Int_StdTime_GetNumField (s.str+23, 3); + + pStdTimeFields->nsec = Int_StdTime_GetNumField (s.str+26, 1) + * STDTIME_SCALE_NSEC; + + if STDTIME_IFNOT (ValidStdTimeFields (pStdTimeFields)) + { + STDTIME_RET_RC; + } + + if ((tzo.str[0] == '+') || (tzo.str[0] == '-')) + { + /* a valid, non-null, non-Z timezone offset exists */ + /* extract the timezone offset fields and adjust the stdtime fields */ + /* +hh:mm:ss# */ + /* 0123456789 */ + + STDTIME_DELTA delta = {0}; + + delta.hour = atoi (tzo.str+1); + delta.min = atoi (tzo.str+4); + + if (tzo.str[6] == ':') /* seconds field is present */ + { + delta.sec = atoi (tzo.str+7); + } + + /* an offset like -05:00 means that 5 hours is subtracted from GMT to */ + /* get local time. however, the -05:00 appears next to the local time, */ + /* not the GMT time. so, to get back to GMT, 5 hours would have to be */ + /* added. thus, '-' means "add offset to get GMT", and '+' means */ + /* "subtract offset to get GMT". we could use the normal meaning of */ + /* '+' and '-' and use a SubDelta call, but there is overhead to negate */ + /* the delta. instead, we negate only when '+' is used, and then call */ + /* AddDelta. it's counter-intuitive, but more efficient. */ + + if (tzo.str[0] == '+') /* yes, '+' */ + { + delta.hour = -(delta.hour); + delta.min = -(delta.min); + delta.sec = -(delta.sec); + } + + STDTIME_RET (StdTimeFields_AddDelta (pStdTimeFields, &delta)); + } + + STDTIME_RET_OK; + + } /* StdTimeStringAToStdTimeFields */ +#endif /* defined(_WIN32) */ + +/*** Get (current UTC/GMT time) functions ************************************/ + +/*-***************************************************************************/ +/* GetStdTime */ +/* get current UTC time and store in StdTime structure */ +/* method: get current UTC time as a FILETIME, then convert to StdTime */ +/*****************************************************************************/ + +STDTIME_RC GetStdTime ( + STDTIME * /*O*/ pStdTime) + { + STDTIME_WIN_FILETIME gmtFileTime; + + STDTIME_ENUM_FUNC (GetStdTime) + + if (pStdTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + STDTIME_API_GETSYSTEMTIMEASFILETIME (&gmtFileTime); + + STDTIME_RET (FileTimeToStdTime (&gmtFileTime, pStdTime)); + + } /* GetStdTime */ + + +/*** validation functions ****************************************************/ + +/*-***************************************************************************/ +/* ValidStdTimeFields */ +/* return STDTIME_OK if StdTimeFields is valid, else STDTIME_FALSE */ +/*****************************************************************************/ + +STDTIME_RC ValidStdTimeFields ( + const STDTIME_FIELDS * /*I*/ pFields) + { + STDTIME_ENUM_FUNC (ValidStdTimeFields) + + if (pFields == NULL) + { + STDTIME_RET_EC (null_argument); + } + + if (! STDTIME_IN_RANGE (pFields->year, STDTIME_YEAR_MIN, STDTIME_YEAR_MAX)) + { + STDTIME_RET_EC (invalid_year); + } + + if (! STDTIME_IN_RANGE (pFields->mon, 1, 12)) + { + STDTIME_RET_EC (invalid_mon); + } + + if (! STDTIME_IN_RANGE (pFields->day, 1, 31)) + { + STDTIME_RET_EC (invalid_day); + } + + if (! STDTIME_IN_RANGE (pFields->hour, 0, 23)) + { + STDTIME_RET_EC (invalid_hour); + } + + if (! STDTIME_IN_RANGE (pFields->min, 0, 59)) + { + STDTIME_RET_EC (invalid_min); + } + + if (! STDTIME_IN_RANGE (pFields->sec, 0, 59)) + { + STDTIME_RET_EC (invalid_sec); + } + + if (! STDTIME_IN_RANGE (pFields->msec, 0, 999)) + { + STDTIME_RET_EC (invalid_msec); + } + + if (! STDTIME_IN_RANGE (pFields->usec, 0, 999)) + { + STDTIME_RET_EC (invalid_usec); + } + + if (! STDTIME_IN_RANGE (pFields->nsec, 0, 999)) + { + STDTIME_RET_EC (invalid_nsec); + } + + /* already checked that day is 0-31, now validate per month */ + + if (pFields->day > + StdTimeDaysInYearMon (pFields->year, pFields->mon)) + { + STDTIME_RET_EC (invalid_mon); + } + + STDTIME_RET_OK; + + } /* ValidStdTimeFields */ + + +/*** AddFraction adjustment function *****************************************/ + +/*-***************************************************************************/ +/* StdTimeFields_AddFraction */ +/* a low-overhead StdTimeFields adjustment without using a delta */ +/* nMsec, nUsec and nNsec must be positive */ +/*****************************************************************************/ + +STDTIME_RC StdTimeFields_AddFraction ( + STDTIME_FIELDS * /*IO*/ pStdTimeFields, + int32_t /*I*/ nMsec, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec) + { + STDTIME_FIELDS f; + int32_t maxday; + + STDTIME_ENUM_FUNC (StdTimeFields_AddFraction) + + if (pStdTimeFields == NULL) + { + STDTIME_RET_EC (null_argument); + } + + if ((nMsec < 0) || (nUsec < 0) || (nNsec < 0)) + { + STDTIME_RET_EC (argument_out_of_range); + } + + if STDTIME_IFNOT (ValidStdTimeFields (pStdTimeFields)) + { + STDTIME_RET_RC; + } + + if ((nMsec == 0) && (nUsec == 0) && (nNsec == 0)) + { + STDTIME_RET_OK; /* nothing to do */ + } + + f.nsec = pStdTimeFields->nsec + nNsec; + pStdTimeFields->nsec = ((f.nsec / 100) * 100) % 1000; + + f.usec = pStdTimeFields->usec + (f.nsec / 1000) + nUsec; + pStdTimeFields->usec = (f.usec % 1000); + + f.msec = pStdTimeFields->msec + (f.usec / 1000) + nMsec; + pStdTimeFields->msec = (f.msec % 1000); + + f.sec = pStdTimeFields->sec + (f.msec / 1000); + pStdTimeFields->sec = (f.sec % 60); + + f.min = pStdTimeFields->min + (f.sec / 60); + pStdTimeFields->min = (f.min % 60); + + f.hour = pStdTimeFields->hour + (f.min / 60); + pStdTimeFields->hour = (f.hour % 24); + + f.day = pStdTimeFields->day + (f.hour / 24); + f.mon = pStdTimeFields->mon; + f.year = pStdTimeFields->year; + + /* adjust days using calander logic */ + + for (;;) + { + maxday = StdTimeDaysInYearMon (f.year, f.mon); + + if (f.day <= maxday) /* no (further) calendar adj needed */ + { + pStdTimeFields->mon = f.mon; + pStdTimeFields->year = f.year; + break; /* and return true */ + } + + f.day -= maxday; + f.mon++; + + if (f.mon > 12) + { + f.mon = 1; + f.year++; + + if (f.year > STDTIME_YEAR_MAX) + { + STDTIME_RET_EC (year_out_of_range); + } + } + } /* for */ + + STDTIME_RET_OK; + + } /* StdTimeFields_AddFraction */ + + +/*** AddSpan functions *******************************************************/ + + +/*-***************************************************************************/ +/* StdTime_AddSpan */ +/* use STDTIME_SPAN parm to increment value in StdTime structure */ +/*****************************************************************************/ + +STDTIME_RC StdTime_AddSpan ( + STDTIME * /*IO*/ pStdTime, + const STDTIME_SPAN * /*I*/ pSpan) + { + QUADLIB_I64 qStdTime; + + STDTIME_ENUM_FUNC (StdTime_AddSpan) + + qStdTime = *(QUADLIB_I64 *)pStdTime; + + QUADLIB_I64_ADD_EQ (qStdTime, pSpan->value); + + *pStdTime = *(STDTIME *)&qStdTime; + STDTIME_RET_OK; + } /* StdTime_AddSpan */ + + +#if defined(_WIN32) +/*-***************************************************************************/ +/* StdTimeFields_AddSpan */ +/* use STDTIME_SPAN parm to increment value in StdTimeFields structure */ +/*****************************************************************************/ + +STDTIME_RC StdTimeFields_AddSpan ( + STDTIME_FIELDS * /*IO*/ pStdTimeFields, + const STDTIME_SPAN * /*I*/ pSpan) + { + STDTIME stdTime; + + STDTIME_ENUM_FUNC (StdTimeFields_AddSpan) + + if STDTIME_IF (StdTimeFieldsToStdTime (pStdTimeFields, &stdTime)) + { + if STDTIME_IF (StdTime_AddSpan (&stdTime, pSpan)) + { + STDTIME_RET (StdTimeToStdTimeFields (&stdTime, pStdTimeFields)); + } + } + + STDTIME_RET_RC; + + } /* StdTimeFields_AddSpan */ +#endif /* defined(_WIN32) */ + + +/*** SubSpan functions *******************************************************/ + + +/*-***************************************************************************/ +/* StdTime_SubSpan */ +/* use STDTIME_SPAN parm to decrement value in StdTime structure */ +/*****************************************************************************/ + +STDTIME_RC StdTime_SubSpan ( + STDTIME * /*IO*/ pStdTime, + const STDTIME_SPAN * /*I*/ pSpan) + { + QUADLIB_I64 qStdTime; + + STDTIME_ENUM_FUNC (StdTime_SubSpan) + + qStdTime = *(QUADLIB_I64 *)pStdTime; + + QUADLIB_I64_SUB_EQ (qStdTime, pSpan->value); + + *pStdTime = *(STDTIME *)&qStdTime; + STDTIME_RET_OK; + } /* StdTime_SubSpan */ + + +/*** AddDelta functions ******************************************************/ + + +/*-***************************************************************************/ +/* StdTime_AddDelta */ +/* use STDTIME_DELTA parm to increment value in StdTime structure */ +/*****************************************************************************/ + +STDTIME_RC StdTime_AddDelta ( + STDTIME * /*IO*/ pStdTime, + const STDTIME_DELTA * /*I*/ pDelta) + { + STDTIME_SPAN span; + + STDTIME_ENUM_FUNC (StdTime_AddDelta) + + if STDTIME_IF (StdTimeDeltaToStdTimeSpan (pDelta, &span)) + { + STDTIME_RET (StdTime_AddSpan (pStdTime, &span)); + } + + STDTIME_RET_RC; + + } /* StdTime_AddDelta */ + +#if defined(_WIN32) +/*-***************************************************************************/ +/* StdTimeFields_AddDelta */ +/* use STDTIME_DELTA parm to increment value in StdTimeFields structure */ +/*****************************************************************************/ + +STDTIME_RC StdTimeFields_AddDelta ( + STDTIME_FIELDS * /*IO*/ pStdTimeFields, + const STDTIME_DELTA * /*I*/ pDelta) + { + STDTIME_SPAN span; + + STDTIME_ENUM_FUNC (StdTimeFields_AddDelta) + + if STDTIME_IF (StdTimeDeltaToStdTimeSpan (pDelta, &span)) + { + STDTIME_RET (StdTimeFields_AddSpan (pStdTimeFields, &span)); + } + + STDTIME_RET_RC; + + } /* StdTimeFields_AddDelta */ +#endif /* defined(_WIN32) */ + + +/*** SubDelta functions ******************************************************/ + + +/*-***************************************************************************/ +/* StdTime_SubDelta */ +/* use STDTIME_DELTA parm to decrement value in StdTime structure */ +/*****************************************************************************/ + +STDTIME_RC StdTime_SubDelta ( + STDTIME * /*IO*/ pStdTime, + const STDTIME_DELTA * /*I*/ pDelta) + { + STDTIME_SPAN span; + + STDTIME_ENUM_FUNC (StdTime_SubDelta) + + if STDTIME_IF (StdTimeDeltaToStdTimeSpan (pDelta, &span)) + { + STDTIME_RET (StdTime_SubSpan (pStdTime, &span)); + } + + STDTIME_RET_RC; + + } /* StdTime_SubDelta */ + + +/*** GetSpan functions *******************************************************/ + + +/*-***************************************************************************/ +/* StdTime_GetSpan */ +/* produce a STDTIME_SPAN value as the delta-t of two STDTIME values */ +/*****************************************************************************/ + + +STDTIME_RC StdTime_GetSpan ( + const STDTIME * /*I*/ pStdTimeOne, + const STDTIME * /*I*/ pStdTimeTwo, + STDTIME_SPAN * /*O*/ pSpan) + { + QUADLIB_I64 qOne; + QUADLIB_I64 qTwo; + + STDTIME_ENUM_FUNC (StdTime_GetSpan) + + qOne = *(QUADLIB_I64 *)pStdTimeOne; + qTwo = *(QUADLIB_I64 *)pStdTimeTwo; + + pSpan->value = QUADLIB_I64_SUB (qOne, qTwo); + + STDTIME_RET (ValidStdTimeSpan (pSpan)); + + } /* StdTime_GetSpan */ + + +/*** GetDelta functions ******************************************************/ + + +/*-***************************************************************************/ +/* StdTime_GetDelta */ +/* produce a STDTIME_DELTA value as the delta-t of two STDTIME values */ +/*****************************************************************************/ + +STDTIME_RC StdTime_GetDelta ( + const STDTIME * /*I*/ pStdTimeOne, + const STDTIME * /*I*/ pStdTimeTwo, + STDTIME_DELTA * /*O*/ pDelta) + { + STDTIME_SPAN span; + + STDTIME_ENUM_FUNC (StdTime_GetDelta) + + if STDTIME_IF (StdTime_GetSpan (pStdTimeOne, pStdTimeTwo, &span)) + { + STDTIME_RET (StdTimeSpanToStdTimeDelta (&span, pDelta)); + } + + STDTIME_RET_RC; + + } /* StdTime_GetDelta */ + + +/*-***************************************************************************/ +/* NormalizeStdTimeDelta */ +/* normalize a delta value to the nearest number of days */ +/* this is the same as truncating its value to the nearest day */ +/*****************************************************************************/ + + +STDTIME_RC NormalizeStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta) + { + STDTIME_ENUM_FUNC (NormalizeStdTimeDelta) + + STDTIME_RET (TruncStdTimeDelta (pDelta, STDTIME_FIELD_DAY)); + + } /* NormalizeStdTimeDelta */ + + +/*-***************************************************************************/ +/* TruncStdTimeDelta */ +/* form normalized value of delta, such that there are non-zero difference */ +/* values only as large as the selected units of the specified field. */ +/* for example, to truncate to 'hour' means that the delta value is */ +/* expressed in units no larger than hours. thus, an 'hour' value of 25 */ +/* is truncated to hours because it does not get changed to 1 day and 1 */ +/* 'hour'. fields of smaller units do not exceed the normal maximum value */ +/* for that field. for example, a value may be truncated to 25 hours, but */ +/* the 'min' field will be within the absolute value of 0 to 59, etc. */ +/* */ +/* all non-zero values in a truncated delta will have the same sign, plus */ +/* or minus, regardless of how they were originally defined. */ +/*****************************************************************************/ + +STDTIME_RC TruncStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta, + int32_t /*I*/ field) + { + QUADLIB_I64 qVal; + int32_t sign = 1; + STDTIME_SPAN span; + STDTIME_DELTA result = {0}; + + STDTIME_ENUM_FUNC (TruncStdTimeDelta) + + if (pDelta == NULL) + { + STDTIME_RET_EC (null_argument); + } + + if ((field < STDTIME_FIELD_DAY) || (field > STDTIME_FIELD_NSEC)) + { + /* field selector is invalid */ + STDTIME_RET_EC (field_selector_out_of_range); + } + + if STDTIME_IFNOT (StdTimeDeltaToStdTimeSpan (pDelta, &span)) + { + STDTIME_RET_RC; + } + + qVal = span.value; + + /* at this point, qVal has a count of 100-nanosecond intervals */ + /* and may be positive or negative */ + /* now, rebuilt the delta value with normalized quantities */ + + /***************************************************************************/ + /* nsecs - only 1 digit available, but we store as 3 digit nsec */ + /***************************************************************************/ + + if (QUADLIB_I64_LT_0 (qVal)) + { + qVal = QUADLIB_I64_NEG (qVal); + sign = -1; + } + + /* if truncating to nsec we are done */ + + if (field == STDTIME_FIELD_NSEC) + { + /* since the 100-nanosecond count must be multiplied by 100 to */ + /* get actual nanoseconds, just checking for overflow is not */ + /* enough. we must check to see if overflow WILL occur when */ + /* the multiply is done, but we have to check before we do it */ + + if ((QUADLIB_I64_HI(qVal) != 0) + || (QUADLIB_U64_LO(qVal) > (0x7FFFFFFF / STDTIME_SCALE_NSEC) )) + { + STDTIME_RET_EC (overflow_in_delta_nsec); + /* cannot hold nsec value in I32 field */ + } + + result.nsec = sign * STDTIME_SCALE_NSEC * QUADLIB_I64_LO(qVal); + *pDelta = result; + + STDTIME_RET_OK; + } + + result.nsec = + sign * STDTIME_SCALE_NSEC * QUADLIB_I32_CASTI64 ( + QUADLIB_I64_MOD (qVal, QUADLIB_I64_CASTI32 (STDTIME_PREC_NSEC)) ); + + QUADLIB_I64_DIV_EQ (qVal, QUADLIB_I64_CASTI32 (STDTIME_PREC_NSEC)); + + /***************************************************************************/ + /* qVal now has usecs */ + /***************************************************************************/ + + /* if truncating to usec we are done */ + + if (field == STDTIME_FIELD_USEC) + { + if (QUADLIB_I64_OVERFLOW_I32 (qVal)) + { + STDTIME_RET_EC (overflow_in_delta_usec); + /* cannot hold usec value in I32 field */ + } + + result.usec = sign * QUADLIB_I64_LO(qVal); + *pDelta = result; + STDTIME_RET_OK; + } + + result.usec = + sign * QUADLIB_I32_CASTI64 ( + QUADLIB_I64_MOD (qVal, QUADLIB_I64_CASTI32 (1000)) ); + + QUADLIB_I64_DIV_EQ (qVal, QUADLIB_I64_CASTI32 (1000)); /* qVal / 1000 */ + + + /***************************************************************************/ + /* qVal now has msecs */ + /***************************************************************************/ + + /* if truncating to msec we are done */ + + if (field == STDTIME_FIELD_MSEC) + { + if (QUADLIB_I64_OVERFLOW_I32 (qVal)) + { + STDTIME_RET_EC (overflow_in_delta_msec); + /* cannot hold msec value in I32 field */ + } + + result.msec = sign * QUADLIB_I64_LO(qVal); + *pDelta = result; + STDTIME_RET_OK; + } + + result.msec = + sign * QUADLIB_I32_CASTI64 ( + QUADLIB_I64_MOD (qVal, QUADLIB_I64_CASTI32 (1000)) ); + + QUADLIB_I64_DIV_EQ (qVal, QUADLIB_I64_CASTI32 (1000)); /* qVal / 1000 */ + + + /***************************************************************************/ + /* qVal now has secs */ + /***************************************************************************/ + + /* if truncating to sec we are done */ + + if (field == STDTIME_FIELD_SEC) + { + if (QUADLIB_I64_OVERFLOW_I32 (qVal)) + { + STDTIME_RET_EC (overflow_in_delta_sec); + /* cannot hold sec value in I32 field */ + } + + result.sec = sign * QUADLIB_I64_LO(qVal); + *pDelta = result; + STDTIME_RET_OK; + } + + result.sec = + sign * QUADLIB_I32_CASTI64 ( + QUADLIB_I64_MOD (qVal, QUADLIB_I64_CASTI32 (60)) ); + + QUADLIB_I64_DIV_EQ (qVal, QUADLIB_I64_CASTI32 (60)); /* qVal / 60 */ + + + /***************************************************************************/ + /* qVal now has mins */ + /***************************************************************************/ + + /* if truncating to min we are done */ + + if (field == STDTIME_FIELD_MIN) + { + if (QUADLIB_I64_OVERFLOW_I32 (qVal)) + { + STDTIME_RET_EC (overflow_in_delta_min); + /* cannot hold min value in I32 field */ + } + + result.min = sign * QUADLIB_I64_LO(qVal); + *pDelta = result; + STDTIME_RET_OK; + } + + result.min = + sign * QUADLIB_I32_CASTI64 ( + QUADLIB_I64_MOD (qVal, QUADLIB_I64_CASTI32 (60)) ); + + QUADLIB_I64_DIV_EQ (qVal, QUADLIB_I64_CASTI32 (60)); /* qVal / 60 */ + + + /***************************************************************************/ + /* qVal now has hours */ + /***************************************************************************/ + + /* if truncating to hour we are done */ + + if (field == STDTIME_FIELD_HOUR) + { + if (QUADLIB_I64_OVERFLOW_I32 (qVal)) + { + STDTIME_RET_EC (overflow_in_delta_hour); + /* cannot hold hour value in I32 field */ + } + + result.hour = sign * QUADLIB_I64_LO(qVal); + *pDelta = result; + STDTIME_RET_OK; + } + + result.hour = + sign * QUADLIB_I32_CASTI64 ( + QUADLIB_I64_MOD (qVal, QUADLIB_I64_CASTI32 (24)) ); + + QUADLIB_I64_DIV_EQ (qVal, QUADLIB_I64_CASTI32 (24)); /* qVal / 24 */ + + + /***************************************************************************/ + /* qVal now has days */ + /***************************************************************************/ + + /* months and years are not linear, so they are left as zero */ + /* field == STDTIME_FIELD_DAY must be true because of prior check */ + + if (QUADLIB_I64_OVERFLOW_I32 (qVal)) + { + STDTIME_RET_EC (overflow_in_delta_day); + /* cannot hold day value in I32 field */ + } + + result.day = sign * QUADLIB_I64_LO(qVal); + *pDelta = result; + STDTIME_RET_OK; + + } /* TruncStdTimeDelta */ + + +/*-***************************************************************************/ +/* RoundStdTimeDelta */ +/* change a delta value to a rounded form. first, truncate the delta value */ +/* using TruncStdTimeDelta above. then, based on the field, if the field */ +/* to its 'right' is greater than or equal to its maximum, the 'round' */ +/* field is incremented. */ +/* */ +/* 'greater than' and 'increment' are relative terms, because the delta */ +/* could be positive or negative; the magnitudes and signs are taken into */ +/* account. */ +/* */ +/* once the rounding occurs, the fields to the right of the rounded field */ +/* are zeroed out. in case the selected field the one to its right are */ +/* both zero, no increment occurs, but zeroing-out is still done. */ +/* */ +/* if the delta is considered invalid by TruncStdTimeDelta, no further */ +/* processing is done. */ +/* */ +/* since nanoseconds (nsec) is the right-most field, a request to round to */ +/* the nsec level is simply ignored; in effect, it is already rounded to */ +/* that level, and TruncStdTimeDelta would already have dropped digits of */ +/* nsec smaller than the 100-nanosecond precision limit anyway. */ +/* */ +/* the helper function Bool_StdTime_AbsDelta forms the absolute value of a */ +/* delta field, and returns STDTIME_TRUE if a sign conflict is found, else */ +/* STDTIME_FALSE; */ +/* */ +/*****************************************************************************/ + +static STDTIME_BOOL Bool_StdTime_AbsDelta ( + int32_t *sign, + int32_t *value) + { + int32_t newsign = 0; + + if (*value > 0) + { + newsign = 1; + } + + else if (*value < 0) + { + newsign = -1; + *value = -(*value); + } + + if ((newsign == 0) || (*sign == newsign)) + { + /* *value is zero, or its sign is the same as the 'old' sign */ + return STDTIME_FALSE; /* no sign conflict detected */ + } + + if (*sign == 0) /* sign not defined yet */ + { + *sign = newsign; + return STDTIME_FALSE; /* no sign conflict detected */ + } + + return STDTIME_TRUE; /* error: delta has conflicting signs */ + + } /* Bool_StdTime_AbsDelta */ + + +/*-***************************************************************************/ +/* RoundStdTimeDelta */ +/*****************************************************************************/ + +STDTIME_RC RoundStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta, + int32_t /*I*/ field) + { + int32_t sign = 0; + STDTIME_DELTA f; + + STDTIME_ENUM_FUNC (RoundStdTimeDelta) + + if STDTIME_IFNOT (TruncStdTimeDelta (pDelta, field)) + { + STDTIME_RET_RC; + } + + if (field == STDTIME_FIELD_NSEC) + { + /* nothing to round - OK - leave value as is */ + + STDTIME_RET_OK; + } + + /* analyze sign of delta fields, and form absolute value of delta */ + + f = *pDelta; /* local copy */ + + if ( (Bool_StdTime_AbsDelta (&sign, &f.day )) + || (Bool_StdTime_AbsDelta (&sign, &f.hour)) + || (Bool_StdTime_AbsDelta (&sign, &f.min )) + || (Bool_StdTime_AbsDelta (&sign, &f.sec )) + || (Bool_StdTime_AbsDelta (&sign, &f.msec)) + || (Bool_StdTime_AbsDelta (&sign, &f.usec)) + || (Bool_StdTime_AbsDelta (&sign, &f.nsec)) ) + { + STDTIME_RET_EC (conflicting_sign_delta); + } + + /* rounding a field means to increment it if the field to its */ + /* 'right' is >= half the (max+1) value for it */ + + /* whether rounds occurs or not, the fields to the right are */ + /* zeroed out to maintain a numerically valid delta value */ + /* to the requested precision of the field being rounded */ + + switch (field) + { + case STDTIME_FIELD_DAY: + if (f.hour >= 12) + { + f.day++; + } + + f.hour = f.min = f.sec = f.msec = f.usec = f.nsec = 0; + break; + + case STDTIME_FIELD_HOUR: + if (f.min >= 30) + { + f.hour++; + } + + f.min = f.sec = f.msec = f.usec = f.nsec = 0; + break; + + case STDTIME_FIELD_MIN: + if (f.sec >= 30) + { + f.min++; + } + + f.sec = f.msec = f.usec = f.nsec = 0; + break; + + case STDTIME_FIELD_SEC: + if (f.msec >= 500) + { + f.sec++; + } + + f.msec = f.usec = f.nsec = 0; + break; + + case STDTIME_FIELD_MSEC: + if (f.usec >= 500) + { + f.msec++; + } + + f.usec = f.nsec = 0; + break; + + case STDTIME_FIELD_USEC: + if (f.nsec >= 500) + { + f.usec++; + } + + f.nsec = 0; + break; + + default: + STDTIME_RET_EC (unexpected_condition); /* should not occur */ + + } /* switch (field) */ + + /* copy back to pDelta parameter, with correct sign */ + + pDelta->day = sign * f.day; + pDelta->hour = sign * f.hour; + pDelta->min = sign * f.min; + pDelta->sec = sign * f.sec; + pDelta->msec = sign * f.msec; + pDelta->usec = sign * f.usec; + pDelta->nsec = sign * f.nsec; + + STDTIME_RET_OK; + + } /* RoundStdTimeDelta */ + + +/*** Delta/Span conversion functions *****************************************/ + + +/*-***************************************************************************/ +/* StdTimeDeltaToStdTimeSpan */ +/* convert a StdTimeDelta to a StdTimeSPan value */ +/* if the resultant value exceeds the maximum range for a span, return */ +/* STDTIME_FALSE. the value range is about +/- 8400 years, in terms of */ +/* 100-nanosecond intervals. */ +/*****************************************************************************/ + + +STDTIME_RC StdTimeDeltaToStdTimeSpan ( + const STDTIME_DELTA * /*I*/ pDelta, + STDTIME_SPAN * /*O*/ pSpan) + { + QUADLIB_I64 qSum; + QUADLIB_I64 qTest; + + STDTIME_ENUM_FUNC (StdTimeDeltaToStdTimeSpan) + + if ((pDelta == NULL) || (pSpan == NULL)) + { + STDTIME_RET_EC (null_argument); + } + + /* accumulate field values, and convert to nanoseconds */ + + /* qSum = day */ + qSum = QUADLIB_I64_CASTI32 (pDelta->day); + + /* qSum (day) *= 24 -> (hour)_*/ + QUADLIB_I64_MUL_EQ (qSum, QUADLIB_I64_CASTI32 (24)); + + /* qSum += hour */ + QUADLIB_I64_ADD_EQ (qSum, QUADLIB_I64_CASTI32 (pDelta->hour)); + + /* qSum (hour) *= 60 -> (min) */ + QUADLIB_I64_MUL_EQ (qSum, QUADLIB_I64_CASTI32 (60)); + + /* qSum += min */ + QUADLIB_I64_ADD_EQ (qSum, QUADLIB_I64_CASTI32 (pDelta->min)); + + /* qSum (min) *= 60 -> (sec) */ + QUADLIB_I64_MUL_EQ (qSum, QUADLIB_I64_CASTI32 (60)); + + /* qSum += sec */ + QUADLIB_I64_ADD_EQ (qSum, QUADLIB_I64_CASTI32 (pDelta->sec)); + + /* qSum (sec) *= 1000 -> (msec) */ + QUADLIB_I64_MUL_EQ (qSum, QUADLIB_I64_CASTI32 (1000)); + + /* qSum += msec */ + QUADLIB_I64_ADD_EQ (qSum, QUADLIB_I64_CASTI32 (pDelta->msec)); + + /* qSum (msec) *= 1000 -> (usec) */ + QUADLIB_I64_MUL_EQ (qSum, QUADLIB_I64_CASTI32 (1000)); + + /* qSum += usec */ + QUADLIB_I64_ADD_EQ (qSum, QUADLIB_I64_CASTI32 (pDelta->usec)); + + /* qSum (usec) *= 10 -> (nsec/100) */ + QUADLIB_I64_MUL10_EQ (qSum); + + /* qSum += nsec/100 */ + QUADLIB_I64_ADD_EQ (qSum, QUADLIB_I64_CASTI32 ((pDelta->nsec) / 100)); + + pSpan->value = qSum; + + if (QUADLIB_I64_LT_0 (qSum)) + { + /* create negative test value and see if value is less than it */ + QUADLIB_U64_HI (qTest) = STDTIME_SPAN_MIN_HI; + QUADLIB_U64_LO (qTest) = STDTIME_SPAN_MIN_LO; + + if (QUADLIB_I64_LT (qSum, qTest)) /* qSum < qTest */ + { + STDTIME_RET_EC (span_out_of_range); + } + } + + else /* qSum >= 0 */ + { + /* create positive test value and see if value is less than it */ + QUADLIB_U64_HI (qTest) = STDTIME_SPAN_MAX_HI; + QUADLIB_U64_LO (qTest) = STDTIME_SPAN_MAX_LO; + + if (QUADLIB_I64_GT (qSum, qTest)) /* qSum > qTest */ + { + STDTIME_RET_EC (span_out_of_range); + } + } + + STDTIME_RET_OK; + + } /* StdTimeDeltaToStdTimeSpan */ + + +/*-***************************************************************************/ +/* StdTimeSpanToStdTimeDelta */ +/* convert a StdTimeSpan to a StdTimeDelta value */ +/* if the resultant day value exceeds the maximum range for a day, return */ +/* STDTIME_FALSE. the value range 8400 years * 366 days, just to keep */ +/* the definition simple. */ +/*****************************************************************************/ + +STDTIME_RC StdTimeSpanToStdTimeDelta ( + const STDTIME_SPAN * /*I*/ pSpan, + STDTIME_DELTA * /*O*/ pDelta) + { + QUADLIB_U64 uVal; + QUADLIB_U64 uMod; + QUADLIB_U64 uDiv; + + int32_t sign = 1; + + STDTIME_ENUM_FUNC (StdTimeSpanToStdTimeDelta) + + if ((pSpan == NULL) || (pDelta == NULL)) + { + STDTIME_RET_EC (null_argument); + } + + if (QUADLIB_I64_LT_0 (pSpan->value)) + { + uVal = QUADLIB_I64_NEG (pSpan->value); + sign = -1; + } + + else + { + uVal = pSpan->value; + } + + /* uVal has count of 100 nsecs intervals */ + /* calculate: nsec = (uVal % 10) * 100; */ + + QUADLIB_U64_HI (uDiv) = 0; + QUADLIB_U64_LO (uDiv) = 10; + uVal = QuadLibU64DivMod (uVal, uDiv, &uMod); + pDelta->nsec = sign * QUADLIB_I64_LO (uMod) * 100; + + /* uVal has usecs */ + /* calculate: usec = uVal % 1000; */ + + QUADLIB_U64_LO (uDiv) = 1000; + uVal = QuadLibU64DivMod (uVal, uDiv, &uMod); + pDelta->usec = sign * QUADLIB_I64_LO (uMod); + + /* uVal has msecs */ + /* calculate: wMilliseconds = uVal % 1000; */ + /* QUADLIB_U64_LO (uDiv) = 1000; ==> still in effect */ + + uVal = QuadLibU64DivMod (uVal, uDiv, &uMod); + pDelta->msec = sign * QUADLIB_U64_LO (uMod); + + /* uVal has secs */ + /* calculate: wSecond = uVal % 60; */ + + QUADLIB_U64_LO (uDiv) = 60; + uVal = QuadLibU64DivMod (uVal, uDiv, &uMod); + pDelta->sec = sign * QUADLIB_U64_LO (uMod); + + /* uVal has mins */ + /* calculate: wMinute = uVal % 60; */ + /* QUADLIB_U64_LO (uDiv) = 60; ==> still in effect */ + + uVal = QuadLibU64DivMod (uVal, uDiv, &uMod); + pDelta->min = sign * QUADLIB_U64_LO(uMod); + + /* uVal has hours */ + /* calculate: wHour = uVal % 24; */ + + QUADLIB_U64_LO (uDiv) = 24; + uVal = QuadLibU64DivMod (uVal, uDiv, &uMod); + + pDelta->hour = sign * QUADLIB_U64_LO (uMod); + + /* uVal has days */ + + pDelta->day = sign * QUADLIB_I64_LO (uVal); + + if (QUADLIB_I64_OVERFLOW_I32 (uVal)) + { + STDTIME_RET_EC (overflow_in_delta_day); + } + + /* we check the positive value for valid range, so that +/- cases */ + /* are both covered in one test */ + + if (QUADLIB_I64_LO (uVal) > STDTIME_DELTA_DAY_MAX) + { + STDTIME_RET_EC (overflow_in_delta_day); + } + + STDTIME_RET_OK; + + } /* StdTimeSpanToStdTimeDelta */ + + +/*** validation of delta and span ********************************************/ + + +/*-***************************************************************************/ +/* ValidStdTimeDelta */ +/* validate delta by converting to a span and discard the result */ +/*****************************************************************************/ + +STDTIME_RC ValidStdTimeDelta ( + const STDTIME_DELTA * /*I*/ pDelta) + { + STDTIME_SPAN span; + + STDTIME_ENUM_FUNC (ValidStdTimeDelta) + + STDTIME_RET (StdTimeDeltaToStdTimeSpan (pDelta, &span)); + + } /* ValidStdTimeDelta */ + + +/*-***************************************************************************/ +/* ValidStdTimeSpan */ +/* validate span by converting to a delta and discard the result */ +/*****************************************************************************/ + +STDTIME_RC ValidStdTimeSpan ( + const STDTIME_SPAN * /*I*/ pSpan) + { + STDTIME_DELTA delta; + + STDTIME_ENUM_FUNC (ValidStdTimeSpan) + + STDTIME_RET (StdTimeSpanToStdTimeDelta (pSpan, &delta)); + + } /* ValidStdTimeSpan */ + + +/*** Delta/Span sign-related functions ***************************************/ + + +/*-***************************************************************************/ +/* SgnStdTimeDelta */ +/* characterize the sign of a delta as -1, 0 or +1 */ +/*****************************************************************************/ + +int32_t SgnStdTimeDelta ( + const STDTIME_DELTA * /*I*/ pDelta) + { + STDTIME_SPAN span; + + if (pDelta == NULL) + { + return STDTIME_ERR; + } + + /* test for a normal sign first */ + + if ((pDelta->day == 0) + && (pDelta->hour == 0) + && (pDelta->min == 0) + && (pDelta->sec == 0) + && (pDelta->msec == 0) + && (pDelta->usec == 0) + && (pDelta->nsec == 0)) + { + return STDTIME_EQ; /* == 0 */ + } + + if ((pDelta->day >= 0) + && (pDelta->hour >= 0) + && (pDelta->min >= 0) + && (pDelta->sec >= 0) + && (pDelta->msec >= 0) + && (pDelta->usec >= 0) + && (pDelta->nsec >= 0)) + { + return STDTIME_GT; /* > 0 (not >= 0, because 0 already checked for) */ + } + + if ((pDelta->day <= 0) + && (pDelta->hour <= 0) + && (pDelta->min <= 0) + && (pDelta->sec <= 0) + && (pDelta->msec <= 0) + && (pDelta->usec <= 0) + && (pDelta->nsec <= 0)) + { + return STDTIME_LT; /* < 0 (not <= 0, because 0 already checked for) */ + } + + /* delta has a complex sign. convert to a span, and report its sign */ + + if (StdTimeDeltaToStdTimeSpan (pDelta, &span) == STDTIME_OK) + { + return SgnStdTimeSpan (&span); + } + + return STDTIME_ERR; + + } /* SgnStdTimeDelta */ + + +/*-***************************************************************************/ +/* AbsStdTimeDelta */ +/* form absolute value of a delta; depends on its sign */ +/*****************************************************************************/ + +STDTIME_RC AbsStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta) + { + int32_t sign; + + STDTIME_ENUM_FUNC (AbsStdTimeDelta) + + sign = SgnStdTimeDelta (pDelta); /* handles NULL argument */ + + if (sign == STDTIME_ERR) + { + STDTIME_RET_EC (failure_in_api_SgnStdTimeDelta); + } + + if (sign == STDTIME_LT) + { + STDTIME_RET (NegStdTimeDelta (pDelta)); + } + + STDTIME_RET_OK; + + } /* AbsStdTimeDelta */ + + +/*-***************************************************************************/ +/* NegStdTimeDelta */ +/* form negative value of a delta; negates each element */ +/*****************************************************************************/ + +STDTIME_RC NegStdTimeDelta ( + STDTIME_DELTA * /*IO*/ pDelta) + { + STDTIME_ENUM_FUNC (NegStdTimeDelta) + + if (pDelta == NULL) + { + STDTIME_RET_EC (null_argument); + } + + pDelta->day = -(pDelta->day); + pDelta->hour = -(pDelta->hour); + pDelta->min = -(pDelta->min); + pDelta->sec = -(pDelta->sec); + pDelta->msec = -(pDelta->msec); + pDelta->usec = -(pDelta->usec); + pDelta->nsec = -(pDelta->nsec); + + STDTIME_RET_OK; + + } /* NegStdTimeDelta */ + + +/*-***************************************************************************/ +/* SgnStdTimeSpan */ +/* characterize the sign of a span as -1, 0 or +1 */ +/*****************************************************************************/ + +int32_t SgnStdTimeSpan ( + const STDTIME_SPAN * /*I*/ pSpan) + { + if (pSpan == NULL) + { + return STDTIME_ERR; + } + + if (QUADLIB_I64_LT_0 (pSpan->value)) + { + return STDTIME_LT; + } + + if (QUADLIB_I64_EQ_0 (pSpan->value)) + { + return STDTIME_EQ; + } + + return STDTIME_GT; + } /* SgnStdTimeSpan */ + + +/*-***************************************************************************/ +/* AbsStdTimeSpan */ +/* form absolute value of a span, via call to QUADLIB function */ +/*****************************************************************************/ + +STDTIME_RC AbsStdTimeSpan ( + STDTIME_SPAN * /*IO*/ pSpan) + { + STDTIME_ENUM_FUNC (AbsStdTimeSpan) + + if (pSpan == NULL) + { + STDTIME_RET_EC (null_argument); + } + + pSpan->value = QUADLIB_I64_ABS (pSpan->value); + + STDTIME_RET_OK; + + } /* AbsStdTimeSpan */ + + +/*-***************************************************************************/ +/* NegStdTimeSpan */ +/* form negative value of a span, via call to QUADLIB function */ +/*****************************************************************************/ + +STDTIME_RC NegStdTimeSpan ( + STDTIME_SPAN * /*IO*/ pSpan) + { + STDTIME_ENUM_FUNC (NegStdTimeSpan) + + if (pSpan == NULL) + { + STDTIME_RET_EC (null_argument); + } + + pSpan->value = QUADLIB_I64_NEG (pSpan->value); + + STDTIME_RET_OK; + + } /* NegStdTimeSpan */ + + +/*** Compare functions *******************************************************/ + + +/*-***************************************************************************/ +/* CompareStdTime */ +/* compare two STDTIME values and return a strcmp-like result */ +/*****************************************************************************/ + +int32_t CompareStdTime ( + const STDTIME * /*I*/ pOne, + const STDTIME * /*I*/ pTwo) + { + if ((pOne == NULL) || (pTwo == NULL)) + { + return STDTIME_ERR; + } + + PVT_STDTIME_COMPARE(dwHighDateTime); + PVT_STDTIME_COMPARE(dwLowDateTime); + + return STDTIME_EQ; + + } /* CompareStdTime */ + +/*-***************************************************************************/ +/* CompareStdTimeFields */ +/* compare two STDTIME_FIELDS values and return a strcmp-like result */ +/*****************************************************************************/ + +int32_t CompareStdTimeFields ( + const STDTIME_FIELDS * /*I*/ pOne, + const STDTIME_FIELDS * /*I*/ pTwo) + { + if ((pOne == NULL) || (pTwo == NULL)) + { + return STDTIME_ERR; + } + + PVT_STDTIME_COMPARE(year); + PVT_STDTIME_COMPARE(mon ); + PVT_STDTIME_COMPARE(day ); + PVT_STDTIME_COMPARE(hour); + PVT_STDTIME_COMPARE(min ); + PVT_STDTIME_COMPARE(sec ); + PVT_STDTIME_COMPARE(msec); + PVT_STDTIME_COMPARE(usec); + PVT_STDTIME_COMPARE(nsec); + + return STDTIME_EQ; + + } /* CompareStdTimeFields */ + + +/*** FileTime functions ******************************************************/ + + +/*-***************************************************************************/ +/* StdTimeToFileTime */ +/* convert: StdTime structure to FILETIME structure */ +/*****************************************************************************/ + +STDTIME_RC StdTimeToFileTime ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_FILETIME * /*O*/ pFileTime) + { + STDTIME_ENUM_FUNC (StdTimeToFileTime) + + if (pFileTime == NULL || pStdTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + /* Structures are now identical, so just copy. */ + *pFileTime = *pStdTime; /* faster than memcpy */ + STDTIME_RET_OK; + + } /* StdTimeToFileTime */ + + +/*-***************************************************************************/ +/* FileTimeToStdTime */ +/* convert: FILETIME structure to StdTime structure */ +/*****************************************************************************/ + +STDTIME_RC FileTimeToStdTime ( + const STDTIME_WIN_FILETIME * /*I*/ pFileTime, + STDTIME * /*O*/ pStdTime) + { + STDTIME_ENUM_FUNC (FileTimeToStdTime) + + if (pFileTime == NULL || pStdTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + /* Structures are now identical, so just copy. */ + *pStdTime = *pFileTime; /* faster than memcpy */ + STDTIME_RET_OK; + + } /* FileTimeToStdTime */ + + +#if defined(_WIN32) +/*-***************************************************************************/ +/* StdTimeFieldsToFileTime */ +/* convert: StdTimeFields structure to FILETIME structure */ +/*****************************************************************************/ + +STDTIME_RC StdTimeFieldsToFileTime ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_FILETIME * /*O*/ pFileTime) + { + STDTIME_WIN_SYSTEMTIME st; + STDTIME_WIN_FILETIME ft; + QUADLIB_U64 qFileTime; + int32_t omit = 0; + uint32_t incr32; + + STDTIME_ENUM_FUNC (StdTimeFieldsToFileTime) + + if (pFileTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pFileTime = StdTimeApiZeroFileTime(); + + if (pStdTimeFields == NULL) + { + STDTIME_RET_EC (null_argument); + } + + /* the 'omit' argument is like NULL, but suppressing rounding */ + + if STDTIME_IFNOT (StdTimeFieldsToSystemTimeEx ( + pStdTimeFields, &st, &omit, &omit)) + { + STDTIME_RET_RC; + } + + if (! STDTIME_API_SYSTEMTIMETOFILETIME (&st, &ft)) + { + STDTIME_RET_EC (failure_in_api_SystemTimeToFileTime); + } + + /* SYSTEMTIME does not have usec and nsec, so add them to FILETIME */ + + QUADLIB_U64_HI (qFileTime) = ft.dwHighDateTime; + QUADLIB_U64_LO (qFileTime) = ft.dwLowDateTime; + + incr32 = (uint32_t) (pStdTimeFields->usec * STDTIME_PREC_NSEC) + + (uint32_t) (pStdTimeFields->nsec / STDTIME_SCALE_NSEC); + + QUADLIB_U64_ADD_EQ (qFileTime, QUADLIB_U64_CASTU32 (incr32)); + + pFileTime->dwHighDateTime = QUADLIB_U64_HI (qFileTime); + pFileTime->dwLowDateTime = QUADLIB_U64_LO (qFileTime); + + STDTIME_RET_OK; + + } /* StdTimeFieldsToFileTime */ + +/*-***************************************************************************/ +/* FileTimeToStdTimeFields */ +/* convert: FILETIME structure to StdTimeFields structure */ +/*****************************************************************************/ + +STDTIME_RC FileTimeToStdTimeFields ( + const STDTIME_WIN_FILETIME * /*I*/ pFileTime, + STDTIME_FIELDS * /*O*/ pStdTimeFields) + { + STDTIME_WIN_SYSTEMTIME st; + int32_t usec; + int32_t nsec; + + STDTIME_ENUM_FUNC (FileTimeToStdTimeFields) + + if (pStdTimeFields == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pStdTimeFields = ZeroStdTimeFields (); + + if (pFileTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + if STDTIME_IFNOT (Rc_StdTime_FileTimeToSystemTimeEx ( + pFileTime, &st, &usec, &nsec)) + { + STDTIME_RET_RC; + } + + STDTIME_RET (SystemTimeExToStdTimeFields (&st, usec, nsec, pStdTimeFields)); + + } /* FileTimeToStdTimeFields */ +#endif /* defined(_WIN32) */ + + +/*** SystemTimeEx functions **************************************************/ + +/*-***************************************************************************/ +/* StdTimeToSystemTimeEx */ +/* convert: StdTime structure to SYSTEMTIME and extra fields */ +/* method: StdTime -> FILETIME -> StdTimeFields */ +/*****************************************************************************/ + +STDTIME_RC StdTimeToSystemTimeEx ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime, + int32_t * /*O*/ pUsec, + int32_t * /*O*/ pNsec) + { + STDTIME_WIN_FILETIME ft; + + STDTIME_ENUM_FUNC (StdTimeToSystemTimeEx) + + if (pSystemTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pSystemTime = StdTimeApiZeroSystemTime(); + + if STDTIME_IF (StdTimeToFileTime (pStdTime, &ft)) + { + STDTIME_RET (Rc_StdTime_FileTimeToSystemTimeEx ( + &ft, pSystemTime, pUsec, pNsec)); + } + + STDTIME_RET_RC; + + } /* StdTimeToSystemTimeEx */ + +/*-***************************************************************************/ +/* SystemTimeExToStdTime */ +/* convert: SYSTEMTIME and extra fields to StdTime structure */ +/* method: SYSTEMTIME, fields -> FILETIME -> StdTime */ +/*****************************************************************************/ + +STDTIME_RC SystemTimeExToStdTime ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec, + STDTIME * /*O*/ pStdTime) + { + STDTIME_WIN_FILETIME ft; + + STDTIME_ENUM_FUNC (SystemTimeExToStdTime) + + if (pStdTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pStdTime = ZeroStdTime (); + + if STDTIME_IF (Rc_StdTime_SystemTimeExToFileTime ( + pSystemTime, nUsec, nNsec, &ft)) + { + STDTIME_RET (FileTimeToStdTime (&ft, pStdTime)); + } + + STDTIME_RET_RC; + + } /* SystemTimeExToStdTime */ + +#if defined(_WIN32) +/*-***************************************************************************/ +/* StdTimeFieldsToSystemTimeEx */ +/* convert: StdTimeFields structure to SYSTEMTIME and extra fields */ +/*****************************************************************************/ + +STDTIME_RC StdTimeFieldsToSystemTimeEx ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime, + int32_t * /*O*/ pUsec, /* optional */ + int32_t * /*O*/ pNsec) /* optional */ + { + int32_t wday; + int32_t msec; + int32_t usec; + int32_t nsec; + + STDTIME_ENUM_FUNC (StdTimeFieldsToSystemTimeEx) + + if (pSystemTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pSystemTime = StdTimeApiZeroSystemTime(); + + if (pStdTimeFields == NULL) + { + STDTIME_RET_EC (null_argument); + } + + if STDTIME_IFNOT (ValidStdTimeFields (pStdTimeFields)) + { + STDTIME_RET_RC; + } + + pSystemTime->wYear = (STDTIME_WIN_WORD) pStdTimeFields->year; + pSystemTime->wMonth = (STDTIME_WIN_WORD) pStdTimeFields->mon; + pSystemTime->wDay = (STDTIME_WIN_WORD) pStdTimeFields->day; + pSystemTime->wHour = (STDTIME_WIN_WORD) pStdTimeFields->hour; + pSystemTime->wMinute = (STDTIME_WIN_WORD) pStdTimeFields->min; + pSystemTime->wSecond = (STDTIME_WIN_WORD) pStdTimeFields->sec; + + nsec = pStdTimeFields->nsec; + usec = pStdTimeFields->usec; + msec = pStdTimeFields->msec; + + /* If pointers not NULL, copy values there. */ + if (pNsec) + *pNsec = nsec; + if (pUsec) + *pUsec = usec; + + pSystemTime->wMilliseconds = (STDTIME_WIN_WORD) msec; + +#if 0 /* OBSOLETE: delete next release */ + Rc_StdTime_NormalizeSystemTimeEx (pSystemTime, pNsec, pUsec); +#endif + + /* generate wDayOfWeek value */ + + /* a conversion to FILETIME and back to SYSTEM could do this */ + /* but that is a lot of overhead for one field */ + /* the 'yday' value, stored in a struct tm, is not contained in */ + /* a SYSTEMTIME struct, so we discard its value with the NULL parm */ + + if STDTIME_IFNOT (StdTimeW32GetDayofWeekAndYear ( + pStdTimeFields->year, + pStdTimeFields->mon, + pStdTimeFields->day, + &wday, NULL)) + { + STDTIME_RET_EC (failure_in_api_StdTimeW32GetDayofWeekAndYear); + } + + pSystemTime->wDayOfWeek = (STDTIME_WIN_WORD) wday; + + STDTIME_RET_OK; + + } /* StdTimeFieldsToSystemTimeEx */ + +/*-***************************************************************************/ +/* SystemTimeExToStdTimeFields */ +/* convert: SYSTEMTIME and extra fields to StdTimeFields structure */ +/*****************************************************************************/ + +STDTIME_RC SystemTimeExToStdTimeFields ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec, + STDTIME_FIELDS * /*O*/ pStdTimeFields) + { + STDTIME_ENUM_FUNC (SystemTimeExToStdTimeFields) + + if (pStdTimeFields == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pStdTimeFields = ZeroStdTimeFields (); + + if (pSystemTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + pStdTimeFields->year = pSystemTime->wYear; + pStdTimeFields->mon = pSystemTime->wMonth; + pStdTimeFields->day = pSystemTime->wDay; + + pStdTimeFields->hour = pSystemTime->wHour; + pStdTimeFields->min = pSystemTime->wMinute; + pStdTimeFields->sec = pSystemTime->wSecond; + + pStdTimeFields->msec = pSystemTime->wMilliseconds; + pStdTimeFields->usec = 0; + pStdTimeFields->nsec = 0; + + STDTIME_RET (StdTimeFields_AddFraction (pStdTimeFields, 0, nUsec, nNsec)); + + } /* SystemTimeExToStdTimeFields */ +#endif /* defined(_WIN32) */ + + +/*** SystemTime functions ****************************************************/ + +/*-***************************************************************************/ +/* StdTimeToSystemTime */ +/* convert: StdTime structure to SYSTEMTIME (without extra fields) */ +/*****************************************************************************/ + +STDTIME_RC StdTimeToSystemTime ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime) + { + STDTIME_ENUM_FUNC (StdTimeToSystemTime) + + STDTIME_RET (StdTimeToSystemTimeEx (pStdTime, pSystemTime, NULL, NULL)); + + } /* StdTimeToSystemTime */ + +/*-***************************************************************************/ +/* SystemTimeToStdTime */ +/* convert: SYSTEMTIME (without extra fields) to StdTime structure */ +/*****************************************************************************/ + +STDTIME_RC SystemTimeToStdTime ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + STDTIME * /*O*/ pStdTime) + { + STDTIME_ENUM_FUNC (SystemTimeToStdTime) + + STDTIME_RET (SystemTimeExToStdTime (pSystemTime, 0, 0, pStdTime)); + + } /* SystemTimeToStdTime */ + + +#ifdef _WIN32 /* DbTimeStamp functions only for _WIN32 */ +/*** DbTimeStamp functions ***************************************************/ + +/*-***************************************************************************/ +/* StdTimeApiZeroDbTimeStamp */ +/* return a zero value of type STDTIME_WIN_DBTIMESTAMP */ +/*****************************************************************************/ + +STDTIME_WIN_DBTIMESTAMP StdTimeApiZeroDbTimeStamp () + { + STDTIME_WIN_DBTIMESTAMP zero = {0}; + + return zero; + + } /* StdTimeApiZeroDbTimeStamp */ + + +/*-***************************************************************************/ +/* StdTimeToDbTimeStamp */ +/* convert: StdTime structure to DBTIMESTAMP */ +/*****************************************************************************/ + +STDTIME_RC StdTimeToDbTimeStamp ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_DBTIMESTAMP * /*O*/ pDbTimeStamp) + { + STDTIME_FIELDS stdTimeFields; + + STDTIME_ENUM_FUNC (StdTimeToDbTimeStamp) + + if (pDbTimeStamp == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pDbTimeStamp = StdTimeApiZeroDbTimeStamp(); + + if STDTIME_IF (StdTimeToStdTimeFields (pStdTime, &stdTimeFields)) + { + STDTIME_RET (StdTimeFieldsToDbTimeStamp (&stdTimeFields, pDbTimeStamp)); + } + + STDTIME_RET_RC; + + } /* StdTimeToDbTimeStamp */ + + +/*-***************************************************************************/ +/* DbTimeStampToStdTime */ +/* convert: DBTIMESTAMP to StdTime structure */ +/*****************************************************************************/ + +STDTIME_RC DbTimeStampToStdTime ( + const STDTIME_WIN_DBTIMESTAMP * /*I*/ pDbTimeStamp, + STDTIME * /*O*/ pStdTime) + { + STDTIME_FIELDS stdTimeFields; + + STDTIME_ENUM_FUNC (DbTimeStampToStdTime) + + if (pStdTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pStdTime = ZeroStdTime (); + + if STDTIME_IF (DbTimeStampToStdTimeFields (pDbTimeStamp, &stdTimeFields)) + { + STDTIME_RET (StdTimeFieldsToStdTime (&stdTimeFields, pStdTime)); + } + + STDTIME_RET_RC; + + } /* DbTimeStampToStdTime */ + + +/*-***************************************************************************/ +/* StdTimeFieldsToDbTimeStamp */ +/* convert: StdTimeFields structure to DBTIMESTAMP */ +/*****************************************************************************/ + +STDTIME_RC StdTimeFieldsToDbTimeStamp ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_DBTIMESTAMP * /*O*/ pDbTimeStamp) + { + STDTIME_ENUM_FUNC (StdTimeFieldsToDbTimeStamp) + + if (pDbTimeStamp == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pDbTimeStamp = StdTimeApiZeroDbTimeStamp(); + + if (pStdTimeFields == NULL) + { + STDTIME_RET_EC (null_argument); + } + + if STDTIME_IFNOT (ValidStdTimeFields (pStdTimeFields)) + { + STDTIME_RET_RC; + } + + pDbTimeStamp->year = (STDTIME_WIN_SHORT) pStdTimeFields->year; + pDbTimeStamp->month = (STDTIME_WIN_USHORT) pStdTimeFields->mon; + pDbTimeStamp->day = (STDTIME_WIN_USHORT) pStdTimeFields->day; + pDbTimeStamp->hour = (STDTIME_WIN_USHORT) pStdTimeFields->hour; + pDbTimeStamp->minute = (STDTIME_WIN_USHORT) pStdTimeFields->min; + pDbTimeStamp->second = (STDTIME_WIN_USHORT) pStdTimeFields->sec; + + /* a DBTIMESTAMP fraction is a number of nanoseconds, 0 to 999,999,999 */ + + pDbTimeStamp->fraction = (STDTIME_WIN_ULONG) + (pStdTimeFields->msec * 1000000) + + (pStdTimeFields->usec * 1000) + + (pStdTimeFields->nsec); + + STDTIME_RET_OK; + + } /* StdTimeFieldsToDbTimeStamp */ + + +/*-***************************************************************************/ +/* DbTimeStampToStdTimeFields */ +/* convert: DBTIMESTAMP to StdTimeFields structure */ +/*****************************************************************************/ + +STDTIME_RC DbTimeStampToStdTimeFields ( + const STDTIME_WIN_DBTIMESTAMP * /*I*/ pDbTimeStamp, + STDTIME_FIELDS * /*O*/ pStdTimeFields) + { + int32_t fraction; + + STDTIME_ENUM_FUNC (DbTimeStampToStdTimeFields) + + if (pStdTimeFields == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pStdTimeFields = ZeroStdTimeFields (); + + if (pDbTimeStamp == NULL) + { + STDTIME_RET_EC (null_argument); + } + + pStdTimeFields->year = (int32_t) pDbTimeStamp->year; + pStdTimeFields->mon = (int32_t) pDbTimeStamp->month; + pStdTimeFields->day = (int32_t) pDbTimeStamp->day; + + pStdTimeFields->hour = (int32_t) pDbTimeStamp->hour; + pStdTimeFields->min = (int32_t) pDbTimeStamp->minute; + pStdTimeFields->sec = (int32_t) pDbTimeStamp->second; + + fraction = (int32_t) pDbTimeStamp->fraction; + + /* limit fraction to valid range */ + + if (fraction < 0) + { + fraction = 0; + } + + else if (fraction > 999999999) + { + fraction = 999999999; + } + + pStdTimeFields->msec = (fraction / 1000000) % 1000; + pStdTimeFields->usec = (fraction / 1000) % 1000; + pStdTimeFields->nsec = (fraction % 1000); + + STDTIME_RET_OK; + + } /* DbTimeStampToStdTimeFields */ +#endif /* DbTimeStamp functions only for _WIN32 */ + + +/*** StructTmEx functions ****************************************************/ + +/*-***************************************************************************/ +/* StdTimeToStructTmEx */ +/* convert: StdTime structure to 'struct tm' and extra fields */ +/*****************************************************************************/ + +STDTIME_RC StdTimeToStructTmEx ( + const STDTIME * /*I*/ pStdTime, + struct tm * /*O*/ pStructTm, + int32_t * /*O*/ pNsec) /* optional */ + { + time_t timet; + int32_t nsec; + + STDTIME_ENUM_FUNC (StdTimeToStructTmEx) + + rc = StdTimeToTimeTypeEx (pStdTime, &timet, &nsec); + if (rc == STDTIME_OK) + { + if (Bool_StdTimeGmTimeR (&timet, pStructTm) != STDTIME_TRUE) + STDTIME_RET_EC (argument_out_of_range); + } + if (pNsec) + *pNsec = nsec; + STDTIME_RET_RC; + + } /* StdTimeToStructTmEx */ + +/*-***************************************************************************/ +/* StructTmExToStdTime */ +/* convert: 'struct tm' and extra fields to StdTime structure */ +/*****************************************************************************/ + +STDTIME_RC StructTmExToStdTime ( + const struct tm * /*I*/ pStructTm, + int32_t /*I*/ nNsec, + STDTIME * /*O*/ pStdTime) + { + time_t timet; + + STDTIME_ENUM_FUNC (StructTmExToStdTime) + + /* usr_mkgmtime doesn't accept const arg so must cast first. */ + if ((timet = usr_mkgmtime ((struct tm *) pStructTm)) < 0) + { + STDTIME_RET_EC (argument_out_of_range); + } + STDTIME_RET (TimeTypeExToStdTime (timet, nNsec, pStdTime)); + + } /* StructTmExToStdTime */ + + +/*** TimeTypeEx functions ************************************************ */ + +/************************************************************************/ +/* StdTimeToTimeTypeEx */ +/* convert: StdTime struct to time_t plus nanoseconds */ +/************************************************************************/ +STDTIME_RC StdTimeToTimeTypeEx ( + const STDTIME * /*I*/ pStdTime, + time_t * /*O*/ pTimeT, + int32_t * /*O*/ pNsec) + { + QUADLIB_U64 qFileTime; + QUADLIB_U64 qValue, qOffset; + QUADLIB_U64 qRemainder; + int32_t nsec; + + STDTIME_ENUM_FUNC (StdTimeToTimeTypeEx) + + /* Check that *pStdTime is not before 1970 (illegal). */ + if (pStdTime->dwHighDateTime < FILETIME_1970_HIGH || + (pStdTime->dwHighDateTime == FILETIME_1970_HIGH && + pStdTime->dwLowDateTime < FILETIME_1970_LOW)) + STDTIME_RET_EC (argument_out_of_range); + + FILETIME_TO_QUADLIB_U64 (pStdTime, &qFileTime); + + /* This just divides by 10000000 to get seconds since 1601 */ + qValue = QUADLIB_I64_DIV ( + qFileTime, + QUADLIB_I64_CASTI32 (PVT_STDTIME_SCALE_FILETIME) ); + + /* Get remainder. */ + qRemainder = QUADLIB_I64_MOD ( + qFileTime, + QUADLIB_I64_CASTI32 (PVT_STDTIME_SCALE_FILETIME) ); + + /* Convert remainder to nanoseconds */ + nsec = (QUADLIB_I32_CASTI64 (qRemainder)) * 100; + if (pNsec != NULL) + *pNsec = nsec; + + /* Subtract number of seconds from 1601 to 1970. */ + QUADLIB_U64_HI(qOffset) = SECONDS_FROM_1601_TO_1970_HIGH; + QUADLIB_U64_LO(qOffset) = SECONDS_FROM_1601_TO_1970_LOW; + QUADLIB_I64_SUB_EQ (qValue, qOffset); /* modifies qValue */ + + /* Cast to time_t. */ +#ifdef STDTIME_TIME_T64_ENABLED + *pTimeT = QUADLIB_I64N_CASTI64(qValue); +#else + /* DEBUG: should check for qValue out of range before this cast.*/ + *pTimeT = QUADLIB_I32_CASTI64 (qValue); +#endif + return (STDTIME_OK); + } /* StdTimeToTimeTypeEx */ + +/************************************************************************/ +/* TimeTypeExToStdTime */ +/* convert: time_t plus nanoseconds to StdTime struct */ +/************************************************************************/ +STDTIME_RC TimeTypeExToStdTime ( + time_t /*I*/ timet, + int32_t /*I*/ nsec, + STDTIME * /*O*/ pStdTime) + { + QUADLIB_U64 qValue, qOffset; + + STDTIME_ENUM_FUNC (TimeTypeExToStdTime) + + if (pStdTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + if (timet < 0) + { + STDTIME_RET_EC (argument_out_of_range); + } + +#ifdef STDTIME_TIME_T64_ENABLED + QUADLIB_U64_HI(qValue) = QUADLIB_U64_HI(timet); + QUADLIB_U64_LO(qValue) = QUADLIB_U64_LO(timet); +#else + QUADLIB_U64_HI(qValue) = 0; + QUADLIB_U64_LO(qValue) = timet; +#endif + + /* Add number of seconds from 1601 to 1970. */ + QUADLIB_U64_HI(qOffset) = SECONDS_FROM_1601_TO_1970_HIGH; + QUADLIB_U64_LO(qOffset) = SECONDS_FROM_1601_TO_1970_LOW; + QUADLIB_I64_ADD_EQ (qValue, qOffset); /* modifies qValue */ + + /* Multiply seconds by 10000000 */ + qValue = QUADLIB_I64_MUL ( + qValue, + QUADLIB_I64_CASTI32 (PVT_STDTIME_SCALE_FILETIME) ); + + + /* Divide nsec by 100 to get num of "100-nanoseccond" intervals & add them.*/ + QUADLIB_U64_HI(qOffset) = 0; + QUADLIB_U64_LO(qOffset) = nsec / 100; + QUADLIB_I64_ADD_EQ (qValue, qOffset); /* modifies qValue */ + + QUADLIB_I64_TO_FILETIME (&qValue, pStdTime); + return (STDTIME_OK); + } /* TimeTypeExToStdTime */ + + +/*** Constructor-like functions **********************************************/ + +/*-***************************************************************************/ +/* StdTimeFields */ +/* construct a STDTIME_FIELDS structure from parameters */ +/*****************************************************************************/ + + +STDTIME_FIELDS StdTimeFields ( + int32_t /*I*/ year, + int32_t /*I*/ mon, + int32_t /*I*/ day, + int32_t /*I*/ hour, + int32_t /*I*/ min, + int32_t /*I*/ sec, + int32_t /*I*/ msec, + int32_t /*I*/ usec, + int32_t /*I*/ nsec) + { + STDTIME_FIELDS x; + + x.year = year; + x.mon = mon; + x.day = day; + x.hour = hour; + x.min = min; + x.sec = sec; + x.msec = msec; + x.usec = usec; + x.nsec = nsec; + + return x; + + } /* StdTimeFields */ + + +/*-***************************************************************************/ +/* StdTimeDelta */ +/* construct a STDTIME_DELTA structure from parameters */ +/*****************************************************************************/ + + +STDTIME_DELTA StdTimeDelta ( + int32_t /*I*/ day, + int32_t /*I*/ hour, + int32_t /*I*/ min, + int32_t /*I*/ sec, + int32_t /*I*/ msec, + int32_t /*I*/ usec, + int32_t /*I*/ nsec) + { + STDTIME_DELTA x; + + x.day = day; + x.hour = hour; + x.min = min; + x.sec = sec; + x.msec = msec; + x.usec = usec; + x.nsec = nsec; + + return x; + + } /* StdTimeDelta */ + + +/*-***************************************************************************/ +/* StdTimeSpan */ +/* construct a STDTIME structure from parameters */ +/*****************************************************************************/ + + +STDTIME_SPAN StdTimeSpan ( + QUADLIB_I64 /*I*/ value) + { + STDTIME_SPAN x; + + x.value = value; + + return x; + + } /* StdTimeSpan */ + + +/*** Initializer functions ***************************************************/ + + +/*-***************************************************************************/ +/* ZeroStdTime */ +/* return a zero value of type STDTIME */ +/*****************************************************************************/ + +STDTIME ZeroStdTime () + { + STDTIME zero = {0}; + + return zero; + + } /* ZeroStdTime */ + + +/*-***************************************************************************/ +/* ZeroStdTimeFields */ +/* return a zero value of type STDTIME_FIELDS */ +/*****************************************************************************/ + +STDTIME_FIELDS ZeroStdTimeFields () + { + STDTIME_FIELDS zero = {0}; + + return zero; + + } /* ZeroStdTimeFields */ + + +/*-***************************************************************************/ +/* ZeroStdTimeStringA */ +/* return a zero value of type STDTIME_STRINGA */ +/*****************************************************************************/ + +STDTIME_STRINGA ZeroStdTimeStringA () + { + STDTIME_STRINGA zero = {{0}}; + + return zero; + + } /* ZeroStdTimeStringA */ + + +/*-***************************************************************************/ +/* ZeroStdTimeDelta */ +/* return a zero value of type STDTIME_DELTA */ +/*****************************************************************************/ + +STDTIME_DELTA ZeroStdTimeDelta () + { + STDTIME_DELTA zero = {0}; + + return zero; + + } /* ZeroStdTimeDelta */ + + +/*-***************************************************************************/ +/* ZeroStdTimeSpan */ +/* return a zero value of type STDTIME_SPAN */ +/*****************************************************************************/ + +STDTIME_SPAN ZeroStdTimeSpan () + { + STDTIME_SPAN zero = {0}; + + return zero; + + } /* ZeroStdTimeSpan */ + + +/*-***************************************************************************/ +/* ZeroStdTimeTzoA */ +/* return a zero value of type STDTIME_TZOA */ +/*****************************************************************************/ + +STDTIME_TZOA ZeroStdTimeTzoA () + { + STDTIME_TZOA zero = {{0}}; + + return zero; + + } /* ZeroStdTimeTzoA */ + + +/*-***************************************************************************/ +/* ZeroStdTimeErrMsgA */ +/* return a zero value of type STDTIME_ERRMSGA */ +/*****************************************************************************/ + +STDTIME_ERRMSGA ZeroStdTimeErrMsgA () + { + STDTIME_ERRMSGA zero = {{0}}; + + return zero; + + } /* ZeroStdTimeErrMsgA */ + + +/*-***************************************************************************/ +/* ZeroStdTimeErrMsgW */ + + +/*** Initializer functions for 'outside' types *******************************/ +/*** names prefixed with 'StdTimeApi' because they are non-STDTIME structs ***/ + +/*-***************************************************************************/ +/* StdTimeApiZeroFileTime */ +/* return a zero value of type STDTIME_WIN_FILETIME */ +/*****************************************************************************/ + +STDTIME_WIN_FILETIME StdTimeApiZeroFileTime () + { + STDTIME_WIN_FILETIME zero = {0}; + + return zero; + + } /* StdTimeApiZeroFileTime */ + + +/*-***************************************************************************/ +/* StdTimeApiZeroSystemTime */ +/* return a zero value of type STDTIME_WIN_SYSTEMTIME */ +/*****************************************************************************/ + +STDTIME_WIN_SYSTEMTIME StdTimeApiZeroSystemTime () + { + STDTIME_WIN_SYSTEMTIME zero = {0}; + + return zero; + + } /* StdTimeApiZeroSystemTime */ + + +/*-***************************************************************************/ +/* StdTimeApiZeroStructTm */ +/* return a zero value of type struct tm */ +/*****************************************************************************/ + +struct tm StdTimeApiZeroStructTm () + { + struct tm zero = {0}; + + return zero; + + } /* StdTimeApiZeroStructTm */ + + +/*** calandar function interface *********************************************/ + + +/*-***************************************************************************/ +/* OBTAIN DAY OF WEEK AND DAY OF WEEK */ +/* This provides an interface to the W32 layer, which we do not want to */ +/* expose to the user. */ +/*****************************************************************************/ + +STDTIME_RC StdTimeGetDayofWeekAndYear ( + int32_t /*I*/ nYear, + int32_t /*I*/ nMon, + int32_t /*I*/ nDayofMon, + int32_t * /*O*/ pDayofWeek, + int32_t * /*O*/ pDayofYear) + { + STDTIME_ENUM_FUNC (StdTimeGetDayofWeekAndYear) + + STDTIME_RET (StdTimeW32GetDayofWeekAndYear ( + nYear, nMon, nDayofMon, pDayofWeek, pDayofYear)); + } + + +#if defined(_WIN32) +/*** Date functions (COM DATE) ***********************************************/ + +/************************************************************************/ +/* FileTimeToDate */ +/* RETURNS: 0=SUCCESS, 1=FAILURE */ +/************************************************************************/ +static int FileTimeToDate(const FILETIME *pft, double *pdate) + { + /* Don't allow FILETIME before 1899 (causes negative DATE). */ + if (*(__int64 *)pft < 0x014f35a9a90cc000) + { + *pdate = 0.0; /* set to bad value in case caller ignores return*/ + return (1); /* error */ + } + *pdate = (double)((double)(*(__int64 *)pft) / 8.64e11) - (double)(363 + (1899 - 1601) * 365 + (24 + 24 + 24)); + assert (*pdate >= 0.0); + return (0); /* success */ + } +/************************************************************************/ +/* DateToFileTime */ +/* RETURNS: 0=SUCCESS, 1=FAILURE */ +/************************************************************************/ +static int DateToFileTime(const double *pdate, FILETIME *pft) + { + __int64 temp; + if (*pdate < 0.0) /* negative date too complicated to deal with */ + { + temp = 0; + *pft = *(FILETIME *)&temp; /* set to bad value in case caller ignores return*/ + return (1); /* error */ + } + /* NOTE: this casts double to _int64 (some precision lost). */ + temp = (__int64)((*pdate + (double)(363 + (1899 - 1601) * 365 + (24 + 24 + 24))) * 8.64e11); + *pft = *(FILETIME *)&temp; + return (0); /* success */ + } + +/*-***************************************************************************/ +/* StdTimeToDate */ +/* convert: StdTime structure to DATE time value */ +/*****************************************************************************/ + +STDTIME_RC StdTimeToDate ( + const STDTIME * /*I*/ pStdTime, + STDTIME_WIN_DATE * /*O*/ pDate) + { + STDTIME_ENUM_FUNC (StdTimeToDate) + + /* STDTIME same as FILETIME, so this works. */ + if (FileTimeToDate (pStdTime, pDate)) + STDTIME_RET_EC (argument_out_of_range); + STDTIME_RET_OK; + } /* StdTimeToDate */ + +/*-***************************************************************************/ +/* DateToStdTime */ +/* convert: DATE time value to StdTime structure */ +/*****************************************************************************/ + +STDTIME_RC DateToStdTime ( + const STDTIME_WIN_DATE * /*I*/ pDate, + STDTIME * /*O*/ pStdTime) + { + STDTIME_ENUM_FUNC (DateToStdTime) + + /* STDTIME same as FILETIME, so this works. */ + if (DateToFileTime (pDate, pStdTime)) + STDTIME_RET_EC (argument_out_of_range); + STDTIME_RET_OK; + } /* DateToStdTime */ + +/*-***************************************************************************/ +/* StdTimeFieldsToDate */ +/* convert: StdTime structure to DATE time value */ +/*****************************************************************************/ + +STDTIME_RC StdTimeFieldsToDate ( + const STDTIME_FIELDS * /*I*/ pStdTimeFields, + STDTIME_WIN_DATE * /*O*/ pDate) + { + STDTIME StdTime; + + STDTIME_ENUM_FUNC (StdTimeFieldsToDate) + + rc = StdTimeFieldsToStdTime (pStdTimeFields, &StdTime); + if (rc == STDTIME_OK) + rc = StdTimeToDate (&StdTime, pDate); + return (rc); + } /* StdTimeFieldsToDate */ + +/*-***************************************************************************/ +/* DateToStdTimeFields */ +/* convert: DATE time value to StdTimeFields structure */ +/*****************************************************************************/ + +STDTIME_RC DateToStdTimeFields ( + const STDTIME_WIN_DATE * /*I*/ pDate, + STDTIME_FIELDS * /*O*/ pStdTimeFields) + { + STDTIME StdTime; + + STDTIME_ENUM_FUNC (DateToStdTimeFields) + + rc = DateToStdTime (pDate, &StdTime); + if (rc == STDTIME_OK) + rc = StdTimeToStdTimeFields (&StdTime, pStdTimeFields); + return (rc); + } /* DateToStdTimeFields */ + +#endif /* defined(_WIN32) */ + +/*-***************************************************************************/ +/* StdTimeToLocalStdTime */ +/* convert: StdTime structure from UTC/GMT time to local time */ +/* if not using TZDB, use local host to speed up conversion */ +/*****************************************************************************/ + +STDTIME_RC StdTimeToLocalStdTime ( + const STDTIME * /*I*/ pStdTime, + STDTIME * /*O*/ pStdTimeLocal) + { + STDTIME_ENUM_FUNC (StdTimeToLocalStdTime) + { + STDTIME_WIN_FILETIME gmtFileTime; + STDTIME_WIN_FILETIME locFileTime; + + if STDTIME_IFNOT (StdTimeToFileTime (pStdTime, &gmtFileTime)) + { + STDTIME_RET_RC; + } + + if (! STDTIME_API_FILETIMETOLOCALFILETIME (&gmtFileTime, &locFileTime)) + { + STDTIME_RET_EC (failure_in_api_FileTimeToLocalFileTime); + } + + STDTIME_RET (FileTimeToStdTime (&locFileTime, pStdTimeLocal)); + } + } /* StdTimeToLocalStdTime */ + + +/*-***************************************************************************/ +/* LocalStdTimeToStdTime */ +/* convert: StdTime structure from local time to UTC/GMT time */ +/* if not using TZDB, use local host to speed up conversion */ +/*****************************************************************************/ + +STDTIME_RC LocalStdTimeToStdTime ( + const STDTIME * /*I*/ pStdTimeLocal, + STDTIME * /*O*/ pStdTime) + { + STDTIME_ENUM_FUNC (LocalStdTimeToStdTime) + + { + STDTIME_WIN_FILETIME gmtFileTime; + STDTIME_WIN_FILETIME locFileTime; + + if STDTIME_IFNOT (StdTimeToFileTime (pStdTimeLocal, &locFileTime)) + { + STDTIME_RET_RC; + } + + if (! STDTIME_API_LOCALFILETIMETOFILETIME (&locFileTime, &gmtFileTime)) + { + STDTIME_RET_EC (failure_in_api_LocalFileTimeToFileTime); + } + + STDTIME_RET (FileTimeToStdTime (&gmtFileTime, pStdTime)); + } + } /* LocalStdTimeToStdTime */ + + +/*** timezone-offset support functions ***************************************/ + + +/*-***************************************************************************/ +/* NormalizeStdTimeTzoA */ +/* if timezone offset string is in a valid format, normalize it. */ +/* normalization involves the following: */ +/* */ +/* 1. a 'z' code is converted to 'Z' */ +/* 2. if the ss field is zero, it is dropped */ +/* 3. if all numeric fields are zero, the offset string becomes Z */ +/* 4. trailing blanks are removed, and replaced by nuls */ +/* */ +/*****************************************************************************/ + + +STDTIME_RC NormalizeStdTimeTzoA ( + STDTIME_TZOA * /*IO*/ pTzo) + { + STDTIME_TZOA tzoA = {{0}}; + int32_t hour; + int32_t min; + int32_t sec; + + STDTIME_ENUM_FUNC (NormalizeStdTimeTzoA) + + if (pTzo == NULL) + { + STDTIME_RET_EC (null_argument); + } + + /* limit input tzo string to declared length, jic */ + + pTzo->str[STDTIME_TZO_LEN] = 0; + + /* see if timezone offset is omitted */ + + if (Bool_StdTime_IsBlankA (pTzo->str)) + { + *pTzo = tzoA; /* clear out entire TZO field */ + STDTIME_RET_OK; + } + + if ((pTzo->str[0] == 'z') || (pTzo->str[0] == 'Z')) + { + if (Bool_StdTime_IsBlankA (pTzo->str+1)) + { + /* normalize Z and pad field with nuls */ + tzoA.str[0] = 'Z'; + *pTzo = tzoA; + STDTIME_RET_OK; + } + } + + if ((pTzo->str[0] != '+') && (pTzo->str[0] != '-')) + { + STDTIME_RET_EC (invalid_timezone_offset); + } + + if ( (! isdigit (pTzo->str[1])) + || (! isdigit (pTzo->str[2])) + || ( pTzo->str[3] != ':') + || (! isdigit (pTzo->str[4])) + || (! isdigit (pTzo->str[5])) ) + { + STDTIME_RET_EC (invalid_timezone_offset); + } + + hour = atoi (pTzo->str+1); + min = atoi (pTzo->str+4); + + if (! STDTIME_IN_RANGE (hour, 0, 23)) + { + STDTIME_RET_EC (invalid_hour); + } + + if (! STDTIME_IN_RANGE (min, 0, 59)) + { + STDTIME_RET_EC (invalid_min); + } + + /* determine whether we have short form or long form */ + /* long form: validate 'ss' digits */ + + if (pTzo->str[6] == ':') + { + if ( (! isdigit (pTzo->str[7])) + || (! isdigit (pTzo->str[8])) ) + { + STDTIME_RET_EC (invalid_timezone_offset); + } + + sec = atoi (pTzo->str+7); + + if (! STDTIME_IN_RANGE (sec, 0, 59)) + { + STDTIME_RET_EC (invalid_sec); + } + + if (! Bool_StdTime_IsBlankA (pTzo->str+9)) + { + STDTIME_RET_EC (invalid_timezone_offset); + } + } + + /* short form: ensure we are at end of string */ + + else + { + if (! Bool_StdTime_IsBlankA (pTzo->str+6)) + { + STDTIME_RET_EC (invalid_timezone_offset); + } + + sec = 0; + } + + /* now, normalize the format */ + + if ((hour == 0) && (min == 0) && (sec == 0)) + { + /* if all fields zero, it is GMT time */ + /* normalize Z and pad field with nuls */ + tzoA.str[0] = 'Z'; + *pTzo = tzoA; + STDTIME_RET_OK; + } + + if (sec == 0) + { + /* +hh:mm or -hh:mm format */ + sprintf (tzoA.str, "%c%02d:%02d", pTzo->str[0], hour, min); + } + + else + { + /* +hh:mm:ss or -hh:mm:ss format */ + sprintf (tzoA.str, "%c%02d:%02d:%02d", pTzo->str[0], hour, min, sec); + } + + *pTzo = tzoA; /* copy back reformatted tzoA */ + STDTIME_RET_OK; + + } /* NormalizeStdTimeTzoA */ + + +/*** error message decoding functions ****************************************/ + + +/*-***************************************************************************/ +/* StdTimeRcToErrMsgA */ +/* interpret STDTIME_RC value and convert to a STDTIME_ERRMSGA structure. */ +/*****************************************************************************/ + +STDTIME_RC StdTimeRcToErrMsgA ( + const STDTIME_RC /*I*/ stdTimeRc, + STDTIME_ERRMSGA * /*O*/ pErrMsg) + { + STDTIME_ERRMSGA errMsg = {{0}}; + int32_t hilevel; + int32_t lolevel; + int32_t reason; + int32_t i; + + STDTIME_ENUM_FUNC (StdTimeRcToErrMsgA) + + if (pErrMsg == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pErrMsg = ZeroStdTimeErrMsgA (); + + /* a STDTIME_RC has the following bit layout */ + /* bits 31-30(2) unused */ + /* bits 29-20(10) hi-level function enum */ + /* bits 19-10(10) lo-level function enum */ + /* bits 09-00(10) error reason code */ + + hilevel = (stdTimeRc >> 20) & 0x3FF; + lolevel = (stdTimeRc >> 10) & 0x3FF; + reason = stdTimeRc & 0x3FF; + + /* an error code has the form 0xNNNNNNNN = HHHH.LLLL.RRRR# */ + /* 0123456789012345678901234567 */ + /* this holds a raw hex RC value, and the RC as decimal subfields */ + + sprintf (errMsg.errcode, "0x%08X = %04d.%04d.%04d", + stdTimeRc, hilevel, lolevel, reason); + + if ((stdTimeRc & 0xC0000000) != 0) + { + strncpy (errMsg.hilevel, "*** invalid STDTIME_RC value", + STDTIME_ERRMSG_LEN); + + *pErrMsg = errMsg; /* pass back result */ + STDTIME_RET_EC (invalid_stdtime_rc_value); + } + + /* the first entry is at STDTIME_FUNC__0000 with an enum value of 0 */ + /* enum 0 is "valid" but 0 is not used for error return codes, because */ + /* a STDTIME_RC of 0 means there is no error, so 0 is skipped. */ + /* example: suppose there were 10 entries; they would have enum's 1 to 10 */ + /* the last entry is at STDTIME_FUNC__SIZE with (example) enum value of 11 */ + + if (hilevel < (STDTIME_RC) STDTIME_FUNC__SIZE) + { + strncpy (errMsg.hilevel, enum_stdtime_func_text[hilevel], + STDTIME_ERRMSG_LEN); + } + + else + { + strncpy (errMsg.hilevel, "*** undefined hilevel function", + STDTIME_ERRMSG_LEN); + } + + if (lolevel < (STDTIME_RC) STDTIME_FUNC__SIZE) + { + strncpy (errMsg.lolevel, enum_stdtime_func_text[lolevel], + STDTIME_ERRMSG_LEN); + } + + else + { + strncpy (errMsg.lolevel, "*** undefined lolevel function", + STDTIME_ERRMSG_LEN); + } + + if (reason < (STDTIME_RC) STDTIME_ERR__SIZE) + { + strncpy (errMsg.reason, enum_stdtime_err_text[reason], + STDTIME_ERRMSG_LEN); + } + + else + { + strncpy (errMsg.reason, "*** undefined reason code", + STDTIME_ERRMSG_LEN); + } + + errMsg.hilevel[STDTIME_ERRMSG_LEN] = 0; + errMsg.lolevel[STDTIME_ERRMSG_LEN] = 0; + errMsg.reason [STDTIME_ERRMSG_LEN] = 0; + + /* remove underscores from reason message */ + /* the underscores were necessary for the macro to form an enum name */ + /* but we don't want them literally present in the message */ + + for (i=0; errMsg.reason[i]; i++) + { + if (errMsg.reason[i] == '_') + { + errMsg.reason[i] = ' '; + } + } + + *pErrMsg = errMsg; /* pass back result */ + + STDTIME_RET_RC; + + } /* StdTimeRcToErrMsgA */ + + +/*** END - STDTIME.C *********************************************************/ + + diff --git a/mmslib/util/stdtime_mms_btime.c b/mmslib/util/stdtime_mms_btime.c new file mode 100644 index 0000000..cc53df0 --- /dev/null +++ b/mmslib/util/stdtime_mms_btime.c @@ -0,0 +1,194 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2006 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtime_mms_btime.c */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Support for MMS Btime4, BTime6 and BTOD conversions to/from STDTIME */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 02/20/08 JRB 02 Make STDTIME same as FILETIME (simplifies a lot). */ +/* Move T84_* defines to header file. */ +/* Del TimeOfDay4, Btod, and StdTimeFields functions. */ +/* 10/05/06 RLH 01 Created */ +/*****************************************************************************/ + + +#include "stdtime.h" +#include "stdtime_mms_btime.h" + +/*** MmsTimeOfDay6 initialization functions ***************************/ + + +STDTIME_MMS_TIMEOFDAY6 StdTimeApiZeroMmsTimeOfDay6 () + { + STDTIME_MMS_TIMEOFDAY6 zero = {0}; + + return zero; + + } /* StdTimeApiZeroMmsTimeOfDay6 */ + + +/*** MmsTimeOfDay6Ex functions ***********************************************/ + + +/*-***************************************************************************/ +/* StdTimeToMmsTimeOfDay6Ex */ +/* convert: StdTime struct to MMS_TIMEOFDAY6 and extra fields */ +/* method: subtract 1984-01-01 from stdTime to form delta */ +/*****************************************************************************/ + +STDTIME_RC StdTimeToMmsTimeOfDay6Ex ( + const STDTIME * /*I*/ pStdTime, + STDTIME_MMS_TIMEOFDAY6 * /*O*/ pMmsTimeOfDay6, + int32_t * /*O*/ pUsec, + int32_t * /*O*/ pNsec) + { + /* pre-calculated STDTIME value of 1984-01-01 00:00:00.0000000 */ + STDTIME t84; /* initialized below */ + + STDTIME_DELTA mms; + + STDTIME_ENUM_FUNC (StdTimeToMmsTimeOfDay6Ex) + + if (pStdTime->dwHighDateTime < T84_HIGHDATETIME || + (pStdTime->dwHighDateTime == T84_HIGHDATETIME && + pStdTime->dwLowDateTime < T84_LOWDATETIME)) + { + STDTIME_RET_EC (MMS_year_LT_1984); + } + + t84.dwHighDateTime = T84_HIGHDATETIME; /* initialize */ + t84.dwLowDateTime = T84_LOWDATETIME; + + if (pMmsTimeOfDay6 == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pMmsTimeOfDay6 = StdTimeApiZeroMmsTimeOfDay6(); + + /* form difference between supplied date and 1984 */ + + if STDTIME_IFNOT (StdTime_GetDelta (pStdTime, &t84, &mms)) + { + STDTIME_RET_RC; + } + + pMmsTimeOfDay6->day = mms.day; + + pMmsTimeOfDay6->ms = + (mms.hour * 60 * 60 * 1000) + + (mms.min * 60 * 1000) + + (mms.sec * 1000) + mms.msec; + + if (pUsec != NULL) + { + *pUsec = mms.usec; + } + + if (pNsec != NULL) + { + *pNsec = mms.nsec; + } + + STDTIME_RET_OK; + + } /* StdTimeToMmsTimeOfDay6Ex */ + + +/*-***************************************************************************/ +/* MmsTimeOfDay6ExToStdTime */ +/* convert: MMS_TIMEOFDAY6 and extra fields to StdTime struct */ +/* method: add MMS days and msec to base value of 1984-01-01 */ +/*****************************************************************************/ + +STDTIME_RC MmsTimeOfDay6ExToStdTime ( + const STDTIME_MMS_TIMEOFDAY6 * /*I*/ pMmsTimeOfDay6, + int32_t /*I*/ nUsec, + int32_t /*I*/ nNsec, + STDTIME * /*O*/ pStdTime) + { + /* pre-calculated STDTIME value of 1984-01-01 00:00:00.0000000 */ + STDTIME t84; /* initialized below */ + STDTIME_DELTA mms = {0}; + + STDTIME_ENUM_FUNC (MmsTimeOfDay6ExToStdTime) + + t84.dwHighDateTime = T84_HIGHDATETIME; /* initialize */ + t84.dwLowDateTime = T84_LOWDATETIME; + + if (pStdTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pStdTime = ZeroStdTime (); + + if (pMmsTimeOfDay6 == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pStdTime = ZeroStdTime(); + + /* create delta from 1984-01-01 */ + + mms.day = pMmsTimeOfDay6->day; + mms.msec = pMmsTimeOfDay6->ms; + mms.usec = nUsec; + mms.nsec = nNsec; + + /* add mms displacement to mms epoch date of Jan 1 1984 */ + + if STDTIME_IFNOT (StdTime_AddDelta (&t84, &mms)) + { + STDTIME_RET_RC; + } + + *pStdTime = t84; + + STDTIME_RET_OK; + + } /* MmsTimeOfDay6ExToStdTime */ + + +/*** MmsTimeOfDay6 functions *************************************************/ + + +/*-***************************************************************************/ +/* StdTimeToMmsTimeOfDay6 */ +/* convert: StdTime struct to MMS_TIMEOFDAY6 (without extra fields) */ +/*****************************************************************************/ + +STDTIME_RC StdTimeToMmsTimeOfDay6 ( + const STDTIME * /*I*/ pStdTime, + STDTIME_MMS_TIMEOFDAY6 * /*O*/ pMmsTimeOfDay6) + { + STDTIME_ENUM_FUNC (StdTimeToMmsTimeOfDay6) + + STDTIME_RET (StdTimeToMmsTimeOfDay6Ex (pStdTime, pMmsTimeOfDay6, NULL, NULL)); + + } /* StdTimeToMmsTimeOfDay6 */ + + +/*-***************************************************************************/ +/* MmsTimeOfDay6ToStdTime */ +/* convert: MMS_TIMEOFDAY6 (without extra fields) to StdTime struct */ +/*****************************************************************************/ + +STDTIME_RC MmsTimeOfDay6ToStdTime ( + const STDTIME_MMS_TIMEOFDAY6 * /*I*/ pMmsTimeOfDay6, + STDTIME * /*O*/ pStdTime) + { + STDTIME_ENUM_FUNC (MmsTimeOfDay6ToStdTime) + + STDTIME_RET (MmsTimeOfDay6ExToStdTime (pMmsTimeOfDay6, 0, 0, pStdTime)); + + } /* MmsTimeOfDay6ToStdTime */ diff --git a/mmslib/util/stdtime_mms_utctime.c b/mmslib/util/stdtime_mms_utctime.c new file mode 100644 index 0000000..904e53e --- /dev/null +++ b/mmslib/util/stdtime_mms_utctime.c @@ -0,0 +1,169 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2006 All Rights Reserved */ +/* */ +/* MODULE NAME : stdtime_mms_utctime.c */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Support for MMS UTC TIME conversions to/from STDTIME */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 02/20/08 JRB 02 Simplified StdTimeToMmsUtcTime (fixes rounding bug). */ +/* Simplified MmsUtcTimeToStdTime. */ +/* Delete StdTimeFields functions. */ +/* 10/05/06 RLH 01 Created */ +/*****************************************************************************/ + + +#include "stdtime.h" +#include "stdtime_mms_utctime.h" + + +/*** MmsUtcTime initialization function **************************************/ + + +STDTIME_MMS_UTC_TIME StdTimeApiZeroMmsUtcTime () + { + STDTIME_MMS_UTC_TIME zero = {0}; + + return zero; + + } /* StdTimeApiZeroMmsUtcTime */ + + +/*** MmsUtcTime functions ****************************************************/ + + +/*-***************************************************************************/ +/* StdTimeToMmsUtcTime */ +/* convert: StdTime structure to MMS_UTC_TIME */ +/* method: convert to TIMETYPE, then calculate binary fraction of second */ +/*****************************************************************************/ + +STDTIME_RC StdTimeToMmsUtcTime ( + const STDTIME * /*I*/ pStdTime, + STDTIME_MMS_UTC_TIME * /*O*/ pMmsUtcTime) + { + QUADLIB_I64 qFrac; + QUADLIB_I64 qRem; + QUADLIB_I64 q10_7; + QUADLIB_I64 q2_24; + time_t timet; + int32_t nsec; + + STDTIME_ENUM_FUNC (StdTimeToMmsUtcTime) + + + if (pMmsUtcTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + if STDTIME_IFNOT (StdTimeToTimeTypeEx (pStdTime, &timet, &nsec)) + { + STDTIME_RET_RC; + } + + /* Init qFrac to number of 100-nsec intervals. */ + QUADLIB_I64_HI(qFrac) = 0; + QUADLIB_I64_LO(qFrac) = nsec / 100; + + QUADLIB_I64_HI(q10_7) = 0; + QUADLIB_I64_LO(q10_7) = 10000000; + + QUADLIB_I64_HI(q2_24) = 0; + QUADLIB_I64_LO(q2_24) = 0x1000000; + + /* multiply by range of UTC fraction */ + + QUADLIB_I64_MUL_EQ (qFrac, q2_24); + + /* divide out number of 100-ns intervals */ + /* as 100-ns intervals approaches 10_7, frac approaches 2_24 */ + + qFrac = QuadLibI64DivMod (qFrac, q10_7, &qRem); + + /* assign UTC values to output argument */ + + pMmsUtcTime->secs = (int32_t) timet; + pMmsUtcTime->fraction = (int32_t) QUADLIB_I64_LO(qFrac); + pMmsUtcTime->qflags = 0; /* IS THIS CORRECT ? */ + + STDTIME_RET_OK; + + } /* StdTimeToMmsUtcTime */ + + +/*-***************************************************************************/ +/* MmsUtcTimeToStdTime */ +/* convert: MMS_UTC_TIME to StdTime structure */ +/*****************************************************************************/ + +STDTIME_RC MmsUtcTimeToStdTime ( + const STDTIME_MMS_UTC_TIME * /*I*/ pMmsUtcTime, + STDTIME * /*O*/ pStdTime) + { + QUADLIB_I64 qFrac; + QUADLIB_I64 qRem; + QUADLIB_I64 q10_7; + QUADLIB_I64 q2_24; + int32_t nsec; /* nanoseconds */ + + STDTIME_ENUM_FUNC (MmsUtcTimeToStdTime) + + if (pStdTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + *pStdTime = ZeroStdTime (); + + if (pMmsUtcTime == NULL) + { + STDTIME_RET_EC (null_argument); + } + + /* Convert fraction to nsec, then call TimeTypeExToStdTime. */ + + /* obtain number of binary fractional units */ + + QUADLIB_I64_HI(q10_7) = 0; + QUADLIB_I64_LO(q10_7) = 10000000; + + QUADLIB_I64_HI(q2_24) = 0; + QUADLIB_I64_LO(q2_24) = 0x1000000; + + QUADLIB_I64_HI(qFrac) = 0; + QUADLIB_I64_LO(qFrac) = pMmsUtcTime->fraction; + + + /* multiply by range of 100-ns intervals */ + + QUADLIB_I64_MUL_EQ (qFrac, q10_7); + + /* divide out number of binary fractional units */ + /* as fractional units approach 2**24, frac approaches 10**7 */ + + qFrac = QuadLibI64DivMod (qFrac, q2_24, &qRem); + + if (QUADLIB_I64_LO(qRem) >= (10000000 / 2)) + { + QUADLIB_I64_LO(qFrac)++; /* ROUND UP */ + } + + nsec = (QUADLIB_I32_CASTI64 (qFrac)) * 100; + + /* Convert and put result at pointer pStdTime. */ + if STDTIME_IFNOT (TimeTypeExToStdTime (pMmsUtcTime->secs, nsec, pStdTime)) + { + STDTIME_RET_RC; + } + STDTIME_RET_OK; + + } /* MmsUtcTimeToStdTime */ + diff --git a/mmslib/util/stdtime_quadlib.c b/mmslib/util/stdtime_quadlib.c new file mode 100644 index 0000000..fb02a28 --- /dev/null +++ b/mmslib/util/stdtime_quadlib.c @@ -0,0 +1,1599 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : QuadLib.c */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* 64-bit Math Simulation Library. */ +/* Provided for platforms without native 64-bit support. */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */ +/* 01/18/06 RLH 01 Created */ +/*****************************************************************************/ + +#include "stdtime.h" + +#ifdef QUADLIB_ENABLED + +int32_t QuadLibU64Cmp (QUADLIB_U64 x, QUADLIB_U64 y) + { + if (x.hi.u < y.hi.u) return -1; + if (x.hi.u > y.hi.u) return 1; + + if (x.lo.u < y.lo.u) return -1; + if (x.lo.u > y.lo.u) return 1; + + return 0; + } + +int32_t QuadLibI64Cmp (QUADLIB_I64 x, QUADLIB_I64 y) + { + if (x.hi.i < y.hi.i) return -1; + if (x.hi.i > y.hi.i) return 1; + + /* the unsigned compare on lo.u works correctly if x.hi.i == y.hi.i */ + /* in case of negative numbers, when lo increases in unsigned */ + /* magnitude, the 64-bit value is less negative, and so is a */ + /* greater signed value, so nothing special needs to be done */ + + if (x.lo.u < y.lo.u) return -1; + if (x.lo.u > y.lo.u) return 1; + + return 0; + } + +#endif /* QUADLIB_ENABLED */ + + +/*****************************************************************************/ +/* GET/SET */ +/*****************************************************************************/ + + +#ifndef QUADLIB_ENABLED + +/* get hi value of a 64-bit value when host has native support */ + +QUADLIB_STATIC int32_t QuadLibI64GetHi (QUADLIB_I64 x) + { + return (int32_t) QUADLIB_I64_HI(x); + + } /* QuadLibI64GetHi */ + +QUADLIB_STATIC uint32_t QuadLibU64GetHi (QUADLIB_U64 x) + { + return (uint32_t) QUADLIB_U64_HI(x); + + } /* QuadLibU64GetHi */ + +/* get lo value of a 64-bit value when host has native support */ + +QUADLIB_STATIC int32_t QuadLibI64GetLo (QUADLIB_I64 x) + { + return (int32_t) QUADLIB_I64_LO(x); + + } /* QuadLibI64GetLo */ + +QUADLIB_STATIC uint32_t QuadLibU64GetLo (QUADLIB_U64 x) + { + return (uint32_t) QUADLIB_U64_LO(x); + + } /* QuadLibU64GetLo */ + + +/* set hi value of a 64-bit value when host has native support */ + +void QuadLibI64SetHi (QUADLIB_I64 *x, int32_t y) + { + (*(QUADLIB_I64_TYPE *)(x)).hi.i = y; + + } /* QuadLibI64SetHi */ + +void QuadLibU64SetHi (QUADLIB_U64 *x, uint32_t y) + { + (*(QUADLIB_I64_TYPE *)(x)).hi.u = y; + + } /* QuadLibU64SetHi */ + +/* set lo value of a 64-bit value when host has native support */ + +void QuadLibI64SetLo (QUADLIB_I64 *x, int32_t y) + { + (*(QUADLIB_I64_TYPE *)(x)).lo.i = y; + + } /* QuadLibI64SetLo */ + +void QuadLibU64SetLo (QUADLIB_U64 *x, uint32_t y) + { + (*(QUADLIB_I64_TYPE *)(x)).lo.u = y; + + } /* QuadLibU64SetLo */ + +#endif /* not QUADLIB_ENABLED */ + + +/*****************************************************************************/ +/* CAST */ +/*****************************************************************************/ + + +#ifdef QUADLIB_ENABLED + + +/* 64-bit to 64-bit conversions */ + + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64CastI64N(void * x, size_t n) + { + QUADLIB_I64 result; + + /* determine type of cast based on sizeof(x) */ + + switch (n) + { + case 8: + QUADLIB_I64_HI(result) = QUADLIB_I64_HI(x); + QUADLIB_I64_LO(result) = QUADLIB_I64_LO(x); + break; + + case 2: + QUADLIB_I64_HI(result) = + QUADLIB_I64_LO(result) = (*(short *)(&x)); + QUADLIB_I64_HI(result) >>= 31; /* sign propagation */ + break; + + case 1: + QUADLIB_I64_HI(result) = + QUADLIB_I64_LO(result) = (*(char *)(&x)); + QUADLIB_I64_HI(result) >>= 31; /* sign propagation */ + break; + + default: + /* assume length 4 */ + QUADLIB_I64_HI(result) = + QUADLIB_I64_LO(result) = (*(long *)(&x)); + QUADLIB_I64_HI(result) >>= 31; /* sign propagation */ + break; + } + + return result; + + } /* QuadLibI64CastI64N */ + + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64CastU64N(void * x, size_t n) + { + QUADLIB_U64 result; + + /* determine type of cast based on sizeof(x) */ + + switch (n) + { + case 8: + QUADLIB_I64_HI(result) = QUADLIB_I64_HI(x); + QUADLIB_I64_LO(result) = QUADLIB_I64_LO(x); + break; + + case 2: + QUADLIB_I64_HI(result) = 0; + QUADLIB_I64_LO(result) = (*(unsigned short *)(&x)); + break; + + case 1: + QUADLIB_I64_HI(result) = 0; + QUADLIB_I64_LO(result) = (*(unsigned char *)(&x)); + break; + + default: + /* assume length 4 */ + QUADLIB_I64_HI(result) = 0; + QUADLIB_I64_LO(result) = (*(unsigned long *)(&x)); + break; + } + + return result; + + } /* QuadLibU64CastU64N */ + + +QUADLIB_STATIC QUADLIB_I64N QuadLibI64NCastI64(QUADLIB_I64 x) + { + QUADLIB_I64N result; + +#ifdef QUADLIB_NATIVE64_ENABLED + QUADLIB_I64_HI(result) = QUADLIB_I64_HI(x); + QUADLIB_I64_LO(result) = QUADLIB_I64_LO(x); + +#else + /* x is a 32-bit value, so we can only return 32 bits of I64 value */ + result = (QUADLIB_I64N) QUADLIB_I64_LO(x); + +#endif + return result; + + } /* QuadLibI64NCastI64 */ + + +QUADLIB_STATIC QUADLIB_U64N QuadLibU64NCastU64(QUADLIB_U64 x) + { + QUADLIB_U64N result; + +#ifdef QUADLIB_NATIVE64_ENABLED + QUADLIB_U64_HI(result) = QUADLIB_U64_HI(x); + QUADLIB_U64_LO(result) = QUADLIB_U64_LO(x); + +#else + /* x is a 32-bit value, so we can only return 32 bits of I64 value */ + result = (QUADLIB_U64N) QUADLIB_U64_LO(x); + +#endif + return result; + + } /* QuadLibU64NCastU64 */ + + +/* upsize casts: 32 to 64 bit */ + + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64CastI32 (int32_t x) + { + QUADLIB_I64 result; + + result.lo.i = x; + result.hi.i = x; + result.hi.i >>= 31; /* for signed, x propagation */ + + return result; + } /* QuadLibI64CastI32 */ + + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64CastU32 (uint32_t x) + { + QUADLIB_U64 result; + + result.hi.u = 0; /* for unsigned, 0 propagation */ + result.lo.u = x; + + return result; + } /* QuadLibU64CastU32 */ + + +/* downsize casts: 64 to 32 bit */ + + +QUADLIB_STATIC int32_t QuadLibI32CastI64 (QUADLIB_I64 x) + { + return x.lo.i; + } /* QuadLibI32CastI64 */ + + +QUADLIB_STATIC uint32_t QuadLibU32CastU64 (QUADLIB_U64 x) + { + return x.lo.u; + } /* QuadLibU32CastU64 */ + + +#endif /* QUADLIB_ENABLED */ + + +/*****************************************************************************/ +/* QuadLibU64Not */ +/* form 1's complement of 64-bit value */ +/*****************************************************************************/ + + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Not (QUADLIB_U64 x) + { + QUADLIB_U64 result; + + result.hi.u = ~(x.hi.u); + result.lo.u = ~(x.lo.u); + return result; + } + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64Neg */ +/* form 2's complement of 64-bit value */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Neg (QUADLIB_U64 x) + { + QUADLIB_U64 result; + + result.hi.u = ~(x.hi.u); + result.lo.u = (~(x.lo.u)) + 1; + + /* if x.lo.u came in as 0, its complement is 0xFFFFFFFF */ + /* if we then increment it, it will become 0 again */ + /* so, if result.lo.u is zero now, there was a carry */ + + if (result.lo.u == 0) + { + result.hi.u++; + } + + return result; + } /* QuadLibU64Neg */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64Abs */ +/* form absolute value of 64-bit value */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Abs (QUADLIB_U64 x) + { + if (x.hi.i < 0) /* value is negative */ + { + return QUADLIB_U64_NEG (x); + } + + return x; /* value is positive, do not negate */ + + } /* QuadLibU64Abs */ + +#else /* not QUADLIB_ENABLED */ + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Abs (QUADLIB_U64 x) + { + if (x < 0) /* value is negative */ + { + return (QUADLIB_U64) (-(QUADLIB_I64) x); + /* negate native I64 value */ + } + + return x; /* value is positive, do not negate */ + + } /* QuadLibU64Abs */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64Mul */ +/* multiply two unsigned 64-bit values. */ +/* form partial products from 16-bit values to limit results to 32 bits. */ +/* */ +/* method: let ABCD mean four 16-bit values with 'one', and WXYZ in 'two' */ +/* then, one * two = ABCD * WXYZ. in "long-hand" this means: */ +/* */ +/* (let xxL mean the Left 16 bits of a word, and xxR the Right 16 bits) */ +/* */ +/* A B C D */ +/* W X Y Z */ +/* -------------- */ +/* AZ BZ CZ DZ */ +/* AY BY CY DY */ +/* AX BX CX DX */ +/* AW BW CW DW */ +/* */ +/* express the partial sums as split L/R pairs, and discard partial sums */ +/* that exceed the 64-bit result capacity. ("discard" means discard from */ +/* the explanation; the discarded values are not actually calculated.) */ +/* */ +/* A B C D */ +/* W X Y Z */ +/* -------------- */ +/* AZR BZR CZR DZR */ +/* BZL CZL DZL */ +/* BYR CYR DYR */ +/* CYL DYL */ +/* CXR DXR */ +/* DXL */ +/* DWR */ +/* */ +/* since there is no carry out of the left 32-bit value (the AB column), */ +/* there is no need to split the left-most (AB column) 32-bit values into */ +/* 16/16. so, we optimize the list of partial sums as follows, (where */ +/* (xxL:xxR represents an unsplit 32-bit value), and reorganize the */ +/* diagram to show the left/right relationships better: */ +/* */ +/* A B C D */ +/* W X Y Z */ +/* -------------- */ +/* AZR */ +/* bzL:bzR */ +/* CZL CZR */ +/* DZL DZR */ +/* -------------- */ +/* BYR */ +/* cyL:cyR */ +/* DYL DYR */ +/* -------------- */ +/* CXR */ +/* dxL:dxR */ +/* -------------- */ +/* DWR */ +/* */ +/* finally, add up the columns, and store the sums in a 64-bit value */ +/* */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +#define QUADLIB_U32_LWORD(x) ( ((uint32_t)(x)) >> 16) +#define QUADLIB_U32_RWORD(x) ((x) & 0xFFFF) + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Mul ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two) + { + QUADLIB_U64 result; + + uint32_t a, b, c, d, w, x, y, z; + uint32_t ab, bc, cd; + uint32_t az, bz, cz, dz; + uint32_t by, cy, dy; + uint32_t cx, dx; + uint32_t dw; + + uint32_t azr, czr, dzr; + uint32_t czl, dzl; + uint32_t byr, dyr; + uint32_t dyl; + uint32_t cxr; + uint32_t dwr; + + + a = QUADLIB_U32_LWORD(one.hi.u); + b = QUADLIB_U32_RWORD(one.hi.u); + c = QUADLIB_U32_LWORD(one.lo.u); + d = QUADLIB_U32_RWORD(one.lo.u); + + w = QUADLIB_U32_LWORD(two.hi.u); + x = QUADLIB_U32_RWORD(two.hi.u); + y = QUADLIB_U32_LWORD(two.lo.u); + z = QUADLIB_U32_RWORD(two.lo.u); + + + az = a * z; bz = b * z; cz = c * z; dz = d * z; + by = b * y; cy = c * y; dy = d * y; + cx = c * x; dx = d * x; + dw = d * w; + azr = QUADLIB_U32_RWORD(az); + czr = QUADLIB_U32_RWORD(cz); + dzr = QUADLIB_U32_RWORD(dz); + czl = QUADLIB_U32_LWORD(cz); + dzl = QUADLIB_U32_LWORD(dz); + byr = QUADLIB_U32_RWORD(by); + dyr = QUADLIB_U32_RWORD(dy); + dyl = QUADLIB_U32_LWORD(dy); + cxr = QUADLIB_U32_RWORD(cx); + dwr = QUADLIB_U32_RWORD(dw); + + bc = czr + dzl + dyr; + + ab = bc >> 16; + cd = bc << 16; + + result.lo.u = cd + dzr; + + result.hi.u = ab + bz + cy + dx + + czl + dyl + + ((azr + byr + cxr + dwr) << 16); + + return result; + + } /* QuadLibU64Mul */ + +#undef QUADLIB_U32_LWORD +#undef QUADLIB_U32_RWORD + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64Add */ +/* add two unsigned 64-bit values */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Add ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two) + { + QUADLIB_U64 sum; + uint32_t carry; + + sum.lo.u = one.lo.u + two.lo.u; + sum.hi.u = one.hi.u + two.hi.u; + + /* calculate carry using boolean algebra */ + + carry = + ( (one.lo.u & two.lo.u) | ((one.lo.u ^ two.lo.u) & (~sum.lo.u)) ) >> 31; + + sum.hi.u += carry; + + return sum; + + } /* QuadLibU64Add */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64Sub */ +/* subtract two unsigned 64-bit values */ +/* method: negate second operand, and then add values */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Sub ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two) + { + return QuadLibU64Add (one, QUADLIB_U64_NEG (two)); + } /* QuadLibU64Sub */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64Add1 */ +/* increment a 64-bit value */ +/* method: add a constant 1 to a 64-bit value */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Add1 ( + QUADLIB_U64 /*I*/ x) + { + QUADLIB_U64 result; + + result.hi.u = x.hi.u; + result.lo.u = x.lo.u + 1; + + if (result.lo.u == 0) + { + /* x.lo.u must have had all 1 bits, so a carry occurred */ + result.hi.u++; + } + + return result; + + } /* QuadLibU64Add1 */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64Sub1 */ +/* decrement a 64-bit value */ +/* method: add a constant -1 to a 64-bit value */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Sub1 ( + QUADLIB_U64 /*I*/ x) + { + QUADLIB_U64 result; + + result.hi.u = x.hi.u; + result.lo.u = x.lo.u - 1; + + if (x.lo.u == 0) + { + /* x.lo.u was 0, so a borrow occurred */ + result.hi.u--; + } + + return result; + + } /* QuadLibU64Sub1 */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64SHR */ +/* shift an unsigned 64-bit value right by n bits */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHR ( + QUADLIB_U64 /*I*/ value, + int32_t /*I*/ shift) + { + QUADLIB_U64 result = QUADLIB_ZERO; + + if (shift == 0) + { + return value; + } + + if (shift < 0) + { + return QuadLibU64SHL (value, -shift); + } + + if (shift > 63) + { + return result; /* all bits shifted out, return 0 */ + } + + for (result = value; shift > 0; shift--) + { + result.lo.u >>= 1; + + if (result.hi.u & 1) + { + /* hi has low-order 1 about to be shifted out */ + result.lo.u |= QUADLIB_U32_HIGHBIT; + } + + result.hi.u >>= 1; /* unsigned shift right */ + } + + return result; + + } /* QuadLibU64SHR */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibI64SHR */ +/* shift a signed 64-bit value right by n bits */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64SHR ( + QUADLIB_I64 /*I*/ value, + int32_t /*I*/ shift) + { + QUADLIB_I64 result = QUADLIB_ZERO; + + if (shift == 0) + { + return value; + } + + if (shift < 0) + { + return QuadLibU64SHL (value, -shift); + } + + if (shift > 63) + { + return result; /* all bits shifted out return 0 */ + } + + for (result = value; shift > 0; shift--) + { + result.lo.u >>= 1; + + if (result.hi.u & 1) + { + /* hi has low-order 1 about to be shifted out */ + result.lo.u |= QUADLIB_U32_HIGHBIT; + } + + result.hi.i >>= 1; /* signed shift right */ + } + + return result; + + } /* QuadLibI64SHR */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64SHL */ +/* shift an unsigned 64-bit value left by n bits */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHL ( + QUADLIB_U64 /*I*/ value, + int32_t /*I*/ shift) + { + QUADLIB_U64 result = QUADLIB_ZERO; + + if (shift == 0) + { + return value; + } + + if (shift < 0) + { + return QuadLibU64SHR (value, -shift); + } + + if (shift > 63) + { + return result; /* all bits shifted out return 0 */ + } + + for (result = value; shift > 0; shift--) + { + QUADLIB_U64_SHL1_EQ_INLINE (result); + } + + return result; + + } /* QuadLibU64SHL */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibI64SHR1 */ +/* shift a signed 64-bit value right by 1 bit */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64SHR1 ( + QUADLIB_I64 /*I*/ value) + { + QUADLIB_I64_SHR1_EQ_INLINE (value); + + return value; + + } /* QuadLibI64SHR1 */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64SHR1 */ +/* shift an unsigned 64-bit value right by 1 bit */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHR1 ( + QUADLIB_U64 /*I*/ value) + { + QUADLIB_U64_SHR1_EQ_INLINE (value); + + return value; + + } /* QuadLibU64SHR1 */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64SHL1 */ +/* shift an unsigned 64-bit value left by 1 bit */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHL1 ( + QUADLIB_U64 /*I*/ value) + { + QUADLIB_U64_SHL1_EQ_INLINE (value); + + return value; + + } /* QuadLibU64SHL1 */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibI64SHR4 */ +/* shift a signed 64-bit value right by 1 bit */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64SHR4 ( + QUADLIB_I64 /*I*/ value) + { + QUADLIB_I64_SHR4_EQ_INLINE (value); + + return value; + + } /* QuadLibI64SHR4 */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64SHR4 */ +/* shift an unsigned 64-bit value right by 1 bit */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHR4 ( + QUADLIB_U64 /*I*/ value) + { + QUADLIB_U64_SHR4_EQ_INLINE (value); + + return value; + + } /* QuadLibU64SHR4 */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64SHL4 */ +/* shift an unsigned 64-bit value left by 1 bit */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64SHL4 ( + QUADLIB_U64 /*I*/ value) + { + QUADLIB_U64_SHL4_EQ_INLINE (value); + + return value; + + } /* QuadLibU64SHL4 */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64Mul10 */ +/* multiple an unsigned 64-bit value by 10 */ +/* method: get value*2 and value*8 by shifting, and then add them */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Mul10 ( + QUADLIB_U64 /*I*/ value) + { + QUADLIB_U64 value2; + QUADLIB_U64 value8; + QUADLIB_U64 result; + + value2 = value; + QUADLIB_U64_SHL1_EQ_INLINE (value2); + + value8 = value2; + QUADLIB_U64_SHL1_EQ_INLINE (value8); + QUADLIB_U64_SHL1_EQ_INLINE (value8); + + result = QuadLibU64Add (value8, value2); + return result; + + } /* QuadLibU64Mul10 */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* StrAToQuadLibU64 */ +/* define a portable 64-bit unsigned atoi convervion */ +/*****************************************************************************/ + +/* StrAToQuadLibU64 always defined */ + +QUADLIB_STATIC QUADLIB_U64 StrAToQuadLibU64 ( + char * /*I*/ str) + { + /* extract a decimal string and return unsigned int64 value */ + + QUADLIB_U64 result = QUADLIB_ZERO; + QUADLIB_U64 digit = QUADLIB_ZERO; + int32_t n; + + if (str == NULL) + { + return result; + } + + while (isspace (*str)) + { + str++; /* skip over whitespace */ + } + + /* handle hex value if present */ + + if ( (str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X')) ) + { + for (str+=2; *str; str++) + { + n = *str; + + if ((n >= '0') && (n <= '9')) + { + n -= '0'; + } + + else if ((n >= 'A') && (n <= 'F')) + { + n = n - 'A' + 10; + } + + else if ((n >= 'a') && (n <= 'f')) + { + n = n - 'a' + 10; + } + + else + { + break; + } + + QUADLIB_I64_LO(digit) = n; + QUADLIB_U64_SHL1_EQ_INLINE (result); + QUADLIB_U64_ADD_EQ (result, digit); + } /* for */ + + return result; + } + + for (; *str; str++) + { + n = (*str) - '0'; + + if ((n < 0) || (n > 9)) + { + break; + } + + QUADLIB_I64_LO(digit) = n; + QUADLIB_U64_MUL10_EQ (result); + QUADLIB_U64_ADD_EQ (result, digit); + } + + return result; + + } /* StrAToQuadLibU64 */ + +/* StrAToQuadLibU64 always defined */ + +/*****************************************************************************/ +/* StrAToQuadLibI64 */ +/* define a portable 64-bit signed atoi convervion */ +/*****************************************************************************/ + +/* StrAToQuadLibI64 always defined */ + +QUADLIB_STATIC QUADLIB_I64 StrAToQuadLibI64 ( + char * /*I*/ str) + { + /* extract a decimal string and return unsigned int64 value */ + + QUADLIB_I64 result = QUADLIB_ZERO; + QUADLIB_I64 digit = QUADLIB_ZERO; + char sign = ' '; + int32_t n; + + if (str == NULL) + { + return result; + } + + while (isspace (*str)) + { + str++; /* skip over whitespace */ + } + + if ((*str == '+') || (*str == '-')) + { + sign = *str; + str++; /* skip over sign */ + } + + /* handle hex value if present */ + + if ( (str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X')) ) + { + for (str+=2; *str; str++) + { + n = *str; + + if ((n >= '0') && (n <= '9')) + { + n -= '0'; + } + + else if ((n >= 'A') && (n <= 'F')) + { + n = n - 'A' + 10; + } + + else if ((n >= 'a') && (n <= 'f')) + { + n = n - 'a' + 10; + } + + else + { + break; + } + + QUADLIB_I64_LO(digit) = n; + QUADLIB_U64_SHL1_EQ_INLINE (result); + QUADLIB_U64_ADD_EQ (result, digit); + } /* for */ + + if (sign == '-') + { + result = QUADLIB_I64_NEG (result); + } + + return result; + } + + for (; *str; str++) + { + n = (*str) - '0'; + + if ((n < 0) || (n > 9)) + { + break; + } + + QUADLIB_I64_LO(digit) = n; + QUADLIB_I64_MUL10_EQ (result); + QUADLIB_I64_ADD_EQ (result, digit); + } + + if (sign == '-') + { + result = QUADLIB_I64_NEG (result); + } + + return result; + + } /* StrAToQuadLibI64 */ + +/* StrAToQuadLibI64 always defined */ + + +/*****************************************************************************/ +/* QuadLibU64ToFixedStrA */ +/* define a portable 64-bit unsigned itoa convervion */ +/*****************************************************************************/ + +/* QuadLibU64ToFixedStrA always defined */ + +QUADLIB_STATIC void QuadLibU64ToFixedStrA ( + QUADLIB_U64 /*I*/ qValue, + QUADLIB_STRINGA * /*O*/ pString) + { + QUADLIB_U64 value = qValue; + int32_t i; + int32_t n; + + int32_t xdigit; + uint8_t sum [QUADLIB_STRING_LEN] = {0}; + uint8_t carry; + + char * factor; + static char * factor_table[16] = + { + "00000000000000000001", + "00000000000000000016", + "00000000000000000256", + "00000000000000004096", + "00000000000000065536", + "00000000000001048576", + "00000000000016777216", + "00000000000268435456", + "00000000004294967296", + "00000000068719476736", + "00000001099511627776", + "00000017592186044416", + "00000281474976710656", + "00004503599627370496", + "00072057594037927936", + "01152921504606846976", + }; + + /* grab 16 hex digits one at a time */ + /* obtain the decimal factor for a '1' in that position */ + /* multiply each decimal digit of the factor by the hex digit */ + /* and add to sum */ + + for (i=0; i < 16; i++) + { + if (QUADLIB_U64_EQ_0 (value)) + { + break; + } + + xdigit = QUADLIB_U64_LO (value) & 0x0F; + QUADLIB_U64_SHR4_EQ (value); + + if (xdigit == 0) + { + continue; /* nothing to do */ + } + + factor = factor_table [i]; + + /* highest value in any position is (15*9)+9 = 135+9 = 144 */ + /* with a carry in of 9, the highest value is 153 */ + /* recall that factor is ASCII when calculating the sum */ + + carry = 0; + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4244) +/* silence the VC compiler warning message: */ +/* "conversion from 'int ' to 'unsigned __int8', possible loss of data" */ +#endif + + for (n = QUADLIB_STRING_LEN-1; n >= 0; n--) + { + sum[n] += (uint8_t) (((factor[n] & 0x0F) * xdigit) + carry); + carry = sum[n] / 10; + sum[n] %= 10; + } + } + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + /* copy sum to output, converting to ASCII */ + + for (n = 0; n < QUADLIB_STRING_LEN; n++) + { + pString->str[n] = (char) ((sum[n] & 0x0F) + '0'); + } + + pString->str[QUADLIB_STRING_LEN] = 0; + + } /* QuadLibU64ToFixedStrA */ + + +/*****************************************************************************/ +/* QuadLibI64ToFixedStrA */ +/* define a portable 64-bit signed itoa convervion */ +/*****************************************************************************/ + +/* QuadLibI64ToFixedStrA always defined */ + +QUADLIB_STATIC void QuadLibI64ToFixedStrA ( + QUADLIB_I64 /*I*/ qValue, + QUADLIB_STRINGA * /*O*/ pString) + { + char sign = '0'; + + if (QUADLIB_I64_LT_0 (qValue)) + { + qValue = QUADLIB_I64_NEG (qValue); + sign = '-'; + } + + QuadLibU64ToFixedStrA (* (QUADLIB_U64 *) &qValue, pString); + pString->str[0] = sign; + + } /* QuadLibI64ToFixedStrA */ + + +/*****************************************************************************/ +/* QuadLibU64ToStrA */ +/* define a portable 64-bit signed itoa convervion, with zero suppression */ +/*****************************************************************************/ + +/* QuadLibU64ToStrA always defined */ + +QUADLIB_STATIC void QuadLibU64ToStrA ( + QUADLIB_U64 /*I*/ qValue, + QUADLIB_STRINGA * /*O*/ pString) + { + QUADLIB_STRINGA s; + int32_t source = 0; + int32_t target = 0; + + QuadLibU64ToFixedStrA (qValue, &s); + + /* copy back value, suppressing leading zeros */ + + while (s.str [source] == '0') + { + source++; + } + + if (s.str [source] == 0) + { + pString->str [target++] = '0'; /* source is all zero */ + } + + while (s.str [source]) + { + pString->str [target++] = s.str [source++]; + } + + pString->str [target] = 0; + + } /* QuadLibU64ToStrA */ + + +/*****************************************************************************/ +/* QuadLibI64ToStrA */ +/* define a portable 64-bit signed itoa convervion, with zero suppression */ +/*****************************************************************************/ + +/* QuadLibI64ToStrA always defined */ + +QUADLIB_STATIC void QuadLibI64ToStrA ( + QUADLIB_I64 /*I*/ qValue, + QUADLIB_STRINGA * /*O*/ pString) + { + QUADLIB_STRINGA s; + int32_t source = 0; + int32_t target = 0; + + QuadLibI64ToFixedStrA (qValue, &s); + + /* copy back value, suppressing leading zeros */ + + if (s.str [source] == '-') + { + pString->str [target++] = s.str [source++]; + } + + while (s.str [source] == '0') + { + source++; + } + + if (s.str [source] == 0) + { + pString->str [target++] = '0'; /* source is all zero */ + } + + while (s.str [source]) + { + pString->str [target++] = s.str [source++]; + } + + pString->str [target] = 0; + + } /* QuadLibI64ToStrA */ + + +/*****************************************************************************/ +/* QuadLibU64DivMod */ +/* divide two unsigned 64-bit values to produce a quotient and remainder */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64DivMod ( + QUADLIB_U64 u64Dividend, + QUADLIB_U64 u64Divisor, + QUADLIB_U64 *pu64Remainder ) + { + int32_t Count; + QUADLIB_U64 A_restore; + + QUADLIB_U64 A = QUADLIB_ZERO; + QUADLIB_U64 M = u64Divisor; + QUADLIB_U64 Q = u64Dividend; + + + if ((u64Divisor.hi.u == 0) + && (u64Divisor.lo.u == 0)) + { + *pu64Remainder = A; /* 0 */ + return A; /* 0 */ + } + + + for (Count=64; Count; Count--) + { + /* shift A:Q left */ + + QUADLIB_U64_SHL1_EQ_INLINE (A); + + if (Q.hi.i < 0) /* Q has high-order 1 bit */ + { + A = QuadLibU64Add1(A); /* A gets low-order 1 bit */ + } + + QUADLIB_U64_SHL1_EQ_INLINE (Q); /* Q gets low-order 0 bit */ + + A_restore = A; + + A = QuadLibU64Sub(A, M); + + if (A.hi.i < 0) /* A has high-order 1 bit */ + { + A = A_restore; /* Q has low-order 0 bit */ + } + + else + { + Q = QuadLibU64Add1(Q); /* Q gets low-order 1 bit */ + } + + } /* for */ + + *pu64Remainder = A; + return Q; + + } /* QuadLibU64DivMod */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64Div */ +/* divide two signed 64-bit values to produce an unsigned quotient */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Div ( + QUADLIB_U64 u64Dividend, + QUADLIB_U64 u64Divisor) + { + QUADLIB_U64 u64Remainder; /* dummy argument */ + + return QuadLibU64DivMod (u64Dividend, u64Divisor, &u64Remainder); + + } /*QuadLibU64Div */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64Mod */ +/* divide two signed 64-bit values to produce unsigned remainder (modulus) */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Mod ( + QUADLIB_U64 u64Dividend, + QUADLIB_U64 u64Divisor) + { + QUADLIB_U64 u64Remainder; + + QuadLibU64DivMod (u64Dividend, u64Divisor, &u64Remainder); + + return u64Remainder; + + } /*QuadLibU64Mod */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibI64DivMod */ +/* divide two signed 64-bit values to produce a quotient and remainder */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64DivMod ( + QUADLIB_I64 s64Dividend, + QUADLIB_I64 s64Divisor, + QUADLIB_I64 *ps64Remainder ) + { + QUADLIB_I64 s64Quotient; + QUADLIB_U64 u64Dividend; + QUADLIB_U64 u64Divisor; + int32_t sign = 0; + + if (s64Dividend.hi.i < 0) + { + u64Dividend = QUADLIB_I64_NEG (s64Dividend); + sign = 1; + } + + else + { + u64Dividend = s64Dividend; + } + + if (s64Divisor.hi.i < 0) + { + u64Divisor = QUADLIB_I64_NEG (s64Divisor); + sign ^= 1; + } + + else + { + u64Divisor = s64Divisor; + } + + s64Quotient = QuadLibU64DivMod (u64Dividend, u64Divisor, ps64Remainder); + + if (sign) + { + /* signs of dividend and divisor are different, result is neg */ + s64Quotient = QUADLIB_I64_NEG (s64Quotient); + } + + /* remainder takes sign of dividend */ + + if (s64Dividend.hi.i < 0) + { + *ps64Remainder = QUADLIB_I64_NEG (*ps64Remainder); + } + + return s64Quotient; + +} /* QuadLibI64DivMod */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibI64Div */ +/* divide two signed 64-bit values to produce a signed quotient */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64Div ( + QUADLIB_I64 s64Dividend, + QUADLIB_I64 s64Divisor) + { + QUADLIB_U64 s64Remainder; /* dummy argument */ + + return QuadLibI64DivMod (s64Dividend, s64Divisor, &s64Remainder); + + } /*QuadLibI64Div */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibI64Mod */ +/* divide two signed 64-bit values to produce a signed remainder (modulus) */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64Mod ( + QUADLIB_I64 s64Dividend, + QUADLIB_I64 s64Divisor) + { + QUADLIB_I64 s64Remainder; + + QuadLibI64DivMod (s64Dividend, s64Divisor, &s64Remainder); + + return s64Remainder; + + } /*QuadLibI64Mod */ + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* QuadLibU64DivMod - COMPATIBILITY MODE */ +/* QuadLibI64DivMod - COMPATIBILITY MODE */ +/* native I64 divide/modulus functions with I64 simulation not in effect */ +/*****************************************************************************/ + +#ifndef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64DivMod ( + QUADLIB_U64 u64Dividend, + QUADLIB_U64 u64Divisor, + QUADLIB_U64 *pu64Remainder) + { + if (pu64Remainder != NULL) + { + *pu64Remainder = u64Dividend % u64Divisor; + } + + return u64Dividend / u64Divisor; + + } /* QuadLibU64DivMod */ + +QUADLIB_STATIC QUADLIB_I64 QuadLibI64DivMod ( + QUADLIB_I64 s64Dividend, + QUADLIB_I64 s64Divisor, + QUADLIB_I64 *ps64Remainder) + { + if (ps64Remainder != NULL) + { + *ps64Remainder = s64Dividend % s64Divisor; + } + + return s64Dividend / s64Divisor; + + } /* QuadLibI64DivMod */ + +#endif /* not QUADLIB_ENABLED */ + + +/*****************************************************************************/ +/* AND */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64And ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two) + { + QUADLIB_U64 result; + + result.hi.u = one.hi.u & two.hi.u; + result.lo.u = one.lo.u & two.lo.u; + + return result; + } + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64AndNot ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two) + { + QUADLIB_U64 result; + + result.hi.u = one.hi.u & (~two.hi.u); + result.lo.u = one.lo.u & (~two.lo.u); + + return result; + } + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* OR */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Or ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two) + { + QUADLIB_U64 result; + + result.hi.u = one.hi.u | two.hi.u; + result.lo.u = one.lo.u | two.lo.u; + + return result; + } + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64OrNot ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two) + { + QUADLIB_U64 result; + + result.hi.u = one.hi.u | (~two.hi.u); + result.lo.u = one.lo.u | (~two.lo.u); + + return result; + } + +#endif /* QUADLIB_ENABLED */ + +/*****************************************************************************/ +/* XOR */ +/*****************************************************************************/ + +#ifdef QUADLIB_ENABLED + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64Xor ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two) + { + QUADLIB_U64 result; + + result.hi.u = one.hi.u ^ two.hi.u; + result.lo.u = one.lo.u ^ two.lo.u; + + return result; + } + +QUADLIB_STATIC QUADLIB_U64 QuadLibU64XorNot ( + QUADLIB_U64 /*I*/ one, + QUADLIB_U64 /*I*/ two) + { + QUADLIB_U64 result; + + result.hi.u = one.hi.u ^ (~two.hi.u); + result.lo.u = one.lo.u ^ (~two.lo.u); + + return result; + } + +#endif /* QUADLIB_ENABLED */ + diff --git a/mmslib/util/stdtime_w32.c b/mmslib/util/stdtime_w32.c new file mode 100644 index 0000000..05d358a --- /dev/null +++ b/mmslib/util/stdtime_w32.c @@ -0,0 +1,1348 @@ +/*****************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER **********************************************/ +/*****************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2005 All Rights Reserved */ +/* */ +/* MODULE NAME : StdTimeW32.h */ +/* PRODUCT(S) : Standard Time Management Library */ +/* */ +/* MODULE DESCRIPTION: */ +/* Implementation of Standard Time Management Library Win32 Compatibility */ +/* Layer. This module is compiled with STDTIMEW32_ENABLED on Windows to */ +/* generate debugging code or to run emulation on Unix. To run on */ +/* Windows, compile with STDTIMEW32_DISABLED. STDTIMEW32_ENABLED is */ +/* required on Unix/Linux (that is, non-Windows) platforms. */ +/* */ +/* MODIFICATION LOG: */ +/* Date Who Rev Comments */ +/* -------- --- --- ----------------------------------------------------- */ +/* 05/16/08 JRB 07 Fix DST adjustment in StdTimeW32LocalFileTimeToFileTime*/ +/* 04/08/08 JRB 06 Chg FILETIME to portable STDTIME_WIN_FILETIME. */ +/* 02/20/08 JRB 05 Use new simpler "TimeTypeEx", "StructTmEx" functions. */ +/* 03/18/07 RLH 04 Enable GMT vs. LOC conversions to work on QNX; */ +/* fix bug in Bool_StdTimeGmTimeR. */ +/* 11/21/06 RLH 03 StdTimeRet no longer static, now in stdtime.c */ +/* 06/07/06 RLH 02 Numerous features added, see stdtime.doc */ +/* 01/18/06 RLH 01 Created */ +/*****************************************************************************/ + +#include "stdtime.h" + +#define STDTIMEW32_FT_TIMET_SCALE 10000000 +#define STDTIMEW32_FT_TIMET_BASE_HI 0x019DB1DE +#define STDTIMEW32_FT_TIMET_BASE_LO 0xD53E8000 + + +/*-***************************************************************************/ +/* Bool_StdTimeGmTimeR - PRIVATE FUNCTION */ +/* provide interface for gmtime_r where possible, otherwise gmtime. */ +/* we provide thread safety for this function, if the operating system and */ +/* runtime library allows for it. */ +/*****************************************************************************/ + +STDTIME_BOOL Bool_StdTimeGmTimeR ( + time_t * pTimeT, + struct tm * pStructTm) + { + + if ((pTimeT == NULL) || (pStructTm == NULL)) + { + return STDTIME_FALSE; + } + + +#ifdef STDTIME_REENTRANT_GMTIME_LOCALTIME + + if (gmtime_r (pTimeT, pStructTm) != 0) + { + return STDTIME_TRUE; + } + + return STDTIME_FALSE; + + +#elif defined(STDTIME_MSVC8) + + +#ifdef _USE_64BIT_TIME_T + if (_gmtime64_s (pStructTm, (__time64_t *) pTimeT) == 0) + { + return STDTIME_TRUE; + } + + return STDTIME_FALSE; + + +#else /* not _USE_64BIT_TIME_T */ + + if (_gmtime32_s (pStructTm, (__time32_t *) pTimeT) == 0) + { + return STDTIME_TRUE; + } + + return STDTIME_FALSE; + +#endif /* _USE_64BIT_TIME_T */ + + +#else /* no reentrant gmtime available */ + + { + struct tm * pTempTm = NULL; + + pTempTm = gmtime (pTimeT); + + if (pTempTm == NULL) + { + return STDTIME_FALSE; + } + + /* copy back to caller */ + *pStructTm = *pTempTm; + + return STDTIME_TRUE; + } + +#endif + + } /* Bool_StdTimeGmTimeR */ + + +/*-***************************************************************************/ +/* Bool_StdTimeLocalTimeR - PRIVATE FUNCTION */ +/* provide interface for localtime_r where possible, otherwise localtime. */ +/* we provide thread safety for this function, if the operating system and */ +/* runtime library allows for it. */ +/*****************************************************************************/ + +STDTIME_BOOL Bool_StdTimeLocalTimeR ( + time_t * pTimeT, + struct tm * pStructTm) + { + + if ((pTimeT == NULL) || (pStructTm == NULL)) + { + return STDTIME_FALSE; + } + + +#ifdef STDTIME_REENTRANT_GMTIME_LOCALTIME + + if (localtime_r (pTimeT, pStructTm) != 0) + { + return STDTIME_TRUE; + } + + return STDTIME_FALSE; + + +#elif defined(STDTIME_MSVC8) + + +#ifdef _USE_64BIT_TIME_T + if (_localtime64_s (pStructTm, (__time64_t *) pTimeT) == 0) + { + return STDTIME_TRUE; + } + + return STDTIME_FALSE; + + +#else /* not _USE_64BIT_TIME_T */ + + if (_localtime32_s (pStructTm, (__time32_t *) pTimeT) == 0) + { + return STDTIME_TRUE; + } + + return STDTIME_FALSE; + +#endif /* _USE_64BIT_TIME_T */ + + +#else /* no reentrant localtime available */ + + { + struct tm * pTempTm = NULL; + + pTempTm = localtime (pTimeT); + + if (pTempTm == NULL) + { + return STDTIME_FALSE; + } + + /* copy back to caller */ + *pStructTm = *pTempTm; + + return STDTIME_TRUE; + } + +#endif + + } /* Bool_StdTimeLocalTimeR */ + + +#if 0 /* Int_StdTimeLocalDiff is obsolete */ + +/* function is obsolete as of 2007-03-18, will be removed in future release. */ + +/*-***************************************************************************/ +/* Int_StdTimeLocalDiff - PRIVATE FUNCTION */ +/* get difference in minutes of (GMT time) - (local time) */ +/* in case gmtime() or localtime() fails, return 0 */ +/*****************************************************************************/ + +static int32_t Int_StdTimeLocalDiff () + { + time_t gmt_time_t; + struct tm locTm; + struct tm gmtTm; + + int32_t locDay; + int32_t gmtDay; + int32_t locMin; + int32_t gmtMin; + int32_t diff; + + /* problem with this logic is that 'time(NULL)' returns current time */ + /* so calculation of LOC vs. GMT is based on current time instead of */ + /* the time value being converted. */ + + gmt_time_t = time(NULL); + + if (! Bool_StdTimeLocalTimeR (&gmt_time_t, &locTm)) + { + return 0; + } + + locDay = ((locTm.tm_year) * 10000) + ((locTm.tm_mon) * 100) + +(locTm.tm_mday); + + locMin = ((locTm.tm_hour) * 60) + locTm.tm_min; + + if (! Bool_StdTimeGmTimeR (&gmt_time_t, &gmtTm)) + { + return 0; + } + + gmtDay = ((gmtTm.tm_year) * 10000) + ((gmtTm.tm_mon) * 100) + +(gmtTm.tm_mday); + + gmtMin = ((gmtTm.tm_hour) * 60) + gmtTm.tm_min; + + if (locDay == gmtDay) + { + /* loc and gmt are in same day */ + diff = gmtMin - locMin; + } + + else if (gmtDay > locDay) + { + /* gmtDay > locDay, so gmtMin < locMin */ + + /* example: 2006-01-01 23:00 EST = 2006-01-02 04:00 GMT */ + /* 04:00 GMT - 23:00 EST = difference of -19:00 but that is wrong. */ + /* it should be a difference of +05:00 */ + + /* to correct, calculate (04:00+24:00) GMT - 23:00 EST = +05:00 */ + /* note that adjustment is made in minutes */ + + diff = (gmtMin + 1440) - locMin; + } + + else + { + /* gmtDay < locDay, so gmtMin > locMin */ + + /* example: 2006-01-02 01:00 MSK = 2006-01-01 22:00 GMT */ + /* 22:00 GMT - 01:00 MSK = difference of +21:00 but that is wrong. */ + /* it should be a difference of -03:00 */ + + /* to correct, calculate 22:00 GMT - (01:00+24:00) MSK = -03:00 */ + /* note that adjustment is made in minutes */ + + diff = gmtMin - (locMin + 1440); + } + + /* calculated difference value is in minutes */ + /* for EST, diff = GMT-EST = 300 [ 5 hours ] */ + /* for EDT, diff = GMT-EDT = 240 [ 4 hours ] */ + + return diff; + + } /* Int_StdTimeLocalDiff */ + +#endif /* Int_StdTimeLocalDiff is obsolete */ + + +/*****************************************************************************/ +/* StdTimeW32FileTimeToLocalFileTime */ +/* portable implementation of WIN32 API FileTimeToLocalFileTime */ +/*****************************************************************************/ + + +STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32FileTimeToLocalFileTime ( + const STDTIME_WIN_FILETIME * /*I*/ pGmtFileTime, + STDTIME_WIN_FILETIME * /*O*/ pLocFileTime) + { + STDTIME gmtStdTime; + STDTIME locStdTime; + STDTIME_RC rc; + time_t gmtTimeT; + + struct tm * pStructTm; + struct tm locStructTm; + int32_t nsec; + + if ((pGmtFileTime == NULL) || (pLocFileTime == NULL)) + { + return STDTIME_WIN_FALSE; + } + + rc = FileTimeToStdTime (pGmtFileTime, &gmtStdTime); + + if (rc != STDTIME_OK) + return STDTIME_WIN_FALSE; + + rc = StdTimeToTimeTypeEx (&gmtStdTime, &gmtTimeT, &nsec); + + if (rc != STDTIME_OK) + return STDTIME_WIN_FALSE; + + pStructTm = localtime (&gmtTimeT); + + if (pStructTm == NULL) + return STDTIME_WIN_FALSE; + + locStructTm = *pStructTm; + + rc = StructTmExToStdTime (&locStructTm, nsec, &locStdTime); + + if (rc != STDTIME_OK) + return STDTIME_WIN_FALSE; + + rc = StdTimeToFileTime (&locStdTime, pLocFileTime); + + if (rc != STDTIME_OK) + return STDTIME_WIN_FALSE; + + return STDTIME_WIN_TRUE; + + } /* StdTimeW32FileTimeToLocalFileTime */ + + +/*****************************************************************************/ +/* StdTimeW32LocalFileTimeToFileTime */ +/* portable implementation of WIN32 API LocalFileTimeToFileTime */ +/*****************************************************************************/ + + +STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32LocalFileTimeToFileTime ( + const STDTIME_WIN_FILETIME * /*I*/ pLocFileTime, + STDTIME_WIN_FILETIME * /*O*/ pGmtFileTime) + { + STDTIME gmtStdTime; + STDTIME locStdTime; + STDTIME_RC rc; + time_t gmtTimeT; + + struct tm locStructTm; + int32_t nsec; + + + if ((pGmtFileTime == NULL) || (pLocFileTime == NULL)) + { + return STDTIME_WIN_FALSE; + } + + rc = FileTimeToStdTime (pLocFileTime, &locStdTime); + + if (rc != STDTIME_OK) + return STDTIME_WIN_FALSE; + + rc = StdTimeToStructTmEx (&locStdTime, &locStructTm, &nsec); + + if (rc != STDTIME_OK) + return STDTIME_WIN_FALSE; + + locStructTm.tm_isdst = -1; /* CRITICAL: make OS figure out if DST */ + gmtTimeT = mktime (&locStructTm); + + if (gmtTimeT == (time_t) (-1)) + return STDTIME_WIN_FALSE; + + rc = TimeTypeExToStdTime (gmtTimeT, nsec, &gmtStdTime); + + if (rc != STDTIME_OK) + return STDTIME_WIN_FALSE; + + rc = StdTimeToFileTime (&gmtStdTime, pGmtFileTime); + + if (rc != STDTIME_OK) + return STDTIME_WIN_FALSE; + + return STDTIME_WIN_TRUE; + + } /* StdTimeW32LocalFileTimeToFileTime */ + + +/*****************************************************************************/ +/* StdTimeW32_IsLeap - return 1 if leap year, else 0 */ +/*****************************************************************************/ + + +STDTIMEW32_STATIC int StdTimeW32_IsLeap (int year) + { + if ((year < 0 ) || (year > 32767)) + { + return 0; + } + + if ((year % 4000) == 0) + { + return 0; /* multiples of 4000 are not leap years */ + } + + if ((year % 400) == 0) + { + return 1; /* multiples of 400 are leap years */ + } + + if ((year % 100) == 0) + { + return 0; /* multiples of 100 are not leap years */ + } + + if ((year % 4) == 0) + { + return 1; /* multiples of 4 are leap years */ + } + + return 0; /* all others are not leap years */ + + } /* StdTimeW32_IsLeap */ + + +/*****************************************************************************/ +/* StdTimeW32_LeapYearDays - number leap-year days based on year y */ +/*****************************************************************************/ + + +STDTIMEW32_STATIC int StdTimeW32_LeapYearDays (int y) + { + /* number of 4000-year multiples */ + int n4000 = (y / 4000); + + /* number of 400-year multiples in excess of 4000 */ + int n400 = (y % 4000) / 400; + + /* number of 100-year multiples in excess of 400 */ + int n100 = (y % 400) / 100; + + /* number of 4-year multiples in excess of 100 */ + int n4 = (y % 100) / 4; + + return + ( 969 * n4000 ) + + ( 97 * n400 ) + + ( 24 * n100 ) + + ( 1 * n4 ); + + } /* StdTimeW32_LeapYearDays */ + + +/*****************************************************************************/ +/* days-per-month table */ +/*****************************************************************************/ + + +static int StdTimeW32_DaysPerMon [13] = + { 00, + 31, /* JAN */ + 28, /* FEB */ + 31, /* MAR */ + 30, /* APR */ + 31, /* MAY */ + 30, /* JUN */ + 31, /* JUL */ + 31, /* AUG */ + 30, /* SEP */ + 31, /* OCT */ + 30, /* NOV */ + 31 /* DEC */ + }; + + +/*****************************************************************************/ +/* StdTimeW32SystemTimeToFileTimeEx */ +/* portable implementation of WIN32 API SystemTimeToFileTime */ +/*****************************************************************************/ + + +STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32SystemTimeToFileTimeEx ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + STDTIME_WIN_FILETIME * /*O*/ pFileTime, + int /*I*/ nsec, + int /*I*/ usec) + { + QUADLIB_U64 uVal; + QUADLIB_U64 uNum; + + STDTIME_WIN_SYSTEMTIME st; + STDTIME_WIN_FILETIME ft; + + + int i; + int d; + int basedays; + + if ((pSystemTime == NULL) || (pFileTime == NULL)) + { + return STDTIME_WIN_FALSE; + } + + st = *pSystemTime; + + /* form # of days for year - will not overflow uVal.lo */ + + QUADLIB_U64_HI(uVal) = 0; + QUADLIB_I64_LO(uVal) = (365 * st.wYear) + StdTimeW32_LeapYearDays (st.wYear); + + /* convert year/mon to days */ + + d = st.wDay; + + for (i=1; i < st.wMonth; i++) + { + d += StdTimeW32_DaysPerMon [i]; + } + + if (st.wMonth > 2) + { + d += StdTimeW32_IsLeap (st.wYear); + } + + /* calculate: uVal += (d - basedays - 1) */ + /* == uVal = uVal + d - basedays - 1 == uVal + d - (basedays + 1); */ + + /* use the equivalence above to avoid one QUADLIB operation, since */ + /* there is an overhead to using them under simulation. */ + + QUADLIB_U64_HI(uNum) = 0; + + QUADLIB_I64_LO(uNum) = d; + QUADLIB_U64_ADD_EQ (uVal, uNum); + + basedays = (STDTIME_WIN_EPOCH_YEAR * 365) + + StdTimeW32_LeapYearDays(STDTIME_WIN_EPOCH_YEAR); + + QUADLIB_I64_LO(uNum) = basedays + 1; + QUADLIB_U64_SUB_EQ (uVal, uNum); + + /* calculate: uVal = (uVal * 24) + st.wHour; */ + + QUADLIB_U64_LO(uNum) = 24; + QUADLIB_U64_MUL_EQ (uVal, uNum); + + QUADLIB_U64_LO(uNum) = st.wHour; + QUADLIB_U64_ADD_EQ (uVal, uNum); + + /* calculate: uVal = (uVal * 60) + st.wMinute; */ + + QUADLIB_U64_LO(uNum) = 60; + QUADLIB_U64_MUL_EQ (uVal, uNum); + + QUADLIB_U64_LO(uNum) = st.wMinute; + QUADLIB_U64_ADD_EQ (uVal, uNum); + + /* calculate: uVal = (uVal * 60) + st.wSecond; */ + + QUADLIB_U64_LO(uNum) = 60; + QUADLIB_U64_MUL_EQ (uVal, uNum); + + QUADLIB_U64_LO(uNum) = st.wSecond; + QUADLIB_U64_ADD_EQ (uVal, uNum); + + /* calculate: uVal = (uVal * 1000) + st.wMilliseconds; */ + + QUADLIB_U64_LO(uNum) = 1000; + QUADLIB_U64_MUL_EQ (uVal, uNum); + + QUADLIB_U64_LO(uNum) = st.wMilliseconds; + QUADLIB_U64_ADD_EQ (uVal, uNum); + + /* calculate: uVal = (uVal * 1000) + usec; */ + + QUADLIB_U64_LO(uNum) = 1000; + QUADLIB_U64_MUL_EQ (uVal, uNum); + + QUADLIB_U64_LO(uNum) = usec; + QUADLIB_U64_ADD_EQ (uVal, uNum); + + /* calculate: uVal = (uVal * 10) + (nsec/100); */ + + QUADLIB_U64_LO(uNum) = 10; + QUADLIB_U64_MUL_EQ (uVal, uNum); + + QUADLIB_U64_LO(uNum) = (nsec/100); + QUADLIB_U64_ADD_EQ (uVal, uNum); + + ft.dwLowDateTime = QUADLIB_U64_LO(uVal); + ft.dwHighDateTime = QUADLIB_U64_HI(uVal); + + *pFileTime = ft; + return STDTIME_WIN_TRUE; + + } /* StdTimeW32SystemTimeToFileTimeEx */ + + +/*****************************************************************************/ +/* StdTimeW32SystemTimeToFileTime */ +/* portable implementation of WIN32 API SystemTimeToFileTime */ +/* convert SYSTEMTIME to FILETIME; usec and nsec values default to zero */ +/*****************************************************************************/ + + +STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32SystemTimeToFileTime ( + const STDTIME_WIN_SYSTEMTIME * /*I*/ pSystemTime, + STDTIME_WIN_FILETIME * /*O*/ pFileTime) + { + return StdTimeW32SystemTimeToFileTimeEx (pSystemTime, pFileTime, 0, 0); + + } /* StdTimeW32SystemTimeToFileTime */ + + +/*****************************************************************************/ +/* StdTimeW32FileTimeToSystemTime */ +/* portable implementation of WIN32 API FileTimeToSystemTime */ +/*****************************************************************************/ + + +STDTIMEW32_STATIC STDTIME_WIN_BOOL StdTimeW32FileTimeToSystemTime ( + const STDTIME_WIN_FILETIME * /*I*/ pFileTime, + STDTIME_WIN_SYSTEMTIME * /*O*/ pSystemTime) + { + QUADLIB_U64 uVal; + QUADLIB_U64 uMod; + QUADLIB_U64 uDiv; + + STDTIME_WIN_SYSTEMTIME st; + STDTIME_WIN_FILETIME ft; + + int yday; + int max_yday; + int day; + int mon; + int nsec; + int usec; + int days; + int year; + int year_hi; + int year_lo; + int leap; + int dpm; + int basedays; + int workdays; + + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4244) +/* silence the VC compiler warning message: */ +/* "conversion from 'int' to 'WORD', possible loss of data" */ +#endif + + + if ((pSystemTime == NULL) || (pFileTime == NULL)) + { + return STDTIME_WIN_FALSE; + } + + ft = *pFileTime; + + QUADLIB_U64_HI(uVal) = ft.dwHighDateTime; + QUADLIB_U64_LO(uVal) = ft.dwLowDateTime; + + /* uVal has count of 100 nsecs intervals */ + /* calculate: nsec = (uVal % 10) * 100; */ + + QUADLIB_U64_HI(uDiv) = 0; + QUADLIB_U64_LO(uDiv) = 10; + uVal = QuadLibU64DivMod (uVal, uDiv, &uMod); + nsec = QUADLIB_I64_LO(uMod) * 100; + + /* uVal has usecs */ + /* calculate: usec = uVal % 1000; */ + + QUADLIB_U64_LO(uDiv) = 1000; + uVal = QuadLibU64DivMod (uVal, uDiv, &uMod); + usec = QUADLIB_I64_LO(uMod); + + /* uVal has msecs */ + /* calculate: wMilliseconds = uVal % 1000; */ + /* QUADLIB_U64_LO(uDiv) = 1000; ==> still in effect */ + + uVal = QuadLibU64DivMod (uVal, uDiv, &uMod); + st.wMilliseconds = QUADLIB_U64_LO(uMod); + + /* uVal has secs */ + /* calculate: wSecond = uVal % 60; */ + + QUADLIB_U64_LO(uDiv) = 60; + uVal = QuadLibU64DivMod (uVal, uDiv, &uMod); + st.wSecond = QUADLIB_U64_LO(uMod); + + /* uVal has mins */ + /* calculate: wMinute = uVal % 60; */ + /* QUADLIB_U64_LO(uDiv) = 60; ==> still in effect */ + + uVal = QuadLibU64DivMod (uVal, uDiv, &uMod); + st.wMinute = QUADLIB_U64_LO(uMod); + + /* uVal has hours */ + /* calculate: wHour = uVal % 24; */ + + QUADLIB_U64_LO(uDiv) = 24; + uVal = QuadLibU64DivMod (uVal, uDiv, &uMod); + + st.wHour = QUADLIB_U64_LO(uMod); + + /* uVal has days */ + + days = QUADLIB_I64_LO(uVal); + + /* Jan 1 1601 was a Monday (day number 1) */ + /* determine day of week by adding base day number to relative 0 day */ + /* modulus 7 is the day number */ + + st.wDayOfWeek = (days + 1) % 7; + + /* FT Epoch starts on Jan 1, 1601 */ + /* calculate the number of days prior to FT Epoch */ + /* treating year 0 as a year = start of year 0 to end of year 1600 */ + /* which is 1601 years = 584753 */ + + basedays = (STDTIME_WIN_EPOCH_YEAR * 365) + + StdTimeW32_LeapYearDays(STDTIME_WIN_EPOCH_YEAR); + + workdays = days + basedays; + + /* if we assumed every year were 365 days long, */ + /* then workdays / 365 would calculate too high a year, whereas */ + /* workdays / 366 would calculate too low a year */ + /* determine year by forming an estimated year, then */ + /* calculating its total days until we get the right number */ + + year_hi = (workdays / 365) + 1; + year_lo = (workdays / 366) - 1; + + for (year = year_hi; year > year_lo; year--) + { + days = (year * 365) + StdTimeW32_LeapYearDays (year); + + if (days <= workdays) break; + } + + if (year == year_lo) + { + /* failed to determine year */ + return STDTIME_WIN_FALSE; + } + + st.wYear = year; + + /* if 'days' == 6 (for example), then 6 complete days have */ + /* elapsed, plus the number of fractional days (sec, msec, etc.) */ + /* once fractional days exist, we are into the next day */ + /* from a calendar point of view, the day is 'days+1' even if a */ + /* day isn't over yet. */ + + /* however, at midnight (fractional days are exactly zero) */ + /* it is assumed to be the start of the next day. */ + /* so regardless, the day of year is days+1 always. */ + + yday = workdays - days + 1; + leap = StdTimeW32_IsLeap (year); + max_yday = 365 + leap; + + if ((yday < 1) || (yday > max_yday)) + { + /* yday is invalid for the given year */ + return STDTIME_WIN_FALSE; + } + + day = yday; + + for (mon=1; mon <= 12; mon++) + { + dpm = StdTimeW32_DaysPerMon [mon]; + + if (leap && (mon == 2)) dpm++; + + if (day <= dpm) break; + day -= dpm; + } + + if (mon > 12) + { + /* failed to determine month */ + return STDTIME_WIN_FALSE; + } + + st.wMonth = mon; + st.wDay = day; + + *pSystemTime = st; + + return STDTIME_WIN_TRUE; + + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + + + } /* StdTimeW32FileTimeToSystemTime */ + + +/*****************************************************************************/ +/* StdTimeW32GetDayofWeekAndYear */ +/* get day of week, day of year from year, mon, day of month */ +/* the maximum day number in the STDTIME system is about 3,652,500 */ +/* so, there is no need for 64-bit math in this function, which only */ +/* deals with days as the finest resolution. */ +/*****************************************************************************/ + +STDTIME_RC StdTimeW32GetDayofWeekAndYear ( + int32_t /*I*/ nYear, + int32_t /*I*/ nMon, + int32_t /*I*/ nDayofMon, + int32_t * /*O*/ pDayofWeek, + int32_t * /*O*/ pDayofYear) + { + int32_t n; + int32_t yeardays; + int32_t basedays; + int32_t leap; + + int32_t nDayofWeek; + int32_t nDayofYear; + + STDTIME_ENUM_FUNC (StdTimeW32GetDayofWeekAndYear) + + /* output fields are optional, but at least one must be present */ + /* for the function to be considered successful */ + + if ((pDayofWeek == NULL) && (pDayofYear == NULL)) + { + STDTIME_RET_EC (null_argument); + } + + if ((nYear < STDTIME_YEAR_MIN) + || (nYear > STDTIME_YEAR_MAX)) + { + STDTIME_RET_EC (invalid_year); + } + + if ((nMon < 1) || (nMon > 12)) + { + STDTIME_RET_EC (invalid_mon); + } + + if (nDayofMon < 1) + { + STDTIME_RET_EC (invalid_day); + } + + leap = StdTimeW32_IsLeap (nYear); + n = StdTimeW32_DaysPerMon [nMon]; + + if (nMon == 2) + { + n += leap; + } + + if (nDayofMon > n) + { + STDTIME_RET_EC (invalid_day); + } + + /* form # of days for year - will not overflow 32 bits */ + + yeardays = (365 * nYear) + StdTimeW32_LeapYearDays (nYear-1); + + /* convert year/mon to days */ + + nDayofYear = nDayofMon; + + for (n=1; n < nMon; n++) + { + nDayofYear += StdTimeW32_DaysPerMon [n]; + } + + if (nMon > 2) + { + nDayofYear += leap; + } + + if (pDayofYear != NULL) + { + *pDayofYear = nDayofYear; + } + + if (pDayofWeek == NULL) + { + STDTIME_RET_OK; /* nothing else to do */ + } + + basedays = (STDTIME_WIN_EPOCH_YEAR * 365) + + StdTimeW32_LeapYearDays(STDTIME_WIN_EPOCH_YEAR); + + yeardays += (nDayofYear - basedays - 1); + + /* uNum now contains a day number relative to January 1, 1601. */ + /* it is known that this day was a Monday (day number == 1) */ + /* so, to get day of week, form mod 7 of the day number + 1 */ + /* and add 1 */ + + nDayofWeek = (yeardays + 1) % 7; + *pDayofWeek = nDayofWeek; + + STDTIME_RET_OK; + + } /* StdTimeW32GetDayofWeekAndYear */ + + + +/*****************************************************************************/ +/* gettimeofday() simulation on Win32 systems */ +/*****************************************************************************/ + +#define STDTIMEW32_GETTIMEOFDAY_SUCCESS 0 +#define STDTIMEW32_GETTIMEOFDAY_FAILURE (-1) + +#ifdef STDTIMEW32_USE_GETTIMEOFDAY +#ifdef STDTIMEW32_DEBUGGING + +/* on Unix/Linux systems, gettimeofday() is defined in */ +/* or */ + +#ifndef _WINSOCKAPI_ +struct timeval + { + long tv_sec; /* seconds since Jan 1 1970 */ + long tv_usec; /* microseconds (seconds / 1_000_000) */ + }; +#endif + +STDTIMEW32_STATIC int gettimeofday ( + struct timeval *pTimeVal, void *pObsolete); + +/*****************************************************************************/ +/* */ +/* pObsolete as an argument is obsolete on most Unix/Linux systems, in */ +/* which it is an error to specify a non-NULL value. */ +/* */ +/* gettimeofday() return codes */ +/* rc 0: success */ +/* rc -1: failure, errno set. */ +/* errno: EFAULT pTimeVal points outside the accessible address space. */ +/* errno: EINVAL The structure pointed to by 'pTimeVal' specifies an */ +/* invalid time (not supported here) */ +/* errno: EINVAL pObsolete argument is not NULL */ +/* errno: EOVERFLOW: The system time is greater than 2038, cannot be stored.*/ +/* Windows does not have EOVERFLOW in errno.h; ERANGE could be used, */ +/* but for simulation purposes, this condition is not supported. */ +/* */ +/*****************************************************************************/ + + +#endif /* STDTIMEW32_DEBUGGING */ +#endif /* STDTIMEW32_USE_GETTIMEOFDAY */ + + +/*****************************************************************************/ +/* gettimeofday - simulate Unix/Linux function gettimeofday() */ +/* function is used for debugging purposes only */ +/*****************************************************************************/ + + +#ifdef STDTIMEW32_USE_GETTIMEOFDAY +#ifdef STDTIMEW32_DEBUGGING + + +STDTIMEW32_STATIC int gettimeofday ( + struct timeval *pTimeVal, void *pObsolete) + { + STDTIME_WIN_FILETIME ft; + QUADLIB_U64 qFileTime; + QUADLIB_U64 qSec; + QUADLIB_U64 qNsec100; + QUADLIB_U64 qNum; + + if (pTimeVal == NULL) + { + errno = EFAULT; + return STDTIMEW32_GETTIMEOFDAY_FAILURE; + } + + if (pObsolete != NULL) + { + /* the obsolete argument is not supposed to be used */ + errno = EINVAL; + return STDTIMEW32_GETTIMEOFDAY_FAILURE; + } + + GetSystemTimeAsFileTime (&ft); + + QUADLIB_U64_HI(qFileTime) = ft.dwHighDateTime; + QUADLIB_U64_LO(qFileTime) = ft.dwLowDateTime; + + /* conversion code adapted from MSDN KB Q167296 */ + /* subtract epoch factor and divide by 10_000_000 */ + + QUADLIB_U64_HI(qNum) = STDTIMEW32_FT_TIMET_BASE_HI; + QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_BASE_LO; + + QUADLIB_I64_SUB_EQ (qFileTime, qNum); + + QUADLIB_U64_HI(qNum) = 0; + QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_SCALE; + + qSec = QuadLibU64DivMod (qFileTime, qNum, &qNsec100); + + pTimeVal->tv_sec = (long) QUADLIB_U64_LO(qSec); + + /* qNsec100 has multiples of 100 nanoseconds, or 1/10 microseconds */ + /* to get whole microseconds, divide by 10 */ + + pTimeVal->tv_usec = (long) QUADLIB_U64_LO(qNsec100) / 10; + + return STDTIMEW32_GETTIMEOFDAY_SUCCESS; + + } /* gettimeofday */ + + +#endif /* STDTIMEW32_DEBUGGING */ +#endif /* STDTIMEW32_USE_GETTIMEOFDAY */ + + +/*****************************************************************************/ +/* StdTimeW32GetTimeOfDayToFileTime - interface Unix to Windows time */ +/* function is used to replace WIN32 API GetSystemTimeAsFileTime */ +/*****************************************************************************/ + + +#ifdef STDTIMEW32_USE_GETTIMEOFDAY + + +STDTIMEW32_STATIC void StdTimeW32GetTimeOfDayToFileTime (STDTIME_WIN_FILETIME *pFileTime) +{ + QUADLIB_U64 qResult; + QUADLIB_U64 qNum; + struct timeval timeVal; + STDTIME_WIN_FILETIME ft = {0}; + + /* since there is no return-code mechanism for the Windows API */ + /* GetSystemTimeAsFileTime, we have none here. if the input */ + /* parameter is NULL, the caller accepts the consequences. */ + /* a call to GetSystemTimeAsFileTime(NULL) crashes on Windows */ + + if (gettimeofday (&timeVal, NULL) != STDTIMEW32_GETTIMEOFDAY_SUCCESS) + { + *pFileTime = ft; + return; + } + + /* multiply seconds result by 10_000_000 */ + QUADLIB_U64_HI(qResult) = 0; + QUADLIB_U64_LO(qResult) = timeVal.tv_sec; + + QUADLIB_U64_HI(qNum) = 0; + QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_SCALE; + + QUADLIB_U64_MUL_EQ (qResult, qNum); + + /* add 100nsec intervals by converting tv_usec to 100nsec */ + /* note that 100nsec units = 10 * usec units */ + /* there is no way to know if multiply by 10 will cause overflow */ + /* in 32-bit mode, so quad lib used for this */ + + QUADLIB_U64_LO(qNum) = timeVal.tv_usec; + QUADLIB_U64_MUL10_EQ (qNum); + QUADLIB_U64_ADD_EQ (qResult, qNum); + + /* add constant difference in epoch values */ + + QUADLIB_U64_HI(qNum) = STDTIMEW32_FT_TIMET_BASE_HI; + QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_BASE_LO; + + QUADLIB_U64_ADD_EQ (qResult, qNum); + + ft.dwHighDateTime = QUADLIB_U64_HI(qResult); + ft.dwLowDateTime = QUADLIB_U64_LO(qResult); + + *pFileTime = ft; + +} /* StdTimeW32GetTimeOfDayToFileTime */ + + +#endif /* STDTIMEW32_USE_GETTIMEOFDAY */ + + +/*****************************************************************************/ +/* clock_gettime() simulation on Win32 systems */ +/* StdTimeW32ClockGetTimeToFileTime - interface Unix to Windows time */ +/*****************************************************************************/ + +#define STDTIMEW32_CLOCKGETTIME_SUCCESS 0 +#define STDTIMEW32_CLOCKGETTIME_FAILURE (-1) + +#ifdef STDTIMEW32_USE_CLOCKGETTIME +#ifdef STDTIMEW32_DEBUGGING + +/* clock_gettime is defined in Unix */ + +#ifndef _CLOCKID_T +#define _CLOCKID_T +typedef int clockid_t; +#endif + +#ifndef _TIME_T_DEFINED +typedef long time_t; +#define _TIME_T_DEFINED +#endif + +#define CLOCK_REALTIME 0 + +/* only CLOCK_REALTIME is supported in this simulation */ + +/*efine CLOCK_MONOTONIC 1 */ +/*efine CLOCK_PROCESS_CPUTIME_ID 2 */ +/*efine CLOCK_THREAD_CPUTIME_ID 3 */ + +struct timespec + { + time_t tv_sec; /* Seconds */ + long tv_nsec; /* Nanoseconds */ + }; + +STDTIMEW32_STATIC int clock_gettime (clockid_t clock_id, struct timespec *tp); + +/*****************************************************************************/ +/* rc 0: success */ +/* rc -1: failure, errno set. */ +/* errno: EFAULT tp points outside the accessible address space. */ +/* errno: EINVAL The clk_id specified is not supported on this system. */ +/*****************************************************************************/ + + +#endif /* STDTIMEW32_DEBUGGING */ +#endif /* STDTIMEW32_USE_CLOCKGETTIME */ + + +/*****************************************************************************/ +/* clock_gettime - simulate Unix/Linux function clock_gettime() */ +/*****************************************************************************/ + +#ifdef STDTIMEW32_USE_CLOCKGETTIME +#ifdef STDTIMEW32_DEBUGGING + +STDTIMEW32_STATIC int clock_gettime ( + clockid_t clock_id, struct timespec *pTimeSpec) + { + STDTIME_WIN_FILETIME ft; + QUADLIB_U64 qFileTime; + QUADLIB_U64 qSec; + QUADLIB_U64 qNsec100; + QUADLIB_U64 qNum; + + if (pTimeSpec == NULL) + { + errno = EFAULT; + return STDTIMEW32_CLOCKGETTIME_FAILURE; + } + + if (clock_id != CLOCK_REALTIME) + { + errno = EINVAL; + return STDTIMEW32_CLOCKGETTIME_FAILURE; + } + + GetSystemTimeAsFileTime (&ft); + + QUADLIB_U64_HI(qFileTime) = ft.dwHighDateTime; + QUADLIB_U64_LO(qFileTime) = ft.dwLowDateTime; + + /* conversion code adapted from MSDN KB Q167296 */ + /* subtract epoch factor and divide by 10_000_000 */ + + QUADLIB_U64_HI(qNum) = STDTIMEW32_FT_TIMET_BASE_HI; + QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_BASE_LO; + + QUADLIB_I64_SUB_EQ (qFileTime, qNum); + + QUADLIB_U64_HI(qNum) = 0; + QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_SCALE; + + qSec = QuadLibU64DivMod (qFileTime, qNum, &qNsec100); + + pTimeSpec->tv_sec = (long) QUADLIB_U64_LO(qSec); + + /* qNsec100 has multiples of 100 nanoseconds, or 1/10 microseconds */ + /* to get whole nanoseconds, multiply by 100 */ + /* since this value was calculated as a remainder, it will never */ + /* exceed 10_000_000, so multiplying by 100 will always work */ + + pTimeSpec->tv_nsec = (long) QUADLIB_U64_LO(qNsec100) * 100; + + return 0; + + } /* clock_gettime */ + + +#endif /* STDTIMEW32_DEBUGGING */ +#endif /* STDTIMEW32_USE_CLOCKGETTIME */ + + +/*****************************************************************************/ +/* StdTimeW32ClockGetTimeToFileTime - interface Unix to Windows time */ +/* function is used to replace WIN32 API GetSystemTimeAsFileTime */ +/*****************************************************************************/ + + +#ifdef STDTIMEW32_USE_CLOCKGETTIME + + +STDTIMEW32_STATIC void StdTimeW32ClockGetTimeToFileTime ( + STDTIME_WIN_FILETIME *pFileTime) + { + QUADLIB_U64 qResult; + QUADLIB_U64 qNum; + struct timespec timeSpec; + STDTIME_WIN_FILETIME ft = {0}; + + /* since there is no return-code mechanism for the Windows API */ + /* GetSystemTimeAsFileTime, we have none here. if the input */ + /* parameter is NULL, the caller accepts the consequences. */ + /* a call to GetSystemTimeAsFileTime(NULL) crashes on Windows */ + + if (clock_gettime (CLOCK_REALTIME, &timeSpec) != + STDTIMEW32_CLOCKGETTIME_SUCCESS) + { + *pFileTime = ft; + return; + } + + /* multiply seconds result by 10_000_000 */ +#if STDTIME_TIME_T64_ENABLED + QUADLIB_U64_HI(qResult) = QUADLIB_U64_HI(timeSpec.tv_sec); + QUADLIB_U64_LO(qResult) = QUADLIB_U64_LO(timeSpec.tv_sec); +#else + QUADLIB_U64_HI(qResult) = 0; + QUADLIB_U64_LO(qResult) = (*(uint32_t *)(&(timeSpec.tv_sec))); +#endif + + QUADLIB_U64_HI(qNum) = 0; + QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_SCALE; + + QUADLIB_U64_MUL_EQ (qResult, qNum); + + /* add 100nsec intervals by converting tv_nsec to 100nsec */ + + QUADLIB_U64_LO(qNum) = timeSpec.tv_nsec / 100; + QUADLIB_U64_ADD_EQ (qResult, qNum); + + /* add constant difference in epoch values */ + + QUADLIB_U64_HI(qNum) = STDTIMEW32_FT_TIMET_BASE_HI; + QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_BASE_LO; + + QUADLIB_U64_ADD_EQ (qResult, qNum); + + ft.dwHighDateTime = QUADLIB_U64_HI(qResult); + ft.dwLowDateTime = QUADLIB_U64_LO(qResult); + + *pFileTime = ft; + + } /* StdTimeW32ClockGetTimeToFileTime */ + + +#endif /* STDTIMEW32_USE_CLOCKGETTIME */ + + +/*****************************************************************************/ +/* StdTimeW32TimeBToFileTime - interface Unix to Windows time */ +/* function is used to replace WIN32 API GetSystemTimeAsFileTime */ +/* */ +/* ftime() and struct timeb exist on Windows and Unix */ +/* however, a struct timeb has only millisecond precision, so there is */ +/* no reason to use it on Windows, and would be used on Unix/Linux only */ +/* if no better alternatives existed. */ +/*****************************************************************************/ + + +#ifdef STDTIMEW32_USE_TIMEB + + +STDTIMEW32_STATIC void StdTimeW32TimeBToFileTime ( + STDTIME_WIN_FILETIME *pFileTime) + { + QUADLIB_U64 qResult; + QUADLIB_U64 qNum; + struct timeb timeBuffer; + STDTIME_WIN_FILETIME ft = {0}; + + /* since there is no return-code mechanism for the Windows API */ + /* GetSystemTimeAsFileTime, we have none here. if the input */ + /* parameter is NULL, the caller accepts the consequences. */ + /* a call to GetSystemTimeAsFileTime(NULL) crashes on Windows */ + + ftime (&timeBuffer); + + /* ftime returns a time_t and a millisecond count */ + /* since there is no further precision, the resulting FILETIME */ + /* value will have zero for microseconds and nanoseconds */ + + /* multiply seconds result by 10_000_000 */ + +#if STDTIME_TIME_T64_ENABLED + QUADLIB_U64_HI(qResult) = QUADLIB_U64_HI(timeBuffer.time); + QUADLIB_U64_LO(qResult) = QUADLIB_U64_LO(timeBuffer.time); +#else + QUADLIB_U64_HI(qResult) = 0; + QUADLIB_U64_LO(qResult) = (*(uint32_t *)(&(timeBuffer.time))); +#endif + + QUADLIB_U64_HI(qNum) = 0; + QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_SCALE; + + QUADLIB_U64_MUL_EQ (qResult, qNum); + + /* add milliseconds after converting to 100-nanosecond intervals */ + /* this requires multiplying an unsigned short by 10,000 */ + /* the maximum value will not overflow an unsigned 32-bit value */ + + QUADLIB_U64_LO(qNum) = 10000 * (unsigned long) timeBuffer.millitm; + QUADLIB_U64_ADD_EQ (qResult, qNum); + + /* add constant difference in epoch values */ + + QUADLIB_U64_HI(qNum) = STDTIMEW32_FT_TIMET_BASE_HI; + QUADLIB_U64_LO(qNum) = STDTIMEW32_FT_TIMET_BASE_LO; + + QUADLIB_U64_ADD_EQ (qResult, qNum); + + ft.dwHighDateTime = QUADLIB_U64_HI(qResult); + ft.dwLowDateTime = QUADLIB_U64_LO(qResult); + + *pFileTime = ft; + + } /* StdTimeW32TimeBToFileTime */ + + +#endif /* STDTIMEW32_USE_TIMEB */ + + diff --git a/mmslib/util/stime.c b/mmslib/util/stime.c new file mode 100644 index 0000000..153de0c --- /dev/null +++ b/mmslib/util/stime.c @@ -0,0 +1,479 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1993 - 2007, All Rights Reserved */ +/* */ +/* MODULE NAME : stime.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* This module implements functions that can be used in */ +/* differencial timimg. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/15/07 EJV 30 Chg S_LOCK_RESOURCES to S_LOCK_UTIL_RESOURCES*/ +/* 10/26/06 EJV 29 HP-UX: changed from gettimeofday() to times()*/ +/* 07/13/06 EJV 28 Sun: changed from gettimeofday() to times(). */ +/* 06/20/06 RKR 27 removed a piece of code from _sGetSysMsTime */ +/* 05/31/06 GLB 26 Integrated porting changes for VMS */ +/* 03/23/06 EJV 25 Corrected VMS chg to _sGetSysMsTime. */ +/* Rearranged includes, del windows.h. */ +/* 01/30/06 GLB 24 Integrated porting changes for VMS */ +/* 01/30/06 EJV 23 _WIN32 _sGetSysMsTime: added (ST_INT64) cast */ +/* before (ST_DOUBLE) to eliminate VS6 compiler*/ +/* error after changing ST_UINT64 define to */ +/* unsigned __int64. */ +/* 06/10/05 EJV 22 Revised the repeating code. */ +/* Linux, QNX: rpl gettimeofday() with times(). */ +/* Del MSDOS and __OS2__ code. */ +/* Del sGetMsStartTime, sSetMsStartTime */ +/* Renamed lastTime to initTime. */ +/* 03/11/04 GLB 21 Remove "thisFileName" */ +/* 12/09/03 JRB 20 Add LYNX support. */ +/* 11/04/03 JRB 19 Add sMsSleep (replaces gs_sleep). */ +/* 10/13/03 EJV 18 Chg defined(vms) to defined(__VMS) */ +/* 04/08/03 EJV 17 Use S_LOCK_RESOURCES (better for non-MT apps)*/ +/* 03/21/03 EJV 16 _WIN32: sGetMsTime, sGetSysMsTime must be */ +/* protected by mutex,prevent incorect wrapCount*/ +/* 03/18/03 EJV 15 Corrected __QNX4__ to __QNX__ (per JRB). */ +/* 03/18/03 EJV 14 sGetMsTime: fixed lastTime casting problem */ +/* (made lastTime ST_UINT on _WIN32). */ +/* 02/17/03 CRM 13 Added "defined(linux)" code. */ +/* 02/17/03 JRB 12 Add "sysincs.h" & del other includes. */ +/* Del obsolete _WINDOWS, MSOS2 code. */ +/* 02/17/03 EJV 11 sGetMsTime, sGetSysMsTime: fixed wrap counter*/ +/* Auto-initialize funs with call to stimeInit()*/ +/* Chg S_LOCK_RESOURCES to gs_get_sem,avoid loop*/ +/* 06/05/02 MDE,EJV 10 sGetMsTime: workaround some math problem */ +/* 11/29/01 EJV 09 Del code for old LATT, XENIX, ultrix, RMX86. */ +/* 06/19/01 JRB 08 Chg S_LOCK_COMMON.. to S_LOCK_RESOURCES so */ +/* glbsem doesn't log (caused infinite loop). */ +/* 04/19/00 JRB 07 Lint cleanup. */ +/* 11/18/99 EJV 06 Added code to capture wrapping of ms counter */ +/* for _WIN32 and PHARLAP_ETS. */ +/* 09/13/99 MDE 05 Added SD_CONST modifiers */ +/* 11/05/97 DSF 04 Added sGetSysMsTime () */ +/* 09/22/97 JRB 03 Fixed some #if's. */ +/* 09/09/97 JRB 02 Use GetTickCount for PHARLAP_ETS. */ +/* 09/08/97 EJV 01 Added code for QNX. */ +/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ +/* history. */ +/************************************************************************/ + + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" + +#if defined (_WIN32) +#include +#if defined (PHARLAP_ETS) +#define timeGetTime GetTickCount /* timeGetTime not supported */ +#endif /* PHARLAP_ETS */ +#endif + +#if defined(__VMS) +#include +#endif + +#if defined(linux) || defined(sun) || defined(__hpux) || \ + defined(__QNX__) || defined(__LYNX) +#include /* for struct tms */ +#endif + +/************************************************************************/ +/* NOTE: Users porting this code to new platform should not use the */ +/* gettimeofday() or similar functions. When the system time */ +/* is changed, for example during clock synchronization, the */ +/* gettimeofday() would also reflect this change. */ +/* Application should use times() function if available. */ +/* */ +/* DEBUG: On UNIX systems we should implement the sTime functions */ +/* the same way as on LINUX. */ +/************************************************************************/ + + /*------------------------------------------------------*/ + /* stime module variables */ + /*------------------------------------------------------*/ + +#if defined(linux) || defined(sun) || defined(__hpux) +static ST_UINT64 wrapCount; /* ms, cumulative wrapped time ticks elapsed since program start*/ + +#elif (defined (__QNX__) || defined(__LYNX)) +static ST_DOUBLE wrapCount; /* ms, cumulative wrapped time ticks elapsed since program start*/ + +#elif defined (_WIN32) +static ST_UINT64 wrapCount; /* wrap count (see timeGetTime or GetTickTime) */ +#endif + +#if defined (__ECOS) +#define ST_UINT64 unsigned long long +static unsigned long long wrapCount; +#endif + +static ST_ULONG ticksPerSec; /* system dependent value, returned by sysconf(_SC_CLK_TCK) */ +static ST_ULONG lastCheckTime; /* last time checked, used to detect clock_t overflow */ +static ST_DOUBLE initMsTime; /* in ms, store initialization time */ +static ST_INT initialized; /* SD_TRUE if stimeInit func successful */ + + +/************************************************************************/ +/* _sGetSysMsTime */ +/*----------------------------------------------------------------------*/ +/* Combined code from sGetMsTime and sGetSysMsTime, now also called by */ +/* stimeInit. */ +/* */ +/* NOTE: this new implementation on LINUX uses the times() function */ +/* to obtain the "number of clock ticks that have elapsed since */ +/* an arbitrary point in the past. For Linux this point is the */ +/* moment the system was booted. The return from times() may */ +/* overflow the possible range of clock_t." */ +/* The revision of the IEEE Std 1003.1, 2004 allows the that */ +/* reference point can be the start-up time of the process */ +/* rather than system start-up time. */ +/* IMPORTANT: */ +/* This implementation is assuming that POSIX compliant clock_t */ +/* type is defined as long (4 bytes integer). If this is not the */ +/* case then the code needs to be revised! */ +/* */ +/* DEBUG: In the future LINUX implementation should be used for all */ +/* UNIX systems. */ +/************************************************************************/ + +static ST_DOUBLE _sGetSysMsTime (ST_VOID) + { +ST_DOUBLE sysMsTime = (ST_DOUBLE) 0.0; /* system time to be returned */ + +#if defined(linux) || defined(sun) || defined(__hpux) + { + struct tms tmsTime; /* must be passed to times() but we do not use it */ + ST_ULONG sysTime; + + sysTime = (ST_ULONG) times (&tmsTime); + if (sysTime != (ST_ULONG) -1) + { + /* NOTE: The value returned from the times() function (number of ticks */ + /* from some fixed point in time) will wrap. */ + /* Wrapping depends on the frequency (ticksPerSec) and can be as */ + /* often as every 39 minutes. This function needs to be called */ + /* frequently enough to detect when the value wraps. */ +#if 0 /* DEBUG: code to test wrapping, */ + /* trigger the wrapping every 60 seconds if this funct is called */ + if ( (sysTime > ticksPerSec) && /* don't wrap before 1-st second elapses*/ + ((sysTime / ticksPerSec) % 60 == 0) ) + lastCheckTime=sysTime+1; /* tweek the lastCheckTime */ +#endif + if (sysTime < lastCheckTime) + /* the ticks counter wrapped to 0 */ + wrapCount += ((ST_UINT64) 1 << 32); /* increment the high part of ST_UINT64 */ + /* convert the sys time to ms accounting for possible wrap */ + /* (switch math operations order / with * for better precission, avoid floating point math) */ + sysMsTime = (ST_DOUBLE)((wrapCount + (ST_UINT64) sysTime) * 1000 / (ST_UINT64) ticksPerSec); + lastCheckTime = sysTime; /* save for next check */ + } + else + { + ST_INT err; + err = errno; /* can't log this error but we could see it in debugger */ + } + } +#elif defined(__ECOS) +{ + struct timeval tp; + struct timezone tzp; + gettimeofday (&tp, &tzp); /* avoid floating math */ + sysMsTime = (ST_DOUBLE) ( (ST_UINT64) ((ST_ULONG) tp.tv_sec) * (ST_UINT64) 1000 + + (ST_UINT64) ((ST_ULONG) tp.tv_usec) / (ST_UINT64) 1000 ); +#if 0 + cyg_tick_count_t sysTime; /* in ecos, cyg_tick_count_t is defined by cyg_uint64 */ + + sysTime = cyg_current_time(); + sysMsTime = (ST_DOUBLE)((wrapCount + (ST_UINT64) sysTime) * 1000 / (ST_UINT64) ticksPerSec); +#endif +} +#elif defined(_AIX) || (defined(__alpha) && !defined(__VMS)) /* Tru64 alpha */ + { + struct timeval tp; + struct timezone tzp; + gettimeofday (&tp, &tzp); /* avoid floating math */ + sysMsTime = (ST_DOUBLE) ( (ST_UINT64) ((ST_ULONG) tp.tv_sec) * (ST_UINT64) 1000 + + (ST_UINT64) ((ST_ULONG) tp.tv_usec) / (ST_UINT64) 1000 ); + } +#elif defined(__VMS) /* OpenVMS non-specific */ + { + struct timeval tp; + ST_LONG tzp; + gettimeofday (&tp, &tzp); /* avoid floating math */ + sysMsTime = (ST_DOUBLE) + ( + /*(ST_UINT64)*/ ((ST_ULONG) tp.tv_sec) * /*(ST_UINT64)*/ 1000 + + /*(ST_UINT64)*/ ((ST_ULONG) tp.tv_usec) / /*(ST_UINT64)*/ 1000 + ); + } +#elif defined (VXWORKS) + { + /*renxiaobao add*/ + struct timeval tp; + vx_gettimeofday (&tp,0); + sysMsTime = ((ST_DOUBLE)tp.tv_sec)*1000 + ((ST_DOUBLE)tp.tv_usec)/1000; + /*sysMsTime = (ST_DOUBLE) time (NULL) * 1000;*/ + } +#elif (defined (__QNX__) || defined(__LYNX)) + { + struct tms tmsTime; /* must be passed to times() but we do not use it */ + ST_ULONG sysTime; + + sysTime = (ST_ULONG) times (&tmsTime); + if (sysTime != (ST_ULONG) -1) + { + /* NOTE: The value returned from the times() function (number of ticks */ + /* from some fixed point in time) will wrap. */ + /* Wrapping depends on the frequency (ticksPerSec) and can be as */ + /* often as every 39 minutes. This function needs to be called */ + /* frequently enough to detect when the value wraps. */ + if (sysTime < lastCheckTime) + /* the ticks counter wrapped to 0 */ + wrapCount += (ST_DOUBLE) (ULONG_MAX); + /* convert the sys time to ms accounting for possible wrap, */ + /* note that we do not have ST_INT64 support on QNX or LYNX systems */ + sysMsTime = (ST_DOUBLE)((wrapCount + (ST_DOUBLE) sysTime) * 1000.0 / (ST_DOUBLE) ticksPerSec); + lastCheckTime = sysTime; /* save for next check */ + } + } +#elif defined (_WIN32) + { + ST_ULONG msTime; + + /* the timeGetTime function retrieves the system time, in milliseconds.*/ + /* The system time is the time elapsed since Windows was started. */ + + /* NOTE: The timeGetTime and GetTickCount (used for PHARLAP_ETS) */ + /* return DWORD value that wraps to 0 every 49 days. */ + /* We need to detect the wrap up moment and save it. */ + msTime = (ST_ULONG) timeGetTime (); + if ( msTime < lastCheckTime ) + /* the ms counter wrapped to 0 */ + wrapCount += ( (ST_UINT64) 1 << 32 ); /* increment the high part of ST_UINT64 */ + sysMsTime = (ST_DOUBLE) (ST_INT64) (wrapCount + (ST_UINT64) msTime); + /* NOTE VC V6.0 compiler: the compiler generates error for the */ + /* conversion of unsigned __int64 to double. We will cast to */ + /* ST_INT64 before the ST_DOUBLE cast. This should work */ + /* because the sum of both numbers will 'never' be negative. */ + + lastCheckTime = msTime; /* save for next check */ + } +#else +#error Missing stime module implementation for this platform +#endif + + return (sysMsTime); + } + +/************************************************************************/ +/* _stimeReset */ +/*----------------------------------------------------------------------*/ +/* Resets stime module variables. */ +/************************************************************************/ + +static ST_RET _stimeReset (ST_VOID) + { +ST_RET rtn = SD_SUCCESS; + +#if (defined(linux) || defined(sun) || defined(__hpux) || defined(_WIN32)) + wrapCount = 0; + lastCheckTime = 0; +#elif (defined(__QNX__) || defined(__LYNX)) + wrapCount = 0.0; + lastCheckTime = 0; +#endif + + initMsTime = _sGetSysMsTime (); + + return (rtn); + } + +/************************************************************************/ +/* stimeInit */ +/*----------------------------------------------------------------------*/ +/* Initialize stime module variables. */ +/************************************************************************/ + +ST_RET stimeInit (ST_VOID) + { +ST_RET rtn = SD_SUCCESS; + + /* Allow multiple calls */ + if (initialized) + return (rtn); + + S_LOCK_UTIL_RESOURCES (); /* NOTE: this macro is now using non-logging gs_get_sem() */ + +#if defined(linux) || defined(sun) || defined(__hpux) || defined(__QNX__) || defined(__LYNX) + { + ticksPerSec = 0; + + ticksPerSec = (ST_ULONG) sysconf(_SC_CLK_TCK); + if (ticksPerSec == (ST_ULONG) -1L || ticksPerSec == 0) + rtn = SD_FAILURE; /* some error getting the number of clock ticks per second */ + } +#endif + + if (rtn == SD_SUCCESS) + { + rtn = _stimeReset (); + if (rtn == SD_SUCCESS) + initialized = SD_TRUE; + } + + S_UNLOCK_UTIL_RESOURCES (); + + return (rtn); + } + +/************************************************************************/ +/* sGetMsTime */ +/*----------------------------------------------------------------------*/ +/* Returns time in milliseconds form the start of the program. */ +/************************************************************************/ + +ST_DOUBLE sGetMsTime (ST_VOID) + { +ST_DOUBLE sysMsTime, retMsTime; + + if (!initialized) + if (stimeInit () != SD_SUCCESS) + return ((ST_DOUBLE)0.0); + + S_LOCK_UTIL_RESOURCES (); + + sysMsTime = _sGetSysMsTime(); + retMsTime = sysMsTime - initMsTime; + + S_UNLOCK_UTIL_RESOURCES (); + + return (retMsTime); + } + +/************************************************************************/ +/* sGetSysMsTime */ +/*----------------------------------------------------------------------*/ +/* Returns system time in milliseconds (time from an arbitrary point */ +/* like system start or program start). */ +/************************************************************************/ + +ST_DOUBLE sGetSysMsTime (ST_VOID) + { +ST_DOUBLE sysMsTime; + + if (!initialized) + if (stimeInit () != SD_SUCCESS) + return ((ST_DOUBLE)0.0); + + S_LOCK_UTIL_RESOURCES (); + + sysMsTime = _sGetSysMsTime(); + + S_UNLOCK_UTIL_RESOURCES (); + + return (sysMsTime); + } + +/************************************************************************/ +/* sResetMsTime */ +/*----------------------------------------------------------------------*/ +/* Reset stime module variables. */ +/************************************************************************/ + +ST_VOID sResetMsTime (ST_VOID) + { + if (!initialized) + { + stimeInit (); /* calls the _stimeReset() */ + return; + } + + S_LOCK_UTIL_RESOURCES (); + + _stimeReset (); + + S_UNLOCK_UTIL_RESOURCES (); + } + +/************************************************************************/ +/* stimeExit */ +/*----------------------------------------------------------------------*/ +/* Terminate timer use. */ +/************************************************************************/ + +ST_VOID stimeExit (ST_VOID) + { + if (!initialized) + return; + + S_LOCK_UTIL_RESOURCES (); + + initialized = SD_FALSE; + + S_UNLOCK_UTIL_RESOURCES (); + } + +/************************************************************************/ +/* sMsSleep */ +/*----------------------------------------------------------------------*/ +/* Calls system function to suspend current task or thread for */ +/* specified amount of time. */ +/* Parameters: */ +/* ST_LONG ms Number of milliseconds to sleep */ +/* Return values: */ +/* none */ +/************************************************************************/ + +#if defined(_WIN32) + +ST_VOID sMsSleep (ST_LONG ms) + { + Sleep (ms); + } + +#elif defined(__VMS) + +ST_VOID sMsSleep (ST_LONG ms) + { +ST_ULONG msec = (ST_ULONG) ms; +unsigned int us; + + while (msec > 0) + { + if (msec >= 1000) + { + us = 999999; /* microseconds, it must be less than 1000000 for usleep */ + msec -= 1000; + } + else + { + us = msec * 1000; + msec = 0; + } + usleep (us); /* unistd.h */ + } + } + +#else /* all other systems */ + +/* This version of the function uses the POSIX nanosleep function. */ +ST_VOID sMsSleep (ST_LONG ms) + { +struct timespec rqtp; + + rqtp.tv_sec = ms / 1000; + rqtp.tv_nsec = (ms % 1000) * 1000000; /* 1000 ms/us, 1000 us/ns ... */ + + nanosleep (&rqtp, NULL); /* should be available on AIX v5.x */ + } + +#endif /* all other systems */ diff --git a/mmslib/util/str_util.c b/mmslib/util/str_util.c new file mode 100644 index 0000000..6c54f4a --- /dev/null +++ b/mmslib/util/str_util.c @@ -0,0 +1,947 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 2000 - 2007 All Rights Reserved */ +/* */ +/* MODULE NAME : str_util.c */ +/* PRODUCT(S) : General Use */ +/* */ +/* MODULE DESCRIPTION : */ +/* General purpose string manipulation functions. */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* ascii_to_hex_str */ +/* hex_to_ascii_str */ +/* strnicmp (UNIX) */ +/* strcmpi (UNIX) */ +/* stricmp (UNIX) */ +/* strncat_maxstrlen */ +/* strncpy_safe */ +/* asciiToSlong */ +/* asciiToUlong */ +/* asciiToSint */ +/* asciiToUint */ +/* asciiToSint32 */ +/* asciiToUint32 */ +/* asciiToSint16 */ +/* asciiToUint16 */ +/* asciiToSint8 */ +/* asciiToUint8 */ +/* asciiToUchar */ +/* asciiToFloat */ +/* asciiToDouble */ +/* sInt8ToAscii */ +/* uInt8ToAscii */ +/* sInt16ToAscii */ +/* uInt16ToAscii */ +/* sInt32ToAscii */ +/* uInt32ToAscii */ +/* sIntToAscii */ +/* uIntToAscii */ +/* sLongToAscii */ +/* uLongToAscii */ +/* getKeywordFromFile */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 11/07/07 EJV 23 Check before defining INT32_MAX, UINT32_MAX. */ +/* 10/29/07 JRB 22 Add strncat_maxstrlen. Del strncat_safe (len */ +/* was wrong), use strncat or strncat_maxstrlen.*/ +/* 10/11/07 JRB 21 Add asciiToSint32, asciiToUint32 */ +/* 08/03/07 JRB 20 get_next_string: don't ignore extra delimiters*/ +/* They now indicate empty field (as in Excel). */ +/* 02/13/06 DSF 19 Migrate to VS.NET 2005 */ +/* 07/28/05 DWL 18 Corrected microsecond resolution, use const */ +/* ST_CHAR* in asciiTo* functions. */ +/* 03/14/05 JRB 17 Add get_next_string. */ +/* 12/03/04 JRB 16 Use strcasecmp, strncasecmp if supported. */ +/* Don't need SISCO strnicmp, etc. */ +/* 07/09/04 JRB 15 Add strncat_safe, strncpy_safe. */ +/* 03/09/04 EJV 14 Added getKeywordFromFile function. */ +/* 12/12/03 JRB 13 Add LYNX support. */ +/* 12/10/03 MDE 12 Added itoa/ltoa/utoa/ultoa replacements */ +/* 04/10/03 DSF 11 Added strnstr */ +/* 02/20/03 JRB 10 Del PSOS code. */ +/* 12/20/02 CRM 09 Added "defined(linux)" for strcmpi, etc. */ +/* 03/01/02 EJV 08 Can't check doubleNum < FLT_MIN (0.0 fails). */ +/* 02/28/02 EJV 07 Added asciiToFloat, asciiToDouble. */ +/* 02/25/02 EJV 06 Replaced non-ANSI ltoa with sprintf. */ +/* Added asciiToUlong, asciiToUint16, */ +/* asciiToUint8, asciiToSint, asciiToUint */ +/* hex_to_ascii_str: added param hex_no_spaces. */ +/* asciiToxxx:eliminated dependency on sx_defs.h*/ +/* 12/09/01 GLB 05 Added asciiToSlong, asciiToSint16, */ +/* asciiToSint8, asciiToUchar */ +/* 05/21/01 MDE 04 Added bitstring_to_ascii_str */ +/* 01/19/01 EJV 03 Moved strcmpi,stricmp,strnicmp from cfg_util */ +/* 11/02/00 MDE 02 Added _hex_no_spaces */ +/* 02/03/00 JRB 01 Created */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "str_util.h" +#include "slog.h" + +#include +#include +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + + + + +/* NOTE: limits.h (included in sysincs.h) should have these defined. */ +/* Used to compare to LONG_MAX, ULONG_MAX to detect the long size.*/ +#if !defined(INT32_MAX) +#define INT32_MAX 0x7fffffff +#endif +#if !defined(UINT32_MAX) +#define UINT32_MAX 0xffffffff +#endif + +/************************************************************************/ +/* ascii_to_hex_str */ +/************************************************************************/ + +ST_RET ascii_to_hex_str ( + ST_UCHAR *hstr, /* hex string */ + ST_UINT *hlen_out, /* ptr to hex len to be set */ + ST_UINT hlen_max, /* maximum hex len to allow. */ + ST_CHAR *astr) /* ascii string */ + { +ST_INT digit; +ST_BOOLEAN nibble; /* SD_TRUE if nibble read, SD_FALSE if whole byte read*/ + + *hlen_out = 0; + nibble = SD_FALSE; + for ( ; *astr; astr++) /* read until NULL terminator */ + { + if (isxdigit (*astr)) /* get hex number */ + { + if (*hlen_out >= hlen_max) + { /* hstr already full. Can't add digit. */ + return (SD_FAILURE); + } + + digit = *astr; + digit = isdigit (digit) ? digit - '0' : 10 + (toupper (digit) - 'A'); + if (nibble) + { /* set low nibble */ + nibble = SD_FALSE; + hstr[*hlen_out] |= (ST_UCHAR) digit; + (*hlen_out)++; + } + else + { /* set high nibble */ + nibble = SD_TRUE; + hstr[*hlen_out] = (ST_UCHAR) digit << 4; + } + } + else if (isspace (*astr)) + continue; + else + { /* not hex digit, not white space, NOT GOOD. */ + return (SD_FAILURE); + } + } /* end "while" */ + + if (nibble) + { /* Only got half of byte. */ + return (SD_FAILURE); + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* hex_to_ascii_str */ +/* To make it more readable, a 'blank' is inserted after every 2 digits */ +/* in the ascii string. The ascii string is NULL terminated. */ +/* The ascii buffer must be at least 3 times the length of the hex */ +/* string (hlen) to allow for the blanks and the NULL terminator. */ +/************************************************************************/ +#define cvt_nibble(a) ((ST_UCHAR) ((a) > 9 ? (a) + 'A' - 10 : (a) + '0')) + +ST_VOID hex_to_ascii_str ( + ST_CHAR *astr, /* ascii string */ + ST_UCHAR *hstr, /* hex string */ + ST_UINT hlen, /* len of hex string */ + ST_BOOLEAN hex_no_spaces) + + { +ST_UINT j; +ST_INT hex_index = 0; +ST_UCHAR ch; +ST_UCHAR hex; + + for (j = 0; j < hlen; j++) + { + if (j && hex_no_spaces != SD_TRUE) + astr[hex_index++] = ' '; /* space between bytes, but not before first*/ + + ch = *hstr++; /* get next character */ + hex = (ch >> 4) & (ST_UCHAR) 0x0f;/* write HEX chars for the byte */ + hex = cvt_nibble(hex); + astr[hex_index++] = hex; + hex = ch & (ST_UCHAR) 0x0f; + hex = cvt_nibble(hex); + astr[hex_index++] = hex; + } + astr[hex_index] = '\0'; /* NULL terminate it. */ + } + + +/************************************************************************/ +/* strnstr */ +/************************************************************************/ + +char * strnstr (char *str1, char *str2, int len) + { +char *cp = (char *) str1; +char *s1, *s2; +int cl; + + if ( !*str2 ) + return((char *)str1); + + while (*cp && len) + { + cl = len; + s1 = cp; + s2 = (char *) str2; + + while (*s1 && *s2 && cl && !(*s1-*s2) ) + s1++, s2++, cl--; + + if (!*s2) + return(cp); + + cp++; + len--; + } + + return(NULL); + } + +/* These functions used when system libraries don't provide them. + * Most UNIX-like systems provide similar functions strcasecmp & + * strncasecmp. On those systems, strnicmp etc. are remapped to strcasecmp & + * strncasecmp (see str_util.h), so these functions NOT needed. + */ +#if defined(VXWORKS) || defined(__LYNX) || defined(__ECOS) + +/************************************************************************/ +/* strnicmp */ +/************************************************************************/ + +ST_INT strnicmp (ST_CHAR *str1, ST_CHAR *str2, ST_INT n ) + { + ST_INT i = 0; + ST_INT test = 1; + + for (i = 0; i < n; i++) + { + if ( tolower ( *(str1+i) ) != tolower ( *(str2+i) ) ) + { + test = 0; + break; + } + } + if (test == 1) + return (0); + else + if ( tolower ( *(str1+i) ) > tolower ( *(str2+i) ) ) + return (1); + else + return (-1); + } + +/************************************************************************/ +/* strcmpi */ +/************************************************************************/ +ST_INT strcmpi (ST_CHAR *str1, ST_CHAR *str2) +{ + ST_INT iLen1, iLen2; + + iLen1 = strlen(str1); + iLen2 = strlen(str2); + return(strnicmp(str1, str2, ((iLen1 > iLen2) ? iLen1 : iLen2))); +} + +/************************************************************************/ +/* stricmp */ +/************************************************************************/ +ST_INT stricmp (ST_CHAR *str1, ST_CHAR *str2) + { + return(strcmpi(str1, str2)); + } + +#endif /* system libs don't provide these functs & don't support strcasecmp, strncasecmp.*/ + +/************************************************************************/ +/* strncat_maxstrlen */ +/* Similar to strncat but third arg is the maximum string length. */ +/* Destination string "dest" is always NULL terminated. */ +/* NOTE: Destination buffer size should always be at least */ +/* (maxstrlen+1) so there is room for NULL. */ +/* RETURNS: SD_SUCCESS or SD_FAILURE if maxstrlen already exceeded. */ +/************************************************************************/ +ST_RET strncat_maxstrlen (char *dest, char *src, size_t maxstrlen) + { + size_t dest_len; + ST_RET retcode; + + dest_len = strlen (dest); + if (dest_len < maxstrlen) + { + strncat (dest, src, maxstrlen-dest_len); /* always NULL-terminates dest*/ + retcode = SD_SUCCESS; + } + else + retcode = SD_FAILURE; /* "dest" is already too long. Don't do anything. */ + return (retcode); + } + +/************************************************************************/ +/* strncpy_safe */ +/* Same as strncpy but always NULL terminates "dest" string. */ +/* strncpy return is useless so this function doesn't bother with return.*/ +/************************************************************************/ +ST_VOID strncpy_safe (char *dest, char *src, int max_len) + { + strncpy (dest, src, max_len); + dest[max_len] = '\0'; + } + +/************************************************************************/ +/* asciiToSlong */ +/************************************************************************/ + +ST_RET asciiToSlong (const ST_CHAR *astr, /* ascii string */ + ST_LONG *sLong) /* ptr to long value obtained + from converted ascii string */ + { +ST_CHAR *retPtr; + + *sLong = 0; + errno = 0; + + /* convert ascii string to signed long */ + *sLong = strtol (astr, &retPtr, 10); + if (retPtr == astr || errno != 0) + return (SD_FAILURE); /* conversion error */ + + return SD_SUCCESS; + } + +/************************************************************************/ +/* asciiToUlong */ +/************************************************************************/ + +ST_RET asciiToUlong (const ST_CHAR *astr, /* ascii string */ + ST_ULONG *uLong) /* ptr to long value obtained + from converted ascii string */ + { +ST_CHAR *retPtr; + + *uLong = 0; + errno = 0; + + /* convert ascii string to unsigned long */ + *uLong = strtoul (astr, &retPtr, 10); + if (retPtr == astr || errno != 0) + return (SD_FAILURE); /* conversion error */ + + return SD_SUCCESS; + } + +/************************************************************************/ +/* asciiToSint */ +/************************************************************************/ + +ST_RET asciiToSint (const ST_CHAR *astr, /* ascii string */ + ST_INT *sInt) /* ptr to value obtained + from converted ascii string */ + { +ST_CHAR *retPtr; +ST_LONG sLong = 0; + + *sInt = 0; + errno = 0; + + /* convert ascii string to signed long */ + sLong = strtol (astr, &retPtr, 10); + if (retPtr == astr || errno != 0) + return (SD_FAILURE); /* conversion error */ + +#if (INT_MAX != LONG_MAX) /* if they are same, don't need to check */ + if (sLong < INT_MIN || sLong > INT_MAX) + /* value does not fit in the range of ST_INT */ + return SD_FAILURE; +#endif + + *sInt = (ST_INT) sLong; + return SD_SUCCESS; + } + +/************************************************************************/ +/* asciiToUint */ +/************************************************************************/ + +ST_RET asciiToUint (const ST_CHAR *astr, /* ascii string */ + ST_UINT *uInt) /* ptr to value obtained + from converted ascii string */ + { +ST_CHAR *retPtr; +ST_ULONG uLong = 0; + + *uInt = 0; + errno = 0; + + /* convert ascii string to unsigned long */ + uLong = strtoul (astr, &retPtr, 10); + if (retPtr == astr || errno != 0) + return (SD_FAILURE); /* conversion error */ + +#if (UINT_MAX != ULONG_MAX) /* if they are same, don't need to check */ + if (uLong > UINT_MAX) + /* value does not fit in the range of ST_UINT */ + return SD_FAILURE; +#endif + + *uInt = (ST_UINT) uLong; + return SD_SUCCESS; + } + +/************************************************************************/ +/* asciiToSint32 */ +/************************************************************************/ +ST_RET asciiToSint32 (const ST_CHAR *astr, /* ascii string */ + ST_INT32 *value) /* ptr to converted value*/ + { +ST_CHAR *retPtr; +ST_LONG sLong = 0; + + *value = 0; + errno = 0; + + /* convert ascii string to signed long */ + sLong = strtol (astr, &retPtr, 10); + if (retPtr == astr || errno != 0) + return (SD_FAILURE); /* conversion error */ + +#if (LONG_MAX < INT32_MAX) /* LONG smaller than 32 bits */ + #error This code will not work on this platform. +#endif +#if (LONG_MAX > INT32_MAX) /* LONG bigger than 32 bits */ + /* DEBUG: test this on 64-bit system. */ + if (sLong > INT32_MAX || sLong < (-0x80000000)) + /* value does not fit in the range of ST_INT32 */ + return (SD_FAILURE); +#endif +/* if (LONG_MAX == INT32_MAX), long is same as ST_INT32, */ +/* so no need to chk range. */ + + *value = (ST_INT32) sLong; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* asciiToUint32 */ +/************************************************************************/ +ST_RET asciiToUint32 (const ST_CHAR *astr, /* ascii string */ + ST_UINT32 *value) /* ptr to converted value*/ + { +ST_CHAR *retPtr; +ST_ULONG uLong = 0; + + *value = 0; + errno = 0; + + /* convert ascii string to unsigned long */ + uLong = strtoul (astr, &retPtr, 10); + if (retPtr == astr || errno != 0) + return (SD_FAILURE); /* conversion error */ + +#if (ULONG_MAX < UINT32_MAX) /* ULONG smaller than 32 bits */ + #error This code will not work on this platform. +#endif +#if (ULONG_MAX > UINT32_MAX) /* ULONG bigger than 32 bits */ + if (uLong > UINT32_MAX) + /* value does not fit in the range of ST_UINT32 */ + return (SD_FAILURE); +#endif +/* if (ULONG_MAX == UINT32_MAX), unsigned long is same as ST_UINT32,*/ +/* so no need to chk range. */ + + *value = (ST_UINT32) uLong; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* asciiToSint16 */ +/************************************************************************/ + +ST_RET asciiToSint16 (const ST_CHAR *astr,/* ascii string */ + ST_INT16 *sInt16) /* ptr to value obtained + from converted ascii string */ + { +ST_CHAR *retPtr; +ST_LONG sLong = 0; + + *sInt16 = 0; + errno = 0; + + /* convert ascii string to signed long */ + sLong = strtol (astr, &retPtr, 10); + if (retPtr == astr || errno != 0) + return (SD_FAILURE); /* conversion error */ + + if (sLong < SHRT_MIN || sLong > SHRT_MAX) + /* value does not fit in the range of ST_INT16 */ + return SD_FAILURE; + + *sInt16 = (ST_INT16) sLong; + return SD_SUCCESS; + } + +/************************************************************************/ +/* asciiToUint16 */ +/************************************************************************/ + +ST_RET asciiToUint16 (const ST_CHAR *astr, /* ascii string */ + ST_UINT16 *uInt16) /* ptr to value obtained + from converted ascii string */ + { +ST_CHAR *retPtr; +ST_ULONG uLong = 0; + + *uInt16 = 0; + errno = 0; + + /* convert ascii string to unsigned long */ + uLong = strtoul (astr, &retPtr, 10); + if (retPtr == astr || errno != 0) + return (SD_FAILURE); /* conversion error */ + + if (uLong > USHRT_MAX) + /* value does not fit in the range of ST_UINT16 */ + return SD_FAILURE; + + *uInt16 = (ST_UINT16) uLong; + return SD_SUCCESS; + } + +/************************************************************************/ +/* asciiToUchar */ +/************************************************************************/ + +ST_RET asciiToUchar (const ST_CHAR *astr, /* ascii string */ + ST_UCHAR *uChar) /* ptr to value obtained + from converted ascii string */ + { +ST_CHAR *retPtr; +ST_ULONG uLong = 0; + + *uChar = 0; + errno = 0; + + /* convert ascii string to unsigned long */ + uLong = strtoul (astr, &retPtr, 10); + if (retPtr == astr || errno != 0) + return (SD_FAILURE); /* conversion error */ + + if (uLong > UCHAR_MAX) + /* value does not fit in range of ST_UCHAR */ + return SD_FAILURE; + + *uChar = (ST_UCHAR) uLong; + return SD_SUCCESS; + } + +/************************************************************************/ +/* asciiToSint8 */ +/************************************************************************/ + +ST_RET asciiToSint8 (const ST_CHAR *astr, /* ascii string */ + ST_INT8 *sInt8) /* ptr to value obtained + from converted ascii string */ + { +ST_CHAR *retPtr; +ST_LONG sLong = 0; + + *sInt8 = 0; + errno = 0; + + /* convert ascii string to signed long */ + sLong = strtol (astr, &retPtr, 10); + if (retPtr == astr || errno != 0) + return (SD_FAILURE); /* conversion error */ + + if (sLong < CHAR_MIN || sLong > CHAR_MAX) + /* value does not fit in range of ST_INT8 */ + return SD_FAILURE; + + *sInt8 = (ST_INT8) sLong; + return SD_SUCCESS; + } + +/************************************************************************/ +/* asciiToUint8 */ +/************************************************************************/ + +ST_RET asciiToUint8 (const ST_CHAR *astr, /* ascii string */ + ST_UINT8 *uInt8) /* ptr to value obtained + from converted ascii string */ + { +ST_CHAR *retPtr; +ST_ULONG uLong = 0; + + *uInt8 = 0; + errno = 0; + + /* convert ascii string to unsigned long */ + uLong = strtoul (astr, &retPtr, 10); + if (retPtr == astr || errno != 0) + return (SD_FAILURE); /* conversion error */ + + if (uLong > UCHAR_MAX) + /* value does not fit in range of ST_UINT8 */ + return SD_FAILURE; + + *uInt8 = (ST_UINT8) uLong; + return SD_SUCCESS; + } + +/************************************************************************/ +/* asciiToFloat */ +/************************************************************************/ + +ST_RET asciiToFloat (const ST_CHAR *astr, + ST_FLOAT *floatNum) + { +ST_CHAR *retPtr; +ST_DOUBLE doubleNum = 0.0; + + *floatNum = 0.0; + errno = 0; + + /* convert ascii string to double */ + doubleNum = strtod (astr, &retPtr); + if (retPtr == astr || errno != 0) + return (SD_FAILURE); /* conversion error */ + + if (fabs(doubleNum) > FLT_MAX) + /* value does not fit in range of ST_FLOAT */ + return SD_FAILURE; + + *floatNum = (ST_FLOAT) doubleNum; + return SD_SUCCESS; + } + +/************************************************************************/ +/* asciiToDouble */ +/************************************************************************/ + +ST_RET asciiToDouble (const ST_CHAR *astr, + ST_DOUBLE *doubleNum) + { +ST_CHAR *retPtr; + + *doubleNum = 0.0; + errno = 0; + + /* convert ascii string to double */ + *doubleNum = strtod (astr, &retPtr); + if (retPtr == astr || errno != 0) + return (SD_FAILURE); /* conversion error */ + + return SD_SUCCESS; + } + + +/************************************************************************/ +/************************************************************************/ +/* Base 10 Integer to ASCII Functions */ +/************************************************************************/ + +static char *lToStr(long int val,char *dst, int radix); + +ST_CHAR *sInt8ToAscii (ST_INT8 v, ST_CHAR *p) {lToStr ((long) v, p, -10); return p;} +ST_CHAR *uInt8ToAscii (ST_UINT8 v, ST_CHAR *p) {lToStr ((long) v, p, 10); return p;} +ST_CHAR *sInt16ToAscii (ST_INT16 v, ST_CHAR *p) {lToStr ((long) v, p, -10); return p;} +ST_CHAR *uInt16ToAscii (ST_UINT16 v, ST_CHAR *p) {lToStr ((long) v, p, 10); return p;} +ST_CHAR *sInt32ToAscii (ST_INT32 v, ST_CHAR *p) {lToStr ((long) v, p, -10); return p;} +ST_CHAR *uInt32ToAscii (ST_UINT32 v, ST_CHAR *p) {lToStr ((long) v, p, 10); return p;} +ST_CHAR *sIntToAscii (ST_INT v, ST_CHAR *p) {lToStr ((long) v, p, -10); return p;} +ST_CHAR *uIntToAscii (ST_UINT v, ST_CHAR *p) {lToStr ((long) v, p, 10); return p;} +ST_CHAR *sLongToAscii (ST_LONG v, ST_CHAR *p) {lToStr ((long) v, p, -10); return p;} +ST_CHAR *uLongToAscii (ST_ULONG v, ST_CHAR *p) {lToStr ((long) v, p, 10); return p;} + +static char *lToStr(long int val,char *dst, int radix) + { +char buffer[65]; +char *p; +long int new_val; + + if (radix < 0) /* -10 */ + { + if (val < 0) + { + *dst++ = '-'; + val = -val; + } + } + + p = &buffer[sizeof(buffer)-1]; + *p = '\0'; + new_val= (long) ((unsigned long int) val / 10); + *--p = '0'+ (char) ((unsigned long int) val - (unsigned long) new_val * 10); + val = new_val; + + while (val != 0) + { + new_val=val/10; + *--p = '0' + (char) (val-new_val*10); + val= new_val; + } + while ((*dst++ = *p++) != 0) ; + return dst-1; + } + +/************************************************************************/ +/************************************************************************/ + +#if 0 +#include "stime.h" + +int testItoA () + { +char dest[100]; +long numMs; +double endTime; +double startTime; +int i; + + startTime = sGetMsTime (); + for (i = 0; i < 100000; ++i) + sprintf (dest, "%ld", 698); + endTime = sGetMsTime (); + numMs = (long) (endTime - startTime); + printf ("\n sprintf took %ld ms", numMs); + + startTime = sGetMsTime (); + for (i = 0; i < 100000; ++i) + ltoa (698, dest, 10); + endTime = sGetMsTime (); + numMs = (long) (endTime - startTime); + printf ("\n ltoa took %ld ms", numMs); + + startTime = sGetMsTime (); + for (i = 0; i < 100000; ++i) + lToStr (698, dest); + endTime = sGetMsTime (); + numMs = (long) (endTime - startTime); + printf ("\n lToStr took %ld ms", numMs); + + lToStr (0, dest); + if (strcmp (dest, "0")) + printf ("\nError in lToStr (0, dest);"); + + lToStr (-1, dest); + if (strcmp (dest, "-1")) + printf ("\nError in lToStr (-1, dest);"); + + lToStr (1, dest); + if (strcmp (dest, "1")) + printf ("\nError in lToStr (1, dest);"); + + sInt16ToAscii (SHRT_MIN, dest); + if (strcmp (dest, "-32768")) + printf ("\nError in sInt16ToAscii (SHRT_MIN, dest);"); + + sInt16ToAscii (SHRT_MAX, dest); + if (strcmp (dest, "32767")) + printf ("\nError in sInt16ToAscii (SHRT_MAX, dest);"); + + uInt16ToAscii (USHRT_MAX, dest); + if (strcmp (dest, "65535")) + printf ("\nError in sUint16ToAscii (USHRT_MAX, dest);"); + + sIntToAscii (INT_MIN, dest); + if (strcmp (dest, "-2147483648")) + printf ("\nError in sIntToAscii (INT_MIN, dest);"); + + sIntToAscii (INT_MAX, dest); + if (strcmp (dest, "2147483647")) + printf ("\nError in sIntToAscii (INT_MAX, dest);"); + + uIntToAscii (UINT_MAX, dest); + if (strcmp (dest, "0xffffffff")) + printf ("\nError in sUintToAscii (UINT_MAX, dest);"); + + sLongToAscii (LONG_MIN, dest); + if (strcmp (dest, "-2147483648")) + printf ("\nError in sIntToAscii (INT_MIN, dest);"); + + sLongToAscii (LONG_MAX, dest); + if (strcmp (dest, "2147483647")) + printf ("\nError in sIntToAscii (INT_MAX, dest);"); + + uLongToAscii (ULONG_MAX, dest); + if (strcmp (dest, "4294967295")) + printf ("\nError in sUintToAscii (UINT_MAX, dest);"); + } +#endif + + +/************************************************************************/ +/* getKeywordFromFile */ +/*----------------------------------------------------------------------*/ +/* Function to check if given keyword is found in a specified text file.*/ +/* When found, keyword value (string) is copied to user buffer valBuf. */ +/* This function assumes that there is one keyword per line in the file */ +/* in the form: */ +/* keyword=val */ +/* Where val is an int, long, string, etc. */ +/* keywordStr should include the '=' char. */ +/* Line length is limited to 255 bytes. */ +/* Any NL or CR characters are eliminated from the end of line. */ +/* Parameters: */ +/* ST_CHAR *fileStr file to open */ +/* ST_CHAR *keywordStr keyword to look for in file */ +/* ST_CHAR *valBuf ptr where to put keyword value */ +/* ST_UINT valBufLen len of buffer for the value. */ +/* Return: */ +/* SD_TRUE if keyword found. */ +/* SD_FALSE otherwise */ +/************************************************************************/ +ST_BOOLEAN getKeywordFromFile (ST_CHAR *fileStr, ST_CHAR *keywordStr, + ST_CHAR *valBuf, ST_UINT valBufLen) +{ +ST_BOOLEAN ret = SD_FALSE; +ST_CHAR lineBuf[256]; +ST_CHAR *keywordPtr = NULL; /* set if keywordStr found */ +FILE *fd = NULL; +ST_INT i; +ST_INT copyLen; + + /* make sure we got some valid parameters */ + if (!fileStr || strlen(fileStr) == 0) + return (ret); + if (!keywordStr || strlen(keywordStr) == 0) + return (ret); + if (!valBuf || valBufLen == 0 || valBufLen >= sizeof(lineBuf)) + return (ret); + + /* open and read the file line by line */ + if ((fd = fopen (fileStr, "r")) != NULL) + { + memset (lineBuf, 0, sizeof(lineBuf)); + while (fgets(lineBuf, sizeof(lineBuf)-1, fd) != NULL) + { + /* eliminate any NL or CR characters from the end of line */ + for (i=0; iTEXT data conversion */ + +ST_CHAR *sxaLocalToText (ST_VOID *dataPtr, SD_CONST RUNTIME_TYPE *rtHead, ST_INT numRt) + { + return (sxaLocalToText2 (dataPtr, rtHead, numRt, + gTextBuf, /* Use global text buffer */ + sizeof (gTextBuf))); /* size of global text buffer */ + } + +/************************************************************************/ +/* sxaLocalToText2 */ +/* This function should be thread-safe as long as caller's "textBuf" */ +/* is not accessed by other threads. */ +/* NOTE: "ms_local_to_text" function produces better text for logging, */ +/* but this function produces text compatible with sxaTextToLocal.*/ +/************************************************************************/ +ST_CHAR *sxaLocalToText2 (ST_VOID *dataPtr, SD_CONST RUNTIME_TYPE *rtHead, ST_INT numRt, + ST_CHAR *textBuf, /* User buffer in which to write text */ + ST_UINT textBufSize) /* size of user buffer */ + { +SXD_CONTEXT sxdContext; +ST_CHAR tempDataBuf[TEMP_DATA_BUF_SIZE]; +ST_RET rtnVal; + +/* Make a global temporary buffer available (easier than calloc..) */ + sxdContext.sTmpData = (ST_CHAR *) tempDataBuf; + sxdContext.sxaTextWorkBuf = textBuf; /* save user buffer pointer */ + sxdContext.workBufLen = textBufSize; /* save user buffer size */ + + sxdContext.nStrLen = 0; + sxdContext.nDataIdx = 0; + sxdContext.nStringCount = 0; + + sxdContext.textDataErrorDetected = SD_FALSE; + + rtnVal = sxd_process_arb_data ((ST_CHAR *) dataPtr, rtHead, numRt, &sxdContext, + &sxaLocToTextTbl, NULL); + + if (rtnVal != SD_SUCCESS) + { + return (NULL); + } + + if (sxdContext.textDataErrorDetected) + { + return (NULL); + } + + /* Null terminate the string */ + sxdContext.sxaTextWorkBuf[sxdContext.nStrLen + 1] = 0; + + return (sxdContext.sxaTextWorkBuf); + } + +/************************************************************************/ +/* sxaLocToTextInt8 () */ +/************************************************************************/ + +static ST_RET sxaLocToTextInt8 (ST_VOID *usr, ST_INT8 *pSrc, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + sprintf (sxdContext->sTmpData,"%d", (ST_INT) *pSrc); + sxaAddString (usr, sxdContext->sTmpData); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sxaLocToTextInt16 () */ +/************************************************************************/ + +static ST_RET sxaLocToTextInt16 (ST_VOID *usr, ST_INT16 *pSrc, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + sprintf (sxdContext->sTmpData,"%d",(ST_INT) *pSrc); + sxaAddString (usr, sxdContext->sTmpData); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sxaLocToTextInt32 () */ +/************************************************************************/ + +static ST_RET sxaLocToTextInt32 (ST_VOID *usr, ST_INT32 *pSrc, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + sprintf (sxdContext->sTmpData,"%ld", (ST_LONG) *pSrc); + sxaAddString (usr, sxdContext->sTmpData); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sxaLocToTextInt64 () */ +/************************************************************************/ + +#if defined(INT64_SUPPORT) +static ST_RET sxaLocToTextInt64 (ST_VOID *usr, ST_INT64 *pSrc, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + sprintf (sxdContext->sTmpData, S_FMT_INT64, *pSrc); + sxaAddString (usr, sxdContext->sTmpData); + return SD_SUCCESS; + } +#endif + +/************************************************************************/ +/* sxaLocToTextUint8 () */ +/************************************************************************/ + +static ST_RET sxaLocToTextUint8 (ST_VOID *usr, ST_UINT8 *pSrc, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + sprintf (sxdContext->sTmpData,"%u",(ST_UINT) *pSrc); + sxaAddString (usr, sxdContext->sTmpData); + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaLocToTextUint16 () */ +/************************************************************************/ + +static ST_RET sxaLocToTextUint16 (ST_VOID *usr, ST_UINT16 *pSrc, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + sprintf (sxdContext->sTmpData,"%u",(ST_UINT) *pSrc); + sxaAddString (usr, sxdContext->sTmpData); + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaLocToTextUint32 () */ +/************************************************************************/ + +static ST_RET sxaLocToTextUint32 (ST_VOID *usr, ST_UINT32 *pSrc, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + sprintf (sxdContext->sTmpData,"%lu", (ST_ULONG) *pSrc); + sxaAddString (usr, sxdContext->sTmpData); + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaLocToTextUint64 () */ +/************************************************************************/ + +#if defined(INT64_SUPPORT) +static ST_RET sxaLocToTextUint64 (ST_VOID *usr, ST_UINT64 *pSrc, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + sprintf (sxdContext->sTmpData, S_FMT_UINT64, *pSrc); + sxaAddString (usr, sxdContext->sTmpData); + return SD_SUCCESS; + } +#endif + +/************************************************************************/ +/* sxaLocToTextBcd1 () */ +/************************************************************************/ + +static ST_RET sxaLocToTextBcd1 (ST_VOID *usr, ST_INT8 *pSrc, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + sprintf (sxdContext->sTmpData,"%d", (ST_INT) *pSrc); + sxaAddString (usr, sxdContext->sTmpData); + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaLocToTextBcd2 () */ +/************************************************************************/ + +static ST_RET sxaLocToTextBcd2 (ST_VOID *usr, ST_INT16 *pSrc, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + sprintf (sxdContext->sTmpData,"%d",(ST_INT) *pSrc); + sxaAddString (usr, sxdContext->sTmpData); + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaLocToTextBcd4 () */ +/************************************************************************/ + +static ST_RET sxaLocToTextBcd4 (ST_VOID *usr, ST_INT32 *pSrc, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + sprintf (sxdContext->sTmpData,"%ld", (ST_LONG) *pSrc); + sxaAddString (usr, sxdContext->sTmpData); + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaLocToTextBool () */ +/************************************************************************/ + +static ST_RET sxaLocToTextBool (ST_VOID *usr, ST_BOOLEAN *pSrc, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + sprintf (sxdContext->sTmpData,"%u",(ST_UINT) *pSrc); + sxaAddString (usr, sxdContext->sTmpData); + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaLocToTextFlt () */ +/************************************************************************/ + +static ST_RET sxaLocToTextFlt (ST_VOID *usr, ST_FLOAT *pSrc, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; +#if defined(_WIN32) || defined(__QNX__) + /* 7 significant digits */ + gcvt((ST_DOUBLE) *pSrc, 7, sxdContext->sTmpData); +#else + sprintf (sxdContext->sTmpData, "%.7g", (ST_DOUBLE) (*pSrc)); +#endif + sxaAddString (usr, sxdContext->sTmpData); + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaLocToTextDbl () */ +/************************************************************************/ + +static ST_RET sxaLocToTextDbl (ST_VOID *usr, ST_DOUBLE *pSrc, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; +#if defined(_WIN32) || defined(__QNX__) + /* 16 significant digits */ + gcvt(*pSrc, 16, sxdContext->sTmpData); +#else + sprintf (sxdContext->sTmpData, "%.16g", *pSrc); +#endif + sxaAddString (usr, sxdContext->sTmpData); + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaLocToTextStr () */ +/************************************************************************/ + +static ST_RET sxaLocToTextStr (ST_VOID *usr, ST_CHAR *pSrc, RUNTIME_TYPE *rt) + { + sxaAddString (usr, pSrc); + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaLocToTextOct */ +/************************************************************************/ + +static ST_RET sxaLocToTextOct (ST_VOID *usr, ST_UCHAR *pSrc, RUNTIME_TYPE *rt) + { +ST_INT i, k; +ST_INT numBytes; +ST_INT16 *sp; +ST_CHAR *destBuf; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + + sxdContext->sTmpData[0] = 0; + numBytes = rt->u.p.el_len; + + if (numBytes < 0) /* a variable length octet string */ + { + sp = (ST_INT16 *) pSrc; + numBytes = *sp; + k=2; + } + else + k=0; + + /* We take 3 bytes per octet, make sure it fits */ + if (numBytes > TEMP_DATA_BUF_SIZE/3) + { + SXLOG_NERR0 ("Octet String to encode too long"); + return SD_FAILURE; + } + + destBuf = sxdContext->sTmpData; + for (i = 0; i < numBytes; ++i, ++k) + { + sprintf (destBuf, "%02x ", (ST_UINT) pSrc[k]); + destBuf += 3; + } + + /* Eliminate the trailing space */ + *(destBuf - 1) = 0; + sxaAddString (usr, sxdContext->sTmpData); + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaLocToTextBs */ +/************************************************************************/ + +static ST_RET sxaLocToTextBs (ST_VOID *usr, ST_UCHAR *pSrc, RUNTIME_TYPE *rt) + { +ST_INT i; +ST_INT j; +ST_INT k; +ST_INT numBits; +ST_INT16 *sp; +ST_CHAR *destBuf; +ST_UCHAR mask; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + + sxdContext->sTmpData[0] = 0; + numBits = rt->u.p.el_len; + +/* We take 1 dest byte per bit, make sure it fits */ + if (numBits > TEMP_DATA_BUF_SIZE-1) + { + SXLOG_NERR0 ("Bit String to encode too long"); + return (SD_FAILURE); + } + + if (numBits < 0) /* a variable length bit string */ + { + sp = (ST_INT16 *) pSrc; + numBits = *sp; + k=2; + } + else + k=0; + + destBuf = sxdContext->sTmpData; + for (i = 0; i < numBits; ++k) /* for each byte, while bits remain */ + { + mask = 0x80; + for (j = 0; j < 8 && i < numBits; ++i, ++j) + { + if (pSrc[k] & mask) + destBuf[i] = '1'; + else + destBuf[i] = '0'; + mask >>= 1; + } + } + destBuf[i] = 0; + sxaAddString (usr, sxdContext->sTmpData); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sxaLocToTextBtime4 */ +/************************************************************************/ + +static ST_RET sxaLocToTextBtime4 (ST_VOID *usr, ST_INT32 *pSrc, RUNTIME_TYPE *rt) + { +ST_CHAR timeString[MAX_TIME_STRING_LEN]; + + if (Btime4ValsToString (timeString, *pSrc)) + { + SXLOG_NERR0 ("Btime4 String conversion error."); + return (SD_FAILURE); + } + + sxaAddString (usr, timeString); + return (SD_SUCCESS); + } + + +/************************************************************************/ +/* sxaLocToTextBtime6 */ +/************************************************************************/ + +static ST_RET sxaLocToTextBtime6 (ST_VOID *usr, ST_INT32 *pSrc, RUNTIME_TYPE *rt) + { +ST_INT32 *pDays, *pMsec; +ST_CHAR timeString[MAX_TIME_STRING_LEN]; + + pMsec = pSrc; + pDays = (pSrc+1); + if (Btime6ValsToString (timeString, *pDays, *pMsec)) + { + SXLOG_NERR0 ("Btime6 String conversion error."); + return (SD_FAILURE); + } + + sxaAddString (usr, timeString); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sxaLocToTextGtime */ +/************************************************************************/ + +static ST_RET sxaLocToTextGtime (ST_VOID *usr, time_t *pSrc, RUNTIME_TYPE *rt) + { +ST_CHAR timeString[MAX_TIME_STRING_LEN]; + + if (tstrTimeToString (*pSrc, timeString)) + { + SXLOG_NERR0 ("Time to String conversion error"); + return (SD_FAILURE); + } + + sxaAddString (usr, timeString); + return (SD_SUCCESS); + } +#if 0 +/************************************************************************/ +/* sxaLocToTextUtc */ +/************************************************************************/ + +static ST_RET sxaLocToTextUtc (ST_VOID *usr, MMS_UTC_TIME *pSrc, RUNTIME_TYPE *rt) + { + SXLOG_ERR0 ("sxaLocToTextUtc error: function not implemented"); + return (SD_FAILURE); + } +#endif +/************************************************************************/ +/* sxaAddString */ +/************************************************************************/ +/* This function is used to add a string to the working string buffer */ + +static ST_VOID sxaAddString (ST_VOID *usr, ST_CHAR *str) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + + /* Watch out for overrun */ + if ((sxdContext->nStrLen + strlen (str) + 3) >= sxdContext->workBufLen) + { + SXLOG_NERR0 ("Local->Text buffer overrun"); + sxdContext->textDataErrorDetected = SD_TRUE; + return; /* STOP: DO NOT write any more data to buffer */ + } + + /* If not the first one, need to add seperators */ + if (sxdContext->nStringCount > 0) + { +/* sxaTextWorkBuf[nStrLen++] = DATA_SEPARATOR; */ + sxdContext->sxaTextWorkBuf[sxdContext->nStrLen++] = DATA_SEPARATOR1; + sxdContext->sxaTextWorkBuf[sxdContext->nStrLen++] = DATA_SEPARATOR2; + sxdContext->sxaTextWorkBuf[sxdContext->nStrLen] = 0x00; + strcat (sxdContext->sxaTextWorkBuf,str); + } + else + strcpy (sxdContext->sxaTextWorkBuf,str); + + sxdContext->nStringCount++; + sxdContext->nStrLen += strlen (str); + } + +/************************************************************************/ +/************************************************************************/ +/* TEXT TO LOCAL DATA CONVERSION */ +/************************************************************************/ +/************************************************************************/ +/* This table is used as input to the MMS-EASE arbitrary data handling */ +/* function. All functions return SUCCESS or FAILURE */ + +static ST_RET sxaTextToLocBool (ST_VOID *usr, ST_BOOLEAN *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocInt8 (ST_VOID *usr, ST_INT8 *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocInt16 (ST_VOID *usr, ST_INT16 *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocInt32 (ST_VOID *usr, ST_INT32 *pDest, RUNTIME_TYPE *rt); +#if defined(INT64_SUPPORT) +static ST_RET sxaTextToLocInt64 (ST_VOID *usr, ST_INT64 *pDest, RUNTIME_TYPE *rt); +#endif +static ST_RET sxaTextToLocUint8 (ST_VOID *usr, ST_UINT8 *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocUint16 (ST_VOID *usr, ST_UINT16 *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocUint32 (ST_VOID *usr, ST_UINT32 *pDest, RUNTIME_TYPE *rt); +#if defined(INT64_SUPPORT) +static ST_RET sxaTextToLocUint64 (ST_VOID *usr, ST_UINT64 *pDest, RUNTIME_TYPE *rt); +#endif +static ST_RET sxaTextToLocBcd1 (ST_VOID *usr, ST_INT8 *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocBcd2 (ST_VOID *usr, ST_INT16 *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocBcd4 (ST_VOID *usr, ST_INT32 *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocFlt (ST_VOID *usr, ST_FLOAT *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocDbl (ST_VOID *usr, ST_DOUBLE *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocStr (ST_VOID *usr, ST_CHAR *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocOct (ST_VOID *usr, ST_UCHAR *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocBs (ST_VOID *usr, ST_UCHAR *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocBtime4 (ST_VOID *usr, ST_INT32 *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocBtime6 (ST_VOID *usr, ST_INT32 *pDest, RUNTIME_TYPE *rt); +static ST_RET sxaTextToLocGtime (ST_VOID *usr, time_t *pDest, RUNTIME_TYPE *rt); +#if 0 +static ST_RET sxaTextToLocUtc (ST_VOID *usr, MMS_UTC_TIME *pDest, RUNTIME_TYPE *rt); +#endif + +static SXD_ARB_DATA_CTRL sxaTextToLocTbl = + { + NULL, /* arrStart */ + NULL, /* arrEnd */ + NULL, /* strStart */ + NULL, /* strEnd */ + sxaTextToLocInt8, /* int8 */ + sxaTextToLocInt16, /* int16 */ + sxaTextToLocInt32, /* int32 */ +#if defined(INT64_SUPPORT) + sxaTextToLocInt64, /* int64 */ +#endif + sxaTextToLocUint8, /* uint8 */ + sxaTextToLocUint16, /* uint16 */ + sxaTextToLocUint32, /* uint32 */ +#if defined(INT64_SUPPORT) + sxaTextToLocUint64, /* uint64 */ +#endif + sxaTextToLocFlt, /* flt */ + sxaTextToLocDbl, /* dbl */ + sxaTextToLocOct, /* oct */ + sxaTextToLocBool, /* bool */ + sxaTextToLocBcd1, /* bcd1 */ + sxaTextToLocBcd2, /* bcd2 */ + sxaTextToLocBcd4, /* bcd4 */ + sxaTextToLocBs, /* bs */ + sxaTextToLocStr, /* visible str */ + sxaTextToLocBtime4, /* Bin Time */ + sxaTextToLocBtime6, /* Bin Time */ + sxaTextToLocGtime, /* Gen Time */ + NULL /* UTC Time */ + }; + +/************************************************************************/ +/* sxaTextToLocal */ +/************************************************************************/ +/* This is the main entry point for TEXT->LOCAL data conversion */ + +ST_RET sxaTextToLocal (ST_CHAR *pSource, ST_VOID *pDest, ST_INT numRt, SD_CONST RUNTIME_TYPE *rtHead) + { +SXD_CONTEXT sxdContext; +ST_CHAR tempDataBuf[TEMP_DATA_BUF_SIZE]; +ST_RET rtnVal; + +/* Make a global temporary buffer available (easier than calloc..) */ + sxdContext.sTmpData = tempDataBuf; + sxdContext.sxaTextWorkBuf = pSource; /* point to input string */ + sxdContext.nStrLen = strlen (sxdContext.sxaTextWorkBuf); + sxdContext.nDataIdx = 0; + sxdContext.nStringCount = 0; + + sxdContext.textDataErrorDetected = SD_FALSE; + + rtnVal = sxd_process_arb_data ((ST_CHAR *) pDest, rtHead, numRt, &sxdContext, + &sxaTextToLocTbl, NULL); + if (sxdContext.textDataErrorDetected) + rtnVal = SD_FAILURE; + + return (rtnVal); + } + +/************************************************************************/ +/* sxaTextToLocBool () */ +/************************************************************************/ + +static ST_RET sxaTextToLocBool (ST_VOID *usr, ST_BOOLEAN *pDest, RUNTIME_TYPE *rt) + { +ST_INT nDest; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string from the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* trim any leading blanks */ + leftTrim (sxdContext->sTmpData); + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckIntString (sxdContext->sTmpData) == SD_SUCCESS && + (sscanf (sxdContext->sTmpData, "%d", &nDest) == 1) && + (nDest >= 0 && nDest <= 255)) + { + *pDest = (ST_UCHAR) nDest; + } + else + { + SXLOG_NERR1 ("Text '%s' to Local error for type Boolean", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaTextToLocInt8 () */ +/************************************************************************/ + +static ST_RET sxaTextToLocInt8 (ST_VOID *usr, ST_INT8 *pDest, RUNTIME_TYPE *rt) + { +ST_INT nDest; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* trim any leading blanks */ + leftTrim (sxdContext->sTmpData); + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckIntString (sxdContext->sTmpData) == SD_SUCCESS && + (sscanf (sxdContext->sTmpData, "%d", &nDest) == 1) && + (nDest >= -128 && nDest <= 127)) + { + *pDest = (ST_CHAR) nDest; + } + else + { + SXLOG_NERR1 ("Text '%s' to Local error for type Integer8", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaTextToLocInt16 () */ +/************************************************************************/ + +static ST_RET sxaTextToLocInt16 (ST_VOID *usr, ST_INT16 *pDest, RUNTIME_TYPE *rt) + { +ST_INT32 nDest; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* trim any leading blanks */ + leftTrim (sxdContext->sTmpData); + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckIntString (sxdContext->sTmpData) == SD_SUCCESS && +#if (defined(__alpha) && !defined(__VMS)) + (sscanf (sxdContext->sTmpData, "%d", &nDest) == 1) && +#else + (sscanf (sxdContext->sTmpData, "%ld", &nDest) == 1) && +#endif + (nDest >= -32768 && nDest <= 32767)) + { + *pDest = (ST_INT16) nDest; + } + else + { + SXLOG_NERR1 ("Text '%s' to Local error for type Integer16", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaTextToLocInt32 () */ +/************************************************************************/ + +static ST_RET sxaTextToLocInt32 (ST_VOID *usr, ST_INT32 *pDest, RUNTIME_TYPE *rt) + { +ST_LONG nDest; +ST_CHAR temp[35]; +ST_CHAR *tempPtr; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* trim any leading blanks */ + leftTrim (sxdContext->sTmpData); + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckIntString (sxdContext->sTmpData) == SD_SUCCESS && + (sscanf (sxdContext->sTmpData, "%ld", &nDest) == 1)) + { +#if defined(_WIN32) || defined(__QNX__) + ltoa(nDest, temp, 10); +#else + sprintf (temp, "%ld", nDest); +#endif + + /* look out for leading zero's */ + if (nDest != 0L) + { + tempPtr = sxdContext->sTmpData; + while (tempPtr[0] == '0') + tempPtr++; + sxdContext->sTmpData = tempPtr; + } + + if (strcmp(sxdContext->sTmpData, temp)) + { + SXLOG_NERR1 ("Text '%s' to Local error for type Integer32", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + else + *pDest = nDest; + } + else + { + SXLOG_NERR1 ("Text '%s' to Local error for type Integer32", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaTextToLocInt64 () */ +/************************************************************************/ + +#if defined(INT64_SUPPORT) +static ST_RET sxaTextToLocInt64 (ST_VOID *usr, ST_INT64 *pDest, RUNTIME_TYPE *rt) + { +ST_INT64 nDest; +ST_CHAR temp[35]; +ST_CHAR *tempPtr; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* trim any leading blanks */ + leftTrim (sxdContext->sTmpData); + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckIntString (sxdContext->sTmpData) == SD_SUCCESS && + (sscanf (sxdContext->sTmpData, S_FMT_INT64, &nDest) == 1)) + { +#ifdef _WIN32 + _i64toa(nDest, temp, 10); +#else + sprintf (temp, S_FMT_INT64, nDest); +#endif + + /* look out for leading zero's */ + if (nDest != 0L) + { + tempPtr = sxdContext->sTmpData; + while (tempPtr[0] == '0') + tempPtr++; + sxdContext->sTmpData = tempPtr; + } + + if (strcmp(sxdContext->sTmpData, temp)) + { + SXLOG_NERR1 ("Text '%s' to Local error for type Integer64", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + else + *pDest = nDest; + } + else + { + SXLOG_NERR1 ("Text '%s' to Local error for type Integer64", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + return SD_SUCCESS; + } +#endif + +/************************************************************************/ +/* sxaTextToLocUint8 () */ +/************************************************************************/ + +static ST_RET sxaTextToLocUint8 (ST_VOID *usr, ST_UINT8 *pDest, RUNTIME_TYPE *rt) + { +ST_UINT nDest; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* trim any leading blanks */ + leftTrim (sxdContext->sTmpData); + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckUintString (sxdContext->sTmpData) == SD_SUCCESS && + (sscanf (sxdContext->sTmpData, "%d", &nDest) == 1) && + (nDest <= 255)) + { + *pDest = (ST_UCHAR) nDest; + } + else + { + SXLOG_NERR1 ("Text '%s' to Local error for type Unsigned8", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaTextToLocUint16 () */ +/************************************************************************/ + +static ST_RET sxaTextToLocUint16 (ST_VOID *usr, ST_UINT16 *pDest, RUNTIME_TYPE *rt) + { +ST_ULONG nDest; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* trim any leading blanks */ + leftTrim (sxdContext->sTmpData); + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckUintString (sxdContext->sTmpData) == SD_SUCCESS && + (sscanf (sxdContext->sTmpData, "%lu", &nDest) == 1) && + (nDest <= 65535)) + { + *pDest = (ST_UINT16) nDest; + } + else + { + SXLOG_NERR1 ("Text '%s' to Local error for type Unsigned16", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaTextToLocUint32 () */ +/************************************************************************/ + +static ST_RET sxaTextToLocUint32 (ST_VOID *usr, ST_UINT32 *pDest, RUNTIME_TYPE *rt) + { +ST_ULONG nDest; +ST_CHAR temp[35]; +ST_CHAR *tempPtr; +SXD_CONTEXT *sxdContext; + + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* Check for hex format */ + if (sxdContext->sTmpData[0] == '0' && sxdContext->sTmpData[1] == 'x') + { + if (sscanf (sxdContext->sTmpData, "0x%lx", &nDest) == 1) + { + *pDest = nDest; + return SD_SUCCESS; + } + } + +/* trim any leading blanks */ + leftTrim (sxdContext->sTmpData); + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckUintString (sxdContext->sTmpData) == SD_SUCCESS && + (sscanf (sxdContext->sTmpData, "%lu", &nDest) == 1)) + { +#if defined(_WIN32) || defined(__QNX__) + ultoa(nDest, temp, 10); +#else + sprintf (temp, "%lu", nDest); +#endif + + /* look out for leading zero's */ + if (nDest != 0L) + { + tempPtr = sxdContext->sTmpData; + while (tempPtr[0] == '0') + tempPtr++; + sxdContext->sTmpData = tempPtr; + } + + if (strcmp(sxdContext->sTmpData, temp)) + { + SXLOG_NERR1 ("Text '%s' to Local error for type Unsigned32", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + else + *pDest = nDest; + } + else + { + SXLOG_NERR1 ("Text '%s' to Local error for type Unsigned32", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + return SD_SUCCESS; + } + + +/************************************************************************/ +/* sxaTextToLocUint64 () */ +/************************************************************************/ + +#if defined(INT64_SUPPORT) +static ST_RET sxaTextToLocUint64 (ST_VOID *usr, ST_UINT64 *pDest, RUNTIME_TYPE *rt) + { +ST_UINT64 nDest; +ST_CHAR temp[35]; +ST_CHAR *tempPtr; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* trim any leading blanks */ + leftTrim (sxdContext->sTmpData); + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckUintString (sxdContext->sTmpData) == SD_SUCCESS && + (sscanf (sxdContext->sTmpData, S_FMT_UINT64, &nDest) == 1)) + { +#ifdef _WIN32 + _ui64toa(nDest, temp, 10); +#else + sprintf (temp, S_FMT_UINT64, nDest); +#endif + + /* look out for leading zero's */ + if (nDest != 0L) + { + tempPtr = sxdContext->sTmpData; + while (tempPtr[0] == '0') + tempPtr++; + sxdContext->sTmpData = tempPtr; + } + + if (strcmp(sxdContext->sTmpData, temp)) + { + SXLOG_NERR1 ("Text '%s' to Local error for type Unsigned64", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + else + *pDest = nDest; + } + else + { + SXLOG_NERR1 ("Text '%s' to Local error for type Unsigned64", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + return SD_SUCCESS; + } +#endif + +/************************************************************************/ +/* sxaTextToLocBcd1 () */ +/************************************************************************/ + +static ST_RET sxaTextToLocBcd1 (ST_VOID *usr, ST_INT8 *pDest, RUNTIME_TYPE *rt) + { +ST_INT nDest; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* trim any leading blanks */ + leftTrim (sxdContext->sTmpData); + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckIntString (sxdContext->sTmpData) == SD_SUCCESS && + (sscanf (sxdContext->sTmpData, "%d", &nDest) == 1)) + { + if ( (rt->u.p.el_len == 1) && (nDest >= 0 && nDest <= 9) ) + *pDest = (ST_CHAR) nDest; + else if ( (rt->u.p.el_len == 2) && (nDest >= 0 && nDest <= 99) ) + *pDest = (ST_CHAR) nDest; + else + { + SXLOG_NERR2 ("Text '%s' to Local error for type BCD%d", + sxdContext->sTmpData, rt->u.p.el_len); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + } + else + { + SXLOG_NERR1 ("Text '%s' to Local error for type BCD1", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaTextToLocBcd2 () */ +/************************************************************************/ + +static ST_RET sxaTextToLocBcd2 (ST_VOID *usr, ST_INT16 *pDest, RUNTIME_TYPE *rt) + { +ST_UINT nDest; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* trim any leading blanks */ + leftTrim (sxdContext->sTmpData); + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckIntString (sxdContext->sTmpData) == SD_SUCCESS && + (sscanf (sxdContext->sTmpData, "%u", &nDest) == 1)) + { + if ( (rt->u.p.el_len == 3) && (nDest <= 999) ) + *pDest = (ST_INT16) nDest; + else if ( (rt->u.p.el_len == 4) && (nDest <= 9999) ) + *pDest = (ST_INT16) nDest; + else + { + SXLOG_NERR2 ("Text '%s' to Local error for type BCD%d", + sxdContext->sTmpData, rt->u.p.el_len); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + } + else + { + SXLOG_NERR1 ("Text '%s' to Local error for type BCD2", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaTextToLocBcd4 () */ +/************************************************************************/ + + +static ST_RET sxaTextToLocBcd4 (ST_VOID *usr, ST_INT32 *pDest, RUNTIME_TYPE *rt) + { +ST_LONG nDest; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* trim any leading blanks */ + leftTrim (sxdContext->sTmpData); + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckIntString (sxdContext->sTmpData) == SD_SUCCESS && + (sscanf (sxdContext->sTmpData, "%ld", &nDest) == 1)) + { + if ( (rt->u.p.el_len == 5) && (nDest >= 0 && nDest <= 99999L) ) + *pDest = nDest; + else if ( (rt->u.p.el_len == 6) && (nDest >= 0 && nDest <= 999999L) ) + *pDest = nDest; + else if ( (rt->u.p.el_len == 7) && + (nDest >= 0 && (ST_ULONG) nDest <= 9999999L) ) + *pDest = nDest; + else if ( (rt->u.p.el_len == 8) && + ((ST_ULONG) nDest <= 99999999L) ) + *pDest = nDest; + else + { + SXLOG_NERR2 ("Text '%s' to Local error for type BCD%d", + sxdContext->sTmpData, rt->u.p.el_len); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + } + else + { + SXLOG_NERR1 ("Text '%s' to Local error for type BCD4", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaTextToLocFlt () */ +/************************************************************************/ + +static ST_RET sxaTextToLocFlt (ST_VOID *usr, ST_FLOAT *pDest, RUNTIME_TYPE *rt) + { +ST_DOUBLE dDest; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* trim any leading blanks */ + leftTrim (sxdContext->sTmpData); + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + if (sxaCheckFloatString (sxdContext->sTmpData) == SD_SUCCESS && + (sscanf (sxdContext->sTmpData, "%lf", &dDest) == 1)) + { + + *pDest = (ST_FLOAT) dDest; + + } + else + { + SXLOG_NERR1 ("Text '%s' to Local error for type Float", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaTextToLocDbl () */ +/************************************************************************/ + +static ST_RET sxaTextToLocDbl (ST_VOID *usr, ST_DOUBLE *pDest, RUNTIME_TYPE *rt) + { +ST_DOUBLE dDest; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* trim any leading blanks */ + leftTrim (sxdContext->sTmpData); + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckFloatString (sxdContext->sTmpData) == SD_SUCCESS && + (sscanf (sxdContext->sTmpData, "%lf", &dDest) == 1)) + { + *pDest = dDest; + } + else + { + SXLOG_NERR1 ("Text '%s' to Local error for type Double", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaTextToLocStr () */ +/************************************************************************/ + +static ST_RET sxaTextToLocStr (ST_VOID *usr, ST_CHAR *pDest, RUNTIME_TYPE *rt) + { +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + { + sxdContext->sTmpData[0] = 0x00; + } + + +/* Verify that the string will fit into the destination */ + if (strlen (sxdContext->sTmpData) > (ST_UINT) (rt->el_size - 1)) + { + sxdContext->textDataErrorDetected = SD_TRUE; + SXLOG_NERR2 ("String too long (%d max) : '%s'", (ST_INT) (rt->el_size - 1), + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + + strcpy (pDest, sxdContext->sTmpData); + return SD_SUCCESS; + } + + +/************************************************************************/ +/* sxaTextToLocOct */ +/************************************************************************/ + +static ST_RET sxaTextToLocOct (ST_VOID *usr, ST_UCHAR *pDest, RUNTIME_TYPE *rt) + { +ST_CHAR outData[TEMP_DATA_BUF_SIZE]; +ST_INT outDataLen; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckOctetString (sxdContext->sTmpData, outData, &outDataLen) != SD_SUCCESS) + { + SXLOG_NERR1 ("Text '%s' to Local error for type Octet String", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + + if (rt->u.p.el_len <0) + { + if (outDataLen > (ST_INT) abs(rt->u.p.el_len)) + { + SXLOG_NERR2 ("Octet String too long (%d max) : '%s'", + abs (rt->u.p.el_len), sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + *((ST_INT16 *) pDest) = (ST_INT16) outDataLen; + memcpy (pDest+2, outData, outDataLen); + } + else + { + if (outDataLen != (ST_INT) rt->u.p.el_len) + { + SXLOG_NERR2 ("Invalid Length Octet String (required length=%d octets) : '%s'", + rt->u.p.el_len, sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + memcpy (pDest, outData, outDataLen); + } + + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaTextToLocBs */ +/************************************************************************/ + +static ST_RET sxaTextToLocBs (ST_VOID *usr, ST_UCHAR *pDest, RUNTIME_TYPE *rt) + { +ST_CHAR outData[TEMP_DATA_BUF_SIZE]; +ST_INT outDataLen, bstringLength; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + +/* Verify the string contents are correct for the data type */ +/* then convert to local format */ + + if (sxaCheckBitString (sxdContext->sTmpData, outData, &outDataLen) != SD_SUCCESS) + { + SXLOG_NERR1 ("Text '%s' to Local error for type Bit String", + sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + + bstringLength = strlen(sxdContext->sTmpData); + if (rt->u.p.el_len <0) /* variable length bit string */ + { + if (bstringLength > abs(rt->u.p.el_len)) + { + SXLOG_NERR2 ("Variable Length Bit String too long (%d bits max) : '%s'", + abs(rt->u.p.el_len), sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + *((ST_INT16 *) pDest) = (ST_INT16) bstringLength; + memcpy (pDest+2, outData, outDataLen); + } + else + { + if (bstringLength != rt->u.p.el_len) + { + SXLOG_NERR2 ("Invlid Length Bit String (required length=%d bits) : '%s'", + rt->u.p.el_len, sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + memcpy (pDest, outData, outDataLen); + } + + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaTextToLocBtime4 */ +/************************************************************************/ + +static ST_RET sxaTextToLocBtime4 (ST_VOID *usr, ST_INT32 *pDest, RUNTIME_TYPE *rt) + { +ST_INT32 nDest; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + + if (Btime4StringToVals (sxdContext->sTmpData, &nDest)) + { + SXLOG_NERR1 ("Local Btime4 conversion error '%s'", sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + + memcpy(pDest, &nDest, sizeof(ST_INT32)); + return SD_SUCCESS; + } + + +/************************************************************************/ +/* sxaTextToLocBtime6 */ +/************************************************************************/ + +static ST_RET sxaTextToLocBtime6 (ST_VOID *usr, ST_INT32 *pDest, RUNTIME_TYPE *rt) + { +ST_INT32 nDest[2]; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + + if (Btime6StringToVals (sxdContext->sTmpData, &nDest[1], &nDest[0])) + { + SXLOG_NERR1 ("Local Btime6 conversion error '%s'", sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + + memcpy(pDest, nDest, 2*sizeof(ST_INT32)); + return SD_SUCCESS; + } + +/************************************************************************/ +/* sxaTextToLocGtime */ +/************************************************************************/ + +static ST_RET sxaTextToLocGtime (ST_VOID *usr, time_t *pDest, RUNTIME_TYPE *rt) + { +time_t t; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Get the next sub-string frm the source string into 'sTmpData' */ + if (sxaGetNextString (usr) != SD_SUCCESS) + return SD_FAILURE; + + if (tstrStringToTime (sxdContext->sTmpData, &t)) + { + SXLOG_NERR1 ("Local time conversion error '%s'", sxdContext->sTmpData); + sxdContext->textDataErrorDetected = SD_TRUE; + return SD_FAILURE; + } + + *pDest = t; + return SD_SUCCESS; + } + +#if 0 +/************************************************************************/ +/* sxaTextToLocUtc */ +/************************************************************************/ + +static ST_RET sxaTextToLocUtc (ST_VOID *usr, MMS_UTC_TIME *pDest, RUNTIME_TYPE *rt) + { + SXLOG_ERR0 ("sxaTextToLocUtc error: function not implemented"); + return (SD_FAILURE); + } +#endif + +/************************************************************************/ +/************************************************************************/ +/* sxaGetNextString */ +/************************************************************************/ +/* Get the next sub-string frm the source string into 'sTmpData' */ + +static ST_INT sxaGetNextString (ST_VOID *usr) + { +ST_INT nCount; +ST_INT nIdx; +ST_CHAR c; +SXD_CONTEXT *sxdContext; + + sxdContext = (SXD_CONTEXT *) usr; + +/* Copy the data from data buffer to temporary data buffer. */ +/* Start at the current position, strip off learing delimiters, */ +/* accept characters until the next delimiter */ +/* */ +/* CF_TEXT: Each line ends with a carriage return/linefeed combination.*/ +/* A null character signals the end of the data. */ + nCount = 0; + nIdx = sxdContext->nDataIdx; + while (sxdContext->nStrLen > 0) + { + sxdContext->nStrLen--; + c = sxdContext->sxaTextWorkBuf[nIdx++]; + if (c == 0x00 || c == 0x0d) + { + break; /* This is the end of this component of the string */ + } + + sxdContext->sTmpData[nCount++] = c; + } + + while (sxdContext->nStrLen > 0) + { + c = sxdContext->sxaTextWorkBuf[nIdx]; + if (c != 0x00 && c != 0x0a ) + { + break; /* This is strips out the linefeed */ + } + nIdx++; + sxdContext->nStrLen--; + } + + sxdContext->nDataIdx = nIdx; + sxdContext->sTmpData[nCount] = 0x00; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* leftTrim: remove leading spaces from text string */ +/************************************************************************/ + +static ST_VOID leftTrim (ST_CHAR *pString) + { +ST_CHAR outData[TEMP_DATA_BUF_SIZE]; +ST_INT len, startPos=0, i=0; + + len = (strlen (pString)); + if (!len) + return; + + strcpy (outData, pString); + while (i 2000) + return (SD_FAILURE); /* length too long */ + digit = *p++; /* separate nibbles */ + digit = isdigit (digit) ? digit - '0' : 10 + (toupper (digit) - 'A'); + if (nibble) + { + nibble = 0; + /* set low byte */ + pOutData[i] = (pOutData[i] | (ST_CHAR) digit); + i++; + SkipWhiteSpace (&p); + } + else + { + nibble = 1; + pOutData[i] = (ST_CHAR) digit << 4; /* set high byte*/ + } + } + } + } + + /* set data length */ + if (nibble == 0) + *pOutLen = i; + else + return (SD_FAILURE); + + return (SD_SUCCESS); + } + + +/************************************************************************/ +/* sxaCheckBitString */ +/************************************************************************/ +/* Verify that this is valid bitstring data */ + +static ST_INT sxaCheckBitString (ST_CHAR *pC, ST_CHAR *pOutData, ST_INT *pOutLen) + { +ST_CHAR *p = pC; +ST_INT i, j; +ST_UCHAR mask; + + i = 0; + j = 0; + mask = 0x80; + while (*p != '\0') + { + + switch (*p) + { + case '0': + pOutData[i] &= ~mask; + break; + + case '1': + pOutData[i] |= mask; + break; + + default: + return (SD_FAILURE); + break; + } + + j++; /* check next bit */ + mask >>= 1; + + if (j == 8) + { + i++; /* do next byte */ + j = 0; + mask = 0x80; + } + + p++; + } + + if (j > 0) + i++; + *pOutLen = i; + + return (SD_SUCCESS); + } + diff --git a/mmslib/util/sx_data.c b/mmslib/util/sx_data.c new file mode 100644 index 0000000..e178e62 --- /dev/null +++ b/mmslib/util/sx_data.c @@ -0,0 +1,2601 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999 - 2008, All Rights Reserved */ +/* */ +/* MODULE NAME : sx_data.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* sxd_process_arb_data */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/30/08 EJV 37 sprintf,sscanf: use S_FMT_* macros for ST_INT64 */ +/* 01/30/06 GLB 36 Integrated porting changes for VMS */ +/* 08/01/05 JRB 35 Avoid risky cast to remove const. */ +/* 09/01/04 EJV 34 Added new include "sx_arb.h" */ +/* 03/16/04 EJV 33 Added ST_(U)LONG typecast to sprintf,on some */ +/* sys ST_(U)INT32 can be (unsigned) long or int*/ +/* Use SISCO types in place of C types. */ +/* 01/23/04 MDE 32 Added type ID validity checking */ +/* 01/13/04 JRB 31 Add LYNX support. */ +/* 01/08/04 EJV 30 Ported 64-bit funcs to sun. Corr (__hpux). */ +/* 10/13/03 EJV 29 Replaced defined(QNX) with defined(__QNX__). */ +/* 04/29/03 JRB 28 Use MAX_IDENT_LEN define. */ +/* 04/14/03 JRB 27 Add linux support. Use #error. */ +/* 04/02/03 JRB 26 Add UTF8string support (see RT_UTF8_STRING). */ +/* 12/11/02 MDE 25 Now include 'mvl_defs.h' */ +/* 12/02/02 MDE 24 Fixed elPres handling */ +/* 04/24/02 EJV 23 Added DEBUG_SISCO for thisFileName */ +/* 04/17/02 EJV 22 sxd_process_arb_data: added RT_UTC_TIME case */ +/* _sxdEncArbFuns: added NULL for 'utc' fun */ +/* 04/08/02 MDE 21 Added NO_MVL ifdefs to support mmslog */ +/* 03/06/02 JRB 20 Add more SD_CONST. Comment out unused statics*/ +/* 02/26/02 EJV 19 strStart: added SD_CONST for rt_head param. */ +/* Eliminated some warnings on VXWORKS. */ +/* Moved limits.h to sysincs.h and INT_MAX check*/ +/* 02/25/02 EJV 18 _AIX: replace itoa, ltoa with ANSI sprintf */ +/* hex_to_ascii_str: added param hex_no_spaces. */ +/* 11/26/01 EJV 17 _sxdDecInt64: fixed logging. */ +/* 09/13/01 JRB 16 Add limits.h so INT_MAX & LONG_MAX defined. */ +/* 08/10/01 EJV 15 _sxdDecUint32: eliminated warning on QNX. */ +/* 06/22/01 EJV 14 Reworked decode of arrays and releated chgs. */ +/* Added rt_head param to _sxdEncStrStart. */ +/* Moved globals _sxdPrefix, _sxdCurrNestLevel */ +/* to SX_END_CTRL (to be thread safe). */ +/* Implemented INT64 funcs: _sxdDecInt64,... */ +/* 05/21/01 MDE 13 Fixed overwrite problem with bad data */ +/* 05/21/01 MDE 12 Changed to work with all RUNTIME_TYPE */ +/* 03/21/01 MDE 11 Fixed bitstring decode for variable len bs */ +/* 03/21/01 MDE 10 Moved sx arb handling defines to sx_defs.h */ +/* 02/28/01 EJV 09 _AIX: use itoa, ltoa instead of slow sprintf */ +/* 02/22/01 MDE 08 Changes to support SXD style selections */ +/* 02/22/01 MDE 07 Allow QNX & Win32 to use itoa, ltoa */ +/* 01/24/01 EJV 06 Replaced non-ANSI itoa, ltoa with sprintf. */ +/* SXD_ARB_DATA_CTRL:replaced bool with booln */ +/* (bool may conflict with C++ compiler). */ +/* Corrected conversion in _sxdEncDbl. */ +/* 01/08/01 EJV 05 Removed unused _writePos from _sxdDecBs. */ +/* 01/04/01 MDE 04 Always define MVL_DYN_ASN1_TYPES */ +/* 12/28/00 KCR 03 Removed unpaired S_LOCK_COMMON_RESOURCES() */ +/* 11/06/00 DWL 02 Modified sx_write_element and sx_end_element */ +/* calls with added parameter */ +/* 10/10/00 MDE 01 New */ +/************************************************************************/ + +#include "glbtypes.h" +#include "sysincs.h" +#include "glbsem.h" +#include "mms_def2.h" +#include "mms_mp.h" +#include "mms_pvar.h" +#include "mms_vvar.h" +#include "time_str.h" +#include "str_util.h" +#include "mem_chk.h" + +#include "sx_defs.h" +#include "sx_arb.h" +#include "sx_log.h" + +#if defined(MMS_LITE) && !defined(NO_MVL) +#include "mvl_defs.h" +#endif + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ +/************************************************************************/ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ +/* sxd_get_runtime */ +/************************************************************************/ + +#if defined(MMS_LITE) && !defined(NO_MVL) + +ST_RET sxd_get_runtime (ST_INT type_id, + RUNTIME_TYPE **rt_out, ST_INT *num_rt_out) + { + if (type_id >= 0 && type_id < mvl_num_types && + mvl_type_ctrl[type_id].num_rt > 0) + { + *rt_out = mvl_type_ctrl[type_id].rt; + *num_rt_out = mvl_type_ctrl[type_id].num_rt; + return (SD_SUCCESS); + } + return (SD_FAILURE); + } + +#endif + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* sxd_process_arb_data */ +/************************************************************************/ + +ST_RET sxd_process_arb_data (ST_CHAR *datptr, SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, ST_VOID *usr, + SXD_ARB_DATA_CTRL *ac, ST_BOOLEAN *elPres) + { +RUNTIME_TYPE *rt_ptr; +RUNTIME_TYPE *rt_end; +ST_RET uDataRet; +ST_INT arr_loop_level; +ST_INT arr_loops[ASN1_MAX_LEVEL]; + + arr_loop_level = 0; + + rt_ptr = (RUNTIME_TYPE *) rt_head; /* point to head rt_block */ + rt_end = rt_ptr + rt_num; /* done when pointer is here */ + + uDataRet = SD_SUCCESS; + while (rt_ptr < rt_end && uDataRet == SD_SUCCESS) + { + if (rt_ptr->el_tag == RT_ARR_END) /* treat case of array ending */ + { + if (--arr_loops[arr_loop_level] > 0) /* if need to do next ar elmnt */ + rt_ptr -= rt_ptr->u.arr.num_rt_blks; /* mv rt_ptr to start of arr */ + else + --arr_loop_level; + } + if (rt_ptr->el_tag == RT_ARR_START) /* treat case of array starting */ + { + /* initialize the loop counter for the array */ + ++arr_loop_level; + arr_loops[arr_loop_level] = rt_ptr->u.arr.num_elmnts; + } + + if (elPres != NULL) + { + if (elPres[rt_ptr - rt_head] != SD_TRUE) + { + datptr += rt_ptr->el_size; /* Adjust data pointer */ + rt_ptr++; /* point to next rt element */ + continue; + } + } + + switch (rt_ptr->el_tag) + { + case RT_ARR_START : + if (ac->arrStart) + uDataRet = (*ac->arrStart) (usr, rt_ptr); + break; + + case RT_STR_START : + if (ac->strStart) + uDataRet = (*ac->strStart) (usr, rt_ptr, rt_head); + break; + + case RT_ARR_END : /* array done */ + if (ac->arrEnd) + uDataRet = (*ac->arrEnd) (usr, rt_ptr); + break; + + case RT_STR_END : /* structure done */ + if (ac->strEnd) + uDataRet = (*ac->strEnd) (usr, rt_ptr); + break; + + case RT_BOOL : + if (ac->booln) + uDataRet = (*ac->booln) (usr, (ST_BOOLEAN *) datptr, rt_ptr); + break; + + case RT_BIT_STRING : + if (ac->bs) + uDataRet = (*ac->bs) (usr, (ST_UCHAR *) datptr, rt_ptr); + break; + + case RT_INTEGER : + switch (rt_ptr->u.p.el_len) /* determine length */ + { + case 1 : /* one byte int */ + if (ac->int8) + uDataRet = (*ac->int8) (usr, (ST_INT8 *) datptr, rt_ptr); + break; + + case 2 : /* two byte int */ + if (ac->int16) + uDataRet = (*ac->int16) (usr, (ST_INT16 *) datptr, rt_ptr); + break; + + case 4 : /* four byte integer */ + if (ac->int32) + uDataRet = (*ac->int32) (usr, (ST_INT32 *) datptr, rt_ptr); + break; + +#ifdef INT64_SUPPORT + case 8 : /* eight byte integer */ + if (ac->int64) + uDataRet = (*ac->int64) (usr, (ST_INT64 *) datptr, rt_ptr); +#endif + break; + } + break; + + case RT_UNSIGNED : + switch (rt_ptr->u.p.el_len) /* determine length */ + { + case 1 : /* one byte int */ + if (ac->uint8) + uDataRet = (*ac->uint8) (usr, (ST_UCHAR *) datptr, rt_ptr); + break; + + case 2 : /* two byte int */ + if (ac->uint16) + uDataRet = (*ac->uint16) (usr, (ST_UINT16 *) datptr, rt_ptr); + break; + + case 4 : /* four byte integer */ + if (ac->uint32) + uDataRet = (*ac->uint32) (usr, (ST_UINT32 *) datptr, rt_ptr); + break; + +#ifdef INT64_SUPPORT + case 8 : /* eight byte integer */ + if (ac->uint64) + uDataRet = (*ac->uint64) (usr, (ST_UINT64 *) datptr, rt_ptr); + break; +#endif /* INT64_SUPPORT */ + } + break; + +#ifdef FLOAT_DATA_SUPPORT + case RT_FLOATING_POINT : + if (rt_ptr->u.p.el_len != sizeof (ST_FLOAT)) + { + if (ac->dbl) + uDataRet = (*ac->dbl) (usr, (ST_DOUBLE *) datptr, rt_ptr); + } + else + { + if (ac->flt) + uDataRet = (*ac->flt) (usr, (ST_FLOAT *) datptr, rt_ptr); + } + break; +#endif + + case RT_OCTET_STRING : + if (ac->oct) + uDataRet = (*ac->oct) (usr, (ST_UCHAR *) datptr, rt_ptr); + break; + + case RT_VISIBLE_STRING : + if (ac->vis) + uDataRet = (*ac->vis) (usr, (ST_CHAR *) datptr, rt_ptr); + break; + +#ifdef TIME_DATA_SUPPORT + case RT_GENERAL_TIME : + if (ac->gt) + uDataRet = (*ac->gt) (usr, (time_t *) datptr, rt_ptr); + break; +#endif + +#ifdef BTOD_DATA_SUPPORT + case RT_BINARY_TIME : + switch (rt_ptr->u.p.el_len) /* determine length */ + { + case 4: + if (ac->bt4) + uDataRet = (*ac->bt4) (usr, (ST_INT32 *) datptr, rt_ptr); + break; + case 6: + if (ac->bt6) + uDataRet = (*ac->bt6) (usr, (ST_INT32 *) datptr, rt_ptr); + break; + } + break; +#endif + + case RT_BCD : + if (rt_ptr->u.p.el_len <= 2) + { + if (ac->bcd1) + uDataRet = (*ac->bcd1) (usr, (ST_INT8 *) datptr, rt_ptr); + } + else if (rt_ptr->u.p.el_len <= 4) + { + if (ac->bcd2) + uDataRet = (*ac->bcd2) (usr, (ST_INT16 *) datptr, rt_ptr); + } + else if (rt_ptr->u.p.el_len <= 8) + { + if (ac->bcd4) + uDataRet = (*ac->bcd4) (usr, (ST_INT32 *) datptr, rt_ptr); + } + break; + + case RT_UTC_TIME : + if (ac->utc) + uDataRet = (*ac->utc) (usr, (MMS_UTC_TIME *) datptr, rt_ptr); + break; + + case RT_UTF8_STRING : + if (ac->utf8) + uDataRet = (*ac->utf8) (usr, (ST_UCHAR *) datptr, rt_ptr); + break; + + default : /* should not be any other tag */ + SXLOG_ERR1 ("Invalid tag: %d", (int) rt_ptr->el_tag); + return (SD_FAILURE); + break; + } + + datptr += rt_ptr->el_size; /* Adjust data pointer */ + rt_ptr++; /* point to next rt element */ + } + return (uDataRet); + } + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +static ST_RET _sxdStripPrefix (ST_CHAR *prefix); +static ST_RET _sxdEncElement (SX_ENC_CTRL *ec, RUNTIME_TYPE *rt, + ST_CHAR *dtString, ST_CHAR *contents); + +/************************************************************************/ + +/* XML data type strings */ +static ST_CHAR _boolDtStr[] = "Bool"; +static ST_CHAR _visStringDtStr[] = "VisString"; +static ST_CHAR _bitStringDtStr[] = "BitString"; +static ST_CHAR _i1DtStr[] = "I1"; +static ST_CHAR _i2DtStr[] = "I2"; +static ST_CHAR _i4DtStr[] = "I4"; +static ST_CHAR _uI1DtStr[] = "UI1"; +static ST_CHAR _uI2DtStr[] = "UI2"; +static ST_CHAR _uI4DtStr[] = "UI4"; +static ST_CHAR _r4DtStr[] = "R4"; +static ST_CHAR _r8DtStr[] = "R8"; +static ST_CHAR _dateTimeDtStr[] = "DateTime"; +static ST_CHAR _binHexDtStr[] = "BinHex"; +#ifdef INT64_SUPPORT /* Only if INT64 supported*/ +static ST_CHAR _i8DtStr[] = "I8"; +static ST_CHAR _uI8DtStr[] = "UI8"; +#endif +#if 0 /* These not used yet. */ +static ST_CHAR _charDtStr[] = "Char"; +static ST_CHAR _octStringDtStr[] = "OctString"; +static ST_CHAR _dateDtStr[] = "Date"; +static ST_CHAR _dateTimeTzDtStr[] = "DateTimeTz"; +static ST_CHAR _timeDtStr[] = "Time"; +static ST_CHAR _timeTzDtStr[] = "TimeTz"; +static ST_CHAR _binDtStr[] = "Bin"; +static ST_CHAR _binBase64DtStr[] = "BinBase64"; +static ST_CHAR _uriDtStr[] = "Uri"; +static ST_CHAR _udtDtStr[] = "Udt"; +#endif + +ST_INT sxdDefXmlStyle; /* Note: 0 is style A */ + +/************************************************************************/ +/* _sxdStripPrefix */ +/************************************************************************/ +static ST_RET _sxdStripPrefix (ST_CHAR *prefix) + { + ST_INT i; + + if (prefix) + { + i = strlen (prefix) - 1; + while (--i > 0) + { + if (prefix[i] == '.') + { + prefix[i+1] = 0; /* keep the dot with remaining prefix */ + break; + } + } + /* if i=0 then dot not found, this must be the first nest level */ + if (i == 0) + prefix[0] = 0; + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* _sxdEncArrStart */ +/************************************************************************/ + +static ST_RET _sxdEncArrStart (ST_VOID *usr, RUNTIME_TYPE *rt) + { + + /* Nothing to do here, the function _sxdEncElement is encoding */ + /* the element<=>array name. */ + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdEncArrEnd */ +/************************************************************************/ + +static ST_RET _sxdEncArrEnd (ST_VOID *usr, RUNTIME_TYPE *rt) + { + + /* Nothing to do here. */ + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdEncStrStart */ +/************************************************************************/ + +static ST_RET _sxdEncStrStart (ST_VOID *usr, RUNTIME_TYPE *rt, + SD_CONST RUNTIME_TYPE *rt_head) + { +SX_ENC_CTRL *ec; +SD_CONST ST_CHAR *elName = ""; /* init to an empty string */ +RUNTIME_TYPE *rt_tmp; + + ec = (SX_ENC_CTRL *) usr; + if (ms_comp_name_pres(rt) == SD_TRUE) + elName = ms_comp_name_find(rt); + else + { + /* name is NULL, it must be the outer element of struct within array */ + if (rt == rt_head) + { + elName = ec->outerElement; + if (elName == NULL) + return (SD_SUCCESS); /* nothing to encode */ + } + else + { + /* check if array of structs (check previous RTs) */ + rt_tmp = rt - 1; + while (rt_tmp->el_tag == RT_ARR_START) + { + if (ms_comp_name_pres(rt_tmp) == SD_TRUE) + { + elName = ms_comp_name_find(rt_tmp); + break; + } + --rt_tmp; + } + } + } + + if (ec->sxdXmlStyle == SXD_XML_STYLE_A) + { + if (ec->sxdStructNestLevel == 0) + { + *(ec->nextWritePos++) = '<'; + sx_add_string (ec, elName, &ec->nextWritePos); + } + else /* Not the outer element */ + { + strcat (ec->sxdPrefix, elName); + strcat (ec->sxdPrefix, "."); + } + ++ec->sxdStructNestLevel; + } + else if (ec->sxdXmlStyle == SXD_XML_STYLE_V || + ec->sxdXmlStyle == SXD_XML_STYLE_C) + { + sx_start_element ((SX_ENC_CTRL *) usr, elName, 0, NULL); + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdEncStrEnd */ +/************************************************************************/ + +static ST_RET _sxdEncStrEnd (ST_VOID *usr, RUNTIME_TYPE *rt) + { +SX_ENC_CTRL *ec; + + ec = (SX_ENC_CTRL *) usr; + + if (ec->sxdXmlStyle == SXD_XML_STYLE_A) + { + if (ms_comp_name_pres(rt) == SD_FALSE && ec->outerElement == NULL) + return (SD_SUCCESS); + + --ec->sxdStructNestLevel; + + if (ec->sxdStructNestLevel == 0) + { + /* this is end of XML */ + *(ec->nextWritePos++) = '/'; + *(ec->nextWritePos++) = '>'; + } + else + { + /* Not the outer element or the first level, remove the last prefix */ + _sxdStripPrefix (ec->sxdPrefix); + } + } + else if (ec->sxdXmlStyle == SXD_XML_STYLE_V || + ec->sxdXmlStyle == SXD_XML_STYLE_C) + { + /* encode struct end tag */ + if (ec->currNestLevel > 0) + sx_end_element ((SX_ENC_CTRL *) usr); + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* _sxdEncInt8 */ +/************************************************************************/ + +static ST_RET _sxdEncInt8 (ST_VOID *usr, ST_INT8 *data_ptr, RUNTIME_TYPE *rt) + { +ST_INT intVal; +ST_CHAR buf[50]; + + intVal = (ST_INT) (*data_ptr); +#if defined(_WIN32) || defined(__QNX__) + itoa (intVal, buf, 10); +#else + sprintf (buf, "%d", intVal); +#endif + return (_sxdEncElement ((SX_ENC_CTRL *) usr, rt, _i1DtStr, buf)); + } + +/************************************************************************/ +/* _sxdEncInt16 */ +/************************************************************************/ + +static ST_RET _sxdEncInt16 (ST_VOID *usr, ST_INT16 *data_ptr, RUNTIME_TYPE *rt) + { +ST_INT intVal; +ST_CHAR buf[50]; + + intVal = (ST_INT) *data_ptr; +#if defined(_WIN32) || defined(__QNX__) + itoa (intVal, buf, 10); +#else + sprintf (buf, "%d", intVal); +#endif + return (_sxdEncElement ((SX_ENC_CTRL *) usr, rt, _i2DtStr, buf)); + } + +/************************************************************************/ +/* _sxdEncInt32 */ +/************************************************************************/ + +static ST_RET _sxdEncInt32 (ST_VOID *usr, ST_INT32 *data_ptr, RUNTIME_TYPE *rt) + { +ST_LONG long_val; +ST_CHAR buf[50]; + + long_val = (ST_LONG) *data_ptr; +#if defined(_WIN32) || defined(__QNX__) + ltoa (long_val, buf, 10); +#else + sprintf (buf, "%ld", long_val); +#endif + return (_sxdEncElement ((SX_ENC_CTRL *) usr, rt, _i4DtStr, buf)); + } + +/************************************************************************/ +/* _sxdEncInt64 */ +/************************************************************************/ +#ifdef INT64_SUPPORT + +static ST_RET _sxdEncInt64 (ST_VOID *usr, ST_INT64 *data_ptr, RUNTIME_TYPE *rt) + { +ST_INT64 i64_val; +ST_CHAR buf[80]; + + i64_val = (ST_INT64) *data_ptr; +#ifdef _WIN32 + _i64toa (i64_val, buf, 10); +#else + sprintf (buf, S_FMT_INT64, i64_val); +#endif + return (_sxdEncElement (usr, rt, _i8DtStr, buf)); + } +#endif + +/************************************************************************/ +/* _sxdEncUint8 */ +/************************************************************************/ + +static ST_RET _sxdEncUint8 (ST_VOID *usr, ST_UINT8 *data_ptr, RUNTIME_TYPE *rt) + { +ST_UINT uintVal; +ST_CHAR buf[50]; + + uintVal = (ST_UINT) *data_ptr; +#if defined(_WIN32) || defined(__QNX__) + itoa ((int) uintVal, buf, 10); +#else + sprintf (buf, "%u", uintVal); +#endif + return (_sxdEncElement ((SX_ENC_CTRL *) usr, rt, _uI1DtStr, buf)); + } + +/************************************************************************/ +/* _sxdEncUint16 */ +/************************************************************************/ + +static ST_RET _sxdEncUint16(ST_VOID *usr, ST_UINT16 *data_ptr, RUNTIME_TYPE *rt) + { +ST_LONG long_val; +ST_CHAR buf[50]; + + long_val = (ST_LONG) *data_ptr; +#if defined(_WIN32) || defined(__QNX__) + ltoa (long_val, buf, 10); +#else + sprintf (buf, "%u", (ST_UINT) long_val); +#endif + return (_sxdEncElement ((SX_ENC_CTRL *) usr, rt, _uI2DtStr, buf)); + } + +/************************************************************************/ +/* _sxdEncUint32 */ +/************************************************************************/ + +static ST_RET _sxdEncUint32(ST_VOID *usr, ST_UINT32 *data_ptr, RUNTIME_TYPE *rt) + { +ST_ULONG ulong_val; +ST_CHAR buf[50]; + + ulong_val = (ST_ULONG) *data_ptr; +#if defined(_WIN32) || defined(__QNX__) + ultoa (ulong_val, buf, 10); +#else + sprintf (buf, "%lu", ulong_val); +#endif + return (_sxdEncElement ((SX_ENC_CTRL *) usr, rt, _uI4DtStr, buf)); + } + +/************************************************************************/ +/* _sxdEncUint64 */ +/************************************************************************/ +#ifdef INT64_SUPPORT + +static ST_RET _sxdEncUint64(ST_VOID *usr, ST_UINT64 *data_ptr, RUNTIME_TYPE *rt) + { +ST_UINT64 u64_val; +ST_CHAR buf[80]; + + u64_val = (ST_INT64) *data_ptr; +#ifdef _WIN32 + _ui64toa (u64_val, buf, 10); +#else + sprintf (buf, S_FMT_UINT64, u64_val); +#endif + return (_sxdEncElement (usr, rt, _uI8DtStr, buf)); + } +#endif + +/************************************************************************/ +/* _sxdEncFlt */ +/************************************************************************/ + +static ST_RET _sxdEncFlt (ST_VOID *usr, ST_FLOAT *data_ptr, RUNTIME_TYPE *rt) + { +ST_DOUBLE d; +ST_CHAR buf[100]; + + d = (ST_DOUBLE) (*(ST_FLOAT *) data_ptr); + sprintf (buf,"%.10f", d); + return (_sxdEncElement ((SX_ENC_CTRL *) usr, rt, _r4DtStr, buf)); + } + +/************************************************************************/ +/* _sxdEncDbl */ +/************************************************************************/ + +static ST_RET _sxdEncDbl (ST_VOID *usr, ST_DOUBLE *data_ptr, RUNTIME_TYPE *rt) + { +ST_DOUBLE d; +ST_CHAR buf[100]; + + d = *data_ptr; + sprintf (buf,"%.16f", d); + return (_sxdEncElement ((SX_ENC_CTRL *) usr, rt, _r8DtStr, buf)); + } + +/************************************************************************/ +/* _sxdEncOct */ +/************************************************************************/ + +static ST_RET _sxdEncOct (ST_VOID *usr, ST_UCHAR *data_ptr, RUNTIME_TYPE *rt) + { +ST_INT16 *sp; +ST_CHAR *buf; +ST_INT dataLen; +ST_RET rc; + + if (rt->u.p.el_len < 0) + { + sp = (ST_INT16 *) data_ptr; + dataLen = (ST_INT) *sp; + data_ptr += 2; + } + else + dataLen = abs (rt->u.p.el_len); + + buf = (ST_CHAR *) M_MALLOC (NULL, (3 * dataLen) + 1); + hex_to_ascii_str (buf, data_ptr, dataLen, SD_TRUE); + rc = _sxdEncElement ((SX_ENC_CTRL *) usr, rt, _binHexDtStr, buf); + M_FREE (NULL, buf); + return (rc); + } + +/************************************************************************/ +/* _sxdEncBool */ +/************************************************************************/ + +static ST_RET _sxdEncBool (ST_VOID *usr, ST_BOOLEAN *data_ptr, RUNTIME_TYPE *rt) + { +ST_BOOLEAN *bptr; +ST_CHAR *valStr; + + bptr = (ST_BOOLEAN *) data_ptr; + if (*bptr == 0) + valStr = "0"; + else + valStr = "1"; + + return (_sxdEncElement ((SX_ENC_CTRL *) usr, rt, _boolDtStr, valStr)); + } + +/************************************************************************/ +/* _sxdEncBcd1 */ +/************************************************************************/ + +static ST_RET _sxdEncBcd1 (ST_VOID *usr, ST_INT8 *data_ptr, RUNTIME_TYPE *rt) + { + return (_sxdEncInt8 (usr, data_ptr, rt)); + } + +/************************************************************************/ +/* _sxdEncBcd2 */ +/************************************************************************/ + +static ST_RET _sxdEncBcd2 (ST_VOID *usr, ST_INT16 *data_ptr, RUNTIME_TYPE *rt) + { + return (_sxdEncInt16 (usr, data_ptr, rt)); + } + +/************************************************************************/ +/* _sxdEncBcd4 */ +/************************************************************************/ + +static ST_RET _sxdEncBcd4 (ST_VOID *usr, ST_INT32 *data_ptr, RUNTIME_TYPE *rt) + { + return (_sxdEncInt32 (usr, data_ptr, rt)); + } + +/************************************************************************/ +/* _sxdEncBs */ +/************************************************************************/ + +static ST_RET _sxdEncBs (ST_VOID *usr, ST_UCHAR *data_ptr, RUNTIME_TYPE *rt) + { +ST_INT i; +ST_INT16 *sp; +ST_CHAR *_writePos; +ST_UINT8 bitMask; +ST_UINT8 *bytePtr; +ST_INT numBits; +ST_CHAR *buf; +ST_RET rc; + + if (rt->u.p.el_len < 0) + { + sp = (ST_INT16 *) data_ptr; + numBits = (ST_INT) *sp; + data_ptr += 2; + } + else + numBits = rt->u.p.el_len; + + buf = (ST_CHAR *) M_MALLOC (NULL, numBits + 1); + + _writePos = buf; + bitMask = 0x80; + bytePtr = data_ptr; + for (i = 0; i < numBits; ++i) + { + if (*bytePtr & bitMask) + *(_writePos++) = '1'; + else + *(_writePos++) = '0'; + + if (bitMask == 0x01) + { + bitMask = 0x80; + ++bytePtr; + } + else + bitMask = bitMask >> 1; + } + + rc = _sxdEncElement ((SX_ENC_CTRL *) usr, rt, _bitStringDtStr, buf); + M_FREE (NULL, buf); + return (rc); + } + +/************************************************************************/ +/************************************************************************/ +/* _sxdEncVis */ +/************************************************************************/ + +static ST_RET _sxdEncVis (ST_VOID *usr, ST_CHAR *data_ptr, RUNTIME_TYPE *rt) + { + return (_sxdEncElement ((SX_ENC_CTRL *) usr, rt, _visStringDtStr, data_ptr)); + } + +/************************************************************************/ +/* _sxdEncBt4 */ +/************************************************************************/ + +static ST_RET _sxdEncBt4 (ST_VOID *usr, ST_INT32 *data_ptr, RUNTIME_TYPE *rt) + { +ST_CHAR buf[100]; +ST_RET rc; + + rc = Btime4ValsToString (buf, (ST_LONG) *data_ptr); + if (rc != SD_SUCCESS) + return (rc); + + return (_sxdEncElement ((SX_ENC_CTRL *) usr, rt, _dateTimeDtStr, buf)); + } + +/************************************************************************/ +/* _sxdEncBt6 */ +/************************************************************************/ + +static ST_RET _sxdEncBt6 (ST_VOID *usr, ST_INT32 *data_ptr, RUNTIME_TYPE *rt) + { +ST_CHAR buf[100]; +ST_RET rc; + + rc = Btime6ValsToString (buf, *(data_ptr+1), (ST_LONG) *data_ptr); + if (rc != SD_SUCCESS) + return (rc); + + return (_sxdEncElement ((SX_ENC_CTRL *) usr, rt, _dateTimeDtStr, buf)); + } + +/************************************************************************/ +/* _sxdEncGt */ +/************************************************************************/ + +#define _SXD_TIME_BUF_LEN 25 + +static ST_RET _sxdEncGt (ST_VOID *usr, time_t *data_ptr, RUNTIME_TYPE *rt) + { +ST_CHAR timeText[_SXD_TIME_BUF_LEN]; + + strcpy (timeText, ctime(data_ptr)); + timeText[24] = 0; /* squash the \n */ + + return (_sxdEncElement ((SX_ENC_CTRL *) usr, rt, _dateTimeDtStr, timeText)); + } + +/************************************************************************/ +/* _sxdEncUTF8 */ +/* Don't know how to display. Just show the hex bytes. */ +/************************************************************************/ + +static ST_RET _sxdEncUTF8 (ST_VOID *usr, ST_UCHAR *data_ptr, RUNTIME_TYPE *rt) + { +ST_CHAR *buf; +ST_INT dataLen; +ST_RET rc; + + dataLen = rt->el_size; + + buf = (ST_CHAR *) M_MALLOC (NULL, (3 * dataLen) + 1); + hex_to_ascii_str (buf, data_ptr, dataLen, SD_TRUE); + rc = _sxdEncElement ((SX_ENC_CTRL *) usr, rt, _binHexDtStr, buf); + M_FREE (NULL, buf); + return (rc); + } + +/************************************************************************/ +/************************************************************************/ +/* _sxdEncElement */ +/************************************************************************/ + +static ST_RET _sxdEncElement (SX_ENC_CTRL *ec, RUNTIME_TYPE *rt, + ST_CHAR *dtString, ST_CHAR *contents) + { +SD_CONST ST_CHAR *elName; +SXE_ATTR_PAIR attr[2]; +ST_INT numAttr; +RUNTIME_TYPE *rt_tmp; + + if (ms_comp_name_pres(rt) == SD_TRUE) + elName = ms_comp_name_find(rt); + else + { + /* must be an array element, get the name from the RT_ARR_START */ + elName = "UNNAMED"; /* set, just in case name not specified */ + rt_tmp = rt-1; + /* this maybe multidimentional array , only the first dim has name in RT tbl */ + while (rt_tmp->el_tag == RT_ARR_START) + { + if (ms_comp_name_pres(rt_tmp) == SD_TRUE) + { + elName = ms_comp_name_find(rt_tmp); + break; + } + --rt_tmp; + } + } + + if (ec->sxdXmlStyle == SXD_XML_STYLE_A) + { + *(ec->nextWritePos++) = ' '; + sx_add_string (ec, ec->sxdPrefix, &ec->nextWritePos); + sx_add_string (ec, elName, &ec->nextWritePos); + *(ec->nextWritePos++) = '='; + *(ec->nextWritePos++) = '"'; + sx_add_string (ec, contents, &ec->nextWritePos); + *(ec->nextWritePos++) = '"'; + } + else if (ec->sxdXmlStyle == SXD_XML_STYLE_C) + { + sx_wr_string_el (ec, elName, contents); + } + else if (ec->sxdXmlStyle == SXD_XML_STYLE_V) + { + if (ec->encDt) + { + attr[0].name = "DT"; + attr[0].value = dtString; + numAttr = 1; + } + else + numAttr = 0; + + attr[numAttr].name = "V"; + attr[numAttr].value = contents; + ++numAttr; + sx_write_element (ec, elName, numAttr, attr, SD_FALSE, SD_TRUE); + } + + return (SD_SUCCESS); + } + + + +/************************************************************************/ +/************************************************************************/ + +SXD_ARB_DATA_CTRL _sxdEncArbFuns = + { + _sxdEncArrStart, /* arrStart */ + _sxdEncArrEnd, /* arrEnd */ + _sxdEncStrStart, /* strStart */ + _sxdEncStrEnd, /* strEnd */ + _sxdEncInt8, /* int8 */ + _sxdEncInt16, /* int16 */ + _sxdEncInt32, /* int32 */ +#ifdef INT64_SUPPORT + _sxdEncInt64, /* int64 */ +#endif + _sxdEncUint8, /* uint8 */ + _sxdEncUint16, /* uint16 */ + _sxdEncUint32, /* uint32 */ +#ifdef INT64_SUPPORT + _sxdEncUint64, /* uint64 */ +#endif + _sxdEncFlt, /* flt */ + _sxdEncDbl, /* dbl */ + _sxdEncOct, /* oct */ + _sxdEncBool, /* booln */ + _sxdEncBcd1, /* bcd1 */ + _sxdEncBcd2, /* bcd2 */ + _sxdEncBcd4, /* bcd4 */ + _sxdEncBs, /* bs */ + _sxdEncVis, /* vis */ + _sxdEncBt4, /* Bin Time */ + _sxdEncBt6, /* Bin Time */ + _sxdEncGt, /* Gen Time */ + NULL, /* UTC Time */ + _sxdEncUTF8, /* UTF8string */ + }; + +/************************************************************************/ +/* _sxd_wr_data */ +/************************************************************************/ + +#if defined(MMS_LITE) && !defined(NO_MVL) + +ST_RET _sxd_wr_data (SX_ENC_CTRL *sxEncCtrl, ST_INT typeId, + ST_CHAR *elName, ST_VOID *data, ST_INT sxdXmlStyle, + ST_BOOLEAN encodeDt, ST_BOOLEAN *elPres) + { +RUNTIME_TYPE *rt; +ST_INT numRt; +ST_RET rc; + + rc = sxd_get_runtime (typeId, &rt, &numRt); + if (rc != SD_SUCCESS) + return (rc); + + rc = sxd_wr_rtdata (sxEncCtrl, rt, numRt, elName, data, sxdXmlStyle, encodeDt, elPres); + return (rc); + } +#endif + + +/************************************************************************/ +/* sxd_wr_rtdata */ +/************************************************************************/ + +ST_RET sxd_wr_rtdata (SX_ENC_CTRL *sxEncCtrl, RUNTIME_TYPE *rt, ST_INT numRt, + ST_CHAR *elName, ST_VOID *data, ST_INT sxdXmlStyle, + ST_BOOLEAN encodeDt, ST_BOOLEAN *elPres) + { +ST_RET rc; + + sxEncCtrl->sxdXmlStyle = sxdXmlStyle; + sxEncCtrl->encDt = encodeDt; + sxEncCtrl->outerElement = elName; + sxEncCtrl->sxdPrefix[0] = 0; + + rc = sxd_process_arb_data ((ST_CHAR *) data, rt, numRt, sxEncCtrl, + &_sxdEncArbFuns, elPres); + if (rc != SD_SUCCESS) + return (rc); + + return (rc); + } + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +#define _SXD_MAX_VAL_BUF 8000 +#define _SXD_MAX_EL_NAME 50 +#define _SXD_MAX_DT 50 + +typedef struct + { + ST_INT sxdXmlStyle; /* See sx_defs.h for values */ + ST_CHAR *xmlDest; + ST_BOOLEAN checkDt; + ST_CHAR *xmlPos; + ST_CHAR *xmlBufEnd; + ST_RET xmlDecResult; + SD_CONST ST_CHAR *outerElement; + ST_CHAR valBuf[_SXD_MAX_VAL_BUF+1]; + ST_CHAR elName[_SXD_MAX_EL_NAME+1]; + ST_CHAR dtBuf[_SXD_MAX_DT+1]; + ST_BOOLEAN endEl; + ST_BOOLEAN dataEl; + } SXD_DEC_CTRL; + +/************************************************************************/ +/************************************************************************/ + +static ST_RET _sxdCheckDt (SXD_DEC_CTRL *dc, ST_CHAR *dtString) + { + if (strcmp (dc->dtBuf, dtString) != 0) + { + SXLOG_NERR3 ("Type mismatch for elName '%s': expected '%s', got '%s'", + dc->elName, dtString, dc->dtBuf); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + return (SD_SUCCESS); + } + + +/************************************************************************/ +/************************************************************************/ +/* _sxdDecArrStart */ +/************************************************************************/ + +static ST_RET _sxdDecArrStart (SXD_DEC_CTRL *dc, RUNTIME_TYPE *rt) + { + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecArrEnd */ +/************************************************************************/ + +static ST_RET _sxdDecArrEnd (SXD_DEC_CTRL *dc, RUNTIME_TYPE *rt) + { + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecStrStart */ +/************************************************************************/ + +static ST_RET _sxdDecStrStart (SXD_DEC_CTRL *dc, RUNTIME_TYPE *rt) + { + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecStrEnd */ +/************************************************************************/ + +static ST_RET _sxdDecStrEnd (SXD_DEC_CTRL *dc, RUNTIME_TYPE *rt) + { + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* _sxdDecInt8 */ +/************************************************************************/ + +static ST_RET _sxdDecInt8 (SXD_DEC_CTRL *dc, ST_INT8 *data_ptr, RUNTIME_TYPE *rt) + { +ST_INT intVal; +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _i1DtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + intVal = atoi (dc->valBuf); + *data_ptr = (ST_INT8) intVal; + SXLOG_CDEC1 ("Integer8: %d",intVal); + return (SD_SUCCESS); + } + +/***********************************************************************/ +/* _sxdDecInt16 */ +/***********************************************************************/ + +static ST_RET _sxdDecInt16 (SXD_DEC_CTRL *dc, ST_INT16 *data_ptr, RUNTIME_TYPE *rt) + { +ST_INT intVal; +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _i2DtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + intVal = atoi (dc->valBuf); + *data_ptr = (ST_INT16) intVal; + SXLOG_CDEC1 ("Integer16: %d",intVal); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecInt32 */ +/************************************************************************/ + +static ST_RET _sxdDecInt32 (SXD_DEC_CTRL *dc, ST_INT32 *data_ptr, RUNTIME_TYPE *rt) + { +ST_INT32 intVal; +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _i4DtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + intVal = atoi (dc->valBuf); + *data_ptr = (ST_INT32) intVal; + SXLOG_CDEC1 ("Integer32: %ld", (ST_LONG) intVal); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecInt64 */ +/************************************************************************/ +#ifdef INT64_SUPPORT + +static ST_RET _sxdDecInt64 (SXD_DEC_CTRL *dc, ST_INT64 *data_ptr, RUNTIME_TYPE *rt) + { +ST_INT64 i64Val; +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _i8DtStr); + if (rc != SD_SUCCESS) + return (rc); + } + +#if defined(_WIN32) + i64Val = _atoi64 (dc->valBuf); +#else + if (sscanf (dc->valBuf, S_FMT_INT64, &i64Val) != 1) + return (SD_FAILURE); +#endif + *data_ptr = i64Val; + SXLOG_CDEC1 ("Integer64: " S_FMT_INT64, i64Val); + return (SD_SUCCESS); + } +#endif + +/************************************************************************/ +/* _sxdDecUint8 */ +/************************************************************************/ + +static ST_RET _sxdDecUint8 (SXD_DEC_CTRL *dc, ST_UINT8 *data_ptr, RUNTIME_TYPE *rt) + { +ST_INT intVal; +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _uI1DtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + intVal = atoi (dc->valBuf); + *data_ptr = (ST_UINT8) intVal; + SXLOG_CDEC1 ("Unsigned8: %d",intVal); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecUint16 */ +/************************************************************************/ + +static ST_RET _sxdDecUint16 (SXD_DEC_CTRL *dc, ST_UINT16 *data_ptr, RUNTIME_TYPE *rt) + { +ST_INT intVal; +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _uI2DtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + intVal = atoi (dc->valBuf); + *data_ptr = (ST_UINT16) intVal; + SXLOG_CDEC1 ("Unsigned16: %d",intVal); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecUint32 */ +/************************************************************************/ + +static ST_RET _sxdDecUint32(SXD_DEC_CTRL *dc, ST_UINT32 *data_ptr, RUNTIME_TYPE *rt) + { +ST_ULONG intVal; +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _uI4DtStr); + if (rc != SD_SUCCESS) + return (rc); + } + +#if (LONG_MAX > INT_MAX) + intVal = atol (dc->valBuf); +#else + if (sscanf (dc->valBuf, "%lu", &intVal) != 1) + return (SD_FAILURE); +#endif + *data_ptr = (ST_UINT32) intVal; + SXLOG_CDEC1 ("Unsigned32: %lu",intVal); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecUint64 */ +/************************************************************************/ +#ifdef INT64_SUPPORT + +static ST_RET _sxdDecUint64(SXD_DEC_CTRL *dc, ST_UINT64 *data_ptr, RUNTIME_TYPE *rt) + { +ST_UINT64 intVal; +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _uI8DtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + if (sscanf (dc->valBuf, S_FMT_UINT64, &intVal) != 1) + return (SD_FAILURE); + *data_ptr = intVal; + SXLOG_CDEC1 ("Unsigned64: " S_FMT_UINT64, intVal); + return (SD_SUCCESS); + } +#endif + +/************************************************************************/ +/* _sxdDecFlt */ +/************************************************************************/ + +static ST_RET _sxdDecFlt (SXD_DEC_CTRL *dc, ST_FLOAT *data_ptr, RUNTIME_TYPE *rt) + { +ST_DOUBLE doubleVal; +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _r4DtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + doubleVal = atof (dc->valBuf); + *data_ptr = (ST_FLOAT) doubleVal; + SXLOG_CDEC1 ("Float: %f", doubleVal); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecDbl */ +/************************************************************************/ + +static ST_RET _sxdDecDbl (SXD_DEC_CTRL *dc, ST_DOUBLE *data_ptr, RUNTIME_TYPE *rt) + { +ST_DOUBLE doubleVal; +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _r8DtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + doubleVal = atof (dc->valBuf); + *data_ptr = (ST_FLOAT) doubleVal; + SXLOG_CDEC1 ("Double: %f", doubleVal); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecOct */ +/************************************************************************/ + +static ST_RET _sxdDecOct (SXD_DEC_CTRL *dc, ST_UCHAR *data_ptr, RUNTIME_TYPE *rt) + { +ST_RET rc; +ST_INT16 *sp; +ST_UINT maxOctets; +ST_UINT hexLen; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _binHexDtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + if (rt->u.p.el_len < 0) + data_ptr += 2; + + maxOctets = abs (rt->u.p.el_len); + rc = ascii_to_hex_str (data_ptr, &hexLen, maxOctets, dc->valBuf); + if (rc != SD_SUCCESS) + return (rc); + + if (rt->u.p.el_len < 0) + { + sp = (ST_INT16 *) (data_ptr-2); + *sp = hexLen; + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecBool */ +/************************************************************************/ + +static ST_RET _sxdDecBool (SXD_DEC_CTRL *dc, ST_BOOLEAN *data_ptr, RUNTIME_TYPE *rt) + { +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _boolDtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + *data_ptr = dc->valBuf[0] == '0' ? 0 : 1; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecBcd1 */ +/************************************************************************/ + +static ST_RET _sxdDecBcd1 (SXD_DEC_CTRL *dc, ST_INT8 *data_ptr, RUNTIME_TYPE *rt) + { + return (_sxdDecInt8 (dc, data_ptr, rt)); + } + +/************************************************************************/ +/* _sxdDecBcd2 */ +/************************************************************************/ + +static ST_RET _sxdDecBcd2 (SXD_DEC_CTRL *dc, ST_INT16 *data_ptr, RUNTIME_TYPE *rt) + { + return (_sxdDecInt16 (dc, data_ptr, rt)); + } + +/************************************************************************/ +/* _sxdDecBcd4 */ +/************************************************************************/ + +static ST_RET _sxdDecBcd4 (SXD_DEC_CTRL *dc, ST_INT32 *data_ptr, RUNTIME_TYPE *rt) + { + return (_sxdDecInt32 (dc, data_ptr, rt)); + } + +/************************************************************************/ +/* _sxdDecBs */ +/************************************************************************/ + +static ST_RET _sxdDecBs (SXD_DEC_CTRL *dc, ST_UCHAR *data_ptr, RUNTIME_TYPE *rt) + { +ST_INT16 *sp; +ST_UINT8 bitMask; +ST_UINT8 *bytePtr; +ST_RET rc; +ST_CHAR *ascPtr; +ST_INT bitCount; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _bitStringDtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + if (rt->u.p.el_len < 0) + bytePtr = data_ptr + 2; + else + bytePtr = data_ptr; + + bitMask = 0x80; + ascPtr = dc->valBuf; + bitCount = 0; + while (*ascPtr != 0 && bitCount < abs (rt->u.p.el_len)) + { + if (*ascPtr == '1') + *bytePtr |= bitMask; + else + *bytePtr &= ~bitMask; + + if (bitMask == 0x01) + { + bitMask = 0x80; + ++bytePtr; + } + else + bitMask = bitMask >> 1; + + ++bitCount; + } + + if (rt->u.p.el_len < 0) + { + sp = (ST_INT16 *) (data_ptr); + *sp = bitCount; + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecVis */ +/************************************************************************/ + +static ST_RET _sxdDecVis (SXD_DEC_CTRL *dc, ST_CHAR *data_ptr, RUNTIME_TYPE *rt) + { +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _visStringDtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + strcpy (data_ptr, dc->valBuf); + SXLOG_CDEC1 ("Visible string: '%s'", data_ptr); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecBt4 */ +/************************************************************************/ + +static ST_RET _sxdDecBt4 (SXD_DEC_CTRL *dc, ST_INT32 *data_ptr, RUNTIME_TYPE *rt) + { +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _dateTimeDtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + rc = Btime4StringToVals (dc->valBuf, data_ptr); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecBt6 */ +/************************************************************************/ + +static ST_RET _sxdDecBt6 (SXD_DEC_CTRL *dc, ST_INT32 *data_ptr, RUNTIME_TYPE *rt) + { +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _dateTimeDtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + rc = Btime6StringToVals (dc->valBuf, data_ptr+1, data_ptr); + return (rc); + } + +/************************************************************************/ +/* _sxdDecGt */ +/************************************************************************/ + +static ST_RET _sxdDecGt (SXD_DEC_CTRL *dc, time_t *data_ptr, RUNTIME_TYPE *rt) + { +ST_RET rc; + +/* Check data type, if requested ... */ + if (dc->checkDt != SD_FALSE) + { + rc = _sxdCheckDt (dc, _dateTimeDtStr); + if (rc != SD_SUCCESS) + return (rc); + } + + rc = tstrStringToTime (dc->valBuf, data_ptr); + return (rc); + } + +/************************************************************************/ +/************************************************************************/ +/* _sxdDecElementA */ +/************************************************************************/ + +static ST_RET _sxdDecElementA (SXD_DEC_CTRL *dc) + { +ST_CHAR *p; +ST_CHAR c; +ST_INT i; + +/* Continue decoding the element, which must be of the form */ +/* */ + + dc->endEl = SD_FALSE; + dc->dataEl = SD_FALSE; + + c = *(dc->xmlPos++); + if (c == '<') + { + /* OK, get the element name */ + c = *(dc->xmlPos++); + p = dc->elName; + i = 0; + while (c != ' ' && c != '>') + { + if (++i > _SXD_MAX_EL_NAME) + { + SXLOG_NERR0 ("Could not find ' ' or '>'"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + + *(p++) = c; + c = *(dc->xmlPos++); + if (dc->xmlPos > dc->xmlBufEnd) + { + SXLOG_NERR0 ("Could not find ' ' or '>'"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + } + *p = 0; + return (SD_SUCCESS); + } + +/* OK, not the start of an element, see if is the end of an element */ + if (c == '/') + { + dc->endEl = SD_TRUE; + c = *(dc->xmlPos++); /* Eat the '>' */ + return (SD_SUCCESS); + } + +/* OK, must be the name of a structure element */ + p = dc->elName; + i = 0; + while (c != '=') + { + if (c != ' ') /* Skip leading spaces before attribute name */ + { + if (++i > _SXD_MAX_EL_NAME) + { + SXLOG_NERR0 ("Could not find ' ' or '>'"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + *(p++) = c; + } + c = *(dc->xmlPos++); + if (dc->xmlPos > dc->xmlBufEnd) + { + SXLOG_NERR0 ("Could not find '='"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + } + *p = 0; + +/* Finally, we get to the value */ + c = *(dc->xmlPos++); /* Eat the '"' */ + p = dc->valBuf; + c = *(dc->xmlPos++); + i = 0; + while (c != '"') + { + if (++i > _SXD_MAX_VAL_BUF) + { + SXLOG_NERR0 ("Could not find ' ' or '>'"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + *(p++) = c; + c = *(dc->xmlPos++); + if (dc->xmlPos > dc->xmlBufEnd) + { + SXLOG_NERR0 ("Could not find end of value attribute"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + } + *p = 0; + dc->dataEl = SD_TRUE; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecElementC */ +/************************************************************************/ + +static ST_RET _sxdDecElementC (SXD_DEC_CTRL *dc) + { +ST_CHAR *p; +ST_CHAR c; + +ST_INT i; +/* Decode the XML element, which must be of the form */ +/* xxxx */ +/* < ... */ +/* */ + +/* Find the opening '<' */ + while (SD_TRUE) + { + c = *(dc->xmlPos++); + if (c == '<') + { + if (*dc->xmlPos != '!') + break; + } + if (dc->xmlPos > dc->xmlBufEnd) + { + SXLOG_NERR0 ("Could not find opening '<'"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + } + + c = *(dc->xmlPos++); + if (c == '/') + { + dc->endEl = SD_TRUE; + c = *(dc->xmlPos++); + } + else + dc->endEl = SD_FALSE; + +/* OK, get the element name */ + p = dc->elName; + i = 0; + while (c != '>') + { + if (++i > _SXD_MAX_EL_NAME) + { + SXLOG_NERR0 ("Could not find ' ' or '>'"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + + *(p++) = c; + c = *(dc->xmlPos++); + if (dc->xmlPos > dc->xmlBufEnd) + { + SXLOG_NERR0 ("Could not find ' '"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + } + *p = 0; + +/* If this is an end element, we are done */ + if (dc->endEl == SD_TRUE) + return (SD_SUCCESS); + +/* Now check to see if this is a nested element */ + p = dc->xmlPos; + while (SD_TRUE) + { + if (*(p++) == '<') /* The end of this element or start of nest */ + { + if (*p != '!') /* if this is not a comment */ + { + if (*p == '/') /* The end of this element */ + break; + + return (SD_SUCCESS); /* Start of nested element */ + } + } + if (p > dc->xmlBufEnd) + { + SXLOG_NERR0 ("Could not find ' '"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + } + +/* OK, now we can get the value */ + dc->dataEl = SD_TRUE; + + p = dc->valBuf; + c = *(dc->xmlPos++); + i = 0; + while (c != '<') + { + if (++i > _SXD_MAX_VAL_BUF) + { + SXLOG_NERR0 ("Could not find ' ' or '>'"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + + *(p++) = c; + c = *(dc->xmlPos++); + if (dc->xmlPos > dc->xmlBufEnd) + { + SXLOG_NERR0 ("Could not find end of value"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + } + *p = 0; + +/* Now we need to consume the end tag */ + c = *(dc->xmlPos++); + if (c != '/') + { + SXLOG_NERR0 ("Expected end tag"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + + while (c != '>') + { + c = *(dc->xmlPos++); + if (dc->xmlPos > dc->xmlBufEnd) + { + SXLOG_NERR0 ("Could not find end of end tag"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/* _sxdDecElementV */ +/************************************************************************/ + +static ST_RET _sxdDecElementV (SXD_DEC_CTRL *dc) + { +ST_CHAR *p; +ST_CHAR c; +ST_INT i; + +/* Decode the XML element, which must be of the form */ +/* */ +/* */ +/* */ + + c = *(dc->xmlPos++); + if (c != '<') + { + SXLOG_NERR0 ("Could not find opening '<'"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + + c = *(dc->xmlPos++); + if (c == '/') + { + dc->endEl = SD_TRUE; + c = *(dc->xmlPos++); + } + else + dc->endEl = SD_FALSE; + +/* OK, get the element name */ + p = dc->elName; + i = 0; + while (c != ' ' && c != '>') + { + if (++i > _SXD_MAX_EL_NAME) + { + SXLOG_NERR0 ("Could not find ' ' or '>'"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + *(p++) = c; + c = *(dc->xmlPos++); + if (dc->xmlPos > dc->xmlBufEnd) + { + SXLOG_NERR0 ("Could not find ' '"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + } + *p = 0; + + if (c == ' ') + { + dc->dataEl = SD_TRUE; + + /* OK, now see if the data type is included ... */ + p = dc->dtBuf; + c = *(dc->xmlPos++); + if (c == 'D') + { + c = *(dc->xmlPos++); /* Eat the 'T' */ + c = *(dc->xmlPos++); /* Eat the '=' */ + c = *(dc->xmlPos++); /* Eat the '"' */ + c = *(dc->xmlPos++); + i = 0; + while (c != '"' && dc->xmlPos <= dc->xmlBufEnd) + { + if (++i > _SXD_MAX_DT) + { + SXLOG_NERR0 ("Could not find end of DT"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + + *(p++) = c; + c = *(dc->xmlPos++); + if (dc->xmlPos > dc->xmlBufEnd) + { + SXLOG_NERR0 ("Could not find ' '"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + } + c = *(dc->xmlPos++); /* Eat the ' ' */ + c = *(dc->xmlPos++); /* This should be the 'V' */ + } + *p = 0; + + /* Finally, we get to the value, right? */ + if (c != 'V') + { + SXLOG_NERR0 ("Expected 'V'"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + c = *(dc->xmlPos++); /* Eat the '=' */ + c = *(dc->xmlPos++); /* Eat the '"' */ + + p = dc->valBuf; + c = *(dc->xmlPos++); + i = 0; + while (c != '"') + { + if (++i > _SXD_MAX_VAL_BUF) + { + SXLOG_NERR0 ("Could not find ' ' or '>'"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + *(p++) = c; + c = *(dc->xmlPos++); + if (dc->xmlPos > dc->xmlBufEnd) + { + SXLOG_NERR0 ("Could not find end of value attribute"); + dc->xmlDecResult = SD_FAILURE; + return (SD_FAILURE); + } + } + *p = 0; + c = *(dc->xmlPos++); /* Eat the '/' */ + c = *(dc->xmlPos++); /* Eat the '>' */ + } + else + dc->dataEl = SD_FALSE; + + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ + +#if defined(MMS_LITE) && !defined(NO_MVL) + +ST_RET _sxd_decode_data_el (ST_CHAR *elName, + ST_CHAR *xml, ST_INT xmlLen, ST_INT *xmlUsed, + ST_VOID *vdp, ST_INT typeId, + ST_BOOLEAN *elPres, ST_INT sxdXmlStyle, ST_BOOLEAN checkDt) + { +RUNTIME_TYPE *rt; +ST_INT numRt; +ST_RET rc; + + rc = sxd_get_runtime (typeId, &rt, &numRt); + if (rc != SD_SUCCESS) + return (rc); + + rc = sxd_decode_rtdata_el (elName, xml, xmlLen, xmlUsed, vdp, rt, numRt, + elPres, sxdXmlStyle, checkDt); + + return (rc); + } +#endif + +/************************************************************************/ +/* sxd_decode_rtdata_el */ +/************************************************************************/ + +ST_RET sxd_decode_rtdata_el (SD_CONST ST_CHAR *elName, + ST_CHAR *xml, ST_INT xmlLen, ST_INT *xmlUsed, + ST_VOID *vdp, SD_CONST RUNTIME_TYPE *rt_head, + ST_INT rt_num, ST_BOOLEAN *elPres, + ST_INT sxdXmlStyle, ST_BOOLEAN checkDt) + { +RUNTIME_TYPE *rt_ptr; +RUNTIME_TYPE *rt_end; +RUNTIME_TYPE *rt_tmp; +ST_RET uDataRet; +ST_INT arr_loop_level; +ST_INT arr_loops[ASN1_MAX_LEVEL]; +ST_RET rc; +SXD_DEC_CTRL *dc; +ST_CHAR *datptr; +ST_CHAR nameBuf[SXD_MAX_PREFIX+MAX_IDENT_LEN+1]; +ST_INT j, cnt; +ST_BOOLEAN set_arr_start; +ST_BOOLEAN set_arr_end; +ST_BOOLEAN plain_array; +ST_CHAR structPrefix[SXD_MAX_PREFIX+1]; /* used only for decoding of style A */ +ST_INT structNestLevel; /* used only for decoding of style A */ + +/* macro to set the elPres field, update datptr, and advance to next RT */ +#define _SXD_ADVANCE_PTR(rt_ptr, pres_flg) { \ + if (elPres != NULL) \ + elPres[(rt_ptr) - rt_head] = pres_flg; \ + datptr += (rt_ptr)->el_size; \ + ++(rt_ptr); } + + datptr = (ST_CHAR *) vdp; + dc = (SXD_DEC_CTRL *) M_CALLOC (NULL, 1, sizeof (SXD_DEC_CTRL)); + if (!dc) + { + SXLOG_ERR1 ("Unable to allocate memory (bytes %u)", sizeof (SX_DEC_CTRL)); + return (SD_FAILURE); + } + dc->sxdXmlStyle = sxdXmlStyle; + if (dc->sxdXmlStyle == SXD_XML_STYLE_V) + dc->checkDt = checkDt; + else + dc->checkDt = SD_FALSE; + + dc->xmlDest = xml; + dc->xmlPos = xml; + dc->xmlBufEnd = xml + xmlLen; + dc->xmlDecResult = SD_SUCCESS; + dc->outerElement = elName; + + arr_loop_level = 0; + memset (arr_loops, 0, sizeof (arr_loops)); + + rt_ptr = (RUNTIME_TYPE *) rt_head; /* point to head rt_block */ + rt_end = rt_ptr + rt_num; /* done when pointer is here */ + +/* Here we will work our way through the XML and the runtime type */ + + uDataRet = SD_SUCCESS; + structPrefix[0] = 0; + structNestLevel = 0; + + while ((dc->xmlPos < dc->xmlBufEnd) && (rt_ptr < rt_end) && + uDataRet == SD_SUCCESS) + { + /* Position to the opening '<' */ + if (dc->sxdXmlStyle == SXD_XML_STYLE_C || + dc->sxdXmlStyle == SXD_XML_STYLE_V) + { + while (*dc->xmlPos != '<' && dc->xmlPos < dc->xmlBufEnd) + ++dc->xmlPos; + } + if (dc->xmlPos >= dc->xmlBufEnd) + { + M_FREE (NULL, dc); + return (SD_SUCCESS); + } + + /* Decode the next XML data element */ + if (dc->sxdXmlStyle == SXD_XML_STYLE_A) + rc = _sxdDecElementA (dc); + else if (dc->sxdXmlStyle == SXD_XML_STYLE_C) + rc = _sxdDecElementC (dc); + else if (dc->sxdXmlStyle == SXD_XML_STYLE_V) + rc = _sxdDecElementV (dc); + else + rc = SD_FAILURE; /* invalid style */ + + if (rc != SD_SUCCESS) + { + M_FREE (NULL, dc); + return (rc); + } + + /* If we reached the end of the element for style A, we are done */ + if (dc->endEl == SD_TRUE && dc->sxdXmlStyle == SXD_XML_STYLE_A) + { + if (dc->outerElement && elPres != NULL) + elPres[rt_num-1] = SD_TRUE; + + break; + } + + /* Note1: The processing is different for plain array and different */ + /* for array of structures when they are decoded. */ + /* In the case of plain array the function sxdDecElementX */ + /* will return the decoded array element (no start or end */ + /* array element tag). */ + /* In the case of array of structures the fun sxdDecElementX */ + /* will return first the start of array element tag, then */ + /* the decoded array element (x struct fields), and at the */ + /* end we get the array element end tag. */ + /* Note2: Arrays are not supported in SXD_XML_STYLE_A because the */ + /* attributes must have unique names. */ + + plain_array = SD_FALSE; + set_arr_start = SD_FALSE; + set_arr_end = SD_FALSE; + + /* OK, we need to find the RT that has the name */ + while (rt_ptr < rt_end && uDataRet == SD_SUCCESS) + { + elName = NULL; + + if (rt_ptr->el_tag == RT_STR_START) /* treat case of struct start */ + { + /*--------------------------------------------------------------*/ + if (ms_comp_name_pres(rt_ptr) == SD_TRUE) + { + elName = ms_comp_name_find(rt_ptr); + if (dc->sxdXmlStyle == SXD_XML_STYLE_A) + { + strcat (structPrefix, elName); + strcat (structPrefix, "."); + if (strncmp (dc->elName, structPrefix, strlen(structPrefix)) == 0) + { + ++structNestLevel; + _SXD_ADVANCE_PTR(rt_ptr, SD_TRUE); + continue; + } + else + { + /* wrong struct, need to skip this struct in rt tbl */ + _sxdStripPrefix (structPrefix); /* restore the prefix */ + } + } + } + if (elName != NULL) + { + /* Check to see if we found the associated RUNTIME element */ + if (strcmp (dc->elName, elName) == 0) + break; /* struct name matches, process it */ + else + { + /* dc->elName does not match, need to skip this struct in rt tbl */ + cnt = rt_ptr->u.str.num_rt_blks + 2; /* 2 for str start, end */ + for (j=0; j 0) + { + /* array of structs, advance to next rt */ + uDataRet = _sxdDecStrStart (dc, rt_ptr);/* normally called from switch */ + _SXD_ADVANCE_PTR(rt_ptr, SD_TRUE); + continue; /* continue processing of the array element */ + } + else + { + /* must be the XML wrapper */ + elName = dc->outerElement; + if (elName == NULL) + /* can't compare the wrapper name, assume it is OK */ + break; + else + { + if (strcmp (dc->elName, elName) == 0) + break; /* process the wrapper */ + else + { + /* wrong XML ? */ + SXLOG_NERR2 ("Could not find XML wrapper '%s' (found '%s')", dc->elName, elName); + M_FREE (NULL, dc); + return (SD_FAILURE); + } + } + } + } + } + else if (rt_ptr->el_tag == RT_STR_END) /* treat case of struct end */ + { + /*--------------------------------------------------------------*/ + if (dc->sxdXmlStyle == SXD_XML_STYLE_A) + { + /* need to strip name of last struct level */ + _sxdStripPrefix (structPrefix); + --structNestLevel; + _SXD_ADVANCE_PTR(rt_ptr, SD_TRUE); + continue; + } + else + { + /* get the struct name from the RT_STR_START rt */ + rt_tmp = rt_ptr - (rt_ptr->u.str.num_rt_blks + 1); + if (ms_comp_name_pres(rt_tmp) == SD_TRUE) + elName = ms_comp_name_find(rt_tmp); + } + if (elName != NULL) + { + /* Check to see if we found the associated RUNTIME element */ + if (strcmp (dc->elName, elName) == 0) + break; /* struct name matches, process end */ + } + else + { + /* elName maybe NULL in the case of array of structures */ + if (arr_loop_level > 0) + { + /* this is an array of structs, advance to next rt (but not to next decoded element)*/ + uDataRet = _sxdDecStrEnd (dc, rt_ptr);/* normally called from switch */ + _SXD_ADVANCE_PTR(rt_ptr, SD_TRUE); + continue; /* continue processing of the array element */ + } + else + { + /* this may be the wrapper end */ + elName = dc->outerElement; + if (elName == NULL) + /* can't compare the wrapper name, assume it is OK */ + break; + else + { + if (strcmp (dc->elName, elName) == 0) + break; /* process the wrapper */ + else + { + /* wrong XML ? */ + SXLOG_NERR2 ("Could not find XML end wrapper tag '%s' (found '%s')", dc->elName, elName); + M_FREE (NULL, dc); + return (SD_FAILURE); + } + } + } + } + } + else if (rt_ptr->el_tag == RT_ARR_START) /* treat case of array element starting */ + { + /*--------------------------------------------------------------*/ + /* check if the start tag of array element matches dc->elName */ + /* before setting loop level */ + if (ms_comp_name_pres(rt_ptr) == SD_TRUE) + elName = ms_comp_name_find(rt_ptr); + if (strcmp (dc->elName, elName) == 0) + { + if (arr_loop_level == 0) /* set only one time per array */ + { + rt_tmp = rt_ptr; + while (rt_tmp->el_tag == RT_ARR_START) + { + ++arr_loop_level; + arr_loops[arr_loop_level] = rt_tmp->u.arr.num_elmnts; + ++rt_tmp; + } + } + /* array may be multidimentional, skip to the last RT_ARR_START */ + while ((rt_ptr+1)->el_tag == RT_ARR_START) + { + uDataRet = _sxdDecArrStart (dc, rt_ptr); /* normally called from switch */ + _SXD_ADVANCE_PTR(rt_ptr, SD_TRUE); + } + + /* if it is array of structs, processing is different */ + if ((rt_ptr+1)->el_tag == RT_STR_START) + /* array of structs */ + break; + else + { + /* plain array, adjust ptrs and go to next rt */ + plain_array = SD_TRUE; + uDataRet = _sxdDecArrStart (dc, rt_ptr);/* normally called from switch */ + _SXD_ADVANCE_PTR(rt_ptr, SD_TRUE); + continue; + } + } + /* dc->elName does not match, need to skip this array in rt tbl */ + cnt = rt_ptr->u.arr.num_rt_blks + 2; /* 2 for arr start, end */ + for (j=0; jelName in rt tbl */ + } + else if (rt_ptr->el_tag == RT_ARR_END) /* treat case of array element ending */ + { + /*--------------------------------------------------------------*/ + /* we get here only in the case of array of structures */ + /* get the array name from the first RT_ARR_START rt (maybe nested) */ + rt_tmp = rt_ptr - (rt_ptr->u.arr.num_rt_blks + 1); + while (ms_comp_name_pres(rt_tmp) != SD_TRUE && rt_tmp->el_tag == RT_ARR_START) + --rt_tmp; + elName = "UNKNOWN"; + if (ms_comp_name_pres(rt_tmp) == SD_TRUE) + elName = ms_comp_name_find(rt_tmp); + + /* check if the end tag of an array element is correct */ + if (strcmp (dc->elName, elName) != 0) + { + /* invalid end tag for the array element, quit decoding */ + SXLOG_NERR2 ("Could not find array element end tag '%s' (found '%s')", elName, dc->elName); + M_FREE (NULL, dc); + return (SD_FAILURE); + } + if (--arr_loops[arr_loop_level] > 0) /* if need next ar elmnt */ + { + /* there should be more array elements to process, need to */ + /* reset the rt to the beginning of the array */ + set_arr_start = SD_TRUE; + } + else + { + /* all array elements processed, decrement loop level */ + --arr_loop_level; + if (arr_loops[arr_loop_level] > 0) + set_arr_start = SD_TRUE; /* more elements to process */ + else + { + /* advance to last RT_ARR_END (if multidimentional array) */ + while ((rt_ptr+1)->el_tag == RT_ARR_END) + { + _SXD_ADVANCE_PTR(rt_ptr, SD_TRUE); + } + } + } + break; + } + else + { + /*--------------------------------------------------------------*/ + /* struct field or array element */ + if (ms_comp_name_pres(rt_ptr) == SD_TRUE) + { + elName = ms_comp_name_find(rt_ptr); + if (dc->sxdXmlStyle == SXD_XML_STYLE_A) + { + strcpy (nameBuf, structPrefix); + strcat (nameBuf, elName); + if (strcmp (dc->elName, nameBuf) == 0) + break; /* found element name, process it */ + else + { + /* not name we search for, skip it */ + _SXD_ADVANCE_PTR(rt_ptr, SD_FALSE); + continue; + } + } + } + + if (elName != NULL) + { + if (strcmp (dc->elName, elName) == 0) + break; /* found element name, process it */ + else + { + _SXD_ADVANCE_PTR(rt_ptr, SD_FALSE); + continue; /* continue looking for the dc->elName */ + } + } + else + { + /* elName maybe NULL in the case of an array element (plain array) */ + if (plain_array) + { + /* since no array element end tag will be decoded, we need */ + /* to handle this case here */ + if (--arr_loops[arr_loop_level] > 0) /* if need next ar elmnt */ + { + /* there should be more array elements to process, need to */ + /* reset the rt to the beginning of the array */ + set_arr_start = SD_TRUE; + } + else + { + /* all array elements processed, decrement loop level */ + --arr_loop_level; + if (arr_loops[arr_loop_level] > 0) + set_arr_start = SD_TRUE; /* more elements to process */ + else + set_arr_end = SD_TRUE; /* end of array */ + } + break; + } + else + { + SXLOG_NERR1 ("Could not find tag '%s' (found 'NULL')", dc->elName); + M_FREE (NULL, dc); + return (SD_FAILURE); + } + } + } + + /* !!! if we get here some 'if-else' is not handled! return error */ + SXLOG_NERR0 ("Unhandled code, returning from function sxd_decode_rtdata_el."); + M_FREE (NULL, dc); + return (SD_FAILURE); + } /* end of inner while loop */ + + if (rt_ptr >= rt_end || uDataRet != SD_SUCCESS) + { + SXLOG_NERR1 ("Could not find RT for element name %s", dc->elName); + M_FREE (NULL, dc); + return (SD_FAILURE); + } + + /* We found a RUNTIME element that matches the XML name */ + + if (1 || dc->dataEl == SD_TRUE) + { + switch (rt_ptr->el_tag) + { + case RT_ARR_START : + uDataRet = _sxdDecArrStart (dc, rt_ptr); + break; + + case RT_STR_START : + uDataRet = _sxdDecStrStart (dc, rt_ptr); + break; + + case RT_ARR_END : /* array done */ + uDataRet = _sxdDecArrEnd (dc, rt_ptr); + break; + + case RT_STR_END : /* structure done */ + uDataRet = _sxdDecStrEnd (dc, rt_ptr); + break; + + case RT_BOOL : + uDataRet = _sxdDecBool (dc, (ST_BOOLEAN *) datptr, rt_ptr); + break; + + case RT_BIT_STRING : + uDataRet = _sxdDecBs (dc, (ST_UCHAR *) datptr, rt_ptr); + break; + + case RT_INTEGER : + switch (rt_ptr->u.p.el_len) /* determine length */ + { + case 1 : /* one byte int */ + uDataRet = _sxdDecInt8 (dc, (ST_INT8 *) datptr, rt_ptr); + break; + + case 2 : /* two byte int */ + uDataRet = _sxdDecInt16 (dc, (ST_INT16 *) datptr, rt_ptr); + break; + + case 4 : /* four byte integer */ + uDataRet = _sxdDecInt32 (dc, (ST_INT32 *) datptr, rt_ptr); + break; + +#ifdef INT64_SUPPORT + case 8 : /* eight byte integer */ + uDataRet = _sxdDecInt64 (dc, (ST_INT64 *) datptr, rt_ptr); + break; +#endif + } + break; + + case RT_UNSIGNED : + switch (rt_ptr->u.p.el_len) /* determine length */ + { + case 1 : /* one byte int */ + uDataRet = _sxdDecUint8 (dc, (ST_UCHAR *) datptr, rt_ptr); + break; + + case 2 : /* two byte int */ + uDataRet = _sxdDecUint16 (dc, (ST_UINT16 *) datptr, rt_ptr); + break; + + case 4 : /* four byte integer */ + uDataRet = _sxdDecUint32 (dc, (ST_UINT32 *) datptr, rt_ptr); + break; + +#ifdef INT64_SUPPORT + case 8 : /* eight byte integer */ + uDataRet = _sxdDecUint64 (dc, (ST_UINT64 *) datptr, rt_ptr); + break; +#endif /* INT64_SUPPORT */ + } + break; + +#ifdef FLOAT_DATA_SUPPORT + case RT_FLOATING_POINT : + if (rt_ptr->u.p.el_len != sizeof (ST_FLOAT)) + { + uDataRet = _sxdDecDbl (dc, (ST_DOUBLE *) datptr, rt_ptr); + } + else + { + uDataRet = _sxdDecFlt (dc, (ST_FLOAT *) datptr, rt_ptr); + } + break; +#endif + + case RT_OCTET_STRING : + uDataRet = _sxdDecOct (dc, (ST_UCHAR *) datptr, rt_ptr); + break; + + case RT_VISIBLE_STRING : + uDataRet = _sxdDecVis (dc, (ST_CHAR *) datptr, rt_ptr); + break; + +#ifdef TIME_DATA_SUPPORT + case RT_GENERAL_TIME : + uDataRet = _sxdDecGt (dc, (time_t *) datptr, rt_ptr); + break; +#endif + +#ifdef BTOD_DATA_SUPPORT + case RT_BINARY_TIME : + switch (rt_ptr->u.p.el_len) /* determine length */ + { + case 4: + uDataRet = _sxdDecBt4 (dc, (ST_INT32 *) datptr, rt_ptr); + break; + case 6: + uDataRet = _sxdDecBt6 (dc, (ST_INT32 *) datptr, rt_ptr); + break; + } + break; +#endif + + case RT_BCD : + if (rt_ptr->u.p.el_len <= 2) + { + uDataRet = _sxdDecBcd1 (dc, (ST_INT8 *) datptr, rt_ptr); + } + else if (rt_ptr->u.p.el_len <= 4) + { + uDataRet = _sxdDecBcd2 (dc, (ST_INT16 *) datptr, rt_ptr); + } + else if (rt_ptr->u.p.el_len <= 8) + { + uDataRet = _sxdDecBcd4 (dc, (ST_INT32 *) datptr, rt_ptr); + } + break; + + default : /* should not be any other tag */ + SXLOG_ERR1 ("Invalid tag: %d", (int) rt_ptr->el_tag); + M_FREE (NULL, dc); + return (SD_FAILURE); + break; + } + + /* Set the element present flag for this element to TRUE */ + if (elPres != NULL) + elPres[rt_ptr - rt_head] = SD_TRUE; + datptr += rt_ptr->el_size; /* Adjust data pointer */ + + if (set_arr_start) + { + if (plain_array) + --rt_ptr; /* rt_ptr to arr start */ + else + rt_ptr -= rt_ptr->u.arr.num_rt_blks + 1; /* rt_ptr to arr start */ + while ((rt_ptr-1)->el_tag == RT_ARR_START) /* if multidimensional */ + --rt_ptr; /* go to first level */ + } + else if (set_arr_end) + { + rt_ptr++; + /* if multidimensional array, pass the last RT_ARR_END */ + while ((rt_ptr)->el_tag == RT_ARR_END) + { + _SXD_ADVANCE_PTR(rt_ptr, SD_TRUE); + } + } + else + rt_ptr++; /* point to next rt elmt*/ + } /* if (1 || ...) */ + } /* end of outher while loop */ + *xmlUsed = dc->xmlPos - xml; + M_FREE (NULL, dc); + return (uDataRet); + } + diff --git a/mmslib/util/sx_dec.c b/mmslib/util/sx_dec.c new file mode 100644 index 0000000..e03960f --- /dev/null +++ b/mmslib/util/sx_dec.c @@ -0,0 +1,2520 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999 - 2008, All Rights Reserved */ +/* */ +/* MODULE NAME : sx_dec.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 02/06/08 EJV 88 Added SX_PARSING_OK, sx_err_str* (for slogs).*/ +/* 01/14/08 MDE 87 Fixed numOcc multithread problem */ +/* 10/04/07 MDE 86 Tweaked LOGCFG_VALUE_GROUP/LOGCFGX_VALUE_MAP */ +/* For early MODLOGS see previous revision of this file on PVCS. */ +/************************************************************************/ + +#if defined (_WIN32) +#pragma warning(disable : 4996) +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "sx_defs.h" +#include "sx_log.h" +#include "time_str.h" +#include "str_util.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +#if defined(USE_EXPAT) +/* Assume linking to Expat "static" library. Must define XML_STATIC */ +/* before including "expat.h". */ +#define XML_STATIC +#include "expat.h" +#define EXPAT_BUF_SIZE 8192 /* parse buffer size if reading from file*/ +#define ENTITY_BUF_SIZE 2000 /* initial size to alloc for entity buffer*/ + /* reallocate larger if needed */ + +static void XMLCALL expatHandlerStartSkip(void *userData, const char *el, const char **attr); +static void XMLCALL expatHandlerEndSkip(void *userData, const char *el); +#endif +/************************************************************************/ + +SD_CONST ST_CHAR *SD_CONST _sx_log_dec_logstr = "SX_LOG_DEC"; +SD_CONST ST_CHAR *SD_CONST _sx_log_enc_logstr = "SX_LOG_ENC"; +SD_CONST ST_CHAR *SD_CONST _sx_log_flow_logstr = "SX_LOG_FLOW"; +SD_CONST ST_CHAR *SD_CONST _sx_log_debug_logstr = "SX_LOG_DEBUG"; +SD_CONST ST_CHAR *SD_CONST _sx_log_err_logstr = "SX_LOG_ERR"; +SD_CONST ST_CHAR *SD_CONST _sx_log_nerr_logstr = "SX_LOG_NERR"; + +ST_UINT sx_debug_sel = SX_LOG_ERR | SX_LOG_NERR; +ST_UINT sx_debug_sel_cfg = SX_LOG_ERR | SX_LOG_NERR; /* saves SX masks while logging configuration is parsed */ + +#ifdef DEBUG_SISCO +LOGCFGX_VALUE_MAP sxLogMaskMaps[] = + { + {"SX_LOG_ERR", SX_LOG_ERR, &sx_debug_sel_cfg, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Error"}, + {"SX_LOG_NERR", SX_LOG_NERR, &sx_debug_sel_cfg, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Notice"}, + {"SX_LOG_FLOW", SX_LOG_FLOW, &sx_debug_sel_cfg, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Flow"}, + {"SX_LOG_DEC", SX_LOG_DEC, &sx_debug_sel_cfg, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Decode"}, + {"SX_LOG_ENC", SX_LOG_ENC, &sx_debug_sel_cfg, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Encode"}, + {"SX_LOG_DEBUG", SX_LOG_DEBUG, &sx_debug_sel_cfg, _LOGCFG_DATATYPE_UINT_MASK, NULL, "Debug"}, + }; + +LOGCFG_VALUE_GROUP sxLogMaskMapCtrl = + { + {NULL,NULL}, + "SxLogMasks", /* Parent Tag */ + sizeof(sxLogMaskMaps)/sizeof(LOGCFGX_VALUE_MAP), + sxLogMaskMaps + }; + +/* tbl of error strings, used in slogs */ +ST_CHAR *sx_err_str[] = + { + "SX_PARSING_OK", /* 0 */ + "SX_USER_ERROR", /* 1 */ + "SX_STRUCT_NOT_FOUND", /* 2 */ + "SX_REQUIRED_TAG_NOT_FOUND", /* 3 */ + "SX_DUPLICATE_NOT_ALLOWED", /* 4 */ + "SX_EMPTY_TAG_NOT_ALLOWED", /* 5 */ + "SX_XML_NEST_TOO_DEEP", /* 6 */ + "SX_XML_BUFFER_OVER_MAX", /* 7 */ + "SX_XML_MALFORMED", /* 8 */ + "SX_FILE_NOT_FOUND", /* 9 */ + "SX_END_PARSING", /* 10 */ + "SX_ELEMENT_TBL_TOO_BIG" /* 11 */ + }; +ST_INT sx_err_str_cnt = sizeof (sx_err_str)/sizeof (ST_CHAR *); +#endif /* DEBUG_SISCO */ + + + +/************************************************************************/ + +ST_BOOLEAN sxUseSax; +ST_BOOLEAN sxIgnoreNS; + +ST_RET sx_rip_xml (SX_DEC_CTRL *sxDecCtrl); +ST_RET sx_rip_xml_file (SX_DEC_CTRL *sxDecCtrl); +ST_RET sx_rip_xml_mem (SX_DEC_CTRL *sxDecCtrl); + +SX_ELEMENT *_uibed_find_element (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag, ST_INT **numOccOut); +static ST_VOID _sx_pop (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN auto_pop); + +/************************************************************************/ +/* sx_parseExx_mt */ +/* Note: when making changes/correction to this function revise also */ +/* other sx_parse functions. */ +/* Decode the XML located in file by loading the whole thing into */ +/* memory first ... */ +/************************************************************************/ + +ST_RET sx_parseExx_mt (ST_CHAR *fileName, ST_INT numItems, + SX_ELEMENT *itemTbl, ST_VOID *usr, + ST_RET (*u_sx_el_start_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag), + ST_RET (*u_sx_el_end_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag)) + { +ST_RET rc; +ST_LONG fileSize; +ST_LONG bytesRead; +ST_CHAR *cfgData; +struct stat buf; +int result; +FILE *fp; + +/* Get the size of the file */ + fp = fopen (fileName, "r"); + if (fp == NULL) + { + /* + SXLOG_FLOW2 ("XML File (%s) Open Error (errno=%d)", fileName, errno); + printf ("XML File (%s) Open Error (errno=%d)\n", fileName, errno); + */ + return (SX_FILE_NOT_FOUND); + } + result = fstat (fileno (fp), &buf); + if (result != 0) + return (SD_FAILURE); + +/* Allocate a buffer and read all into memory */ + fileSize = buf.st_size; + cfgData = (ST_CHAR *) chk_malloc (fileSize); + + bytesRead = fread (cfgData, 1, fileSize, fp); + fclose (fp); + if (bytesRead <= 0) + { + chk_free (cfgData); + SXLOG_FLOW1 ("Error: Could not read from '%s'", fileName); + return (SX_FILE_NOT_FOUND); + } + + rc = sx_parse_mt (bytesRead, cfgData, numItems, itemTbl, usr, + u_sx_el_start_fun, u_sx_el_end_fun); + if (rc != SD_SUCCESS) + { + SXLOG_FLOW1 ("ERROR: parsing failed, return code: '%d'", rc); + } + + chk_free (cfgData); + return (rc); + } + +/************************************************************************/ +/* sx_parse_mt */ +/* Note: when making changes/correction to this function revise also */ +/* other sx_parse functions. */ +/* Decode the XML located in memory (thread safe version). */ +/************************************************************************/ +ST_RET sx_parse_mt (ST_LONG lMsgLen, ST_CHAR *xml, ST_INT numItems, + SX_ELEMENT *itemTbl, ST_VOID *usr, + ST_RET (*u_sx_el_start_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag), + ST_RET (*u_sx_el_end_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag)) +{ +SX_DEC_CTRL *sxDecCtrl; +ST_RET rc; + + SXLOG_FLOW0 ("Start Decoding XML"); + SXLOG_FLOWH ((ST_INT) lMsgLen, xml); + + sxDecCtrl = (SX_DEC_CTRL *) calloc (1, sizeof (SX_DEC_CTRL)); + /* !we need to use here the system calloc */ + + sx_push (sxDecCtrl, numItems, itemTbl, SD_FALSE); + sxDecCtrl->xmlStart = xml; + sxDecCtrl->xmlLen = lMsgLen; + sxDecCtrl->ignoreNS = sxIgnoreNS; + sxDecCtrl->useFp = SD_FALSE; + sxDecCtrl->usr = usr; + sxDecCtrl->u_sx_el_start = u_sx_el_start_fun; + sxDecCtrl->u_sx_el_end = u_sx_el_end_fun; + +#if defined(USE_EXPAT) + sx_rip_xml_mem (sxDecCtrl); +#else + sx_rip_xml (sxDecCtrl); +#endif + + if (sxDecCtrl->xmlNestLevel != 0 && sxDecCtrl->errCode == SD_SUCCESS) + { + sxDecCtrl->errCode = SX_XML_MALFORMED; + SXLOG_NERR0 ("Invalid XML nesting"); + } + + rc = sxDecCtrl->errCode; + + free (sxDecCtrl); + + return (rc); +} + +/************************************************************************/ +/* sx_parseEx_mt */ +/* Note: when making changes/correction to this function revise also */ +/* other sx_parse functions. */ +/* Decode the XML located in file (thread safe version). */ +/************************************************************************/ +ST_RET sx_parseEx_mt (ST_CHAR *fileName, ST_INT numItems, + SX_ELEMENT *itemTbl, ST_VOID *usr, + ST_RET (*u_sx_el_start_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag), + ST_RET (*u_sx_el_end_fun) (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag)) +{ +SX_DEC_CTRL *sxDecCtrl; +ST_RET rc; +FILE *fp; + + SXLOG_FLOW1 ("Start Decoding XML file %s", fileName); + if ((fp = fopen (fileName,"r"))==NULL) + { + SXLOG_FLOW1 ("XML File (%s) Open Error",fileName); + return (SX_FILE_NOT_FOUND); + } + + sxDecCtrl = (SX_DEC_CTRL *) calloc (1, sizeof (SX_DEC_CTRL)); + /* !we need to use here the system calloc */ + + sx_push (sxDecCtrl, numItems, itemTbl, SD_FALSE); + sxDecCtrl->fp = fp; + sxDecCtrl->ignoreNS = sxIgnoreNS; + sxDecCtrl->useFp = SD_TRUE; + sxDecCtrl->usr = usr; + sxDecCtrl->u_sx_el_start = u_sx_el_start_fun; + sxDecCtrl->u_sx_el_end = u_sx_el_end_fun; + +#if defined(USE_EXPAT) + sx_rip_xml_file (sxDecCtrl); +#else + sx_rip_xml (sxDecCtrl); +#endif + + if (sxDecCtrl->errCode == 0) + { + if (sxDecCtrl->xmlNestLevel != 0) + { + sxDecCtrl->errCode = SX_XML_MALFORMED; + SXLOG_NERR0 ("Invalid XML nesting"); + } + } + + rc = sxDecCtrl->errCode; + + free (sxDecCtrl); + + fclose (fp); + return (rc); +} + + +/************************************************************************/ +/* sxStartElement */ +/************************************************************************/ + +ST_VOID sxStartElement (SX_DEC_CTRL *sxDecCtrl) + { +SX_ELEMENT *item; +SX_DEC_ELEMENT_INFO *sxDecElInfo; +ST_CHAR *tag; +ST_RET rc = SD_FAILURE; +ST_INT stackLevelSave; +ST_INT *numOccPtr; + + sxDecElInfo = &sxDecCtrl->sxDecElInfo; + tag = sxDecElInfo->tag; + SXLOG_DEC1 ("Start element '%s'", tag); + if (sxDecCtrl->errCode != SD_SUCCESS && sxDecCtrl->errCode != SX_ERR_CONVERT) + { + return; + } + + item = _uibed_find_element (sxDecCtrl, tag, &numOccPtr); + + stackLevelSave = sxDecCtrl->itemStackLevel; + while (item == NULL && sxDecCtrl->itemStackLevel > 0) + { + if (sxDecCtrl->auto_pop[sxDecCtrl->itemStackLevel-1] == SD_TRUE) + { + _sx_pop (sxDecCtrl, SD_TRUE); + item = _uibed_find_element (sxDecCtrl, tag, &numOccPtr); + } + else + break; + } + + if (item != NULL) + { + if (*numOccPtr != 0 && ((item->elementFlags & SX_ELF_RPT) == 0)) + { + sxDecCtrl->errCode = SX_DUPLICATE_NOT_ALLOWED; + SXLOG_NERR1 ("Duplicate of element '%s' not allowed", tag); + return; + } + ++(*numOccPtr); + if (*numOccPtr > 1) + { + SXLOG_CDEC1 ("Number occurences: %d", *numOccPtr); + } + + /* Save the item for later */ + ++sxDecCtrl->xmlNestLevel; + sxDecCtrl->elTbl[sxDecCtrl->xmlNestLevel] = item; + + /* Call the user function, if there is one ... */ + sxDecCtrl->item = item; + sxDecCtrl->reason = SX_ELEMENT_START; + if ((item->elementFlags & SX_ELF_CSTART) != 0) + { + if (item->funcPtr != NULL) + { + sxDecCtrl->elUser = item->user; + (item->funcPtr)(sxDecCtrl); + } + else + { + SXLOG_CDEC0 ("No state function for this element"); + } + } + } + else if (sxDecCtrl->u_sx_el_start != NULL) + { + sxDecCtrl->itemStackLevel = stackLevelSave; + + if (sxDecCtrl->u_sx_el_start != NULL) + rc = (*(sxDecCtrl->u_sx_el_start)) (sxDecCtrl, tag); + if (rc == SD_SUCCESS) + { + ++sxDecCtrl->xmlNestLevel; + sxDecCtrl->elTbl[sxDecCtrl->xmlNestLevel] = NULL; + } + else + { + sxDecCtrl->errCode = SX_STRUCT_NOT_FOUND; + SXLOG_CDEC1 ("u_sx_el_start failed for element '%s'", tag); + } + } + else + { + sxDecCtrl->errCode = SX_STRUCT_NOT_FOUND; + SXLOG_NERR1 ("Could not find element '%s' in element table", tag); + } + } + +/************************************************************************/ +/* sxEndElement */ +/************************************************************************/ + +ST_VOID sxEndElement (SX_DEC_CTRL *sxDecCtrl) + { +SX_DEC_ELEMENT_INFO *sxDecElInfo; +SX_ELEMENT *item; +ST_CHAR *tag; +ST_RET rc = SD_FAILURE; + + sxDecElInfo = &sxDecCtrl->sxDecElInfo; + tag = sxDecElInfo->tag; + SXLOG_DEC1 ("End element '%s'", tag); + if (sxDecCtrl->errCode != SD_SUCCESS && sxDecCtrl->errCode != SX_ERR_CONVERT) + { + return; + } + + item = sxDecCtrl->elTbl[sxDecCtrl->xmlNestLevel]; + --sxDecCtrl->xmlNestLevel; + + if (item != NULL) + { + if (strcmp (tag, item->tag) != 0) /* verify end tag */ + { + sxDecCtrl->errCode = SX_XML_MALFORMED; + SXLOG_NERR2 ("XML malformed: found , expected ", tag, item->tag); + } + else + { + if ((item->elementFlags & SX_ELF_CEND) != 0) + { + sxDecCtrl->item = item; + sxDecCtrl->reason = SX_ELEMENT_END; + if (item->funcPtr != NULL) + { + sxDecCtrl->elUser = item->user; + (item->funcPtr)(sxDecCtrl); + } + else + { + SXLOG_CDEC0 ("No state function for this element"); + } + } + } + } + else + { + if (sxDecCtrl->u_sx_el_end != NULL) + { + rc = (*(sxDecCtrl->u_sx_el_end)) (sxDecCtrl, sxDecCtrl->sxDecElInfo.tag); + if (rc != SD_SUCCESS) + { + sxDecCtrl->errCode = SX_STRUCT_NOT_FOUND; + SXLOG_NERR1 ("u_sx_el_end failed for element '%s'", tag); + } + } + } + } + +/************************************************************************/ +/************************************************************************/ +/* sx_push */ +/************************************************************************/ + +ST_VOID sx_push (SX_DEC_CTRL *sxDecCtrl, ST_INT numItems, SX_ELEMENT *itemTbl, + ST_BOOLEAN auto_pop) + { +ST_INT i; +SX_ELEMENT_TBL_CTRL *itemTblCtrl; +ST_INT *numOccTbl; + +/* Do some sanity checks first */ + if (sxDecCtrl->itemStackLevel >= SX_MAX_STACK_LEVEL) + { + sxDecCtrl->errCode = SX_XML_NEST_TOO_DEEP; + return; + } + if (numItems > SX_MAX_ITEMS_PER_TABLE) + { + sxDecCtrl->errCode = SX_ELEMENT_TBL_TOO_BIG; + return; + } + + itemTblCtrl = &sxDecCtrl->items[sxDecCtrl->itemStackLevel]; + numOccTbl = itemTblCtrl->numOccTbl; + + itemTblCtrl->itemTbl= itemTbl; + itemTblCtrl->numItems= numItems; + sxDecCtrl->auto_pop[sxDecCtrl->itemStackLevel] = auto_pop; + ++sxDecCtrl->itemStackLevel; + +/* reset the numOCc elements */ + for (i = 0; i < numItems; ++i) + numOccTbl[i] = 0; + } + +/************************************************************************/ +/* sx_pop */ +/************************************************************************/ + +ST_VOID sx_pop (SX_DEC_CTRL *sxDecCtrl) + { + _sx_pop (sxDecCtrl, SD_FALSE); + } + + +/************************************************************************/ +/* _sx_pop */ +/************************************************************************/ + +static ST_VOID _sx_pop (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN auto_pop) + { +SX_ELEMENT_TBL_CTRL *itemTblCtrl; +SX_ELEMENT *item; +ST_INT i; +ST_INT *numOccTbl; + +/* Check for mandatory elements */ + if (sxDecCtrl->itemStackLevel > 0) + { + --sxDecCtrl->itemStackLevel; + /* If auto-popping AND have a unknown element handler, don't check mandatory */ + if (auto_pop && sxDecCtrl->u_sx_el_start != NULL) + return; + + itemTblCtrl = &sxDecCtrl->items[sxDecCtrl->itemStackLevel]; + numOccTbl = itemTblCtrl->numOccTbl; + for (i = 0; i < itemTblCtrl->numItems; ++i) + { + item = &itemTblCtrl->itemTbl[i]; + if (numOccTbl[i] == 0 && ((item->elementFlags & SX_ELF_OPT) == 0)) + { + sxDecCtrl->errCode = SX_REQUIRED_TAG_NOT_FOUND; + SXLOG_NERR1 ("Mandatory element '%s' not found", item->tag); + break; + } + } + } + } + + +/************************************************************************/ +/************************************************************************/ + +SX_ELEMENT *_uibed_find_element (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag, ST_INT **numOccPtrOut) + { +SX_ELEMENT_TBL_CTRL *itemTblCtrl; +ST_INT numItems; +SX_ELEMENT *item; +ST_INT i; + + itemTblCtrl = &sxDecCtrl->items[sxDecCtrl->itemStackLevel-1]; + item = itemTblCtrl->itemTbl; + numItems = itemTblCtrl->numItems; + +/* See if this element is in our table */ + for (i = 0; i < numItems; ++i, ++item) + { + if (strcmp (tag, item->tag) == 0) + { + *numOccPtrOut = &itemTblCtrl->numOccTbl[i]; + return (item); + } + } + return (NULL); + } + + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ + +ST_RET sx_get_element_contents (SX_DEC_CTRL *sxDecCtrl, + ST_CHAR *destBuf, ST_INT destLen, + ST_INT *lenOut) + { +ST_CHAR *src; +ST_INT len; +ST_INT rc; + + rc = sx_find_element_contents (sxDecCtrl, &src, &len); + if (rc != SD_SUCCESS) + return (rc); + + if (destLen < len) + { + SXLOG_NERR0("sx_get_element_contents: dest too small"); + SXLOG_NERR1 ("Error: sx_get_element_contents: dest too small for tag '%s'", sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + + memcpy (destBuf, src, len); + *lenOut = len; + return (SD_SUCCESS); + } + +/************************************************************************/ + +ST_RET sx_find_element_contents (SX_DEC_CTRL *sxDecCtrl, + ST_CHAR **elStartOut, ST_INT *lenOut) + { +SX_DEC_ELEMENT_INFO *sxDecElInfo; +ST_CHAR *start; +ST_CHAR *end; +ST_CHAR endTagBuf[100]; +ST_INT len; +#if defined(USE_EXPAT) +int offset; +int size; +const char *ptr; + + /* Doesn't work if reading one buffer at a time from a file. */ + if (sxDecCtrl->fp) + { + SXLOG_ERR0 ("sx_find_element_contents only works if entire XML is in memory. Use sx_parseExx_mt or sx_parse_mt."); + return (SD_FAILURE); + } + + /* Set "start" ptr to point after end of this start tag. */ + ptr = XML_GetInputContext(sxDecCtrl->parser, &offset, &size); + ptr += offset; /* point to current position in XML buffer */ + /* should be beginning of start tag */ + start = strchr (ptr, '>') + 1; /* point after end of start tag */ + + /* save nest level to help find corresponding end tag */ + sxDecCtrl->skipNestLevel = sxDecCtrl->xmlNestLevel; + /* Change handlers to skip to end of this element (look for end tag). */ + XML_SetCharacterDataHandler(sxDecCtrl->parser, NULL); /* ignore element data */ + XML_SetElementHandler(sxDecCtrl->parser, expatHandlerStartSkip, expatHandlerEndSkip); + sxDecElInfo = &sxDecCtrl->sxDecElInfo; +#else + sxDecElInfo = &sxDecCtrl->sxDecElInfo; + start = sxDecCtrl->xmlPos; +#endif +/* Check to see if this is an empty element */ + if (*(start - 2) == '/') + { + *lenOut = 0; + return (SD_SUCCESS); + } + + *elStartOut = start; + len = sxDecCtrl->xmlLen - (start - sxDecCtrl->xmlStart); + +/* We need to find the closing element for this start element */ + endTagBuf[0] = '<'; + endTagBuf[1] = '/'; + strcpy (&endTagBuf[2], sxDecElInfo->tag); + strcat (endTagBuf, ">"); + + end = strnstr (start, endTagBuf, len); + if (end == NULL) + { + SXLOG_NERR1("Can't find end tag '%s'", sxDecElInfo->tag); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + *lenOut = end - start; + +#if !defined(USE_EXPAT) /* with Expat, can't set or use xmlPos */ + sxDecCtrl->xmlPos = end; +#endif + + SXLOG_CDEC0("sx_find_element_contents got data:"); + SXLOG_DECH (*lenOut, *elStartOut); + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +/* sx_get_entity */ +/************************************************************************/ + +ST_RET sx_get_entity (SX_DEC_CTRL *sxDecCtrl, + ST_CHAR *destBuf, ST_INT destLen, + ST_INT *lenOut) + { +#if defined(USE_EXPAT) + if (destLen < sxDecCtrl->entityLen) + { + SXLOG_NERR2 ("Error: sx_get_entity: dest too small (max %d bytes expected) for tag '%s'", destLen, sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + *lenOut = 0; /* return empty buf */ + return (SD_FAILURE); + } + else + { + memcpy (destBuf, sxDecCtrl->entityBuf, sxDecCtrl->entityLen); + *lenOut = sxDecCtrl->entityLen; + } + if (*lenOut == 0) + SXLOG_CDEC0("sx_get_entity (no data)"); + else + { + SXLOG_CDEC0("sx_get_entity got data:"); + SXLOG_DECH (*lenOut, destBuf); + } + return (SD_SUCCESS); +#else /* !USE_EXPAT */ +SX_DEC_ELEMENT_INFO *sxDecElInfo; +ST_INT i; +ST_CHAR *dest; +ST_CHAR *src; +ST_CHAR *end; + + sxDecElInfo = &sxDecCtrl->sxDecElInfo; + src = sxDecElInfo->entityStart; + dest = destBuf; + end = sxDecElInfo->entityEnd; + for (i = 0; i < destLen && src < end; ++i, ++src, ++dest) + *dest = *src; + + *lenOut = i; + + if (src < end) + { + SXLOG_NERR2 ("Error: sx_get_entity: dest too small (max %d bytes expected) for tag '%s'", destLen, sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + + SXLOG_CDEC0("sx_get_entity got data:"); + SXLOG_DECH (i, destBuf); + return (SD_SUCCESS); +#endif /* !USE_EXPAT */ + } + + +/************************************************************************/ +/* sx_get_bool */ +/************************************************************************/ + +ST_RET sx_get_bool (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN *out_ptr) + { +ST_INT d; +ST_RET rc; + + rc = sx_get_value (sxDecCtrl, "%d", &d); + if (rc != SD_SUCCESS) + return (rc); + + if (d == 0) + *out_ptr = SD_FALSE; + else + *out_ptr = SD_TRUE; + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_get_int */ +/************************************************************************/ + +ST_RET sx_get_int (SX_DEC_CTRL *sxDecCtrl, ST_INT *out_ptr) + { + return (sx_get_value (sxDecCtrl, "%d", out_ptr)); + } + +/************************************************************************/ +/* sx_get_float */ +/************************************************************************/ + +ST_RET sx_get_float (SX_DEC_CTRL *sxDecCtrl, ST_FLOAT *out_ptr) + { + return (sx_get_value (sxDecCtrl, "%f", out_ptr)); + } + +/************************************************************************/ +/* sx_get_double */ +/************************************************************************/ + +ST_RET sx_get_double (SX_DEC_CTRL *sxDecCtrl, ST_DOUBLE *out_ptr) + { + /* Note: must use the '%le' format specifier for double */ + return (sx_get_value (sxDecCtrl, "%le", out_ptr)); + } + +/************************************************************************/ +/* sx_get_uchar */ +/************************************************************************/ + +ST_RET sx_get_uchar (SX_DEC_CTRL *sxDecCtrl, ST_UCHAR *out_ptr) + { + return (sx_get_value (sxDecCtrl, "%c", out_ptr)); + } + +/************************************************************************/ +/* sx_get_int16 */ +/************************************************************************/ + +ST_RET sx_get_int16 (SX_DEC_CTRL *sxDecCtrl, ST_INT16 *out_ptr) + { +ST_INT i; +ST_RET rc; + + if ((rc = sx_get_value (sxDecCtrl, "%d", &i)) == SD_SUCCESS) + *out_ptr = (ST_INT16) i; + return (rc); + } + +/************************************************************************/ +/* sx_get_uint16 */ +/************************************************************************/ + +ST_RET sx_get_uint16 (SX_DEC_CTRL *sxDecCtrl, ST_UINT16 *out_ptr) + { + return (sx_get_value (sxDecCtrl, "%hu", out_ptr)); + } + +/************************************************************************/ +/* sx_get_uint32 */ +/************************************************************************/ + +ST_RET sx_get_uint32 (SX_DEC_CTRL *sxDecCtrl, ST_UINT32 *out_ptr) + { +ST_ULONG ul; +ST_RET rc; + + if ((rc = sx_get_value (sxDecCtrl, "%lu", &ul)) == SD_SUCCESS) + *out_ptr = (ST_UINT32) ul; + return (rc); + } + +/************************************************************************/ +/* sx_get_uint32_hex */ +/************************************************************************/ + +ST_RET sx_get_uint32_hex (SX_DEC_CTRL *sxDecCtrl, ST_UINT32 *out_ptr) + { +ST_ULONG ul; +ST_RET rc; + + if ((rc = sx_get_value (sxDecCtrl, "0x%lx", &ul)) == SD_SUCCESS) + *out_ptr = (ST_UINT32) ul; + return (rc); + } +/************************************************************************/ +/* sx_get_int32 */ +/************************************************************************/ + +ST_RET sx_get_int32 (SX_DEC_CTRL *sxDecCtrl, ST_INT32 *out_ptr) + { +ST_LONG sl; +ST_RET rc; + + if ((rc = sx_get_value (sxDecCtrl, "%ld", &sl)) == SD_SUCCESS) + *out_ptr = (ST_INT32) sl; + return (rc); + } + +/************************************************************************/ +/* sx_get_long */ +/************************************************************************/ + +ST_RET sx_get_long (SX_DEC_CTRL *sxDecCtrl, ST_LONG *out_ptr) + { + return (sx_get_value (sxDecCtrl, "%ld", out_ptr)); + } + +/************************************************************************/ +/* sx_get_ulong */ +/************************************************************************/ + +ST_RET sx_get_ulong (SX_DEC_CTRL *sxDecCtrl, ST_ULONG *out_ptr) + { + return (sx_get_value (sxDecCtrl, "%lu", out_ptr)); + } + +/************************************************************************/ +/* sx_get_uint */ +/************************************************************************/ + +ST_RET sx_get_uint (SX_DEC_CTRL *sxDecCtrl, ST_UINT *out_ptr) + { + return (sx_get_value (sxDecCtrl, "%u", out_ptr)); + } + +/************************************************************************/ +/* sx_get_value */ +/************************************************************************/ + +ST_RET sx_get_value (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *format_string, ST_VOID *out_ptr) + { +ST_CHAR *str; +ST_INT strLen; +ST_RET rc; + + strLen = 0; + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return (rc); + +/* Convert to desired data format*/ +/* Note: sscanf may return 'bad' value if the number in the str */ +/* exceeds the max value in format_string. */ + if (sscanf (str, format_string, out_ptr) != 1) + /* we just want to get one value out of the string, any other ret is an error */ + { + SXLOG_NERR1 ("Data Conversion Error for tag '%s'", sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/* *sx_get_alloc_string */ +/************************************************************************/ + +ST_RET sx_get_alloc_string (SX_DEC_CTRL *sxDecCtrl, ST_CHAR **strOut) + { +ST_CHAR *str; +ST_INT strLen; +ST_RET rc; + + strLen = 0; + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return (rc); + + *strOut = M_STRDUP(NULL,str); + return (SD_SUCCESS); + } + +/************************************************************************/ +/* *sx_get_string */ +/************************************************************************/ + +ST_RET sx_get_string (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *dest, ST_INT *lenOut) + { +ST_CHAR *str; +ST_INT strLen; +ST_RET rc; + + strLen = 0; + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return (rc); + + if (*lenOut != 0) + { + if (strLen > *lenOut) + { + SXLOG_NERR1 ("Error: String too long for tag '%s'", sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + } + + sx_format_string_dec (dest, str); + *lenOut = strLen; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_format_string_dec */ +/************************************************************************/ + +ST_VOID sx_format_string_dec (ST_CHAR *dest, ST_CHAR *src) + { +ST_CHAR *srcPtr; +ST_CHAR *srcPtrLast; +ST_CHAR *dstPtr; +ST_INT diff; + + dstPtr = dest; + srcPtrLast = src; + srcPtr = strchr (src, '&'); + + if (srcPtr == NULL) + { + strcpy (dest, src); + return; + } + + diff = srcPtr - srcPtrLast; + strncpy (dstPtr, srcPtrLast, diff); + dstPtr += diff; + + /* parse the source string and generate the dest string */ + while (srcPtr != NULL) + { + /* srcPtr points at a & */ + /* lets find out if the following characters are what we are looking for */ + if (strncmp (srcPtr, CODE_APOS, CODE_APOS_LEN) == 0) + { + *dstPtr++ = CHAR_APOS; + srcPtr += CODE_APOS_LEN; + } + else if (strncmp (srcPtr, CODE_QUOT, CODE_QUOT_LEN) == 0) + { + *dstPtr++ = CHAR_QUOT; + srcPtr += CODE_QUOT_LEN; + } + else if (strncmp (srcPtr, CODE_AMP, CODE_AMP_LEN) == 0) + { + *dstPtr++ = CHAR_AMP; + srcPtr += CODE_AMP_LEN; + } + else if (strncmp (srcPtr, CODE_LT, CODE_LT_LEN) == 0) + { + *dstPtr++ = CHAR_LT; + srcPtr += CODE_LT_LEN; + } + else if (strncmp (srcPtr, CODE_GT, CODE_GT_LEN) == 0) + { + *dstPtr++ = CHAR_GT; + srcPtr += CODE_GT_LEN; + } + else + { + *dstPtr++ = '&'; + srcPtr++; + } + + srcPtrLast = srcPtr; + srcPtr = strchr (srcPtr, '&'); + + if (srcPtr == NULL) + { + /* copy the remaining section of the string */ + strcpy (dstPtr, srcPtrLast); + } + else + { + diff = srcPtr - srcPtrLast; + strncpy (dstPtr, srcPtrLast, diff); + dstPtr += diff; + } + } + } + + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* sx_get_bool_attr */ +/************************************************************************/ + +ST_RET sx_get_bool_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_BOOLEAN *out_ptr) + { +ST_INT d; +ST_RET rc; + + rc = sx_get_attr_value (sxDecCtrl, name, "%d", &d); + if (rc != SD_SUCCESS) + return (rc); + + if (d == 0) + *out_ptr = SD_FALSE; + else + *out_ptr = SD_TRUE; + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_get_int_attr */ +/************************************************************************/ + +ST_RET sx_get_int_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_INT *out_ptr) + { + return (sx_get_attr_value (sxDecCtrl, name, "%d", out_ptr)); + } + +/************************************************************************/ +/* sx_get_float_attr */ +/************************************************************************/ + +ST_RET sx_get_float_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_FLOAT *out_ptr) + { + return (sx_get_attr_value (sxDecCtrl, name, "%f", out_ptr)); + } + +/************************************************************************/ +/* sx_get_double_attr */ +/************************************************************************/ + +ST_RET sx_get_double_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_DOUBLE *out_ptr) + { + return (sx_get_attr_value (sxDecCtrl, name, "%le", out_ptr)); + } + +/************************************************************************/ +/* sx_get_uchar_attr */ +/************************************************************************/ + +ST_RET sx_get_uchar_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UCHAR *out_ptr) + { + return (sx_get_attr_value (sxDecCtrl, name, "%c", out_ptr)); + } + +/************************************************************************/ +/* sx_get_int16_attr */ +/************************************************************************/ + +ST_RET sx_get_int16_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_INT16 *out_ptr) + { +ST_INT i; +ST_RET rc; + + if ((rc = sx_get_attr_value (sxDecCtrl, name, "%d", &i)) == SD_SUCCESS) + *out_ptr = (ST_INT16) i; + return (rc); + } + +/************************************************************************/ +/* sx_get_uint16_attr */ +/************************************************************************/ + +ST_RET sx_get_uint16_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UINT16 *out_ptr) + { +ST_UINT i; +ST_RET rc; + + if ((rc = sx_get_attr_value (sxDecCtrl, name, "%u", &i)) == SD_SUCCESS) + *out_ptr = (ST_UINT16) i; + return (rc); + } + +/************************************************************************/ +/* sx_get_uint32_attr */ +/************************************************************************/ + +ST_RET sx_get_uint32_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UINT32 *out_ptr) + { +ST_ULONG ul; +ST_RET rc; + + if ((rc = sx_get_attr_value (sxDecCtrl, name, "%lu", &ul)) == SD_SUCCESS) + *out_ptr = (ST_UINT32) ul; + return (rc); + } + +/************************************************************************/ +/* sx_get_int32_attr */ +/************************************************************************/ + +ST_RET sx_get_int32_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_INT32 *out_ptr) + { +ST_LONG sl; +ST_RET rc; + + if ((rc = sx_get_attr_value (sxDecCtrl, name, "%ld", &sl)) == SD_SUCCESS) + *out_ptr = (ST_INT32) sl; + return (rc); + } + +/************************************************************************/ +/* sx_get_long_attr */ +/************************************************************************/ + +ST_RET sx_get_long_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_LONG *out_ptr) + { + return (sx_get_attr_value (sxDecCtrl, name, "%ld", out_ptr)); + } + +/************************************************************************/ +/* sx_get_ulong_attr */ +/************************************************************************/ + +ST_RET sx_get_ulong_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_ULONG *out_ptr) + { + return (sx_get_attr_value (sxDecCtrl, name, "%lu", out_ptr)); + } + +/************************************************************************/ +/* sx_get_uint_attr */ +/************************************************************************/ + +ST_RET sx_get_uint_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, ST_UINT *out_ptr) + { + return (sx_get_attr_value (sxDecCtrl, name, "%u", out_ptr)); + } + +/************************************************************************/ +/* XmlStringToDuration */ +/************************************************************************/ + +ST_RET XmlStringToDuration (ST_CHAR *src, SX_DURATION *out_ptr) + { +ST_CHAR *p; +ST_CHAR temp[50]; /* arbitrary length */ +ST_CHAR temp2[50]; /* arbitrary length */ +ST_BOOLEAN foundP = SD_FALSE; +ST_BOOLEAN foundT = SD_FALSE; +ST_BOOLEAN foundDot = SD_FALSE; +ST_UINT i; +ST_BOOLEAN something = SD_FALSE; /* Make sure we got SOMETHING out of */ + /* this, any of the fields can be missing */ + + out_ptr->inUse = SD_TRUE; + p = src; + memset (temp, 0, sizeof(temp)); + memset (temp2, 0, sizeof(temp2)); + for (i = 0; i < strlen(src); i++, p++) + { + /* check all error conditions I can think of */ + if ((*p == '-' && foundP) || + (isdigit(*p) && !foundP) || + (*p == 'Y' && !foundP) || + (*p == 'M' && !foundP) || + (*p == 'D' && !foundP) || + (!foundP && foundT) || + (*p == 'H' && !foundT) || + (*p == 'S' && !foundT) || + (*p != 'P' && *p != 'T' && isalpha(*p) && strlen(temp) == 0)) + return (SD_FAILURE); + + /* check for negative */ + else if (*p == '-') + out_ptr->negative = SD_TRUE; + else if (*p == '.') + foundDot = SD_TRUE; + /* We found a number */ + else if (isdigit(*p)) + { + if (foundDot) + strncat (temp2, p, 1); + else + strncat (temp, p, 1); + } + /* We found a letter */ + else if (isalpha(*p)) + { + switch (*p) + { + case 'P': + foundP = SD_TRUE; + break; + case 'T': + foundT = SD_TRUE; + break; + case 'Y': + sscanf(temp, "%d", &out_ptr->years); + temp[0] = 0; + something = SD_TRUE; + break; + case 'M': + if (foundT) + sscanf(temp, "%d", &out_ptr->minutes); + else + sscanf(temp, "%d", &out_ptr->months); + temp[0] = 0; + something = SD_TRUE; + break; + case 'D': + sscanf(temp, "%d", &out_ptr->days); + temp[0] = 0; + something = SD_TRUE; + break; + case 'H': + sscanf(temp, "%d", &out_ptr->hours); + temp[0] = 0; + something = SD_TRUE; + break; + case 'S': + sscanf(temp, "%d", &out_ptr->seconds); + temp[0] = 0; + sscanf(temp2, "%ld", &out_ptr->microseconds); + temp2[0] = 0; + something = SD_TRUE; + break; + default: + return (SD_FAILURE); + } + } + } + if (something == SD_FALSE) + return (SD_FAILURE); + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_get_duration_attr */ +/************************************************************************/ + +ST_RET sx_get_duration_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, SX_DURATION *out_ptr) + { +ST_RET rc; +ST_CHAR *sxDuration; + + memset (out_ptr, 0, sizeof (*out_ptr)); + + rc = sx_get_attr_ptr (sxDecCtrl, &sxDuration, name); + if (rc) + return (rc); + + rc = XmlStringToDuration (sxDuration, out_ptr); + if (rc != SD_SUCCESS) + { + SXLOG_NERR1 ("Error: String to Duration conversion for tag '%s'", sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_get_xtime_attr */ +/************************************************************************/ + +ST_RET sx_get_xtime_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, SX_DATE_TIME *out_ptr) + { +ST_RET rc; +ST_CHAR *sxDateTime; + + memset (out_ptr, 0, sizeof (*out_ptr)); + + rc = sx_get_attr_ptr (sxDecCtrl, &sxDateTime, name); + if (rc) + return (rc); + + rc = XmlStringToUtcValue (sxDateTime, out_ptr); + if (rc != SD_SUCCESS) + { + SXLOG_NERR1 ("Error: String to Value date/time conversion for tag '%s'", sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (rc); + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_get_tm_attr */ +/************************************************************************/ + +ST_RET sx_get_tm_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, struct tm *out_ptr) + { +ST_RET rc; +ST_CHAR *theTime; + + memset (out_ptr, 0, sizeof (*out_ptr)); + + rc = sx_get_attr_ptr (sxDecCtrl, &theTime, name); + if (rc) + return (rc); + + rc = tstrStringToTm (theTime, out_ptr); + if (rc != SD_SUCCESS) + { + SXLOG_NERR1 ("Error: String to Value (struct tm) date/time conversion for tag '%s'", sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (rc); + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_get_attr_value */ +/************************************************************************/ + +ST_RET sx_get_attr_value (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name, + ST_CHAR *format_string, ST_VOID *out_ptr) + { +ST_UINT i; + + for (i = 0; i < sxDecCtrl->sxDecElInfo.attrCount; ++i) + { + if (strcmp (sxDecCtrl->sxDecElInfo.attr[i].name, name) == 0) + { + /* Convert to desired data format*/ + if (!sscanf (sxDecCtrl->sxDecElInfo.attr[i].value, + format_string, out_ptr)) + { + SXLOG_NERR1 ("Error: Attribute Data Conversion Error for tag '%s'", sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + return (SD_SUCCESS); + } + } + return (SD_FAILURE); + } + +/************************************************************************/ +/* sx_get_attr */ +/************************************************************************/ + +ST_RET sx_get_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *value, ST_CHAR *name) + { +ST_UINT i; + + for (i = 0; i < sxDecCtrl->sxDecElInfo.attrCount; ++i) + { + if (strcmp (sxDecCtrl->sxDecElInfo.attr[i].name, name) == 0) + { + strcpy (value, sxDecCtrl->sxDecElInfo.attr[i].value); + return (SD_SUCCESS); + } + } + return (SD_FAILURE); + } + +/************************************************************************/ +/* sx_get_attr_ptr */ +/************************************************************************/ + +ST_RET sx_get_attr_ptr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR **ptrOut, ST_CHAR *name) + { +ST_UINT i; + + for (i = 0; i < sxDecCtrl->sxDecElInfo.attrCount; ++i) + { + if (strcmp (sxDecCtrl->sxDecElInfo.attr[i].name, name) == 0) + { + *ptrOut = sxDecCtrl->sxDecElInfo.attr[i].value; + return (SD_SUCCESS); + } + } + return (SD_FAILURE); + } + +/************************************************************************/ +/* *sx_get_bitstring */ +/************************************************************************/ + +ST_RET sx_get_bitstring (SX_DEC_CTRL *sxDecCtrl, ST_INT *dest, ST_INT *lenOut) + { +ST_CHAR *str; +ST_INT strLen; +ST_INT *bits; +ST_CHAR *pStr; +ST_RET rc; +ST_INT i; + + strLen = 0; + bits = dest; + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return (rc); + + if (*lenOut != 0) + { + if (strLen > *lenOut) + { + SXLOG_NERR1 ("Error: String too long for tag '%s'", sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + } + + pStr = str; + pStr += strlen(str) - 1; + for (i=0;i<(ST_INT)strlen(str);++i,--pStr) + { + if (strncmp(pStr, "0", 1) != 0 && + strncmp(pStr, "1", 1) != 0) + { + SXLOG_NERR1 ("Error: Not a bitstring for tag '%s'", sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + + if (strncmp(pStr, "1", 1) == 0) + { + *bits |= (1 << i); + } + } + + *lenOut = strLen; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_get_string_ptr */ +/************************************************************************/ + +ST_RET sx_get_string_ptr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR **strOut, ST_INT *lenOut) + { +ST_INT vLen; +ST_RET rc; + + rc = sx_get_entity (sxDecCtrl, sxDecCtrl->elemBuf, sizeof(sxDecCtrl->elemBuf), &vLen); + if (rc != SD_SUCCESS) + return (SD_FAILURE); + +/* Convert to desired data format*/ + sxDecCtrl->elemBuf[vLen] = 0; + *strOut = sxDecCtrl->elemBuf; + *lenOut = vLen; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_get_string_YesNo */ +/*----------------------------------------------------------------------*/ +/* This user helper function parses element value for the string */ +/* "Yes"/"No" and sets the dest to SD_TRUE/SD_FALSE respectively. */ +/* The string comparison is not case sensitive. */ +/* Parameters: */ +/* SX_DEC_CTRL *sxDecCtrl pointer to SX decoding control */ +/* ST_BOOLEAN *dest pointer to dest to SD_TRUE/SD_FALSE */ +/* ST_RET errCode SX err code to set in sxDecCtrl->errCode*/ +/* in case of invalid element value, */ +/* SX_ERR_CONVERT allows continue parsing. */ +/* Return: */ +/* SD_SUCCESS if function successful */ +/* SD_FAILURE otherwise,and the sxDecCtrl->errCode is */ +/* set to errCode. */ +/************************************************************************/ +ST_RET sx_get_string_YesNo (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN *dest, + ST_RET errCode) + { +ST_RET rc; +ST_CHAR *str; +ST_INT strLen; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc == SD_SUCCESS) + { + if (stricmp (str, "Yes") == 0) + *dest = SD_TRUE; + else if (stricmp (str, "No") == 0) + *dest = SD_FALSE; + else + { + SXLOG_ERR2 ("SX DEC ERROR: invalid %s value '%s' (Yes/No expected)", + sxDecCtrl->sxDecElInfo.tag, str); + sxDecCtrl->errCode = errCode; + rc = SD_FAILURE; + } + } + + return (rc); + } + + +/************************************************************************/ +/* sx_get_string_OnOff_mask */ +/*----------------------------------------------------------------------*/ +/* This user helper function parses element value for the string */ +/* "On"/"Off" and sets/resets a maskBit in the mask. */ +/* The string comparison is not case sensitive. */ +/* Parameters: */ +/* SX_DEC_CTRL *sxDecCtrl pointer to SX decoding control */ +/* ST_UINT *mask pointer to mask to set/reset a bit */ +/* ST_UINT maskBit mask bit to set/reset if ON/OFF found */ +/* ST_RET errCode SX err code to set in sxDecCtrl->errCode*/ +/* in case of invalid element value, */ +/* SX_ERR_CONVERT allows continue parsing. */ +/* Return: */ +/* SD_SUCCESS if function successful */ +/* SD_FAILURE otherwise,and the sxDecCtrl->errCode is */ +/* set to errCode */ +/************************************************************************/ + +ST_RET sx_get_string_OnOff_mask (SX_DEC_CTRL *sxDecCtrl, ST_UINT *mask, + ST_UINT maskBit, ST_RET errCode) + { +ST_RET rc; +ST_CHAR *str; +ST_INT strLen; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc == SD_SUCCESS) + { + if (stricmp (str, "On") == 0) + { + *mask |= maskBit; /* turn on this bit in the mask */ + } + else if (stricmp (str, "Off") == 0) + { + *mask &= ~maskBit; /* turn off this bit in the mask */ + } + else + { + SXLOG_ERR2 ("SX DEC ERROR: invalid %s value '%s' (On/Off expected)", + sxDecCtrl->sxDecElInfo.tag, str); + sxDecCtrl->errCode = errCode; + rc = SD_FAILURE; + } + } + return (rc); + } + +/************************************************************************/ +/* sx_get_string_OnOff_bool */ +/*----------------------------------------------------------------------*/ +/* This user helper function parses element value for the string */ +/* "On"/"Off" and sets the dest to SD_TRUE/SD_FALSE respectively. */ +/* The string comparison is not case sensitive. */ +/* Parameters: */ +/* SX_DEC_CTRL *sxDecCtrl pointer to SX decoding control */ +/* ST_BOOLEAN *dest pointer to dest to SD_TRUE/SD_FALSE */ +/* ST_RET errCode SX err code to set in sxDecCtrl->errCode*/ +/* in case of invalid element value, */ +/* SX_ERR_CONVERT allows continue parsing. */ +/* Return: */ +/* SD_SUCCESS if function successful */ +/* SD_FAILURE otherwise,and the sxDecCtrl->errCode is */ +/* set to errCode */ +/************************************************************************/ + +ST_RET sx_get_string_OnOff_bool (SX_DEC_CTRL *sxDecCtrl, ST_BOOLEAN *dest, + ST_RET errCode) + { +ST_RET rc; +ST_CHAR *str; +ST_INT strLen; + + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc == SD_SUCCESS) + { + if (stricmp (str, "On") == 0) + *dest = SD_TRUE; + else if (stricmp (str, "Off") == 0) + *dest = SD_FALSE; + else + { + SXLOG_ERR2 ("SX DEC ERROR: invalid %s value '%s' (On/Off expected)", + sxDecCtrl->sxDecElInfo.tag, str); + sxDecCtrl->errCode = errCode; + rc = SD_FAILURE; + } + } + return (rc); + } + +/************************************************************************/ +/* sx_get_time */ +/************************************************************************/ +ST_RET sx_get_time (SX_DEC_CTRL *sxDecCtrl, time_t *out_ptr) + { +ST_CHAR *str; +ST_RET rc; +time_t t; +ST_INT strLen; + + strLen = 0; + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return (rc); + + + rc = tstrStringToTime (str, &t); + if (rc != SD_SUCCESS) + { + SXLOG_NERR2 ("Error: Time conversion (0x%04x) for tag '%s'", rc, sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (rc); + } + + *out_ptr = t; + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_get_tm */ +/************************************************************************/ +ST_RET sx_get_tm (SX_DEC_CTRL *sxDecCtrl, struct tm *out_ptr) + { +ST_CHAR *str; +ST_RET rc; +ST_INT strLen; + + strLen = 0; + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return (rc); + + rc = tstrStringToTm (str, out_ptr); + if (rc != SD_SUCCESS) + { + SXLOG_NERR2 ("Error: Time conversion (0x%04x) for tag '%s'", rc, sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (rc); + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_get_tm_ex */ +/************************************************************************/ +ST_RET sx_get_tm_ex (SX_DEC_CTRL *sxDecCtrl, struct tm *out_ptr, ST_LONG *microseconds) + { +ST_CHAR *str; +ST_RET rc; +ST_INT strLen; +ST_CHAR *strMicro = NULL; /* init to invalid value*/ +char *periodLoc; + + strLen = 0; + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return (rc); + + periodLoc = strchr (str, '.'); + if (periodLoc != NULL) + { + if ((periodLoc + 1) == '\0') + { + SXLOG_NERR2 ("Error: Time conversion (0x%04x) for tag '%s'", rc, sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (rc); + } + *periodLoc = '\0'; + strMicro = periodLoc + 1; + } + + rc = tstrStringToTm (str, out_ptr); + if (rc != SD_SUCCESS) + { + SXLOG_NERR2 ("Error: Time conversion (0x%04x) for tag '%s'", rc, sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (rc); + } + + if (strMicro != NULL) + { + while (strlen(strMicro) < 6) + strcat (strMicro, "0"); + while (strlen(strMicro) > 6) + strMicro[strlen(strMicro)-1] = '\0'; + *microseconds = atol(strMicro); + } + else + *microseconds = 0; + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_get_duration */ +/************************************************************************/ +/* Store duration string found in an xml file into the structure */ +/* "SX_DURATION". */ +/************************************************************************/ + +ST_RET sx_get_duration (SX_DEC_CTRL *sxDecCtrl, SX_DURATION *sxDuration) + { +ST_CHAR *str; +ST_RET rc; +ST_INT strLen; + + memset (sxDuration, 0, sizeof (*sxDuration)); + + strLen = 0; + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return (rc); + + rc = XmlStringToDuration (str, sxDuration); + if (rc != SD_SUCCESS) + { + SXLOG_NERR1 ("Error: String to Duration for tag '%s'", sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (rc); + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_get_xtime */ +/************************************************************************/ +/* Store date and time string found in an xml file into the structure */ +/* "SX_DATE_TIME" specifying the number of seconds from */ +/* 1/1/1970 (UTC time), the number of microseconds in a decimal */ +/* fraction if it is specified and the number of minutes in the time */ +/* zone offset if it is specified. */ +/************************************************************************/ + +ST_RET sx_get_xtime (SX_DEC_CTRL *sxDecCtrl, SX_DATE_TIME *sxDateTime) + { +ST_CHAR *str; +ST_RET rc; +ST_INT strLen; + + memset (sxDateTime, 0, sizeof (*sxDateTime)); + + strLen = 0; + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return (rc); + + /* convert input xml string to date and time */ + /* store data in "SX_DATE_TIME" structure */ + rc = XmlStringToUtcValue (str, sxDateTime); + if (rc != SD_SUCCESS) + { + SXLOG_NERR1 ("Error: String to Value date/time conversion for tag '%s'", sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (rc); + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_get_time_ex */ +/************************************************************************/ +ST_RET sx_get_time_ex (SX_DEC_CTRL *sxDecCtrl, time_t *out_ptr, ST_LONG *microseconds) + { +ST_CHAR *str; +ST_CHAR strMicro[10]; +char *periodLoc; +ST_RET rc; +time_t t; +ST_INT strLen; + + strLen = 0; + rc = sx_get_string_ptr (sxDecCtrl, &str, &strLen); + if (rc != SD_SUCCESS) + return (rc); + + periodLoc = strchr (str, '.'); + if (periodLoc != NULL) + { + if ((periodLoc + 1) == '\0') + { + SXLOG_NERR2 ("Error: Time conversion (0x%04x) for tag '%s'", rc, sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (rc); + } + strcpy(strMicro, periodLoc + 1); + *periodLoc = '\0'; + } + + rc = tstrStringToTime (str, &t); + if (rc != SD_SUCCESS) + { + SXLOG_NERR2 ("Error: Time conversion (0x%04x) for tag '%s'", rc, sxDecCtrl->sxDecElInfo.tag); + sxDecCtrl->errCode = SD_FAILURE; + return (rc); + } + + *out_ptr = t; + if (periodLoc != NULL) + { + while (strlen(strMicro) < 6) + strcat (strMicro, "0"); + while (strlen(strMicro) > 6) + strMicro[strlen(strMicro)-1] = '\0'; + *microseconds = atol(strMicro); + } + else + *microseconds = 0; + + return (SD_SUCCESS); + } + +/************************************************************************/ +/************************************************************************/ +#define MAX_BYTES_IN_CHUNK (2*SX_MAX_ELEM_LEN) /* MUST BE EVEN */ + +#define SX_LOAD_CHAR(a) {\ + if (sxDecCtrl->useFp == SD_TRUE)\ + {\ + sx_load_characters (lineBuf, &eof, sxDecCtrl->fp, a);\ + sxDecElInfo->entityStart-= a;\ + sxDecElInfo->entityEnd-= a;\ + }\ + else\ + {\ + xml+= a;\ + }\ + } + +#define SX_RIP_NOT_DONE (!sxDecCtrl->termFlag && (((sxDecCtrl->useFp == SD_FALSE) && (xml < xmlEnd)) || ((sxDecCtrl->useFp == SD_TRUE) && (*xml != '\0')))) + +#define SX_RIP_DONE (sxDecCtrl->termFlag || ((sxDecCtrl->useFp == SD_FALSE) && (xml >= xmlEnd)) || ((sxDecCtrl->useFp == SD_TRUE) && (*xml == '\0'))) + + +#if !defined(USE_EXPAT) +/************************************************************************/ +/* sx_rip_xml */ +/************************************************************************/ + +ST_RET sx_rip_xml (SX_DEC_CTRL *sxDecCtrl) + { +SX_DEC_ELEMENT_INFO *sxDecElInfo; +ST_CHAR *xml; +ST_INT nestLevel; +ST_CHAR *tagDest; +ST_CHAR *attribNameDest; +ST_CHAR *attribValDest; +ST_CHAR attribValCopy[SX_MAX_ATTR_VALUE]; +ST_INT len; +ST_INT midBuff; +ST_INT numChRead; +ST_LONG xmlLen; +ST_CHAR *xmlEnd = NULL; /* init to avoid compiler warning */ +ST_CHAR c; +ST_BOOLEAN bEmptyTag; +ST_BOOLEAN eof; +ST_BOOLEAN sawStartTag = SD_FALSE; +ST_CHAR lineBuf[MAX_BYTES_IN_CHUNK]; + + sxDecElInfo = &sxDecCtrl->sxDecElInfo; + + bEmptyTag = SD_FALSE; + + if (sxDecCtrl->useFp == SD_TRUE) + { + memset (lineBuf, 0, MAX_BYTES_IN_CHUNK); + eof = SD_FALSE; + midBuff = MAX_BYTES_IN_CHUNK / 2; + + /* get the first (MAX_BTYES_IN_CHUNK / 2) chunk from the file */ + numChRead = fread(lineBuf + midBuff, 1, MAX_BYTES_IN_CHUNK - midBuff, sxDecCtrl->fp); + if (numChRead > 0) + xml = lineBuf + midBuff; + else + { + SXLOG_NERR0 ("SX decode error: could not read xml from file"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + } + else + { + sxDecElInfo = &sxDecCtrl->sxDecElInfo; + xml = sxDecCtrl->xmlStart; + xmlLen = sxDecCtrl->xmlLen; + xmlEnd = xml + xmlLen; + } + + while (SX_RIP_NOT_DONE) + { +/* Find a begin or end tag */ + while (*xml != '<' && SX_RIP_NOT_DONE) + SX_LOAD_CHAR (1); + + if (SX_RIP_DONE) + break; + + sawStartTag = SD_TRUE; + + sxDecElInfo->tagStart = xml; + +/* OK, this should be the start of a start tag, an end tag, or a comment */ +/* or block of binary CDATA */ + SX_LOAD_CHAR (1); + if (strncmp (xml, "!--", 3) == 0 || *xml == '?') /* Comment */ + { + while (strncmp (xml, "-->", 3) != 0 && + strncmp (xml, "?>", 2) != 0 && + SX_RIP_NOT_DONE) + { + SX_LOAD_CHAR (1); + } + } + else if (strncmp (xml, "![CDATA[", 8) == 0) /* CDATA */ + { + while (strncmp (xml, "]]>", 3) != 0 && + SX_RIP_NOT_DONE) + { + SX_LOAD_CHAR (1); + } + } + else if (strncmp (xml, "!DOCTYPE", 8) == 0) /* DocType */ + { + nestLevel = 0; + while (SD_TRUE) + { + if (*xml == '>') + { + if (nestLevel == 0) + break; + else + --nestLevel; + } + if (*xml == '<') + ++nestLevel; + + SX_LOAD_CHAR (1); + if (SX_RIP_DONE) + { + SXLOG_NERR0 ("SX decode error: could not find DOCTYPE end"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + } + SX_LOAD_CHAR (1); + } + else if (*xml != '/') /* Begin tag */ + { + /* We have a element tag start, get the tag first */ + tagDest = sxDecElInfo->tag; + len = 0; + while (SX_RIP_NOT_DONE) + { + c = *xml; + if (c == '>' || c == ' ' || c == '/' || c == 10 || c == 9 || c == 13) /* Found the end of the tag */ + break; + + *(tagDest++) = c; + ++len; + if (len >= SX_MAX_TAG_LEN) + { + SXLOG_NERR0 ("SX decode error: tag too long"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + SX_LOAD_CHAR (1); + if (sxDecCtrl->ignoreNS && c == ':') + { + tagDest = sxDecElInfo->tag; + len = 0; + } + } + if (SX_RIP_DONE) + { + SXLOG_NERR0 ("SX decode error: could not find tag end"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + *tagDest = 0; /* terminate the tag */ + + /* Now look for attributes */ + sxDecElInfo->attrCount = 0; + while (*xml != '>' && *xml != '/') /* we could have attributes! */ + { + /* skip any whitespace before the start of the attribute name */ + while (*xml == ' ' && SX_RIP_NOT_DONE) + SX_LOAD_CHAR (1); + + if (SX_RIP_DONE) + { + SXLOG_NERR0 ("SX decode error: could not find attribute name"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + + if (*xml != '>' && *xml != '/') + { + if (sxDecElInfo->attrCount >= SX_MAX_ATTRIB) + { + SXLOG_NERR0 ("SX decode error: too many attributes. Look at SX_MAX_ATTRIB define"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + + /* This should be the start of an attribute name */ + attribNameDest = sxDecElInfo->attr[sxDecElInfo->attrCount].name; + len = 0; + while (SX_RIP_NOT_DONE) + { + c = *xml; + if (c == '=' || c == ' ') /* Found the end of the name */ + break; + + if (c == '>') /* this isn't really an attribute like we first thought */ + break; + + if (c != 9 && c != 10 && c != 13) /* dont include these characters */ + { + *(attribNameDest++) = c; + ++len; + } + + if (len >= SX_MAX_ATTR_NAME) + { + SXLOG_NERR0 ("SX decode error: attribute name too long"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + SX_LOAD_CHAR (1); + if (sxDecCtrl->ignoreNS && c == ':') + { + attribNameDest = sxDecElInfo->attr[sxDecElInfo->attrCount].name; + len = 0; + } + } + + if (SX_RIP_DONE) + { + SXLOG_NERR0 ("SX decode error: could not find attribute name end"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + + if (*xml == '>') /* this isn't really an attribute like we first thought */ + break; + + *attribNameDest = 0; /* terminate the attrib name */ + + /* skip to the attribute '=' */ + while (*xml != '=' && SX_RIP_NOT_DONE) + SX_LOAD_CHAR (1); + if (SX_RIP_DONE) + { + SXLOG_NERR0 ("SX decode error: could not find attribute '='"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + SX_LOAD_CHAR (1); + + /* skip white space */ + while ((*xml == ' ' || *xml == '\t') && SX_RIP_NOT_DONE) + SX_LOAD_CHAR (1); + + /* OK, get the attrib value */ + if (*(xml) != '"' && *(xml) != '\'') /* skip the opening " */ + { + SXLOG_NERR0 ("SX decode error: could not find leading attribute value '\"'"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + + SX_LOAD_CHAR (1); + + /* At the start of the attribute value */ + attribValDest = sxDecElInfo->attr[sxDecElInfo->attrCount].value; + len = 0; + while (SX_RIP_NOT_DONE) + { + c = *xml; + if (c == '"' || c == '\'') /* Found the end of the attrib */ + break; + + if (c != 9 && c != 10 && c != 13) /* dont include these characters */ + { + *(attribValDest++) = c; + ++len; + } + + if (len >= SX_MAX_ATTR_VALUE) + { + SXLOG_NERR0 ("SX decode error: attribute value too long"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + SX_LOAD_CHAR (1); + } + if (SX_RIP_DONE) + { + SXLOG_NERR0 ("SX decode error: could not find closing attribute value '\"'"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + + if (*(xml) != '"' && *(xml) != '\'') /* skip the closing " */ + { + SXLOG_NERR0 ("SX decode error: could not find closing attribute value '\"'"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + SX_LOAD_CHAR (1); + + *attribValDest = 0; /* terminate the attrib value */ + strcpy (attribValCopy, sxDecElInfo->attr[sxDecElInfo->attrCount].value); + sx_format_string_dec (sxDecElInfo->attr[sxDecElInfo->attrCount].value, attribValCopy); + ++sxDecElInfo->attrCount; + } + + if (SX_RIP_DONE) + { + SXLOG_NERR0 ("SX decode error: could not find tag end"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + } + + /* Could be empty tag */ + if (*xml == '/') + { + bEmptyTag = SD_TRUE; + while (*xml != '>') + SX_LOAD_CHAR (1); + } + SX_LOAD_CHAR (1); /* skip the '>' */ + + /* OK, now call the element start function */ + sxDecElInfo->entityStart = xml; + sxDecElInfo->entityEnd = xml; + sxDecCtrl->xmlPos = xml; /* Save current dec position */ + + sxStartElement (sxDecCtrl); + /* Fail on any error except convert error */ + if (sxDecCtrl->errCode != SD_SUCCESS && sxDecCtrl->errCode != SX_ERR_CONVERT) + { + return (SD_FAILURE); + } + + if (bEmptyTag) + { + /* OK, now call the element end function */ + sxEndElement (sxDecCtrl); + bEmptyTag = SD_FALSE; + } + SX_LOAD_CHAR (sxDecCtrl->xmlPos - xml); + sxDecCtrl->xmlPos = xml; /* Save current dec position */ + } + else /* End tag */ + { + sxDecElInfo->entityEnd = xml - 1; + SX_LOAD_CHAR (1); + tagDest = sxDecElInfo->tag; + len = 0; + while (SX_RIP_NOT_DONE) + { + c = *xml; + if (c == '>' || c == ' ') /* Found the end of the tag */ + break; + + *(tagDest++) = c; + ++len; + if (len >= SX_MAX_TAG_LEN) + { + SXLOG_NERR0 ("SX decode error: tag too long"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + SX_LOAD_CHAR (1); + if (sxDecCtrl->ignoreNS && c == ':') + { + tagDest = sxDecElInfo->tag; + len = 0; + } + } + if (SX_RIP_DONE) + { + SXLOG_NERR0 ("SX decode error: could not find tag end"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + *tagDest = 0; /* terminate the tag */ + + + /* any white space up to the end of the tag name */ + while (*xml != '>' && SX_RIP_NOT_DONE) + SX_LOAD_CHAR (1); + if (SX_RIP_DONE) + { + SXLOG_NERR0 ("SX decode error: could not find tag end"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + SX_LOAD_CHAR (1); + + sxDecCtrl->xmlPos = xml; /* Save current dec position */ + + /* OK, now call the element end function */ + sxEndElement (sxDecCtrl); + /* Fail on any error except convert error */ + if (sxDecCtrl->errCode != SD_SUCCESS && sxDecCtrl->errCode != SX_ERR_CONVERT) + { + return (SD_FAILURE); + } + } + } + + if (!sawStartTag) + { + SXLOG_ERR0 ("SX decode error: could not find start tag"); + sxDecCtrl->errCode = SD_FAILURE; + return (SD_FAILURE); + } + else + return (SD_SUCCESS); + } + +ST_VOID sx_load_characters (ST_CHAR *lineBuf, ST_BOOLEAN *eof, FILE *fp, ST_INT numToRead) +{ +ST_LONG numChRead; +ST_LONG i; + + if (numToRead > 0) + { + /* first shift the characters by numToRead */ + memmove (lineBuf, &lineBuf[numToRead], MAX_BYTES_IN_CHUNK - numToRead); + + if (*eof != SD_TRUE) + { + numChRead = fread(lineBuf + (MAX_BYTES_IN_CHUNK - numToRead), 1, numToRead, fp); + if (numChRead == 0) + { + *eof = SD_TRUE; + for (i = 1; i < numToRead + 1; i++) + { + lineBuf[MAX_BYTES_IN_CHUNK - i] = '\0'; + } + } + } + } + } +#else /* USE_EXPAT */ + + +/************************************************************************/ +/* expatHandlerStart */ +/* Normal 'start tag' handler. */ +/* Log and set "errCode" if any string is too long to be stored. */ +/************************************************************************/ +static void XMLCALL expatHandlerStart(void *userData, const char *el, const char **attr) + { + SX_DEC_CTRL *sxDecCtrl = (SX_DEC_CTRL *) userData; + int i; + const ST_CHAR *ptr; + + if (!sxDecCtrl->termFlag) + { + /* Copy tag to sxDecCtrl */ + /* If ignoreNS flag set, ignore namespace prefix on tag. */ + if (sxDecCtrl->ignoreNS) + { + /* If ':' in the string, copy only text after ':' */ + if ((ptr = strrchr (el, ':')) != NULL) + ptr += 1; /* point after ':' */ + else + ptr = el; + } + else + ptr = el; + + if (strlen (ptr) < SX_MAX_TAG_LEN) + strcpy (sxDecCtrl->sxDecElInfo.tag, ptr); + else + { + SXLOG_ERR1 ("start tag '%s' too long. Can't be stored.", ptr); + sxDecCtrl->errCode = SD_FAILURE; + } + + /* Copy attributes to sxDecCtrl */ + for (i = 0; attr[i]; i += 2) + { + if (strlen (attr[i]) < SX_MAX_ATTR_NAME) + strcpy (sxDecCtrl->sxDecElInfo.attr[i/2].name, attr[i]); + else + { + SXLOG_ERR1 ("attr name '%s' too long. Can't be stored.", ptr); + sxDecCtrl->errCode = SD_FAILURE; + } + + if (strlen (attr[i+1]) < SX_MAX_ATTR_VALUE) + strcpy (sxDecCtrl->sxDecElInfo.attr[i/2].value, attr[i+1]); + else + { + SXLOG_ERR1 ("attr value '%s' too long. Can't be stored.", ptr); + sxDecCtrl->errCode = SD_FAILURE; + } + } + sxDecCtrl->sxDecElInfo.attrCount = i/2; + sxDecCtrl->entityLen = 0; /* reset entityLen */ + sxStartElement (sxDecCtrl); + } /* !termFlag */ + } + +/************************************************************************/ +/* expatHandlerEnd */ +/* Normal 'end tag' handler. */ +/************************************************************************/ +static void XMLCALL expatHandlerEnd(void *userData, const char *el) + { + SX_DEC_CTRL *sxDecCtrl = (SX_DEC_CTRL *) userData; + + if (!sxDecCtrl->termFlag) + { + strcpy (sxDecCtrl->sxDecElInfo.tag, el); + sxEndElement (sxDecCtrl); + sxDecCtrl->entityLen = 0; /* reset entityLen */ + } /* !termFlag */ + } + +/************************************************************************/ +/* expatHandlerData */ +/* Normal data handler. */ +/* Log and set "errCode" if data is too long to be stored. */ +/************************************************************************/ +static void XMLCALL expatHandlerData(void *userData, + const XML_Char *s, + int len) + { + SX_DEC_CTRL *sxDecCtrl = (SX_DEC_CTRL *) userData; + ST_INT sizeNeeded; /* buffer size needed to store this data */ + + if (!sxDecCtrl->termFlag) + { + sizeNeeded = len + sxDecCtrl->entityLen; + + /* Save data to access with "sx_get_entity" later. */ + if (sizeNeeded > sxDecCtrl->entityBufSize) + { + /* Reallocate buffer twice as big as currently needed. */ + sxDecCtrl->entityBufSize = sizeNeeded * 2; + SXLOG_FLOW1 ("entity buffer too small. Reallocating entity buffer size = %d", sxDecCtrl->entityBufSize); + sxDecCtrl->entityBuf = chk_realloc (sxDecCtrl->entityBuf, sxDecCtrl->entityBufSize); + } + + memcpy (&(sxDecCtrl->entityBuf [sxDecCtrl->entityLen]), s, len); + sxDecCtrl->entityLen += len; + } /* !termFlag */ + } + +/************************************************************************/ +/* expatHandlerStartSkip */ +/* The 'start tag' handler when tags are being skipped. */ +/************************************************************************/ +static void XMLCALL expatHandlerStartSkip(void *userData, const char *el, const char **attr) + { + SX_DEC_CTRL *sxDecCtrl = (SX_DEC_CTRL *) userData; + + if (!sxDecCtrl->termFlag) + { + /* Not calling normal start funct, so must increment nest level here*/ + sxDecCtrl->xmlNestLevel++; + } /* !termFlag */ + } + +/************************************************************************/ +/* expatHandlerEndSkip */ +/* The 'end tag' handler when tags are being skipped. */ +/************************************************************************/ +static void XMLCALL expatHandlerEndSkip(void *userData, const char *el) + { + SX_DEC_CTRL *sxDecCtrl = (SX_DEC_CTRL *) userData; + + if (!sxDecCtrl->termFlag) + { + if (sxDecCtrl->xmlNestLevel == sxDecCtrl->skipNestLevel) + { + SXLOG_DEC1 ("End element '%s' (contents skipped)", el); + /* Go back to normal handlers. */ + XML_SetCharacterDataHandler(sxDecCtrl->parser, expatHandlerData); + XML_SetElementHandler(sxDecCtrl->parser, expatHandlerStart, expatHandlerEnd); + } + + /* Not calling normal end funct, so must decrement nest level here*/ + sxDecCtrl->xmlNestLevel--; + } /* !termFlag */ + } +/************************************************************************/ +/* setup_expat */ +/* NOTE: If "sxDecCtrl->termFlag" is set by user (i.e. error found), */ +/* let parse complete, but ignore data (see "expatHandler*"). */ +/************************************************************************/ +static XML_Parser setup_expat(SX_DEC_CTRL *sxDecCtrl) + { + XML_Parser parser = XML_ParserCreate(NULL); + if (! parser) + { + SXLOG_ERR0 ("Couldn't allocate memory for XML parser"); + return (parser); + } + XML_SetUserData (parser, sxDecCtrl); /* passes sxDecCtrl to handlers */ + XML_SetCharacterDataHandler(parser, expatHandlerData); + XML_SetElementHandler(parser, expatHandlerStart, expatHandlerEnd); + sxDecCtrl->parser = parser; /* CRITICAL: save parser to use in callbacks*/ + + return (parser); + } +/************************************************************************/ +/* sx_rip_xml_file */ +/* Parse XML from a file. The caller must open a file */ +/* and store the file ptr in "sxDecCtrl->fp". It reads one segment */ +/* at a time from the file and passes it to XML_Parse. */ +/************************************************************************/ +ST_RET sx_rip_xml_file (SX_DEC_CTRL *sxDecCtrl) + { + XML_Parser parser; /* Expat parser control structure */ + ST_RET retcode = SD_SUCCESS; + char *parseBuf; /* temporary buffer to store text read from input file */ + + if (!(parser = setup_expat (sxDecCtrl))) + retcode = SD_FAILURE; /* error already logged in setup_expat */ + else + { + /* Allocate a reasonable size entity buffer. */ + /* This may be reallocated later if it is too small. */ + sxDecCtrl->entityBufSize = ENTITY_BUF_SIZE; + sxDecCtrl->entityBuf = chk_malloc (sxDecCtrl->entityBufSize); + + parseBuf = chk_malloc (EXPAT_BUF_SIZE); + + /* In a loop, read the file one segment at a time & pass to parser. */ + for (;;) + { + int done; + int len; + + len = fread(parseBuf, 1, EXPAT_BUF_SIZE, sxDecCtrl->fp); + if (ferror(sxDecCtrl->fp)) + { + fprintf(stderr, "Read error\n"); + retcode = SD_FAILURE; + break; /* stop now */ + } + done = feof(sxDecCtrl->fp); + + if (XML_Parse(parser, parseBuf, len, done) == XML_STATUS_ERROR) + { + SXLOG_ERR2 ("XML parse error at line %d: %s\n", + XML_GetCurrentLineNumber(parser), + XML_ErrorString(XML_GetErrorCode(parser))); + retcode = SD_FAILURE; + break; /* stop now */ + } + + if (done) + break; + } /* end main loop */ + chk_free (parseBuf); + chk_free (sxDecCtrl->entityBuf); + } + return (retcode); + } +/************************************************************************/ +/* sx_rip_xml_mem */ +/* Parse XML from a memory buffer. The caller must set */ +/* the following members of sxDecCtrl before calling this function: */ +/* sxDecCtrl->xmlStart points to the buffer. */ +/* sxDecCtrl->xmlLen contains the length of the buffer. */ +/* It simply sets up the parse and passes the buffer to XML_Parse. */ +/************************************************************************/ +ST_RET sx_rip_xml_mem (SX_DEC_CTRL *sxDecCtrl) + { + XML_Parser parser; /* Expat parser control structure */ + int done = SD_TRUE; /* indicates to parser that all data is being passed*/ + ST_RET retcode = SD_SUCCESS; + + if (!(parser = setup_expat (sxDecCtrl))) + retcode = SD_FAILURE; /* error already logged in setup_expat */ + else + { + /* Allocate a reasonable size entity buffer. */ + /* This may be reallocated later if it is too small. */ + sxDecCtrl->entityBufSize = ENTITY_BUF_SIZE; + sxDecCtrl->entityBuf = chk_malloc (sxDecCtrl->entityBufSize); + + /* Just pass data all at once to XML_Parse. */ + if (XML_Parse(parser, sxDecCtrl->xmlStart, sxDecCtrl->xmlLen, done) == XML_STATUS_ERROR) + { + SXLOG_ERR2 ("XML parse error at line %d: %s\n", + XML_GetCurrentLineNumber(parser), + XML_ErrorString(XML_GetErrorCode(parser))); + retcode = SD_FAILURE; + } + chk_free (sxDecCtrl->entityBuf); + } + + return (retcode); + } +#endif /* USE_EXPAT */ + diff --git a/mmslib/util/sx_enc.c b/mmslib/util/sx_enc.c new file mode 100644 index 0000000..14eca02 --- /dev/null +++ b/mmslib/util/sx_enc.c @@ -0,0 +1,1344 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1999 - 2008, All Rights Reserved */ +/* */ +/* MODULE NAME : sx_enc.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 01/30/08 EJV 57 Corr slogs (fun names). */ +/* 10/29/07 JRB 56 strncat_safe obsolete, use strncat_maxstrlen.*/ +/* 10/17/06 MDE 55 Added support for unsigned hex ints (32 bit) */ +/* 02/13/06 DSF 54 Migrate to VS.NET 2005 */ +/* 08/09/05 DWL 53 Handle duration of zero. */ +/* 01/31/05 DSF 52 Added sxLogOverrunAsFlow to control how */ +/* encode overrun errors are logged */ +/* 01/19/05 EJV 51 Replaced // comment. */ +/* 07/14/04 DWL 50 Added handling for Duration type */ +/* Added encode functions for struct tm type. */ +/* 03/17/04 EJV 49 Use SISCO types in place of C types. */ +/* 10/30/03 EJV 48 Added size param to UtcValueToXmlString */ +/* 10/27/03 RWM 47 Added sx_format_nstring_enc for */ +/* sx_wr_nstring */ +/* 10/27/03 DSF 46 Don't format strings if bUnformattedStrings */ +/* is set */ +/* 10/24/03 DSF 45 Added missing functions */ +/* Fixed SX_DATE_TIME functions */ +/* 10/13/03 EJV 44 Replaced defined(QNX) with defined(__QNX__). */ +/* 09/01/03 GLB 43 Added "sx_wr_xtime" */ +/* 05/15/03 RWM 42 Added support for special characters when */ +/* encoding */ +/* 03/24/03 DSF 27 Added sx_wrx_nstring, sx_wrx_nstring_el */ +/* 03/05/02 JRB 26 Add more SD_CONST. */ +/* 02/25/02 EJV 25 _AIX: replace itoa, ltoa with ANSI sprintf */ +/* sx_wr_double: repl non-ANSI '%le' with '%e'. */ +/* 01/21/02 EJV 24 Added support for encoding into a file: */ +/* New sx_start_encodeEx, sx_init_encodeEx. */ +/* Added sx_add_buf and _SX_ADD_BUF. */ +/* Added sx_wr_comment funcs. */ +/* Changed sx_add_string and _SX_ADD_STRING. */ +/* Eliminated _src, _xmlBufEnd ptrs from funs.*/ +/* 11/15/01 DGE 23 Added sx_wr_float functions & changed type */ +/* on sx_wr_double functions to ST_DOUBLE from */ +/* double. */ +/* 07/02/01 EJV 22 sx_init_encode: memset to 0 the sxEncCtrl. */ +/* 02/28/01 EJV 21 _AIX: use itoa, ltoa instead of slow sprintf */ +/* 02/28/01 MDE 20 Removed bEmptyTag from SX_ENC_CTRL */ +/* 02/26/01 MDE 19 Make sx_add_string global */ +/* 02/22/01 MDE 18 Allow QNX & Win32 to use itoa, ltoa */ +/* 01/24/01 EJV 17 Replaced non-ANSI itoa, ltoa with sprintf. */ +/* Replaced "%ud" with "%u". */ +/* 01/22/01 DWL 16 Created global var sxUseFormatting */ +/* 01/05/01 EJV 15 sx_wr_ulong: changed "%ul" to "%lu". */ +/* 01/02/01 DWL 14 Removed UIB_DEFINED check */ +/* 11/06/00 DWL 13 Modified sx_write_element and sx_end_element */ +/* to handle data syntax */ +/* 11/02/00 MDE 12 Changed attribute handling a bit */ +/* 10/31/00 MDE 11 Significant rewrite */ +/* 10/11/00 KCR 10 Fixed xmlBufLen calc. because of CDATA */ +/* 09/01/00 MDE 09 Now handle large strings better */ +/* 08/15/00 DWL 08 Added check for UIB_DEFINED, fixed support */ +/* for multiple attributes */ +/* 07/20/00 DWL 07 Added formatting option, code optimizations */ +/* 04/12/00 MDE 06 Changes for V1.00P2 release */ +/* 03/23/00 DWL 05 Format XML with CRLF and tabs */ +/* 03/21/00 DWL 04 Removed includes already in sysincs */ +/* 03/21/00 DWL 03 Changed sx_wr_string_el to accept attributes */ +/* 03/17/00 DWL 02 Changed sx_wr_string_el to skip empty strings*/ +/* 09/15/99 01 Module created */ +/************************************************************************/ + +#if defined (_WIN32) +#pragma warning(disable : 4996) +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "mem_chk.h" +#include "time_str.h" +#include "str_util.h" +#include "sx_defs.h" +#include "sx_log.h" + +/************************************************************************/ +/* For debug version, use a static pointer to avoid duplication of */ +/* __FILE__ strings. */ + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + + +/************************************************************************/ +ST_BOOLEAN sxUseFormatting; +ST_BOOLEAN sxLogOverrunAsFlow; +/************************************************************************/ + +#if 0 + /* to increase speed we prefer not to call functions */ +#define _SX_ADD_BUF(_src, _srcLen) sx_add_buf (sxEncCtrl, _src, _srcLen, &_writePos) +#define _SX_ADD_STRING(_src) sx_add_string (sxEncCtrl, _src, &_writePos) + +#else + +#define _SX_ADD_BUF(_src, _srcLen)\ + {\ + if (sxEncCtrl->useFp)\ + {\ + if (fwrite( _src, sizeof( ST_CHAR ), _srcLen, sxEncCtrl->fp) != (ST_UINT) _srcLen)\ + {\ + sxEncCtrl->errCode = SD_FAILURE;\ + SXLOG_ERR0 ("XML encode file write error");\ + return;\ + }\ + }\ + else\ + {\ + if (_writePos + _srcLen >= sxEncCtrl->xmlBufEnd)\ + {\ + sxEncCtrl->errCode = SX_XML_BUFFER_OVER_MAX;\ + if (sxLogOverrunAsFlow)\ + SXLOG_FLOW0 ("XML encode buffer overrun");\ + else\ + SXLOG_ERR0 ("XML encode buffer overrun");\ + return;\ + }\ + else\ + {\ + memcpy (_writePos, _src, _srcLen);\ + _writePos += _srcLen;\ + *_writePos = 0;\ + }\ + }\ + } + +#define _SX_ADD_STRING(_src) _SX_ADD_BUF(_src, strlen(_src)) +#endif + + +/************************************************************************/ +/* sx_add_string */ +/************************************************************************/ + +ST_VOID sx_add_string (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *_src, + ST_CHAR **writePosIo) + { + sx_add_buf (sxEncCtrl, _src, strlen(_src), writePosIo); + } + +/************************************************************************/ +/* sx_add_buf */ +/************************************************************************/ + +ST_RET sx_add_buf (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *_src, ST_INT _srcLen, + ST_CHAR **writePosIo) + { +ST_CHAR *_writePos; + + if (sxEncCtrl->useFp) + { + if (fwrite( _src, sizeof( ST_CHAR ), _srcLen, sxEncCtrl->fp) != (ST_UINT) _srcLen) + { + sxEncCtrl->errCode = SD_FAILURE; + SXLOG_ERR0 ("XML encode file write error"); + return (SD_FAILURE); + } + } + else + { + _writePos = *writePosIo; + if (_writePos + _srcLen >= sxEncCtrl->xmlBufEnd) + { + sxEncCtrl->errCode = SX_XML_BUFFER_OVER_MAX; + if (sxLogOverrunAsFlow) + SXLOG_FLOW0 ("XML encode buffer overrun"); + else + SXLOG_ERR0 ("XML encode buffer overrun"); + return (SD_FAILURE); + } + else + { + memcpy (_writePos, _src, _srcLen); + _writePos += _srcLen; + *_writePos = 0; /* need string termination for logging */ + } + *writePosIo = _writePos; + } + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_start_encode */ +/************************************************************************/ + +SX_ENC_CTRL *sx_start_encode (ST_CHAR *xmlBuf, ST_INT xmlBufLen) + { +SX_ENC_CTRL *sxEncCtrl; + + sxEncCtrl = (SX_ENC_CTRL *) M_CALLOC (NULL, 1, sizeof (SX_ENC_CTRL)); + sx_init_encode (sxEncCtrl, xmlBuf, xmlBufLen); + return (sxEncCtrl); + } + + +/************************************************************************/ +/* sx_start_encodeEx */ +/************************************************************************/ + +SX_ENC_CTRL *sx_start_encodeEx (ST_CHAR *fileName) + { +SX_ENC_CTRL *sxEncCtrl; + + sxEncCtrl = (SX_ENC_CTRL *) M_CALLOC (NULL, 1, sizeof (SX_ENC_CTRL)); + if (sx_init_encodeEx (sxEncCtrl, fileName) != SD_SUCCESS) + { + M_FREE (NULL, sxEncCtrl); + sxEncCtrl = NULL; + } + return (sxEncCtrl); + } + +/************************************************************************/ +/* sx_init_encode */ +/************************************************************************/ + +ST_VOID sx_init_encode (SX_ENC_CTRL *sxEncCtrl, + ST_CHAR *xmlBuf, ST_INT xmlBufLen) + { + /* sxEncCtrl must be cleared before usage */ + memset (sxEncCtrl, 0, sizeof(SX_ENC_CTRL)); + sxEncCtrl->xmlBufLen = xmlBufLen; + sxEncCtrl->xmlBuf = xmlBuf; + sxEncCtrl->xmlBufEnd = xmlBuf + xmlBufLen; + sxEncCtrl->useFp = SD_FALSE; + sxEncCtrl->nextWritePos = xmlBuf; + sxEncCtrl->currNestLevel = 0; + + sxEncCtrl->errCode = SD_SUCCESS; + sxEncCtrl->bUseFormatting = sxUseFormatting; + SXLOG_ENC0 ("Initialized XML Encode"); + } + +/************************************************************************/ +/* sx_init_encodeEx */ +/************************************************************************/ + +ST_RET sx_init_encodeEx (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *fileName) + { +FILE *fp; + + if ((fp = fopen (fileName, "w")) == NULL) + { + SXLOG_ERR2 ("XML File (%s) Open Error (errno=%d)", fileName, errno); + return (SD_FAILURE); + } + + /* sxEncCtrl must be cleared before usage */ + memset (sxEncCtrl, 0, sizeof(SX_ENC_CTRL)); + sxEncCtrl->xmlBufLen = 0; + sxEncCtrl->xmlBuf = NULL; + sxEncCtrl->xmlBufEnd = NULL; + sxEncCtrl->useFp = SD_TRUE; + sxEncCtrl->fp = fp; + sxEncCtrl->nextWritePos = NULL; + sxEncCtrl->currNestLevel = 0; + + sxEncCtrl->errCode = SD_SUCCESS; + sxEncCtrl->bUseFormatting = sxUseFormatting; + SXLOG_ENC1 ("Initialized XML Encode to file '%s'", fileName); + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_end_encode */ +/************************************************************************/ + +ST_VOID sx_end_encode (SX_ENC_CTRL *sxEncCtrl) + { +ST_LONG xmlLen; + + if (sxEncCtrl->useFp) + { + if (sxEncCtrl->fp) + fclose (sxEncCtrl->fp); + if (sxEncCtrl->errCode == SD_SUCCESS) + { + SXLOG_FLOW0 ("Encode XML to file complete."); + } + } + else + { + /* encoding into buffer */ + if (sxEncCtrl->errCode == SD_SUCCESS) + { + xmlLen = sxEncCtrl->nextWritePos - sxEncCtrl->xmlBuf; + SXLOG_FLOW0 ("Encode XML Complete:"); + SXLOG_FLOWH (xmlLen, sxEncCtrl->xmlBuf); + } + } + M_FREE (NULL, sxEncCtrl); + } + +/************************************************************************/ +/* sx_end_element */ +/************************************************************************/ + +ST_VOID sx_end_element (SX_ENC_CTRL *sxEncCtrl) + { +ST_CHAR *tag; + + if (sxEncCtrl->errCode == 0) + { + --sxEncCtrl->currNestLevel; + tag = sxEncCtrl->tags[sxEncCtrl->currNestLevel]; + sx_write_element (sxEncCtrl, tag, 0, NULL, SD_TRUE, SD_FALSE); + } + } + +/************************************************************************/ +/* sx_write_element */ +/************************************************************************/ + +ST_VOID sx_write_element (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *tag, + ST_INT numAttr, SXE_ATTR_PAIR *attr, + ST_BOOLEAN end, ST_BOOLEAN empty) + { +ST_INT i; +ST_CHAR *_writePos; +ST_CHAR tabBuf[SX_MAX_XML_NEST+1]; +ST_CHAR attrValFormatted [8192]; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; + if (sxEncCtrl->bUseFormatting) + { + if (!sxEncCtrl->bOneLineEl || (sxEncCtrl->bOneLineEl && !end)) + { + for (i = 0; i < sxEncCtrl->currNestLevel; i++) + tabBuf[i] = '\t'; /* assemble all tabs in buffer */ + _SX_ADD_BUF (tabBuf, sxEncCtrl->currNestLevel); + } + } + + _SX_ADD_BUF ("<", 1); + if (end == SD_TRUE) + _SX_ADD_BUF ("/", 1); + _SX_ADD_STRING (tag); + + for (i = 0; i < numAttr; ++i, ++attr) + { + _SX_ADD_BUF (" ", 1); + _SX_ADD_STRING (attr->name); + _SX_ADD_BUF ("=", 1); + _SX_ADD_BUF ("\"", 1); + sx_format_string_enc (attrValFormatted, attr->value); + _SX_ADD_STRING (attrValFormatted); + _SX_ADD_BUF ("\"", 1); + } + + if (empty == SD_TRUE) + _SX_ADD_BUF ("/", 1); + + _SX_ADD_BUF (">", 1); + if (sxEncCtrl->bUseFormatting) + { + if (!sxEncCtrl->bOneLineEl || (sxEncCtrl->bOneLineEl && end)) + _SX_ADD_BUF ("\n", 1); + } + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_write_element: %s", sxEncCtrl->nextWritePos); + } + + if (empty != SD_TRUE && end != SD_TRUE) + { + strcpy (sxEncCtrl->tags[sxEncCtrl->currNestLevel], tag); + ++sxEncCtrl->currNestLevel; + } + sxEncCtrl->nextWritePos = _writePos; + sxEncCtrl->bOneLineEl = SD_FALSE; + } + } + +/************************************************************************/ +/* sx_wr_string */ +/************************************************************************/ + +ST_VOID sx_wr_string (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *str) + { +ST_CHAR *_writePos; +ST_CHAR strFormatted [8192]; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; + if (!sxEncCtrl->bUnformattedStrings) + { + sx_format_string_enc (strFormatted, str); + _SX_ADD_STRING (strFormatted); + } + else + _SX_ADD_STRING (str); + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_string: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + } + +/************************************************************************/ +/* sx_wrx_string_el */ +/************************************************************************/ + +ST_VOID sx_wrx_string_el (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *tag, ST_CHAR *str, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + sx_wr_string (sxEncCtrl, str); + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + +/************************************************************************/ +/* sx_wr_nstring */ +/************************************************************************/ + +ST_VOID sx_wr_nstring (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *str, ST_INT len) + { +ST_CHAR *_writePos; +ST_CHAR strFormatted [8192]; +ST_INT formattedLen; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; + if (!sxEncCtrl->bUnformattedStrings) + { + sx_format_nstring_enc (strFormatted, str, len); + formattedLen = strlen (strFormatted); + _SX_ADD_BUF (strFormatted, formattedLen); + } + else + _SX_ADD_BUF (str, len); + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_nstring: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + } + +/************************************************************************/ +/* sx_wrx_string_el */ +/************************************************************************/ + +ST_VOID sx_wrx_nstring_el (SX_ENC_CTRL *sxEncCtrl, SD_CONST ST_CHAR *tag, ST_CHAR *str, ST_INT len, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + sx_wr_nstring (sxEncCtrl, str, len); + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + +/************************************************************************/ +/* sx_wr_bitstring */ +/************************************************************************/ + +ST_VOID sx_wr_bitstring (SX_ENC_CTRL *sxEncCtrl, ST_INT numBits, + ST_UINT8 *bitStr) + { +ST_CHAR *_writePos; +ST_UINT8 bitMask; +ST_UINT8 *bytePtr; +ST_INT i; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; + + bitMask = 0x80; + bytePtr = bitStr; + for (i = 0; i < numBits; ++i) + { + if (*bytePtr & bitMask) + { + _SX_ADD_BUF ("1", 1); + } + else + { + _SX_ADD_BUF ("0", 1); + } + + if (bitMask == 0x01) + { + bitMask = 0x80; + ++bytePtr; + } + else + bitMask = bitMask >> 1; + } + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_bitstring: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + } + +/************************************************************************/ +/* sx_wrx_bitstring_el */ +/************************************************************************/ + +ST_VOID sx_wrx_bitstring_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, + ST_INT numBits, ST_UINT8 *bitStr, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + + sx_wr_bitstring (sxEncCtrl, numBits, bitStr); + + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + +/************************************************************************/ +/* sx_wr_int */ +/************************************************************************/ + +ST_VOID sx_wr_int (SX_ENC_CTRL *sxEncCtrl, ST_INT val) + { +ST_CHAR *_writePos; +ST_CHAR strVal[100]; + + if (sxEncCtrl->errCode == 0) + { +#if defined(_WIN32) || defined(__QNX__) + itoa (val, strVal, 10); +#else + sprintf (strVal, "%d", val); +#endif + _writePos = sxEncCtrl->nextWritePos; + _SX_ADD_STRING (strVal); + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_int: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + } + +/************************************************************************/ +/* sx_wrx_int_el */ +/************************************************************************/ + +ST_VOID sx_wrx_int_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_INT val, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + + sx_wr_int (sxEncCtrl, val); + + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + +/************************************************************************/ +/* sx_wr_uint */ +/************************************************************************/ + +ST_VOID sx_wr_uint (SX_ENC_CTRL *sxEncCtrl, ST_UINT val) + { +ST_CHAR *_writePos; +ST_CHAR strVal[100]; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; + sprintf (strVal, "%u", val); + _SX_ADD_STRING (strVal); + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_uint: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + } + +/************************************************************************/ +/* sx_wrx_uint_el */ +/************************************************************************/ + +ST_VOID sx_wrx_uint_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_UINT val, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + + sx_wr_uint (sxEncCtrl, val); + + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + +/************************************************************************/ +/* sx_wr_ulong */ +/************************************************************************/ + +ST_VOID sx_wr_ulong (SX_ENC_CTRL *sxEncCtrl, ST_ULONG val) + { +ST_CHAR *_writePos; +ST_CHAR strVal[100]; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; + sprintf (strVal, "%lu", val); + _SX_ADD_STRING (strVal); + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_ulong: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + } + +/************************************************************************/ +/* sx_wrx_ulong_el */ +/************************************************************************/ + +ST_VOID sx_wrx_ulong_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_ULONG val, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + + sx_wr_ulong (sxEncCtrl, val); + + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + +/************************************************************************/ +/* sx_wr_uint32_hex */ +/************************************************************************/ + +ST_VOID sx_wr_uint32_hex (SX_ENC_CTRL *sxEncCtrl, ST_UINT32 val) + { +ST_CHAR *_writePos; +ST_CHAR strVal[100]; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; + sprintf (strVal, "0x%08lx", val); + _SX_ADD_STRING (strVal); + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_uint32_hex: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + } +/************************************************************************/ +/* sx_wrx_uint32_hex_el */ +/************************************************************************/ + +ST_VOID sx_wrx_uint32_hex_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_UINT32 val, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + + sx_wr_uint32_hex (sxEncCtrl, val); + + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + +/************************************************************************/ +/************************************************************************/ +/* sx_wr_double */ +/************************************************************************/ + +ST_VOID sx_wr_double (SX_ENC_CTRL *sxEncCtrl, ST_DOUBLE val) + { +ST_CHAR *_writePos; +ST_CHAR strVal[100]; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; + sprintf (strVal, "%e", val); + _SX_ADD_STRING (strVal); + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_double: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + } + +/************************************************************************/ +/* sx_wrx_double_el */ +/************************************************************************/ + +ST_VOID sx_wrx_double_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_DOUBLE val, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + + sx_wr_double (sxEncCtrl, val); + + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + +/************************************************************************/ +/************************************************************************/ +/* sx_wr_float */ +/************************************************************************/ + +ST_VOID sx_wr_float (SX_ENC_CTRL *sxEncCtrl, ST_FLOAT val) + { +ST_CHAR *_writePos; +ST_CHAR strVal[100]; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; + sprintf (strVal, "%f", val); + _SX_ADD_STRING (strVal); + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_float: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + } + +/************************************************************************/ +/* sx_wrx_float_el */ +/************************************************************************/ + +ST_VOID sx_wrx_float_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_FLOAT val, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + + sx_wr_float (sxEncCtrl, val); + + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + +/************************************************************************/ +/************************************************************************/ +/* sx_wr_long */ +/************************************************************************/ + +ST_VOID sx_wr_long (SX_ENC_CTRL *sxEncCtrl, ST_LONG val) + { +ST_CHAR *_writePos; +ST_CHAR strVal[100]; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; +#if defined(_WIN32) || defined(__QNX__) + ltoa (val, strVal, 10); +#else + sprintf (strVal,"%ld", val); +#endif + _SX_ADD_STRING (strVal); + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_long: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + } + +/************************************************************************/ +/* sx_wrx_long_el */ +/************************************************************************/ + +ST_VOID sx_wrx_long_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_LONG val, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + + sx_wr_long (sxEncCtrl, val); + + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + +/************************************************************************/ +/************************************************************************/ +/* sx_wr_bool */ +/************************************************************************/ + +ST_VOID sx_wr_bool (SX_ENC_CTRL *sxEncCtrl, ST_BOOLEAN val) + { +ST_CHAR *_writePos; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; + if (val != SD_FALSE) + { + _SX_ADD_BUF ("1", 1); + } + else + { + _SX_ADD_BUF ("0", 1); + } + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_bool: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + } + +/************************************************************************/ +/* sx_wrx_bool_el */ +/************************************************************************/ +ST_VOID sx_wrx_bool_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, ST_BOOLEAN val, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + + sx_wr_bool (sxEncCtrl, val); + + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + +/************************************************************************/ +/************************************************************************/ +/************************************************************************/ +/* sx_wr_time */ +/************************************************************************/ +#define SX_MAX_TIME_STRING_LEN 30 +ST_CHAR *sxTimeFormatStr = "%m-%d-%Y %H:%M:%S"; + +ST_VOID sx_wr_time (SX_ENC_CTRL *sxEncCtrl, time_t val) + { +ST_CHAR *_writePos; +ST_CHAR timeStr[50]; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; + strftime (timeStr, SX_MAX_TIME_STRING_LEN, sxTimeFormatStr, localtime (&val)); + _SX_ADD_STRING (timeStr); + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_time: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + } + +/************************************************************************/ +/* sx_wr_tm */ +/************************************************************************/ + +ST_VOID sx_wr_tm (SX_ENC_CTRL *sxEncCtrl, struct tm *val) + { +ST_CHAR *_writePos; +ST_CHAR timeStr[50]; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; + strftime (timeStr, SX_MAX_TIME_STRING_LEN, sxTimeFormatStr, val); + _SX_ADD_STRING (timeStr); + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_tm: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + } + +/************************************************************************/ +/* XmlDurationToString */ +/************************************************************************/ + +ST_RET XmlDurationToString (ST_CHAR *buffer, ST_LONG size, SX_DURATION *sxDuration) + { +ST_CHAR temp[256]; +ST_BOOLEAN dateMemberFound = SD_FALSE; +ST_BOOLEAN timeMemberFound = SD_FALSE; + /* convert duration information stored in */ + /* "SX_DURATION" structure to an xml string */ + /* Use strncat_maxstrlen to avoid buffer overrun */ + if (sxDuration->negative == SD_TRUE) + strncpy_safe( buffer, "-P", size - 1 ); + else + strncpy_safe( buffer, "P", size - 1 ); + + if (sxDuration->years > 0 || + sxDuration->months > 0 || + sxDuration->days > 0) + dateMemberFound = SD_TRUE; + + if (sxDuration->years > 0) + { + sprintf( temp, "%dY", sxDuration->years ); + strncat_maxstrlen( buffer, temp, size - 1 ); + } + if (sxDuration->months > 0) + { + sprintf( temp, "%dM", sxDuration->months ); + strncat_maxstrlen( buffer, temp, size - 1 ); + } + if (sxDuration->days > 0) + { + sprintf( temp, "%dD", sxDuration->days ); + strncat_maxstrlen( buffer, temp, size - 1 ); + } + + if (sxDuration->hours > 0 || + sxDuration->minutes > 0 || + sxDuration->seconds > 0 || + sxDuration->microseconds > 0) + { + timeMemberFound = SD_TRUE; + sprintf( temp, "T" ); + strncat_maxstrlen( buffer, temp, size - 1 ); + } + + if (sxDuration->hours > 0) + { + sprintf( temp, "%dH", sxDuration->hours ); + strncat_maxstrlen( buffer, temp, size - 1 ); + } + if (sxDuration->minutes > 0) + { + sprintf( temp, "%dM", sxDuration->minutes ); + strncat_maxstrlen( buffer, temp, size - 1 ); + } + if (sxDuration->seconds > 0) + { + sprintf( temp, "%d", sxDuration->seconds ); + strncat_maxstrlen( buffer, temp, size - 1 ); + } + if (sxDuration->microseconds > 0) + { + if (sxDuration->seconds > 0) + sprintf( temp, ".%06ld", sxDuration->microseconds ); + else + sprintf( temp, "0.%06ld", sxDuration->microseconds ); + strncat_maxstrlen( buffer, temp, size - 1 ); + } + if (sxDuration->seconds > 0 || sxDuration->microseconds > 0) + { + sprintf( temp, "S" ); + strncat_maxstrlen( buffer, temp, size - 1 ); + } + + if (dateMemberFound == SD_FALSE && timeMemberFound == SD_FALSE) + { + sprintf( temp, "T0S" ); /* 0 seconds = duration of zero */ + strncat_maxstrlen( buffer, temp, size - 1 ); + } + + return (SD_SUCCESS); + } + +/************************************************************************/ +/* sx_wr_duration */ +/************************************************************************/ +/* Convert a SX_DURATION structure into a text string, and store it in */ +/* control structure for output to an XML file. The string */ +/* looks like the following: PnYnMnDTnHnMnS where n are the various */ +/* values, P = period, Y = years, M = months, D = days, T = date/time */ +/* seperator, H = hours, M = minutes, S = seconds. Seconds may be a */ +/* decimal number of arbitrary precisions. */ +/* Ex: P12Y10M2DT0H40M27.87S */ +/* Ex: P12Y10M2DT40M27.87S */ +/************************************************************************/ + +ST_VOID sx_wr_duration (SX_ENC_CTRL *sxEncCtrl, SX_DURATION *sxDuration) + { +ST_RET rc; +ST_CHAR *_writePos; +ST_CHAR buffer[100]; /* arbitrary size */ + + if (sxEncCtrl->errCode != 0) + return; + + rc = XmlDurationToString (buffer, sizeof(buffer), sxDuration); + + /* place newly created date/time string in xml encode structure */ + _writePos = sxEncCtrl->nextWritePos; + _SX_ADD_STRING (buffer); + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_duration: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + +/************************************************************************/ +/* sx_wr_xtime */ +/************************************************************************/ +/* Using the date and time data in the "SX_DATE_TIME" structure convert */ +/* the number of seconds from 1/1/1970 (UTC time), the decimal fraction */ +/* of microseconds if specified and the number of minutes in the */ +/* time zone offset if specified to a date and time string. */ +/* The string is stored in an encode structure for output to an xml */ +/* file. */ +/************************************************************************/ + +ST_VOID sx_wr_xtime (SX_ENC_CTRL *sxEncCtrl, SX_DATE_TIME *sxDateTime) + { +ST_RET rc; +ST_CHAR *_writePos; +ST_CHAR dateTimeStr[MAX_TIME_STRING_LEN]; + + if (sxEncCtrl->errCode != 0) + return; + + /* convert date and time information stored in */ + /* "SX_DATE_TIME" structure to an xml string */ + rc = UtcValueToXmlString (dateTimeStr, sizeof(dateTimeStr), sxDateTime); + if (rc != SD_SUCCESS) + { + SXLOG_NERR0 ("ERROR: Value to String date/time conversion "); + sxEncCtrl->errCode = SD_FAILURE; + return; + } + + /* place newly created date/time string in xml encode structure */ + _writePos = sxEncCtrl->nextWritePos; + _SX_ADD_STRING (dateTimeStr); + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_xtime: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + +/************************************************************************/ +/* sx_wrx_duration_el */ +/************************************************************************/ + +ST_VOID sx_wrx_duration_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, SX_DURATION *val, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + + sx_wr_duration (sxEncCtrl, val); + + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + +/************************************************************************/ +/* sx_wrx_xtime_el */ +/************************************************************************/ + +ST_VOID sx_wrx_xtime_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, SX_DATE_TIME *val, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + + sx_wr_xtime (sxEncCtrl, val); + + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + + +/************************************************************************/ +/* sx_wrx_time_el */ +/************************************************************************/ + +ST_VOID sx_wrx_time_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, time_t val, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + + sx_wr_time (sxEncCtrl, val); + + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + +/************************************************************************/ +/* sx_wrx_tm_el */ +/************************************************************************/ + +ST_VOID sx_wrx_tm_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, struct tm *val, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + + sx_wr_tm (sxEncCtrl, val); + + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + +/************************************************************************/ +/* sx_wr_cdata */ +/************************************************************************/ + +ST_VOID sx_wr_cdata (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *str, ST_INT len) + { +ST_INT i; +ST_CHAR *_writePos; +ST_CHAR tabBuf[SX_MAX_XML_NEST+1]; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; + + if (sxEncCtrl->bUseFormatting) + { + for (i = 0; i < sxEncCtrl->currNestLevel; i++) + tabBuf[i] = '\t'; /* assemble all tabs in buffer */ + _SX_ADD_BUF (tabBuf, sxEncCtrl->currNestLevel); + } + + _SX_ADD_BUF ("", 3); + + sxEncCtrl->nextWritePos = _writePos; + } + } + +/************************************************************************/ +/* sx_wrx_cdata_el */ +/************************************************************************/ + +ST_VOID sx_wrx_cdata_el (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *tag, + ST_CHAR *str, ST_INT len, + ST_INT numAttr, SXE_ATTR_PAIR *attr) + { + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_write_element (sxEncCtrl, tag, numAttr, attr, SD_FALSE, SD_FALSE); + + sx_wr_cdata (sxEncCtrl, str, len); + + sxEncCtrl->bOneLineEl = SD_TRUE; + sx_end_element (sxEncCtrl); + } + + +/************************************************************************/ +/* sx_wr_comment */ +/************************************************************************/ + +ST_VOID sx_wr_comment (SX_ENC_CTRL *sxEncCtrl, ST_CHAR *str) + { +ST_INT i; +ST_CHAR *_writePos; +ST_INT writeLen; +ST_CHAR tabBuf[SX_MAX_XML_NEST+1]; + + if (sxEncCtrl->errCode == 0) + { + _writePos = sxEncCtrl->nextWritePos; + + if (sxEncCtrl->bUseFormatting) + { + for (i = 0; i < sxEncCtrl->currNestLevel; i++) + tabBuf[i] = '\t'; /* assemble all tabs in buffer */ + _SX_ADD_BUF (tabBuf, sxEncCtrl->currNestLevel); + } + + _SX_ADD_BUF ("\n", 4); + } + else + { + _SX_ADD_BUF (str, writeLen); + _SX_ADD_BUF ("-->", 3); + } + + if (!sxEncCtrl->useFp && (sx_debug_sel & SX_LOG_ENC)) + { + SLOGCALWAYS1 ("sx_wr_comment: %s", sxEncCtrl->nextWritePos); + } + sxEncCtrl->nextWritePos = _writePos; + } + } + +/************************************************************************/ +/* sx_format_string_enc */ +/************************************************************************/ + +ST_VOID sx_format_string_enc (ST_CHAR *dest, ST_CHAR *src) + { + ST_CHAR *srcPtr = src; + ST_CHAR *destPtr = dest; + + *destPtr = '\0'; + + while (*srcPtr != '\0') + { + switch (*srcPtr) + { + case CHAR_APOS: + strcat (destPtr, CODE_APOS); + destPtr += CODE_APOS_LEN; + break; + + case CHAR_QUOT: + strcat (destPtr, CODE_QUOT); + destPtr += CODE_QUOT_LEN; + break; + + case CHAR_AMP: + strcat (destPtr, CODE_AMP); + destPtr += CODE_AMP_LEN; + break; + + case CHAR_LT: + strcat (destPtr, CODE_LT); + destPtr += CODE_LT_LEN; + break; + + case CHAR_GT: + strcat (destPtr, CODE_GT); + destPtr += CODE_GT_LEN; + break; + + default: + *destPtr = *srcPtr; + *(destPtr + 1) = '\0'; + destPtr++; + break; + } + + srcPtr++; + } + } + +/************************************************************************/ +/* sx_format_nstring_enc */ +/************************************************************************/ + +ST_VOID sx_format_nstring_enc (ST_CHAR *dest, ST_CHAR *src, ST_INT len) + { + ST_CHAR *srcPtr = src; + ST_CHAR *destPtr = dest; + ST_INT i = 0; + + *destPtr = '\0'; + + while (i++ < len) + { + switch (*srcPtr) + { + case CHAR_APOS: + strcat (destPtr, CODE_APOS); + destPtr += CODE_APOS_LEN; + break; + + case CHAR_QUOT: + strcat (destPtr, CODE_QUOT); + destPtr += CODE_QUOT_LEN; + break; + + case CHAR_AMP: + strcat (destPtr, CODE_AMP); + destPtr += CODE_AMP_LEN; + break; + + case CHAR_LT: + strcat (destPtr, CODE_LT); + destPtr += CODE_LT_LEN; + break; + + case CHAR_GT: + strcat (destPtr, CODE_GT); + destPtr += CODE_GT_LEN; + break; + + default: + *destPtr = *srcPtr; + *(destPtr + 1) = '\0'; + destPtr++; + break; + } + + srcPtr++; + } + } + diff --git a/mmslib/util/time_str.c b/mmslib/util/time_str.c new file mode 100644 index 0000000..5a20203 --- /dev/null +++ b/mmslib/util/time_str.c @@ -0,0 +1,2748 @@ +/************************************************************************/ +/* SISCO SOFTWARE MODULE HEADER *****************************************/ +/************************************************************************/ +/* (c) Copyright Systems Integration Specialists Company, Inc., */ +/* 1994 - 2008, All Rights Reserved */ +/* */ +/* MODULE NAME : time_str.c */ +/* PRODUCT(S) : */ +/* */ +/* MODULE DESCRIPTION : */ +/* */ +/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ +/* */ +/* MODIFICATION LOG : */ +/* Date Who Rev Comments */ +/* -------- --- ------ ------------------------------------------- */ +/* 06/24/08 EJV 41 Btime6StringToVals CORR: *1000 was missing. */ +/* 02/28/08 JRB 40 GetTimeAndUsec ONLY for _WIN32, linux, QNX. */ +/* 09/20/07 nav 39 Put TimeAccuracy in UTC Quality string */ +/* 02/15/07 RLH 38 Add validity checks to UtcValueToXmlString */ +/* so that invalid data will not cause a bad */ +/* string to be generated. */ +/* 01/16/07 RLH 37 Comment-out code obsoleted by rev 36 */ +/* 11/29/06 RLH 36 Merge time_str.c and time_str2, adjust revs, */ +/* add portable usr_mkgmtime function, */ +/* rewrite date and time parsing functions */ +/* tstrStringToTime, tstrStringToTm; */ +/* remove stdtime.h include, add validation to */ +/* quality-bit string, make date-field ordering */ +/* (m-d-y, d-m-y, y-m-d) based on locale, not */ +/* always assuming US m-d-y ordering. improve */ +/* compliance with use of standard SISCO types. */ +/* 09/13/06 NAV 35 Fix quality bits in UTC conversion */ +/* 07/13/06 MDE 34 Fixed compile warning */ +/* 06/05/06 RLH 33 Change to stdtime include */ +/* 03/06/06 RLH 32 add GetTimeAndUsec, tstrTimeToStringGmt, */ +/* tstrStringToTimeGmt */ +/* 02/28/06 EJV 31 UtcStringToVals: added cast. */ +/* 01/30/06 GLB 30 Integrated porting changes for VMS */ +/* 02/13/06 DSF 29 Migrate to VS.NET 2005 */ +/* 02/03/06 NAV 28 UTC - use 0x1000000 instead of 0xFFFFFF */ +/* 01/30/06 GLB 27 Integrated porting changes for VMS */ +/* 07/27/04 DWL 26 Added tstrTmToString (struct tm) */ +/* 07/16/04 DWL 25 Added tstrStringToTm (struct tm) */ +/* 01/27/04 nav 24 UtcValsToString: check for gmtime failure */ +/* 12/09/03 JRB 24 Btime6String..: stop using "daylight" global,*/ +/* use tm_isdst=0 to treat input as std time. */ +/* 10/30/03 GLB & 23 Reworked "XmlStringToUtcValue" & */ +/* EJV "UtcValueToXmlString" */ +/* 10/24/03 DSF 22 Fixed SX_DATE_TIME functions */ +/* 10/15/03 JRB 21 Del _WIN32 ifdef. */ +/* 09/01/03 GLB 20 Added "XmlStringToUtcValue" & */ +/* "UtcValueToXmlString" */ +/* 06/03/03 DSF 19 More compiler warnings */ +/* 04/14/03 JRB 18 Eliminate compiler warnings. */ +/* 09/26/02 NAV 17 UtcValsToString: use gmtime */ +/* 08/05/02 NAV 16 Make Btime4 conversion funcs ansi compatible */ +/* 07/12/02 NAV 15 Add UtcValsToString and UtcStringToVals */ +/* 06/07/02 NAV 14 sprintf msec to %03d */ +/* 02/25/02 JRB 13 Don't use "daylight" global on VXWORKS. */ +/* Fix "thisFil..", sprintf call. Add str_util.h*/ +/* 12/27/01 GLB 12 Remove embedded comment in prior log 11 */ +/* 12/19/01 EJV 11 Converted comments from double slash to */ +/* slash star */ +/* Substituted AXS4_LOG_xxx with SLOGALWAYS. */ +/* Replaced sys includes with sysincs.h */ +/* 06/26/01 EJV 10 Eliminated globals to make thread safe. */ +/* 02/02/01 EJV 09 tstrStringToTime: chg (long *) to (time_t *) */ +/* 11/21/00 MDE 08 Changes for QNX (Btime4 for Win32 only) */ +/* 07/17/98 NAV 07 Modify century calculation for y2k */ +/* 10/15/97 NAV 06 Add Btime4 Support Functions */ +/* 10/08/97 NAV 05 Add seconds to Btime4 and Gtime */ +/* 10/06/97 NAV 04 Handle daylight savings time problem - Btime6*/ +/* 09/04/97 NAV 03 Add Btime6 Conversion routines */ +/* 08/01/96 NAV 02 Lint CleanUp */ +/* 11/08/94 MDE 01 New */ +/************************************************************************/ + +#if defined (_WIN32) +#pragma warning(disable : 4996) +#endif + +#include "glbtypes.h" +#include "sysincs.h" +#include "slog.h" +#include "time_str.h" +#include "str_util.h" + +#ifdef DEBUG_SISCO +SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; +#endif + +/************************************************************************/ + +ST_CHAR *tstrTimeFormat = TSTR_DEF_TIME_FORMAT; +ST_CHAR *BtimeTimeFormat = BTIME_DEF_TIME_FORMAT; + +/************************************************************************/ +/************************************************************************/ +/* tstrTimeToString */ +/************************************************************************/ + +ST_RET tstrTimeToString (time_t t, ST_CHAR *dest) + { + strftime (dest, MAX_TIME_STRING_LEN, tstrTimeFormat, localtime (&t)); + return (SD_SUCCESS); + } + + +/************************************************************************/ +/* tstrTimeToStringGmt */ +/* this code was merged from time_str2.c */ +/************************************************************************/ + +ST_RET tstrTimeToStringGmt (time_t t, ST_CHAR *dest) + { + strftime (dest, MAX_TIME_STRING_LEN, tstrTimeFormat, gmtime (&t)); + return (SD_SUCCESS); + } + + +/************************************************************************/ +/************************************************************************/ + +/* structure to hold results from parsing date and time strings */ + +typedef struct + { + int month; + int day; + int year; + int hour; + int min; + int sec; + int mSec; + int uSec; + int nSec; + int zoneHour; + int zoneMin; + char zoneCode; /* 'Z', '+', '-' or 0 */ + int dateFound; /* not needed by new parsers */ + int timeFound; /* not needed by new parsers */ + int order; /*date-field ordering; 0 =f ANY */ + char *pflags; /* ptr to (qual= ... ) or NULL */ + + } _TS_DATETIME; + +#if 0 +/* obsoleted code */ +static int parseDateString (char *s, _TS_DATETIME *dt); +static int parseTimeString (char *s, _TS_DATETIME *dt); +static int parseBtimeString (char *s, _TS_DATETIME *dt); + +static int strToMonth (char *s, int *monthOut); +#endif + +/************************************************************************/ + + +typedef struct + { + ST_INT32 /*O*/ len; /* length of field */ + ST_INT32 /*O*/ value; /* extracted num value */ + ST_INT32 /*O*/ scale; /* for scaling fractions */ + ST_CHAR /*O*/ delim; /* field delimiter */ + ST_CHAR /*O*/ text[16]; /* extracted text value */ + } DATETIME_FIELD; + + +/************************************************************************/ +/* getDateTimeField */ +/* extract a (possible) date or time field, and report its value */ +/* return pointer to next position to parse, or NULL if no field found */ +/* a _DATETIME_FIELD len of 0 also means the field is not valid */ +/************************************************************************/ + +static ST_CHAR * getDateTimeField ( + ST_CHAR * /*I*/ buf, /* field being parsed */ + ST_CHAR /*I*/ prevDelim, /* '.' allows longer num */ + DATETIME_FIELD * /*O*/ dtf) + { + ST_INT32 i; + ST_CHAR work[4]; + + static ST_CHAR * monthTab[13] = + { + "", + "JAN", "FEB", "MAR", + "APR", "MAY", "JUN", + "JUL", "AUG", "SEP", + "OCT", "NOV", "DEC" + }; + + + if (dtf == NULL) + { + return NULL; /* bad parameter */ + } + + dtf->len = 0; + dtf->value = 0; + dtf->scale = 1; + dtf->delim = ' '; + dtf->text[0] = 0; + + if (buf == NULL) + { + return NULL; /* bad buf pointer */ + } + + /* skip leading whitespace */ + + while (isspace (*buf)) + { + buf++; + } + + if (*buf == 0) + { + return NULL; /* buf has no data */ + } + + /* accumulate value */ + + while (isdigit (*buf)) + { + dtf->text[dtf->len] = *buf; + dtf->text[dtf->len+1] = 0; + + dtf->value = (dtf->value * 10) + (*buf - '0'); + dtf->scale *= 10; + dtf->len++; + buf++; + + if (dtf->len > 9) + { + return NULL; /* numeric field too long */ + } + } /* while */ + + if (dtf->len > 0) /* field is numeric */ + { + + /* only lengths 1, 2 and 4 are allowed */ + /* this allows for 1 or 2 digit months, days and years */ + /* and 4 digit years */ + + /* when prevDelim is '.', the current field is a fraction */ + /* so, we allow longer field values */ + + if (prevDelim == '.') + { + if (dtf->len == 9) + { + /* a (fake) length of 9 is a 'marker' for an alpha month */ + /* we change numbers of length 9 to 8 to get around this */ + + /* we are lying about the length; don't worry, it's OK */ + + /* the precise length of fractional seconds isn't critical anyway. */ + /* we need lengths mainly to analyze month/day/year ordering. */ + + dtf->len = 8; + } + + else if (dtf->len > 9) + { + /* too many digits for a fraction */ + return NULL; + } + } + + else /* prevDelim != '.' */ + { + /* numbers for dates and times only have valid lengths of 1, 2 or 4 */ + /* except for fractional seconds, which can vary from 0 to 9 digits */ + + if ( (dtf->len > 4) + || (dtf->len == 3) ) + { + /* not a valid date or time numeric field size */ + return NULL; + } + + /* if a number is followed by . then a blank, nul, +/-, T or Z */ + /* the . is just noise, so ignore it */ + + /* this test is not made on the "if prevDelim == '.'" branch above */ + /* we don't want to permit values like .123. which is illegal */ + + if (*buf == '.') + { + if ( (buf[1] == 0 ) + || (buf[1] == ' ') + || (buf[1] == '+') + || (buf[1] == '-') + || (buf[1] == 'T') + || (buf[1] == 'Z') ) + { + buf++; /* a pointless dot */ + } + } /* *buf == '.' */ + + } /* when prevDelim != '.' */ + + /* next field is after curr delim at 'buf'; assume delim len is 1 */ + /* assume curr pos is the delimiter */ + /* example: buf == "-12", so delim == '-' and next field "12" at buf+1 */ + /* this holds in most cases, except AM/PM, when next field at buf+2 */ + + dtf->delim = (ST_CHAR) toupper (*buf); + + if (*buf == 0) /* end of buffer */ + { + /* delim is blank when there is no non-blank delimiter */ + /* to determine if end of buffer, look at dtf->buf */ + /* we don't return buf+1 because end of buffer was reached */ + /* be careful not to run off end of buffer */ + dtf->delim = ' '; + return buf; + } + + if (isspace (*buf)) + { + /* delim is blank when there is no non-blank delimiter */ + /* to determine if end of buffer, look at dtf->buf */ + dtf->delim = ' '; /* just in case of tabs, etc. */ + return buf + 1; + } + + if ( (*buf == ':') /* part of a time */ + || (*buf == '.') /* part of a time */ + || (*buf == '-') /* part of a date */ + || (*buf == '+') ) /* possibly part of a timezone offset */ + { + return buf + 1; + } + + if (*buf == '/') + { + dtf->delim = '-'; /* treat '/' same as '-' for dates */ + return buf + 1; + } + + if ( (dtf->delim == 'T') + && (isdigit (buf[1])) ) /* value is part of ISO 8601 time */ + { + return buf + 1; + } + + if (dtf->delim == 'Z') + { + if ( (buf[1] <= ' ') /* Zulu/GMT timezone suffix */ + || (buf[1] == '(') ) /* Z followed by (qual= ... ) */ + { + return buf + 1; + } + } /* Z */ + + /* look for A, P, AM or PM suffix */ + + if ( (dtf->delim == 'A') + || (dtf->delim == 'P') ) + { + if (!isalnum (buf[1])) /* short AM/PM suffix */ + { + return buf + 1; + } + + if ( (toupper (buf[1]) == 'M') /* long AM/PM suffix */ + && (!isalnum (buf[2])) ) /* good delim after M */ + { + return buf + 2; + } + + return NULL; /* malformed AM/PM */ + + } /* A or P delim */ + + } /* field is numeric */ + + /* look for alphabetic month */ + /* we are supporting the following date formats: */ + + /* 2006-Dec-17 */ + /* Dec-17-06 */ + /* Dec-17-2006 */ + /* 17-Dec-2006 */ + + /* in each case, the alpha month is followed by '-' or '/' */ + + /* the format 06-Dec-17 is not supported, because it is not */ + /* clear if it is day-month-year or year-month-day order. */ + + /* if found, return equivalent value (1 to 12) and a (fake) length of 9 */ + /* check for length of 9 is used to see if an alpha month is present */ + + if ( (buf[3] != '-') + && (buf[3] != '/') ) + { + return NULL; + } + + work[0] = (ST_CHAR) toupper (buf[0]); + work[1] = (ST_CHAR) toupper (buf[1]); + work[2] = (ST_CHAR) toupper (buf[2]); + work[3] = 0; + + strcpy (dtf->text, work); + + for (i=1; i <= 12; i++) + { + if (strcmp (work, monthTab[i]) == 0) + { + dtf->delim = '-'; /* treat '/' same as '-' for dates */ + dtf->value = i; + dtf->len = 9; /* fake length of 9 = alpha month */ + return buf + 4; + } + } + + return NULL; /* no valid date/time field found */ + + } /* getDateTimeField */ + + +/************************************************************************/ +/* getDateOrder */ +/* */ +/* on Windows systems, use GetLocaleInfo to determine the ordering of */ +/* month, day and year fields in a date, according to the current */ +/* locale. on non-Windows systems, assume m/d/y. */ +/* */ +/************************************************************************/ + +#ifdef _WIN32 +/* on Windows, GetLocaleInfo() depends on windows.h and kernel32.lib */ +#pragma comment(lib, "kernel32.lib") +#include +#endif + +ST_INT32 getDateOrder () + { +#ifdef _WIN32 + ST_CHAR work[2]; + ST_INT32 rc; + + work[0] = work[1] = 0; + rc = GetLocaleInfoA (LOCALE_USER_DEFAULT, LOCALE_ILDATE, work, 2); + + if (rc != 2) + { + return S_DATE_ORDER_MDY; + } + + if (work[0] == '1') + { + return S_DATE_ORDER_DMY; + } + + if (work[0] == '2') + { + return S_DATE_ORDER_YMD; + } + + /* in case of error, or default '0' returned */ + return S_DATE_ORDER_MDY; + +#else + /* unable to determine ordering, so assume a default order */ + return S_DATE_ORDER_MDY; +#endif + } + + +/************************************************************************/ +/* storeDateValue */ +/* */ +/* take a DATETIME_FIELD array, determine field order of a date, and */ +/* store into a _TS_DATETIME. if DATETIME_FIELD array is valid, and */ +/* the fields appear to be in the correct order, return SD_SUCCESS, */ +/* else return SD_FAILURE. */ +/* */ +/************************************************************************/ + +ST_RET storeDateValue ( + DATETIME_FIELD * /*I*/ dtf, + _TS_DATETIME * /*IO*/ dt) + { + ST_INT32 len; + ST_INT32 mm; + ST_INT32 dd; + ST_INT32 yy; + ST_INT32 order; + + if (dt == NULL) + { + return SD_FAILURE; + } + + dt->month = 0; + dt->day = 0; + dt->year = 0; + dt->dateFound = SD_FALSE; + + if (dtf == NULL) + { + return SD_FAILURE; + } + + if ( (dtf[0].delim != '-') + || (dtf[1].delim != '-') ) + { + return SD_FAILURE; + } + + if ( (dtf[2].delim != 'T') + && (dtf[2].delim != ' ') ) + { + return SD_FAILURE; + } + + /* determine field order by the lengths of 3 fields */ + /* form a single int value for easier testing */ + + /* for example, 412 means a 4-digit field, then a 1-digit field */ + /* and finally a 2-digit field, in that order. */ + + len = (100 * dtf[0].len) + (10 * dtf[1].len) + (dtf[2].len); + + /* if a specific date order is requested by caller, use it. */ + /* otherwise, ask system for the default order */ + + if (dt->order == S_DATE_ORDER_ANY) + { + /* caller accepts any currently active order, based on locale */ + order = getDateOrder (); + } + + else + { + /* caller insisted on date fields being in a particular order */ + order = dt->order; + } + + switch (len) + { + case 411: /* yyyy-m-d : ordering is confident */ + case 412: /* yyyy-m-dd : ordering is confident */ + case 421: /* yyyy-mm-d : ordering is confident */ + case 422: /* yyyy-mm-dd : ordering is confident */ + case 491: /* yyyy-Mon-d : ordering is confident */ + case 492: /* yyyy-Mon-dd : ordering is confident */ + + /* when date starts with a 4-digit number, the first field is a year. */ + /* no (known) locales use year-day-month, so we can assume the order */ + /* is year-month-day here, regardless of locale, with confidence. */ + + yy = dtf[0].value; + mm = dtf[1].value; + dd = dtf[2].value; + break; + + case 914: /* Mon-d-yyyy : ordering is certain */ + case 924: /* Mon-dd-yyyy : ordering is certain */ + + mm = dtf[0].value; + dd = dtf[1].value; + yy = dtf[2].value; + break; + + case 114: /* m-d-yyyy or d-m-yyyy */ + case 124: /* m-dd-yyyy or d-mm-yyyy */ + case 214: /* mm-d-yyyy or dd-m-yyyy */ + case 224: /* mm-dd-yyyy or dd-mm-yyyy */ + + if (order == S_DATE_ORDER_DMY) + { + dd = dtf[0].value; + mm = dtf[1].value; + } + + else + { + /* for S_DATE_ORDER_MDY, the field ordering is certain */ + /* for S_DATE_ORDER_YMD, the field ordering is not certain */ + /* but since YMD implies month before year, we assume this is right */ + + mm = dtf[0].value; + dd = dtf[1].value; + } + + yy = dtf[2].value; + break; + + case 194: /* d-Mon-yyyy : for alpha month, ordering is certain */ + case 294: /* dd-Mon-yyyy : for alpha month, ordering is certain */ + + dd = dtf[0].value; + mm = dtf[1].value; + yy = dtf[2].value; + break; + + case 911: /* Mon-d-y : ordering is confident */ + case 921: /* Mon-dd-y : ordering is confident */ + case 912: /* Mon-d-yy : ordering is confident */ + case 922: /* Mon-dd-yy : ordering is confident */ + + /* for alpha month, there is no such format as Mon-yy-dd */ + /* so, the mm-dd-yy ordering is reasonably certain */ + + mm = dtf[0].value; + dd = dtf[1].value; + yy = dtf[2].value; + + /* year is 2-digit, so form the default century */ + /* we would normally have a cutoff of 1970, but in some cases */ + /* a conversion error will leave a time_t with Dec 31 1969 */ + /* so, values < 69 are assumed to be in the 21 century */ + + if (yy < 69) + { + yy += 2000; + } + + else + { + yy += 1900; + } + + break; + + case 191: /* d-Mon-y */ + case 291: /* dd-Mon-y */ + case 192: /* d-Mon-yy */ + case 292: /* dd-Mon-yy */ + + if (order == S_DATE_ORDER_YMD) + { + yy = dtf[0].value; + mm = dtf[1].value; + dd = dtf[2].value; + } + + else + { + /* for S_DATE_ORDER_DMY, the field ordering is certain */ + /* for S_DATE_ORDER_MDY, the field ordering is not certain */ + /* but since MDY implies day before year, we assume this is right */ + + dd = dtf[0].value; + mm = dtf[1].value; + yy = dtf[2].value; + } + + /* year is 2-digit, so form the default century */ + /* we would normally have a cutoff of 1970, but in some cases */ + /* a conversion error will leave a time_t with Dec 31 1969 */ + /* so, values < 69 are assumed to be in the 21 century */ + + if (yy < 69) + { + yy += 2000; + } + + else + { + yy += 1900; + } + + break; + + case 111: /* d-m-y y-m-d m-d-y */ + case 112: /* d-m-yy y-m-dd m-d-yy */ + + case 121: /* d-mm-y y-mm-d m-dd-y */ + case 122: /* d-mm-yy y-mm-dd m-dd-yy */ + + case 211: /* dd-m-y yy-m-d mm-d-y */ + case 212: /* dd-m-yy yy-m-dd mm-d-yy */ + + case 221: /* dd-mm-y yy-mm-d mm-dd-y */ + case 222: /* dd-mm-yy yy-mm-dd mm-dd-yy */ + + if (order == S_DATE_ORDER_DMY) + { + dd = dtf[0].value; + mm = dtf[1].value; + yy = dtf[2].value; + } + + else if (order == S_DATE_ORDER_YMD) + { + yy = dtf[0].value; + mm = dtf[1].value; + dd = dtf[2].value; + } + + else /* assume mm-dd-yy */ + { + mm = dtf[0].value; + dd = dtf[1].value; + yy = dtf[2].value; + } + + /* year is 2-digit, so form the default century */ + /* we would normally have a cutoff of 1970, but in some cases */ + /* a conversion error will leave a time_t with Dec 31 1969 */ + /* so, values < 69 are assumed to be in the 21 century */ + + if (yy < 69) + { + yy += 2000; + } + + else + { + yy += 1900; + } + + break; + + default: + return SD_FAILURE; + + } /* switch */ + + if ( (mm < 1) + || (mm > 12) + || (dd < 1) + || (dd > 31) + || (yy < 1969) ) + { + return SD_FAILURE; + } + + dt->month = mm; + dt->day = dd; + dt->year = yy; + dt->dateFound = SD_TRUE; + + return SD_SUCCESS; + + } /* storeDateValue */ + + +/************************************************************************/ +/* storeTimeValue */ +/* */ +/* take a DATETIME_FIELD array, determine field order of a time, and */ +/* store into a _TS_DATETIME. if DATETIME_FIELD array is valid, and */ +/* the fields appear to be in the correct order, return SD_SUCCESS, */ +/* else return SD_FAILURE. */ +/* */ +/************************************************************************/ + +ST_RET storeTimeValue ( + DATETIME_FIELD * /*I*/ dtf, + _TS_DATETIME * /*O*/ dt) + { + ST_INT32 n = 0; + ST_INT32 len; + ST_INT32 hour = 0; + ST_INT32 min = 0; + ST_INT32 zoneHour = 0; + ST_INT32 zoneMin = 0; + ST_INT32 sec = 0; + ST_INT32 mSec = 0; + ST_INT32 uSec = 0; + ST_INT32 nSec = 0; + ST_CHAR work[32]; + + + if (dt == NULL) + { + return SD_FAILURE; + } + + dt->hour = 0; + dt->min = 0; + dt->sec = 0; + dt->mSec = 0; + dt->uSec = 0; + dt->nSec = 0; + dt->timeFound = SD_FALSE; + + dt->zoneHour = 0; + dt->zoneMin = 0; + dt->zoneCode = 0; + + if (dtf == NULL) + { + return SD_FAILURE; + } + + /* hh:mm:ss[A] [.frac] [+hh:mm] yyyy-mm-dd */ + /* 0 1 2 3 4 5 6 7 8 */ + + + if ( (dtf[n].delim != ':') + && (dtf[n].len != 1) + && (dtf[n].len != 2) ) + { + return SD_FAILURE; + } + + hour = dtf[n++].value; + + /* store minutes, a required field */ + + if ( (dtf[n].len != 1) + && (dtf[n].len != 2) ) + { + return SD_FAILURE; + } + + min = dtf[n].value; + + /* see if seconds field is present */ + + if (dtf[n].delim == ':') + { + n++; /* look at seconds field */ + + if ( (dtf[n].len != 1) + && (dtf[n].len != 2) ) + { + return SD_FAILURE; + } + + sec = dtf[n].value; + } + + /* see if AM/PM field is present, and validate hour */ + /* in AM/PM mode, hour cannot be 00 or > 12 */ + /* so 00:00 AM and 00:00 PM are illegal */ + /* as are 14:00 PM etc. */ + + if (dtf[n].delim == 'A') + { + if ((hour < 1) || (hour > 12)) + { + return SD_FAILURE; + } + + if (hour == 12) + { + hour = 0; /* 12:05 AM is really 00:00 */ + } + } + + else if (dtf[n].delim == 'P') + { + if ((hour < 1) || (hour > 12)) + { + return SD_FAILURE; + } + + /* 12:05 PM is 12:05 (so hour == 12 is OK), but 1:05 PM is 13:05 */ + + if (hour < 12) + { + hour += 12; + } + } + + /* if decimal point is followed by nothing, it is a null fraction */ + /* if so, treat this as the end of the string */ + /* for example, "12:34." is the same as "12:34" */ + + if ( (dtf[n].delim == '.') + && (dtf[n+1].len == 0) ) + { + dtf[n].delim = ' '; /* end of string */ + } + + if (dtf[n].delim == '.') + { + /* extract mSec */ + /* this requires normalizing the value to 3 digits */ + /* since the current field ends with a dot, there must be */ + /* a following field that is numeric */ + + n++; /* look at fraction field */ + + len = dtf[n].len; + + if (len > 9) + { + return SD_FAILURE; /* malformed/missing mSec field */ + } + + /* express fraction as a count of milliseconds */ + /* method: pad or truncate ms field to 3 digits */ + + strncpy (work, dtf[n].text, 3); + work[3] = 0; + strcat (work, "000"); + work[3] = 0; + mSec = atoi (work); + + /* express fraction as a count of microseconds */ + /* method: pad or truncate ms field to 6 digits */ + + strncpy (work, dtf[n].text, 6); + work[6] = 0; + strcat (work, "000000"); + work[6] = 0; + uSec = atoi (work); + + /* express fraction as a count of nanoseconds */ + /* method: pad or truncate ms field to 9 digits */ + + strncpy (work, dtf[n].text, 9); + work[9] = 0; + strcat (work, "000000000"); + work[9] = 0; + nSec = atoi (work); + } + + if (dtf[n].delim == 'Z') + { + dt->zoneCode = 'Z'; + } + + else if ( (dtf[n].delim == '+') /* +hh:mm or +h:mm */ + || (dtf[n].delim == '-') ) /* -hh:mm or -h:mm */ + { + dt->zoneCode = dtf[n].delim; + /* look at zone hour, it may be 1 or 2 digits */ + n++; + + /* allow for zone of +hhmm or -hhmm if it's the last field */ + + if ( (dtf[n].delim == ' ') + || (dtf[n].delim == 'T') ) + { + if (dtf[n].len != 4) + { + return SD_FAILURE; /* in this format, exactly 4 digits needed */ + } + + zoneHour = (dtf[n].value) / 100; + zoneMin = (dtf[n].value) % 100; + } + + else + { + if ( (dtf[n].delim != ':') /* zone hour must have minutes */ + && (dtf[n].len != 1) + && (dtf[n].len != 2) ) + { + return SD_FAILURE; + } + + zoneHour = dtf[n++].value; /* grab hours, index to minutes */ + + if (dtf[n].len != 2) + { + return SD_FAILURE; + } + + zoneMin = dtf[n].value; + + if ( (zoneHour < 0) + || (zoneHour > 23) + || (zoneMin < 0) + || (zoneMin > 59) ) + { + return SD_FAILURE; + } + } + } + + if ( (hour < 0) + || (hour > 23) + || (min < 0) + || (min > 59) + || (sec < 0) + || (sec > 59) ) + { + return SD_FAILURE; + } + + dt->hour = hour; + dt->min = min; + dt->sec = sec; + dt->mSec = mSec; + dt->uSec = uSec; + dt->nSec = nSec; + dt->timeFound = SD_TRUE; + + dt->zoneHour = zoneHour; + dt->zoneMin = zoneMin; + + return SD_SUCCESS; + + } /* storeTimeValue */ + + +/************************************************************************/ +/* getTsDateTime */ +/* parse a string containing a time and date value, and produce a */ +/* struct tm value. accepted formats are: */ +/* */ +/* time [fraction] date */ +/* date time [fraction] */ +/* */ +/* date may be in the following formats: */ +/* */ +/* yyyy-mm-dd */ +/* yy-mm-dd (may be used in some locales) */ +/* mm-dd-yy (US format) */ +/* mm-dd-yyyy (US format) */ +/* dd-mm-yy (European format) */ +/* dd-mm-yyyy (European format) */ +/* */ +/* yyyy-Mon-dd */ +/* Mon-dd-yy */ +/* Mon-dd-yyyy */ +/* dd-Mon-yyyy (European format) */ +/* */ +/* when date format may be ambiguous, the system is queried as to the */ +/* default field ordering, based on the current locale. for example, */ +/* 01-02-03 could be Jan 01 2003, 01 Feb 2003 or 2001 Feb 03. */ +/* */ +/* when date contains one 4-digit value, it is assumed to be a year. */ +/* this helps to unambiguate some values. */ +/* */ +/* date delimiter may be '-' or '/' */ +/* */ +/* time may or may not have a fraction and/or a timezone */ +/* */ +/* max number of fields possible: 9, consisting of: */ +/* date: 3 */ +/* time: 3 */ +/* fraction: 1 */ +/* timezone: 2 */ +/* */ +/************************************************************************/ + +static ST_RET getTsDateTime ( + ST_CHAR * /*I*/ in_buf, + _TS_DATETIME * /*IO*/ out_dt) + { + ST_INT32 maxfield = 10; + ST_INT32 numfields = 0; + ST_INT32 i; + ST_CHAR * buf; + ST_CHAR prevDelim = ' '; + ST_INT32 datefield; + ST_INT32 timefield; + DATETIME_FIELD dtf[10] = {{0}}; + _TS_DATETIME dt = {0}; + + + if ((in_buf == NULL) || (out_dt == NULL)) + { + return SD_FAILURE; /* bad parameters */ + } + + dt.order = out_dt->order; /* copy date-ordering option */ + + /* extract fields */ + /* prevDelim is set so that a '.' will allow the next field */ + /* to have 1 to 7 digits */ + + buf = in_buf; + + for (i=0; i < maxfield; i++) + { + buf = getDateTimeField (buf, prevDelim, &dtf[i]); + + if (buf != NULL) + { + prevDelim = dtf[i].delim; + numfields++; + + if (*buf == '(') + { + dt.pflags = buf; /* start of quality-flag field */ + break; + } + } + } /* for */ + + if (numfields < 5) + { + return SD_FAILURE; /* we were expecting year,mon,day,hour,min fields */ + } + + /* determine field order */ + + if ( (dtf[0].delim == '-') + && (dtf[1].delim == '-') ) + { + /* first field is date */ + /* example field layout: */ + + /* yyyy-mm-dd [T] hh:mm:ss[A] [.frac] [+hh:mm] */ + /* 0 1 2 3 4 5 6 7 8 */ + + if ( (dtf[2].delim != ' ') + && (dtf[2].delim != 'T') ) + { + return SD_FAILURE; /* bad delimiter */ + } + + datefield = 0; + timefield = 3; + } /* if - - found */ + + else if (dtf[0].delim == ':') + { + /* first field is time (T code would not be present) */ + /* example field layout: */ + + /* hh:mm:ss[A] [.frac] [Z|+hh:mm|-hh:mm] yyyy-mm-dd */ + /* 0 1 2 3 4 5 6 7 8 */ + + /* ensure we have a valid time format */ + /* mm must be followed by AM/PM code, :ss or space, not a '-' */ + + if ( (dtf[1].delim != ' ') + && (dtf[1].delim != ':') + && (dtf[1].delim != 'Z') + && (dtf[1].delim != '+') + && (dtf[1].delim != '-') + && (dtf[1].delim != 'A') + && (dtf[1].delim != 'P') ) + { + return SD_FAILURE; /* bad delimiter */ + } + + timefield = 0; + datefield = 0; + + /* find date field by looking for two '-' delimiters */ + /* if numfields == 9, then last field is at [8] */ + /* so we look for pairs up to [numfields-1] */ + + for (i = 2; i < numfields-1; i++) + { + if ( (dtf[i].delim == '-') + && (dtf[i+1].delim == '-') ) + { + datefield = i; + break; + } + } /* for */ + + if (datefield == 0) + { + return SD_FAILURE; /* cannot find date field */ + } + + } /* if : found */ + + else + { + return SD_FAILURE; /* cannot determine date-time vs. time-date */ + } + + /* populate dt structure with date and time values */ + + if (storeDateValue (&dtf[datefield], &dt) != SD_SUCCESS) + { + return SD_FAILURE; /* malformed date */ + } + + if (storeTimeValue (&dtf[timefield], &dt) != SD_SUCCESS) + { + return SD_FAILURE; /* malformed time */ + } + + *out_dt = dt; + + return SD_SUCCESS; + + } /* getTsDateTime */ + + +/************************************************************************/ +/* tstrStringToTm */ +/* parse a string containing a time and date value, and produce a */ +/* struct tm value. method: convert to _TS_DATEITIME via getTsDateTime */ +/* then convert result to struct tm. */ +/************************************************************************/ + +ST_RET tstrStringToTm (ST_CHAR *in_buf, struct tm *out_struct_tm) + { + _TS_DATETIME dt = {0}; + + struct tm w_struct_tm = {0}; + + if ((in_buf == NULL) || (out_struct_tm == NULL)) + { + return SD_FAILURE; /* bad parameters */ + } + + /* compatibility with old time_str.c requires month-day-year ordering */ + + dt.order = S_DATE_ORDER_MDY; + + if (getTsDateTime (in_buf, &dt) != SD_SUCCESS) + { + return SD_FAILURE; /* bad parameters */ + } + + /* convert the components to struct tm */ + + w_struct_tm.tm_year = dt.year - 1900; + w_struct_tm.tm_mon = dt.month - 1; + w_struct_tm.tm_mday = dt.day; + w_struct_tm.tm_hour = dt.hour; + w_struct_tm.tm_min = dt.min; + w_struct_tm.tm_sec = dt.sec; + w_struct_tm.tm_isdst = -1; /* let api determine DST */ + + usr_mkgmtime (&w_struct_tm); /* generate tm_wday, tm_yday */ + + /* we do not know if supplied date was GMT or not, so DST is uncertain */ + w_struct_tm.tm_isdst = -1; /* a reasonable default value */ + + *out_struct_tm = w_struct_tm; + + return SD_SUCCESS; + + } /* tstrStringToTm */ + + +/************************************************************************/ +/* tstrStringToTime */ +/* parse a string containing a time and date value, and produce a */ +/* time_t value. method: convert to struct tm via tstrStringToTm, */ +/* then convert result to time_t. */ +/************************************************************************/ + +ST_RET tstrStringToTime (ST_CHAR *in_buf, time_t *out_time_t) + { + time_t w_time_t; + struct tm w_struct_tm; + + if ((in_buf == NULL) || (out_time_t == NULL)) + { + return SD_FAILURE; /* bad parameters */ + } + + if (tstrStringToTm (in_buf, &w_struct_tm) != SD_SUCCESS) + { + return SD_FAILURE; /* parse failed */ + } + + w_time_t = mktime (&w_struct_tm); + + if (w_time_t == (time_t) -1) + { + return SD_FAILURE; + } + + *out_time_t = w_time_t; + return SD_SUCCESS; + + } /* tstrStringToTime */ + + +/************************************************************************/ +/* tstrStringToTimeGmt */ +/* time_t value. method: convert to struct tm via tstrStringToTm, */ +/* then convert result to time_t using usr_mkgmtime(). */ +/************************************************************************/ + +ST_RET tstrStringToTimeGmt (ST_CHAR *in_buf, time_t *out_time_t) + { + time_t w_time_t; + struct tm w_struct_tm; + + if ((in_buf == NULL) || (out_time_t == NULL)) + { + return SD_FAILURE; /* bad parameters */ + } + + if (tstrStringToTm (in_buf, &w_struct_tm) != SD_SUCCESS) + { + return SD_FAILURE; /* parse failed */ + } + + w_time_t = usr_mkgmtime (&w_struct_tm); + + if (w_time_t == (time_t) -1) + { + return SD_FAILURE; + } + + *out_time_t = w_time_t; + return SD_SUCCESS; + + } /* tstrStringToTimeGmt */ + + +/************************************************************************/ +/* tstrTmToString */ +/* Convert struct tm to string. */ +/************************************************************************/ + +ST_RET tstrTmToString (struct tm *t, ST_CHAR *dest) + { + ST_CHAR *timeFormatStr = "%m-%d-%Y %H:%M:%S"; + strftime (dest, 30, timeFormatStr, t); + return (SD_SUCCESS); + } + + +#if 0 +/* obsoleted code */ + +/************************************************************************/ +/* parseDateString */ +/************************************************************************/ + +/* parseDateString IS NO LONGER REFERENCED IN THIS CODE */ + +static ST_RET parseDateString (ST_CHAR *s, _TS_DATETIME *dt) + { +ST_CHAR *p; +ST_CHAR *d1; +ST_CHAR *d2; +ST_CHAR *d3; +int century; + + dt->dateFound = SD_TRUE; + + /* break into three substrings */ + d1 = s; + p = strpbrk (s,"-"); + *p = 0; + d2 = ++p; + p = strpbrk (d2,"-"); + if (!p) + return (SD_FAILURE); + *p = 0; + d3 = ++p; + + /* Now process each date sub-substring seperately */ + + /* Check for alpha month forms */ + if (isalpha (*d1)) + { + if (strToMonth (d1, &dt->month)) + return (SD_FAILURE); + if (!sscanf (d2, "%d", &dt->day)) + return (SD_FAILURE); + } + else if (isalpha (*d2)) + { + if (!sscanf (d1, "%d", &dt->day)) + return (SD_FAILURE); + if (strToMonth (d2, &dt->month)) + return (SD_FAILURE); + } + else /* Not an ALPHA month form */ + { + /* Numeric month is d1 */ + if (!sscanf (d1, "%d", &dt->month)) + return (SD_FAILURE); + --dt->month; /* we use 0-11 for month */ + + /* Numeric day is d2 */ + if (!sscanf (d2, "%d", &dt->day)) + return (SD_FAILURE); + } + + /* Numeric year is always d3 */ + if (!sscanf (d3, "%d", &dt->year)) + return (SD_FAILURE); + if (strlen (d3) == 2) + { + /* any year < 1984 is assumed to be in the 21st century */ + century = (dt->year < 84) ? 2000 : 1900; + dt->year += century; + } + return (SD_SUCCESS); + } + + +/* end of obsoleted code */ +#endif + + +#if 0 +/* obsoleted code */ + + +/************************************************************************/ +/* parseTimeString */ +/************************************************************************/ + +/* parseTimeString IS NO LONGER REFERENCED IN THIS CODE */ + +static ST_RET parseTimeString (ST_CHAR *s, _TS_DATETIME *dt) + { +int pm; +ST_CHAR *p, *t1, *t2, *t3; + + dt->timeFound = SD_TRUE; + + /* break into two substrings */ + p = strpbrk (s,":"); + t1 = s; /* hours are here */ + *p = 0; + t2 = ++p; /* minutes are here */ + if (!p) + return (SD_FAILURE); + + p = strpbrk (t2, ":"); + if (!p) + t3 = NULL; + else + { + *p = 0; + t3 = ++p; + } + + pm = SD_FALSE; + if (t3) + { + if (t3[2] == 'A' || t3[2] == 'a') + { + t3[2] = 0; + } + else if (t3[2] == 'P' || t3[2] == 'p') + { + pm = SD_TRUE; + t3[2] = 0; + } + } + + if (!sscanf (t1, "%d", &dt->hour)) + return (SD_FAILURE); + + if (!sscanf (t2, "%d", &dt->min)) + return (SD_FAILURE); + + if (t3) + sscanf (t3, "%d", &dt->sec); + else + dt->sec = 0; + + if (pm) + dt->hour += 12; + + return (SD_SUCCESS); + } + + +/* end of obsoleted code */ +#endif + + +/************************************************************************/ + +#if 0 +/* obsoleted code */ + +static ST_CHAR *monthStrings[12] = + { + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + }; + + +static ST_RET strToMonth (ST_CHAR *s, int *monthOut) + { +int i; + + for (i = 0; i < 12; ++i) + { + if (!stricmp (s, monthStrings[i])) + { + *monthOut = i; + return (SD_SUCCESS); + } + } + return (SD_FAILURE); + } + +#endif + + +/************************************************************************/ +/* Btime6 Conversion Routines: */ +/************************************************************************/ + +#define SEC_PER_MIN 60 +#define SEC_PER_HOUR (60 * SEC_PER_MIN) +#define SEC_PER_DAY (24 * SEC_PER_HOUR) +#define MSEC_PER_SEC 1000 + + +/************************************************************************/ +/* Btime6StringToVals: Receive string in BTIME_DEF_TIME_FORMAT+mSec */ +/* and return the number of days and msecs */ +/* since Jan 1, 1984 midnight */ +/* */ +/* format BTIME_DEF_TIME_FORMAT.mSec is 'mm-dd-yyyy hh:mm:ss.mmm' */ +/* NOTE: output values are NOT adjusted for timezone or DST */ +/* */ +/* method: parse string, capturing mSec. create time_t, and adjust */ +/* for difference in seconds between 1970-01-01 and 1984-01-01. */ +/************************************************************************/ + +ST_RET Btime6StringToVals (ST_CHAR *src, ST_INT32 *numDays, ST_INT32 *numMSec) + { + _TS_DATETIME dt = {0}; + struct tm w_struct_tm = {0}; + + time_t w_time_t; + time_t w_days; + time_t w_msec; + + if ((src == NULL) || (numDays == NULL) || (numMSec == NULL)) + { + return SD_FAILURE; /* bad parameters */ + } + + /* for Btime strings, month-day-year date ordering is required */ + + dt.order = S_DATE_ORDER_MDY; + + if (getTsDateTime (src, &dt) != SD_SUCCESS) + { + SLOGALWAYS1 ("Btime6StringToVals: Unable to parse Btime6 '%s'", src); + return SD_FAILURE; /* bad parameters */ + } + + /* convert the components to struct tm */ + + w_struct_tm.tm_year = dt.year - 1900; + w_struct_tm.tm_mon = dt.month - 1; + w_struct_tm.tm_mday = dt.day; + w_struct_tm.tm_hour = dt.hour; + w_struct_tm.tm_min = dt.min; + w_struct_tm.tm_sec = dt.sec; + w_struct_tm.tm_isdst = 0; /* BTime is GMT based */ + + w_time_t = usr_mkgmtime (&w_struct_tm); /* portable GMT-based mktime() */ + + if (w_time_t == (time_t) -1) + { + SLOGALWAYS1 ("Btime6StringToVals: Unable to convert '%s' to time_t", src); + return SD_FAILURE; + } + + /* adjust for diff between 1984 (Btime epoch) and 1970 (Unix time epoch) */ + /* this is a known constant amount, so we don't recalculate it each time */ + + w_time_t -= (time_t) S_SECS_DIFF_1984_1970; + + w_days = w_time_t / SEC_PER_DAY; + w_msec = (w_time_t % SEC_PER_DAY) * 1000; /* EJV CORR: the multiplication by 1000 was missing */ + + /* save the calculated time value */ + *numDays = (ST_UINT32) w_days; + *numMSec = (ST_UINT32) w_msec + (ST_UINT32) dt.mSec; + + return SD_SUCCESS; + + } /* Btime6StringToVals */ + + +/************************************************************************/ +/* Btime6ValsToString: Receive the number of days and msecs since */ +/* Jan 1, 1984 - midnight and return a string in */ +/* BTIME_DEF_TIME_FORMAT+mSec */ +/************************************************************************/ + +ST_RET Btime6ValsToString (char *dest, ST_INT32 numDays, ST_INT32 numMSec) + { +struct tm tmVal; +time_t tmRslt; +long numSeconds, balMSec; +char stash[MAX_TIME_STRING_LEN+1]; +ldiv_t divResult; +_TS_DATETIME dt; + + divResult = ldiv (numMSec, MSEC_PER_SEC); + numSeconds = divResult.quot; + balMSec = divResult.rem; + + divResult = ldiv (numSeconds, SEC_PER_DAY); + dt.day = divResult.quot + numDays; + numSeconds = divResult.rem; + + divResult = ldiv (numSeconds, SEC_PER_HOUR); + dt.hour = divResult.quot; + numSeconds = divResult.rem; + + divResult = ldiv (numSeconds, SEC_PER_MIN); + dt.min = divResult.quot; + numSeconds = divResult.rem; + + dt.sec = numSeconds; + + /* set up the struct tm */ + tmVal.tm_wday = 0; /* this is an output parameter */ + tmVal.tm_yday = 0; /* this is an output parameter */ + + tmVal.tm_year = 84; + tmVal.tm_mon = 0; + tmVal.tm_mday = dt.day+1; + tmVal.tm_hour = dt.hour; + tmVal.tm_min = dt.min; + tmVal.tm_sec = dt.sec; + tmVal.tm_isdst = -1; /* let function guess */ + tmRslt = mktime(&tmVal); + + if (tmRslt == (time_t) -1) + return (SD_FAILURE); + + /* now turn it into a string with out mSeconds */ + strftime (stash, MAX_TIME_STRING_LEN, BtimeTimeFormat, localtime (&tmRslt)); + + /* now append the mSeconds to the string */ + sprintf (dest, "%s.%03ld", stash, balMSec); + + return (SD_SUCCESS); + + } /* Btime6ValsToString */ + + +/************************************************************************/ +/* Btime4StringToVals: Receive string in BTIME_DEF_TIME_FORMAT.mSec */ +/* and return the number of msecs since midnight */ +/* format BTIME_DEF_TIME_FORMAT.mSec is 'mm-dd-yyyy hh:mm:ss.mmm' */ +/************************************************************************/ + +ST_RET Btime4StringToVals (char *src, ST_INT32 *numMSec) + { + _TS_DATETIME dt = {0}; + struct tm * p_struct_tm = {0}; + + time_t w_time_t; + ST_INT32 curDay; + ST_INT32 curMonth; + ST_INT32 curYear; + ST_INT32 totalMsec; + + + if ((src == NULL) || (numMSec == NULL)) + { + return SD_FAILURE; /* bad parameters */ + } + + /* get current time for validation of date */ + + w_time_t = time (NULL); + + if (w_time_t == (time_t) -1) + { + SLOGALWAYS0 ("Btime4StringToVals: Unable to obtain current time"); + return SD_FAILURE; /* normally should not occur */ + } + + /* current time is converted to a GMT-based struct tm */ + /* because the Btime6 version of this function calculates the offset */ + /* from 1984-01-01 GMT, so we use a GMT-based struct tm here to be */ + /* consistent. */ + + p_struct_tm = gmtime (&w_time_t); + + if (p_struct_tm == NULL) + { + SLOGALWAYS0 ( + "Btime4StringToVals: Unable to convert current time_t to struct tm"); + return SD_FAILURE; /* normally should not occur */ + } + + curYear = p_struct_tm->tm_year + 1900; + curMonth = p_struct_tm->tm_mon + 1; + curDay = p_struct_tm->tm_mday; + + /* for Btime strings, month-day-year date ordering is required */ + + dt.order = S_DATE_ORDER_MDY; + + if (getTsDateTime (src, &dt) != SD_SUCCESS) + { + SLOGALWAYS1 ("Btime4StringToVals: Unable to parse Btime4 '%s'", src); + return SD_FAILURE; /* bad parameters */ + } + + if ( (dt.year != curYear ) + || (dt.month != curMonth) + || (dt.day != curDay ) ) + { + SLOGALWAYS0 ("Btime4 Conversion Error: Input date must be today's date"); + return SD_FAILURE; + } + + /* get mSecs from hours/min/secs */ + + totalMsec = (dt.hour * SEC_PER_HOUR * MSEC_PER_SEC) + + (dt.min * SEC_PER_MIN * MSEC_PER_SEC) + + (dt.sec * MSEC_PER_SEC) + + (dt.mSec); + + /* ensure mSecs does not exceed num mSecs in a day. the count must not */ + /* equal ms/day either, otherwise it would be an offset to the next day */ + + if ( (totalMsec < 0) + || (totalMsec >= (SEC_PER_DAY * MSEC_PER_SEC)) ) + { + SLOGALWAYS1 ("Btime4 Conversion Error: Invalid millisecond count: %d", totalMsec); + return SD_FAILURE; + } + + *numMSec = totalMsec; + + return SD_SUCCESS; + + } /* Btime4StringToVals */ + + +/************************************************************************/ +/* Btime4ValsToString: Receive number of msecs since midnight and return*/ +/* string in BTIM_DEF_TIME_FORMAT.mSec */ +/************************************************************************/ + +ST_RET Btime4ValsToString (char *dest, ST_INT32 numMSec) + { +int curDay, curMonth, curYear; +struct tm tmVal, *curTime; +time_t tmRslt; +long numSeconds, balMSec; +char stash[MAX_TIME_STRING_LEN+1]; +ldiv_t divResult; +_TS_DATETIME dt; +time_t theTime; + + /* figure out todays date */ + theTime = time (NULL); + curTime = localtime (&theTime); + curDay = curTime->tm_mday; + curMonth = curTime->tm_mon; + curYear = curTime->tm_year; + + divResult = ldiv (numMSec, MSEC_PER_SEC); + numSeconds = divResult.quot; + balMSec = divResult.rem; + + divResult = ldiv (numSeconds, SEC_PER_HOUR); + dt.hour = divResult.quot; + numSeconds = divResult.rem; + + divResult = ldiv (numSeconds, SEC_PER_MIN); + dt.min = divResult.quot; + numSeconds = divResult.rem; + + dt.sec = numSeconds; + + /* set up the struct tm */ + tmVal.tm_wday = 0; /* this is an output parameter */ + tmVal.tm_yday = 0; /* this is an output parameter */ + + tmVal.tm_year = curYear; + tmVal.tm_mon = curMonth; + tmVal.tm_mday = curDay; + tmVal.tm_hour = dt.hour; + tmVal.tm_min = dt.min; + tmVal.tm_sec = dt.sec; + tmVal.tm_isdst = -1; /* let function guess */ + tmRslt = mktime(&tmVal); + + if (tmRslt == (time_t) -1) + return (SD_FAILURE); + + /* now turn it into a string with out mSeconds */ + strftime (stash, MAX_TIME_STRING_LEN, BtimeTimeFormat, localtime (&tmRslt)); + + /* now append the mSeconds to the string */ + sprintf (dest, "%s.%03ld", stash, balMSec); + + return (SD_SUCCESS); + } + + +#if 0 +/* obsoleted code */ + +/************************************************************************/ +/* parseBtimeString: parse HH:MM:SS:msec */ +/************************************************************************/ + +/* parseBtimeString IS NO LONGER REFERENCED IN THIS CODE */ + +static ST_RET parseBtimeString (char *s, _TS_DATETIME *dt) + { +char stash[MAX_TIME_STRING_LEN+1]; +char toFind[] = ":."; +char *token; +int count = 0; + + dt->timeFound = SD_TRUE; + + /* make a copy first */ + strcpy (stash, s); + + /* set default values */ + dt->hour = dt->min = dt->sec = dt->mSec = 0; + + /* do the token thing to separate the string */ + token = strtok (stash, toFind); + while (token != NULL) + { + switch (count) + { + case 0: + dt->hour = atoi (token); + break; + case 1: + dt->min = atoi (token); + break; + case 2: + dt->sec = atoi (token); + break; + case 3: + dt->mSec = atoi (token); + break; + } + count++; + /* get next token */ + token = strtok (NULL, toFind); + } + + return (SD_SUCCESS); + } + + +/* end of obsoleted code */ +#endif + + +/************************************************************************/ +/* validQualField */ +/* verify that a string contains a valid Quality field (qual=b,b,b,n) */ +/* there must be at least 3 bit flags present, and proper comma delims. */ +/* if valid, return number characterizing the field, else return 0. */ +/* then, create a buffer with the extracted flags and 'n' value, */ +/* with default values if trailing flags or ''n' value is omitted. */ +/************************************************************************/ + +static ST_INT32 validQualField ( + ST_CHAR * qual, + ST_CHAR * flagBuf) + { + ST_CHAR work[32]; + ST_INT32 i; + ST_INT32 digit = 0; + + if ((qual == NULL) | (flagBuf == NULL)) + { + return 0; + } + + /* (qual=1,2,3,n) */ + /* 0123456789012345 */ + /* 111111 */ + + strcpy (flagBuf, "00000"); /* create defaults */ + + /* make copy of string, modifying it to create a pattern to verify */ + + for (i=0; i < 24; i++) + { + if (qual[i] <= ' ') + { + break; + } + + else if (qual[i] == ')') + { + work[i++] = ')'; + break; + } + + else if (isdigit (qual[i])) + { + /* first 3 digits must be 0 or 1, rest is value 0 to 31 */ + digit++; + + if (digit <= 3) + { + if (qual[i] > '1') + { + return 0; /* char is digit but > '1', not a valid bit value */ + } + work[i] = '1'; /* '1' stands for '0' or '1' */ + } + + else /* digits after 3rd */ + { + work[i] = '9'; /* to check pattern */ + } + + } /* digit */ + + else + { + work[i] = (ST_CHAR) toupper (qual[i]); + } + + } /* for */ + + work[i] = 0; + + + if (strcmp (work, "(QUAL=1,1,1)") == 0) + { + flagBuf[0] = qual[6]; + flagBuf[1] = qual[8]; + flagBuf[2] = qual[10]; + return 3; + } + else if (strcmp (work, "(QUAL=1,1,1,9)") == 0) + { + flagBuf[0] = qual[6]; + flagBuf[1] = qual[8]; + flagBuf[2] = qual[10]; + flagBuf[3] = qual[12]; /* 1-digit 'n' value */ + flagBuf[4] = 0; /* shorten return value */ + + /* when 'n' value is 1-digit, any digit value is OK */ + return 4; + } + else if (strcmp (work, "(QUAL=1,1,1,99)") == 0) + { + ST_INT32 num; + + flagBuf[0] = qual[6]; + flagBuf[1] = qual[8]; + flagBuf[2] = qual[10]; + flagBuf[3] = qual[12]; /* 2-digit 'n' value */ + flagBuf[4] = qual[13]; + + /* when 'n' value is 1-digit, check for range 0 to 31 */ + /* the 'n' value is supposed to be a 5-bit value */ + + num = atoi (flagBuf + 3); + + if ((num < 0) || (num > 31)) + { + return 0; /* 'n' value is out of range */ + } + + return 6; + } + + + /* quality field was none of the above formats */ + + return 0; + + } /* validQualField */ + + +/************************************************************************/ +/* UTC Time Conversion Functions: */ +/* Format = YYYY-MM-DDThh:mm:ss.000000000Z(qual=b,b,b,b,n) */ +/************************************************************************/ +/* UtcStringToVals: */ +/************************************************************************/ + +ST_RET UtcStringToVals ( + ST_CHAR * src, + ST_UINT32 * pSecs, + ST_UINT32 * pFraction, + ST_UINT32 * pQflags) + { + _TS_DATETIME dt = {0}; + + struct tm w_struct_tm = {0}; + time_t w_time_t; + ST_CHAR * pflags; + ST_CHAR flagBuf[8]; + + ST_INT b0; + ST_INT b1; + ST_INT b2; + ST_INT bx; + + ST_DOUBLE decSecs; + ST_DOUBLE binSecs; + + + if ( (src == NULL) + || (pSecs == NULL) + || (pFraction == NULL) + || (pQflags == NULL) ) + { + SLOGALWAYS0 ("UtcStringToVals: NULL parameters"); + return SD_FAILURE; /* bad parameters */ + } + + /* for UTC time strings, date ordering is yyyy-mm-dd*/ + dt.order = S_DATE_ORDER_YMD; + dt.pflags = NULL; + + if (getTsDateTime (src, &dt) != SD_SUCCESS) + { + SLOGALWAYS1 ("UtcStringToVals: Unable to parse time '%s'", src); + return SD_FAILURE; /* bad parameters */ + } + + if (dt.zoneCode != 'Z') + { + SLOGALWAYS1 ("UtcStringToVals: GMT timezone code Z missing in '%s'", src); + return SD_FAILURE; + } + + pflags = dt.pflags; /* pointer to (qual string */ + + if (pflags == NULL) + { + /* quality fields were not present, assume they are all 0 */ + /* SLOGALWAYS1 ("UtcStringToVals: Missing quality in '%s'", src); */ + + *pQflags = 0; + } + else if (validQualField (pflags, flagBuf) < 3) /* not enough flags */ + { + SLOGALWAYS1 ("UtcStringToVals: Invalid quality in '%s'", src); + return SD_FAILURE; + } + else + { + /* flags are already validated as '0' or '1' char values, so AND to get */ + /* bit values, and shift into correct positions */ + + b0 = (flagBuf[0] & 1) << 7; + b1 = (flagBuf[1] & 1) << 6; + b2 = (flagBuf[2] & 1) << 5; + bx = atoi (flagBuf + 3); + + *pQflags = (b0 | b1 | b2 | bx); + } + + /* convert the components to struct tm */ + w_struct_tm.tm_year = dt.year - 1900; + w_struct_tm.tm_mon = dt.month - 1; + w_struct_tm.tm_mday = dt.day; + w_struct_tm.tm_hour = dt.hour; + w_struct_tm.tm_min = dt.min; + w_struct_tm.tm_sec = dt.sec; + w_struct_tm.tm_isdst = 0; + + w_time_t = usr_mkgmtime (&w_struct_tm); /* portable GMT-based mktime() */ + + if (w_time_t == (time_t) -1) + { + SLOGALWAYS1 ("UtcStringToVals: Unable to convert '%s' to time_t", src); + return SD_FAILURE; + } + + /* save the calculated time value */ + *pSecs = (ST_UINT32) w_time_t; + + /* set the decimal fraction of seconds */ + /* dt.nSec contains a count of nanoseconds */ + /* this must be converted to a 24-bit binary fraction of fractional time */ + + /* note: 0x1000000 == 16777216 */ + + /* form decimal fraction of 1 second from 0.0 to 0.999,999,999 */ + + /* 123456789 */ + decSecs = ((ST_DOUBLE) dt.nSec) / 1000000000.0; + + /* convert to binary fraction of 1 second from 0x0.0 to 0x0.FFFFFF */ + binSecs = (decSecs * 16777216.0) + 0.5; + + /* return int equivalent count to caller */ + *pFraction = (ST_UINT32) binSecs; + + return SD_SUCCESS; + + } /* UtcStringToVals */ + + +/************************************************************************/ +/* UtcValsToString: */ +/************************************************************************/ + +ST_RET UtcValsToString (char *dest, ST_UINT32 secs, ST_UINT32 fraction, + ST_UINT32 qflags) + { +ST_CHAR theDate[MAX_TIME_STRING_LEN]; +ST_CHAR theFraction[25]; +ST_CHAR theQual[25]; +ST_DOUBLE dFraction; +ST_CHAR *pFract; + +ST_CHAR b0, b1, b2; +ST_INT rest; + +time_t t = secs; +struct tm *pTm; + + /* get the date portion */ + + pTm = gmtime (&t); + + if (!pTm) + { + SLOGALWAYS0 ("UtcValsToString: conversion failure - invalid seconds."); + return SD_FAILURE; + } + + strftime (theDate, MAX_TIME_STRING_LEN, UTC_DEF_TIME_FORMAT, pTm); + + /* get the fraction portion */ + + dFraction = ((ST_DOUBLE) fraction / (ST_DOUBLE) 0x01000000); + sprintf (theFraction, " %#0.09f", dFraction); + pFract = strchr (theFraction, '.'); + + if (!pFract) + { + SLOGALWAYS1 ("UtcToString - unable to convert fraction %d", fraction); + return SD_FAILURE; + } + + /* get the qflags */ + + b0 = b1 = b2 = rest ='0'; + + if (qflags & 0x80) b0 = '1'; + if (qflags & 0x40) b1 = '1'; + if (qflags & 0x20) b2 = '1'; + rest = (qflags & 0x1F); + sprintf (theQual, "Z(qual=%c,%c,%c,%d)", b0, b1, b2, rest); + + /* put them together */ + sprintf (dest, "%s%s%s", theDate, pFract, theQual); + + return SD_SUCCESS; + } + + +/************************************************************************/ +/* XmlStringToUtcValue */ +/************************************************************************/ +/* An input time and date string is converted to the number of */ +/* seconds since 1/1/1970. */ +/* */ +/* Any of the following strings are valid input to this subroutine: */ +/* */ +/* "yyyy-mm-ddThh:mm:ss.fffff+/-hh:mm" */ +/* "yyyy-mm-ddThh:mm:ss+/-hh:mm" */ +/* */ +/* "yyyy-mm-ddThh:mm:ss.fffffZ" */ +/* "yyyy-mm-ddThh:mm:ssZ" */ +/* */ +/* "yyyy-mm-ddThh:mm:ss.fffff" */ +/* "yyyy-mm-ddThh:mm:ss" */ +/* */ +/* Note: */ +/* Decimal fraction for microseconds: .fffff */ +/* East time zone offset from GMT (Greenwich Mean Time): +hh:mm */ +/* West time zone offset from GMT (Greenwich Mean Time): -hh:mm */ +/* */ +/* */ +/* Output is stored in SX_DATE_TIME structure as: */ +/* */ +/* dateTime stored as number of seconds elapsed since */ +/* midnight (00:00:00) January 1, 1970, */ +/* UTC (Coordinated Universal Time), according */ +/* to the system clock */ +/* useMicroseconds indicates decimal fraction for seconds was */ +/* specified */ +/* microseconds specified decimal fraction of seconds stored as */ +/* microseconds */ +/* useTZ indicates a time zone offset is present */ +/* tz time zone offset specified as minutes */ +/* */ +/* Time zone offset "tz" and time zone presence "useTZ" will be */ +/* specified in output as follows: */ +/* */ +/* "yyyy-mm-ddThh:mm:ss.fffff+/-hh:mm" 'useTZ = SD_TRUE' */ +/* 'tz = +/-seconds' */ +/* "yyyy-mm-ddThh:mm:ss+/-hh:mm" 'useTZ = SD_TRUE' */ +/* 'tz = +/-seconds' */ +/* */ +/* "yyyy-mm-ddThh:mm:ss.fffffZ" 'useTZ = SD_TRUE' 'tz = 0' */ +/* "yyyy-mm-ddThh:mm:ssZ" 'useTZ = SD_TRUE' 'tz = 0' */ +/* */ +/* "yyyy-mm-ddThh:mm:ss.fffff" 'useTZ = SD_FALSE' 'tz ignored' */ +/* "yyyy-mm-ddThh:mm:ss" 'useTZ = SD_FALSE' 'tz ignored' */ +/* */ +/************************************************************************/ + +ST_RET XmlStringToUtcValue (ST_CHAR *in_buf, SX_DATE_TIME *sxDateTime) + { + _TS_DATETIME dt = {0}; + + struct tm w_struct_tm = {0}; + time_t w_time_t; /* local time in seconds */ + + + if ((in_buf == NULL) || (sxDateTime == NULL)) + { + SLOGALWAYS0 ("XmlStringToUtcValue: NULL parameters"); + return SD_FAILURE; /* bad parameters */ + } + + /* split up the string input from XML file so we can store */ + /* number of seconds, number of microseconds (decimal */ + /* fraction of seconds) and number of minutes in time zone */ + /* offset separately */ + + /* for XML time strings, date ordering is yyyy-mm-dd*/ + + dt.order = S_DATE_ORDER_YMD; + + if (getTsDateTime (in_buf, &dt) != SD_SUCCESS) + { + return SD_FAILURE; /* bad parameters */ + } + + /* convert the components to struct tm */ + + w_struct_tm.tm_year = dt.year - 1900; + w_struct_tm.tm_mon = dt.month - 1; + w_struct_tm.tm_mday = dt.day; + w_struct_tm.tm_hour = dt.hour; + w_struct_tm.tm_min = dt.min; + w_struct_tm.tm_sec = dt.sec; + + /* set the decimal fraction of seconds if present */ + + if (dt.uSec == 0) + { + sxDateTime->microseconds = 0; + sxDateTime->useMicroseconds = SD_FALSE; + } + + else + { + sxDateTime->microseconds = dt.uSec; + sxDateTime->useMicroseconds = SD_TRUE; + } + + /* get the time zone offset in minutes if present */ + + if (dt.zoneCode) /* '+', '-' or 'Z' present */ + { + sxDateTime->useTZ = SD_TRUE; + sxDateTime->tz = (dt.zoneHour * 60) + dt.zoneMin; + + if (dt.zoneCode == '-') + { + sxDateTime->tz = -sxDateTime->tz; + } + } + + else + { + sxDateTime->useTZ = SD_FALSE; + sxDateTime->tz = 0; + } + + /* calculate total seconds in UTC time so we can store it */ + /* as a number of seconds since 01/01/1970 */ + + if (sxDateTime->useTZ && sxDateTime->tz == 0) + { + w_struct_tm.tm_isdst = 0; + w_time_t = usr_mkgmtime (&w_struct_tm); /* portable GMT-based mktime() */ + } + + else + { + w_struct_tm.tm_isdst = -1; + w_time_t = mktime (&w_struct_tm); + } + + if (w_time_t == (time_t) -1) + { + SLOGALWAYS1 ("XmlStringToUtcValue: Unable to convert time '%s'", in_buf); + return SD_FAILURE; + } + + /* save the calculated time value */ + sxDateTime->dateTime = w_time_t; + + return SD_SUCCESS; + + } /* XmlStringToUtcValue */ + + +/************************************************************************/ +/* UtcValueToXmlString */ +/************************************************************************/ +/* The specified number of seconds since 1/1/1970 is converted to a */ +/* time and date string. */ +/* */ +/* Input is stored in "SX_DATE_TIME" as: */ +/* */ +/* dateTime stored as number of seconds elapsed since */ +/* midnight (00:00:00) January 1, 1970, */ +/* UTC (Coordinated Universal Time), according */ +/* to the system clock */ +/* useMicroseconds indicates decimal fraction of seconds was */ +/* specified */ +/* microseconds decimal fraction of seconds specified stored as */ +/* microseconds */ +/* useTZ indicates a time zone offset is present */ +/* tz time zone offset from GMT (Greenwich Mean Time) */ +/* specified as minutes */ +/* */ +/* Output string format will depend upon values present in the */ +/* "SX_DATE_TIME" structure as follows: */ +/* */ +/* 'useTZ = SD_TRUE' 'tz = nn..n' "yyyy-mm-ddThh:mm:ss.fffff+/-hh:mm" */ +/* 'useTZ = SD_TRUE' 'tz = nn..n' "yyyy-mm-ddThh:mm:ss+/-hh:mm" */ +/* */ +/* 'useTZ = SD_TRUE' 'tz = 0' "yyyy-mm-ddThh:mm:ss.fffffZ" */ +/* 'useTZ = SD_TRUE' 'tz = 0' "yyyy-mm-ddThh:mm:ssZ" */ +/* */ +/* 'useTZ = SD_FALSE' 'tz ignored' "yyyy-mm-ddThh:mm:ss.fffff" */ +/* 'useTZ = SD_FALSE' 'tz ignored' "yyyy-mm-ddThh:mm:ss" */ +/* */ +/************************************************************************/ + +ST_RET UtcValueToXmlString (ST_CHAR *dest, ST_UINT destLen, + SX_DATE_TIME *sxDateTime) + { +ST_CHAR theFraction[64], theTZ[64]; +ST_CHAR tzSign = '+'; +ST_INT tzValue; + +#define MAX_DATE_TIME_STR_LEN 32 /* longest output format: */ + /* "yyyy-mm-ddThh:mm:ss.fffff+/-hh:mm" */ + + if (destLen < MAX_DATE_TIME_STR_LEN) + { + SLOGALWAYS2 ("ERROR: Buffer %d bytes may be too small for XML string (min=%d)", + destLen, MAX_DATE_TIME_STR_LEN); + return (SD_FAILURE); + } + + /* get the date and time from the "dateTime" or + number of seconds from 1/1/1970 (UTC time) + stored in "sxDateTime" and place it in a + structure of type "tm" returned from the call + to "gmtime" as: + sec + min + hour + day of month + month + year + day of week + day of year */ + + /* from the data stored in the structure utilize + "strftime" to format a date and time string using + the following output format: + %Y is year with century as a decimal number + %m is month as a decimal number (01-12) + %d is day of month as a decimal number (01-31) + %H is hour in 24 hour format (00-23) + %M is minute as decimal number (00-59) + %S is second as decimal number (00-59) */ + + if (sxDateTime->useTZ && sxDateTime->tz == 0) + strftime (dest, destLen, "%Y-%m-%dT%H:%M:%S", gmtime (&sxDateTime->dateTime)); + else + strftime (dest, destLen, "%Y-%m-%dT%H:%M:%S", localtime (&sxDateTime->dateTime)); + + /* then get number of microseconds stored as an */ + /* "long" value in the "sxDateTime" structure and */ + /* format it as a string with a leading decimal point */ + + if (sxDateTime->useMicroseconds) + { + /* this code was merged from time_str2.c */ + /* number of microsecond digits changed from 5 to to 6 */ + + sprintf (theFraction, ".%06ld", sxDateTime->microseconds); + strcat (dest, theFraction); + } + + /* now get the number of minutes stored as an integer */ + /* for time zone offset and place it in a string */ + /* in the format of "+hh:mm" or "-hh:mm" */ + + if (sxDateTime->useTZ) + { + tzValue = sxDateTime->tz; + /* there are 1440 minutes in a day */ + /* if tzValue is outsize this value +/- it is invalid */ + /* if so, we don't know the correct zone but will default to zero */ + + /* we are allowing +/- 23:59 just to be tolerant, but usually only */ + /* only +/- 12 hours is actually used. */ + + if ((tzValue >= 1440) || (tzValue <= -1440)) + { + SLOGALWAYS1 ("ERROR: UtcValueToXmlString sxDateTime.tz value %d out of range", + sxDateTime->tz); + strcat (dest, "Z"); /* assume GMT in case our retcode is ignored */ + return SD_FAILURE; + } + + if (tzValue == 0) + /* output format: "yyyy-mm-ddThh:mm:ss.fffffZ" */ + strcat (dest, "Z"); + + else + { + /* output format: "yyyy-mm-ddThh:mm:ss.fffff+/-hh:mm" */ + + if (tzValue < 0) + { + tzSign = '-'; + tzValue = -tzValue; + } + + sprintf (theTZ, "%c%02d:%02d", tzSign, tzValue / 60, tzValue % 60); + strcat (dest, theTZ); + } + } + + return SD_SUCCESS; + } + + +/************************************************************************/ +/* CalculateTimeZoneOffset */ +/************************************************************************/ +/* Figures out the difference between UTC/GMT/Zulu time and */ +/* local time. */ +/* This difference can be used after the "mktime" */ +/* function is called. The "mktime" function returns local time */ +/* and to convert this time to a UTC time this calculated */ +/* adjustment must be added to the local time value returned */ +/* from "mktime". */ +/************************************************************************/ + +/* NOTE: this function may no longer be necessary */ + +ST_DOUBLE CalculateTimeZoneOffset (ST_VOID) + { +time_t currTime, local_t, utc_t; +struct tm *pJunkTm, localTm, utcTm; +ST_DOUBLE timeZoneAdjustment; + + currTime = time (NULL); /* get the current system time */ + pJunkTm = gmtime (&currTime); /* convert current time value in seconds to a structure */ + memcpy (&utcTm, pJunkTm, sizeof (utcTm)); /* save current UTC time */ + pJunkTm = localtime (&currTime); /* convert current time value and correct for local time zone */ + memcpy (&localTm, pJunkTm, sizeof (localTm)); /* save local UTC time */ + utc_t = mktime (&utcTm); /* convert UTC time to UTC seconds */ + local_t = mktime (&localTm); /* convert local time to UTC seconds */ + timeZoneAdjustment = difftime (local_t, utc_t); /* find the difference or time zone offset */ + + return (timeZoneAdjustment); + } + +/* this code was merged from time_str2.c */ + +/************************************************************************/ +/* GetTimeAndUsec */ +/************************************************************************/ +/* a function to supply current time as a time_t, and the number of */ +/* microseconds, in a single call. this will simplify the setting of */ +/* data structures such as DateTime which have both of these values. */ +/************************************************************************/ + +#if defined(_WIN32) || defined(linux) || defined(__QNX__) +time_t GetTimeAndUsec (long *usec) + { +#ifdef _WIN32 + struct _timeb tb; + _ftime (&tb); +#else + struct timeb tb; + ftime (&tb); +#endif + + if (usec != NULL) + { + *usec = ((long)tb.millitm) * 1000; + } + return tb.time; + } +#endif /* some platforms */ + + +/*****************************************************************************/ +/* usr_mkgmtime_isleap */ +/* return 1 if 'year' is a leap year, else return 0 */ +/*****************************************************************************/ + +static time_t usr_mkgmtime_isleap (time_t year) + { + if ((year < 0 ) || (year > 32767)) + { + return 0; /* assume invalid years are not leap years */ + } + + if ((year % 4000) == 0) + { + return 0; /* multiples of 4000 are not leap years */ + } + + if ((year % 400) == 0) + { + return 1; /* multiples of 400 are leap years */ + } + + if ((year % 100) == 0) + { + return 0; /* multiples of 100 are not leap years */ + } + + if ((year % 4) == 0) + { + return 1; /* multiples of 4 are leap years */ + } + + return 0; /* all others are not leap years */ + + } /* usr_mkgmtime_isleap */ + + +/*****************************************************************************/ +/* usr_mkgmtime_leap_year_days */ +/* return number leap-year days based on 'year' */ +/*****************************************************************************/ + +static time_t usr_mkgmtime_leap_year_days (time_t year) + { + /* number of 4000-year multiples */ + time_t n4000 = (year / (time_t) 4000); + + /* number of 400-year multiples in excess of 4000 */ + time_t n400 = (year % (time_t) 4000) / (time_t) 400; + + /* number of 100-year multiples in excess of 400 */ + time_t n100 = (year % (time_t) 400) / (time_t) 100; + + /* number of 4-year multiples in excess of 100 */ + time_t n4 = (year % (time_t) 100) / (time_t) 4; + + return + ( (time_t) 969 * n4000 ) + + ( (time_t) 97 * n400 ) + + ( (time_t) 24 * n100 ) + + ( (time_t) 1 * n4 ); + + } /* usr_mkgmtime_leap_year_days */ + + +/*****************************************************************************/ +/* usr_mkgmtime */ +/* a portable implementation of mkgmtime(), a GMT-based mktime() function. */ +/* */ +/* note: unlike typical system implementations of mktime(), this function */ +/* does NOT normalize the struct tm fields, which are required to be valid. */ +/* */ +/* for consistency, tm_isdst should be set to 0 upon entry (since GMT does */ +/* not use daylight savings time), but the function ignores this field. */ +/* (when tm_isdst is set to 0, the system mktime() api could be used to */ +/* normalize the input fields prior to calling usr_mkgmtime, if necessary.) */ +/* */ +/* the output fields tm_wday and tm_yday are correctly set upon exit when */ +/* the result time_t value is normal. */ +/* */ +/* upon error, a value of (time_t) (-1) is returned, and the output fields */ +/* tm_wday and tm_yday are not set in that case. detected errors are: NULL */ +/* pointer to the struct tm, date/time values out of valid range, and any */ +/* input that results in a negative time_t value. note that the range of */ +/* input values that could produce a negative time_t are dependent on the */ +/* datatype of time_t, which could be 32 or 64-bit, and signed or unsigned */ +/* on some platforms. */ +/*****************************************************************************/ + + +#define USR_MKGMTIME_BASE_DAY 719527 + + +time_t usr_mkgmtime ( + struct tm * t) + { + time_t w_time_t; + time_t this_year, this_mon, this_day, leap, max_day; + int wday; + + static int usr_mkgmtime_days_per_mon [13] = + { 0, + 31, /* JAN */ + 28, /* FEB */ + 31, /* MAR */ + 30, /* APR */ + 31, /* MAY */ + 30, /* JUN */ + 31, /* JUL */ + 31, /* AUG */ + 30, /* SEP */ + 31, /* OCT */ + 30, /* NOV */ + 31 /* DEC */ + }; + + /* offset from start of year for a given month. */ + /* to compensate for normal day numbers starting with 1, */ + /* we pre-subtract 1 to optimize the calculation. */ + + static int usr_mkgmtime_mon_offset [13] = + { 0, + 0-1, /* JAN */ /* so Jan 1 is day 0 */ + 31-1, /* FEB */ + 59-1, /* MAR */ + 90-1, /* APR */ + 120-1, /* MAY */ + 151-1, /* JUN */ + 181-1, /* JUL */ + 212-1, /* AUG */ + 243-1, /* SEP */ + 273-1, /* OCT */ + 304-1, /* NOV */ + 334-1 /* DEC */ + }; + + /* validate struct tm input values */ + + if (t == NULL) + { + return (time_t) (-1); + } + + this_year = t->tm_year + 1900; + this_mon = t->tm_mon + 1; + this_day = t->tm_mday; + + if ( (this_year < 1970) + || (this_mon < 1) + || (this_mon > 12) + || (this_day < 1) + || (t->tm_hour < 0) + || (t->tm_hour > 23) + || (t->tm_min < 0) + || (t->tm_min > 59) + || (t->tm_sec < 0) + || (t->tm_sec > 59) ) + { + return (time_t) (-1); + } + + leap = usr_mkgmtime_isleap (this_year); + max_day = usr_mkgmtime_days_per_mon[this_mon]; + + if (this_mon == (time_t) 2) + { + max_day += leap; + } + + if (this_day > max_day) + { + return (time_t) (-1); + } + + /* form number of days for given year. we start by determining number */ + /* of leap-year days in the years prior to current one */ + + w_time_t = (time_t) (((time_t) 365 * this_year) + + usr_mkgmtime_leap_year_days (this_year-1)); + + /* convert year/mon to days using month-offset table */ + + /* we must account for the fact that Jan 1 is day 0 of a year. */ + /* so, "day number" is one less than the number of days */ + /* by subtracting 1 from the day-offset of a given month */ + + /* however, since this value will be constant for a given month, */ + /* the offset table already applies the '-1' factor, to save time. */ + /* see the comments above for the table's definition. */ + + this_day += (time_t) usr_mkgmtime_mon_offset [this_mon]; + + if (this_mon > (time_t) 2) + { + this_day += leap; /* leap-year day's effect doesn't occur until March */ + } + + /* calculate base day of Jan 1 1970. 1970 was not a leap year, */ + /* so the number of leap-year days of 1970 is the same as 1969, */ + /* but to be consistent, we call the function using (1970-1). */ + /* since 1,970 years go from the (theoretical) year 0 to 1969, */ + /* the two parts of this equation are consistent. */ + + /* the following would calculate the base day value */ + + /* however, since the values are all constants, the same base day will be */ + /* produced each time. running the equation with these constants produces */ + /* the number 719527, which we use in order to save time. */ + + /* USR_MKGMTIME_BASE_DAY = (time_t) (1970 * 365) */ + /* + usr_mkgmtime_leap_year_days ((time_t) (1970-1)) */ + + w_time_t += (time_t) (this_day - ((time_t) USR_MKGMTIME_BASE_DAY)); + + /* create output fields: tm_wday and tm_yday */ + /* the unix epoch of 1970-01-01 was a Thursday, or tm_wday == 4, */ + + /* tm_wday: Day of week (0 ?6; Sunday = 0) */ + /* tm_yday: Day of year (0 ?365; January 1 = 0) */ + + wday = ((int) w_time_t + 4) % 7; + + w_time_t = (w_time_t * (time_t) 24) + (time_t) t->tm_hour; + w_time_t = (w_time_t * (time_t) 60) + (time_t) t->tm_min; + w_time_t = (w_time_t * (time_t) 60) + (time_t) t->tm_sec; + + if (w_time_t < (time_t) 0) + { + return (time_t) (-1); + } + + /* store output fields after time_t has been validated */ + + t->tm_wday = wday; + t->tm_yday = (int) this_day;; + + return w_time_t; + + } /* usr_mkgmtime */ diff --git a/pt61850netd_pqfe.pro b/pt61850netd_pqfe.pro index 9b6a893..726b62e 100644 --- a/pt61850netd_pqfe.pro +++ b/pt61850netd_pqfe.pro @@ -2,7 +2,7 @@ TEMPLATE = app TARGET = pt61850netd_pqfe DEPENDPATH += . -INCLUDEPATH += . ./source/include ./source/include/mmslite ./source/include/pg_inst ./source/include/curl ./source/include/oss_sdk ./source/include/roketmq +INCLUDEPATH += . ./source/include ./source/include/inc ./source/include/curl ./source/include/rocketmq QMAKE_ORIG_TARGET = $(TARGET) @@ -64,40 +64,28 @@ win32 { unix { include(fe_common.pri) + SOURCES += source/mms/event2.c + INCLUDEPATH += ./source/include/apr-linux + LIBS += -L/FeProject/lib LIBS += -L/FeProject/lib/pgodbc + DEFINES += DEBUG_SISCO VERSION = 1.0.0 - CONFIG(debug, debug|release) { - - } else { - - } LIBS += -lrt -lpthread - MMS_LIB_SUFFIX = _ld.a - LIBS += /FeProject/lib/mmslite/ositcps$$MMS_LIB_SUFFIX \ - /FeProject/lib/mmslite/mvl$$MMS_LIB_SUFFIX \ - /FeProject/lib/mmslite/mmsle$$MMS_LIB_SUFFIX \ - /FeProject/lib/mmslite/mmsl$$MMS_LIB_SUFFIX \ - /FeProject/lib/mmslite/asn1l$$MMS_LIB_SUFFIX \ - /FeProject/lib/mmslite/mem$$MMS_LIB_SUFFIX \ - /FeProject/lib/mmslite/slog$$MMS_LIB_SUFFIX \ - /FeProject/lib/mmslite/util$$MMS_LIB_SUFFIX \ - /FeProject/lib/mmslite/ssec0$$MMS_LIB_SUFFIX \ - /FeProject/lib/pgodbc/psqlodbc.so \ - /FeProject/lib/libcurl.so \ - /FeProject/lib/liboss_c_sdk.so.3.0.0 \ - /FeProject/lib/libmxml.so \ - /FeProject/lib/librocketmq.so \ - /FeProject/lib/libhttprun.so \ - /FeProject/lib/liblog4cplus.so - LIBS += -lapr-1 -laprutil-1 -ljclite - LIBS += -lrdkafka++ - LIBS += -lhttprun - LIBS += -llog4cplus + + LIBS += ./lib/libmmslib.a + + LIBS += ./lib/libcurl.so \ + ./lib/libmxml.so \ + ./lib/librocketmq.so \ + ./lib/libhttprun.so \ + ./lib/liblog4cplus.so + LIBS += -lapr-1 -laprutil-1 -ljclite + LIBS += -lrdkafka++ } #install @@ -156,11 +144,11 @@ SOURCES += source/mms/main.c \ source/json/kafka_producer.cpp \ source/json/create_json.cpp \ source/json/cjson.c \ - source/cfg_parse/oss_aliyun.cpp \ - source/cfg_parse/obs_huaweiyun.cpp \ - source/cfg_parse/datahub.cpp \ +# source/cfg_parse/oss_aliyun.cpp \ +# source/cfg_parse/obs_huaweiyun.cpp \ +# source/cfg_parse/datahub.cpp \ source/cfg_parse/nacos.cpp \ source/cfg_parse/base64.cpp \ - source/cfg_parse/uds_huaweiyun.cpp \ +# source/cfg_parse/uds_huaweiyun.cpp \ source/cfg_parse/SimpleProducer.cpp \ source/cfg_parse/log4.cpp